Plugin Directory

Changeset 3367268


Ignore:
Timestamp:
09/24/2025 02:47:37 PM (5 months ago)
Author:
mxchat
Message:

upgrade to 2.4.4 includes various bug fixes, such as similarity_threshold default setting and streaming fix.

Location:
mxchat-basic
Files:
98 added
9 edited

Legend:

Unmodified
Added
Removed
  • mxchat-basic/trunk/admin/class-ajax-handler.php

    r3364278 r3367268  
    3131    add_action('wp_ajax_migrate_pinecone_settings', array($this, 'ajax_migrate_pinecone_settings'));
    3232   
    33     // License AJAX - FIXED TO MATCH JAVASCRIPT
     33    // License AJAX
    3434    add_action('wp_ajax_mxchat_handle_activate_license', array($this, 'mxchat_handle_activate_license'));
    3535    add_action('wp_ajax_mxchat_check_license_status', array($this, 'mxchat_check_license_status'));
     
    249249    update_option('mxchat_current_knowledge_bot', $bot_id);
    250250   
    251     // Clear caches when switching bots
    252     $pinecone_manager = MxChat_Pinecone_Manager::get_instance();
    253     $pinecone_manager->mxchat_clear_all_bot_caches();
     251    // No cache clearing needed since we removed caching
    254252   
    255253    wp_send_json_success(array(
     
    499497
    500498/**
    501  * Validates and activates chat license via AJAX - FIXED VERSION
     499 * Validates and activates chat license via AJAX
    502500 */
    503501public function mxchat_handle_activate_license() {
     
    607605     */
    608606    public function mxchat_check_license_status() {
    609         // Verify nonce - FIXED: Use the correct nonce string
     607        // Verify nonce
    610608        if (!check_ajax_referer('mxchat_activate_license_nonce', 'security', false)) {
    611609            wp_send_json_error('Security check failed');
  • mxchat-basic/trunk/admin/class-knowledge-manager.php

    r3364278 r3367268  
    9191       
    9292        // Debug logging
    93         error_log('MANUAL BATCH DEBUG: Process type: ' . $process_type);
    94         error_log('MANUAL BATCH DEBUG: URL: ' . $url);
     93        //error_log('MANUAL BATCH DEBUG: Process type: ' . $process_type);
     94        //error_log('MANUAL BATCH DEBUG: URL: ' . $url);
    9595       
    9696        // FIXED: Extract bot_id from stored status instead of POST data
     
    100100            $status_key = sanitize_key('mxchat_pdf_status_' . md5($url));
    101101            $status = get_transient($status_key);
    102             error_log('MANUAL BATCH DEBUG: Status key: ' . $status_key);
    103             error_log('MANUAL BATCH DEBUG: Status data: ' . print_r($status, true));
     102            //error_log('MANUAL BATCH DEBUG: Status key: ' . $status_key);
     103            //error_log('MANUAL BATCH DEBUG: Status data: ' . print_r($status, true));
    104104           
    105105            if ($status && isset($status['bot_id'])) {
    106106                $bot_id = $status['bot_id'];
    107                 error_log('MANUAL BATCH DEBUG: Bot ID from status: ' . $bot_id);
     107                //error_log('MANUAL BATCH DEBUG: Bot ID from status: ' . $bot_id);
    108108            } else {
    109                 error_log('MANUAL BATCH DEBUG: No bot_id in status, using default');
     109                //error_log('MANUAL BATCH DEBUG: No bot_id in status, using default');
    110110            }
    111111        } elseif ($process_type === 'sitemap') {
     
    117117        }
    118118       
    119         error_log('MANUAL BATCH DEBUG: Final bot_id: ' . $bot_id);
     119        //error_log('MANUAL BATCH DEBUG: Final bot_id: ' . $bot_id);
    120120       
    121121        $processed = 0;
     
    123123        if ($process_type === 'pdf') {
    124124            $processed = $this->mxchat_manual_process_pdf_batch($url);
    125             error_log('MANUAL BATCH DEBUG: PDF processing returned: ' . $processed);
     125            //error_log('MANUAL BATCH DEBUG: PDF processing returned: ' . $processed);
    126126        } elseif ($process_type === 'sitemap') {
    127127            $processed = $this->mxchat_manual_process_sitemap_batch($url);
     
    149149       
    150150    } catch (Exception $e) {
    151         error_log('MANUAL BATCH DEBUG: Exception: ' . $e->getMessage());
     151        //error_log('MANUAL BATCH DEBUG: Exception: ' . $e->getMessage());
    152152        wp_send_json_error('Processing failed: ' . $e->getMessage());
    153153    }
     
    156156private function mxchat_manual_process_pdf_batch($pdf_url) {
    157157    try {
    158         error_log('MANUAL PDF DEBUG: Starting batch processing for: ' . $pdf_url);
     158        //error_log('MANUAL PDF DEBUG: Starting batch processing for: ' . $pdf_url);
    159159       
    160160        $status_key = sanitize_key('mxchat_pdf_status_' . md5($pdf_url));
    161161        $status = get_transient($status_key);
    162162       
    163         error_log('MANUAL PDF DEBUG: Status key: ' . $status_key);
    164         error_log('MANUAL PDF DEBUG: Status data: ' . print_r($status, true));
     163        //error_log('MANUAL PDF DEBUG: Status key: ' . $status_key);
     164        //error_log('MANUAL PDF DEBUG: Status data: ' . print_r($status, true));
    165165       
    166166        if (!$status || $status['status'] !== 'processing') {
    167             error_log('MANUAL PDF DEBUG: No processing status found or status is not processing');
    168             error_log('MANUAL PDF DEBUG: Status: ' . ($status ? $status['status'] : 'NULL'));
     167            //error_log('MANUAL PDF DEBUG: No processing status found or status is not processing');
     168            //error_log('MANUAL PDF DEBUG: Status: ' . ($status ? $status['status'] : 'NULL'));
    169169            return 0;
    170170        }
     
    172172        // FIXED: Extract bot_id from status
    173173        $bot_id = $status['bot_id'] ?? 'default';
    174         error_log('MANUAL PDF DEBUG: Bot ID from status: ' . $bot_id);
     174        //error_log('MANUAL PDF DEBUG: Bot ID from status: ' . $bot_id);
    175175       
    176176        // Get current progress
     
    178178        $total_pages = $status['total_pages'] ?? 0;
    179179       
    180         error_log('MANUAL PDF DEBUG: Current page: ' . $current_page . ', Total pages: ' . $total_pages);
     180        //error_log('MANUAL PDF DEBUG: Current page: ' . $current_page . ', Total pages: ' . $total_pages);
    181181       
    182182        if ($current_page >= $total_pages) {
    183             error_log('MANUAL PDF DEBUG: Already completed');
     183            //error_log('MANUAL PDF DEBUG: Already completed');
    184184            return 0;
    185185        }
    186186       
    187187        // Try to download the PDF again for processing
    188         error_log('MANUAL PDF DEBUG: Attempting to download PDF');
     188        //error_log('MANUAL PDF DEBUG: Attempting to download PDF');
    189189        $response = wp_remote_get($pdf_url, array('timeout' => 30));
    190190       
    191191        if (is_wp_error($response)) {
    192             error_log('MANUAL PDF DEBUG: Failed to download PDF: ' . $response->get_error_message());
     192            //error_log('MANUAL PDF DEBUG: Failed to download PDF: ' . $response->get_error_message());
    193193            return 0;
    194194        }
     
    196196        $pdf_content = wp_remote_retrieve_body($response);
    197197        if (empty($pdf_content)) {
    198             error_log('MANUAL PDF DEBUG: Empty PDF content');
     198            //error_log('MANUAL PDF DEBUG: Empty PDF content');
    199199            return 0;
    200200        }
    201201       
    202         error_log('MANUAL PDF DEBUG: PDF content size: ' . strlen($pdf_content) . ' bytes');
     202        //error_log('MANUAL PDF DEBUG: PDF content size: ' . strlen($pdf_content) . ' bytes');
    203203       
    204204        // Save PDF temporarily
     
    207207        file_put_contents($temp_pdf_path, $pdf_content);
    208208       
    209         error_log('MANUAL PDF DEBUG: Temp PDF saved to: ' . $temp_pdf_path);
     209        //error_log('MANUAL PDF DEBUG: Temp PDF saved to: ' . $temp_pdf_path);
    210210       
    211211        // Process 5 pages directly with bot_id
    212212        $processed = $this->mxchat_process_pdf_pages_direct($temp_pdf_path, $pdf_url, $current_page, 5, $bot_id);
    213213       
    214         error_log('MANUAL PDF DEBUG: Direct processing returned: ' . $processed);
     214        //error_log('MANUAL PDF DEBUG: Direct processing returned: ' . $processed);
    215215       
    216216        // Clean up temp file
    217217        if (file_exists($temp_pdf_path)) {
    218218            wp_delete_file($temp_pdf_path);
    219             error_log('MANUAL PDF DEBUG: Cleaned up temp file');
     219            //error_log('MANUAL PDF DEBUG: Cleaned up temp file');
    220220        }
    221221       
     
    223223       
    224224    } catch (Exception $e) {
    225         error_log('MANUAL PDF DEBUG: Exception in manual batch: ' . $e->getMessage());
     225        //error_log('MANUAL PDF DEBUG: Exception in manual batch: ' . $e->getMessage());
    226226        return 0;
    227227    }
     
    547547public function mxchat_handle_pdf_for_knowledge_base($pdf_url, $response, $bot_id = 'default') {
    548548    if (!current_user_can('manage_options')) {
    549         error_log('[PDF DEBUG] Unauthorized PDF processing attempt');
     549        //error_log('[PDF DEBUG] Unauthorized PDF processing attempt');
    550550        return false;
    551551    }
    552552
    553     error_log('[PDF DEBUG] Starting PDF processing for bot: ' . $bot_id);
    554     error_log('[PDF DEBUG] PDF URL: ' . $pdf_url);
     553    //error_log('[PDF DEBUG] Starting PDF processing for bot: ' . $bot_id);
     554    //error_log('[PDF DEBUG] PDF URL: ' . $pdf_url);
    555555
    556556    $pdf_url = esc_url_raw($pdf_url);
     
    558558
    559559    if (isset($upload_dir['error']) && $upload_dir['error'] !== false) {
    560         error_log('[PDF DEBUG] Upload directory error: ' . $upload_dir['error']);
     560        //error_log('[PDF DEBUG] Upload directory error: ' . $upload_dir['error']);
    561561        return false;
    562562    }
     
    567567    $response_body = wp_remote_retrieve_body($response);
    568568    if (empty($response_body)) {
    569         error_log('[PDF DEBUG] Empty PDF response body');
     569        //error_log('[PDF DEBUG] Empty PDF response body');
    570570        return false;
    571571    }
    572572
    573573    if (!wp_mkdir_p(dirname($pdf_path))) {
    574         error_log('[PDF DEBUG] Failed to create directory for PDF: ' . $pdf_path);
     574        //error_log('[PDF DEBUG] Failed to create directory for PDF: ' . $pdf_path);
    575575        return false;
    576576    }
     
    589589        }
    590590
    591         error_log('[PDF DEBUG] PDF validated successfully with ' . $total_pages . ' pages');
     591        //error_log('[PDF DEBUG] PDF validated successfully with ' . $total_pages . ' pages');
    592592
    593593        // UPDATED: Pass bot_id to PDF processing cron
     
    601601        ));
    602602
    603         error_log('[PDF DEBUG] Cron job scheduled with bot_id: ' . $bot_id);
     603        //error_log('[PDF DEBUG] Cron job scheduled with bot_id: ' . $bot_id);
    604604
    605605        // UPDATED: Store bot_id in status data
     
    615615        set_transient($status_key, $status_data, DAY_IN_SECONDS);
    616616
    617         error_log('[PDF DEBUG] Status stored with bot_id: ' . $bot_id . ' using key: ' . $status_key);
     617        //error_log('[PDF DEBUG] Status stored with bot_id: ' . $bot_id . ' using key: ' . $status_key);
    618618
    619619        return __('scheduled', 'mxchat');
    620620
    621621    } catch (Exception $e) {
    622         error_log('[PDF DEBUG] Error preparing PDF for processing: ' . $e->getMessage());
     622        //error_log('[PDF DEBUG] Error preparing PDF for processing: ' . $e->getMessage());
    623623        if (file_exists($pdf_path)) {
    624624            wp_delete_file($pdf_path);
     
    788788public function mxchat_process_pdf_pages_cron($pdf_path, $pdf_url, $total_pages, $batch_size, $batch_pause, $bot_id = 'default') {
    789789    // ADD THIS DEBUG SECTION AT THE VERY BEGINNING
    790     error_log('[PDF CRON DEBUG] ===== PDF Cron Job Started =====');
    791     error_log('[PDF CRON DEBUG] Initial bot_id parameter: ' . $bot_id);
    792     error_log('[PDF CRON DEBUG] Received parameters:');
    793     error_log('[PDF CRON DEBUG] - pdf_path: ' . $pdf_path);
    794     error_log('[PDF CRON DEBUG] - pdf_url: ' . $pdf_url);
    795     error_log('[PDF CRON DEBUG] - total_pages: ' . $total_pages);
    796     error_log('[PDF CRON DEBUG] - batch_size: ' . $batch_size);
    797     error_log('[PDF CRON DEBUG] - batch_pause: ' . $batch_pause);
    798     error_log('[PDF CRON DEBUG] - Total args received: ' . func_num_args());
    799     error_log('[PDF CRON DEBUG] - All args: ' . print_r(func_get_args(), true));
     790    //error_log('[PDF CRON DEBUG] ===== PDF Cron Job Started =====');
     791    //error_log('[PDF CRON DEBUG] Initial bot_id parameter: ' . $bot_id);
     792    //error_log('[PDF CRON DEBUG] Received parameters:');
     793    //error_log('[PDF CRON DEBUG] - pdf_path: ' . $pdf_path);
     794    //error_log('[PDF CRON DEBUG] - pdf_url: ' . $pdf_url);
     795    //error_log('[PDF CRON DEBUG] - total_pages: ' . $total_pages);
     796    //error_log('[PDF CRON DEBUG] - batch_size: ' . $batch_size);
     797    //error_log('[PDF CRON DEBUG] - batch_pause: ' . $batch_pause);
     798    //error_log('[PDF CRON DEBUG] - Total args received: ' . func_num_args());
     799    //error_log('[PDF CRON DEBUG] - All args: ' . print_r(func_get_args(), true));
    800800   
    801801    // FIXED: Get the correct bot_id from stored status instead of relying on cron parameters
     
    805805    if ($status && isset($status['bot_id'])) {
    806806        $bot_id = $status['bot_id'];
    807         error_log('[PDF CRON DEBUG] Using bot_id from status: ' . $bot_id);
     807        //error_log('[PDF CRON DEBUG] Using bot_id from status: ' . $bot_id);
    808808    } else {
    809         error_log('[PDF CRON DEBUG] No bot_id in status, using default: ' . $bot_id);
     809        //error_log('[PDF CRON DEBUG] No bot_id in status, using default: ' . $bot_id);
    810810    }
    811811   
     
    876876        $options = !empty($bot_options) ? $bot_options : get_option('mxchat_options');
    877877       
    878         error_log('[PDF CRON DEBUG] Using bot options for bot: ' . $bot_id);
     878        //error_log('[PDF CRON DEBUG] Using bot options for bot: ' . $bot_id);
    879879       
    880880        if (empty($options['api_key'])) {
     
    939939                    $page_processed = true;
    940940                    $successful_pages++;
    941                     error_log('[PDF CRON DEBUG] Successfully processed page ' . $page_number . ' for bot: ' . $bot_id);
     941                    //error_log('[PDF CRON DEBUG] Successfully processed page ' . $page_number . ' for bot: ' . $bot_id);
    942942                   
    943943                } catch (Exception $e) {
     
    945945                    $last_error = $e->getMessage();
    946946                   
    947                     error_log("PDF page {$page_number} failed (attempt {$retry_count}/{$max_retries}): " . $last_error);
     947                    //error_log("PDF page {$page_number} failed (attempt {$retry_count}/{$max_retries}): " . $last_error);
    948948                   
    949949                    if ($retry_count < $max_retries) {
     
    967967                }
    968968               
    969                 error_log("PDF page {$page_number} permanently failed after {$max_retries} attempts: " . $last_error);
     969                //error_log("PDF page {$page_number} permanently failed after {$max_retries} attempts: " . $last_error);
    970970            }
    971971
     
    10071007            }
    10081008           
    1009             error_log('[PDF CRON DEBUG] PDF processing completed for bot: ' . $bot_id);
     1009            //error_log('[PDF CRON DEBUG] PDF processing completed for bot: ' . $bot_id);
    10101010        }
    10111011
    10121012    } catch (\Exception $e) {
    1013         error_log(sprintf('[MXCHAT-PDF] Error processing PDF for bot %s: %s', $bot_id, $e->getMessage()));
     1013        //error_log(sprintf('[MXCHAT-PDF] Error processing PDF for bot %s: %s', $bot_id, $e->getMessage()));
    10141014       
    10151015        $status_key = sanitize_key('mxchat_pdf_status_' . md5($pdf_url));
     
    11421142public function mxchat_handle_sitemap_submission() {
    11431143    // START DEBUG
    1144     error_log('[SITEMAP DEBUG] ===== Starting URL submission process =====');
    1145     error_log('[SITEMAP DEBUG] POST data: ' . print_r($_POST, true));
     1144    //error_log('[SITEMAP DEBUG] ===== Starting URL submission process =====');
     1145    //error_log('[SITEMAP DEBUG] POST data: ' . print_r($_POST, true));
    11461146   
    11471147    // Get bot_id from form submission EARLY for debugging
    11481148    $bot_id = isset($_POST['bot_id']) ? sanitize_key($_POST['bot_id']) : 'default';
    1149     error_log('[SITEMAP DEBUG] Extracted bot_id: ' . $bot_id);
    1150     error_log('[SITEMAP DEBUG] Class exists MxChat_Multi_Bot_Manager: ' . (class_exists('MxChat_Multi_Bot_Manager') ? 'YES' : 'NO'));
     1149    //error_log('[SITEMAP DEBUG] Extracted bot_id: ' . $bot_id);
     1150    //error_log('[SITEMAP DEBUG] Class exists MxChat_Multi_Bot_Manager: ' . (class_exists('MxChat_Multi_Bot_Manager') ? 'YES' : 'NO'));
    11511151    // END DEBUG
    11521152
    11531153    // Check if the form was submitted and verify permissions
    11541154    if (!isset($_POST['submit_sitemap']) || !current_user_can('manage_options')) {
    1155         error_log('[SITEMAP DEBUG] Error: Unauthorized access or form not submitted properly');
     1155        //error_log('[SITEMAP DEBUG] Error: Unauthorized access or form not submitted properly');
    11561156        wp_die(esc_html__('Unauthorized access', 'mxchat'));
    11571157    }
    11581158
    11591159    // Verify nonce
    1160     error_log('[SITEMAP DEBUG] Verifying nonce');
     1160    //error_log('[SITEMAP DEBUG] Verifying nonce');
    11611161    check_admin_referer('mxchat_submit_sitemap_action', 'mxchat_submit_sitemap_nonce');
    11621162
    11631163    // Validate URL
    11641164    if (!isset($_POST['sitemap_url']) || empty($_POST['sitemap_url'])) {
    1165         error_log('[SITEMAP DEBUG] Error: Empty or missing URL');
     1165        //error_log('[SITEMAP DEBUG] Error: Empty or missing URL');
    11661166        set_transient('mxchat_admin_notice_error',
    11671167            esc_html__('Please provide a valid URL.', 'mxchat'),
     
    11751175   
    11761176    // Continue processing with already extracted bot_id
    1177     error_log('[SITEMAP DEBUG] Processing URL: ' . $submitted_url . ' for bot: ' . $bot_id);
     1177    //error_log('[SITEMAP DEBUG] Processing URL: ' . $submitted_url . ' for bot: ' . $bot_id);
    11781178
    11791179    // UPDATED: Get bot-specific options and validate API key
    11801180    $bot_options = $this->get_bot_options($bot_id);
    1181     error_log('[SITEMAP DEBUG] Bot options retrieved: ' . print_r($bot_options, true));
     1181    //error_log('[SITEMAP DEBUG] Bot options retrieved: ' . print_r($bot_options, true));
    11821182   
    11831183    $options = !empty($bot_options) ? $bot_options : get_option('mxchat_options');
    11841184    $selected_model = $options['embedding_model'] ?? 'text-embedding-ada-002';
    11851185   
    1186     error_log('[SITEMAP DEBUG] Selected embedding model: ' . $selected_model);
     1186    //error_log('[SITEMAP DEBUG] Selected embedding model: ' . $selected_model);
    11871187   
    11881188    if (strpos($selected_model, 'voyage') === 0) {
     
    11971197    }
    11981198   
    1199     error_log('[SITEMAP DEBUG] Provider: ' . $provider_name . ', Has API key: ' . (!empty($api_key) ? 'YES' : 'NO'));
     1199    //error_log('[SITEMAP DEBUG] Provider: ' . $provider_name . ', Has API key: ' . (!empty($api_key) ? 'YES' : 'NO'));
    12001200   
    12011201    if (empty($api_key)) {
     
    12041204            $provider_name
    12051205        );
    1206         error_log('[SITEMAP DEBUG] Error: ' . $error_message);
     1206        //error_log('[SITEMAP DEBUG] Error: ' . $error_message);
    12071207        set_transient('mxchat_admin_notice_error', $error_message, 30);
    12081208        wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
     
    12101210    }
    12111211
    1212     error_log('[SITEMAP DEBUG] Fetching URL content');
     1212    //error_log('[SITEMAP DEBUG] Fetching URL content');
    12131213    $response = wp_remote_get($submitted_url, array('timeout' => 30));
    12141214
    12151215    if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
    12161216        $error_message = is_wp_error($response) ? $response->get_error_message() : 'HTTP Status: ' . wp_remote_retrieve_response_code($response);
    1217         error_log('[SITEMAP DEBUG] Error fetching URL: ' . $error_message);
     1217        //error_log('[SITEMAP DEBUG] Error fetching URL: ' . $error_message);
    12181218        set_transient('mxchat_admin_notice_error',
    12191219            sprintf(
     
    12281228
    12291229    $content_type = wp_remote_retrieve_header($response, 'content-type');
    1230     error_log('[SITEMAP DEBUG] Content type: ' . $content_type);
     1230    //error_log('[SITEMAP DEBUG] Content type: ' . $content_type);
    12311231    $body_content = wp_remote_retrieve_body($response);
    12321232
    12331233    if (empty($body_content)) {
    1234         error_log('[SITEMAP DEBUG] Error: Empty response body');
     1234        //error_log('[SITEMAP DEBUG] Error: Empty response body');
    12351235        set_transient('mxchat_admin_notice_error',
    12361236            esc_html__('Empty response received from URL.', 'mxchat'),
     
    12401240        exit;
    12411241    }
    1242     error_log('[SITEMAP DEBUG] Retrieved body content length: ' . strlen($body_content) . ' bytes');
     1242    //error_log('[SITEMAP DEBUG] Retrieved body content length: ' . strlen($body_content) . ' bytes');
    12431243
    12441244    // Handle PDF URL
    12451245    if ($this->mxchat_is_pdf_url($submitted_url, $response)) {
    1246         error_log('[SITEMAP DEBUG] Detected PDF URL, handling PDF for knowledge base');
    1247         error_log('[SITEMAP DEBUG] About to call PDF handler with bot_id: ' . $bot_id);
     1246        //error_log('[SITEMAP DEBUG] Detected PDF URL, handling PDF for knowledge base');
     1247        //error_log('[SITEMAP DEBUG] About to call PDF handler with bot_id: ' . $bot_id);
    12481248       
    12491249        // UPDATED: Pass bot_id to PDF handler
    12501250        $result = $this->mxchat_handle_pdf_for_knowledge_base($submitted_url, $response, $bot_id);
    1251         error_log('[SITEMAP DEBUG] PDF handling result: ' . $result);
     1251        //error_log('[SITEMAP DEBUG] PDF handling result: ' . $result);
    12521252
    12531253        if ($result === 'scheduled') {
     
    12631263                DAY_IN_SECONDS
    12641264            );
    1265             error_log('[SITEMAP DEBUG] PDF processing scheduled successfully for bot: ' . $bot_id);
     1265            //error_log('[SITEMAP DEBUG] PDF processing scheduled successfully for bot: ' . $bot_id);
    12661266            set_transient('mxchat_admin_notice_info',
    12671267                esc_html__('PDF processing has started in the background. You can check the progress in the Knowledge Base section.', 'mxchat'),
     
    12691269            );
    12701270        } else {
    1271             error_log('[SITEMAP DEBUG] PDF processing failed: ' . $result);
     1271            //error_log('[SITEMAP DEBUG] PDF processing failed: ' . $result);
    12721272            set_transient('mxchat_admin_notice_error',
    12731273                esc_html__('Failed to start PDF processing: ', 'mxchat') . esc_html($result),
     
    12821282    // Handle Sitemap XML
    12831283    if (strpos($content_type, 'xml') !== false || strpos($body_content, '<urlset') !== false) {
    1284         error_log('[SITEMAP DEBUG] Detected XML content, processing as sitemap');
     1284        //error_log('[SITEMAP DEBUG] Detected XML content, processing as sitemap');
    12851285        libxml_use_internal_errors(true);
    12861286        $xml = simplexml_load_string($body_content);
     
    12891289
    12901290        if ($xml === false || !empty($xml_errors)) {
    1291             error_log('[SITEMAP DEBUG] Error: Invalid XML format');
     1291            //error_log('[SITEMAP DEBUG] Error: Invalid XML format');
    12921292            if (!empty($xml_errors)) {
    12931293                foreach ($xml_errors as $error) {
    1294                     error_log('[SITEMAP DEBUG] XML Error: ' . $error->message);
     1294                    //error_log('[SITEMAP DEBUG] XML Error: ' . $error->message);
    12951295                }
    12961296            }
     
    13041304        }
    13051305
    1306         error_log('[SITEMAP DEBUG] Valid XML found, handling sitemap for knowledge base');
     1306        //error_log('[SITEMAP DEBUG] Valid XML found, handling sitemap for knowledge base');
    13071307        // UPDATED: Pass bot_id to sitemap handler
    13081308        $result = $this->mxchat_handle_sitemap_for_knowledge_base($xml, $submitted_url, $bot_id);
    1309         error_log('[SITEMAP DEBUG] Sitemap handling result: ' . $result);
     1309        //error_log('[SITEMAP DEBUG] Sitemap handling result: ' . $result);
    13101310
    13111311        if ($result === 'scheduled') {
     
    13371337
    13381338    // Handle Regular URL
    1339     error_log('[SITEMAP DEBUG] Processing as regular webpage');
     1339    //error_log('[SITEMAP DEBUG] Processing as regular webpage');
    13401340    $page_content = $this->mxchat_extract_main_content($body_content);
    1341     error_log('[SITEMAP DEBUG] Extracted content length: ' . strlen($page_content) . ' bytes');
     1341    //error_log('[SITEMAP DEBUG] Extracted content length: ' . strlen($page_content) . ' bytes');
    13421342
    13431343    $sanitized_content = $this->mxchat_sanitize_content_for_api($page_content);
    1344     error_log('[SITEMAP DEBUG] Sanitized content length: ' . strlen($sanitized_content) . ' bytes');
     1344    //error_log('[SITEMAP DEBUG] Sanitized content length: ' . strlen($sanitized_content) . ' bytes');
    13451345
    13461346    if (empty($sanitized_content)) {
    1347         error_log('[SITEMAP DEBUG] Error: No valid content after sanitization');
     1347        //error_log('[SITEMAP DEBUG] Error: No valid content after sanitization');
    13481348       
    13491349        set_transient('mxchat_admin_notice_error',
     
    13631363    }
    13641364
    1365     error_log('[SITEMAP DEBUG] Generating embedding for content');
     1365    //error_log('[SITEMAP DEBUG] Generating embedding for content');
    13661366    $embedding_vector = $this->mxchat_generate_embedding($sanitized_content, $bot_id);
    13671367
    13681368    if (is_string($embedding_vector)) {
    1369         error_log('[SITEMAP DEBUG] Error generating embedding: ' . $embedding_vector);
     1369        //error_log('[SITEMAP DEBUG] Error generating embedding: ' . $embedding_vector);
    13701370        $error_message = esc_html__('Failed to generate embedding: ', 'mxchat') . esc_html($embedding_vector);
    13711371       
     
    13841384
    13851385    if (is_array($embedding_vector)) {
    1386         error_log('[SITEMAP DEBUG] Successfully generated embedding with ' . count($embedding_vector) . ' dimensions');
     1386        //error_log('[SITEMAP DEBUG] Successfully generated embedding with ' . count($embedding_vector) . ' dimensions');
    13871387
    13881388        // UPDATED: Pass bot_id to database submission
     
    13961396
    13971397        if (is_wp_error($db_result)) {
    1398             error_log('[SITEMAP DEBUG] Error: Failed to store content in database: ' . $db_result->get_error_message());
     1398            //error_log('[SITEMAP DEBUG] Error: Failed to store content in database: ' . $db_result->get_error_message());
    13991399            $error_message = esc_html__('Failed to store content in database: ', 'mxchat') . esc_html($db_result->get_error_message());
    14001400           
     
    14121412        }
    14131413
    1414         error_log('[SITEMAP DEBUG] Successfully stored content in database');
     1414        //error_log('[SITEMAP DEBUG] Successfully stored content in database');
    14151415        $success_message = esc_html__('URL content successfully submitted!', 'mxchat');
    14161416       
     
    14261426       
    14271427    } else {
    1428         error_log('[SITEMAP DEBUG] Error: Failed to generate embedding. Unexpected result type: ' . gettype($embedding_vector));
     1428        //error_log('[SITEMAP DEBUG] Error: Failed to generate embedding. Unexpected result type: ' . gettype($embedding_vector));
    14291429        $error_message = esc_html__('Failed to generate embedding: Unexpected result type. Please check your API key and try again.', 'mxchat');
    14301430       
     
    14391439    }
    14401440
    1441     error_log('[SITEMAP DEBUG] ===== Completed URL submission process =====');
     1441    //error_log('[SITEMAP DEBUG] ===== Completed URL submission process =====');
    14421442    wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
    14431443    exit;
     
    21962196
    21972197
    2198 
    21992198/**
    2200  * checking if WooCommerce products were already processed in the WordPress database.
     2199 * Get content list for processing
    22012200 */
    22022201public function ajax_mxchat_get_content_list() {
     
    22242223    );
    22252224   
    2226     // Handle post types
     2225    // Handle post types - IMPROVED VERSION
    22272226    if ($post_type !== 'all') {
    22282227        $args['post_type'] = $post_type;
    22292228    } else {
    2230         // Default to post and page if we can't get post types
    2231         $args['post_type'] = array('post', 'page');
    2232        
    2233         // Try to get public post types
    2234         $public_types = $this->mxchat_get_public_post_types();
    2235         if (is_array($public_types) && !empty($public_types)) {
    2236             $args['post_type'] = array_keys($public_types);
    2237         }
     2229        // Get all available post types that might contain content
     2230        $all_post_types = array();
     2231       
     2232        // First get all public post types
     2233        $public_types = get_post_types(array('public' => true), 'names');
     2234        $all_post_types = array_merge($all_post_types, $public_types);
     2235       
     2236        // Add common forum/community post types
     2237        $forum_types = array('topic', 'reply', 'forum', 'wpforo_topic', 'wpforo_post');
     2238        foreach ($forum_types as $forum_type) {
     2239            if (post_type_exists($forum_type)) {
     2240                $all_post_types[] = $forum_type;
     2241            }
     2242        }
     2243       
     2244        // Add other commonly used post types
     2245        $common_types = array('product', 'job_listing', 'event', 'portfolio');
     2246        foreach ($common_types as $common_type) {
     2247            if (post_type_exists($common_type)) {
     2248                $all_post_types[] = $common_type;
     2249            }
     2250        }
     2251       
     2252        // Remove duplicates and ensure we have at least some post types
     2253        $all_post_types = array_unique($all_post_types);
     2254       
     2255        if (empty($all_post_types)) {
     2256            // Fallback to basic post types
     2257            $all_post_types = array('post', 'page');
     2258        }
     2259       
     2260        $args['post_type'] = $all_post_types;
     2261       
     2262        // Debug logging to see what post types are being queried
     2263        //error_log('MxChat Debug: Querying post types: ' . implode(', ', $all_post_types));
    22382264    }
    22392265   
     
    22422268    }
    22432269   
    2244     // ================================
    2245     // WordPress DB checking for WooCommerce products
    2246     // ================================
    2247    
     2270    // Get processed data from storage
    22482271    $processed_data = array();
    22492272   
    2250     $pinecone_manager = MxChat_Pinecone_Manager::get_instance();
    22512273    $pinecone_options = get_option('mxchat_pinecone_addon_options', array());
    2252     $pinecone_manager->mxchat_refresh_after_new_content($pinecone_options);
    22532274    $use_pinecone = ($pinecone_options['mxchat_use_pinecone'] ?? '0') === '1';
    22542275
    22552276    if ($use_pinecone && !empty($pinecone_options['mxchat_pinecone_api_key'])) {
    2256         // ONLY check Pinecone if it's enabled
     2277        // Get fresh data from Pinecone - no caching
    22572278        $processed_data = $this->mxchat_get_pinecone_processed_content($pinecone_options);
    22582279    } else {
    2259         // IMPROVED: WordPress DB checking with better URL matching for WooCommerce
     2280        // WordPress DB checking with better URL matching for all post types
    22602281        global $wpdb;
    22612282        $table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
     
    22642285        if (!empty($processed_items)) {
    22652286            foreach ($processed_items as $item) {
    2266                 // FIXED: Use improved URL matching for WooCommerce products
     2287                // Use improved URL matching that works for all post types
    22672288                $post_id = $this->mxchat_url_to_post_id_improved($item->source_url);
    22682289               
     
    22782299        }
    22792300    }
    2280    
    2281     // ================================
    22822301   
    22832302    // Get processed IDs as a simple array for in_array checks
     
    23542373}
    23552374
     2375
    23562376/**
    23572377 * This function handles various WooCommerce URL formats and permalink structures
     
    23652385    }
    23662386   
    2367     // If that fails, try more aggressive URL matching for WooCommerce products
     2387    // If that fails, try more aggressive URL matching
    23682388    // Remove trailing slashes and query parameters for better matching
    23692389    $clean_url = rtrim($url, '/');
     
    23762396    }
    23772397   
    2378     // For WooCommerce products, try extracting slug from URL
     2398    // For bbPress forum topics, try extracting slug from URL
     2399    if (strpos($url, '/topic/') !== false || strpos($url, '/forums/') !== false) {
     2400        // Handle bbPress URLs: /forums/topic/topic-name/
     2401        if (preg_match('/\/forums\/topic\/([^\/\?]+)/', $url, $matches)) {
     2402            $topic_slug = $matches[1];
     2403           
     2404            // Look up topic by slug
     2405            $topic = get_page_by_path($topic_slug, OBJECT, 'topic');
     2406            if ($topic) {
     2407                return $topic->ID;
     2408            }
     2409           
     2410            // Alternative method: query by post_name
     2411            global $wpdb;
     2412            $post_id = $wpdb->get_var($wpdb->prepare(
     2413                "SELECT ID FROM {$wpdb->posts} WHERE post_name = %s AND post_type = 'topic' AND post_status IN ('publish', 'closed')",
     2414                $topic_slug
     2415            ));
     2416           
     2417            if ($post_id) {
     2418                return intval($post_id);
     2419            }
     2420        }
     2421       
     2422        // Handle simpler topic URLs: /topic/topic-name/
     2423        if (preg_match('/\/topic\/([^\/\?]+)/', $url, $matches)) {
     2424            $topic_slug = $matches[1];
     2425           
     2426            global $wpdb;
     2427            $post_id = $wpdb->get_var($wpdb->prepare(
     2428                "SELECT ID FROM {$wpdb->posts} WHERE post_name = %s AND post_type = 'topic' AND post_status IN ('publish', 'closed')",
     2429                $topic_slug
     2430            ));
     2431           
     2432            if ($post_id) {
     2433                return intval($post_id);
     2434            }
     2435        }
     2436    }
     2437   
     2438    // For WooCommerce products
    23792439    if (strpos($url, '/product/') !== false || strpos($url, 'product=') !== false) {
    23802440        // Extract product slug from various URL formats
     
    24102470    }
    24112471   
    2412     // ADDITIONAL FIX: Try direct database lookup by URL variations
     2472    // Generic approach: try to extract slug and match against all post types
     2473    $parsed_url = wp_parse_url($clean_url);
     2474    $path = $parsed_url['path'] ?? '';
     2475   
     2476    if (!empty($path)) {
     2477        // Get the last part of the path as potential slug
     2478        $path_parts = array_filter(explode('/', trim($path, '/')));
     2479        $potential_slug = end($path_parts);
     2480       
     2481        if (!empty($potential_slug)) {
     2482            global $wpdb;
     2483           
     2484            // Try to find any post with this slug
     2485            $post_id = $wpdb->get_var($wpdb->prepare(
     2486                "SELECT ID FROM {$wpdb->posts}
     2487                 WHERE post_name = %s
     2488                 AND post_status IN ('publish', 'closed', 'private')
     2489                 AND post_type NOT IN ('revision', 'attachment', 'nav_menu_item')
     2490                 ORDER BY CASE
     2491                    WHEN post_type = 'post' THEN 1
     2492                    WHEN post_type = 'page' THEN 2
     2493                    WHEN post_type = 'topic' THEN 3
     2494                    WHEN post_type = 'product' THEN 4
     2495                    ELSE 5
     2496                 END
     2497                 LIMIT 1",
     2498                $potential_slug
     2499            ));
     2500           
     2501            if ($post_id) {
     2502                return intval($post_id);
     2503            }
     2504        }
     2505    }
     2506   
     2507    // ADDITIONAL: Try direct database lookup by URL variations
    24132508    global $wpdb;
    24142509    $table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
    24152510   
    2416     // Try exact match first
    2417     $existing_record = $wpdb->get_row($wpdb->prepare(
    2418         "SELECT id, source_url FROM $table_name WHERE source_url = %s",
    2419         $url
    2420     ));
    2421    
    2422     if ($existing_record) {
    2423         // Found exact match, now convert the URL to post ID
    2424         $post_id = url_to_postid($existing_record->source_url);
    2425         if ($post_id > 0) {
    2426             return $post_id;
    2427         }
    2428     }
    2429    
    24302511    // Try variations of the URL (with/without trailing slash, http/https)
    24312512    $url_variations = array(
     2513        $url,
    24322514        rtrim($url, '/'),
    24332515        $url . '/',
     
    24382520    );
    24392521   
     2522    // Remove duplicates
     2523    $url_variations = array_unique($url_variations);
     2524   
    24402525    foreach ($url_variations as $variation) {
    24412526        $existing_record = $wpdb->get_row($wpdb->prepare(
     
    24452530       
    24462531        if ($existing_record) {
    2447             $post_id = url_to_postid($existing_record->source_url);
    2448             if ($post_id > 0) {
    2449                 return $post_id;
    2450             }
    2451         }
    2452     }
    2453    
    2454     // Last resort: try to match against all published products by URL if WooCommerce is active
    2455     if (function_exists('wc_get_products')) {
    2456         // Get all published products (limited to avoid memory issues)
    2457         $products = wc_get_products(array(
    2458             'status' => 'publish',
    2459             'limit' => 1000, // Reasonable limit
    2460             'return' => 'ids'
    2461         ));
    2462        
    2463         foreach ($products as $product_id) {
    2464             $product_url = get_permalink($product_id);
    2465            
    2466             // Compare cleaned URLs
    2467             $clean_product_url = rtrim($product_url, '/');
    2468             $clean_product_url = strtok($clean_product_url, '?');
    2469            
    2470             if ($clean_url === $clean_product_url) {
    2471                 return $product_id;
    2472             }
    2473            
    2474             // Also check if any of our URL variations match
    2475             foreach ($url_variations as $variation) {
    2476                 $clean_variation = rtrim($variation, '/');
    2477                 $clean_variation = strtok($clean_variation, '?');
    2478                
    2479                 if ($clean_variation === $clean_product_url) {
    2480                     return $product_id;
    2481                 }
     2532            // Try to get post ID from this stored URL
     2533            $stored_post_id = url_to_postid($existing_record->source_url);
     2534            if ($stored_post_id > 0) {
     2535                return $stored_post_id;
    24822536            }
    24832537        }
     
    24862540    return 0; // No match found
    24872541}
    2488 
     2542/**
     2543 * Process selected content via AJAX
     2544 */
    24892545public function ajax_mxchat_process_selected_content() {
    24902546    // Basic request validation
     
    26132669    }
    26142670   
    2615     // Update caches if Pinecone is enabled for this bot
    2616     if ($use_pinecone && !empty($bot_pinecone_config['api_key'])) {
    2617         // Update vector ID cache for improved fetching
    2618         $this->mxchat_update_pinecone_vector_cache($vector_id);
    2619        
    2620         // Update local processed content cache for immediate UI feedback
    2621         $pinecone_cache = get_option('mxchat_pinecone_processed_cache', array());
    2622         $pinecone_cache[$post_id] = array(
    2623             'db_id' => $vector_id,
    2624             'processed_date' => 'Just now',
    2625             'url' => $source_url,
    2626             'source' => 'pinecone',
    2627             'timestamp' => current_time('timestamp')
    2628         );
    2629         update_option('mxchat_pinecone_processed_cache', $pinecone_cache);
    2630        
    2631         // Also update the general processed content cache
    2632         $processed_cache = get_option('mxchat_processed_content_cache', array());
    2633         $processed_cache[$post_id] = array(
    2634             'db_id' => $vector_id,
    2635             'timestamp' => current_time('timestamp'),
    2636             'url' => $source_url,
    2637             'source' => 'pinecone'
    2638         );
    2639         update_option('mxchat_processed_content_cache', $processed_cache);
    2640     }
    2641    
    26422671    $operation_type = $is_update ? 'update' : 'new';
    26432672   
     
    26522681        'operation_type' => $operation_type,
    26532682        'vector_id' => $vector_id,
    2654         'cache_updated' => $use_pinecone,
    26552683        'acf_fields_found' => $acf_field_count,
    26562684        'content_preview' => substr($content, 0, 100) . '...',
     
    26602688}
    26612689
    2662 
    2663 
    2664 
    2665     /**
    2666      * Updates cache with new vector ID if absent
    2667      */
    2668      public function mxchat_update_pinecone_vector_cache($vector_id) {
    2669          $cached_ids = get_option('mxchat_pinecone_vector_ids_cache', array());
    2670          if (!in_array($vector_id, $cached_ids)) {
    2671              $cached_ids[] = $vector_id;
    2672              update_option('mxchat_pinecone_vector_ids_cache', $cached_ids);
    2673          }
    2674      }
    26752690public function mxchat_get_public_post_types() {
     2691    // Get all public post types
    26762692    $post_types = get_post_types(array('public' => true), 'objects');
    26772693    $post_type_options = array();
     
    26812697    }
    26822698   
     2699    // Also include common forum/community post types that might not be marked as public
     2700    $additional_types = array(
     2701        'topic' => 'Forum Topics (bbPress)',
     2702        'reply' => 'Forum Replies (bbPress)',
     2703        'forum' => 'Forums (bbPress)',
     2704        'wpforo_topic' => 'wpForo Topics',
     2705        'wpforo_post' => 'wpForo Posts'
     2706    );
     2707   
     2708    foreach ($additional_types as $type_name => $type_label) {
     2709        if (post_type_exists($type_name) && !isset($post_type_options[$type_name])) {
     2710            $post_type_options[$type_name] = $type_label;
     2711        }
     2712    }
     2713   
    26832714    return $post_type_options;
    26842715}
     2716
     2717/**
     2718 * Retrieves processed content from Pinecone API
     2719 */
    26852720public function mxchat_get_pinecone_processed_content($pinecone_options) {
    2686     //error_log('=== DEBUG: Starting mxchat_get_pinecone_processed_content ===');
    2687    
    2688     // First check local cache for immediate updates
    2689     $cached_data = get_option('mxchat_pinecone_processed_cache', array());
    2690     //error_log('DEBUG: Found ' . count($cached_data) . ' items in local cache');
    2691 
    26922721    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
    26932722    $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
    2694    
    2695     //error_log('DEBUG: API key present: ' . (!empty($api_key) ? 'YES' : 'NO'));
    2696     //error_log('DEBUG: Host: ' . $host);
    26972723
    26982724    if (empty($api_key) || empty($host)) {
    2699         //error_log('DEBUG: Missing API credentials, returning cached data only');
    2700         return $cached_data;
     2725        return array();
    27012726    }
    27022727
     
    27042729
    27052730    try {
    2706         // Method 1: Try to get vectors using cached vector IDs first
    2707         $cached_vector_ids = get_option('mxchat_pinecone_vector_ids_cache', array());
    2708         //error_log('DEBUG: Found ' . count($cached_vector_ids) . ' cached vector IDs');
    2709 
    2710         if (!empty($cached_vector_ids)) {
    2711             //error_log('DEBUG: Trying to fetch by cached vector IDs...');
    2712             $pinecone_data = $this->mxchat_fetch_pinecone_vectors_by_ids($pinecone_options, $cached_vector_ids);
    2713             //error_log('DEBUG: Fetch by IDs returned ' . count($pinecone_data) . ' items');
    2714         }
    2715 
    2716         // Method 2: If no cached IDs or fetch failed, use scanning approach
     2731        // Always get fresh data from Pinecone
     2732        $pinecone_data = $this->mxchat_scan_pinecone_for_processed_content($pinecone_options);
     2733
     2734        // Method 2: Final fallback - try stats endpoint (if available)
    27172735        if (empty($pinecone_data)) {
    2718             //error_log('DEBUG: Trying scanning approach...');
    2719             $pinecone_data = $this->mxchat_scan_pinecone_for_processed_content($pinecone_options);
    2720             //error_log('DEBUG: Scanning returned ' . count($pinecone_data) . ' items');
    2721         }
    2722 
    2723         // Method 3: Final fallback - try stats endpoint
    2724         if (empty($pinecone_data)) {
    2725             //error_log('DEBUG: Trying stats endpoint...');
    27262736            $stats_url = "https://{$host}/describe_index_stats";
    27272737
     
    27382748                $body = wp_remote_retrieve_body($response);
    27392749                $stats_data = json_decode($body, true);
    2740                 //error_log('DEBUG: Pinecone stats: ' . print_r($stats_data, true));
    2741             } else {
    2742                 if (is_wp_error($response)) {
    2743                     //error_log('DEBUG: Stats endpoint error: ' . $response->get_error_message());
    2744                 } else {
    2745                     //error_log('DEBUG: Stats endpoint failed with code: ' . wp_remote_retrieve_response_code($response));
    2746                 }
    27472750            }
    27482751        }
    27492752
    27502753    } catch (Exception $e) {
    2751         //error_log('DEBUG: Exception in get_pinecone_processed_content: ' . $e->getMessage());
    2752     }
    2753 
    2754     // Merge cached data with Pinecone data
    2755     $merged_data = $pinecone_data;
    2756 
    2757     foreach ($cached_data as $post_id => $cache_item) {
    2758         $cache_timestamp = $cache_item['timestamp'] ?? 0;
    2759         $time_diff = current_time('timestamp') - $cache_timestamp;
    2760 
    2761         if ($time_diff < 300) { // 5 minutes = 300 seconds
    2762             $merged_data[$post_id] = $cache_item;
    2763         } else {
    2764             if (!isset($merged_data[$post_id])) {
    2765                 $merged_data[$post_id] = $cache_item;
    2766             }
    2767         }
    2768     }
    2769 
    2770     //error_log('DEBUG: Final merged data count: ' . count($merged_data));
    2771     //error_log('=== DEBUG: End mxchat_get_pinecone_processed_content ===');
    2772 
    2773     return $merged_data;
    2774 }
    2775 
     2754        // Log error but return fresh data only
     2755    }
     2756
     2757    return $pinecone_data;
     2758}
    27762759public function mxchat_fetch_pinecone_vectors_by_ids($pinecone_options, $vector_ids) {
    27772760    //error_log('=== DEBUG: Starting mxchat_fetch_pinecone_vectors_by_ids ===');
     
    28672850}
    28682851
     2852/**
     2853 * Scan Pinecone for processed content
     2854 */
    28692855public function mxchat_scan_pinecone_for_processed_content($pinecone_options) {
    2870     //error_log('=== DEBUG: Starting mxchat_scan_pinecone_for_processed_content ===');
    2871    
    28722856    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
    28732857    $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
    28742858
    28752859    if (empty($api_key) || empty($host)) {
    2876         //error_log('DEBUG: Missing API credentials for scanning');
    28772860        return array();
    28782861    }
     
    28852868        // Try 3 different random vectors to get better coverage
    28862869        for ($i = 0; $i < 3; $i++) {
    2887             //error_log('DEBUG: Scanning attempt ' . ($i + 1) . '/3');
    2888            
    28892870            $query_url = "https://{$host}/query";
    28902871
     
    29182899
    29192900            if (is_wp_error($response)) {
    2920                 //error_log('DEBUG: Query attempt ' . ($i + 1) . ' WP error: ' . $response->get_error_message());
    29212901                continue;
    29222902            }
    29232903
    29242904            $response_code = wp_remote_retrieve_response_code($response);
    2925             //error_log('DEBUG: Query attempt ' . ($i + 1) . ' response code: ' . $response_code);
    29262905           
    29272906            if ($response_code !== 200) {
    2928                 $error_body = wp_remote_retrieve_body($response);
    2929                 //error_log('DEBUG: Query attempt ' . ($i + 1) . ' failed with body: ' . substr($error_body, 0, 500));
    29302907                continue;
    29312908            }
     
    29352912
    29362913            if (isset($data['matches'])) {
    2937                 //error_log('DEBUG: Query attempt ' . ($i + 1) . ' returned ' . count($data['matches']) . ' matches');
    29382914                foreach ($data['matches'] as $match) {
    29392915                    $match_id = $match['id'] ?? '';
     
    29432919                    }
    29442920                }
    2945             } else {
    2946                 //error_log('DEBUG: Query attempt ' . ($i + 1) . ' - no matches key in response');
    2947             }
    2948         }
    2949 
    2950         //error_log('DEBUG: Total unique matches found: ' . count($all_matches));
     2921            }
     2922        }
    29512923
    29522924        // Convert matches to processed data format
    29532925        $processed_data = array();
    2954         $vector_ids_for_cache = array();
    29552926
    29562927        foreach ($all_matches as $match) {
     
    29792950                        'timestamp' => $timestamp ?? current_time('timestamp')
    29802951                    );
    2981 
    2982                     $vector_ids_for_cache[] = $match_id;
    29832952                }
    29842953            }
    29852954        }
    29862955
    2987         // Update the vector IDs cache for future use
    2988         if (!empty($vector_ids_for_cache)) {
    2989             update_option('mxchat_pinecone_vector_ids_cache', $vector_ids_for_cache);
    2990             //error_log('DEBUG: Updated vector IDs cache with ' . count($vector_ids_for_cache) . ' IDs');
    2991         }
    2992 
    2993         //error_log('DEBUG: Returning ' . count($processed_data) . ' processed items from scanning');
    29942956        return $processed_data;
    29952957
    29962958    } catch (Exception $e) {
    2997         //error_log('DEBUG: Exception in scan_pinecone_for_processed_content: ' . $e->getMessage());
    29982959        return array();
    29992960    }
    30002961}
    3001 
    30022962/**
    30032963 * UPDATED: Generate embeddings from input text for MXChat with bot support
     
    32163176 */
    32173177private function get_bot_options($bot_id = 'default') {
    3218     error_log("MXCHAT DEBUG: get_bot_options called for bot: " . $bot_id);
     3178    //error_log("MXCHAT DEBUG: get_bot_options called for bot: " . $bot_id);
    32193179   
    32203180    if ($bot_id === 'default' || !class_exists('MxChat_Multi_Bot_Manager')) {
    3221         error_log("MXCHAT DEBUG: Using default options (no multi-bot or bot is 'default')");
     3181        //error_log("MXCHAT DEBUG: Using default options (no multi-bot or bot is 'default')");
    32223182        return array();
    32233183    }
     
    32263186   
    32273187    if (!empty($bot_options)) {
    3228         error_log("MXCHAT DEBUG: Got bot-specific options from filter");
     3188        //error_log("MXCHAT DEBUG: Got bot-specific options from filter");
    32293189        if (isset($bot_options['similarity_threshold'])) {
    3230             error_log("  - similarity_threshold: " . $bot_options['similarity_threshold']);
     3190            //error_log("  - similarity_threshold: " . $bot_options['similarity_threshold']);
    32313191        }
    32323192    }
     
    32413201// Also add debugging to your get_bot_pinecone_config function
    32423202private function get_bot_pinecone_config($bot_id = 'default') {
    3243     error_log("MXCHAT DEBUG: get_bot_pinecone_config called for bot: " . $bot_id);
     3203    //error_log("MXCHAT DEBUG: get_bot_pinecone_config called for bot: " . $bot_id);
    32443204   
    32453205    // If default bot or multi-bot add-on not active, use default Pinecone config
    32463206    if ($bot_id === 'default' || !class_exists('MxChat_Multi_Bot_Manager')) {
    3247         error_log("MXCHAT DEBUG: Using default Pinecone config (no multi-bot or bot is 'default')");
     3207        //error_log("MXCHAT DEBUG: Using default Pinecone config (no multi-bot or bot is 'default')");
    32483208        $addon_options = get_option('mxchat_pinecone_addon_options', array());
    32493209        $config = array(
     
    32533213            'namespace' => $addon_options['mxchat_pinecone_namespace'] ?? ''
    32543214        );
    3255         error_log("MXCHAT DEBUG: Default config - use_pinecone: " . ($config['use_pinecone'] ? 'true' : 'false'));
     3215        //error_log("MXCHAT DEBUG: Default config - use_pinecone: " . ($config['use_pinecone'] ? 'true' : 'false'));
    32563216        return $config;
    32573217    }
    32583218   
    3259     error_log("MXCHAT DEBUG: Calling filter 'mxchat_get_bot_pinecone_config' for bot: " . $bot_id);
     3219    //error_log("MXCHAT DEBUG: Calling filter 'mxchat_get_bot_pinecone_config' for bot: " . $bot_id);
    32603220   
    32613221    // Hook for multi-bot add-on to provide bot-specific Pinecone config
     
    32633223   
    32643224    if (!empty($bot_pinecone_config)) {
    3265         error_log("MXCHAT DEBUG: Got bot-specific config from filter");
    3266         error_log("  - use_pinecone: " . (isset($bot_pinecone_config['use_pinecone']) ? ($bot_pinecone_config['use_pinecone'] ? 'true' : 'false') : 'not set'));
    3267         error_log("  - host: " . ($bot_pinecone_config['host'] ?? 'not set'));
    3268         error_log("  - namespace: " . ($bot_pinecone_config['namespace'] ?? 'not set'));
     3225        //error_log("MXCHAT DEBUG: Got bot-specific config from filter");
     3226        //error_log("  - use_pinecone: " . (isset($bot_pinecone_config['use_pinecone']) ? ($bot_pinecone_config['use_pinecone'] ? 'true' : 'false') : 'not set'));
     3227        //error_log("  - host: " . ($bot_pinecone_config['host'] ?? 'not set'));
     3228        //error_log("  - namespace: " . ($bot_pinecone_config['namespace'] ?? 'not set'));
    32693229    } else {
    3270         error_log("MXCHAT DEBUG: Filter returned empty config!");
     3230        //error_log("MXCHAT DEBUG: Filter returned empty config!");
    32713231    }
    32723232   
     
    42654225   
    42664226    if ($result['success']) {
    4267         // Remove from ALL caches
    4268         $pinecone_manager->mxchat_remove_from_pinecone_vector_cache($vector_id);
    4269         $pinecone_manager->mxchat_remove_from_processed_content_caches($vector_id);
    4270        
    4271         // CLEAR ALL RELEVANT CACHES
    4272         delete_transient('mxchat_pinecone_recent_1k_cache');
    4273         delete_option('mxchat_pinecone_vector_ids_cache');
    4274         delete_option('mxchat_pinecone_processed_cache');
    4275         delete_option('mxchat_processed_content_cache');
    4276        
    4277         // Also force refresh for next page load
    4278         $pinecone_manager->mxchat_refresh_after_new_content($pinecone_options);
    4279        
     4227        // No cache clearing needed since we removed caching
    42804228        set_transient('mxchat_admin_notice_success',
    42814229            esc_html__('Entry deleted successfully from Pinecone.', 'mxchat'),
     
    42924240    exit;
    42934241}
    4294 
     4242/**
     4243 * Handle individual Pinecone content deletion via AJAX
     4244 */
    42954245public function ajax_mxchat_delete_pinecone_prompt() {
    42964246    // Verify nonce and permissions
     
    43324282   
    43334283    if ($result['success']) {
    4334         // Clear bot-specific caches
    4335         $pinecone_manager->mxchat_clear_bot_caches($bot_id);
    4336        
     4284        // No cache clearing needed since we removed caching
    43374285        wp_send_json_success(array(
    43384286            'message' => 'Entry deleted successfully from Pinecone',
     
    43464294    exit;
    43474295}
     4296
    43484297/**
    43494298 * NEW: Get hierarchical roles for dropdown
     
    44114360
    44124361/**
    4413  *  Handle role restriction updates via AJAX
    4414  */
    4415 /**
    4416  * UPDATED: Handle role restriction updates for both WordPress and Pinecone via AJAX
     4362 * Handle role restriction updates via AJAX
     4363 * UPDATED: Removed cache clearing call since we removed caching
    44174364 */
    44184365public function ajax_mxchat_update_role_restriction() {
     
    44624409        );
    44634410       
    4464         // Clear Pinecone cache to reflect changes
    4465         delete_transient('mxchat_pinecone_recent_1k_cache');
     4411        // No cache clearing needed since we removed caching
    44664412       
    44674413    } else {
  • mxchat-basic/trunk/admin/class-pinecone-manager.php

    r3366492 r3367268  
    2929 */
    3030public function mxchat_fetch_pinecone_records($pinecone_options, $search_query = '', $page = 1, $per_page = 20, $bot_id = 'default') {
    31     error_log('=== DEBUG: mxchat_fetch_pinecone_records ===');
    32     error_log('Bot ID: ' . $bot_id);
    33     error_log('Pinecone Host: ' . ($pinecone_options['mxchat_pinecone_host'] ?? 'NOT SET'));
    34     error_log('Pinecone Namespace: ' . ($pinecone_options['mxchat_pinecone_namespace'] ?? 'NOT SET'));
    35     error_log('Use Pinecone: ' . ($pinecone_options['mxchat_use_pinecone'] ?? 'NOT SET'));
     31    //error_log('=== DEBUG: mxchat_fetch_pinecone_records ===');
     32    //error_log('Bot ID: ' . $bot_id);
     33    //error_log('Pinecone Host: ' . ($pinecone_options['mxchat_pinecone_host'] ?? 'NOT SET'));
     34    //error_log('Pinecone Namespace: ' . ($pinecone_options['mxchat_pinecone_namespace'] ?? 'NOT SET'));
     35    //error_log('Use Pinecone: ' . ($pinecone_options['mxchat_use_pinecone'] ?? 'NOT SET'));
    3636   
    3737    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
     
    4040
    4141    if (empty($api_key) || empty($host)) {
    42         //error_log('DEBUG: Missing required Pinecone parameters');
    4342        return array('data' => array(), 'total' => 0, 'total_in_database' => 0, 'showing_recent_only' => false);
    4443    }
     
    4847        $total_in_database = $this->mxchat_get_pinecone_total_count($pinecone_options, $bot_id);
    4948       
    50         // Check cache first for consistency (bot-specific cache)
    51         $cache_key = 'mxchat_pinecone_recent_1k_cache_' . $bot_id;
    52         $all_records = get_transient($cache_key);
    53        
    54         if ($all_records === false) {
    55             // Cache miss - get fresh data (bot-specific)
    56             $all_records = $this->mxchat_get_recent_1k_entries($pinecone_options, $bot_id);
    57         }
     49        // Always get fresh data - no caching
     50        $all_records = $this->mxchat_get_recent_1k_entries($pinecone_options, $bot_id);
    5851       
    5952        // Filter by search query if provided
     
    7063        $offset = ($page - 1) * $per_page;
    7164        $paged_records = array_slice($all_records, $offset, $per_page);
    72 
    73         //error_log('DEBUG: Returning ' . count($paged_records) . ' records for bot ' . $bot_id);
    7465       
    7566        return array(
     
    8172
    8273    } catch (Exception $e) {
    83         //error_log('DEBUG: Exception: ' . $e->getMessage());
    8474        return array('data' => array(), 'total' => 0, 'total_in_database' => 0, 'showing_recent_only' => false);
    8575    }
    8676}
    87 
    8877/**
    8978     * Get embedding dimensions based on the selected model
     
    143132
    144133
     134/**
     135 * Get recent 1K entries from Pinecone
     136 */
    145137private function mxchat_get_recent_1k_entries($pinecone_options, $bot_id = 'default') {
    146138    global $wpdb;
    147     error_log('=== DEBUG: mxchat_get_recent_1k_entries started ===');
    148     error_log('DEBUG: Bot ID: ' . $bot_id);
     139    //error_log('=== DEBUG: mxchat_get_recent_1k_entries started ===');
     140    //error_log('DEBUG: Bot ID: ' . $bot_id);
    149141   
    150142    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
     
    164156       
    165157        foreach ($fixed_vectors as $vector_index => $query_vector) {
    166             error_log('DEBUG: Using fixed query vector ' . ($vector_index + 1) . '/' . count($fixed_vectors));
     158            //error_log('DEBUG: Using fixed query vector ' . ($vector_index + 1) . '/' . count($fixed_vectors));
    167159           
    168160            $query_data = array(
     
    177169                $query_data['namespace'] = $namespace;
    178170            }
    179            
    180             // REMOVE THE BOT_ID FILTER - Each bot has its own Pinecone index
    181             // No need to filter by bot_id within the index
    182171
    183172            $response = wp_remote_post($query_url, array(
     
    199188                        if (!empty($match_id) && !isset($seen_ids[$match_id])) {
    200189                            $metadata = $match['metadata'] ?? array();
    201                            
    202                             // Remove the bot_id checking since each bot has its own index
    203190                           
    204191                            // Get created_at timestamp
     
    217204                                'source_url' => $metadata['source_url'] ?? '',
    218205                                'role_restriction' => $metadata['role_restriction'] ?? 'public',
    219                                 'bot_id' => $bot_id, // Just set it to current bot for display
     206                                'bot_id' => $bot_id,
    220207                                'created_at' => $created_at,
    221208                                'data_source' => 'pinecone'
     
    254241        }
    255242       
    256         error_log('DEBUG: Found ' . count($all_records) . ' total unique records, returning top ' . count($recent_1k));
    257        
    258         // Cache the results
    259         $cache_key = 'mxchat_pinecone_recent_1k_cache_' . $bot_id;
    260         set_transient($cache_key, $recent_1k, 60);
     243        //error_log('DEBUG: Found ' . count($all_records) . ' total unique records, returning top ' . count($recent_1k));
    261244       
    262245        return $recent_1k;
    263246
    264247    } catch (Exception $e) {
    265         error_log('DEBUG: Exception in get_recent_1k_entries: ' . $e->getMessage());
     248        //error_log('DEBUG: Exception in get_recent_1k_entries: ' . $e->getMessage());
    266249        return array();
    267250    }
    268251}
    269 
    270252/**
    271253 * Generate fixed query vectors for consistent results
     
    323305
    324306/**
    325      * Scan Pinecone for processed content (MISSING FUNCTION - ADD THIS)
    326      */
    327     public function mxchat_scan_pinecone_for_processed_content($pinecone_options) {
    328         //error_log('=== DEBUG: Starting mxchat_scan_pinecone_for_processed_content ===');
    329        
    330         $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
    331         $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
    332 
    333         if (empty($api_key) || empty($host)) {
    334             //error_log('DEBUG: Missing API credentials for scanning');
    335             return array();
    336         }
    337 
    338         try {
    339             // Use multiple random vectors to get better coverage
    340             $all_matches = array();
    341             $seen_ids = array();
    342 
    343             // Try 3 different random vectors to get better coverage
    344             for ($i = 0; $i < 3; $i++) {
    345                 //error_log('DEBUG: Scanning attempt ' . ($i + 1) . '/3');
    346                
    347                 $query_url = "https://{$host}/query";
    348 
    349                 // Generate random vector with CORRECT dimensions
    350                 $random_vector = $this->mxchat_generate_random_vector();
    351 
    352                 $query_data = array(
    353                     'includeMetadata' => true,
    354                     'includeValues' => false,
    355                     'topK' => 10000,
    356                     'vector' => $random_vector
    357                 );
    358 
    359                 $response = wp_remote_post($query_url, array(
    360                     'headers' => array(
    361                         'Api-Key' => $api_key,
    362                         'Content-Type' => 'application/json'
    363                     ),
    364                     'body' => json_encode($query_data),
    365                     'timeout' => 30
    366                 ));
    367 
    368                 if (is_wp_error($response)) {
    369                     //error_log('DEBUG: Query attempt ' . ($i + 1) . ' WP error: ' . $response->get_error_message());
    370                     continue;
     307 * Scan Pinecone for processed content
     308 */
     309public function mxchat_scan_pinecone_for_processed_content($pinecone_options) {
     310    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
     311    $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
     312
     313    if (empty($api_key) || empty($host)) {
     314        return array();
     315    }
     316
     317    try {
     318        // Use multiple random vectors to get better coverage
     319        $all_matches = array();
     320        $seen_ids = array();
     321
     322        // Try 3 different random vectors to get better coverage
     323        for ($i = 0; $i < 3; $i++) {
     324            $query_url = "https://{$host}/query";
     325
     326            // Generate random vector with CORRECT dimensions
     327            $random_vector = $this->mxchat_generate_random_vector();
     328
     329            $query_data = array(
     330                'includeMetadata' => true,
     331                'includeValues' => false,
     332                'topK' => 10000,
     333                'vector' => $random_vector
     334            );
     335
     336            $response = wp_remote_post($query_url, array(
     337                'headers' => array(
     338                    'Api-Key' => $api_key,
     339                    'Content-Type' => 'application/json'
     340                ),
     341                'body' => json_encode($query_data),
     342                'timeout' => 30
     343            ));
     344
     345            if (is_wp_error($response)) {
     346                continue;
     347            }
     348
     349            $response_code = wp_remote_retrieve_response_code($response);
     350           
     351            if ($response_code !== 200) {
     352                continue;
     353            }
     354
     355            $body = wp_remote_retrieve_body($response);
     356            $data = json_decode($body, true);
     357
     358            if (isset($data['matches'])) {
     359                foreach ($data['matches'] as $match) {
     360                    $match_id = $match['id'] ?? '';
     361                    if (!empty($match_id) && !isset($seen_ids[$match_id])) {
     362                        $all_matches[] = $match;
     363                        $seen_ids[$match_id] = true;
     364                    }
    371365                }
    372 
    373                 $response_code = wp_remote_retrieve_response_code($response);
    374                 //error_log('DEBUG: Query attempt ' . ($i + 1) . ' response code: ' . $response_code);
    375                
    376                 if ($response_code !== 200) {
    377                     $error_body = wp_remote_retrieve_body($response);
    378                     //error_log('DEBUG: Query attempt ' . ($i + 1) . ' failed with body: ' . substr($error_body, 0, 500));
    379                     continue;
    380                 }
    381 
    382                 $body = wp_remote_retrieve_body($response);
    383                 $data = json_decode($body, true);
    384 
    385                 if (isset($data['matches'])) {
    386                     //error_log('DEBUG: Query attempt ' . ($i + 1) . ' returned ' . count($data['matches']) . ' matches');
    387                     foreach ($data['matches'] as $match) {
    388                         $match_id = $match['id'] ?? '';
    389                         if (!empty($match_id) && !isset($seen_ids[$match_id])) {
    390                             $all_matches[] = $match;
    391                             $seen_ids[$match_id] = true;
     366            }
     367        }
     368
     369        // Convert matches to processed data format
     370        $processed_data = array();
     371
     372        foreach ($all_matches as $match) {
     373            $metadata = $match['metadata'] ?? array();
     374            $source_url = $metadata['source_url'] ?? '';
     375            $match_id = $match['id'] ?? '';
     376
     377            if (!empty($source_url) && !empty($match_id)) {
     378                $post_id = url_to_postid($source_url);
     379                if ($post_id) {
     380                    $created_at = $metadata['created_at'] ?? '';
     381                    $processed_date = 'Recently';
     382
     383                    if (!empty($created_at)) {
     384                        $timestamp = is_numeric($created_at) ? $created_at : strtotime($created_at);
     385                        if ($timestamp) {
     386                            $processed_date = human_time_diff($timestamp, current_time('timestamp')) . ' ago';
    392387                        }
    393388                    }
    394                 } else {
    395                     //error_log('DEBUG: Query attempt ' . ($i + 1) . ' - no matches key in response');
     389
     390                    $processed_data[$post_id] = array(
     391                        'db_id' => $match_id,
     392                        'processed_date' => $processed_date,
     393                        'url' => $source_url,
     394                        'source' => 'pinecone',
     395                        'timestamp' => $timestamp ?? current_time('timestamp')
     396                    );
    396397                }
    397398            }
    398 
    399             //error_log('DEBUG: Total unique matches found: ' . count($all_matches));
    400 
    401             // Convert matches to processed data format
    402             $processed_data = array();
    403             $vector_ids_for_cache = array();
    404 
    405             foreach ($all_matches as $match) {
    406                 $metadata = $match['metadata'] ?? array();
    407                 $source_url = $metadata['source_url'] ?? '';
    408                 $match_id = $match['id'] ?? '';
    409 
    410                 if (!empty($source_url) && !empty($match_id)) {
    411                     $post_id = url_to_postid($source_url);
    412                     if ($post_id) {
    413                         $created_at = $metadata['created_at'] ?? '';
    414                         $processed_date = 'Recently';
    415 
    416                         if (!empty($created_at)) {
    417                             $timestamp = is_numeric($created_at) ? $created_at : strtotime($created_at);
    418                             if ($timestamp) {
    419                                 $processed_date = human_time_diff($timestamp, current_time('timestamp')) . ' ago';
    420                             }
    421                         }
    422 
    423                         $processed_data[$post_id] = array(
    424                             'db_id' => $match_id,
    425                             'processed_date' => $processed_date,
    426                             'url' => $source_url,
    427                             'source' => 'pinecone',
    428                             'timestamp' => $timestamp ?? current_time('timestamp')
    429                         );
    430 
    431                         $vector_ids_for_cache[] = $match_id;
    432                     }
    433                 }
    434             }
    435 
    436             // Update the vector IDs cache for future use
    437             if (!empty($vector_ids_for_cache)) {
    438                 update_option('mxchat_pinecone_vector_ids_cache', $vector_ids_for_cache);
    439                 //error_log('DEBUG: Updated vector IDs cache with ' . count($vector_ids_for_cache) . ' IDs');
    440             }
    441 
    442             //error_log('DEBUG: Returning ' . count($processed_data) . ' processed items from scanning');
    443             return $processed_data;
    444 
    445         } catch (Exception $e) {
    446             //error_log('DEBUG: Exception in scan_pinecone_for_processed_content: ' . $e->getMessage());
    447             return array();
    448         }
    449     }
    450 
     399        }
     400
     401        return $processed_data;
     402
     403    } catch (Exception $e) {
     404        return array();
     405    }
     406}
     407
     408/**
     409 * Get total count from Pinecone stats API
     410 * UPDATED: Removed cache fallback reference
     411 */
    451412private function mxchat_get_pinecone_total_count($pinecone_options, $bot_id = 'default') {
    452413    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
     
    467428            $request_data['namespace'] = $namespace;
    468429        }
    469        
    470         // REMOVE THE BOT_ID FILTER - Each bot has its own index
    471430
    472431        $response = wp_remote_post($stats_url, array(
     
    485444            $total_count = $stats_data['totalVectorCount'] ?? 0;
    486445            if ($total_count > 0) {
    487                 error_log('DEBUG: Got total count from stats API: ' . $total_count);
     446                //error_log('DEBUG: Got total count from stats API: ' . $total_count);
    488447                return intval($total_count);
    489448            }
    490449        }
    491450
    492         // Fallback: estimate from previous scans
    493         $cached_vector_ids = get_option('mxchat_pinecone_vector_ids_cache_' . $bot_id, array());
    494         if (!empty($cached_vector_ids)) {
    495             $estimated_count = count($cached_vector_ids);
    496             return intval($estimated_count);
    497         }
     451        // If stats API fails, return 0 instead of using cache
     452        return 0;
    498453
    499454    } catch (Exception $e) {
    500         error_log('DEBUG: Exception getting total count: ' . $e->getMessage());
    501     }
    502 
    503     return 0;
    504 }
    505 
    506 /**
    507  * Clear all caches for a specific bot (and general caches)
    508  */
    509 public function mxchat_clear_bot_caches($bot_id = 'default') {
    510     //error_log('DEBUG: Clearing all caches for bot: ' . $bot_id);
    511    
    512     // Clear bot-specific caches
    513     delete_transient('mxchat_pinecone_recent_1k_cache_' . $bot_id);
    514     delete_transient('mxchat_pinecone_recent_1k_' . $bot_id);
    515     delete_transient('mxchat_pinecone_total_count_' . $bot_id);
    516     delete_option('mxchat_pinecone_vector_ids_cache_' . $bot_id);
    517     delete_option('mxchat_pinecone_processed_cache_' . $bot_id);
    518     delete_option('mxchat_processed_content_cache_' . $bot_id);
    519    
    520     // Also clear general caches for backward compatibility
    521     delete_transient('mxchat_pinecone_recent_1k_cache');
    522     delete_transient('mxchat_pinecone_recent_1k');
    523     delete_transient('mxchat_pinecone_total_count');
    524     delete_option('mxchat_pinecone_vector_ids_cache');
    525     delete_option('mxchat_pinecone_processed_cache');
    526     delete_option('mxchat_processed_content_cache');
    527    
    528     //error_log('DEBUG: All caches cleared for bot: ' . $bot_id);
    529    
    530     return true;
    531 }
    532 
    533 /**
    534  * Clear caches for all bots
    535  */
    536 public function mxchat_clear_all_bot_caches() {
    537     // Clear default/general caches
    538     $this->mxchat_clear_bot_caches('default');
    539    
    540     // If multi-bot addon is active, clear caches for all bots
    541     if (class_exists('MxChat_Multi_Bot_Manager')) {
    542         $multi_bot_manager = MxChat_Multi_Bot_Core_Manager::get_instance();
    543         $available_bots = $multi_bot_manager->get_available_bots();
    544        
    545         foreach ($available_bots as $bot_id => $bot_name) {
    546             if ($bot_id !== 'default') {
    547                 $this->mxchat_clear_bot_caches($bot_id);
    548             }
    549         }
    550     }
    551    
    552     return true;
    553 }
    554 
    555 /**
    556  * Call this after adding new content to refresh the view for specific bot
    557  */
    558 public function mxchat_refresh_after_new_content($pinecone_options, $bot_id = 'default') {
    559     //error_log('DEBUG: Refreshing after new content added for bot: ' . $bot_id);
    560    
    561     // Use the new comprehensive cache clearing method
    562     $this->mxchat_clear_bot_caches($bot_id);
    563    
    564     // Force fresh fetch on next page load
    565     return true;
     455        //error_log('DEBUG: Exception getting total count: ' . $e->getMessage());
     456        return 0;
     457    }
    566458}
    567459
     
    570462 */
    571463public function mxchat_get_bot_pinecone_options($bot_id = 'default') {
    572     error_log('DEBUG: Getting Pinecone options for bot: ' . $bot_id);
     464    //error_log('DEBUG: Getting Pinecone options for bot: ' . $bot_id);
    573465   
    574466    // If default bot or multi-bot add-on not active, use default Pinecone config
    575467    if ($bot_id === 'default' || !class_exists('MxChat_Multi_Bot_Manager')) {
    576468        $addon_options = get_option('mxchat_pinecone_addon_options', array());
    577         error_log('DEBUG: Using default Pinecone options');
     469        //error_log('DEBUG: Using default Pinecone options');
    578470        return $addon_options;
    579471    }
     
    582474    $bot_config = apply_filters('mxchat_get_bot_pinecone_config', array(), $bot_id);
    583475   
    584     error_log('DEBUG: Bot config from filter: ' . print_r($bot_config, true));
     476    //error_log('DEBUG: Bot config from filter: ' . print_r($bot_config, true));
    585477   
    586478    // Check if we got valid bot-specific config
     
    596488        );
    597489       
    598         error_log('DEBUG: Returning bot-specific Pinecone options for bot: ' . $bot_id);
     490        //error_log('DEBUG: Returning bot-specific Pinecone options for bot: ' . $bot_id);
    599491        return $pinecone_options;
    600492    }
    601493   
    602494    // Fallback to default options if bot-specific config is invalid
    603     error_log('DEBUG: Bot-specific config invalid, falling back to default');
     495    //error_log('DEBUG: Bot-specific config invalid, falling back to default');
    604496    return get_option('mxchat_pinecone_addon_options', array());
    605497}
     
    610502 */
    611503private function get_bot_pinecone_config($bot_id = 'default') {
    612     error_log("MXCHAT DEBUG: get_bot_pinecone_config called for bot: " . $bot_id);
     504    //error_log("MXCHAT DEBUG: get_bot_pinecone_config called for bot: " . $bot_id);
    613505   
    614506    // If default bot or multi-bot add-on not active, use default Pinecone config
    615507    if ($bot_id === 'default' || !class_exists('MxChat_Multi_Bot_Manager')) {
    616         error_log("MXCHAT DEBUG: Using default Pinecone config (no multi-bot or bot is 'default')");
     508        //error_log("MXCHAT DEBUG: Using default Pinecone config (no multi-bot or bot is 'default')");
    617509        $addon_options = get_option('mxchat_pinecone_addon_options', array());
    618510        $config = array(
     
    622514            'namespace' => $addon_options['mxchat_pinecone_namespace'] ?? ''
    623515        );
    624         error_log("MXCHAT DEBUG: Default config - use_pinecone: " . ($config['use_pinecone'] ? 'true' : 'false'));
     516        //error_log("MXCHAT DEBUG: Default config - use_pinecone: " . ($config['use_pinecone'] ? 'true' : 'false'));
    625517        return $config;
    626518    }
    627519   
    628     error_log("MXCHAT DEBUG: Calling filter 'mxchat_get_bot_pinecone_config' for bot: " . $bot_id);
     520    //error_log("MXCHAT DEBUG: Calling filter 'mxchat_get_bot_pinecone_config' for bot: " . $bot_id);
    629521   
    630522    // Hook for multi-bot add-on to provide bot-specific Pinecone config
     
    632524   
    633525    if (!empty($bot_pinecone_config)) {
    634         error_log("MXCHAT DEBUG: Got bot-specific config from filter");
    635         error_log("  - use_pinecone: " . (isset($bot_pinecone_config['use_pinecone']) ? ($bot_pinecone_config['use_pinecone'] ? 'true' : 'false') : 'not set'));
    636         error_log("  - host: " . ($bot_pinecone_config['host'] ?? 'not set'));
    637         error_log("  - namespace: " . ($bot_pinecone_config['namespace'] ?? 'not set'));
     526        //error_log("MXCHAT DEBUG: Got bot-specific config from filter");
     527        //error_log("  - use_pinecone: " . (isset($bot_pinecone_config['use_pinecone']) ? ($bot_pinecone_config['use_pinecone'] ? 'true' : 'false') : 'not set'));
     528        //error_log("  - host: " . ($bot_pinecone_config['host'] ?? 'not set'));
     529        //error_log("  - namespace: " . ($bot_pinecone_config['namespace'] ?? 'not set'));
    638530    } else {
    639         error_log("MXCHAT DEBUG: Filter returned empty config!");
     531        //error_log("MXCHAT DEBUG: Filter returned empty config!");
    640532    }
    641533   
    642534    return is_array($bot_pinecone_config) ? $bot_pinecone_config : array();
    643535}   
     536
     537
    644538/**
    645539 * Fetches vectors from Pinecone using provided IDs (for content selection feature)
    646540 */
    647541public function fetch_pinecone_vectors_by_ids($pinecone_options, $vector_ids) {
    648     //error_log('=== DEBUG: fetch_pinecone_vectors_by_ids started (content selection method) ===');
    649    
    650542    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
    651543    $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
    652544
    653     //error_log('DEBUG: API key present: ' . (!empty($api_key) ? 'YES' : 'NO'));
    654     //error_log('DEBUG: Host: ' . $host);
    655     //error_log('DEBUG: Vector IDs count: ' . count($vector_ids));
    656 
    657545    if (empty($api_key) || empty($host) || empty($vector_ids)) {
    658         //error_log('DEBUG: Missing parameters for fetch by IDs (content selection)');
    659546        return array();
    660547    }
     
    662549    try {
    663550        $fetch_url = "https://{$host}/vectors/fetch";
    664         //error_log('DEBUG: Fetch URL: ' . $fetch_url);
    665551
    666552        // Pinecone fetch API allows fetching specific vectors by ID
     
    679565
    680566        if (is_wp_error($response)) {
    681             //error_log('DEBUG: Fetch by IDs WP error (content selection): ' . $response->get_error_message());
    682567            return array();
    683568        }
    684569
    685570        $response_code = wp_remote_retrieve_response_code($response);
    686         //error_log('DEBUG: Fetch response code (content selection): ' . $response_code);
    687571       
    688572        if ($response_code !== 200) {
    689             $error_body = wp_remote_retrieve_body($response);
    690             //error_log('DEBUG: Fetch failed with body (content selection): ' . $error_body);
    691573            return array();
    692574        }
     
    696578
    697579        if (!isset($data['vectors'])) {
    698             //error_log('DEBUG: No vectors key in response (content selection)');
    699580            return array();
    700581        }
     
    730611        }
    731612
    732         //error_log('DEBUG: Processed ' . count($processed_data) . ' records (content selection method)');
    733         //error_log('=== DEBUG: fetch_pinecone_vectors_by_ids completed (content selection) ===');
    734 
    735613        return $processed_data;
    736614
    737615    } catch (Exception $e) {
    738         //error_log('DEBUG: Exception in fetch_pinecone_vectors_by_ids (content selection): ' . $e->getMessage());
    739616        return array();
    740617    }
    741618}
    742 
    743 
    744619    // ========================================
    745620    // PINECONE DELETE OPERATIONS
    746621    // ========================================
    747622
     623/**
     624 * Delete all vectors from Pinecone
     625 */
    748626public function mxchat_delete_all_from_pinecone($pinecone_options) {
    749627    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
     
    758636
    759637    try {
    760         // First, get all vector IDs
     638        // First, get all vector IDs by scanning Pinecone directly
    761639        $all_vector_ids = array();
    762640
    763         // Try to get from cache first
    764         $cached_vector_ids = get_option('mxchat_pinecone_vector_ids_cache', array());
    765         if (!empty($cached_vector_ids)) {
    766             $all_vector_ids = $cached_vector_ids;
    767         } else {
    768             // Use the correct method name that exists in your class
    769             $records = $this->mxchat_get_recent_1k_entries($pinecone_options);
    770             foreach ($records as $record) {
    771                 if (!empty($record->id)) {
    772                     $all_vector_ids[] = $record->id;
    773                 }
     641        // Get fresh data from Pinecone
     642        $records = $this->mxchat_get_recent_1k_entries($pinecone_options);
     643        foreach ($records as $record) {
     644            if (!empty($record->id)) {
     645                $all_vector_ids[] = $record->id;
    774646            }
    775647        }
     
    794666            } else {
    795667                $failed_batches++;
    796                 //error_log('Failed to delete Pinecone batch: ' . $result['message']);
    797             }
    798         }
    799 
    800         // CLEAR ALL RELEVANT CACHES - EXACTLY like your single delete
    801         delete_transient('mxchat_pinecone_recent_1k_cache');
    802         delete_option('mxchat_pinecone_vector_ids_cache');
    803         delete_option('mxchat_pinecone_processed_cache');
    804         delete_option('mxchat_processed_content_cache');
    805        
    806         // Also force refresh for next page load - EXACTLY like your single delete
    807         $this->mxchat_refresh_after_new_content($pinecone_options);
     668            }
     669        }
    808670
    809671        if ($failed_batches > 0) {
     
    820682
    821683    } catch (Exception $e) {
    822         //error_log('Pinecone delete all exception: ' . $e->getMessage());
    823684        return array(
    824685            'success' => false,
     
    827688    }
    828689}
    829 
    830690
    831691    /**
     
    889749 */
    890750public function mxchat_delete_from_pinecone_by_vector_id($vector_id, $api_key, $host, $namespace = '') {
    891     error_log('=== PINECONE DELETE OPERATION ===');
    892     error_log('Vector ID: ' . $vector_id);
    893     error_log('Host: ' . $host);
    894     error_log('API Key: ' . (empty($api_key) ? 'EMPTY' : 'SET'));
     751    //error_log('=== PINECONE DELETE OPERATION ===');
     752    //error_log('Vector ID: ' . $vector_id);
     753    //error_log('Host: ' . $host);
     754    //error_log('API Key: ' . (empty($api_key) ? 'EMPTY' : 'SET'));
    895755   
    896756    // First, let's verify the vector exists before trying to delete
     
    921781        $fetch_data = json_decode($fetch_body, true);
    922782       
    923         error_log('DEBUG: Fetch response: ' . print_r($fetch_data, true));
     783        //error_log('DEBUG: Fetch response: ' . print_r($fetch_data, true));
    924784       
    925785        if (isset($fetch_data['vectors']) && isset($fetch_data['vectors'][$vector_id])) {
    926             error_log('DEBUG: Vector EXISTS in this index before deletion');
     786            //error_log('DEBUG: Vector EXISTS in this index before deletion');
    927787        } else {
    928             error_log('WARNING: Vector NOT FOUND in this index! It may be in a different bot\'s index');
     788            //error_log('WARNING: Vector NOT FOUND in this index! It may be in a different bot\'s index');
    929789            // You might want to return an error here
    930790        }
    931791    } else {
    932         error_log('DEBUG: Could not fetch vector to verify existence');
     792        //error_log('DEBUG: Could not fetch vector to verify existence');
    933793    }
    934794   
     
    946806    }
    947807   
    948     error_log('DEBUG: Delete request body: ' . json_encode($request_body));
    949     error_log('DEBUG: Delete endpoint: ' . $api_endpoint);
     808    //error_log('DEBUG: Delete request body: ' . json_encode($request_body));
     809    //error_log('DEBUG: Delete endpoint: ' . $api_endpoint);
    950810
    951811    // Make the deletion request
     
    962822    // Handle WordPress HTTP API errors
    963823    if (is_wp_error($response)) {
    964         error_log('DEBUG: WP Error: ' . $response->get_error_message());
     824        //error_log('DEBUG: WP Error: ' . $response->get_error_message());
    965825        return array(
    966826            'success' => false,
     
    973833    $response_body = wp_remote_retrieve_body($response);
    974834   
    975     error_log('DEBUG: Delete response code: ' . $response_code);
    976     error_log('DEBUG: Delete response body: ' . $response_body);
     835    //error_log('DEBUG: Delete response code: ' . $response_code);
     836    //error_log('DEBUG: Delete response body: ' . $response_body);
    977837
    978838    // Pinecone returns 200 for successful deletion (even if vector didn't exist)
    979839    if ($response_code !== 200) {
    980         error_log('DEBUG: Non-200 response from Pinecone');
     840        //error_log('DEBUG: Non-200 response from Pinecone');
    981841        return array(
    982842            'success' => false,
     
    1005865       
    1006866        if (isset($verify_data['vectors']) && isset($verify_data['vectors'][$vector_id])) {
    1007             error_log('ERROR: Vector STILL EXISTS after deletion attempt!');
     867            //error_log('ERROR: Vector STILL EXISTS after deletion attempt!');
    1008868            return array(
    1009869                'success' => false,
     
    1011871            );
    1012872        } else {
    1013             error_log('SUCCESS: Vector confirmed deleted (or never existed)');
    1014         }
    1015     }
    1016    
    1017     error_log('=== END PINECONE DELETE OPERATION ===');
     873            //error_log('SUCCESS: Vector confirmed deleted (or never existed)');
     874        }
     875    }
     876   
     877    //error_log('=== END PINECONE DELETE OPERATION ===');
    1018878
    1019879    return array(
     
    11511011
    11521012
    1153     // ========================================
    1154     // VECTOR CACHE MANAGEMENT
    1155     // ========================================
    1156 
    1157 
    1158     /**
    1159      * Removes vector ID from cache array option
    1160      */
    1161      public function mxchat_remove_from_pinecone_vector_cache($vector_id) {
    1162          $cached_ids = get_option('mxchat_pinecone_vector_ids_cache', array());
    1163          $key = array_search($vector_id, $cached_ids);
    1164          if ($key !== false) {
    1165              unset($cached_ids[$key]);
    1166              update_option('mxchat_pinecone_vector_ids_cache', array_values($cached_ids));
    1167          }
    1168      }
    1169 
    1170     /**
    1171      * Removes vector ID from processed content caches
    1172      */
    1173      public function mxchat_remove_from_processed_content_caches($vector_id) {
    1174          // Get all caches
    1175          $pinecone_cache = get_option('mxchat_pinecone_processed_cache', array());
    1176          $processed_cache = get_option('mxchat_processed_content_cache', array());
    1177 
    1178          // We need to find the post ID that corresponds to this vector ID
    1179          // Vector ID is typically md5 of the source URL
    1180          $post_id_to_remove = null;
    1181 
    1182          // Search through caches to find matching post
    1183          foreach ($pinecone_cache as $post_id => $cache_data) {
    1184              if (isset($cache_data['db_id']) && $cache_data['db_id'] === $vector_id) {
    1185                  $post_id_to_remove = $post_id;
    1186                  break;
    1187              }
    1188          }
    1189 
    1190          // Also check the processed cache
    1191          if (!$post_id_to_remove) {
    1192              foreach ($processed_cache as $post_id => $cache_data) {
    1193                  if (isset($cache_data['db_id']) && $cache_data['db_id'] === $vector_id) {
    1194                      $post_id_to_remove = $post_id;
    1195                      break;
    1196                  }
    1197              }
    1198          }
    1199 
    1200          // If we found the post ID, remove it from both caches
    1201          if ($post_id_to_remove) {
    1202              unset($pinecone_cache[$post_id_to_remove]);
    1203              unset($processed_cache[$post_id_to_remove]);
    1204 
    1205              update_option('mxchat_pinecone_processed_cache', $pinecone_cache);
    1206              update_option('mxchat_processed_content_cache', $processed_cache);
    1207 
    1208              //error_log('Removed post ID ' . $post_id_to_remove . ' from processed content caches');
    1209          } else {
    1210              // If we can't find by vector ID, we might need to reconstruct the URL
    1211              // and find the post ID that way
    1212              //error_log('Could not find post ID for vector ID: ' . $vector_id);
    1213          }
    1214      }
    1215 
    1216 
    1217     /**
    1218      * Retrieves and caches Pinecone API processed content
    1219      */
    1220      public function mxchat_get_pinecone_processed_content($pinecone_options) {
    1221          // First check local cache for immediate updates
    1222          $cached_data = get_option('mxchat_pinecone_processed_cache', array());
    1223 
    1224          $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
    1225          $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
    1226 
    1227          if (empty($api_key) || empty($host)) {
    1228              // Return only cached data if API credentials are missing
    1229              return $cached_data;
    1230          }
    1231 
    1232          $pinecone_data = array();
    1233 
    1234          try {
    1235              // Method 1: Try to get vectors using cached vector IDs first
    1236              $cached_vector_ids = get_option('mxchat_pinecone_vector_ids_cache', array());
    1237 
    1238              if (!empty($cached_vector_ids)) {
    1239                  $pinecone_data = $this->fetch_pinecone_vectors_by_ids($pinecone_options, $cached_vector_ids);
    1240              }
    1241 
    1242              // Method 2: If no cached IDs or fetch failed, use scanning approach
    1243              if (empty($pinecone_data)) {
    1244                  $pinecone_data = $this->mxchat_scan_pinecone_for_processed_content($pinecone_options);
    1245              }
    1246 
    1247              // Method 3: Final fallback - try stats endpoint (if available)
    1248              if (empty($pinecone_data)) {
    1249                  $stats_url = "https://{$host}/describe_index_stats";
    1250 
    1251                  $response = wp_remote_post($stats_url, array(
    1252                      'headers' => array(
    1253                          'Api-Key' => $api_key,
    1254                          'Content-Type' => 'application/json'
    1255                      ),
    1256                      'body' => json_encode(array()),
    1257                      'timeout' => 30
    1258                  ));
    1259 
    1260                  if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
    1261                      $body = wp_remote_retrieve_body($response);
    1262                      $stats_data = json_decode($body, true);
    1263 
    1264                      // Log stats for debugging but don't rely on them for vector listing
    1265                      //error_log('Pinecone index stats: ' . print_r($stats_data, true));
    1266                  }
    1267              }
    1268 
    1269          } catch (Exception $e) {
    1270              //error_log('Pinecone processed content exception: ' . $e->getMessage());
    1271          }
    1272 
    1273          // Merge cached data with Pinecone data
    1274          // Cache takes priority for recent updates (within last 5 minutes)
    1275          $merged_data = $pinecone_data;
    1276 
    1277          foreach ($cached_data as $post_id => $cache_item) {
    1278              $cache_timestamp = $cache_item['timestamp'] ?? 0;
    1279              $time_diff = current_time('timestamp') - $cache_timestamp;
    1280 
    1281              // If cache item is recent (less than 5 minutes), prioritize it
    1282              if ($time_diff < 300) { // 5 minutes = 300 seconds
    1283                  $merged_data[$post_id] = $cache_item;
    1284              } else {
    1285                  // If not in Pinecone data and cache is old, keep cache but mark as potentially stale
    1286                  if (!isset($merged_data[$post_id])) {
    1287                      $merged_data[$post_id] = $cache_item;
    1288                  }
    1289              }
    1290          }
    1291 
    1292          return $merged_data;
    1293      }
    1294 
    1295 
     1013
     1014/**
     1015 * Retrieves processed content from Pinecone API
     1016 */
     1017public function mxchat_get_pinecone_processed_content($pinecone_options) {
     1018    $api_key = $pinecone_options['mxchat_pinecone_api_key'] ?? '';
     1019    $host = $pinecone_options['mxchat_pinecone_host'] ?? '';
     1020
     1021    if (empty($api_key) || empty($host)) {
     1022        return array();
     1023    }
     1024
     1025    $pinecone_data = array();
     1026
     1027    try {
     1028        // Always get fresh data from Pinecone
     1029        $pinecone_data = $this->mxchat_scan_pinecone_for_processed_content($pinecone_options);
     1030
     1031        // Method 2: Final fallback - try stats endpoint (if available)
     1032        if (empty($pinecone_data)) {
     1033            $stats_url = "https://{$host}/describe_index_stats";
     1034
     1035            $response = wp_remote_post($stats_url, array(
     1036                'headers' => array(
     1037                    'Api-Key' => $api_key,
     1038                    'Content-Type' => 'application/json'
     1039                ),
     1040                'body' => json_encode(array()),
     1041                'timeout' => 30
     1042            ));
     1043
     1044            if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
     1045                $body = wp_remote_retrieve_body($response);
     1046                $stats_data = json_decode($body, true);
     1047            }
     1048        }
     1049
     1050    } catch (Exception $e) {
     1051        // Log error but don't return cached data
     1052    }
     1053
     1054    return $pinecone_data;
     1055}
    12961056    // ========================================
    12971057    // HELPER METHODS
  • mxchat-basic/trunk/includes/class-mxchat-addons.php

    r3366492 r3367268  
    191191     */
    192192    public function enqueue_styles() {
    193         $plugin_version = '2.4.3';
     193        $plugin_version = '2.4.4';
    194194
    195195        wp_enqueue_style(
  • mxchat-basic/trunk/includes/class-mxchat-admin.php

    r3366492 r3367268  
    592592                <div class="mxchat-pro-notification">
    593593                    <div class="mxchat-pro-content">
    594                         <h3>🚀 Limited Lifetime Offer: Save 30% on MxChat Pro, Agency, or Agency Plus!</h3>
    595                     <p>Unlock <strong>unlimited access</strong> to our growing collection of powerful add-ons including Admin AI Assistant (ChatGPT-like experience), Forms Builder, AI Theme Generator, WooCommerce, Perplexity, and more – all included with your <strong>lifetime license!</strong></p>                    </div>
     594                        <h3>🚀 Limited Lifetime Offer: Save 15% on MxChat Pro, Agency, or Agency Plus!</h3>
     595                    <p>Unlock <strong>unlimited access</strong> to our growing collection of powerful add-ons including Admin AI Assistant (ChatGPT-like experience), Forms Builder, AI Theme Generator, WooCommerce, multi-bot, and more – all included with your <strong>lifetime license!</strong></p>                    </div>
    596596                    <div class="mxchat-pro-cta">
    597597                        <a href="https://mxchat.ai/" target="_blank" class="mxchat-button"><?php echo esc_html__('Upgrade Today', 'mxchat'); ?></a>
     
    65316531public function mxchat_enqueue_admin_assets() {
    65326532    // Get plugin version (define this in your main plugin file)
    6533     $version = defined('MXCHAT_VERSION') ? MXCHAT_VERSION : '2.4.3';
     6533    $version = defined('MXCHAT_VERSION') ? MXCHAT_VERSION : '2.4.4';
    65346534
    65356535    // Use file modification time for development (remove in production)
     
    72537253        }
    72547254       
    7255         // Clear bot-specific caches
    7256         $pinecone_manager->mxchat_clear_bot_caches($bot_id);
    7257        
    7258         // Clear bot-specific vector cache
    7259         delete_option('mxchat_pinecone_vector_ids_cache_' . $bot_id);
    7260        
    7261         // Clear bot-specific processed content caches
    7262         delete_option('mxchat_pinecone_processed_cache_' . $bot_id);
    7263         delete_option('mxchat_processed_content_cache_' . $bot_id);
    7264        
    7265         // Clear bot-specific transient cache
    7266         delete_transient('mxchat_pinecone_recent_1k_cache_' . $bot_id);
     7255        // No cache clearing needed since we removed caching
    72677256       
    72687257    } else {
     
    72917280    }
    72927281   
    7293     // Clear relevant cache
    7294     wp_cache_delete('all_prompts', 'mxchat_prompts');
    7295     wp_cache_delete('all_prompts_' . $bot_id, 'mxchat_prompts');
     7282    // No cache clearing needed since we removed caching
    72967283
    72977284    error_log('=== DELETE ALL DEBUG END ===');
  • mxchat-basic/trunk/includes/class-mxchat-integrator.php

    r3366492 r3367268  
    928928            $similarity_threshold = isset($current_options['similarity_threshold'])
    929929                ? ((int) $current_options['similarity_threshold']) / 100
    930                 : 0.75;
     930                : 0.35;
    931931           
    932932            $testing_data['similarity_threshold'] = $similarity_threshold;
     
    36223622    $similarity_threshold = isset($current_options['similarity_threshold'])
    36233623        ? ((int) $current_options['similarity_threshold']) / 100
    3624         : 0.75;
     3624        : 0.35;
    36253625       
    36263626    $this->last_similarity_analysis['threshold_used'] = $similarity_threshold;
     
    38213821    $similarity_threshold = isset($current_options['similarity_threshold'])
    38223822        ? ((int) $current_options['similarity_threshold']) / 100
    3823         : 0.75;
     3823        : 0.35;
    38243824   
    38253825    $this->last_similarity_analysis['threshold_used'] = $similarity_threshold;
     
    39983998    return trim($content);
    39993999}
     4000
     4001
    40004002/**
    40014003 * Get role restriction for a single vector (with caching)
     
    45054507    }
    45064508}
     4509
    45074510private function mxchat_generate_response_openai_stream($selected_model, $api_key, $conversation_history, $relevant_content, $session_id, $testing_data = null) {
    45084511    try {
    4509          $bot_id = $this->get_current_bot_id($session_id);
     4512        $bot_id = $this->get_current_bot_id($session_id);
    45104513       
    45114514        // Get system prompt instructions using centralized function
     
    45444547        if (headers_sent() || !function_exists('curl_init')) {
    45454548            // Fallback to regular response with testing data
    4546             //error_log("MxChat: OpenAI streaming not possible, falling back to regular response");
    45474549            $regular_response = $this->mxchat_generate_response_openai(
    45484550                $selected_model,
     
    45604562            if ($testing_data !== null) {
    45614563                $response_data['testing_data'] = $testing_data;
    4562                 //error_log("MxChat Testing: Added testing data to OpenAI fallback response");
    45634564            }
    45644565           
     
    45914592        $full_response = ''; // Accumulate full response for saving
    45924593        $stream_started = false;
     4594        $buffer = ''; // CRITICAL: Add persistent buffer for incomplete chunks
    45934595       
    45944596        // Buffer control for real-time streaming
    4595         curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, $testing_data) {
     4597        curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, &$buffer, $testing_data) {
    45964598            // Send testing data as the first event if available
    45974599            if (!$stream_started && $testing_data !== null) {
     
    45994601                flush();
    46004602                $stream_started = true;
    4601                 //error_log("MxChat Testing: Sent testing data in OpenAI stream");
    4602             }
    4603            
    4604             // Process each chunk of data
    4605             $lines = explode("\n", $data);
     4603            }
     4604           
     4605            // CRITICAL FIX: Append new data to buffer
     4606            $buffer .= $data;
     4607           
     4608            // Process complete lines only
     4609            $lines = explode("\n", $buffer);
     4610           
     4611            // CRITICAL FIX: Keep the last incomplete line in the buffer
     4612            // The last element might be incomplete, so keep it in buffer
     4613            $buffer = array_pop($lines);
    46064614           
    46074615            foreach ($lines as $line) {
    4608                 if (trim($line) === '' || strpos($line, 'data: ') !== 0) {
     4616                // Skip empty lines
     4617                if (trim($line) === '') {
     4618                    continue;
     4619                }
     4620               
     4621                // Only process lines that start with "data: "
     4622                if (strpos($line, 'data: ') !== 0) {
    46094623                    continue;
    46104624                }
     
    46124626                $json_str = substr($line, 6); // Remove 'data: ' prefix
    46134627               
    4614                 if ($json_str === '[DONE]') {
     4628                if (trim($json_str) === '[DONE]') {
    46154629                    echo "data: [DONE]\n\n";
    46164630                    flush();
     
    46184632                }
    46194633               
    4620                 $json = json_decode($json_str, true);
    4621                 if (isset($json['choices'][0]['delta']['content'])) {
     4634                // Try to decode JSON
     4635                $json = json_decode(trim($json_str), true);
     4636                if ($json && isset($json['choices'][0]['delta']['content'])) {
    46224637                    $content = $json['choices'][0]['delta']['content'];
    4623                     $full_response .= $content; // Accumulate
     4638                    $full_response .= $content; // Accumulate the full response
     4639                   
    46244640                    // Send as SSE format
    46254641                    echo "data: " . json_encode(['content' => $content]) . "\n\n";
     
    46384654           
    46394655            // Fallback to regular response
    4640             //error_log("MxChat: OpenAI streaming failed, falling back");
    46414656            $regular_response = $this->mxchat_generate_response_openai(
    46424657                $selected_model,
     
    46544669            if ($testing_data !== null) {
    46554670                $response_data['testing_data'] = $testing_data;
    4656                 //error_log("MxChat Testing: Added testing data to OpenAI error fallback");
    46574671            }
    46584672           
     
    46724686       
    46734687    } catch (Exception $e) {
    4674         //error_log("MxChat OpenAI streaming exception: " . $e->getMessage());
    4675        
    46764688        // Fallback to regular response
    46774689        $regular_response = $this->mxchat_generate_response_openai(
     
    46904702        if ($testing_data !== null) {
    46914703            $response_data['testing_data'] = $testing_data;
    4692             //error_log("MxChat Testing: Added testing data to OpenAI exception fallback");
    46934704        }
    46944705       
     
    47944805        $full_response = ''; // Accumulate full response for saving
    47954806        $stream_started = false;
     4807        $buffer = ''; // CRITICAL: Add persistent buffer for incomplete chunks
    47964808
    47974809        // Buffer control for real-time streaming
    4798         curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, $testing_data) {
     4810        curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, &$buffer, $testing_data) {
    47994811            // Send testing data as the first event if available
    48004812            if (!$stream_started && $testing_data !== null) {
     
    48054817            }
    48064818           
    4807             // Process each chunk of data
    4808             $lines = explode("\n", $data);
     4819            // CRITICAL FIX: Append new data to buffer
     4820            $buffer .= $data;
     4821           
     4822            // Process complete lines only
     4823            $lines = explode("\n", $buffer);
     4824           
     4825            // CRITICAL FIX: Keep the last incomplete line in the buffer
     4826            // The last element might be incomplete, so keep it in buffer
     4827            $buffer = array_pop($lines);
    48094828
    48104829            foreach ($lines as $line) {
     
    48224841                    $json_str = substr($line, 6); // Remove 'data: ' prefix
    48234842
    4824                     $json = json_decode($json_str, true);
     4843                    $json = json_decode(trim($json_str), true);
    48254844                    if (json_last_error() !== JSON_ERROR_NONE) {
    48264845                        continue;
     
    50145033        $full_response = ''; // Accumulate full response for saving
    50155034        $stream_started = false;
     5035        $buffer = ''; // CRITICAL: Add persistent buffer for incomplete chunks
    50165036       
    50175037        // Buffer control for real-time streaming
    5018         curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, $testing_data) {
     5038        curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, &$buffer, $testing_data) {
    50195039            // Send testing data as the first event if available
    50205040            if (!$stream_started && $testing_data !== null) {
     
    50255045            }
    50265046           
    5027             // Process each chunk of data
    5028             $lines = explode("\n", $data);
     5047            // CRITICAL FIX: Append new data to buffer
     5048            $buffer .= $data;
     5049           
     5050            // Process complete lines only
     5051            $lines = explode("\n", $buffer);
     5052           
     5053            // CRITICAL FIX: Keep the last incomplete line in the buffer
     5054            // The last element might be incomplete, so keep it in buffer
     5055            $buffer = array_pop($lines);
    50295056           
    50305057            foreach ($lines as $line) {
    5031                 if (trim($line) === '' || strpos($line, 'data: ') !== 0) {
     5058                // Skip empty lines
     5059                if (trim($line) === '') {
     5060                    continue;
     5061                }
     5062               
     5063                // Only process lines that start with "data: "
     5064                if (strpos($line, 'data: ') !== 0) {
    50325065                    continue;
    50335066                }
     
    50355068                $json_str = substr($line, 6); // Remove 'data: ' prefix
    50365069               
    5037                 if ($json_str === '[DONE]') {
     5070                if (trim($json_str) === '[DONE]') {
    50385071                    echo "data: [DONE]\n\n";
    50395072                    flush();
     
    50415074                }
    50425075               
    5043                 $json = json_decode($json_str, true);
    5044                 if (isset($json['choices'][0]['delta']['content'])) {
     5076                // Try to decode JSON
     5077                $json = json_decode(trim($json_str), true);
     5078                if ($json && isset($json['choices'][0]['delta']['content'])) {
    50455079                    $content = $json['choices'][0]['delta']['content'];
    50465080                    $full_response .= $content; // Accumulate
     
    52085242        $full_response = ''; // Accumulate full response for saving
    52095243        $stream_started = false;
     5244        $buffer = ''; // CRITICAL: Add persistent buffer for incomplete chunks
    52105245       
    52115246        // Buffer control for real-time streaming
    5212         curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, $testing_data) {
     5247        curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$full_response, &$stream_started, &$buffer, $testing_data) {
    52135248            // Send testing data as the first event if available
    52145249            if (!$stream_started && $testing_data !== null) {
     
    52195254            }
    52205255           
    5221             // Process each chunk of data
    5222             $lines = explode("\n", $data);
     5256            // CRITICAL FIX: Append new data to buffer
     5257            $buffer .= $data;
     5258           
     5259            // Process complete lines only
     5260            $lines = explode("\n", $buffer);
     5261           
     5262            // CRITICAL FIX: Keep the last incomplete line in the buffer
     5263            // The last element might be incomplete, so keep it in buffer
     5264            $buffer = array_pop($lines);
    52235265           
    52245266            foreach ($lines as $line) {
    5225                 if (trim($line) === '' || strpos($line, 'data: ') !== 0) {
     5267                // Skip empty lines
     5268                if (trim($line) === '') {
     5269                    continue;
     5270                }
     5271               
     5272                // Only process lines that start with "data: "
     5273                if (strpos($line, 'data: ') !== 0) {
    52265274                    continue;
    52275275                }
     
    52295277                $json_str = substr($line, 6); // Remove 'data: ' prefix
    52305278               
    5231                 if ($json_str === '[DONE]') {
     5279                if (trim($json_str) === '[DONE]') {
    52325280                    echo "data: [DONE]\n\n";
    52335281                    flush();
     
    52355283                }
    52365284               
    5237                 $json = json_decode($json_str, true);
    5238                 if (isset($json['choices'][0]['delta']['content'])) {
     5285                // Try to decode JSON
     5286                $json = json_decode(trim($json_str), true);
     5287                if ($json && isset($json['choices'][0]['delta']['content'])) {
    52395288                    $content = $json['choices'][0]['delta']['content'];
    5240                     $full_response .= $content; // Accumulate
     5289                    $full_response .= $content; // Accumulate the full response
     5290                   
    52415291                    // Send as SSE format
    52425292                    echo "data: " . json_encode(['content' => $content]) . "\n\n";
     
    62896339public function mxchat_enqueue_scripts_styles() {
    62906340    // Define version numbers for the styles and scripts
    6291     $chat_style_version = '2.4.3';
    6292     $chat_script_version = '2.4.3';
     6341    $chat_style_version = '2.4.4';
     6342    $chat_script_version = '2.4.4';
    62936343    // Enqueue the script
    62946344    wp_enqueue_script(
     
    69046954        : 'No system prompt configured';
    69056955   
    6906     // Get selected model
    6907     $selected_model = isset($current_options['model']) ? $current_options['model'] : 'gpt-4o';
     6956    // Get selected model - FIXED: Use $this->options instead of $current_options
     6957    $selected_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-4o';
    69086958   
    69096959    // Get API key status (just check if they exist, don't expose the keys)
     
    69386988    }
    69396989   
    6940     // Get similarity threshold from main options (default 75%)
     6990    // Get similarity threshold from main options (default 35%)
    69416991    $similarity_threshold = isset($this->options['similarity_threshold'])
    69426992        ? ((int) $this->options['similarity_threshold']) / 100
    6943         : 0.75;
     6993        : 0.35;
    69446994   
    69456995    wp_send_json_success([
     
    71127162    $similarity_threshold = isset($this->options['similarity_threshold'])
    71137163        ? ((int) $this->options['similarity_threshold']) / 100
    7114         : 0.75;
     7164        : 0.35;
    71157165   
    71167166    $testing_data['similarity_threshold'] = $similarity_threshold;
  • mxchat-basic/trunk/js/chat-script.js

    r3366492 r3367268  
    480480            // Log the error with code for debugging
    481481            //console.log("Response data:", response.data);
    482             ////console.error("API Error:", errorMessage, "Code:", errorCode);
     482            //console.error("API Error:", errorMessage, "Code:", errorCode);
    483483
    484484            // Format user-friendly error message
     
    12251225   
    12261226    function linkify(inputText) {
    1227     console.log('=== LINKIFY DEBUG START ===');
    1228     console.log('Input to linkify:', inputText);
    1229     console.log('Input type:', typeof inputText);
    1230     console.log('Input length:', inputText ? inputText.length : 'null/undefined');
     1227    //console.log('=== LINKIFY DEBUG START ===');
     1228    //console.log('Input to linkify:', inputText);
     1229    //console.log('Input type:', typeof inputText);
     1230    //console.log('Input length:', inputText ? inputText.length : 'null/undefined');
    12311231   
    12321232    if (!inputText) {
    1233         console.log('Empty input, returning empty string');
     1233        //console.log('Empty input, returning empty string');
    12341234        return '';
    12351235    }
    12361236   
    12371237    // Process markdown headers FIRST (before paragraph wrapping)
    1238     console.log('--- Processing Headers ---');
     1238    //console.log('--- Processing Headers ---');
    12391239    let processedText = formatMarkdownHeaders(inputText);
    1240     console.log('After headers:', processedText);
    1241     console.log('Headers changed:', processedText !== inputText);
     1240    //console.log('After headers:', processedText);
     1241    //console.log('Headers changed:', processedText !== inputText);
    12421242   
    12431243    // Process text styling (bold, italic, strikethrough)
    1244     console.log('--- Processing Text Styling ---');
    1245     const beforeStyling = processedText;
     1244    //console.log('--- Processing Text Styling ---');
     1245    //const beforeStyling = processedText;
    12461246    processedText = formatTextStyling(processedText);
    1247     console.log('After styling:', processedText);
    1248     console.log('Styling changed:', processedText !== beforeStyling);
     1247    //console.log('After styling:', processedText);
     1248    //console.log('Styling changed:', processedText !== beforeStyling);
    12491249   
    12501250    // Process code blocks BEFORE processing links to avoid conflicts
    1251     console.log('--- Processing Code Blocks ---');
     1251    //console.log('--- Processing Code Blocks ---');
    12521252    const beforeCodeBlocks = processedText;
    12531253    processedText = formatCodeBlocks(processedText);
    1254     console.log('After code blocks:', processedText);
    1255     console.log('Code blocks changed:', processedText !== beforeCodeBlocks);
     1254    //console.log('After code blocks:', processedText);
     1255    //console.log('Code blocks changed:', processedText !== beforeCodeBlocks);
    12561256   
    12571257    // NOW convert to paragraphs (this should be AFTER markdown processing)
    1258     console.log('--- Converting to Paragraphs ---');
     1258    //console.log('--- Converting to Paragraphs ---');
    12591259    const beforeParagraphs = processedText;
    12601260    processedText = convertNewlinesToBreaks(processedText);
    1261     console.log('After paragraph conversion:', processedText);
    1262     console.log('Paragraphs changed:', processedText !== beforeParagraphs);
     1261    //console.log('After paragraph conversion:', processedText);
     1262    //console.log('Paragraphs changed:', processedText !== beforeParagraphs);
    12631263   
    12641264    // Process markdown links
    1265     console.log('--- Processing Markdown Links ---');
     1265    //console.log('--- Processing Markdown Links ---');
    12661266    const beforeMarkdownLinks = processedText;
    12671267    const markdownLinkPattern = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
    12681268    processedText = processedText.replace(markdownLinkPattern, (match, text, url) => {
    1269         console.log('Found markdown link:', match, 'text:', text, 'url:', url);
     1269        //console.log('Found markdown link:', match, 'text:', text, 'url:', url);
    12701270        const safeUrl = encodeURI(url);
    12711271        const safeText = sanitizeUserInput(text);
    12721272        return `<a href="${safeUrl}" target="${linkTarget}">${safeText}</a>`;
    12731273    });
    1274     console.log('After markdown links:', processedText);
    1275     console.log('Markdown links changed:', processedText !== beforeMarkdownLinks);
     1274    //console.log('After markdown links:', processedText);
     1275    //console.log('Markdown links changed:', processedText !== beforeMarkdownLinks);
    12761276
    12771277    // Process phone numbers (tel:)
    1278     console.log('--- Processing Phone Numbers ---');
     1278    //console.log('--- Processing Phone Numbers ---');
    12791279    const beforePhone = processedText;
    12801280    const phonePattern = /\[([^\]]+)\]\((tel:[\d+\-\s()]+)\)/g;
    12811281    processedText = processedText.replace(phonePattern, (match, text, phone) => {
    1282         console.log('Found phone link:', match, 'text:', text, 'phone:', phone);
     1282        //console.log('Found phone link:', match, 'text:', text, 'phone:', phone);
    12831283        const safePhone = encodeURI(phone);
    12841284        const safeText = sanitizeUserInput(text);
    12851285        return `<a href="${safePhone}">${safeText}</a>`;
    12861286    });
    1287     console.log('After phone numbers:', processedText);
    1288     console.log('Phone numbers changed:', processedText !== beforePhone);
     1287    //console.log('After phone numbers:', processedText);
     1288    //console.log('Phone numbers changed:', processedText !== beforePhone);
    12891289
    12901290    // Process mailto links
    1291     console.log('--- Processing Mailto Links ---');
     1291    //console.log('--- Processing Mailto Links ---');
    12921292    const beforeMailto = processedText;
    12931293    const mailtoPattern = /\[([^\]]+)\]\((mailto:[^\)]+)\)/g;
     
    12981298        return `<a href="${safeMailto}">${safeText}</a>`;
    12991299    });
    1300     console.log('After mailto links:', processedText);
    1301     console.log('Mailto links changed:', processedText !== beforeMailto);
     1300    //console.log('After mailto links:', processedText);
     1301    //console.log('Mailto links changed:', processedText !== beforeMailto);
    13021302
    13031303    // Process standalone URLs (avoid already processed links)
    1304     console.log('--- Processing Standalone URLs ---');
     1304   //console.log('--- Processing Standalone URLs ---');
    13051305    const beforeStandaloneUrls = processedText;
    13061306    const urlPattern = /(^|[^">])(https?:\/\/[^\s<]+)(?![^<]*<\/a>)/gim;
    13071307    processedText = processedText.replace(urlPattern, (match, prefix, url) => {
    1308         console.log('Found standalone URL:', match, 'prefix:', prefix, 'url:', url);
     1308        //console.log('Found standalone URL:', match, 'prefix:', prefix, 'url:', url);
    13091309        const safeUrl = encodeURI(url);
    13101310        return `${prefix}<a href="${safeUrl}" target="${linkTarget}">${url}</a>`;
    13111311    });
    1312     console.log('After standalone URLs:', processedText);
    1313     console.log('Standalone URLs changed:', processedText !== beforeStandaloneUrls);
     1312    //console.log('After standalone URLs:', processedText);
     1313    //console.log('Standalone URLs changed:', processedText !== beforeStandaloneUrls);
    13141314   
    13151315    // Process www. URLs (avoid already processed links)
    1316     console.log('--- Processing WWW URLs ---');
     1316    //console.log('--- Processing WWW URLs ---');
    13171317    const beforeWwwUrls = processedText;
    13181318    const wwwPattern = /(^|[^">])(www\.[\S]+(\b|$))(?![^<]*<\/a>)/gim;
    13191319    processedText = processedText.replace(wwwPattern, (match, prefix, url) => {
    1320         console.log('Found www URL:', match, 'prefix:', prefix, 'url:', url);
     1320        //console.log('Found www URL:', match, 'prefix:', prefix, 'url:', url);
    13211321        const safeUrl = encodeURI(`http://${url}`);
    13221322        return `${prefix}<a href="${safeUrl}" target="${linkTarget}">${url}</a>`;
    13231323    });
    1324     console.log('After www URLs:', processedText);
    1325     console.log('WWW URLs changed:', processedText !== beforeWwwUrls);
    1326 
    1327     console.log('=== FINAL RESULT ===');
    1328     console.log('Final processed text:', processedText);
    1329     console.log('Total transformation:', inputText !== processedText);
    1330     console.log('=== LINKIFY DEBUG END ===');
     1324    //console.log('After www URLs:', processedText);
     1325    //console.log('WWW URLs changed:', processedText !== beforeWwwUrls);
     1326
     1327    //console.log('=== FINAL RESULT ===');
     1328    //console.log('Final processed text:', processedText);
     1329    //console.log('Total transformation:', inputText !== processedText);
     1330    //console.log('=== LINKIFY DEBUG END ===');
    13311331   
    13321332    return processedText;
  • mxchat-basic/trunk/mxchat-basic.php

    r3366492 r3367268  
    33 * Plugin Name: MxChat
    44 * Description: AI chatbot for WordPress with OpenAI, Claude, xAI, DeepSeek, live agent, PDF uploads, WooCommerce, and training on website data.
    5  * Version: 2.4.3
     5 * Version: 2.4.4
    66 * Author: MxChat
    77 * Author URI: https://mxchat.ai
     
    1717
    1818// Define plugin version constant for asset versioning
    19 define('MXCHAT_VERSION', '2.4.3');
     19define('MXCHAT_VERSION', '2.4.4');
    2020
    2121function mxchat_load_textdomain() {
     
    468468            }
    469469           
    470             // NEW: Run enabled_bots column migration for 2.4.3
    471             if (version_compare($current_version, '2.4.3', '<')) {
     470            // NEW: Run enabled_bots column migration for 2.4.4
     471            if (version_compare($current_version, '2.4.4', '<')) {
    472472                mxchat_add_enabled_bots_column();
    473473            }
  • mxchat-basic/trunk/readme.txt

    r3366492 r3367268  
    66Tested up to: 6.8
    77Requires PHP: 7.2
    8 Stable tag: 2.4.3
     8Stable tag: 2.4.4
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    1414== Description ==
    1515
    16 [Documentation](https://mxchat.ai/documentation/) | [MxChat Pro](https://mxchat.ai/)
    17 
    18 ### 🎥 Product Demo Videos:
    19 - [AI Theme Generator Add-On](https://www.youtube.com/watch?v=rSQDW2qbtRU&t) - Transform your chatbot's appearance in seconds with AI-powered design
    20 - [Admin Assistant Add-On](https://www.youtube.com/watch?v=AdEA1k-UCFM) - ChatGPT-like experience directly inside your WordPress dashboard
    21 - [WooCommerce Add-On](https://www.youtube.com/watch?v=WsqAppHRGdA) - Display product cards, recommendations, and supercharge your store
    22 - [MxChat Forms Add-On](https://www.youtube.com/watch?v=3MrWy5dRalA&t) - Convert conversations into data collection with smart forms that trigger during chats
    23 - [Chat with PDF & Word](https://www.youtube.com/watch?v=j_c45WWCTG0) - Let users upload and interact with documents
    24 
    25 [Explore all product videos on YouTube](https://www.youtube.com/@MxChat/videos)
     16[Documentation](https://mxchat.ai/documentation/)
     17
     18### 📦 Optional Premium Add-Ons 
     19Extend the free plugin with these optional premium features: 
     20
     21- [Forms Action Add-On](https://mxchat.ai/forms-action/) – Capture leads and data with custom in-chat forms 
     22- [WooCommerce Add-On](https://mxchat.ai/woocommerce/) – AI-powered shopping assistance and product recommendations 
     23- [AI Theme Customizer Add-On](https://mxchat.ai/ai-theme-customizer/) – Instantly design chatbot themes with natural language 
     24- [Multi-Bot Add-On](https://mxchat.ai/multi-bot/) – Run unlimited AI chatbots with custom knowledge and personalities 
     25- [Image Analysis Add-On](https://mxchat.ai/image-analysis/) – Enable AI-powered image analysis and OCR inside chats 
     26
     27👉 [Visit our website to view all add-ons](https://mxchat.ai) 
     28
     29### 🎥 Product Demo Videos 
     30[Explore all product videos on YouTube](https://www.youtube.com/@MxChat/videos) 
    2631
    2732## Why Choose MxChat AI Chatbot for Your WordPress Website?
     
    3439✅ **Extensive Add-On Ecosystem**: Forms, moderation, recommendations, theme customization, and more 
    3540
    36 ## 🔥 What's New in Version 2.4.2
    37 🤖 **NEW: Multi-Bot Manager Add-on Support** – Create and manage multiple specialized chatbots with dedicated knowledge databases for different purposes (support, sales, technical, etc.). Each bot can have its own Pinecone configuration and settings. 
     41## 🔥 What's New in Version 2.4.4 
     42
     43🐞 **Bug Fixes** 
     44- Default similarity is now accurate across all settings 
     45- Improved streaming responses to prevent dropped characters or words 
     46
     47⚡ **Enhancements** 
     48- Removed unnecessary Pinecone caching in the knowledge database for more accurate results 
    3849
    3950## Core Features That Set MxChat Apart
     
    171182== Changelog ==
    172183
     184= 2.4.4 - September 24, 2025 =
     185- Bug Fix: Default similarity is now accurate across all settings. 
     186- Bug Fix: Improved streaming responses to prevent dropped characters or words. 
     187- Enhanced: Removed unnecessary Pinecone caching in the knowledge database for more accurate results. 
     188
    173189= 2.4.3 - September 23, 2025 =
    174190- Added: Support for upcoming multi-bot update that allows for more customized settings such as individual chat models.
     
    532548== Upgrade Notice ==
    533549
    534 = 2.4.3 =
    535 - Added: Support for upcoming multi-bot update that allows for more customized settings such as individual chat models.
    536 - Improved: CSS for chatbot UI & more robust markdown support.
     550= 2.4.4 =
     551This update fixes similarity accuracy issues, improves streaming responses, and enhances knowledge database accuracy. Recommended for all users. 
    537552
    538553== License & Warranty ==
Note: See TracChangeset for help on using the changeset viewer.