Plugin Directory

Changeset 3459102


Ignore:
Timestamp:
02/11/2026 03:48:47 PM (9 days ago)
Author:
mxchat
Message:

3.0.6 - February 11, 2026

New: RAG Sources Limit slider, Claude Opus 4.6/4.5 models, {visitor_name} placeholder support. Deprecated OpenAI & Claude models auto-migrated.

Location:
mxchat-basic
Files:
127 added
11 edited

Legend:

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

    r3448781 r3459102  
    9595                            'grok-3-mini-fast-beta', 'grok-2',
    9696                            'deepseek-chat',
     97                            'claude-opus-4-6', 'claude-opus-4-5',
    9798                            'claude-sonnet-4-5-20250929', 'claude-opus-4-1-20250805', 'claude-haiku-4-5-20251001',
    98                             'claude-opus-4-20250514', 'claude-sonnet-4-20250514', 'claude-3-7-sonnet-20250219',
    99                             'claude-3-5-sonnet-20241022', 'claude-3-opus-20240229', 'claude-3-sonnet-20240229',
    100                             'claude-3-haiku-20240307',
    101                             'gpt-5.2', 'gpt-5.1-2025-11-13', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano', 'gpt-4.1-2025-04-14',
    102                             'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo',
     99                            'claude-opus-4-20250514', 'claude-sonnet-4-20250514',
     100                            'gpt-5.2', 'gpt-5.1-chat-latest', 'gpt-5.1-2025-11-13', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano',
    103101                        );
    104102               
     
    165163        case 'similarity_threshold':
    166164            //error_log('MXChat Save: Processing similarity_threshold');
    167             // Save to the options array
    168             $options[$name] = $value;
     165            // Validate and save - enforce min 20, max 85
     166            $threshold = intval($value);
     167            if ($threshold < 20) $threshold = 20;
     168            if ($threshold > 85) $threshold = 85;
     169            $options[$name] = $threshold;
     170            break;
     171        case 'rag_sources_limit':
     172            //error_log('MXChat Save: Processing rag_sources_limit');
     173            // Validate and save - enforce min 3, max 10, default 6
     174            $rag_limit = intval($value);
     175            if ($rag_limit < 3) $rag_limit = 3;
     176            if ($rag_limit > 10) $rag_limit = 10;
     177            $options[$name] = $rag_limit;
    169178            break;
    170179        case 'user_message_bg_color':
  • mxchat-basic/trunk/admin/class-knowledge-manager.php

    r3442157 r3459102  
    10311031            }
    10321032        }
    1033        
    1034         // Fallback: Return the body content if no specific selector matches
    1035         $debug("Using body fallback");
     1033
     1034        // Generic container selectors for non-CMS sites (like .asp pages)
     1035        $debug("Trying generic container selectors");
     1036        $generic_selectors = [
     1037            '//div[@id="main"]',
     1038            '//div[@id="wrapper"]',
     1039            '//div[@id="page"]',
     1040            '//div[@id="site-content"]',
     1041            '//div[contains(@class, "main-content")]',
     1042            '//div[contains(@class, "page-content")]',
     1043            '//div[contains(@class, "site-content")]',
     1044        ];
     1045
     1046        foreach ($generic_selectors as $selector) {
     1047            $debug("Trying generic selector: " . $selector);
     1048            $nodes = $xpath->query($selector);
     1049            if ($nodes && $nodes->length > 0) {
     1050                $content = $dom->saveHTML($nodes->item(0));
     1051                if (!empty($content)) {
     1052                    $debug("Returning content from generic selector: " . $selector);
     1053                    return $content;
     1054                }
     1055            }
     1056        }
     1057
     1058        // Paragraph-based content detection - find regions with substantial text
     1059        $debug("Trying paragraph-based content detection");
     1060        $paragraphs = $xpath->query('//p[string-length(normalize-space()) > 50]');
     1061        if ($paragraphs && $paragraphs->length >= 3) {
     1062            $debug("Found " . $paragraphs->length . " substantial paragraphs");
     1063            // Collect all substantial paragraphs and their content
     1064            $paragraph_content = '';
     1065            foreach ($paragraphs as $p) {
     1066                $paragraph_content .= $dom->saveHTML($p) . "\n";
     1067            }
     1068            if (!empty($paragraph_content)) {
     1069                $debug("Returning paragraph-based content");
     1070                return $paragraph_content;
     1071            }
     1072        }
     1073
     1074        // Improved body fallback - strip nav/header/footer elements first
     1075        $debug("Using improved body fallback");
    10361076        $body = $dom->getElementsByTagName('body');
    10371077        if ($body->length > 0) {
    1038             return $dom->saveHTML($body->item(0));
    1039         }
    1040        
     1078            // Clone the body to avoid modifying the original DOM
     1079            $body_clone = $body->item(0)->cloneNode(true);
     1080
     1081            // Remove common non-content elements by tag name
     1082            $remove_tags = ['nav', 'header', 'footer', 'aside', 'script', 'style', 'noscript'];
     1083            foreach ($remove_tags as $tag) {
     1084                $elements = $body_clone->getElementsByTagName($tag);
     1085                // Iterate backwards to safely remove elements
     1086                for ($i = $elements->length - 1; $i >= 0; $i--) {
     1087                    $el = $elements->item($i);
     1088                    if ($el && $el->parentNode) {
     1089                        $el->parentNode->removeChild($el);
     1090                    }
     1091                }
     1092            }
     1093
     1094            // Remove elements with common non-content class names using XPath on the cloned body
     1095            $temp_dom = new DOMDocument();
     1096            @$temp_dom->appendChild($temp_dom->importNode($body_clone, true));
     1097            $temp_xpath = new DOMXPath($temp_dom);
     1098
     1099            $remove_class_patterns = [
     1100                '//*[contains(@class, "nav")]',
     1101                '//*[contains(@class, "menu")]',
     1102                '//*[contains(@class, "sidebar")]',
     1103                '//*[contains(@class, "footer")]',
     1104                '//*[contains(@class, "header")]',
     1105                '//*[contains(@id, "nav")]',
     1106                '//*[contains(@id, "menu")]',
     1107                '//*[contains(@id, "sidebar")]',
     1108                '//*[contains(@id, "footer")]',
     1109                '//*[contains(@id, "header")]',
     1110            ];
     1111
     1112            foreach ($remove_class_patterns as $pattern) {
     1113                $elements = $temp_xpath->query($pattern);
     1114                if ($elements) {
     1115                    for ($i = $elements->length - 1; $i >= 0; $i--) {
     1116                        $el = $elements->item($i);
     1117                        if ($el && $el->parentNode) {
     1118                            $el->parentNode->removeChild($el);
     1119                        }
     1120                    }
     1121                }
     1122            }
     1123
     1124            $cleaned_content = $temp_dom->saveHTML();
     1125            if (!empty($cleaned_content)) {
     1126                $debug("Returning cleaned body content");
     1127                return $cleaned_content;
     1128            }
     1129        }
     1130
    10411131        // Last resort: return the original HTML
    10421132        $debug("Returning original HTML");
  • mxchat-basic/trunk/css/chat-transcripts.css

    r3446370 r3459102  
    832832.mxch-user-info {
    833833    flex: 1;
     834    min-width: 0; /* Allow flex item to shrink below content size */
     835    overflow: hidden;
    834836}
    835837
     
    838840    font-weight: 600;
    839841    color: #111827;
     842    overflow: hidden;
     843    text-overflow: ellipsis;
     844    white-space: nowrap;
    840845}
    841846
     
    844849    color: #6b7280;
    845850    margin-top: 2px;
     851    overflow: hidden;
     852    text-overflow: ellipsis;
     853    white-space: nowrap;
    846854}
    847855
  • mxchat-basic/trunk/includes/admin-knowledge-page.php

    r3448781 r3459102  
    15431543    // Get current chat model to check compatibility
    15441544    $mxchat_options = get_option('mxchat_options', array());
    1545     $current_model = $mxchat_options['model'] ?? 'gpt-4o';
     1545    $current_model = $mxchat_options['model'] ?? 'gpt-5.1-chat-latest';
    15461546    $is_openai_model = preg_match('/^(gpt-|o1-|o3-)/', $current_model);
    15471547    ?>
     
    15561556                <div class="mxch-notice mxch-notice-info" style="margin-bottom: 20px;">
    15571557                    <svg class="mxch-notice-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>
    1558                     <span><strong><?php esc_html_e('Requires OpenAI Chat Model.', 'mxchat'); ?></strong> <?php esc_html_e('Vector Store search only works with OpenAI models (gpt-4o, gpt-4o-mini, etc.). Create Vector Stores in your OpenAI Dashboard.', 'mxchat'); ?></span>
     1558                    <span><strong><?php esc_html_e('Requires OpenAI Chat Model.', 'mxchat'); ?></strong> <?php esc_html_e('Vector Store search only works with OpenAI models (gpt-5.1-chat-latest, gpt-5-mini, etc.). Create Vector Stores in your OpenAI Dashboard.', 'mxchat'); ?></span>
    15591559                </div>
    15601560
  • mxchat-basic/trunk/includes/admin-settings-page.php

    r3444379 r3459102  
    267267                            $admin_instance->mxchat_similarity_threshold_callback();
    268268                        }, __('Adjust threshold for content matching. Lower values = more matches, higher values = stricter matching.', 'mxchat'));
     269
     270                        // RAG Sources Limit
     271                        mxchat_render_field_wrapper('rag_sources_limit', __('RAG Sources Limit', 'mxchat'), function() use ($admin_instance) {
     272                            $admin_instance->mxchat_rag_sources_limit_callback();
     273                        }, __('Number of knowledge base sources (pages/documents) to include in AI context. Higher values provide more context but use more tokens.', 'mxchat'));
    269274
    270275                        // Contextual Awareness
  • mxchat-basic/trunk/includes/class-mxchat-admin.php

    r3448781 r3459102  
    128128        - When knowledge base information is unclear or contradictory, acknowledge the limitation rather than guessing
    129129        - Better to admit insufficient information than provide inaccurate answers',
    130         'model' => esc_html__('gpt-4o', 'mxchat'),
     130        'model' => esc_html__('gpt-5.1-chat-latest', 'mxchat'),
    131131        'rate_limit_logged_out' => esc_html__('100', 'mxchat'),
    132132        'role_rate_limits' => array(),
     
    307307    // Get user's selected model and API key
    308308    $options = get_option('mxchat_options', []);
    309     $selected_model = $options['model'] ?? 'gpt-4o';
     309    $selected_model = $options['model'] ?? 'gpt-5.1-chat-latest';
    310310
    311311    // Get the provider from the model
     
    15531553    // Get user's selected model and determine provider
    15541554    $options = get_option('mxchat_options', []);
    1555     $selected_model = $options['model'] ?? 'gpt-4o';
     1555    $selected_model = $options['model'] ?? 'gpt-5.1-chat-latest';
    15561556
    15571557    // Check if using OpenRouter
     
    45754575    );
    45764576
     4577    // RAG Sources Limit Slider
     4578    add_settings_field(
     4579        'rag_sources_limit', // Field ID
     4580        esc_html__('RAG Sources Limit', 'mxchat'), // Field title
     4581        array($this, 'mxchat_rag_sources_limit_callback'), // Callback function
     4582        'mxchat-chatbot', // Page
     4583        'mxchat_chatbot_section' // Section
     4584    );
     4585
    45774586    add_settings_field(
    45784587        'append_to_body',
     
    55745583        $instructions
    55755584    );
     5585    // Personalization hint
     5586    echo '<p class="description" style="margin-top: 8px;">';
     5587    echo esc_html__('Use {visitor_name} to personalize AI responses when lead capture is enabled.', 'mxchat') . '<br>';
     5588    echo '<code style="font-size: 12px;">' . esc_html__('Example: The visitor\'s name is {visitor_name}. Address them by name.', 'mxchat') . '</code>';
     5589    echo '</p>';
    55765590    // Sample instructions button
    55775591    echo '<div class="mxchat-instructions-container">';
     
    56815695        ),
    56825696        esc_html__('Claude Models', 'mxchat') => array(
     5697            'claude-opus-4-6' => esc_html__('Claude Opus 4.6 (Most Capable - Recommended)', 'mxchat'),
     5698            'claude-opus-4-5' => esc_html__('Claude Opus 4.5 (Highly Capable)', 'mxchat'),
    56835699            'claude-sonnet-4-5-20250929' => esc_html__('Claude Sonnet 4.5 (Best for Agents & Coding)', 'mxchat'),
    56845700            'claude-opus-4-1-20250805' => esc_html__('Claude Opus 4.1 (Exceptional for Complex Tasks)', 'mxchat'),
    56855701            'claude-haiku-4-5-20251001' => esc_html__('Claude Haiku 4.5 (Fastest & Most Intelligent)', 'mxchat'),
    5686             'claude-opus-4-20250514' => esc_html__('Claude 4 Opus (Most Capable)', 'mxchat'),
     5702            'claude-opus-4-20250514' => esc_html__('Claude 4 Opus (Complex Tasks)', 'mxchat'),
    56875703            'claude-sonnet-4-20250514' => esc_html__('Claude 4 Sonnet (High Performance)', 'mxchat'),
    5688             'claude-3-7-sonnet-20250219' => esc_html__('Claude 3.7 Sonnet (High Intelligence)', 'mxchat'),
    5689             'claude-3-opus-20240229' => esc_html__('Claude 3 Opus (Complex Tasks)', 'mxchat'),
    5690             'claude-3-sonnet-20240229' => esc_html__('Claude 3 Sonnet (Balanced)', 'mxchat'),
    5691             'claude-3-haiku-20240307' => esc_html__('Claude 3 Haiku (Fastest)', 'mxchat'),
    56925704        ),
    56935705        esc_html__('OpenAI Models', 'mxchat') => array(
    5694             //  GPT-5 family
    56955706            'gpt-5.2' => esc_html__('GPT-5.2 (Best General-Purpose & Agentic Model)', 'mxchat'),
     5707            'gpt-5.1-chat-latest' => esc_html__('GPT-5.1 Chat Latest (Recommended)', 'mxchat'),
    56965708            'gpt-5.1-2025-11-13' => esc_html__('GPT-5.1 (Flagship for Coding & Agentic Tasks)', 'mxchat'),
    56975709            'gpt-5' => esc_html__('GPT-5 (Flagship for Coding, Reasoning & Agents)', 'mxchat'),
    5698             'gpt-5-mini' => esc_html__('GPT-5 Mini (Faster, Cost-Efficient for Precise Prompts)', 'mxchat'),
     5710            'gpt-5-mini' => esc_html__('GPT-5 Mini (Fast and Lightweight)', 'mxchat'),
    56995711            'gpt-5-nano' => esc_html__('GPT-5 Nano (Fastest & Cheapest for Summarization/Classification)', 'mxchat'),
    5700 
    5701             // Existing OpenAI models
    5702             'gpt-4.1-2025-04-14' => esc_html__('GPT-4.1 (Flagship for Complex Tasks)', 'mxchat'),
    5703             'gpt-4o' => esc_html__('GPT-4o (Recommended)', 'mxchat'),
    5704             'gpt-4o-mini' => esc_html__('GPT-4o Mini (Fast and Lightweight)', 'mxchat'),
    5705             'gpt-4-turbo' => esc_html__('GPT-4 Turbo (High-Performance)', 'mxchat'),
    5706             'gpt-4' => esc_html__('GPT-4 (High Intelligence)', 'mxchat'),
    5707             'gpt-3.5-turbo' => esc_html__('GPT-3.5 Turbo (Affordable and Fast)', 'mxchat'),
    57085712        ),
    57095713    );
    57105714
    57115715    // Retrieve the currently selected model from saved options
    5712     $selected_model = isset($this->options['model']) ? esc_attr($this->options['model']) : 'gpt-4o';
     5716    $selected_model = isset($this->options['model']) ? esc_attr($this->options['model']) : 'gpt-5.1-chat-latest';
    57135717
    57145718    // Begin the select dropdown
     
    58355839
    58365840    // Get current model to determine if we should show/enable the toggle
    5837     $current_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-4o';
     5841    $current_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-5.1-chat-latest';
    58385842
    58395843    // Models that DON'T support web search (per OpenAI docs)
     
    58435847    // Check if current model is an OpenAI model that supports web search
    58445848    $openai_models = array(
    5845         'gpt-5.2', 'gpt-5.1-2025-11-13', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano',
    5846         'gpt-4.1-2025-04-14', 'gpt-4o', 'gpt-4o-mini', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo'
     5849        'gpt-5.2', 'gpt-5.1-chat-latest', 'gpt-5.1-2025-11-13', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano'
    58475850    );
    58485851
     
    60796082    ?>
    60806083    <textarea id="intro_message" name="intro_message" rows="5" cols="50"><?php echo $saved_message; ?></textarea>
     6084    <p class="description" style="margin-top: 8px;">
     6085        <?php esc_html_e('Use {visitor_name} to personalize greetings when lead capture is enabled.', 'mxchat'); ?><br>
     6086        <code style="font-size: 12px;"><?php esc_html_e('Example: Hello {visitor_name}! How can I help you today?', 'mxchat'); ?></code>
     6087    </p>
    60816088    <?php
    60826089}
     
    72417248    $options = get_option('mxchat_options', []);
    72427249
    7243     // Get value from options array with default of 80
     7250    // Get value from options array with default of 35
    72447251    $threshold = isset($options['similarity_threshold']) ? $options['similarity_threshold'] : 35;
    72457252
     
    72617268    );
    72627269    echo '</div>';
    7263     echo '<p class="description">';
    7264     echo esc_html__('Adjust similarity threshold for optimal content matching. Too high may limit knowledge retrieval. We highly recommend using the MxChat Debugger found on the left side of your website when logged in as admin while testing the bot.', 'mxchat');
    7265     echo '</p>';
     7270}
     7271
     7272public function mxchat_rag_sources_limit_callback() {
     7273    // Load from mxchat_options array
     7274    $options = get_option('mxchat_options', []);
     7275
     7276    // Get value from options array with default of 6
     7277    $rag_sources_limit = isset($options['rag_sources_limit']) ? intval($options['rag_sources_limit']) : 6;
     7278
     7279    echo '<div class="slider-container">';
     7280    echo sprintf(
     7281        '<input type="range"
     7282               id="rag_sources_limit"
     7283               name="rag_sources_limit"
     7284               min="3"
     7285               max="10"
     7286               step="1"
     7287               value="%s"
     7288               class="range-slider" />',
     7289        esc_attr($rag_sources_limit)
     7290    );
     7291    echo sprintf(
     7292        '<span id="rag_sources_limit_value" class="range-value">%s</span>',
     7293        esc_html($rag_sources_limit)
     7294    );
     7295    echo '</div>';
    72667296}
    72677297
     
    75247554    }
    75257555
     7556    if (isset($input['rag_sources_limit'])) {
     7557        $new_input['rag_sources_limit'] = absint($input['rag_sources_limit']); // Ensure it's an integer
     7558        $new_input['rag_sources_limit'] = min(max($new_input['rag_sources_limit'], 3), 10); // Enforce range 3-10
     7559    }
     7560
    75267561    if (isset($input['xai_api_key'])) {
    75277562        $new_input['xai_api_key'] = sanitize_text_field($input['xai_api_key']);
     
    77387773            'grok-2',
    77397774            'deepseek-chat',
     7775            'claude-opus-4-6',
     7776            'claude-opus-4-5',
    77407777            'claude-sonnet-4-5-20250929',
    77417778            'claude-opus-4-1-20250805',
     
    77437780            'claude-opus-4-20250514',
    77447781            'claude-sonnet-4-20250514',
    7745             'claude-3-7-sonnet-20250219',
    7746             // REMOVED: 'claude-3-5-sonnet-20241022',
    7747             'claude-3-opus-20240229',
    7748             'claude-3-sonnet-20240229',
    7749             'claude-3-haiku-20240307',
    77507782            'gpt-5.2',
     7783            'gpt-5.1-chat-latest',
    77517784            'gpt-5.1-2025-11-13',
    77527785            'gpt-5',
    77537786            'gpt-5-mini',
    77547787            'gpt-5-nano',
    7755             'gpt-4.1-2025-04-14',
    7756             'gpt-4o',
    7757             'gpt-4o-mini',
    7758             'gpt-4-turbo',
    7759             'gpt-4',
    7760             'gpt-3.5-turbo',
    77617788        );
    7762        
     7789
    77637790        if (in_array($input['model'], $allowed_models)) {
    77647791            $new_input['model'] = sanitize_text_field($input['model']);
    77657792        } else {
    77667793            // Fallback for any deprecated model
    7767             $new_input['model'] = 'claude-3-7-sonnet-20250219';
     7794            $new_input['model'] = 'gpt-5.1-chat-latest';
    77687795        }
    77697796    }
  • mxchat-basic/trunk/includes/class-mxchat-integrator.php

    r3446370 r3459102  
    185185    wp_die();
    186186}
    187 private function mxchat_fetch_conversation_history_for_ai($session_id) {
     187private function mxchat_fetch_conversation_history_for_ai($session_id, $session_start_timestamp = 0) {
    188188    $history = get_option("mxchat_history_{$session_id}", []);
     189
     190    // Check persistence setting - when OFF, only include messages from current page load
     191    $options = get_option('mxchat_options', []);
     192    $persistence_enabled = isset($options['chat_persistence_toggle']) && $options['chat_persistence_toggle'] === 'on';
     193
     194    // Filter history when persistence is OFF to match what the user sees
     195    if (!$persistence_enabled && $session_start_timestamp > 0) {
     196        $history = array_filter($history, function($entry) use ($session_start_timestamp) {
     197            // Include messages from this page load onwards
     198            return isset($entry['timestamp']) && $entry['timestamp'] >= $session_start_timestamp;
     199        });
     200        // Re-index array after filtering
     201        $history = array_values($history);
     202    }
     203
    189204    $formatted_history = [];
    190205
     
    15771592
    15781593        // If we get here, no intent matched OR the intent didn't provide a usable response
    1579        
     1594
    15801595        // Step 4: Generate AI response
    1581         $conversation_history = $this->mxchat_fetch_conversation_history_for_ai($session_id);
     1596        // Get session start timestamp - when persistence is OFF, only include messages from this page load
     1597        $session_start_timestamp = isset($_POST['session_start_timestamp']) ? intval($_POST['session_start_timestamp']) : 0;
     1598        $conversation_history = $this->mxchat_fetch_conversation_history_for_ai($session_id, $session_start_timestamp);
    15821599        $this->mxchat_increment_chat_count();
    15831600       
     
    16671684        $citation_links_enabled = isset($fresh_options['citation_links_toggle']) ? ($fresh_options['citation_links_toggle'] === 'on') : true;
    16681685
    1669         $system_instructions = $this->get_system_instructions($bot_id);
     1686        $system_instructions = $this->get_system_instructions($bot_id, $session_id);
    16701687        if ($citation_links_enabled && !empty($system_instructions)) {
    16711688            preg_match_all(
     
    17531770
    17541771        // Extract model from current options for bot-specific model support
    1755         $selected_model = isset($current_options['model']) ? $current_options['model'] : 'gpt-4o';
     1772        $selected_model = isset($current_options['model']) ? $current_options['model'] : 'gpt-5.1-chat-latest';
    17561773       
    17571774        $response = $this->mxchat_generate_response(
     
    25352552    // Get options and determine the selected model
    25362553    $options = $this->options ?? get_option('mxchat_options');
    2537     $selected_model = isset($options['model']) ? $options['model'] : 'gpt-4o';
     2554    $selected_model = isset($options['model']) ? $options['model'] : 'gpt-5.1-chat-latest';
    25382555   
    25392556    // Extract model prefix to determine the provider
     
    25852602 * Interpret query using OpenAI models
    25862603 */
    2587 private function interpret_query_with_openai($user_query, $system_prompt, $api_key, $model = 'gpt-4o') {
     2604private function interpret_query_with_openai($user_query, $system_prompt, $api_key, $model = 'gpt-5.1-chat-latest') {
    25882605    $url = 'https://api.openai.com/v1/chat/completions';
    25892606    $args = [
     
    44384455        $mxchat_options = get_option('mxchat_options', array());
    44394456        $current_options = !empty($bot_options) ? $bot_options : $mxchat_options;
    4440         $selected_model = $current_options['model'] ?? 'gpt-4o';
     4457        $selected_model = $current_options['model'] ?? 'gpt-5.1-chat-latest';
    44414458
    44424459        if ($this->is_openai_chat_model($selected_model)) {
     
    46534670    });
    46544671
    4655     // Take top 3 unique URLs
    4656     $top_urls = array_slice($url_groups, 0, 3, true);
     4672    // Get RAG sources limit from options (default 6, min 3, max 10)
     4673    $rag_sources_limit = isset($options['rag_sources_limit']) ? intval($options['rag_sources_limit']) : 6;
     4674    if ($rag_sources_limit < 3) $rag_sources_limit = 3;
     4675    if ($rag_sources_limit > 10) $rag_sources_limit = 10;
     4676
     4677    // Take top N unique URLs based on user setting
     4678    $top_urls = array_slice($url_groups, 0, $rag_sources_limit, true);
    46574679
    46584680    // Track which document IDs are used for context
     
    46804702    $content = '';
    46814703    $matches_used = 0;
     4704    $total_chunks_used = 0;
     4705    $max_total_chunks = 30; // Hard cap on total chunks to prevent excessive token usage
    46824706
    46834707    // Check if citation links are enabled (default to 'on' for backwards compatibility)
     
    46884712    // Build content from top URLs
    46894713    foreach ($top_urls as $source_url => $group) {
     4714        // Stop if we've hit the total chunk limit
     4715        if ($total_chunks_used >= $max_total_chunks) {
     4716            break;
     4717        }
     4718
    46904719        $full_text = '';
     4720        $chunks_in_this_source = 1; // Default for non-chunked content
    46914721
    46924722        if ($group['is_chunked']) {
    4693             // Fetch all chunks for this URL and reassemble
    4694             $full_text = $this->reassemble_chunks_from_wordpress($source_url);
     4723            // Calculate how many chunks we can still use
     4724            $chunks_remaining = $max_total_chunks - $total_chunks_used;
     4725
     4726            // Fetch chunks for this URL with limit
     4727            $full_text = $this->reassemble_chunks_from_wordpress($source_url, $chunks_remaining, $chunks_in_this_source);
    46954728
    46964729            // If fetching all chunks fails, fall back to matched chunks
     
    47024735
    47034736                $chunk_texts = array();
     4737                $chunks_in_this_source = 0;
    47044738                foreach ($group['chunks'] as $chunk) {
     4739                    if ($total_chunks_used + $chunks_in_this_source >= $max_total_chunks) {
     4740                        break;
     4741                    }
    47054742                    $chunk_texts[] = $chunk['text'];
     4743                    $chunks_in_this_source++;
    47064744                }
    47074745                $full_text = implode("\n\n", $chunk_texts);
     
    47094747        } else {
    47104748            $full_text = $group['single_text'];
     4749            $chunks_in_this_source = 1;
    47114750        }
    47124751
     
    47404779
    47414780            $matches_used++;
     4781            $total_chunks_used += $chunks_in_this_source;
    47424782        }
    47434783    }
     
    47724812
    47734813/**
    4774  * Fetch and reassemble all chunks for a URL from WordPress database
     4814 * Fetch and reassemble chunks for a URL from WordPress database
    47754815 *
    47764816 * @param string $source_url The source URL to fetch chunks for
    4777  * @return string Reassembled content from all chunks
     4817 * @param int $max_chunks Maximum number of chunks to return (0 = unlimited)
     4818 * @param int &$chunk_count Reference to store the actual number of chunks returned
     4819 * @return string Reassembled content from chunks
    47784820 */
    4779 private function reassemble_chunks_from_wordpress($source_url) {
     4821private function reassemble_chunks_from_wordpress($source_url, $max_chunks = 0, &$chunk_count = 0) {
    47804822    global $wpdb;
    47814823    $table = $wpdb->prefix . 'mxchat_system_prompt_content';
     
    47904832
    47914833    if (empty($rows)) {
     4834        $chunk_count = 0;
    47924835        return '';
    47934836    }
     
    48094852    // Sort by chunk index
    48104853    ksort($chunks);
     4854
     4855    // Apply chunk limit if specified
     4856    if ($max_chunks > 0 && count($chunks) > $max_chunks) {
     4857        $chunks = array_slice($chunks, 0, $max_chunks, true);
     4858    }
     4859
     4860    // Store actual chunk count
     4861    $chunk_count = count($chunks);
    48114862
    48124863    // Reassemble content
     
    48764927    $request_body = array(
    48774928        'vector' => $user_embedding,
    4878         'topK' => 50, // Increased for chunked content grouping - need more candidates to find top 3 unique URLs
     4929        'topK' => 50, // Increased for chunked content grouping - need more candidates to find top N unique URLs
    48794930        'includeMetadata' => true,
    48804931        'includeValues' => true
     
    49615012    $matches_used = 0;
    49625013    $matches_used_for_context = [];
     5014    $total_chunks_used = 0;
     5015    $max_total_chunks = 30; // Hard cap on total chunks to prevent excessive token usage
    49635016
    49645017    // Check if citation links are enabled (default to 'on' for backwards compatibility)
     
    50295082    });
    50305083
    5031     // Take top 3 unique URLs
    5032     $top_urls = array_slice($url_groups, 0, 3, true);
    5033 
    5034     // Track which match IDs are actually used for context (only from top 3 URLs)
     5084    // Get RAG sources limit from options (default 6, min 3, max 10)
     5085    $rag_sources_limit = isset($current_options['rag_sources_limit']) ? intval($current_options['rag_sources_limit']) : 6;
     5086    if ($rag_sources_limit < 3) $rag_sources_limit = 3;
     5087    if ($rag_sources_limit > 10) $rag_sources_limit = 10;
     5088
     5089    // Take top N unique URLs based on user setting
     5090    $top_urls = array_slice($url_groups, 0, $rag_sources_limit, true);
     5091
     5092    // Track which match IDs are actually used for context
    50355093    foreach ($top_urls as $group) {
    50365094        if ($group['is_chunked']) {
     
    50455103    // Build content from top URLs
    50465104    foreach ($top_urls as $source_url => $group) {
     5105        // Stop if we've hit the total chunk limit
     5106        if ($total_chunks_used >= $max_total_chunks) {
     5107            break;
     5108        }
     5109
    50475110        $full_text = '';
     5111        $chunks_in_this_source = 1; // Default for non-chunked content
    50485112
    50495113        if ($group['is_chunked']) {
    5050             // Fetch all chunks for this URL and reassemble
    5051             $full_text = $this->reassemble_chunks_from_pinecone($source_url, $bot_config);
     5114            // Calculate how many chunks we can still use
     5115            $chunks_remaining = $max_total_chunks - $total_chunks_used;
     5116
     5117            // Fetch chunks for this URL with limit
     5118            $full_text = $this->reassemble_chunks_from_pinecone($source_url, $bot_config, $chunks_remaining, $chunks_in_this_source);
    50525119
    50535120            // If fetching all chunks fails, fall back to matched chunks
     
    50595126
    50605127                $chunk_texts = array();
     5128                $chunks_in_this_source = 0;
    50615129                foreach ($group['chunks'] as $chunk) {
     5130                    if ($total_chunks_used + $chunks_in_this_source >= $max_total_chunks) {
     5131                        break;
     5132                    }
    50625133                    $chunk_texts[] = $chunk['text'];
     5134                    $chunks_in_this_source++;
    50635135                }
    50645136                $full_text = implode("\n\n", $chunk_texts);
     
    50665138        } else {
    50675139            $full_text = $group['single_text'];
     5140            $chunks_in_this_source = 1;
    50685141        }
    50695142
     
    50975170
    50985171            $matches_used++;
     5172            $total_chunks_used += $chunks_in_this_source;
    50995173        }
    51005174    }
     
    52305304 * @return string Reassembled content from all chunks
    52315305 */
    5232 private function reassemble_chunks_from_pinecone($source_url, $bot_config) {
     5306private function reassemble_chunks_from_pinecone($source_url, $bot_config, $max_chunks = 0, &$chunk_count = 0) {
    52335307    $api_key = $bot_config['api_key'] ?? '';
    52345308    $host = $bot_config['host'] ?? '';
     
    52365310
    52375311    if (empty($host) || empty($api_key)) {
     5312        $chunk_count = 0;
    52385313        return '';
    52395314    }
     
    52445319    $list_url = "https://{$host}/vectors/list";
    52455320
     5321    // Limit to max_chunks if specified, otherwise fetch up to 100
     5322    $fetch_limit = ($max_chunks > 0 && $max_chunks < 100) ? $max_chunks : 100;
     5323
    52465324    $list_body = array(
    52475325        'prefix' => $base_hash . '_chunk_',
    5248         'limit' => 100
     5326        'limit' => $fetch_limit
    52495327    );
    52505328
     
    53325410    // Sort by chunk index
    53335411    ksort($chunks);
     5412
     5413    // Apply chunk limit if specified
     5414    if ($max_chunks > 0 && count($chunks) > $max_chunks) {
     5415        $chunks = array_slice($chunks, 0, $max_chunks, true);
     5416    }
     5417
     5418    // Store actual chunk count
     5419    $chunk_count = count($chunks);
    53345420
    53355421    // Reassemble content
     
    53965482    $bot_options = $this->get_bot_options($bot_id);
    53975483    $current_options = !empty($bot_options) ? $bot_options : $mxchat_options;
    5398     $selected_model = $current_options['model'] ?? 'gpt-4o';
     5484    $selected_model = $current_options['model'] ?? 'gpt-5.1-chat-latest';
    53995485
    54005486    // Verify it's an OpenAI model
     
    58985984 * Checks for multi-bot add-on and uses bot-specific instructions if available
    58995985 * Automatically strips URLs if citation links are disabled
     5986 * Replaces {visitor_name} placeholder with actual visitor name if available
    59005987 *
    59015988 * @param string $bot_id The bot ID to get instructions for
     5989 * @param string $session_id Optional session ID to lookup visitor name
    59025990 */
    5903 private function get_system_instructions($bot_id = 'default') {
     5991private function get_system_instructions($bot_id = 'default', $session_id = '') {
    59045992    $instructions = '';
    59055993
     
    59276015        $instructions = preg_replace('#\bhttps?://[^\s<>"\']+#i', '', $instructions);
    59286016        $instructions = preg_replace('/\s+/', ' ', trim($instructions)); // Clean up extra spaces
     6017    }
     6018
     6019    // Replace {visitor_name} placeholder with actual visitor name if available
     6020    if (!empty($instructions) && !empty($session_id) && stripos($instructions, '{visitor_name}') !== false) {
     6021        $name_option_key = "mxchat_name_{$session_id}";
     6022        $visitor_name = get_option($name_option_key, '');
     6023
     6024        if (!empty($visitor_name)) {
     6025            $instructions = str_ireplace('{visitor_name}', sanitize_text_field($visitor_name), $instructions);
     6026        } else {
     6027            // Remove placeholder if no name is available
     6028            $instructions = str_ireplace('{visitor_name}', '', $instructions);
     6029            $instructions = preg_replace('/\s{2,}/', ' ', trim($instructions)); // Clean up extra spaces
     6030        }
    59296031    }
    59306032
     
    59516053    return 'default';
    59526054}
    5953 private function mxchat_generate_response($relevant_content, $api_key, $xai_api_key, $claude_api_key, $deepseek_api_key, $gemini_api_key, $openrouter_api_key, $conversation_history, $streaming = false, $session_id = '', $testing_data = null, $selected_model = 'gpt-4o') {
     6055private function mxchat_generate_response($relevant_content, $api_key, $xai_api_key, $claude_api_key, $deepseek_api_key, $gemini_api_key, $openrouter_api_key, $conversation_history, $streaming = false, $session_id = '', $testing_data = null, $selected_model = 'gpt-5.1-chat-latest') {
    59546056    try {
    59556057        if (!$relevant_content) {
     
    62626364    try {
    62636365        $bot_id = $this->get_current_bot_id($session_id);
    6264         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     6366        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    62656367       
    62666368        if (!is_array($conversation_history)) {
     
    64726574       
    64736575        // Get system prompt instructions using centralized function
    6474         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     6576        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    64756577       
    64766578        // Ensure conversation_history is an array
     
    67576859    try {
    67586860        $bot_id = $this->get_current_bot_id($session_id);
    6759         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     6861        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    67606862
    67616863        if (!is_array($conversation_history)) {
     
    70877189       
    70887190        // Get system prompt instructions using centralized function
    7089         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     7191        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    70907192        // Ensure conversation_history is an array
    70917193        if (!is_array($conversation_history)) {
     
    73827484       
    73837485        // Get system prompt instructions using centralized function
    7384         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     7486        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    73857487       
    73867488        // Ensure conversation_history is an array
     
    76197721       
    76207722        // Get system prompt instructions using centralized function
    7621         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     7723        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    76227724       
    76237725        // Ensure conversation_history is an array
     
    78837985
    78847986        $bot_id = $this->get_current_bot_id('');
    7885         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     7987        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    78867988       
    78877989        $formatted_conversation = array();
     
    79858087       
    79868088        // Get system prompt instructions using centralized function
    7987         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     8089        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    79888090       
    79898091    // Clean and validate conversation history
     
    80948196       
    80958197        // Get system prompt instructions using centralized function
    8096         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     8198        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    80978199       
    80988200        // Create a new array for the formatted conversation
     
    82628364       
    82638365        // Get system prompt instructions using centralized function
    8264         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     8366        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    82658367       
    82668368        // Add system prompt to relevant content
     
    84618563       
    84628564        // Get system prompt instructions using centralized function
    8463         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     8565        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    84648566       
    84658567        // Create a new array for the formatted conversation
     
    86208722       
    86218723        // Get system prompt instructions using centralized function
    8622         $system_prompt_instructions = $this->get_system_instructions($bot_id);
     8724        $system_prompt_instructions = $this->get_system_instructions($bot_id, $session_id);
    86238725       
    86248726    // Add system prompt to relevant content
     
    87648866public function test_streaming_request() {
    87658867    $options = get_option('mxchat_options', []);
    8766     $model = $options['model'] ?? 'gpt-4o';
     8868    $model = $options['model'] ?? 'gpt-5.1-chat-latest';
    87678869
    87688870    // Detect provider from model prefix
     
    89789080        'ajax_url' => admin_url('admin-ajax.php'),
    89799081        'nonce' => wp_create_nonce('mxchat_chat_nonce'),
    8980         'model' => isset($this->options['model']) ? $this->options['model'] : 'gpt-4o',
     9082        'model' => isset($this->options['model']) ? $this->options['model'] : 'gpt-5.1-chat-latest',
    89819083        'enable_streaming_toggle' => isset($this->options['enable_streaming_toggle']) ? $this->options['enable_streaming_toggle'] : 'on',
    89829084        'contextual_awareness_toggle' => isset($this->options['contextual_awareness_toggle']) ? $this->options['contextual_awareness_toggle'] : 'off',
     
    95749676   
    95759677    // Get selected model
    9576     $selected_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-4o';
     9678    $selected_model = isset($this->options['model']) ? $this->options['model'] : 'gpt-5.1-chat-latest';
    95779679   
    95789680    // Check if OpenRouter is being used
  • mxchat-basic/trunk/js/chat-script.js

    r3446370 r3459102  
    1212        init: function(botId) {
    1313            if (!this.instances[botId]) {
     14                // When persistence is OFF, track when this session started
     15                // so the AI only sees messages from this page load
     16                var chatPersistenceEnabled = typeof mxchatChat !== 'undefined' && mxchatChat.chat_persistence_toggle === 'on';
     17
    1418                this.instances[botId] = {
    1519                    botId: botId,
     
    2226                    activeWordFile: null,
    2327                    chatHistoryLoaded: false,
    24                     isStreaming: false
     28                    isStreaming: false,
     29                    // Fresh context timestamp - only used when persistence is OFF
     30                    sessionStartTimestamp: chatPersistenceEnabled ? 0 : Date.now()
    2531                };
    2632            }
     
    398404        scrollToBottom(botId);
    399405
    400         const currentModel = mxchatChat.model || 'gpt-4o';
     406        const currentModel = mxchatChat.model || 'gpt-5.1-chat-latest';
    401407
    402408        // Check if streaming is enabled AND supported for this model
     
    433439    scrollToBottom(botId);
    434440
    435     const currentModel = mxchatChat.model || 'gpt-4o';
     441    const currentModel = mxchatChat.model || 'gpt-5.1-chat-latest';
    436442
    437443    // Check if streaming is enabled AND supported for this model
     
    510516    const pageContext = getPageContext();
    511517
     518    // Get instance for session start timestamp (used when persistence is OFF)
     519    var instance = MxChatInstances.get(botId);
     520
    512521    // Prepare AJAX data
    513522    const ajaxData = {
     
    518527        current_page_url: window.location.href,
    519528        current_page_title: document.title,
    520         bot_id: botId
     529        bot_id: botId,
     530        // Pass session start timestamp so AI context matches what user sees
     531        session_start_timestamp: instance.sessionStartTimestamp || 0
    521532    };
    522533   
     
    590601                        scrollToBottom(botId);
    591602                        // Determine whether to use streaming
    592                         const currentModel = mxchatChat.model || 'gpt-4o';
     603                        const currentModel = mxchatChat.model || 'gpt-5.1-chat-latest';
    593604                        if (shouldUseStreaming(currentModel)) {
    594605                            callMxChatStream(originalMessage, function(response) {
     
    736747    getElement(botId, 'mxchat-chatbot-wrapper').find('.mxchat-input-holder textarea').data('pending-message', message);
    737748
    738     const currentModel = mxchatChat.model || 'gpt-4o';
     749    const currentModel = mxchatChat.model || 'gpt-5.1-chat-latest';
    739750    if (!isStreamingSupported(currentModel)) {
    740751        callMxChat(message, callback, botId);
     
    744755    // Get page context if contextual awareness is enabled
    745756    const pageContext = getPageContext();
     757
     758    // Get instance for session start timestamp (used when persistence is OFF)
     759    var instance = MxChatInstances.get(botId);
    746760
    747761    const formData = new FormData();
     
    753767    formData.append('current_page_title', document.title);
    754768    formData.append('bot_id', botId);
    755    
     769    // Pass session start timestamp so AI context matches what user sees
     770    formData.append('session_start_timestamp', instance.sessionStartTimestamp || 0);
     771
    756772    // Add page context if available
    757773    if (pageContext) {
     
    10041020                scrollToBottom(botId);
    10051021                // Determine whether to use streaming
    1006                 const currentModel = mxchatChat.model || 'gpt-4o';
     1022                const currentModel = mxchatChat.model || 'gpt-5.1-chat-latest';
    10071023                if (shouldUseStreaming(currentModel)) {
    10081024                    callMxChatStream(originalMessage, callback, botId);
     
    27022718    }
    27032719
     2720    /**
     2721     * Replace {visitor_name} placeholder in intro message with actual visitor name
     2722     * @param {string} botId - The bot instance ID
     2723     * @param {string} visitorName - The visitor's name to insert
     2724     */
     2725    function replaceVisitorNamePlaceholder(botId, visitorName) {
     2726        var chatBox = getElementDOM(botId, 'chat-box');
     2727        if (!chatBox) return;
     2728
     2729        // Find the first bot message (intro message)
     2730        var introMessage = chatBox.querySelector('.bot-message');
     2731        if (!introMessage) return;
     2732
     2733        var messageContent = introMessage.querySelector('div[dir="auto"]');
     2734        if (!messageContent) return;
     2735
     2736        var html = messageContent.innerHTML;
     2737
     2738        // Replace {visitor_name} placeholder (case-insensitive)
     2739        if (visitorName && visitorName.trim()) {
     2740            // Escape HTML to prevent XSS
     2741            var safeName = $('<div>').text(visitorName.trim()).html();
     2742            html = html.replace(/\{visitor_name\}/gi, safeName);
     2743        } else {
     2744            // Remove placeholder and clean up spacing if no name provided
     2745            html = html.replace(/\{visitor_name\}/gi, '');
     2746            // Clean up any double spaces that might result
     2747            html = html.replace(/\s{2,}/g, ' ').trim();
     2748        }
     2749
     2750        messageContent.innerHTML = html;
     2751    }
     2752
    27042753    function setEmailSubmissionState(botId, loading) {
    27052754        var submitButton = getElementDOM(botId, 'email-submit-button');
     
    28872936            if (data.success) {
    28882937                showChatContainerForBot(botId);
     2938
     2939                // Replace {visitor_name} placeholder in intro message with actual name
     2940                if (userName) {
     2941                    replaceVisitorNamePlaceholder(botId, userName);
     2942                } else {
     2943                    // Remove placeholder if no name provided
     2944                    replaceVisitorNamePlaceholder(botId, '');
     2945                }
    28892946
    28902947                if (data.message && typeof appendMessage === 'function') {
  • mxchat-basic/trunk/js/mxchat-admin.js

    r3448781 r3459102  
    410410        $autosaveSections.find('input[type="range"]').on('input', function() {
    411411            const value = $(this).val();
    412             $('#threshold_value').text(value);
     412            const $slider = $(this);
     413            const sliderId = $slider.attr('id');
     414            // Find the corresponding value display span (convention: id_value)
     415            const $valueSpan = $('#' + sliderId + '_value');
     416            if ($valueSpan.length) {
     417                $valueSpan.text(value);
     418            } else {
     419                // Fallback for similarity_threshold which uses threshold_value
     420                $('#threshold_value').text(value);
     421            }
    413422        });
    414423
     
    10081017            openai: [
    10091018                { value: 'gpt-5.2', label: 'GPT-5.2', description: 'Best general-purpose & agentic model with fast responses' },
     1019                { value: 'gpt-5.1-chat-latest', label: 'GPT-5.1 Chat Latest', description: 'Recommended for most use cases' },
    10101020                { value: 'gpt-5.1-2025-11-13', label: 'GPT-5.1', description: 'Flagship for coding & agentic tasks with low reasoning (400K context)' },
    10111021                { value: 'gpt-5', label: 'GPT-5', description: 'Flagship for coding, reasoning, and agentic tasks across domains' },
    1012                 { value: 'gpt-5-mini', label: 'GPT-5 Mini', description: 'Faster, more cost-efficient for well-defined tasks and precise prompts' },
     1022                { value: 'gpt-5-mini', label: 'GPT-5 Mini', description: 'Fast and lightweight' },
    10131023                { value: 'gpt-5-nano', label: 'GPT-5 Nano', description: 'Fastest and cheapest; ideal for summarization and classification' },
    1014                 { value: 'gpt-4.1-2025-04-14', label: 'GPT-4.1', description: 'Flagship model for complex tasks' },
    1015                 { value: 'gpt-4o', label: 'GPT-4o', description: 'Recommended for most use cases' },
    1016                 { value: 'gpt-4o-mini', label: 'GPT-4o Mini', description: 'Fast and lightweight' },
    1017                 { value: 'gpt-4-turbo', label: 'GPT-4 Turbo', description: 'High-performance model' },
    1018                 { value: 'gpt-4', label: 'GPT-4', description: 'High intelligence model' },
    1019                 { value: 'gpt-3.5-turbo', label: 'GPT-3.5 Turbo', description: 'Affordable and fast' },
    10201024            ],
    10211025            claude: [
     1026                { value: 'claude-opus-4-6', label: 'Claude Opus 4.6', description: 'Most capable Claude model - recommended' },
     1027                { value: 'claude-opus-4-5', label: 'Claude Opus 4.5', description: 'Highly capable for complex tasks' },
    10221028                { value: 'claude-sonnet-4-5-20250929', label: 'Claude Sonnet 4.5', description: 'Best for complex agents and coding' },
    10231029                { value: 'claude-opus-4-1-20250805', label: 'Claude Opus 4.1', description: 'Exceptional for specialized complex tasks' },
    10241030                { value: 'claude-haiku-4-5-20251001', label: 'Claude Haiku 4.5', description: 'Fastest and most intelligent Haiku' },
    1025                 { value: 'claude-opus-4-20250514', label: 'Claude 4 Opus', description: 'Most capable Claude model' },
     1031                { value: 'claude-opus-4-20250514', label: 'Claude 4 Opus', description: 'Complex tasks' },
    10261032                { value: 'claude-sonnet-4-20250514', label: 'Claude 4 Sonnet', description: 'High performance' },
    1027                 { value: 'claude-3-7-sonnet-20250219', label: 'Claude 3.7 Sonnet', description: 'High intelligence' },
    1028                 { value: 'claude-3-opus-20240229', label: 'Claude 3 Opus', description: 'Highly complex tasks' },
    1029                 { value: 'claude-3-sonnet-20240229', label: 'Claude 3 Sonnet', description: 'Balanced performance' },
    1030                 { value: 'claude-3-haiku-20240307', label: 'Claude 3 Haiku', description: 'Fastest Claude model' },
    10311033            ],
    10321034            xai: [
  • mxchat-basic/trunk/mxchat-basic.php

    r3448781 r3459102  
    44 * Plugin URI: https://mxchat.ai/
    55 * Description: AI chatbot for WordPress with OpenAI, Claude, xAI, DeepSeek, live agent, PDF uploads, WooCommerce, and training on website data.
    6  * Version: 3.0.5
     6 * Version: 3.0.6
    77 * Author: MxChat
    88 * Author URI: https://mxchat.ai
     
    479479 * Migrate deprecated AI models to their replacements
    480480 * Version 2.5.1: Migrate Claude 3.5 Sonnet (deprecated) to Claude 3.7 Sonnet
     481 * Version 3.0.55: Migrate GPT-4 series models (deprecated 2026-02-17) to GPT-5 series
    481482 */
    482483function mxchat_migrate_deprecated_models() {
    483484    $options = get_option('mxchat_options', array());
    484    
    485     // Check if model is set and is the deprecated Claude 3.5 Sonnet
    486     if (isset($options['model']) && $options['model'] === 'claude-3-5-sonnet-20241022') {
    487         // Update to Claude 3.7 Sonnet (the replacement model)
    488         $options['model'] = 'claude-3-7-sonnet-20250219';
     485    $migrated = false;
     486    $migration_message = '';
     487
     488    if (!isset($options['model'])) {
     489        return;
     490    }
     491
     492    $current_model = $options['model'];
     493
     494    // Migrate deprecated Claude models to Claude Opus 4.6 (recommended replacement per Anthropic)
     495    $deprecated_claude_models = array(
     496        'claude-3-5-sonnet-20240620',  // Retired Oct 28, 2025
     497        'claude-3-5-sonnet-20241022',  // Retired Oct 28, 2025
     498        'claude-3-7-sonnet-20250219',  // Retiring Feb 19, 2026
     499        'claude-3-opus-20240229',      // Retired Jan 5, 2026
     500        'claude-3-sonnet-20240229',    // Legacy
     501        'claude-3-haiku-20240307',     // Legacy
     502    );
     503    if (in_array($current_model, $deprecated_claude_models, true)) {
     504        $options['model'] = 'claude-opus-4-6';
     505        $migrated = true;
     506        $migration_message = sprintf(
     507            __('Your chatbot model has been automatically updated from %s to Claude Opus 4.6 due to Anthropic deprecating older Claude models.', 'mxchat'),
     508            $current_model
     509        );
     510    }
     511
     512    // Migrate deprecated Claude Haiku 3.5 to Claude Haiku 4.5
     513    if ($current_model === 'claude-3-5-haiku-20241022') {
     514        $options['model'] = 'claude-haiku-4-5-20251001';
     515        $migrated = true;
     516        $migration_message = __('Your chatbot model has been automatically updated from Claude Haiku 3.5 to Claude Haiku 4.5 due to Anthropic deprecating the older model.', 'mxchat');
     517    }
     518
     519    // Migrate deprecated GPT-4 series and GPT-3.5 Turbo to GPT-5.1 Chat Latest
     520    if (in_array($current_model, array('gpt-4o', 'gpt-4.1-2025-04-14', 'gpt-4-turbo', 'gpt-4', 'gpt-3.5-turbo'), true)) {
     521        $options['model'] = 'gpt-5.1-chat-latest';
     522        $migrated = true;
     523        $migration_message = sprintf(
     524            __('Your chatbot model has been automatically updated from %s to GPT-5.1 Chat Latest due to OpenAI deprecating older models.', 'mxchat'),
     525            $current_model
     526        );
     527    }
     528
     529    // Migrate deprecated GPT-4o Mini and GPT-4.1 Mini to GPT-5 Mini
     530    if (in_array($current_model, array('gpt-4o-mini', 'gpt-4.1-mini'), true)) {
     531        $options['model'] = 'gpt-5-mini';
     532        $migrated = true;
     533        $migration_message = sprintf(
     534            __('Your chatbot model has been automatically updated from %s to GPT-5 Mini due to OpenAI deprecating GPT-4 series models.', 'mxchat'),
     535            $current_model
     536        );
     537    }
     538
     539    if ($migrated) {
    489540        update_option('mxchat_options', $options);
    490        
    491         // Set a flag to show admin notice
    492541        update_option('mxchat_model_migrated_notice', true);
    493        
    494         //error_log('MxChat: Migrated deprecated Claude 3.5 Sonnet to Claude 3.7 Sonnet');
     542        update_option('mxchat_model_migration_message', $migration_message);
    495543    }
    496544}
     
    501549function mxchat_show_migration_notice() {
    502550    if (get_option('mxchat_model_migrated_notice')) {
     551        $migration_message = get_option('mxchat_model_migration_message', __('Your chatbot model has been automatically updated due to a model deprecation.', 'mxchat'));
    503552        ?>
    504553        <div class="notice notice-info is-dismissible">
    505554            <p>
    506555                <strong><?php esc_html_e('MxChat Model Updated', 'mxchat'); ?></strong><br>
    507                 <?php esc_html_e('Your chatbot model has been automatically updated from Claude 3.5 Sonnet to Claude 3.7 Sonnet due to the deprecation of the previous model by Anthropic. Claude 3.7 Sonnet offers improved performance and capabilities.', 'mxchat'); ?>
     556                <?php echo esc_html($migration_message); ?>
    508557            </p>
    509558        </div>
    510559        <?php
    511560        delete_option('mxchat_model_migrated_notice');
     561        delete_option('mxchat_model_migration_message');
    512562    }
    513563}
     
    773823            }
    774824
     825            // 3.0.6: Migrate deprecated OpenAI and Claude models
     826            if (version_compare($current_version, '3.0.6', '<')) {
     827                mxchat_migrate_deprecated_models();
     828            }
     829
    775830            // Run full activation to ensure everything is up to date
    776831            mxchat_activate();
  • mxchat-basic/trunk/readme.txt

    r3448781 r3459102  
    66Tested up to: 6.9
    77Requires PHP: 7.2
    8 Stable tag: 3.0.5
     8Stable tag: 3.0.6
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    3838👉 [Visit our website to view all add-ons](https://mxchat.ai)
    3939
    40 ## 🔥 What's New in Version 3.0.5
    41 
    42 🔧 **Gemini Embedding Model Update**
    43 - Fixed: Updated Gemini embedding model from deprecated `gemini-embedding-exp-03-07` to stable `gemini-embedding-001`
    44 
    45 🐛 **Bug Fixes**
    46 - Fixed: Notification settings not saving on new installations
    47 - Fixed: Save indicators not visible on settings fields (API keys, Slack, Telegram, Loops, Brave Search)
    48 
    49 ✨ **Improvements**
    50 - Added: Warning notice for WordPress database users recommending Pinecone for large knowledge bases (500+ entries)
    51 - Improved: Minor admin UI updates for better user experience
     40## 🔥 What's New in Version 3.0.6
     41
     42- New: RAG Sources Limit slider - control how many knowledge base sources (3-10) are included in AI responses
     43- New: {visitor_name} placeholder support in Intro Message and AI Behavior settings for personalized greetings
     44- New: Added Claude Opus 4.6 and Claude Opus 4.5 models
     45- Fixed: Chat persistence OFF now correctly starts fresh AI context on page reload
     46- Deprecated: Removed all GPT-4 series, GPT-3.5 Turbo, and Claude 3.x models per provider deprecations
     47- Updated: Users on deprecated models auto-migrated to GPT-5.1/GPT-5 Mini or Claude Opus 4.6/Haiku 4.5
    5248
    5349## Core Features That Set MxChat Apart
     
    6965
    7066**OpenRouter**: 100+ models from multiple providers with a single API key – including OpenAI, Anthropic, Google, Meta, Mistral, and more!
    71 **OpenAI**: 
    72 GPT-5.2, GPT-5, GPT-5-mini, GPT-5-nano, GPT-5.1, GPT-4.1, GPT-4o, GPT-4o-mini, GPT-4-turbo, GPT-4, GPT-3.5-turbo
    73 **Anthropic Claude**: 
    74 Claude Sonnet 4.5, Claude Opus 4.1, Claude Haiku 4.5, Claude 4 Sonnet, Claude 4 Opus, Claude 3.7 Sonnet, Claude 3.5 Sonnet (deprecated), Claude 3 Opus
     67**OpenAI**:
     68GPT-5.2, GPT-5.1 Chat Latest, GPT-5.1, GPT-5, GPT-5-mini, GPT-5-nano
     69**Anthropic Claude**:
     70Claude Opus 4.6, Claude Opus 4.5, Claude Sonnet 4.5, Claude Opus 4.1, Claude Haiku 4.5, Claude 4 Sonnet, Claude 4 Opus
    7571**X.AI**: 
    7672Grok-4, Grok-3, Grok-3 Fast, Grok-3 Mini, Grok-3 Mini Fast, Grok-2, **Grok 4.1 Fast (Reasoning)**, **Grok 4.1 Fast (Non-Reasoning)**
     
    164160= What AI models does MxChat support? =
    165161
    166 MxChat supports 100+ AI models including OpenAI GPT-5, GPT-5 Mini, GPT-4.1, GPT-4o, GPT-4 Turbo, Anthropic Claude Sonnet 4.5, Claude Opus 4, Claude Haiku, Google Gemini 2.0 Flash, Gemini 1.5 Pro, xAI Grok 4, Grok 3, DeepSeek Chat, and many more. With OpenRouter integration, you get access to models from OpenAI, Anthropic, Google, Meta, Mistral, and other providers with a single API key.
     162MxChat supports 100+ AI models including OpenAI GPT-5.2, GPT-5.1, GPT-5, GPT-5 Mini, Anthropic Claude Opus 4.6, Claude Opus 4.5, Claude Sonnet 4.5, Claude Haiku 4.5, Google Gemini 2.0 Flash, Gemini 1.5 Pro, xAI Grok 4, Grok 3, DeepSeek Chat, and many more. With OpenRouter integration, you get access to models from OpenAI, Anthropic, Google, Meta, Mistral, and other providers with a single API key.
    167163
    168164= How do I get API keys for the AI chatbot? =
     
    266262
    267263== Changelog ==
     264
     265= 3.0.6 - February 11, 2026 =
     266- New: RAG Sources Limit slider - control how many knowledge base sources (3-10) are included in AI responses
     267- New: {visitor_name} placeholder support in Intro Message and AI Behavior settings for personalized greetings
     268- New: Added Claude Opus 4.6 and Claude Opus 4.5 models
     269- Fixed: Chat persistence OFF now correctly starts fresh AI context on page reload (previously AI retained full history)
     270- Deprecated: Removed all GPT-4 series and GPT-3.5 Turbo from model selection (OpenAI deprecation)
     271- Deprecated: Removed Claude 3.x series models (3.7 Sonnet, 3.5 Sonnet, 3 Opus, 3 Sonnet, 3 Haiku) per Anthropic deprecation
     272- Updated: Users on deprecated OpenAI models auto-migrated to GPT-5.1 Chat Latest (or GPT-5 Mini for mini models)
     273- Updated: Users on deprecated Claude models auto-migrated to Claude Opus 4.6 (or Claude Haiku 4.5 for Haiku users)
    268274
    269275= 3.0.5 - January 28, 2026 =
     
    790796== Upgrade Notice ==
    791797
    792 = 3.0.5 - January 28, 2026 =
    793 Minor update: Updated Gemini embedding model to stable version, fixed notification settings on new installs, improved save indicators visibility, and added WordPress database warning for large knowledge bases.
     798= 3.0.6 - February 11, 2026 =
     799New: RAG Sources Limit slider, Claude Opus 4.6/4.5 models, {visitor_name} placeholder support. Deprecated OpenAI & Claude models auto-migrated.
    794800
    795801== License & Warranty ==
Note: See TracChangeset for help on using the changeset viewer.