| @@ -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', |