PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 2.1.4
MxChat – AI Chatbot & Content Generation for WordPress v2.1.4
3.2.22 3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 2.0.3 2.0.4 2.0.5 All 153 releases
← All changes | includes/class-mxchat-integrator.php +621 -307 2.0.52.1.4 View file →
@@ -187,9 +187,9 @@
187 187 return $formatted_history;
188 188 }
189 189
190 190 public function register_routes() {
191 - //error_log(esc_html__('Registering MxChat REST routes', 'mxchat'));
191 + error_log(esc_html__('Registering MxChat REST routes', 'mxchat'));
192 192
193 193 register_rest_route('mxchat/v1', '/stream', [
194 194 'methods' => 'GET',
195 195 'callback' => [$this, 'mxchat_stream_events'],
@@ -207,9 +207,9 @@
207 207 'callback' => [$this, 'handle_slack_interaction'],
208 208 'permission_callback' => [$this, 'verify_slack_request'],
209 209 ]);
210 210
211 - //error_log(esc_html__('MxChat REST routes registered', 'mxchat'));
211 + error_log(esc_html__('MxChat REST routes registered', 'mxchat'));
212 212 }
213 213
214 214 /**
215 215 * Verify valid chat session
@@ -216,9 +216,9 @@
216 216 */
217 217 public function verify_chat_session($request) {
218 218 $session_id = $request->get_param('session_id');
219 219 if (empty($session_id)) {
220 - //error_log(esc_html__('Empty session ID in chat request', 'mxchat'));
220 + error_log(esc_html__('Empty session ID in chat request', 'mxchat'));
221 221 return false;
222 222 }
223 223
224 224 $chat_mode = get_option("mxchat_mode_{$session_id}", 'ai');
@@ -235,9 +235,9 @@
235 235 // Get the Slack signing secret from your plugin options
236 236 $valid_key = $this->options['live_agent_secret_key'] ?? '';
237 237
238 238 if (empty($valid_key)) {
239 - //error_log(esc_html__('Slack signing secret not configured', 'mxchat'));
239 + error_log(esc_html__('Slack signing secret not configured', 'mxchat'));
240 240 return false;
241 241 }
242 242
243 243 $timestamp = $request->get_header('X-Slack-Request-Timestamp');
@@ -244,9 +244,9 @@
244 244 $slack_signature = $request->get_header('X-Slack-Signature');
245 245
246 246 // Verify timestamp to prevent replay attacks
247 247 if (abs(time() - intval($timestamp)) > 300) {
248 - //error_log(esc_html__('Slack request timestamp too old', 'mxchat'));
248 + error_log(esc_html__('Slack request timestamp too old', 'mxchat'));
249 249 return false;
250 250 }
251 251
252 252 // Get raw request body
@@ -299,9 +299,9 @@
299 299 private function mxchat_save_chat_message($session_id, $role, $message) {
300 300 global $wpdb;
301 301
302 302 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
303 - //error_log("[DEBUG] mxchat_save_chat_message -> START for session_id: {$session_id}, role: {$role}");
303 + error_log("[DEBUG] mxchat_save_chat_message -> START for session_id: {$session_id}, role: {$role}");
304 304
305 305 // 1) Extract agent name if present
306 306 $agent_name = '';
307 307 if (preg_match('/^Agent: (.*?) - /', $message, $matches)) {
@@ -310,15 +310,15 @@
310 310
311 311 $session_meta_key = "mxchat_agent_name_{$session_id}";
312 312 if (empty(get_option($session_meta_key))) {
313 313 update_option($session_meta_key, $agent_name);
314 - //error_log("[DEBUG] mxchat_save_chat_message -> Stored agent_name in option: {$session_meta_key} => {$agent_name}");
314 + error_log("[DEBUG] mxchat_save_chat_message -> Stored agent_name in option: {$session_meta_key} => {$agent_name}");
315 315 }
316 316 }
317 317
318 318 // 2) Generate unique message_id
319 319 $message_id = uniqid();
320 - //error_log("[DEBUG] mxchat_save_chat_message -> Generated message_id: {$message_id}");
320 + error_log("[DEBUG] mxchat_save_chat_message -> Generated message_id: {$message_id}");
321 321
322 322 // 3) Determine user_id
323 323 $user_id = is_user_logged_in() ? get_current_user_id() : 0;
324 324
@@ -333,9 +333,9 @@
333 333
334 334 // 6) Check for a saved email in wp_options
335 335 $email_option_key = "mxchat_email_{$session_id}";
336 336 $saved_email = get_option($email_option_key);
337 - //error_log("[DEBUG] mxchat_save_chat_message -> Checking wp_options for email_option_key: {$email_option_key}, found: {$saved_email}");
337 + error_log("[DEBUG] mxchat_save_chat_message -> Checking wp_options for email_option_key: {$email_option_key}, found: {$saved_email}");
338 338
339 339 // If found, update DB user_email
340 340 if ($saved_email) {
341 341 $update_res = $wpdb->update(
@@ -344,9 +344,9 @@
344 344 ['session_id' => $session_id],
345 345 ['%s'],
346 346 ['%s']
347 347 );
348 - //error_log("[DEBUG] mxchat_save_chat_message -> Attempted DB user_email update for session_id {$session_id}. update_res: {$update_res}");
348 + error_log("[DEBUG] mxchat_save_chat_message -> Attempted DB user_email update for session_id {$session_id}. update_res: {$update_res}");
349 349 }
350 350
351 351 // 7) Save to session history in wp_options
352 352 $history_key = "mxchat_history_{$session_id}";
@@ -358,9 +358,9 @@
358 358 'timestamp' => round(microtime(true) * 1000),
359 359 'agent_name' => $displayed_name,
360 360 ];
361 361 update_option($history_key, $history);
362 - //error_log("[DEBUG] mxchat_save_chat_message -> Updated session history in option: {$history_key}");
362 + error_log("[DEBUG] mxchat_save_chat_message -> Updated session history in option: {$history_key}");
363 363
364 364 // 8) Save the message to DB (INSERT)
365 365 $insert_data = [
366 366 'user_id' => $user_id,
@@ -371,16 +371,16 @@
371 371 'message' => $message,
372 372 'timestamp' => current_time('mysql', 1),
373 373 ];
374 374 $wpdb->insert($table_name, $insert_data);
375 - //error_log("[DEBUG] mxchat_save_chat_message -> Inserted message into DB. row_id: {$wpdb->insert_id}, data: " . print_r($insert_data, true));
375 + error_log("[DEBUG] mxchat_save_chat_message -> Inserted message into DB. row_id: {$wpdb->insert_id}, data: " . print_r($insert_data, true));
376 376
377 - //error_log("[DEBUG] mxchat_save_chat_message -> END for session_id: {$session_id}");
377 + error_log("[DEBUG] mxchat_save_chat_message -> END for session_id: {$session_id}");
378 378 return $message_id;
379 379 }
380 380
381 381 public function mxchat_handle_save_email_and_response() {
382 - //error_log('[DEBUG] ---------- mxchat_handle_save_email_and_response START ----------');
382 + error_log('[DEBUG] ---------- mxchat_handle_save_email_and_response START ----------');
383 383
384 384 // Validate nonce
385 385 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'mxchat_chat_nonce')) {
386 386 error_log(esc_html__('[ERROR] Invalid nonce in mxchat_handle_save_email_and_response', 'mxchat'));
@@ -390,12 +390,12 @@
390 390
391 391 $session_id = isset($_POST['session_id']) ? sanitize_text_field($_POST['session_id']) : '';
392 392 $email = isset($_POST['email']) ? sanitize_email($_POST['email']) : '';
393 393
394 - //error_log("[DEBUG] handle_save_email_and_response -> session_id: {$session_id}, email: {$email}");
394 + error_log("[DEBUG] handle_save_email_and_response -> session_id: {$session_id}, email: {$email}");
395 395
396 396 if (empty($session_id) || empty($email)) {
397 - //error_log("[ERROR] Missing session_id or email: session_id={$session_id}, email={$email}");
397 + error_log("[ERROR] Missing session_id or email: session_id={$session_id}, email={$email}");
398 398 wp_send_json_error(['message' => esc_html__('Session ID or email is missing.', 'mxchat')]);
399 399 wp_die();
400 400 }
401 401
@@ -401,9 +401,9 @@
401 401
402 402 // 1) Always store in wp_options
403 403 $option_key = "mxchat_email_{$session_id}";
404 404 update_option($option_key, $email);
405 - //error_log("[DEBUG] handle_save_email_and_response -> updated option: {$option_key} => {$email}");
405 + error_log("[DEBUG] handle_save_email_and_response -> updated option: {$option_key} => {$email}");
406 406
407 407 // 2) (Optional) Also store in DB if a row already exists
408 408 global $wpdb;
409 409 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
@@ -411,9 +411,9 @@
411 411 // Make sure we have a valid placeholder in prepare
412 412 $sql = $wpdb->prepare("SELECT COUNT(*) FROM {$table_name} WHERE session_id = %s", $session_id);
413 413 $session_count = $wpdb->get_var($sql);
414 414
415 - //error_log("[DEBUG] handle_save_email_and_response -> session_count for {$session_id}: {$session_count} (SQL: {$sql})");
415 + error_log("[DEBUG] handle_save_email_and_response -> session_count for {$session_id}: {$session_count} (SQL: {$sql})");
416 416
417 417 if ($session_count) {
418 418 // Update user_email if row(s) exist
419 419 $update_sql = $wpdb->prepare(
@@ -421,31 +421,31 @@
421 421 $email,
422 422 $session_id
423 423 );
424 424 $wpdb->query($update_sql);
425 - //error_log("[DEBUG] handle_save_email_and_response -> DB updated: {$update_sql}");
425 + error_log("[DEBUG] handle_save_email_and_response -> DB updated: {$update_sql}");
426 426 } else {
427 - //error_log("[INFO] handle_save_email_and_response -> No DB entry for {$session_id}, so email is only in wp_options.");
427 + error_log("[INFO] handle_save_email_and_response -> No DB entry for {$session_id}, so email is only in wp_options.");
428 428 }
429 429
430 430 // Provide success response
431 431 $bot_message = __('Thanks for providing your email! You can continue chatting now.', 'mxchat');
432 - //error_log("[DEBUG] handle_save_email_and_response -> success, returning bot_message: {$bot_message}");
432 + error_log("[DEBUG] handle_save_email_and_response -> success, returning bot_message: {$bot_message}");
433 433 wp_send_json_success(['message' => $bot_message]);
434 434 wp_die();
435 435 }
436 436
437 437 public function mxchat_check_email_provided() {
438 - //error_log('[DEBUG] ---------- mxchat_check_email_provided START ----------');
438 + error_log('[DEBUG] ---------- mxchat_check_email_provided START ----------');
439 439
440 440 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'mxchat_chat_nonce')) {
441 - //error_log('[ERROR] Invalid nonce in mxchat_check_email_provided');
441 + error_log('[ERROR] Invalid nonce in mxchat_check_email_provided');
442 442 wp_send_json_error(['message' => esc_html__('Invalid nonce', 'mxchat')]);
443 443 }
444 444
445 445 $session_id = isset($_POST['session_id']) ? sanitize_text_field($_POST['session_id']) : '';
446 446 if (empty($session_id)) {
447 - //error_log('[ERROR] No session ID provided in mxchat_check_email_provided');
447 + error_log('[ERROR] No session ID provided in mxchat_check_email_provided');
448 448 wp_send_json_error(['message' => esc_html__('No session ID provided', 'mxchat')]);
449 449 }
450 450
451 451 // Check if the user is logged in
@@ -450,9 +450,9 @@
450 450
451 451 // Check if the user is logged in
452 452 if (is_user_logged_in()) {
453 453 $current_user = wp_get_current_user();
454 - //error_log("[DEBUG] User is logged in as {$current_user->user_email}");
454 + error_log("[DEBUG] User is logged in as {$current_user->user_email}");
455 455 wp_send_json_success(['logged_in' => true, 'email' => $current_user->user_email]);
456 456 }
457 457
458 458 $option_key = "mxchat_email_{$session_id}";
@@ -457,15 +457,15 @@
457 457
458 458 $option_key = "mxchat_email_{$session_id}";
459 459 $stored_email = get_option($option_key, '');
460 460
461 - //error_log("[DEBUG] mxchat_check_email_provided -> Checking option: {$option_key}, found: {$stored_email}");
461 + error_log("[DEBUG] mxchat_check_email_provided -> Checking option: {$option_key}, found: {$stored_email}");
462 462
463 463 if (!empty($stored_email)) {
464 - //error_log("[DEBUG] mxchat_check_email_provided -> Email found, returning success");
464 + error_log("[DEBUG] mxchat_check_email_provided -> Email found, returning success");
465 465 wp_send_json_success(['email' => $stored_email]);
466 466 } else {
467 - //error_log("[DEBUG] mxchat_check_email_provided -> No email found, returning error");
467 + error_log("[DEBUG] mxchat_check_email_provided -> No email found, returning error");
468 468 wp_send_json_error(['message' => esc_html__('No email found', 'mxchat')]);
469 469 }
470 470 }
471 471
@@ -471,45 +471,45 @@
471 471
472 472
473 473 // First, add this helper function to get the highest rate limit for a user's roles
474 474 private function get_user_role_rate_limit($user_id) {
475 - //error_log(esc_html__("Checking rate limit for user ID: ", 'mxchat') . $user_id);
475 + error_log(esc_html__("Checking rate limit for user ID: ", 'mxchat') . $user_id);
476 476
477 477 if (!$user_id) {
478 - //error_log(esc_html__("No user ID provided, using logged-out limit: ", 'mxchat') . ($this->options['rate_limit_logged_out'] ?? '10'));
478 + error_log(esc_html__("No user ID provided, using logged-out limit: ", 'mxchat') . ($this->options['rate_limit_logged_out'] ?? '10'));
479 479 return $this->options['rate_limit_logged_out'] ?? '10';
480 480 }
481 481
482 482 $user = get_userdata($user_id);
483 483 if (!$user || !$user->roles) {
484 - //error_log(esc_html__("No user data or roles found, using logged-out limit: ", 'mxchat') . ($this->options['rate_limit_logged_out'] ?? '10'));
484 + error_log(esc_html__("No user data or roles found, using logged-out limit: ", 'mxchat') . ($this->options['rate_limit_logged_out'] ?? '10'));
485 485 return $this->options['rate_limit_logged_out'] ?? '10';
486 486 }
487 487
488 - //error_log(esc_html__("User roles: ", 'mxchat') . print_r($user->roles, true));
489 - //error_log(esc_html__("Available role rate limits: ", 'mxchat') . print_r($this->options['role_rate_limits'] ?? [], true));
488 + error_log(esc_html__("User roles: ", 'mxchat') . print_r($user->roles, true));
489 + error_log(esc_html__("Available role rate limits: ", 'mxchat') . print_r($this->options['role_rate_limits'] ?? [], true));
490 490
491 491 $max_limit = 0;
492 492 foreach ($user->roles as $role) {
493 - //error_log(esc_html__("Checking limit for role: ", 'mxchat') . $role);
493 + error_log(esc_html__("Checking limit for role: ", 'mxchat') . $role);
494 494 if (isset($this->options['role_rate_limits'][$role])) {
495 495 $role_limit = $this->options['role_rate_limits'][$role];
496 - //error_log(esc_html__("Found limit for role ", 'mxchat') . $role . esc_html__(": ", 'mxchat') . $role_limit);
496 + error_log(esc_html__("Found limit for role ", 'mxchat') . $role . esc_html__(": ", 'mxchat') . $role_limit);
497 497
498 498 if ($role_limit === 'unlimited') {
499 - //error_log(esc_html__("Returning unlimited for role: ", 'mxchat') . $role);
499 + error_log(esc_html__("Returning unlimited for role: ", 'mxchat') . $role);
500 500 return 'unlimited';
501 501 }
502 502
503 503 $max_limit = max($max_limit, (int)$role_limit);
504 - //error_log(esc_html__("Current max limit: ", 'mxchat') . $max_limit);
504 + error_log(esc_html__("Current max limit: ", 'mxchat') . $max_limit);
505 505 } else {
506 - //error_log(esc_html__("No limit found for role: ", 'mxchat') . $role);
506 + error_log(esc_html__("No limit found for role: ", 'mxchat') . $role);
507 507 }
508 508 }
509 509
510 510 $final_limit = $max_limit > 0 ? (string)$max_limit : '100';
511 - //error_log(esc_html__("Final rate limit: ", 'mxchat') . $final_limit);
511 + error_log(esc_html__("Final rate limit: ", 'mxchat') . $final_limit);
512 512 return $final_limit;
513 513 }
514 514
515 515
@@ -610,9 +610,9 @@
610 610 $user_id = sanitize_key($user_id);
611 611
612 612 // Determine if user is logged in
613 613 $is_logged_in = is_user_logged_in();
614 - //error_log("User logged in status: " . ($is_logged_in ? 'true' : 'false'));
614 + error_log("User logged in status: " . ($is_logged_in ? 'true' : 'false'));
615 615
616 616 // Get rate limit based on user status
617 617 // Get rate limit based on user status
618 618 $rate_limit = $is_logged_in
@@ -618,9 +618,9 @@
618 618 $rate_limit = $is_logged_in
619 619 ? $this->get_user_role_rate_limit($user_id)
620 620 : ($this->options['rate_limit_logged_out'] ?? '10');
621 621
622 - //error_log("Selected rate limit: " . $rate_limit);
622 + error_log("Selected rate limit: " . $rate_limit);
623 623
624 624 // Rest of your code remains the same
625 625 // If rate limit is 'unlimited', skip rate limiting checks
626 626 if ($rate_limit !== 'unlimited') {
@@ -661,12 +661,12 @@
661 661 }
662 662
663 663 // Rest of your existing code...
664 664 $session_id = isset($_POST['session_id']) ? sanitize_text_field($_POST['session_id']) : '';
665 - //error_log("Session ID: $session_id");
665 + error_log("Session ID: $session_id");
666 666
667 667 if (empty($session_id)) {
668 - //error_log("Error: Session ID is missing.");
668 + error_log("Error: Session ID is missing.");
669 669 wp_send_json_error(esc_html__('Session ID is missing.', 'mxchat'));
670 670 wp_die();
671 671 }
672 672
@@ -671,9 +671,9 @@
671 671 }
672 672
673 673 // Validate and sanitize the incoming message
674 674 if (empty($_POST['message'])) {
675 - //error_log("Error: No message received.");
675 + error_log("Error: No message received.");
676 676 wp_send_json_error(esc_html__('No message received.', 'mxchat'));
677 677 wp_die();
678 678 }
679 679
@@ -703,8 +703,30 @@
703 703
704 704 // Preserve code blocks from markdown conversion
705 705 $message = preg_replace('/```(\w+)?\s*([\s\S]+?)```/s', '<pre><code class="$1">$2</code></pre>', $message);
706 706
707 +// Check if any add-ons want to pre-process this message (for web search etc.)
708 +$pre_processed_result = apply_filters('mxchat_pre_process_message', $message, $user_id, $session_id);
709 +
710 +// If the pre-processing returned a result (not the original message), use it directly
711 +if (is_array($pre_processed_result) && isset($pre_processed_result['text'])) {
712 + // Save the AI response
713 + $this->mxchat_save_chat_message($session_id, 'bot', $pre_processed_result['text']);
714 +
715 + // Save HTML content if provided
716 + if (!empty($pre_processed_result['html'])) {
717 + $this->mxchat_save_chat_message($session_id, 'bot', $pre_processed_result['html']);
718 + }
719 +
720 + // Return the response
721 + wp_send_json([
722 + 'text' => $pre_processed_result['text'],
723 + 'html' => $pre_processed_result['html'] ?? '',
724 + 'session_id' => $session_id
725 + ]);
726 + wp_die();
727 +}
728 +
707 729 // Save the user's message
708 730 $this->mxchat_save_chat_message($session_id, 'user', $message);
709 731
710 732 // Check if the message is an email address
@@ -727,9 +749,9 @@
727 749 $intent_info = '';
728 750
729 751 // Check chat mode
730 752 $chat_mode = get_option("mxchat_mode_{$session_id}", 'ai');
731 - //error_log("Chat Mode: $chat_mode");
753 + error_log("Chat Mode: $chat_mode");
732 754
733 755 // Handle agent mode
734 756 if ($chat_mode === 'agent') {
735 757 // First, check for switch intent before doing anything else
@@ -736,9 +758,9 @@
736 758 $intent_matched = $this->mxchat_check_intent_and_invoke_callback($message, $user_id, $session_id);
737 759
738 760 // If we matched an intent and it's the switch intent, handle it
739 761 if ($intent_matched && !empty($this->fallbackResponse['text'])) {
740 - //error_log("Switch to chatbot intent detected");
762 + error_log("Switch to chatbot intent detected");
741 763
742 764 // Update chat mode first
743 765 update_option("mxchat_mode_{$session_id}", 'ai');
744 766
@@ -763,9 +785,9 @@
763 785 } elseif (!$intent_matched) {
764 786 // No intent matched, handle live agent message
765 787 try {
766 788 $this->mxchat_send_user_message_to_agent($message, $user_id, $session_id);
767 - //error_log("Message sent to agent.");
789 + error_log("Message sent to agent.");
768 790
769 791 wp_send_json_success([
770 792 'status' => 'waiting_for_agent',
771 793 'message' => esc_html__('Message sent to live agent.', 'mxchat')
@@ -770,9 +792,9 @@
770 792 'status' => 'waiting_for_agent',
771 793 'message' => esc_html__('Message sent to live agent.', 'mxchat')
772 794 ]);
773 795 } catch (\Exception $e) {
774 - //error_log("Error sending message to agent: " . $e->getMessage());
796 + error_log("Error sending message to agent: " . $e->getMessage());
775 797 wp_send_json_error(esc_html__('Failed to send message to agent', 'mxchat'));
776 798 }
777 799 wp_die();
778 800 }
@@ -857,27 +879,49 @@
857 879 }
858 880 }
859 881 }
860 882
861 - // Step 2: Detect intent and handle intent-based responses
862 - $intent_matched = $this->mxchat_check_intent_and_invoke_callback($message, $user_id, $session_id);
863 - //error_log("Intent Matched: " . ($intent_matched ? "Yes" : "No"));
883 + // Step 2: Detect intent and handle intent-based responses
884 +$intent_result = $this->mxchat_check_intent_and_invoke_callback($message, $user_id, $session_id);
885 +error_log("Intent Result Type: " . gettype($intent_result));
864 886
865 - // Step 3: If intent is matched and handled, respond immediately
866 - if ($intent_matched && (!empty($this->fallbackResponse['text']) || !empty($this->fallbackResponse['html']))) {
867 - //error_log("Intent response triggered.");
887 +// Step 3: Handle the intent result appropriately
888 +if ($intent_result !== false) {
889 + // The intent was matched and handled
890 + error_log("Intent was matched and handled.");
891 +
892 + if (is_array($intent_result) && (isset($intent_result['text']) || isset($intent_result['html']))) {
893 + // Intent returned a direct response array
894 + error_log("Intent returned a direct response.");
868 895 $response_data = [
869 - 'text' => $this->fallbackResponse['text'],
870 - 'html' => $this->fallbackResponse['html'],
896 + 'text' => $intent_result['text'] ?? '',
897 + 'html' => $intent_result['html'] ?? '',
871 898 'session_id' => $session_id
872 899 ];
873 - $this->mxchat_save_chat_message($session_id, 'bot', $this->fallbackResponse['text'] . $this->fallbackResponse['html']);
900 +
874 901 wp_send_json($response_data);
875 902 wp_die();
903 + }
904 + else if ($intent_result === true && (!empty($this->fallbackResponse['text']) || !empty($this->fallbackResponse['html']))) {
905 + // Intent returned true and set fallbackResponse
906 + error_log("Intent returned true with fallbackResponse set.");
907 + $response_data = [
908 + 'text' => $this->fallbackResponse['text'] ?? '',
909 + 'html' => $this->fallbackResponse['html'] ?? '',
910 + 'session_id' => $session_id
911 + ];
912 +
913 + wp_send_json($response_data);
914 + wp_die();
876 915 }
916 +
917 + // Intent was matched but no usable response was provided
918 + // This shouldn't happen with proper intent implementation
919 + error_log("Warning: Intent matched but no response provided.");
920 +}
877 921
878 - // If no intent matched or product not found, proceed with AI response
879 - //error_log("No matching intent or fallback. Generating AI response.");
922 +// If we get here, no intent matched OR the intent didn't provide a usable response
923 +error_log("No matching intent or usable response. Generating AI response.");
880 924
881 925 // Step 4: Generate AI response
882 926 $conversation_history = $this->mxchat_fetch_conversation_history_for_ai($session_id);
883 927 $this->mxchat_increment_chat_count();
@@ -884,9 +928,9 @@
884 928
885 929 // Generate embedding for the user's query
886 930 $user_message_embedding = $this->mxchat_generate_embedding($message, $this->options['api_key']);
887 931 if (!is_array($user_message_embedding)) {
888 - //error_log("Failed to generate message embedding for session $session_id");
932 + error_log("Failed to generate message embedding for session $session_id");
889 933 wp_send_json_error(esc_html__('Error processing your message.', 'mxchat'));
890 934 wp_die();
891 935 }
892 936
@@ -928,18 +972,22 @@
928 972 }
929 973 $context_content .= "\n";
930 974 }
931 975 }
932 - // Generate the response using the full context
933 - $response = $this->mxchat_generate_response(
934 - $context_content,
935 - $this->options['api_key'],
936 - $this->options['xai_api_key'],
937 - $this->options['claude_api_key'],
938 - $this->options['deepseek_api_key'],
939 - $conversation_history
940 - );
976 +
977 + $context_content = apply_filters('mxchat_prepare_context', $context_content, $session_id);
941 978
979 + // Generate the response using the full context
980 + $response = $this->mxchat_generate_response(
981 + $context_content,
982 + $this->options['api_key'],
983 + $this->options['xai_api_key'],
984 + $this->options['claude_api_key'],
985 + $this->options['deepseek_api_key'],
986 + $this->options['gemini_api_key'], // Added Gemini API key
987 + $conversation_history
988 + );
989 +
942 990 $this->mxchat_save_chat_message($session_id, 'bot', $response);
943 991
944 992 // Step 5: Save additional content if available
945 993 if (!empty($this->productCardHtml)) {
@@ -961,43 +1009,45 @@
961 1009 wp_die();
962 1010 }
963 1011
964 1012 // New function to check intents and invoke the callback function
1013 +// Updated function to check intents and invoke the callback function
965 1014 private function mxchat_check_intent_and_invoke_callback($message, $user_id, $session_id) {
966 1015 global $wpdb;
967 1016 $chat_mode = get_option("mxchat_mode_{$session_id}", 'ai');
968 1017
969 - //error_log('🔍 MXCHAT DEBUG: Intent Check Started ==================');
970 - //error_log("🔍 MXCHAT DEBUG: Message: '$message'");
971 - //error_log("🔍 MXCHAT DEBUG: Chat Mode: $chat_mode");
1018 + error_log('🔍 MXCHAT DEBUG: Intent Check Started ==================');
1019 + error_log("🔍 MXCHAT DEBUG: Message: '$message'");
1020 + error_log("🔍 MXCHAT DEBUG: Chat Mode: $chat_mode");
972 1021
973 1022 // Generate the user embedding
974 - //error_log('🔄 MXCHAT DEBUG: Generating user embedding');
1023 + error_log('🔄 MXCHAT DEBUG: Generating user embedding');
975 1024 $user_embedding = $this->mxchat_generate_embedding($message, $this->options['api_key']);
976 1025 if (!is_array($user_embedding)) {
977 - //error_log('❌ MXCHAT DEBUG: Failed to generate user embedding');
1026 + error_log('❌ MXCHAT DEBUG: Failed to generate user embedding');
978 1027 return false;
979 1028 }
980 - //error_log('✅ MXCHAT DEBUG: User embedding generated successfully');
1029 + error_log('✅ MXCHAT DEBUG: User embedding generated successfully');
981 1030
982 1031 // Fetch intents from the database
983 1032 $table_name = $wpdb->prefix . 'mxchat_intents';
984 1033 if ($chat_mode === 'agent') {
985 - //error_log('🔍 MXCHAT DEBUG: Agent mode - fetching only chatbot switch intent');
1034 + error_log('🔍 MXCHAT DEBUG: Agent mode - fetching only chatbot switch intent');
986 1035 $query = $wpdb->prepare(
987 - "SELECT * FROM $table_name WHERE callback_function = %s",
1036 + "SELECT * FROM $table_name WHERE callback_function = %s AND (enabled = 1 OR enabled IS NULL)",
988 1037 'mxchat_handle_switch_to_chatbot_intent'
989 1038 );
990 1039 $intents = $wpdb->get_results($query);
991 1040 } else {
992 - //error_log('🔍 MXCHAT DEBUG: AI mode - fetching all intents');
993 - $intents = $wpdb->get_results("SELECT * FROM $table_name");
1041 + error_log('🔍 MXCHAT DEBUG: AI mode - fetching all enabled intents');
1042 + // Only fetch enabled intents (either explicitly enabled with 1 or implicitly enabled with NULL for backward compatibility)
1043 + $intents = $wpdb->get_results("SELECT * FROM $table_name WHERE enabled = 1 OR enabled IS NULL");
994 1044 }
995 1045
996 - //error_log('🔍 MXCHAT DEBUG: Found ' . count($intents) . ' intents to check');
1046 + error_log('🔍 MXCHAT DEBUG: Found ' . count($intents) . ' enabled intents to check');
997 1047
998 1048 if (empty($intents)) {
999 - //error_log('❌ MXCHAT DEBUG: No intents found in database');
1049 + error_log('❌ MXCHAT DEBUG: No enabled intents found in database');
1000 1050 return false;
1001 1051 }
1002 1052
1003 1053 $highest_similarity = -INF;
@@ -1002,12 +1052,19 @@
1002 1052
1003 1053 $highest_similarity = -INF;
1004 1054 $matched_intent = null;
1005 1055
1006 - //error_log('📊 MXCHAT DEBUG: Intent Similarity Scores ==================');
1056 + error_log('📊 MXCHAT DEBUG: Intent Similarity Scores ==================');
1007 1057 foreach ($intents as $intent) {
1008 - //error_log("🔄 MXCHAT DEBUG: Checking intent: '{$intent->intent_label}' (callback: {$intent->callback_function})");
1058 + error_log("🔄 MXCHAT DEBUG: Checking intent: '{$intent->intent_label}' (callback: {$intent->callback_function})");
1009 1059
1060 + // Additional check for enabled state in case database structure was modified
1061 + $is_enabled = isset($intent->enabled) ? (bool)$intent->enabled : true;
1062 + if (!$is_enabled) {
1063 + error_log("⚠️ MXCHAT DEBUG: Skipping disabled intent: {$intent->intent_label}");
1064 + continue;
1065 + }
1066 +
1010 1067 $intent_embedding_serialized = $intent->embedding_vector;
1011 1068 $intent_embedding = $intent_embedding_serialized
1012 1069 ? unserialize($intent_embedding_serialized, ['allowed_classes' => false])
1013 1070 : null;
@@ -1012,9 +1069,9 @@
1012 1069 ? unserialize($intent_embedding_serialized, ['allowed_classes' => false])
1013 1070 : null;
1014 1071
1015 1072 if (!is_array($intent_embedding)) {
1016 - //error_log("❌ MXCHAT DEBUG: Invalid embedding for intent: {$intent->intent_label}");
1073 + error_log("❌ MXCHAT DEBUG: Invalid embedding for intent: {$intent->intent_label}");
1017 1074 continue;
1018 1075 }
1019 1076
1020 1077 $similarity = $this->mxchat_calculate_cosine_similarity($user_embedding, $intent_embedding);
@@ -1019,24 +1076,25 @@
1019 1076
1020 1077 $similarity = $this->mxchat_calculate_cosine_similarity($user_embedding, $intent_embedding);
1021 1078 $intent_threshold = isset($intent->similarity_threshold) ? $intent->similarity_threshold : 0.85;
1022 1079
1080 + error_log("📊 MXCHAT DEBUG: Intent '{$intent->intent_label}' similarity: {$similarity}, threshold: {$intent_threshold}");
1023 1081
1024 1082 if ($similarity >= $intent_threshold && $similarity > $highest_similarity) {
1025 1083 $highest_similarity = $similarity;
1026 1084 $matched_intent = $intent;
1027 - //error_log("✅ MXCHAT DEBUG: New best match: '{$intent->intent_label}' with similarity {$similarity}");
1085 + error_log("✅ MXCHAT DEBUG: New best match: '{$intent->intent_label}' with similarity {$similarity}");
1028 1086 }
1029 1087 }
1030 - //error_log('📊 MXCHAT DEBUG: End Intent Scores ==================');
1088 + error_log('📊 MXCHAT DEBUG: End Intent Scores ==================');
1031 1089
1032 1090 if ($matched_intent) {
1033 - //error_log("🎯 MXCHAT DEBUG: Final Intent Match: '{$matched_intent->intent_label}'");
1034 - //error_log("🔄 MXCHAT DEBUG: Invoking callback: {$matched_intent->callback_function}");
1091 + error_log("🎯 MXCHAT DEBUG: Final Intent Match: '{$matched_intent->intent_label}'");
1092 + error_log("🔄 MXCHAT DEBUG: Invoking callback: {$matched_intent->callback_function}");
1035 1093
1036 1094 // If the callback is a method on this instance (core callback), call it directly
1037 1095 if (method_exists($this, $matched_intent->callback_function)) {
1038 - //error_log('🔍 MXCHAT DEBUG: Using direct method call for core callback');
1096 + error_log('🔍 MXCHAT DEBUG: Using direct method call for core callback');
1039 1097 $callback_result = call_user_func(
1040 1098 [$this, $matched_intent->callback_function],
1041 1099 $message,
1042 1100 $user_id,
@@ -1041,12 +1099,12 @@
1041 1099 $message,
1042 1100 $user_id,
1043 1101 $session_id,
1044 1102 $matched_intent,
1045 - $user_context // Add user context
1103 + $user_context
1046 1104 );
1047 1105 } else {
1048 - //error_log('🔍 MXCHAT DEBUG: Using apply_filters for add-on callback');
1106 + error_log('🔍 MXCHAT DEBUG: Using apply_filters for add-on callback');
1049 1107 // Otherwise, use apply_filters for add-on callbacks
1050 1108 $callback_result = apply_filters(
1051 1109 $matched_intent->callback_function,
1052 1110 false, // default return value
@@ -1056,24 +1114,22 @@
1056 1114 $matched_intent
1057 1115 );
1058 1116 }
1059 1117
1060 - //error_log('🔍 MXCHAT DEBUG: Callback result type: ' . gettype($callback_result));
1118 + error_log('🔍 MXCHAT DEBUG: Callback result type: ' . gettype($callback_result));
1061 1119 if ($callback_result !== false) {
1062 - //error_log('✅ MXCHAT DEBUG: Intent handled successfully');
1120 + error_log('✅ MXCHAT DEBUG: Intent handled successfully');
1063 1121 $this->fallbackResponse = $callback_result;
1064 1122 return true;
1065 1123 }
1066 - //error_log('❌ MXCHAT DEBUG: Callback returned false');
1124 + error_log('❌ MXCHAT DEBUG: Callback returned false');
1067 1125 } else {
1068 - //error_log('❌ MXCHAT DEBUG: No matching intent found');
1126 + error_log('❌ MXCHAT DEBUG: No matching intent found');
1069 1127 }
1070 1128
1071 - //error_log('🔍 MXCHAT DEBUG: Intent Check Completed ==================');
1129 + error_log('🔍 MXCHAT DEBUG: Intent Check Completed ==================');
1072 1130 return false;
1073 1131 }
1074 -
1075 -
1076 1132 // Helper function to clear PDF and Word document related transients
1077 1133 private function clear_pdf_transients($session_id) {
1078 1134 // PDF transients
1079 1135 delete_transient('mxchat_pdf_url_' . $session_id);
@@ -1093,9 +1149,9 @@
1093 1149
1094 1150 //verified good
1095 1151 public function mxchat_handle_email_capture($message, $user_id, $session_id) {
1096 1152 // Log the message safely
1097 - //error_log("Triggered email capture intent for message: " . sanitize_text_field($message));
1153 + error_log("Triggered email capture intent for message: " . sanitize_text_field($message));
1098 1154
1099 1155 // Initiate email capture flow
1100 1156 $response = esc_html($this->options['triggered_phrase_response'] ?? esc_html__("Would you like to join our mailing list? Please provide your email below.", 'mxchat'));
1101 1157
@@ -1106,47 +1162,63 @@
1106 1162 wp_send_json(['message' => $response]);
1107 1163 wp_die();
1108 1164 }
1109 1165
1110 -//very good
1111 1166 public function mxchat_generate_image($message, $user_id, $session_id) {
1167 + error_log("Starting image generation for message: " . $message);
1168 +
1112 1169 // Prepare a prompt for DALL-E
1113 1170 $prompt = esc_html__('Create an image of ', 'mxchat') . sanitize_text_field($message);
1114 -
1171 +
1115 1172 // Use the existing OpenAI API key
1116 1173 $openai_api_key = sanitize_text_field($this->options['api_key']);
1117 -
1174 +
1118 1175 // Call DALL-E to generate an image
1119 1176 $image_response = $this->mxchat_generate_dalle_image($prompt, $openai_api_key);
1120 -
1177 +
1121 1178 // Check if the response contains an image URL
1122 1179 if (isset($image_response['imageUrl'])) {
1123 1180 $image_url = esc_url_raw($image_response['imageUrl']);
1124 -
1181 +
1125 1182 // Construct the HTML with a CSS class instead of inline styles
1126 1183 $response_html = '<img src="' . esc_url($image_url) . '" alt="' . esc_attr__('Generated Image', 'mxchat') . '" class="mxchat-generated-image" />';
1184 + $response_text = esc_html__('Here is the image I generated:', 'mxchat');
1185 +
1186 + // Save the bot message with both text and HTML
1187 + $this->mxchat_save_chat_message($session_id, 'bot', $response_text);
1188 + $this->mxchat_save_chat_message($session_id, 'bot', $response_html);
1189 +
1190 + // Set the fallback response for the chat handler
1191 + $this->fallbackResponse = [
1192 + 'text' => $response_text,
1193 + 'html' => $response_html,
1194 + 'images' => [$image_url]
1195 + ];
1196 +
1197 + // For debugging/verification - Use json_encode to verify what's being set
1198 + error_log("Image generation successful - fallbackResponse set: " . json_encode($this->fallbackResponse));
1127 1199
1128 - $response_text = esc_html__('Here is the image I generated:', 'mxchat');
1200 + // Return the response directly instead of relying on the property
1201 + return $this->fallbackResponse;
1129 1202 } else {
1130 1203 $response_text = esc_html__("I'm sorry, but I couldn't generate an image based on your request.", 'mxchat');
1131 - $response_html = '';
1132 - //error_log("DALL-E image generation error: " . esc_html($image_response['error'] ?? 'Unknown error.'));
1204 +
1205 + // Save the error message
1206 + $this->mxchat_save_chat_message($session_id, 'bot', $response_text);
1207 +
1208 + // Set the fallback response for the chat handler
1209 + $this->fallbackResponse = [
1210 + 'text' => $response_text,
1211 + 'html' => '',
1212 + 'images' => []
1213 + ];
1214 +
1215 + error_log("DALL-E image generation error: " . esc_html($image_response['error'] ?? 'Unknown error.'));
1216 + error_log("Error fallbackResponse set: " . json_encode($this->fallbackResponse));
1217 +
1218 + // Return the response directly instead of relying on the property
1219 + return $this->fallbackResponse;
1133 1220 }
1134 -
1135 - // Save both text and HTML responses
1136 - $this->mxchat_save_chat_message($session_id, 'bot', $response_text . "\n" . $response_html);
1137 -
1138 - // Prepare the response data
1139 - $response_data = [
1140 - 'message' => $response_text,
1141 - 'html' => $response_html,
1142 - 'image_url' => $image_url ?? '',
1143 - ];
1144 -
1145 - // Send the JSON response
1146 - header('Content-Type: application/json; charset=' . get_option('blog_charset'));
1147 - echo json_encode($response_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
1148 - wp_die();
1149 1221 }
1150 1222 private function mxchat_generate_dalle_image($prompt, $api_key, $model = 'dall-e-3', $timeout = 60) {
1151 1223 $api_url = 'https://api.openai.com/v1/images/generations';
1152 1224 $body = json_encode([
@@ -1168,9 +1240,9 @@
1168 1240
1169 1241 $response = wp_remote_post($api_url, $args);
1170 1242
1171 1243 if (is_wp_error($response)) {
1172 - //error_log("DALL-E request failed: " . $response->get_error_message());
1244 + error_log("DALL-E request failed: " . $response->get_error_message());
1173 1245 return ['error' => esc_html__('Error generating image: ', 'mxchat') . $response->get_error_message()];
1174 1246 }
1175 1247
1176 1248 $response_body = json_decode(wp_remote_retrieve_body($response), true);
@@ -1177,9 +1249,9 @@
1177 1249
1178 1250 if (isset($response_body['data'][0]['url'])) {
1179 1251 return ['imageUrl' => esc_url_raw($response_body['data'][0]['url'])];
1180 1252 } else {
1181 - //error_log("DALL-E response error: " . wp_remote_retrieve_body($response));
1253 + error_log("DALL-E response error: " . wp_remote_retrieve_body($response));
1182 1254 return ['error' => esc_html__('Failed to generate image.', 'mxchat')];
1183 1255 }
1184 1256 }
1185 1257
@@ -1185,44 +1257,43 @@
1185 1257
1186 1258 /**
1187 1259 * Handle web search requests.
1188 1260 *
1189 - * Sends the refined search query to the Brave Search API and displays neatly formatted,
1190 - * styled search results. Results are cached for performance.
1261 + * Sends the refined search query to the Brave Search API and uses the
1262 + * results to generate a conversational response with the AI model.
1191 1263 *
1192 1264 * @since 1.0.0
1193 1265 * @param string $message The user's search query.
1194 1266 * @param string $user_id The user identifier.
1195 1267 * @param string $session_id The current session ID.
1196 - * @return void
1268 + * @return array Response array containing text with embedded HTML links
1197 1269 */
1198 -public function mxchat_handle_search_request( $message, $user_id, $session_id ) {
1270 +public function mxchat_handle_search_request($message, $user_id, $session_id) {
1199 1271 // Step 1: Interpret and refine the search query
1200 - $refined_search_query = $this->mxchat_interpret_search_query( $message );
1201 -
1202 - if ( empty( $refined_search_query ) ) {
1203 - $this->fallbackResponse = array(
1204 - 'text' => esc_html__( 'I apologize, but could you please rephrase your search request?', 'mxchat' ),
1272 + $refined_search_query = $this->mxchat_interpret_search_query($message);
1273 + if (empty($refined_search_query)) {
1274 + return array(
1275 + 'text' => esc_html__('I apologize, but could you please rephrase your search request?', 'mxchat'),
1276 + 'html' => ''
1205 1277 );
1206 - return;
1207 1278 }
1208 -
1279 +
1209 1280 // Retrieve and validate API settings
1210 - $options = get_option( 'mxchat_options' );
1211 - $api_key = isset( $options['brave_api_key'] ) ? sanitize_text_field( $options['brave_api_key'] ) : '';
1212 - $results_count = isset( $options['brave_results_count'] ) ? absint( $options['brave_results_count'] ) : 5;
1213 -
1214 - if ( empty( $api_key ) ) {
1215 - $this->fallbackResponse = array(
1216 - 'text' => esc_html__( 'Search functionality is temporarily unavailable. Please try again later.', 'mxchat' ),
1281 + $options = get_option('mxchat_options');
1282 + $api_key = isset($options['brave_api_key']) ? sanitize_text_field($options['brave_api_key']) : '';
1283 + $results_count = isset($options['brave_results_count']) ? absint($options['brave_results_count']) : 5;
1284 +
1285 + if (empty($api_key)) {
1286 + return array(
1287 + 'text' => esc_html__('Search functionality is temporarily unavailable. Please try again later.', 'mxchat'),
1288 + 'html' => ''
1217 1289 );
1218 - return;
1219 1290 }
1220 -
1291 +
1221 1292 // Build the API request URL
1222 1293 $api_url = add_query_arg(
1223 1294 array(
1224 - 'q' => rawurlencode( $refined_search_query ),
1295 + 'q' => rawurlencode($refined_search_query),
1225 1296 'count' => $results_count,
1226 1297 'text_decorations' => 'true',
1227 1298 'rich_data' => 'true',
1228 1299 ),
@@ -1227,14 +1298,14 @@
1227 1298 'rich_data' => 'true',
1228 1299 ),
1229 1300 'https://api.search.brave.com/res/v1/web/search'
1230 1301 );
1231 -
1302 +
1232 1303 // Attempt to retrieve cached results first
1233 - $transient_key = 'mxchat_search_' . md5( $refined_search_query );
1234 - $results = get_transient( $transient_key );
1235 -
1236 - if ( false === $results ) {
1304 + $transient_key = 'mxchat_search_' . md5($refined_search_query);
1305 + $results = get_transient($transient_key);
1306 +
1307 + if (false === $results) {
1237 1308 // Fetch new results from the Brave Search API
1238 1309 $response = wp_remote_get(
1239 1310 $api_url,
1240 1311 array(
@@ -1245,51 +1316,78 @@
1245 1316 ),
1246 1317 'timeout' => 10,
1247 1318 )
1248 1319 );
1249 -
1250 - if ( is_wp_error( $response ) ) {
1251 - $this->fallbackResponse = array(
1252 - 'text' => esc_html__( 'I encountered an error while searching. Please try again.', 'mxchat' ),
1320 +
1321 + if (is_wp_error($response)) {
1322 + return array(
1323 + 'text' => esc_html__('I encountered an error while searching. Please try again.', 'mxchat'),
1324 + 'html' => ''
1253 1325 );
1254 - return;
1255 1326 }
1256 -
1257 - $results = json_decode( wp_remote_retrieve_body( $response ), true );
1258 -
1259 - if ( json_last_error() !== JSON_ERROR_NONE ) {
1260 - $this->fallbackResponse = array(
1261 - 'text' => esc_html__( 'I received an invalid response from the search service.', 'mxchat' ),
1327 +
1328 + $results = json_decode(wp_remote_retrieve_body($response), true);
1329 +
1330 + if (json_last_error() !== JSON_ERROR_NONE) {
1331 + return array(
1332 + 'text' => esc_html__('I received an invalid response from the search service.', 'mxchat'),
1333 + 'html' => ''
1262 1334 );
1263 - return;
1264 1335 }
1265 -
1336 +
1266 1337 // Cache results for one hour
1267 - set_transient( $transient_key, $results, HOUR_IN_SECONDS );
1338 + set_transient($transient_key, $results, HOUR_IN_SECONDS);
1268 1339 }
1269 -
1270 - // Process and display results
1271 - if ( ! empty( $results['web']['results'] ) && is_array( $results['web']['results'] ) ) {
1272 - $html = $this->generate_search_results_html( $results['web']['results'], $refined_search_query );
1273 -
1274 - // Only return HTML (no large text summary)
1275 - $this->fallbackResponse = array(
1276 - 'html' => $html,
1340 +
1341 + // Process results
1342 + if (!empty($results['web']['results']) && is_array($results['web']['results'])) {
1343 + // Create a more straightforward summary with HTML links
1344 + $search_results_text = '';
1345 +
1346 + // Add a simple intro
1347 + $search_results_text .= sprintf(
1348 + esc_html__("Here's what I found about '%s':", 'mxchat'),
1349 + esc_html($refined_search_query)
1277 1350 );
1278 -
1351 +
1352 + // Add the top results with HTML links
1353 + foreach (array_slice($results['web']['results'], 0, 5) as $result) {
1354 + $title = isset($result['title']) ? wp_strip_all_tags($result['title']) : '';
1355 + $url = isset($result['url']) ? esc_url($result['url']) : '';
1356 + $description = isset($result['description']) ? wp_strip_all_tags($result['description']) : '';
1357 +
1358 + // Add a line break after the intro
1359 + $search_results_text .= '<br><br>';
1360 +
1361 + // Add title as a link
1362 + $search_results_text .= sprintf(
1363 + '<a href="%s" target="_blank" rel="noopener noreferrer">%s</a><br>',
1364 + $url,
1365 + $title
1366 + );
1367 +
1368 + // Add a condensed description
1369 + $search_results_text .= sprintf("%s", $description);
1370 + }
1371 +
1279 1372 // Save to chat history
1280 - $this->mxchat_save_chat_message( $session_id, 'bot', $html );
1373 + $this->mxchat_save_chat_message($session_id, 'bot', $search_results_text);
1374 +
1375 + // Return the formatted text with embedded HTML links
1376 + return array(
1377 + 'text' => $search_results_text,
1378 + 'html' => ''
1379 + );
1281 1380 } else {
1282 - $this->fallbackResponse = array(
1381 + return array(
1283 1382 'text' => sprintf(
1284 - esc_html__( 'I couldn\'t find any relevant results for "%s". Would you like to try different search terms?', 'mxchat' ),
1285 - esc_html( $refined_search_query )
1383 + esc_html__('I searched for "%s" but couldn\'t find any relevant results. Would you like to try different search terms?', 'mxchat'),
1384 + esc_html($refined_search_query)
1286 1385 ),
1386 + 'html' => ''
1287 1387 );
1288 1388 }
1289 1389 }
1290 -
1291 -
1292 1390 /**
1293 1391 * Format search results into a natural text summary.
1294 1392 *
1295 1393 * @since 1.0.0
@@ -1529,9 +1627,9 @@
1529 1627 }
1530 1628 */
1531 1629
1532 1630 if (empty($api_key)) {
1533 - //error_log("OpenAI API key is missing.");
1631 + error_log("OpenAI API key is missing.");
1534 1632 return sanitize_text_field($user_query); // Default to the original query if API key is missing
1535 1633 }
1536 1634
1537 1635 $url = 'https://api.openai.com/v1/chat/completions';
@@ -1554,9 +1652,9 @@
1554 1652
1555 1653 $response = wp_remote_post($url, $args);
1556 1654
1557 1655 if (is_wp_error($response)) {
1558 - //error_log("OpenAI request failed: " . $response->get_error_message());
1656 + error_log("OpenAI request failed: " . $response->get_error_message());
1559 1657 return sanitize_text_field($user_query); // Fallback to the original query if there's an error
1560 1658 }
1561 1659
1562 1660 $body = json_decode(wp_remote_retrieve_body($response), true);
@@ -1573,9 +1671,9 @@
1573 1671 */
1574 1672
1575 1673 return $interpreted_query;
1576 1674 } else {
1577 - //error_log("Unexpected API response format: " . print_r($body, true));
1675 + error_log("Unexpected API response format: " . print_r($body, true));
1578 1676 return sanitize_text_field($user_query);
1579 1677 }
1580 1678 }
1581 1679
@@ -1656,9 +1754,8 @@
1656 1754 // New method to handle intent responses
1657 1755 private function generate_intent_response($context_content, $session_id) {
1658 1756 // Convert the context array to a structured string for the AI
1659 1757 $context_string = $this->format_intent_context($context_content);
1660 -
1661 1758 // Generate AI response using the context
1662 1759 $response = $this->mxchat_generate_response(
1663 1760 $context_string,
1664 1761 $this->options['api_key'],
@@ -1664,14 +1761,15 @@
1664 1761 $this->options['api_key'],
1665 1762 $this->options['xai_api_key'],
1666 1763 $this->options['claude_api_key'],
1667 1764 $this->options['deepseek_api_key'],
1765 + $this->options['gemini_api_key'], // Added Gemini API key
1668 1766 $this->mxchat_fetch_conversation_history_for_ai($session_id)
1669 1767 );
1670 -
1671 1768 $this->fallbackResponse['text'] = $response;
1672 1769 return true;
1673 1770 }
1771 +
1674 1772 // Helper method to format intent context
1675 1773 private function format_intent_context($context) {
1676 1774 $context_string = esc_html__("INTENT CONTEXT:\n", 'mxchat');
1677 1775
@@ -1718,9 +1816,9 @@
1718 1816 $mailing_list_id = isset($this->options['loops_mailing_list']) ? sanitize_text_field($this->options['loops_mailing_list']) : '';
1719 1817
1720 1818 // Check for missing API key or mailing list ID
1721 1819 if (empty($api_key) || empty($mailing_list_id)) {
1722 - //error_log(esc_html__('Loops API key or mailing list ID is missing.', 'mxchat'));
1820 + error_log(esc_html__('Loops API key or mailing list ID is missing.', 'mxchat'));
1723 1821 return;
1724 1822 }
1725 1823
1726 1824 $data = array(
@@ -1744,9 +1842,9 @@
1744 1842 $response = wp_remote_post($url, $args);
1745 1843
1746 1844 // Handle errors in the API request
1747 1845 if (is_wp_error($response)) {
1748 - //error_log(esc_html__('Error adding email to Loops: ', 'mxchat') . $response->get_error_message());
1846 + error_log(esc_html__('Error adding email to Loops: ', 'mxchat') . $response->get_error_message());
1749 1847 return;
1750 1848 }
1751 1849
1752 1850 // Check for non-200 HTTP responses
@@ -1752,9 +1850,9 @@
1752 1850 // Check for non-200 HTTP responses
1753 1851 $response_code = wp_remote_retrieve_response_code($response);
1754 1852 if ($response_code != 200) {
1755 1853 $response_body = wp_remote_retrieve_body($response);
1756 - //error_log(esc_html__('Loops API responded with code ', 'mxchat') . $response_code . ': ' . $response_body);
1854 + error_log(esc_html__('Loops API responded with code ', 'mxchat') . $response_code . ': ' . $response_body);
1757 1855 }
1758 1856 }
1759 1857
1760 1858 public function mxchat_handle_pdf_discussion($message, $user_id, $session_id) {
@@ -1804,9 +1902,9 @@
1804 1902 $temp_file = wp_tempnam($pdf_source); // Safe temporary file name
1805 1903 $response = wp_remote_get($pdf_source, ['timeout' => 60]);
1806 1904
1807 1905 if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
1808 - //error_log(esc_html__("Failed to download PDF. Error: ", 'mxchat') . print_r($response, true));
1906 + error_log(esc_html__("Failed to download PDF. Error: ", 'mxchat') . print_r($response, true));
1809 1907 return false;
1810 1908 }
1811 1909
1812 1910 file_put_contents($temp_file, wp_remote_retrieve_body($response));
@@ -1813,9 +1911,9 @@
1813 1911
1814 1912 // Validate that the downloaded file is a PDF
1815 1913 $mime_type = mime_content_type($temp_file);
1816 1914 if ($mime_type !== 'application/pdf') {
1817 - //error_log(esc_html__("Invalid MIME type detected for PDF: ", 'mxchat') . $mime_type);
1915 + error_log(esc_html__("Invalid MIME type detected for PDF: ", 'mxchat') . $mime_type);
1818 1916 unlink($temp_file);
1819 1917 return false;
1820 1918 }
1821 1919 } else {
@@ -1828,9 +1926,9 @@
1828 1926 $pdf = $parser->parseFile($temp_file);
1829 1927 $pages = $pdf->getPages();
1830 1928
1831 1929 if (count($pages) > $max_pages) {
1832 - //error_log(esc_html__("PDF exceeds the maximum allowed pages: ", 'mxchat') . count($pages));
1930 + error_log(esc_html__("PDF exceeds the maximum allowed pages: ", 'mxchat') . count($pages));
1833 1931 if (filter_var($pdf_source, FILTER_VALIDATE_URL)) {
1834 1932 unlink($temp_file);
1835 1933 }
1836 1934 return esc_html__('too_many_pages', 'mxchat');
@@ -1841,9 +1939,9 @@
1841 1939 $text = $page->getText();
1842 1940
1843 1941 // Ensure text is non-empty before generating embeddings
1844 1942 if (empty(trim($text))) {
1845 - //error_log(esc_html__("Skipping empty page: ", 'mxchat') . ($page_number + 1));
1943 + error_log(esc_html__("Skipping empty page: ", 'mxchat') . ($page_number + 1));
1846 1944 continue;
1847 1945 }
1848 1946
1849 1947 $embedding = $this->mxchat_generate_embedding(
@@ -1857,9 +1955,9 @@
1857 1955 'embedding' => $embedding,
1858 1956 'text' => $text,
1859 1957 ];
1860 1958 } else {
1861 - //error_log(esc_html__("Failed to generate embedding for page ", 'mxchat') . ($page_number + 1));
1959 + error_log(esc_html__("Failed to generate embedding for page ", 'mxchat') . ($page_number + 1));
1862 1960 }
1863 1961 }
1864 1962
1865 1963 // Clean up downloaded file if it was from URL
@@ -1880,9 +1978,9 @@
1880 1978 return false;
1881 1979 }
1882 1980 }
1883 1981 private function find_relevant_pdf_pages($query_embedding, $embeddings) {
1884 - //error_log(esc_html__("find_relevant_pdf_pages called.", 'mxchat'));
1982 + error_log(esc_html__("find_relevant_pdf_pages called.", 'mxchat'));
1885 1983
1886 1984 $most_relevant = null;
1887 1985 $highest_similarity = -INF;
1888 1986
@@ -2010,9 +2108,9 @@
2010 2108 $persistence_enabled = $_POST['persistence_enabled'] === 'true';
2011 2109 $initial_timestamp = isset($_POST['initial_timestamp']) ? intval($_POST['initial_timestamp']) : 0;
2012 2110
2013 2111 if (empty($session_id)) {
2014 - //error_log(esc_html__('Fetch new messages error: Session ID missing.', 'mxchat'));
2112 + error_log(esc_html__('Fetch new messages error: Session ID missing.', 'mxchat'));
2015 2113 wp_send_json_error(['message' => esc_html__('Session ID missing.', 'mxchat')]);
2016 2114 wp_die();
2017 2115 }
2018 2116
@@ -2031,9 +2129,9 @@
2031 2129 $message['role'] === 'agent' &&
2032 2130 $message['timestamp'] > $initial_timestamp;
2033 2131 });
2034 2132
2035 - //error_log(esc_html__("New agent messages fetched for session $session_id. Last seen ID: $last_seen_id", 'mxchat'));
2133 + error_log(esc_html__("New agent messages fetched for session $session_id. Last seen ID: $last_seen_id", 'mxchat'));
2036 2134
2037 2135 wp_send_json_success([
2038 2136 'new_messages' => array_values($new_messages)
2039 2137 ]);
@@ -2181,9 +2279,9 @@
2181 2279 public function mxchat_send_user_message_to_agent($message, $user_id, $session_id) {
2182 2280 $slack_webhook_url = $this->options['live_agent_webhook_url'] ?? '';
2183 2281
2184 2282 if (empty($slack_webhook_url)) {
2185 - //error_log(esc_html__('Slack Webhook URL is not configured.', 'mxchat'));
2283 + error_log(esc_html__('Slack Webhook URL is not configured.', 'mxchat'));
2186 2284 return false;
2187 2285 }
2188 2286
2189 2287 $webhook_data = [
@@ -2242,20 +2340,20 @@
2242 2340 ],
2243 2341 ]);
2244 2342
2245 2343 if (is_wp_error($response)) {
2246 - //error_log(esc_html__('Error sending message to Slack: ', 'mxchat') . $response->get_error_message());
2344 + error_log(esc_html__('Error sending message to Slack: ', 'mxchat') . $response->get_error_message());
2247 2345 return false;
2248 2346 }
2249 2347
2250 - //error_log(esc_html__('Message sent to Slack successfully.', 'mxchat'));
2348 + error_log(esc_html__('Message sent to Slack successfully.', 'mxchat'));
2251 2349 return true;
2252 2350 }
2253 2351 public function handle_slack_interaction(WP_REST_Request $request) {
2254 - //error_log('Received Slack interaction');
2352 + error_log('Received Slack interaction');
2255 2353
2256 2354 $payload = json_decode($request->get_param('payload'), true);
2257 - //error_log('Payload: ' . print_r($payload, true));
2355 + error_log('Payload: ' . print_r($payload, true));
2258 2356
2259 2357 // Handle button click
2260 2358 if ($payload['type'] === 'block_actions' && $payload['actions'][0]['action_id'] === 'reply_to_user') {
2261 2359 $session_id = $payload['actions'][0]['value'];
@@ -2264,9 +2362,9 @@
2264 2362 // Get Bot Token from settings
2265 2363 $slack_token = $this->options['live_agent_bot_token'] ?? '';
2266 2364
2267 2365 if (empty($slack_token)) {
2268 - //error_log('Slack Bot Token not configured');
2366 + error_log('Slack Bot Token not configured');
2269 2367 return new WP_REST_Response(['error' => esc_html__('Bot token not configured', 'mxchat')], 400);
2270 2368 }
2271 2369 $response = wp_remote_post('https://slack.com/api/views.open', [
2272 2370 'headers' => [
@@ -2313,9 +2411,9 @@
2313 2411 ]
2314 2412 ])
2315 2413 ]);
2316 2414
2317 - //error_log('Views.open response: ' . print_r($response, true));
2415 + error_log('Views.open response: ' . print_r($response, true));
2318 2416
2319 2417 // Return immediate acknowledgment
2320 2418 return new WP_REST_Response(['ok' => true]);
2321 2419 }
@@ -2339,10 +2437,10 @@
2339 2437 return new WP_REST_Response(['ok' => true]);
2340 2438 }
2341 2439
2342 2440 public function mxchat_handle_agent_response(WP_REST_Request $request) {
2343 - //error_log('Received agent response request');
2344 - //error_log('Request data: ' . print_r($request->get_params(), true));
2441 + error_log('Received agent response request');
2442 + error_log('Request data: ' . print_r($request->get_params(), true));
2345 2443 // error_log('Raw body: ' . file_get_contents('php://input'));
2346 2444
2347 2445 // Get the data from Slack's slash command format
2348 2446 $command_text = $request->get_param('text');
@@ -2348,9 +2446,9 @@
2348 2446 $command_text = $request->get_param('text');
2349 2447 // error_log('Command text: ' . $command_text);
2350 2448
2351 2449 if (empty($command_text)) {
2352 - //error_log(esc_html__('Agent response error: No command text received', 'mxchat'));
2450 + error_log(esc_html__('Agent response error: No command text received', 'mxchat'));
2353 2451 return new WP_REST_Response([
2354 2452 'error' => esc_html__('Command text is required. Format: /reply session_id message', 'mxchat')
2355 2453 ], 400);
2356 2454 }
@@ -2357,9 +2455,9 @@
2357 2455
2358 2456 // Split the command text into session_id and message
2359 2457 $parts = explode(' ', $command_text, 2);
2360 2458 if (count($parts) !== 2) {
2361 - //error_log('Agent response error: Invalid command format');
2459 + error_log('Agent response error: Invalid command format');
2362 2460 return new WP_REST_Response([
2363 2461 'error' => esc_html__('Invalid format. Use: /reply session_id message', 'mxchat')
2364 2462 ], 400);
2365 2463 }
@@ -2366,9 +2464,9 @@
2366 2464
2367 2465 $session_id = sanitize_text_field($parts[0]);
2368 2466 $message = sanitize_text_field($parts[1]);
2369 2467
2370 - //error_log("Processing agent response - Session ID: $session_id, Message: $message");
2468 + error_log("Processing agent response - Session ID: $session_id, Message: $message");
2371 2469
2372 2470 // Save the message
2373 2471 $message_id = $this->mxchat_save_chat_message($session_id, 'agent', $message);
2374 2472
@@ -2387,9 +2485,9 @@
2387 2485 }
2388 2486
2389 2487
2390 2488 public function mxchat_handle_switch_to_chatbot_intent($message, $user_id, $session_id) {
2391 - //error_log(esc_html__("Switching back to chatbot mode via intent.", 'mxchat'));
2489 + error_log(esc_html__("Switching back to chatbot mode via intent.", 'mxchat'));
2392 2490
2393 2491 // Just update mode to AI
2394 2492 update_option("mxchat_mode_{$session_id}", 'ai');
2395 2493
@@ -2429,46 +2527,68 @@
2429 2527 return MxChat_User::mxchat_get_user_identifier();
2430 2528 }
2431 2529
2432 2530 private function mxchat_generate_embedding($text, $api_key) {
2531 + // Get options and selected model
2532 + $options = get_option('mxchat_options');
2533 + $selected_model = $options['embedding_model'] ?? 'text-embedding-ada-002';
2534 +
2535 + // Determine endpoint and API key based on model
2536 + if (strpos($selected_model, 'voyage') === 0) {
2537 + $endpoint = 'https://api.voyageai.com/v1/embeddings';
2538 + $api_key = $options['voyage_api_key'] ?? '';
2539 + } else {
2433 2540 $endpoint = 'https://api.openai.com/v1/embeddings';
2434 -
2435 - $body = wp_json_encode([
2436 - 'input' => $text,
2437 - 'model' => 'text-embedding-ada-002'
2438 - ]);
2439 -
2440 - $args = [
2441 - 'body' => $body,
2442 - 'headers' => [
2443 - 'Content-Type' => 'application/json',
2444 - 'Authorization' => 'Bearer ' . $api_key,
2445 - ],
2446 - 'timeout' => 60,
2447 - 'redirection' => 5,
2448 - 'blocking' => true,
2449 - 'httpversion' => '1.0',
2450 - 'sslverify' => true,
2451 - ];
2452 -
2453 - $response = wp_remote_post($endpoint, $args);
2454 -
2455 - if (is_wp_error($response)) {
2456 - return null;
2457 - }
2458 -
2459 - $response_body = json_decode(wp_remote_retrieve_body($response), true);
2460 -
2461 - if (isset($response_body['data'][0]['embedding']) && is_array($response_body['data'][0]['embedding'])) {
2462 - return $response_body['data'][0]['embedding'];
2463 - } else {
2464 - return null;
2465 - }
2541 + // Use the passed API key for OpenAI
2466 2542 }
2543 +
2544 + // Prepare request body with conditional output_dimension
2545 + $request_body = [
2546 + 'input' => $text,
2547 + 'model' => $selected_model
2548 + ];
2549 +
2550 + // Add output_dimension for voyage-3-large
2551 + if ($selected_model === 'voyage-3-large') {
2552 + $request_body['output_dimension'] = 2048;
2553 + }
2554 +
2555 + // Prepare request arguments
2556 + $args = [
2557 + 'body' => wp_json_encode($request_body),
2558 + 'headers' => [
2559 + 'Content-Type' => 'application/json',
2560 + 'Authorization' => 'Bearer ' . $api_key,
2561 + ],
2562 + 'timeout' => 60,
2563 + 'redirection' => 5,
2564 + 'blocking' => true,
2565 + 'httpversion' => '1.0',
2566 + 'sslverify' => true,
2567 + ];
2568 +
2569 + // Make the request
2570 + $response = wp_remote_post($endpoint, $args);
2571 +
2572 + // Rest of your existing code...
2573 + if (is_wp_error($response)) {
2574 + error_log('Embedding Generation Error: ' . $response->get_error_message());
2575 + return null;
2576 + }
2577 +
2578 + $response_body = json_decode(wp_remote_retrieve_body($response), true);
2579 +
2580 + if (isset($response_body['data'][0]['embedding']) && is_array($response_body['data'][0]['embedding'])) {
2581 + return $response_body['data'][0]['embedding'];
2582 + } else {
2583 + error_log('Invalid embedding response: ' . wp_json_encode($response_body));
2584 + return null;
2585 + }
2586 +}
2467 2587
2468 2588
2469 2589 private function mxchat_find_relevant_content($user_embedding) {
2470 - //error_log('MXChat Vector Search: Starting content search...');
2590 + error_log('MXChat Vector Search: Starting content search...');
2471 2591
2472 2592 // Retrieve the add-on settings from the database.
2473 2593 $addon_options = get_option('mxchat_pinecone_addon_options', array());
2474 2594
@@ -2475,19 +2595,20 @@
2475 2595 // Determine whether Pinecone is enabled.
2476 2596 // We expect the sanitized setting to be a string '1' if enabled, otherwise '0'.
2477 2597 $use_pinecone = (isset($addon_options['mxchat_use_pinecone']) && $addon_options['mxchat_use_pinecone'] === '1') ? 1 : 0;
2478 2598
2479 - //error_log('Pinecone enabled flag: ' . $use_pinecone);
2599 + error_log('Pinecone enabled flag: ' . $use_pinecone);
2480 2600
2481 2601 if ($use_pinecone === 1) {
2482 - //error_log('MXChat Vector Search: Using Pinecone database');
2602 + error_log('MXChat Vector Search: Using Pinecone database');
2483 2603 return $this->find_relevant_content_pinecone($user_embedding);
2484 2604 } else {
2485 - //error_log('MXChat Vector Search: Using WordPress database');
2605 + error_log('MXChat Vector Search: Using WordPress database');
2486 2606 return $this->find_relevant_content_wordpress($user_embedding);
2487 2607 }
2488 2608 }
2489 2609
2610 +
2490 2611 private function find_relevant_content_wordpress($user_embedding) {
2491 2612 global $wpdb;
2492 2613 $system_prompt_table = $wpdb->prefix . 'mxchat_system_prompt_content';
2493 2614 $cache_key = 'mxchat_system_prompt_embeddings';
@@ -2492,11 +2613,15 @@
2492 2613 $system_prompt_table = $wpdb->prefix . 'mxchat_system_prompt_content';
2493 2614 $cache_key = 'mxchat_system_prompt_embeddings';
2494 2615 $batch_size = 500;
2495 2616
2617 + // Log start of matching process
2618 + error_log('[MXCHAT] Starting similarity matching process');
2619 +
2496 2620 // Retrieve embeddings from cache or database
2497 2621 $embeddings = wp_cache_get($cache_key, 'mxchat_system_prompts');
2498 2622 if ($embeddings === false) {
2623 + error_log('[MXCHAT] Cache miss - loading embeddings from database');
2499 2624 $embeddings = [];
2500 2625 $offset = 0;
2501 2626
2502 2627 // Load in batches and build cache
@@ -2522,15 +2647,28 @@
2522 2647
2523 2648 } while (true);
2524 2649
2525 2650 if (empty($embeddings)) {
2651 + error_log('[MXCHAT] No embeddings found in database');
2526 2652 return ''; // Return an empty string if no embeddings found
2527 2653 }
2528 2654 wp_cache_set($cache_key, $embeddings, 'mxchat_system_prompts', 3600);
2655 + error_log('[MXCHAT] Cached ' . count($embeddings) . ' embeddings');
2656 + } else {
2657 + error_log('[MXCHAT] Using ' . count($embeddings) . ' cached embeddings');
2529 2658 }
2530 2659
2531 2660 // Initialize array to store relevant results with similarity scores
2532 2661 $relevant_results = [];
2662 +
2663 + // Get the similarity threshold from the main options array only
2664 + $main_options = get_option('mxchat_options', []);
2665 + $similarity_threshold = isset($main_options['similarity_threshold'])
2666 + ? ((int) $main_options['similarity_threshold']) / 100
2667 + : 0.8; // Default to 80%
2668 +
2669 + error_log('[MXCHAT] Using similarity threshold: ' . ($similarity_threshold * 100) . '%');
2670 +
2533 2671 // Iterate through embeddings to calculate similarity
2534 2672 foreach ($embeddings as $embedding) {
2535 2673 $database_embedding = $embedding->embedding_vector
2536 2674 ? unserialize($embedding->embedding_vector, ['allowed_classes' => false])
@@ -2536,8 +2674,14 @@
2536 2674 ? unserialize($embedding->embedding_vector, ['allowed_classes' => false])
2537 2675 : null;
2538 2676 if (is_array($database_embedding) && is_array($user_embedding)) {
2539 2677 $similarity = $this->mxchat_calculate_cosine_similarity($user_embedding, $database_embedding);
2678 +
2679 + // Log each similarity score over 0.5 to reduce log spam
2680 + if ($similarity > 0.1) {
2681 + error_log(sprintf('[MXCHAT] ID: %d | Similarity Score: %.4f', $embedding->id, $similarity));
2682 + }
2683 +
2540 2684 $relevant_results[] = [
2541 2685 'id' => $embedding->id,
2542 2686 'similarity' => $similarity
2543 2687 ];
@@ -2545,11 +2689,8 @@
2545 2689 // Free memory
2546 2690 unset($database_embedding);
2547 2691 }
2548 2692
2549 - // Retrieve the similarity threshold
2550 - $similarity_threshold = ((int) get_option('mxchat_similarity_threshold', 80)) / 100;
2551 -
2552 2693 // Filter and sort relevant results by similarity
2553 2694 $relevant_results = array_filter($relevant_results, function ($result) use ($similarity_threshold) {
2554 2695 return $result['similarity'] >= $similarity_threshold;
2555 2696 });
@@ -2556,11 +2697,20 @@
2556 2697 usort($relevant_results, function ($a, $b) {
2557 2698 return $b['similarity'] <=> $a['similarity'];
2558 2699 });
2559 2700
2701 + // Log number of results that met threshold
2702 + error_log('[MXCHAT] ' . count($relevant_results) . ' results met the similarity threshold');
2703 +
2560 2704 // Limit to the top 5 results
2561 2705 $top_results = array_slice($relevant_results, 0, 5);
2562 2706
2707 + // Log the top matches
2708 + error_log('[MXCHAT] Top matching results:');
2709 + foreach ($top_results as $index => $result) {
2710 +
2711 + }
2712 +
2563 2713 // Initialize the final content
2564 2714 $content = '';
2565 2715
2566 2716 // Fetch and combine content for the top results
@@ -2567,10 +2717,11 @@
2567 2717 foreach ($top_results as $result) {
2568 2718 $chunk_content = $this->fetch_content_with_product_links($result['id']);
2569 2719 // Check if the content is PDF-related and add surrounding pages
2570 2720 if (strpos($chunk_content, '{"document_type":"pdf"') !== false) {
2721 + error_log('[MXCHAT] ID ' . $result['id'] . ' is PDF content, adding surrounding pages');
2571 2722 $surrounding_content = $wpdb->get_results($wpdb->prepare(
2572 - "SELECT article_content FROM {$system_prompt_table}
2723 + "SELECT id, article_content FROM {$system_prompt_table}
2573 2724 WHERE id IN (
2574 2725 (SELECT id FROM {$system_prompt_table} WHERE id < %d ORDER BY id DESC LIMIT 1),
2575 2726 (SELECT id FROM {$system_prompt_table} WHERE id > %d ORDER BY id ASC LIMIT 1)
2576 2727 )",
@@ -2592,29 +2743,38 @@
2592 2743 $content .= $chunk_content . "\n\n";
2593 2744 }
2594 2745 }
2595 2746
2747 + // Log content length
2748 + error_log('[MXCHAT] Retrieved content length: ' . strlen(trim($content)) . ' characters');
2749 +
2596 2750 return trim($content);
2597 2751 }
2598 -/**
2599 - * Find relevant content in Pinecone vector database
2600 - */
2752 +
2753 +
2601 2754 private function find_relevant_content_pinecone($user_embedding) {
2602 2755 $options = get_option('mxchat_pinecone_addon_options', array());
2603 2756 $api_key = $options['mxchat_pinecone_api_key'] ?? '';
2604 2757 $host = $options['mxchat_pinecone_host'] ?? '';
2605 -
2758 +
2606 2759 if (empty($host) || empty($api_key)) {
2607 - //error_log('Pinecone credentials not properly configured');
2760 + error_log('[MXCHAT Debug] Pinecone credentials not properly configured');
2608 2761 return '';
2609 2762 }
2610 -
2611 - // Get similarity threshold from WordPress settings
2612 - $similarity_threshold = ((int) get_option('mxchat_similarity_threshold', 80)) / 100;
2613 -
2763 +
2764 + // Get the similarity threshold from the main options array only
2765 + $main_options = get_option('mxchat_options', []);
2766 + $similarity_threshold = isset($main_options['similarity_threshold'])
2767 + ? ((int) $main_options['similarity_threshold']) / 100
2768 + : 0.8; // Default to 80%
2769 +
2770 + error_log('[MXCHAT Debug] Using similarity threshold: ' . ($similarity_threshold * 100) . '%');
2771 +
2614 2772 // Prepare the query request for Pinecone
2615 2773 $api_endpoint = "https://{$host}/query";
2616 -
2774 +
2775 + error_log('[MXCHAT Debug] Querying Pinecone at: ' . $api_endpoint);
2776 +
2617 2777 $request_body = array(
2618 2778 'vector' => $user_embedding,
2619 2779 'topK' => 5,
2620 2780 'includeMetadata' => true,
@@ -2619,9 +2779,9 @@
2619 2779 'topK' => 5,
2620 2780 'includeMetadata' => true,
2621 2781 'includeValues' => true
2622 2782 );
2623 -
2783 +
2624 2784 $response = wp_remote_post($api_endpoint, array(
2625 2785 'headers' => array(
2626 2786 'Api-Key' => $api_key,
2627 2787 'accept' => 'application/json',
@@ -2629,35 +2789,43 @@
2629 2789 ),
2630 2790 'body' => wp_json_encode($request_body),
2631 2791 'timeout' => 30
2632 2792 ));
2633 -
2793 +
2634 2794 if (is_wp_error($response)) {
2635 - //error_log('Pinecone query error: ' . $response->get_error_message());
2795 + error_log('[MXCHAT Debug] Pinecone query error: ' . $response->get_error_message());
2636 2796 return '';
2637 2797 }
2638 -
2798 +
2639 2799 $response_code = wp_remote_retrieve_response_code($response);
2640 2800 if ($response_code !== 200) {
2641 - //error_log('Pinecone API error: ' . wp_remote_retrieve_body($response));
2801 + error_log('[MXCHAT Debug] Pinecone API error: ' . wp_remote_retrieve_body($response));
2642 2802 return '';
2643 2803 }
2644 -
2804 +
2645 2805 $results = json_decode(wp_remote_retrieve_body($response), true);
2646 2806 if (empty($results['matches'])) {
2807 + error_log('[MXCHAT Debug] No matches found in Pinecone response');
2647 2808 return '';
2648 2809 }
2649 -
2810 +
2811 + error_log('[MXCHAT Debug] Found ' . count($results['matches']) . ' matches in Pinecone');
2812 +
2650 2813 // Initialize the final content
2651 2814 $content = '';
2815 + $matches_above_threshold = 0;
2816 +
2817 + // Process each match
2818 + foreach ($results['matches'] as $index => $match) {
2819 + // Log score for each match
2652 2820
2653 - // Process each match
2654 - foreach ($results['matches'] as $match) {
2655 2821 // Skip if similarity is below threshold
2656 2822 if ($match['score'] < $similarity_threshold) {
2657 2823 continue;
2658 2824 }
2659 -
2825 +
2826 + $matches_above_threshold++;
2827 +
2660 2828 if (!empty($match['metadata']['text']) && !empty($match['metadata']['source_url'])) {
2661 2829 // Add content with citation
2662 2830 $content .= $match['metadata']['text'] . "\n";
2663 2831 $content .= "Source: " . $match['metadata']['source_url'] . "\n\n";
@@ -2662,15 +2830,17 @@
2662 2830 $content .= $match['metadata']['text'] . "\n";
2663 2831 $content .= "Source: " . $match['metadata']['source_url'] . "\n\n";
2664 2832 }
2665 2833 }
2666 -
2834 +
2835 + error_log('[MXCHAT Debug] Total matches used (above threshold): ' . $matches_above_threshold);
2836 + error_log('[MXCHAT Debug] Content length returned: ' . strlen(trim($content)) . ' characters');
2837 +
2667 2838 return trim($content);
2668 2839 }
2669 2840
2670 -
2671 2841 private function mxchat_find_relevant_products($user_embedding) {
2672 - //error_log('MXChat Vector Search: Starting product search...');
2842 + error_log('MXChat Vector Search: Starting product search...');
2673 2843
2674 2844 // Retrieve the add-on settings from the database
2675 2845 $addon_options = get_option('mxchat_pinecone_addon_options', array());
2676 2846
@@ -2676,15 +2846,15 @@
2676 2846
2677 2847 // Determine whether Pinecone is enabled
2678 2848 $use_pinecone = (isset($addon_options['mxchat_use_pinecone']) && $addon_options['mxchat_use_pinecone'] === '1') ? 1 : 0;
2679 2849
2680 - //error_log('Pinecone enabled flag: ' . $use_pinecone);
2850 + error_log('Pinecone enabled flag: ' . $use_pinecone);
2681 2851
2682 2852 if ($use_pinecone === 1) {
2683 - //error_log('MXChat Vector Search: Using Pinecone database for products');
2853 + error_log('MXChat Vector Search: Using Pinecone database for products');
2684 2854 return $this->find_relevant_products_pinecone($user_embedding);
2685 2855 } else {
2686 - //error_log('MXChat Vector Search: Using WordPress database for products');
2856 + error_log('MXChat Vector Search: Using WordPress database for products');
2687 2857 return $this->find_relevant_products_wordpress($user_embedding);
2688 2858 }
2689 2859 }
2690 2860
@@ -2765,9 +2935,9 @@
2765 2935 }
2766 2936
2767 2937 // Modified search function with correct filter syntax
2768 2938 private function find_relevant_products_pinecone($user_embedding) {
2769 - //error_log('Starting Pinecone product search...');
2939 + error_log('Starting Pinecone product search...');
2770 2940
2771 2941 $options = get_option('mxchat_pinecone_addon_options', array());
2772 2942 $api_key = $options['mxchat_pinecone_api_key'] ?? '';
2773 2943 $host = $options['mxchat_pinecone_host'] ?? '';
@@ -2772,9 +2942,9 @@
2772 2942 $api_key = $options['mxchat_pinecone_api_key'] ?? '';
2773 2943 $host = $options['mxchat_pinecone_host'] ?? '';
2774 2944
2775 2945 if (empty($host) || empty($api_key)) {
2776 - //error_log('Pinecone credentials not properly configured for product search');
2946 + error_log('Pinecone credentials not properly configured for product search');
2777 2947 return '';
2778 2948 }
2779 2949
2780 2950 $similarity_threshold = 0.85;
@@ -2789,9 +2959,9 @@
2789 2959 'type' => 'product'
2790 2960 )
2791 2961 );
2792 2962
2793 - //error_log('Sending request to Pinecone with body: ' . wp_json_encode($request_body));
2963 + error_log('Sending request to Pinecone with body: ' . wp_json_encode($request_body));
2794 2964
2795 2965 $response = wp_remote_post($api_endpoint, array(
2796 2966 'headers' => array(
2797 2967 'Api-Key' => $api_key,
@@ -2802,25 +2972,25 @@
2802 2972 'timeout' => 30
2803 2973 ));
2804 2974
2805 2975 if (is_wp_error($response)) {
2806 - //error_log('Pinecone product query error: ' . $response->get_error_message());
2976 + error_log('Pinecone product query error: ' . $response->get_error_message());
2807 2977 return '';
2808 2978 }
2809 2979
2810 2980 $response_code = wp_remote_retrieve_response_code($response);
2811 - //error_log('Pinecone response code: ' . $response_code);
2981 + error_log('Pinecone response code: ' . $response_code);
2812 2982
2813 2983 if ($response_code !== 200) {
2814 - //error_log('Pinecone API error during product search: ' . wp_remote_retrieve_body($response));
2984 + error_log('Pinecone API error during product search: ' . wp_remote_retrieve_body($response));
2815 2985 return '';
2816 2986 }
2817 2987
2818 2988 $results = json_decode(wp_remote_retrieve_body($response), true);
2819 - //error_log('Pinecone raw response: ' . wp_remote_retrieve_body($response));
2989 + error_log('Pinecone raw response: ' . wp_remote_retrieve_body($response));
2820 2990
2821 2991 if (empty($results['matches'])) {
2822 - //error_log('No matches found in Pinecone response');
2992 + error_log('No matches found in Pinecone response');
2823 2993 return '';
2824 2994 }
2825 2995
2826 2996 $content = '';
@@ -2825,9 +2995,9 @@
2825 2995
2826 2996 $content = '';
2827 2997 foreach ($results['matches'] as $match) {
2828 2998 if ($match['score'] < $similarity_threshold) {
2829 - //error_log("Match below threshold: " . $match['score']);
2999 + error_log("Match below threshold: " . $match['score']);
2830 3000 continue;
2831 3001 }
2832 3002
2833 3003 if (!empty($match['metadata']['text'])) {
@@ -2863,28 +3033,35 @@
2863 3033 return null;
2864 3034 }
2865 3035
2866 3036 // Function definition
2867 -private function mxchat_generate_response($relevant_content, $api_key, $xai_api_key, $claude_api_key, $deepseek_api_key, $conversation_history) {
3037 +// Function definition
3038 +private function mxchat_generate_response($relevant_content, $api_key, $xai_api_key, $claude_api_key, $deepseek_api_key, $gemini_api_key, $conversation_history) {
2868 3039 try {
2869 3040 if (!$relevant_content) {
2870 3041 return esc_html__("I'm sorry, I couldn't find relevant information on that topic.", 'mxchat');
2871 3042 }
2872 -
2873 3043 // Ensure conversation_history is an array
2874 3044 if (!is_array($conversation_history)) {
2875 3045 $conversation_history = array();
2876 3046 }
2877 -
2878 3047 // Get selected model with default fallback
2879 3048 $selected_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-4o';
2880 -
2881 3049 // Extract model prefix to determine the provider
2882 3050 $model_parts = explode('-', $selected_model);
2883 3051 $provider = strtolower($model_parts[0]);
2884 -
2885 3052 // Handle model selection based on provider prefix
2886 3053 switch ($provider) {
3054 + case 'gemini':
3055 + if (empty($gemini_api_key)) {
3056 + throw new Exception(esc_html__('Google Gemini API key is not configured', 'mxchat'));
3057 + }
3058 + return $this->mxchat_generate_response_gemini(
3059 + $selected_model,
3060 + $gemini_api_key,
3061 + $conversation_history,
3062 + $relevant_content
3063 + );
2887 3064 case 'claude':
2888 3065 if (empty($claude_api_key)) {
2889 3066 throw new Exception(esc_html__('Claude API key is not configured', 'mxchat'));
2890 3067 }
@@ -2893,9 +3070,8 @@
2893 3070 $claude_api_key,
2894 3071 $conversation_history,
2895 3072 $relevant_content
2896 3073 );
2897 -
2898 3074 case 'grok':
2899 3075 if (empty($xai_api_key)) {
2900 3076 throw new Exception(esc_html__('X.AI API key is not configured', 'mxchat'));
2901 3077 }
@@ -2904,9 +3080,8 @@
2904 3080 $xai_api_key,
2905 3081 $conversation_history,
2906 3082 $relevant_content
2907 3083 );
2908 -
2909 3084 case 'deepseek':
2910 3085 if (empty($deepseek_api_key)) {
2911 3086 throw new Exception(esc_html__('DeepSeek API key is not configured', 'mxchat'));
2912 3087 }
@@ -2915,9 +3090,8 @@
2915 3090 $deepseek_api_key,
2916 3091 $conversation_history,
2917 3092 $relevant_content
2918 3093 );
2919 -
2920 3094 case 'gpt':
2921 3095 if (empty($api_key)) {
2922 3096 throw new Exception(esc_html__('OpenAI API key is not configured', 'mxchat'));
2923 3097 }
@@ -2926,9 +3100,8 @@
2926 3100 $api_key,
2927 3101 $conversation_history,
2928 3102 $relevant_content
2929 3103 );
2930 -
2931 3104 default:
2932 3105 // Default to OpenAI for custom models or unrecognized prefixes
2933 3106 if (empty($api_key)) {
2934 3107 throw new Exception(esc_html__('OpenAI API key is not configured', 'mxchat'));
@@ -2940,9 +3113,9 @@
2940 3113 $relevant_content
2941 3114 );
2942 3115 }
2943 3116 } catch (Exception $e) {
2944 - //error_log('MXChat Error: ' . $e->getMessage());
3117 + error_log('MXChat Error: ' . $e->getMessage());
2945 3118 return sprintf(
2946 3119 esc_html__('An error occurred: %s', 'mxchat'),
2947 3120 esc_html($e->getMessage())
2948 3121 );
@@ -2948,9 +3121,8 @@
2948 3121 );
2949 3122 }
2950 3123 }
2951 3124
2952 -
2953 3125 private function mxchat_generate_response_deepseek($selected_model, $deepseek_api_key, $conversation_history, $relevant_content) {
2954 3126 // Ensure conversation_history is an array
2955 3127 if (!is_array($conversation_history)) {
2956 3128 $conversation_history = array();
@@ -3010,9 +3182,9 @@
3010 3182
3011 3183 $response = wp_remote_post('https://api.deepseek.com/v1/chat/completions', $args);
3012 3184
3013 3185 if (is_wp_error($response)) {
3014 - //error_log('DeepSeek API Error: ' . $response->get_error_message());
3186 + error_log('DeepSeek API Error: ' . $response->get_error_message());
3015 3187 return "Sorry, there was an error processing your request.";
3016 3188 }
3017 3189
3018 3190 $response_body = wp_remote_retrieve_body($response);
@@ -3020,13 +3192,12 @@
3020 3192
3021 3193 if (isset($decoded_response['choices'][0]['message']['content'])) {
3022 3194 return trim($decoded_response['choices'][0]['message']['content']);
3023 3195 } else {
3024 - //error_log('DeepSeek API Response Format Error: ' . print_r($decoded_response, true));
3196 + error_log('DeepSeek API Response Format Error: ' . print_r($decoded_response, true));
3025 3197 return "Sorry, I couldn't process that request.";
3026 3198 }
3027 3199 }
3028 -
3029 3200 private function mxchat_generate_response_openai($selected_model, $api_key, $conversation_history, $relevant_content) {
3030 3201 // Ensure conversation_history is an array
3031 3202 if (!is_array($conversation_history)) {
3032 3203 $conversation_history = array();
@@ -3086,9 +3257,9 @@
3086 3257
3087 3258 $response = wp_remote_post('https://api.openai.com/v1/chat/completions', $args);
3088 3259
3089 3260 if (is_wp_error($response)) {
3090 - //error_log('OpenAI API Error: ' . $response->get_error_message());
3261 + error_log('OpenAI API Error: ' . $response->get_error_message());
3091 3262 return "Sorry, there was an error processing your request.";
3092 3263 }
3093 3264
3094 3265 $response_body = wp_remote_retrieve_body($response);
@@ -3096,9 +3267,9 @@
3096 3267
3097 3268 if (isset($decoded_response['choices'][0]['message']['content'])) {
3098 3269 return trim($decoded_response['choices'][0]['message']['content']);
3099 3270 } else {
3100 - //error_log('OpenAI API Response Format Error: ' . print_r($decoded_response, true));
3271 + error_log('OpenAI API Response Format Error: ' . print_r($decoded_response, true));
3101 3272 return "Sorry, I couldn't process that request.";
3102 3273 }
3103 3274 }
3104 3275 private function mxchat_generate_response_xai($selected_model, $xai_api_key, $conversation_history, $relevant_content) {
@@ -3170,9 +3341,8 @@
3170 3341 } else {
3171 3342 return "Sorry, I couldn't process that request.";
3172 3343 }
3173 3344 }
3174 -
3175 3345 private function mxchat_generate_response_claude($selected_model, $claude_api_key, $conversation_history, $relevant_content) {
3176 3346 // Get system prompt instructions from options
3177 3347 $system_prompt_instructions = isset($this->options['system_prompt_instructions']) ? $this->options['system_prompt_instructions'] : '';
3178 3348
@@ -3231,9 +3401,9 @@
3231 3401 $response = wp_remote_post('https://api.anthropic.com/v1/messages', $args);
3232 3402
3233 3403 // Check for WordPress errors
3234 3404 if (is_wp_error($response)) {
3235 - //error_log("Claude API request error: " . $response->get_error_message());
3405 + error_log("Claude API request error: " . $response->get_error_message());
3236 3406 return "Sorry, there was an error connecting to the API.";
3237 3407 }
3238 3408
3239 3409 // Check HTTP response code
@@ -3239,9 +3409,9 @@
3239 3409 // Check HTTP response code
3240 3410 $http_code = wp_remote_retrieve_response_code($response);
3241 3411 if ($http_code !== 200) {
3242 3412 $error_body = wp_remote_retrieve_body($response);
3243 - //error_log("Claude API HTTP error: " . $http_code . " - " . $error_body);
3413 + error_log("Claude API HTTP error: " . $http_code . " - " . $error_body);
3244 3414
3245 3415 // Try to extract error message from response
3246 3416 $error_data = json_decode($error_body, true);
3247 3417 $error_message = isset($error_data['error']['message']) ?
@@ -3255,9 +3425,9 @@
3255 3425 $response_body = json_decode(wp_remote_retrieve_body($response), true);
3256 3426
3257 3427 // Check for JSON decode errors
3258 3428 if (json_last_error() !== JSON_ERROR_NONE) {
3259 - //error_log("Claude API JSON decode error: " . json_last_error_msg());
3429 + error_log("Claude API JSON decode error: " . json_last_error_msg());
3260 3430 return "Sorry, there was an error processing the API response.";
3261 3431 }
3262 3432
3263 3433 // Extract and validate response content
@@ -3268,11 +3438,155 @@
3268 3438 return trim($response_body['content'][0]['text']);
3269 3439 }
3270 3440
3271 3441 // Log unexpected response format
3272 - //error_log("Claude API unexpected response format: " . print_r($response_body, true));
3442 + error_log("Claude API unexpected response format: " . print_r($response_body, true));
3273 3443 return "Sorry, I received an unexpected response format from the API.";
3274 3444 }
3445 +
3446 +private function mxchat_generate_response_gemini($selected_model, $gemini_api_key, $conversation_history, $relevant_content) {
3447 + // Get system prompt instructions from options
3448 + $system_prompt_instructions = isset($this->options['system_prompt_instructions']) ? $this->options['system_prompt_instructions'] : '';
3449 +
3450 + // Add system prompt to relevant content
3451 + $content_with_instructions = $system_prompt_instructions . " " . $relevant_content;
3452 +
3453 + // Format messages for Gemini API
3454 + $formatted_messages = [];
3455 +
3456 + // Add system message as the first user message with role prefix
3457 + // Note: Gemini doesn't have a dedicated system role, so we use a prefixed user message
3458 + $formatted_messages[] = [
3459 + 'role' => 'user',
3460 + 'parts' => [
3461 + ['text' => "[System Instructions] " . $content_with_instructions]
3462 + ]
3463 + ];
3464 +
3465 + // Add model response to acknowledge system instructions
3466 + $formatted_messages[] = [
3467 + 'role' => 'model',
3468 + 'parts' => [
3469 + ['text' => "I understand and will follow these instructions."]
3470 + ]
3471 + ];
3472 +
3473 + // Process the rest of the conversation history
3474 + $current_role = null;
3475 + $current_parts = [];
3476 +
3477 + foreach ($conversation_history as $message) {
3478 + // Skip the first system message as we already handled it
3479 + if ($message['role'] === 'system') {
3480 + continue;
3481 + }
3482 +
3483 + // Map roles to Gemini format
3484 + $gemini_role = '';
3485 + if ($message['role'] === 'user') {
3486 + $gemini_role = 'user';
3487 + } else if (in_array($message['role'], ['assistant', 'bot', 'agent'])) {
3488 + $gemini_role = 'model';
3489 + } else {
3490 + // Skip unsupported roles
3491 + continue;
3492 + }
3493 +
3494 + // If we have a new role, add the previous message
3495 + if ($current_role !== null && $current_role !== $gemini_role && !empty($current_parts)) {
3496 + $formatted_messages[] = [
3497 + 'role' => $current_role,
3498 + 'parts' => $current_parts
3499 + ];
3500 + $current_parts = [];
3501 + }
3502 +
3503 + // Set current role and add text to parts
3504 + $current_role = $gemini_role;
3505 + $current_parts[] = ['text' => $message['content']];
3506 + }
3507 +
3508 + // Add the last message if there's content
3509 + if ($current_role !== null && !empty($current_parts)) {
3510 + $formatted_messages[] = [
3511 + 'role' => $current_role,
3512 + 'parts' => $current_parts
3513 + ];
3514 + }
3515 +
3516 + // Build the request body
3517 + $body = json_encode([
3518 + 'contents' => $formatted_messages,
3519 + 'generationConfig' => [
3520 + 'temperature' => 0.7,
3521 + 'topP' => 0.95,
3522 + 'topK' => 40,
3523 + 'maxOutputTokens' => 8192,
3524 + ],
3525 + 'safetySettings' => [
3526 + [
3527 + 'category' => 'HARM_CATEGORY_HARASSMENT',
3528 + 'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
3529 + ],
3530 + [
3531 + 'category' => 'HARM_CATEGORY_HATE_SPEECH',
3532 + 'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
3533 + ],
3534 + [
3535 + 'category' => 'HARM_CATEGORY_SEXUALLY_EXPLICIT',
3536 + 'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
3537 + ],
3538 + [
3539 + 'category' => 'HARM_CATEGORY_DANGEROUS_CONTENT',
3540 + 'threshold' => 'BLOCK_MEDIUM_AND_ABOVE'
3541 + ]
3542 + ]
3543 + ]);
3544 +
3545 + // Prepare the API endpoint
3546 + $api_endpoint = 'https://generativelanguage.googleapis.com/v1/models/' . $selected_model . ':generateContent?key=' . $gemini_api_key;
3547 +
3548 + // Set up the API request
3549 + $args = [
3550 + 'body' => $body,
3551 + 'headers' => [
3552 + 'Content-Type' => 'application/json',
3553 + ],
3554 + 'timeout' => 60,
3555 + 'redirection' => 5,
3556 + 'blocking' => true,
3557 + 'httpversion' => '1.0',
3558 + 'sslverify' => true,
3559 + ];
3560 +
3561 + // Make the API request
3562 + $response = wp_remote_post($api_endpoint, $args);
3563 +
3564 + // Process the response
3565 + if (is_wp_error($response)) {
3566 + return "Sorry, there was an error processing your request: " . $response->get_error_message();
3567 + }
3568 +
3569 + $response_body = json_decode(wp_remote_retrieve_body($response), true);
3570 +
3571 + // Handle potential errors in the response
3572 + if (isset($response_body['error'])) {
3573 + error_log('Gemini API Error: ' . json_encode($response_body['error']));
3574 + return "Sorry, there was an error with the Gemini API: " .
3575 + (isset($response_body['error']['message']) ? $response_body['error']['message'] : 'Unknown error');
3576 + }
3577 +
3578 + // Extract the response text
3579 + if (isset($response_body['candidates'][0]['content']['parts'][0]['text'])) {
3580 + return trim($response_body['candidates'][0]['content']['parts'][0]['text']);
3581 + } else {
3582 + error_log('Unexpected Gemini API response format: ' . json_encode($response_body));
3583 + return "Sorry, I couldn't process that request. The response format was unexpected.";
3584 + }
3585 +}
3586 +
3587 +
3588 +
3275 3589 public function mxchat_dismiss_pre_chat_message() {
3276 3590 // Get and sanitize the user identifier
3277 3591 $user_id = $this->mxchat_get_user_identifier();
3278 3592 $user_id = sanitize_key($user_id);
@@ -3293,9 +3607,9 @@
3293 3607 $transient_key = 'mxchat_pre_chat_message_dismissed_' . $user_id;
3294 3608 $dismissed = get_transient($transient_key);
3295 3609
3296 3610 // Log the result to see if it's being set correctly
3297 - //error_log("Check pre-chat message dismissed for $user_id: " . ($dismissed ? 'Yes' : 'No'));
3611 + error_log("Check pre-chat message dismissed for $user_id: " . ($dismissed ? 'Yes' : 'No'));
3298 3612
3299 3613 if ($dismissed) {
3300 3614 wp_send_json_success(['dismissed' => true]);
3301 3615 } else {
@@ -3328,10 +3642,10 @@
3328 3642 }
3329 3643
3330 3644 public function mxchat_enqueue_scripts_styles() {
3331 3645 // Define version numbers for the styles and scripts
3332 - $chat_style_version = '2.0.5'; // Replace with your actual version
3333 - $chat_script_version = '2.0.5'; // Replace with your actual version
3646 + $chat_style_version = '2.1.4'; // Replace with your actual version
3647 + $chat_script_version = '2.1.4'; // Replace with your actual version
3334 3648
3335 3649 // Enqueue the script
3336 3650 wp_enqueue_script(
3337 3651 'mxchat-chat-js',