Changeset 3392455
- Timestamp:
- 11/09/2025 04:56:59 PM (3 months ago)
- Location:
- mxchat-basic
- Files:
-
- 103 added
- 9 edited
-
tags/2.5.3 (added)
-
tags/2.5.3/admin (added)
-
tags/2.5.3/admin/class-ajax-handler.php (added)
-
tags/2.5.3/admin/class-knowledge-manager.php (added)
-
tags/2.5.3/admin/class-pinecone-manager.php (added)
-
tags/2.5.3/css (added)
-
tags/2.5.3/css/admin-add-ons.css (added)
-
tags/2.5.3/css/admin-style.css (added)
-
tags/2.5.3/css/chat-style.css (added)
-
tags/2.5.3/css/chat-transcripts.css (added)
-
tags/2.5.3/css/content-selector.css (added)
-
tags/2.5.3/css/intent-style.css (added)
-
tags/2.5.3/css/knowledge-style.css (added)
-
tags/2.5.3/css/test-panel.css (added)
-
tags/2.5.3/images (added)
-
tags/2.5.3/images/Icon-01.svg (added)
-
tags/2.5.3/images/Icon-02.svg (added)
-
tags/2.5.3/images/Icon-03.svg (added)
-
tags/2.5.3/images/Icon-04.svg (added)
-
tags/2.5.3/images/pro-only-dark.png (added)
-
tags/2.5.3/includes (added)
-
tags/2.5.3/includes/class-mxchat-addons.php (added)
-
tags/2.5.3/includes/class-mxchat-admin.php (added)
-
tags/2.5.3/includes/class-mxchat-integrator.php (added)
-
tags/2.5.3/includes/class-mxchat-meta-box.php (added)
-
tags/2.5.3/includes/class-mxchat-public.php (added)
-
tags/2.5.3/includes/class-mxchat-user.php (added)
-
tags/2.5.3/includes/class-mxchat-utils.php (added)
-
tags/2.5.3/includes/class-mxchat-woocommerce.php (added)
-
tags/2.5.3/includes/class-mxchat-word-handler.php (added)
-
tags/2.5.3/includes/pdf-parser (added)
-
tags/2.5.3/includes/pdf-parser/alt_autoload.php (added)
-
tags/2.5.3/includes/pdf-parser/src (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Config.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Document.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementArray.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementBoolean.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementDate.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementHexa.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementMissing.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementName.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementNull.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementNumeric.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementString.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementStruct.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Element/ElementXRef.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/AbstractEncoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/EncodingLocator.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/ISOLatin1Encoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/ISOLatin9Encoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/MacRomanEncoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/PDFDocEncoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/PostScriptGlyphs.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/StandardEncoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Encoding/WinAnsiEncoding.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Exception (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Exception/EmptyPdfException.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Exception/EncodingNotFoundException.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Exception/MissingPdfHeaderException.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Exception/NotImplementedException.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font/FontCIDFontType0.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font/FontCIDFontType2.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font/FontTrueType.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font/FontType0.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font/FontType1.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Font/FontType3.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Header.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/PDFObject.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Page.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Pages.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/Parser.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/RawData (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/RawData/FilterHelper.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/RawData/RawDataParser.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/XObject (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/XObject/Form.php (added)
-
tags/2.5.3/includes/pdf-parser/src/Smalot/PdfParser/XObject/Image.php (added)
-
tags/2.5.3/js (added)
-
tags/2.5.3/js/activation-script.js (added)
-
tags/2.5.3/js/admin-status.js (added)
-
tags/2.5.3/js/chat-script.js (added)
-
tags/2.5.3/js/content-selector.js (added)
-
tags/2.5.3/js/embedding-check.js (added)
-
tags/2.5.3/js/floating-script.js (added)
-
tags/2.5.3/js/knowledge-processing.js (added)
-
tags/2.5.3/js/meta-box.js (added)
-
tags/2.5.3/js/mxchat-admin.js (added)
-
tags/2.5.3/js/mxchat-test-streaming.js (added)
-
tags/2.5.3/js/mxchat_transcripts.js (added)
-
tags/2.5.3/js/my-color-picker.js (added)
-
tags/2.5.3/js/test-panel.js (added)
-
tags/2.5.3/languages (added)
-
tags/2.5.3/languages/mxchat.pot (added)
-
tags/2.5.3/mxchat-basic.php (added)
-
tags/2.5.3/readme.txt (added)
-
trunk/admin/class-ajax-handler.php (modified) (2 diffs)
-
trunk/includes/class-mxchat-addons.php (modified) (1 diff)
-
trunk/includes/class-mxchat-admin.php (modified) (23 diffs)
-
trunk/includes/class-mxchat-integrator.php (modified) (14 diffs)
-
trunk/js/chat-script.js (modified) (1 diff)
-
trunk/js/knowledge-processing.js (modified) (5 diffs)
-
trunk/js/mxchat-admin.js (modified) (4 diffs)
-
trunk/mxchat-basic.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
mxchat-basic/trunk/admin/class-ajax-handler.php
r3379814 r3392455 39 39 add_action('wp_ajax_mxchat_toggle_action', array($this, 'mxchat_toggle_action')); 40 40 add_action('wp_ajax_mxchat_update_intent_threshold', array($this, 'mxchat_update_intent_threshold')); 41 41 42 42 add_action('wp_ajax_mxchat_save_selected_bot', array($this, 'mxchat_save_selected_bot')); 43 add_action('wp_ajax_mxchat_check_api_keys', array($this, 'mxchat_check_api_keys')); 43 44 } 44 45 … … 873 874 } 874 875 876 /** 877 * Check API key status for all providers 878 */ 879 public function mxchat_check_api_keys() { 880 // Check nonce 881 if (!wp_verify_nonce($_POST['nonce'] ?? '', 'mxchat_save_setting_nonce')) { 882 wp_send_json_error('Invalid nonce'); 883 } 884 885 // Check permissions 886 if (!current_user_can('manage_options')) { 887 wp_send_json_error('Unauthorized'); 888 } 889 890 // Get current options 891 $options = get_option('mxchat_options', array()); 892 893 // Check which API keys are present 894 $api_key_status = array( 895 'openai' => !empty($options['api_key']), 896 'claude' => !empty($options['claude_api_key']), 897 'xai' => !empty($options['xai_api_key']), 898 'deepseek' => !empty($options['deepseek_api_key']), 899 'gemini' => !empty($options['gemini_api_key']), 900 'openrouter' => !empty($options['openrouter_api_key']), 901 'voyage' => !empty($options['voyage_api_key']) 902 ); 903 904 wp_send_json_success($api_key_status); 905 } 906 875 907 } 876 908 -
mxchat-basic/trunk/includes/class-mxchat-addons.php
r3389316 r3392455 177 177 */ 178 178 public function enqueue_styles() { 179 $plugin_version = '2.5.2';180 181 179 wp_enqueue_style( 182 180 'mxchat-addons', 183 181 plugin_dir_url(__FILE__) . '../css/admin-add-ons.css', 184 182 array(), 185 $plugin_version,183 MXCHAT_VERSION, 186 184 'all' 187 185 ); -
mxchat-basic/trunk/includes/class-mxchat-admin.php
r3389316 r3392455 610 610 <div class="mxchat-tabs"> 611 611 <button class="mxchat-tab-button active" data-tab="chatbot"><?php echo esc_html__('Chatbot', 'mxchat'); ?></button> 612 <button class="mxchat-tab-button" data-tab="api-keys"><?php echo esc_html__('API Keys', 'mxchat'); ?></button> 612 613 <button class="mxchat-tab-button" data-tab="embed"><?php echo esc_html__('Toolbar & Components', 'mxchat'); ?></button> 613 614 <button class="mxchat-tab-button" data-tab="general"><?php echo esc_html__('YouTube Tutorials', 'mxchat'); ?></button> … … 619 620 <div class="mxchat-autosave-section"> 620 621 <?php do_settings_sections('mxchat-chatbot'); ?> 622 </div> 623 </div> 624 </div> 625 626 <div id="api-keys" class="mxchat-tab-content"> 627 <div class="mxchat-card"> 628 <div class="mxchat-autosave-section"> 629 <table class="form-table"> 630 <?php do_settings_fields('mxchat-api-keys', 'mxchat_api_keys_section'); ?> 631 </table> 621 632 </div> 622 633 </div> … … 1741 1752 </div> 1742 1753 </div> 1743 1744 <script>1745 jQuery(document).ready(function($) {1746 var saveTimer;1747 1748 // Function to update bot_id in forms1749 function updateBotIdInForm(formSelector) {1750 var botId = $('#mxchat-bot-selector').val();1751 var form = $(formSelector);1752 1753 if (form.length > 0) {1754 // Remove existing bot_id hidden input1755 form.find('input[name="bot_id"]').remove();1756 1757 // Add new bot_id hidden input if not default1758 if (botId && botId !== 'default') {1759 form.append('<input type="hidden" name="bot_id" value="' + botId + '">');1760 }1761 }1762 }1763 1764 $('#mxchat-bot-selector').on('change', function() {1765 var botId = $(this).val();1766 1767 // Clear any existing timer1768 clearTimeout(saveTimer);1769 1770 // Update all forms with new bot_id when bot selection changes1771 updateBotIdInForm('#mxchat-url-form');1772 updateBotIdInForm('#mxchat-content-form');1773 1774 // Save the selection via AJAX1775 $.ajax({1776 url: ajaxurl,1777 type: 'POST',1778 data: {1779 action: 'mxchat_save_selected_bot',1780 bot_id: botId,1781 nonce: '<?php echo wp_create_nonce('mxchat_save_setting_nonce'); ?>'1782 },1783 success: function(response) {1784 if (response.success) {1785 // Show saved indicator1786 $('#mxchat-bot-save-status').fadeIn().delay(2000).fadeOut();1787 1788 // Reload the page after a short delay to refresh content1789 saveTimer = setTimeout(function() {1790 var currentUrl = new URL(window.location.href);1791 currentUrl.searchParams.set('bot_id', botId);1792 currentUrl.searchParams.set('page', 'mxchat-prompts');1793 window.location.href = currentUrl.toString();1794 }, 500);1795 }1796 },1797 error: function() {1798 console.error('Failed to save bot selection');1799 }1800 });1801 });1802 1803 // Initialize forms with current bot_id when the page loads1804 setTimeout(function() {1805 updateBotIdInForm('#mxchat-url-form');1806 updateBotIdInForm('#mxchat-content-form');1807 }, 100);1808 });1809 </script>1810 1754 1811 1755 <?php … … 4355 4299 ); 4356 4300 4301 // API Keys Settings Section 4302 add_settings_section( 4303 'mxchat_api_keys_section', 4304 esc_html__('API Keys', 'mxchat'), 4305 array($this, 'mxchat_api_keys_section_callback'), 4306 'mxchat-api-keys' 4307 ); 4308 4309 // OpenAI API Key 4310 add_settings_field( 4311 'api_key', 4312 esc_html__('OpenAI API Key', 'mxchat'), 4313 array($this, 'api_key_callback'), 4314 'mxchat-api-keys', 4315 'mxchat_api_keys_section' 4316 ); 4317 4318 // X.AI API Key 4319 add_settings_field( 4320 'xai_api_key', 4321 esc_html__('X.AI API Key', 'mxchat'), 4322 array($this, 'xai_api_key_callback'), 4323 'mxchat-api-keys', 4324 'mxchat_api_keys_section' 4325 ); 4326 4327 // Claude API Key 4328 add_settings_field( 4329 'claude_api_key', 4330 esc_html__('Claude API Key', 'mxchat'), 4331 array($this, 'claude_api_key_callback'), 4332 'mxchat-api-keys', 4333 'mxchat_api_keys_section' 4334 ); 4335 4336 // DeepSeek API Key 4337 add_settings_field( 4338 'deepseek_api_key', 4339 esc_html__('DeepSeek API Key', 'mxchat'), 4340 array($this, 'deepseek_api_key_callback'), 4341 'mxchat-api-keys', 4342 'mxchat_api_keys_section' 4343 ); 4344 4345 // Google Gemini API Key 4346 add_settings_field( 4347 'gemini_api_key', 4348 esc_html__('Google Gemini API Key', 'mxchat'), 4349 array($this, 'gemini_api_key_callback'), 4350 'mxchat-api-keys', 4351 'mxchat_api_keys_section' 4352 ); 4353 4354 // Voyage AI API Key 4355 add_settings_field( 4356 'voyage_api_key', 4357 esc_html__('Voyage AI API Key', 'mxchat'), 4358 array($this, 'voyage_api_key_callback'), 4359 'mxchat-api-keys', 4360 'mxchat_api_keys_section' 4361 ); 4362 4363 // OpenRouter API Key 4364 add_settings_field( 4365 'openrouter_api_key', 4366 esc_html__('OpenRouter API Key', 'mxchat'), 4367 array($this, 'openrouter_api_key_callback'), 4368 'mxchat-api-keys', 4369 'mxchat_api_keys_section' 4370 ); 4371 4372 // Loops API Key 4373 add_settings_field( 4374 'loops_api_key', 4375 esc_html__('Loops API Key', 'mxchat'), 4376 array($this, 'mxchat_loops_api_key_callback'), 4377 'mxchat-api-keys', 4378 'mxchat_api_keys_section' 4379 ); 4380 4381 // Brave Search API Key 4382 add_settings_field( 4383 'brave_api_key', 4384 __('Brave API Key', 'mxchat'), 4385 array($this, 'mxchat_brave_api_key_callback'), 4386 'mxchat-api-keys', 4387 'mxchat_api_keys_section' 4388 ); 4389 4357 4390 // Similarity Threshold Slider 4358 4391 add_settings_field( … … 4379 4412 'mxchat_chatbot_section' 4380 4413 ); 4381 4382 add_settings_field(4383 'api_key',4384 esc_html__('OpenAI API Key', 'mxchat'),4385 array($this, 'api_key_callback'),4386 'mxchat-chatbot',4387 'mxchat_chatbot_section',4388 array(4389 'class' => 'mxchat-setting-row',4390 'data-provider' => 'openai'4391 )4392 );4393 4394 add_settings_field(4395 'xai_api_key',4396 esc_html__('X.AI API Key', 'mxchat'),4397 array($this, 'xai_api_key_callback'),4398 'mxchat-chatbot',4399 'mxchat_chatbot_section',4400 array(4401 'class' => 'mxchat-setting-row',4402 'data-provider' => 'xai'4403 )4404 );4405 4406 add_settings_field(4407 'claude_api_key',4408 esc_html__('Claude API Key', 'mxchat'),4409 array($this, 'claude_api_key_callback'),4410 'mxchat-chatbot',4411 'mxchat_chatbot_section',4412 array(4413 'class' => 'mxchat-setting-row',4414 'data-provider' => 'claude'4415 )4416 );4417 4418 add_settings_field(4419 'deepseek_api_key',4420 esc_html__('DeepSeek API Key', 'mxchat'),4421 array($this, 'deepseek_api_key_callback'),4422 'mxchat-chatbot',4423 'mxchat_chatbot_section',4424 array(4425 'class' => 'mxchat-setting-row',4426 'data-provider' => 'deepseek'4427 )4428 );4429 4430 add_settings_field(4431 'gemini_api_key',4432 esc_html__('Google Gemini API Key', 'mxchat'),4433 array($this, 'gemini_api_key_callback'),4434 'mxchat-chatbot',4435 'mxchat_chatbot_section',4436 array(4437 'class' => 'mxchat-setting-row',4438 'data-provider' => 'gemini'4439 )4440 );4441 4442 add_settings_field(4443 'voyage_api_key',4444 esc_html__('Voyage AI API Key', 'mxchat'),4445 array($this, 'voyage_api_key_callback'),4446 'mxchat-chatbot',4447 'mxchat_chatbot_section',4448 array(4449 'class' => 'mxchat-setting-row',4450 'data-provider' => 'voyage'4451 )4452 );4453 4414 4454 4415 add_settings_field( … … 4472 4433 'mxchat_chatbot_section' 4473 4434 ); 4474 4475 4476 add_settings_field(4477 'openrouter_api_key',4478 esc_html__('OpenRouter API Key', 'mxchat'),4479 array($this, 'openrouter_api_key_callback'),4480 'mxchat-chatbot',4481 'mxchat_chatbot_section',4482 array(4483 'class' => 'mxchat-setting-row mxchat-openrouter-key-row', // Special class so we can always show it4484 'data-provider' => 'openrouter'4485 )4486 );4487 4435 4488 4436 add_settings_field( … … 4664 4612 ); 4665 4613 4666 // Loops Settings Fields 4667 add_settings_field( 4668 'loops_api_key', 4669 esc_html__('Loops API Key', 'mxchat'), 4670 array($this, 'mxchat_loops_api_key_callback'), 4671 'mxchat-embed', 4672 'mxchat_loops_section' 4673 ); 4674 4614 // Loops Settings Fields (API Key moved to API Keys tab) 4675 4615 add_settings_field( 4676 4616 'loops_mailing_list', … … 4705 4645 ); 4706 4646 4707 add_settings_field( 4708 'brave_api_key', 4709 __('Brave API Key', 'mxchat'), 4710 array($this, 'mxchat_brave_api_key_callback'), 4711 'mxchat-embed', 4712 'mxchat_brave_section' 4713 ); 4714 4647 // Brave API Key moved to API Keys tab 4715 4648 add_settings_field( 4716 4649 'brave_image_count', … … 5175 5108 } 5176 5109 5110 // API Keys Section Callback 5111 public function mxchat_api_keys_section_callback() { 5112 echo '<p>' . esc_html__('Manage all your API keys in one place. Add the API keys for the services you want to use with your chatbot.', 'mxchat') . '</p>'; 5113 } 5114 5177 5115 // OpenAI API Key 5178 5116 public function api_key_callback() { 5179 5117 $apiKey = isset($this->options['api_key']) ? esc_attr($this->options['api_key']) : ''; 5180 5118 5181 echo '<div class="api-key-wrapper" data-provider="openai">';5119 echo '<div class="api-key-wrapper">'; 5182 5120 echo '<input type="password" id="api_key" name="api_key" value="' . $apiKey . '" class="regular-text" autocomplete="off" />'; 5183 5121 echo '<button type="button" id="toggleApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5184 echo '<p class="description api-key-notice">' . esc_html__('Required for your selected chat model. Important: You must add credits before use.', 'mxchat') . '</p>';5122 echo '<p class="description">' . esc_html__('Required for OpenAI GPT models and OpenAI embeddings. Get your API key from OpenAI Platform.', 'mxchat') . '</p>'; 5185 5123 echo '</div>'; 5186 5124 } … … 5190 5128 $xaiApiKey = isset($this->options['xai_api_key']) ? esc_attr($this->options['xai_api_key']) : ''; 5191 5129 5192 echo '<div class="api-key-wrapper" data-provider="xai">';5130 echo '<div class="api-key-wrapper">'; 5193 5131 echo '<input type="password" id="xai_api_key" name="xai_api_key" value="' . $xaiApiKey . '" class="regular-text" autocomplete="off" />'; 5194 5132 echo '<button type="button" id="toggleXaiApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5195 echo '<p class="description api-key-notice">' . esc_html__('Required for your selected chat model. Important: You must add credits before use.', 'mxchat') . '</p>';5133 echo '<p class="description">' . esc_html__('Required for X.AI Grok models. Get your API key from X.AI Console.', 'mxchat') . '</p>'; 5196 5134 echo '</div>'; 5197 5135 } … … 5200 5138 $claudeApiKey = isset($this->options['claude_api_key']) ? esc_attr($this->options['claude_api_key']) : ''; 5201 5139 5202 echo '<div class="api-key-wrapper" data-provider="claude">';5140 echo '<div class="api-key-wrapper">'; 5203 5141 echo '<input type="password" id="claude_api_key" name="claude_api_key" value="' . $claudeApiKey . '" class="regular-text" autocomplete="off" />'; 5204 5142 echo '<button type="button" id="toggleClaudeApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5205 echo '<p class="description api-key-notice">' . esc_html__('Required for your selected chat model. Important: You must add credits before use.', 'mxchat') . '</p>';5143 echo '<p class="description">' . esc_html__('Required for Anthropic Claude models. Get your API key from Anthropic Console.', 'mxchat') . '</p>'; 5206 5144 echo '</div>'; 5207 5145 } … … 5211 5149 $apiKey = isset($this->options['deepseek_api_key']) ? esc_attr($this->options['deepseek_api_key']) : ''; 5212 5150 5213 echo '<div class="api-key-wrapper" data-provider="deepseek">';5151 echo '<div class="api-key-wrapper">'; 5214 5152 echo '<input type="password" id="deepseek_api_key" name="deepseek_api_key" value="' . $apiKey . '" class="regular-text" autocomplete="off" />'; 5215 5153 echo '<button type="button" id="toggleDeepSeekApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5216 echo '<p class="description api-key-notice">' . esc_html__('Required for your selected chat model. Important: You must add credits before use.', 'mxchat') . '</p>';5154 echo '<p class="description">' . esc_html__('Required for DeepSeek models. Get your API key from DeepSeek Platform.', 'mxchat') . '</p>'; 5217 5155 echo '</div>'; 5218 5156 } … … 5222 5160 $geminiApiKey = isset($this->options['gemini_api_key']) ? esc_attr($this->options['gemini_api_key']) : ''; 5223 5161 5224 echo '<div class="api-key-wrapper" data-provider="gemini">';5162 echo '<div class="api-key-wrapper">'; 5225 5163 echo '<input type="password" id="gemini_api_key" name="gemini_api_key" value="' . $geminiApiKey . '" class="regular-text" autocomplete="off" />'; 5226 5164 echo '<button type="button" id="toggleGeminiApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5227 echo '<p class="description api-key-notice">' . esc_html__('Required for Google Gemini models. Get your API key from Google AI Studio.', 'mxchat') . '</p>';5165 echo '<p class="description">' . esc_html__('Required for Google Gemini models and embeddings. Get your API key from Google AI Studio.', 'mxchat') . '</p>'; 5228 5166 echo '</div>'; 5229 5167 } … … 5233 5171 public function openrouter_api_key_callback() { 5234 5172 $openrouterApiKey = isset($this->options['openrouter_api_key']) ? esc_attr($this->options['openrouter_api_key']) : ''; 5235 echo '<div class="api-key-wrapper" data-provider="openrouter">';5173 echo '<div class="api-key-wrapper">'; 5236 5174 echo '<input type="password" id="openrouter_api_key" name="openrouter_api_key" value="' . $openrouterApiKey . '" class="regular-text" autocomplete="off" />'; 5237 5175 echo '<button type="button" id="toggleOpenRouterApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5238 echo '<p class="description api-key-notice">' . esc_html__('Required only if using OpenRouter. Get your API key from OpenRouter.ai', 'mxchat') . '</p>';5176 echo '<p class="description">' . esc_html__('Required for OpenRouter models. Get your API key from OpenRouter.ai', 'mxchat') . '</p>'; 5239 5177 echo '</div>'; 5240 5178 } … … 5244 5182 $apiKey = isset($this->options['voyage_api_key']) ? esc_attr($this->options['voyage_api_key']) : ''; 5245 5183 5246 echo '<div class="api-key-wrapper" data-provider="voyage">';5184 echo '<div class="api-key-wrapper">'; 5247 5185 echo '<input type="password" id="voyage_api_key" name="voyage_api_key" value="' . $apiKey . '" class="regular-text" autocomplete="off" />'; 5248 5186 echo '<button type="button" id="toggleVoyageAPIKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5249 echo '<p class="description api-key-notice">' . esc_html__('Required for your selected embedding model. Important: You must add credits before use.', 'mxchat') . '</p>';5187 echo '<p class="description">' . esc_html__('Required for Voyage AI embedding models. Get your API key from Voyage AI.', 'mxchat') . '</p>'; 5250 5188 echo '</div>'; 5251 5189 } … … 5258 5196 echo '<input type="password" style="display:none" autocomplete="current-password" />'; 5259 5197 5260 echo '<div class="api-key-wrapper" data-provider="loops">';5198 echo '<div class="api-key-wrapper">'; 5261 5199 echo sprintf( 5262 5200 '<input type="password" id="loops_api_key" name="loops_api_key" value="%s" class="regular-text" autocomplete="new-password" />', … … 5265 5203 echo '<button type="button" id="toggleLoopsApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 5266 5204 echo '</div>'; 5267 echo '<p class="description">' . esc_html__(' Enter your Loops API Key here. Once entered, refreshed page to load list (See FAQ for details)', 'mxchat') . '</p>';5205 echo '<p class="description">' . esc_html__('Required for Loops email integration. Get your API key from Loops.so', 'mxchat') . '</p>'; 5268 5206 } 5269 5207 public function mxchat_loops_mailing_list_callback() { … … 5510 5448 5511 5449 echo '<p class="description">' . esc_html__('Select the AI model your chatbot will use for chatting.', 'mxchat') . '</p>'; 5512 5450 5513 5451 // Add a note for OpenRouter 5514 5452 echo '<p class="description" id="openrouter-model-note" style="display:none; color: #d63638; font-weight: 500;">'; … … 5516 5454 echo esc_html__('After entering your OpenRouter API key above, click the button below to load available models.', 'mxchat'); 5517 5455 echo '</p>'; 5456 5457 // API Key Status Messages (hidden by default, shown by JS based on selected model) 5458 $has_openai_key = !empty($this->options['api_key']); 5459 $has_claude_key = !empty($this->options['claude_api_key']); 5460 $has_xai_key = !empty($this->options['xai_api_key']); 5461 $has_deepseek_key = !empty($this->options['deepseek_api_key']); 5462 $has_gemini_key = !empty($this->options['gemini_api_key']); 5463 $has_openrouter_key = !empty($this->options['openrouter_api_key']); 5464 5465 // OpenAI/GPT models 5466 echo '<p class="mxchat-api-status" data-provider="openai" style="display:none;">'; 5467 if ($has_openai_key) { 5468 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for OpenAI detected', 'mxchat') . '</span>'; 5469 } else { 5470 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for OpenAI detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5471 } 5472 echo '</p>'; 5473 5474 // Claude models 5475 echo '<p class="mxchat-api-status" data-provider="claude" style="display:none;">'; 5476 if ($has_claude_key) { 5477 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for Anthropic (Claude) detected', 'mxchat') . '</span>'; 5478 } else { 5479 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for Anthropic (Claude) detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5480 } 5481 echo '</p>'; 5482 5483 // X.AI models 5484 echo '<p class="mxchat-api-status" data-provider="xai" style="display:none;">'; 5485 if ($has_xai_key) { 5486 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for X.AI (Grok) detected', 'mxchat') . '</span>'; 5487 } else { 5488 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for X.AI (Grok) detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5489 } 5490 echo '</p>'; 5491 5492 // DeepSeek models 5493 echo '<p class="mxchat-api-status" data-provider="deepseek" style="display:none;">'; 5494 if ($has_deepseek_key) { 5495 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for DeepSeek detected', 'mxchat') . '</span>'; 5496 } else { 5497 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for DeepSeek detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5498 } 5499 echo '</p>'; 5500 5501 // Gemini models 5502 echo '<p class="mxchat-api-status" data-provider="gemini" style="display:none;">'; 5503 if ($has_gemini_key) { 5504 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for Google Gemini detected', 'mxchat') . '</span>'; 5505 } else { 5506 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for Google Gemini detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5507 } 5508 echo '</p>'; 5509 5510 // OpenRouter models 5511 echo '<p class="mxchat-api-status" data-provider="openrouter" style="display:none;">'; 5512 if ($has_openrouter_key) { 5513 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for OpenRouter detected', 'mxchat') . '</span>'; 5514 } else { 5515 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for OpenRouter detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5516 } 5517 echo '</p>'; 5518 5518 5519 // ADD THESE HIDDEN FIELDS RIGHT HERE: 5519 5520 $openrouter_model = isset($this->options['openrouter_selected_model']) ? esc_attr($this->options['openrouter_selected_model']) : ''; 5520 5521 $openrouter_model_name = isset($this->options['openrouter_selected_model_name']) ? esc_attr($this->options['openrouter_selected_model_name']) : ''; 5521 5522 5522 5523 echo '<input type="hidden" id="openrouter_selected_model" name="openrouter_selected_model" value="' . $openrouter_model . '" />'; 5523 5524 echo '<input type="hidden" id="openrouter_selected_model_name" name="openrouter_selected_model_name" value="' . $openrouter_model_name . '" />'; … … 5623 5624 echo '</select>'; 5624 5625 echo '<p class="description"><span class="red-warning">IMPORTANT:</span> A vector embedding model is required for MxChat to function. Changing models is not recommended; if you do, you must delete all existing knowledge & intent data and reconfigure them.</p>'; 5626 5627 // API Key Status Messages for Embedding Models 5628 $has_openai_key = !empty($this->options['api_key']); 5629 $has_voyage_key = !empty($this->options['voyage_api_key']); 5630 $has_gemini_key = !empty($this->options['gemini_api_key']); 5631 5632 // OpenAI Embeddings 5633 echo '<p class="mxchat-embedding-api-status" data-provider="openai" style="display:none;">'; 5634 if ($has_openai_key) { 5635 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for OpenAI detected', 'mxchat') . '</span>'; 5636 } else { 5637 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for OpenAI detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5638 } 5639 echo '</p>'; 5640 5641 // Voyage AI Embeddings 5642 echo '<p class="mxchat-embedding-api-status" data-provider="voyage" style="display:none;">'; 5643 if ($has_voyage_key) { 5644 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for Voyage AI detected', 'mxchat') . '</span>'; 5645 } else { 5646 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for Voyage AI detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5647 } 5648 echo '</p>'; 5649 5650 // Gemini Embeddings 5651 echo '<p class="mxchat-embedding-api-status" data-provider="gemini" style="display:none;">'; 5652 if ($has_gemini_key) { 5653 echo '<span style="color: #00a32a;">✓ ' . esc_html__('API key for Google Gemini detected', 'mxchat') . '</span>'; 5654 } else { 5655 echo '<span style="color: #d63638;">⚠ ' . esc_html__('No API key for Google Gemini detected. Please enter API key in API Keys tab.', 'mxchat') . '</span>'; 5656 } 5657 echo '</p>'; 5625 5658 } 5626 5659 … … 6446 6479 echo '<button type="button" id="toggleBraveApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; 6447 6480 echo '</div>'; 6448 echo '<p class="description">' . __(' Enter your Brave Search API Key here. (See FAQ for details)', 'mxchat') . '</p>';6481 echo '<p class="description">' . __('Required for Brave Search integration. Get your API key from Brave Search API.', 'mxchat') . '</p>'; 6449 6482 } 6450 6483 … … 6771 6804 6772 6805 public function mxchat_enqueue_admin_assets() { 6773 // Get plugin version (define this in your main plugin file)6774 $version = defined('MXCHAT_VERSION') ? MXCHAT_VERSION : '2.5.2';6806 // Get plugin version 6807 $version = MXCHAT_VERSION; 6775 6808 6776 6809 // Use file modification time for development (remove in production) … … 6890 6923 'ajax_url' => admin_url('admin-ajax.php'), 6891 6924 'status_nonce' => wp_create_nonce('mxchat_status_nonce'), 6892 'queue_nonce' => wp_create_nonce('mxchat_queue_nonce'), // ADD THIS LINE6925 'queue_nonce' => wp_create_nonce('mxchat_queue_nonce'), 6893 6926 'stop_nonce' => wp_create_nonce('mxchat_stop_processing_action'), 6894 6927 'settings_nonce' => wp_create_nonce('mxchat_prompts_setting_nonce'), 6928 'setting_nonce' => wp_create_nonce('mxchat_save_setting_nonce'), 6895 6929 'admin_url' => admin_url(), 6896 6930 'ajaxurl' => admin_url('admin-ajax.php'), -
mxchat-basic/trunk/includes/class-mxchat-integrator.php
r3389316 r3392455 1259 1259 'session_id' => $session_id 1260 1260 ]; 1261 1261 1262 // IMPORTANT: Include chat_mode if present (for WhatsApp, Slack, etc.) 1263 if (isset($intent_result['chat_mode'])) { 1264 $response_data['chat_mode'] = $intent_result['chat_mode']; 1265 } 1266 1262 1267 if ($testing_data !== null) { 1263 1268 $response_data['testing_data'] = $testing_data; … … 2845 2850 $history = get_option("mxchat_history_{$session_id}", []); 2846 2851 2852 error_log("MxChat WhatsApp DEBUG: Fetch new messages for session {$session_id}"); 2853 error_log("MxChat WhatsApp DEBUG: last_seen_id = " . var_export($last_seen_id, true)); 2854 error_log("MxChat WhatsApp DEBUG: History count = " . count($history)); 2855 error_log("MxChat WhatsApp DEBUG: Full history = " . print_r($history, true)); 2856 2847 2857 $new_messages = array_filter($history, function ($message) use ($last_seen_id, $persistence_enabled, $initial_timestamp) { 2858 error_log("MxChat WhatsApp DEBUG: Checking message - ID: " . ($message['id'] ?? 'NO_ID') . ", Role: " . ($message['role'] ?? 'NO_ROLE')); 2859 2848 2860 // If persistence is enabled, show all new messages 2849 2861 if ($persistence_enabled) { 2850 return !empty($message['id']) && 2851 strcmp($message['id'], $last_seen_id) > 0 && 2852 $message['role'] === 'agent'; 2862 $has_id = !empty($message['id']); 2863 $is_agent = $message['role'] === 'agent'; 2864 2865 // If last_seen_id is empty, 'NaN', or invalid, show all agent messages 2866 if (empty($last_seen_id) || $last_seen_id === 'NaN' || $last_seen_id === 'undefined') { 2867 $is_newer = true; 2868 } else { 2869 $is_newer = strcmp($message['id'] ?? '', $last_seen_id) > 0; 2870 } 2871 2872 error_log("MxChat WhatsApp DEBUG: has_id={$has_id}, is_newer={$is_newer}, is_agent={$is_agent}"); 2873 2874 return $has_id && $is_newer && $is_agent; 2853 2875 } 2854 2876 … … 2859 2881 }); 2860 2882 2861 //error_log(esc_html__("New agent messages fetched for session $session_id. Last seen ID: $last_seen_id", 'mxchat'));2883 error_log("MxChat WhatsApp DEBUG: Filtered messages count = " . count($new_messages)); 2862 2884 2863 2885 wp_send_json_success([ … … 5008 5030 } 5009 5031 5010 // Prepare the request body with stream: true 5011 $body = json_encode([ 5032 // Check if this is a GPT-5 model (supports reasoning_effort parameter) 5033 $is_gpt5_model = ( 5034 strpos($selected_model, 'gpt-5') === 0 || 5035 $selected_model === 'gpt-5' || 5036 $selected_model === 'gpt-5-mini' || 5037 $selected_model === 'gpt-5-nano' 5038 ); 5039 5040 // Build request body with optimal settings for fast streaming 5041 $request_body = [ 5012 5042 'model' => $selected_model, 5013 5043 'messages' => $formatted_conversation, 5014 5044 'temperature' => 1, 5015 5045 'stream' => true 5016 ]); 5046 ]; 5047 5048 // Add reasoning_effort only for GPT-5 models 5049 if ($is_gpt5_model) { 5050 $request_body['reasoning_effort'] = 'minimal'; // Fastest response for GPT-5 5051 } 5052 5053 $body = json_encode($request_body); 5017 5054 5018 5055 // Use cURL for streaming support … … 6044 6081 6045 6082 // Get bot ID from session or request 6046 $bot_id = $this->get_current_bot_id( $session_id);6083 $bot_id = $this->get_current_bot_id(''); 6047 6084 6048 6085 // Get system prompt instructions using centralized function … … 6078 6115 } 6079 6116 6080 $body = json_encode([ 6117 // Check if this is a GPT-5 model (supports reasoning_effort parameter) 6118 $is_gpt5_model = ( 6119 strpos($selected_model, 'gpt-5') === 0 || 6120 $selected_model === 'gpt-5' || 6121 $selected_model === 'gpt-5-mini' || 6122 $selected_model === 'gpt-5-nano' 6123 ); 6124 6125 // Build request body with optimal settings for fast responses 6126 $request_body = [ 6081 6127 'model' => $selected_model, 6082 6128 'messages' => $formatted_conversation, 6083 6129 'temperature' => 1, 6084 6130 'stream' => false 6085 ]); 6131 ]; 6132 6133 // Add reasoning_effort only for GPT-5 models 6134 if ($is_gpt5_model) { 6135 $request_body['reasoning_effort'] = 'minimal'; // Fastest response for GPT-5 6136 } 6137 6138 $body = json_encode($request_body); 6086 6139 6087 6140 $args = [ … … 6102 6155 if (is_wp_error($response)) { 6103 6156 $error_message = $response->get_error_message(); 6104 //error_log('OpenAI API Error: ' . $error_message);6105 6157 return [ 6106 6158 'error' => esc_html__('Connection error when contacting OpenAI: ', 'mxchat') . esc_html($error_message), … … 6122 6174 ? $decoded_response['error']['type'] 6123 6175 : 'unknown'; 6124 6125 //error_log('OpenAI API HTTP Error: ' . $status_code . ' - ' . $error_message);6126 6176 6127 6177 // Handle specific error types … … 6174 6224 return trim($decoded_response['choices'][0]['message']['content']); 6175 6225 } else { 6176 //error_log('OpenAI API Response Format Error: ' . print_r($decoded_response, true));6177 6226 return [ 6178 6227 'error' => esc_html__('Unexpected response format from OpenAI.', 'mxchat'), … … 6182 6231 } 6183 6232 } catch (Exception $e) { 6184 //error_log('OpenAI Exception: ' . $e->getMessage());6185 6233 return [ 6186 6234 'error' => esc_html__('System error when processing OpenAI request: ', 'mxchat') . esc_html($e->getMessage()), … … 6190 6238 } 6191 6239 } 6240 6192 6241 private function mxchat_generate_response_xai($selected_model, $xai_api_key, $conversation_history, $relevant_content) { 6193 6242 try { … … 6881 6930 6882 6931 public function mxchat_enqueue_scripts_styles() { 6883 // Define version numbers for the styles and scripts6884 $chat_style_version = '2.5.2';6885 $chat_script_version = '2.5.2';6886 6932 // Enqueue the script 6887 6933 wp_enqueue_script( … … 6889 6935 plugin_dir_url(__FILE__) . '../js/chat-script.js', 6890 6936 array('jquery'), 6891 $chat_script_version,6937 MXCHAT_VERSION, 6892 6938 true 6893 6939 ); … … 6897 6943 plugin_dir_url(__FILE__) . '../css/chat-style.css', 6898 6944 array(), 6899 $chat_style_version6945 MXCHAT_VERSION 6900 6946 ); 6901 6947 // Fetch options from the database -
mxchat-basic/trunk/js/chat-script.js
r3389316 r3392455 1355 1355 } 1356 1356 1357 function formatTextStyling(text) { 1358 // Handle bold text (**text**) 1359 text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>'); 1360 1361 // Handle italic text (*text* or _text_) - avoid conflicts with bold 1362 text = text.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, '<em>$1</em>'); 1363 text = text.replace(/(?<!_)_([^_\n]+)_(?!_)/g, '<em>$1</em>'); 1364 1365 // Handle strikethrough (~~text~~) 1366 text = text.replace(/~~(.*?)~~/g, '<del>$1</del>'); 1367 1368 return text; 1369 } 1370 1357 function formatTextStyling(text) { 1358 // IMPORTANT: Protect BOTH HTML href and Markdown URLs from formatting 1359 const protectedSegments = []; 1360 let protectedText = text; 1361 1362 // Step 1a: Protect HTML href="..." attributes 1363 protectedText = protectedText.replace(/href\s*=\s*["']([^"']+)["']/gi, function(match) { 1364 const placeholder = `__PROTECTED_${protectedSegments.length}__`; 1365 protectedSegments.push(match); 1366 return placeholder; 1367 }); 1368 1369 // Step 1b: Protect Markdown links [text](url) 1370 // This is crucial - we need to protect the URLs in markdown format 1371 protectedText = protectedText.replace(/\[([^\]]*)\]\(([^)]+)\)/g, function(match) { 1372 const placeholder = `__PROTECTED_${protectedSegments.length}__`; 1373 protectedSegments.push(match); 1374 return placeholder; 1375 }); 1376 1377 // Step 1c: Also protect bare URLs that might exist 1378 protectedText = protectedText.replace(/(https?:\/\/[^\s<>"]+)/gi, function(match) { 1379 const placeholder = `__PROTECTED_${protectedSegments.length}__`; 1380 protectedSegments.push(match); 1381 return placeholder; 1382 }); 1383 1384 // Step 2: Now apply text styling to the protected text 1385 // Handle bold text (**text**) 1386 protectedText = protectedText.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>'); 1387 1388 // Handle italic text (*text* or _text_) - avoid conflicts with bold 1389 protectedText = protectedText.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, '<em>$1</em>'); 1390 1391 // Handle underscores for italic - this won't touch URLs now since they're protected 1392 protectedText = protectedText.replace(/(?<!_)_([^_\n]+)_(?!_)/g, '<em>$1</em>'); 1393 1394 // Handle strikethrough (~~text~~) 1395 protectedText = protectedText.replace(/~~(.*?)~~/g, '<del>$1</del>'); 1396 1397 // Step 3: Restore all protected segments 1398 protectedSegments.forEach((original, index) => { 1399 const placeholder = `__PROTECTED_${index}__`; 1400 protectedText = protectedText.replace(placeholder, original); 1401 }); 1402 1403 return protectedText; 1404 } 1371 1405 function formatBoldText(text) { 1372 1406 // This function is kept for compatibility but now uses formatTextStyling -
mxchat-basic/trunk/js/knowledge-processing.js
r3389316 r3392455 7 7 let currentQueueId = null; 8 8 let currentQueueType = null; 9 9 10 // Process 5 items at a time 11 const BATCH_SIZE = 5; 12 10 13 // Check if we should start queue processing on page load 11 14 checkForActiveQueues(); … … 115 118 // Create or update status card 116 119 createOrUpdateStatusCard(queueType); 117 118 // Start the processing loop119 processNext QueueItem();120 } 121 122 /** 123 * Process the next item in the queue124 */ 125 function processNext QueueItem() {120 121 // Start the batch processing loop 122 processNextBatch(); 123 } 124 125 /** 126 * Process the next batch of items (5 at a time) 127 */ 128 function processNextBatch() { 126 129 if (!isProcessingQueue) { 127 130 //console.log('MxChat: Processing stopped'); 128 131 return; 129 132 } 130 131 // Get next item from queue 132 $.ajax({ 133 url: ajaxurl, 134 type: 'POST', 135 data: { 136 action: 'mxchat_get_next_queue_item', 137 nonce: mxchatAdmin.queue_nonce, 138 queue_id: currentQueueId 139 }, 140 success: function(response) { 141 if (!response.success) { 142 console.error('MxChat: Error getting next queue item:', response.data); 143 // Check if queue is actually complete despite error 133 134 // Fetch the next batch of items 135 const fetchPromises = []; 136 137 for (let i = 0; i < BATCH_SIZE; i++) { 138 const promise = $.ajax({ 139 url: ajaxurl, 140 type: 'POST', 141 data: { 142 action: 'mxchat_get_next_queue_item', 143 nonce: mxchatAdmin.queue_nonce, 144 queue_id: currentQueueId 145 } 146 }); 147 fetchPromises.push(promise); 148 } 149 150 // Wait for all fetch requests to complete 151 Promise.all(fetchPromises).then(function(responses) { 152 // Filter out completed/error responses and extract items 153 const items = []; 154 let queueComplete = false; 155 156 for (let response of responses) { 157 if (response.success && response.data && !response.data.complete) { 158 items.push(response.data.item); 159 } else if (response.data && response.data.complete) { 160 queueComplete = true; 161 } 162 } 163 164 // If no items to process, queue is done 165 if (items.length === 0) { 166 if (queueComplete) { 167 handleQueueComplete(); 168 } else { 144 169 verifyQueueCompletion(); 145 return; 146 } 147 148 if (response.data.complete) { 149 // Queue is complete! 150 //console.log('MxChat: Queue processing complete!'); 151 handleQueueComplete(); 152 return; 153 } 154 155 // Process this item 156 const item = response.data.item; 157 //console.log('MxChat: Processing item:', item.type, item.id); 158 159 processQueueItem(item); 160 }, 161 error: function(xhr, status, error) { 162 console.error('MxChat: AJAX error getting next item:', error); 163 // Network error - verify queue status before retrying 170 } 171 return; 172 } 173 174 // Process all items in this batch simultaneously 175 const processPromises = items.map(item => processQueueItem(item)); 176 177 // Wait for all items to finish processing 178 Promise.all(processPromises).then(function() { 179 // Update progress after batch completes 180 updateQueueProgress(); 181 182 // If we got fewer items than batch size, queue might be done 183 if (items.length < BATCH_SIZE || queueComplete) { 184 verifyQueueCompletion(); 185 } else { 186 // Process next batch immediately 187 processNextBatch(); 188 } 189 }).catch(function(error) { 190 console.error('MxChat: Error processing batch:', error); 191 // Continue anyway 192 updateQueueProgress(); 164 193 setTimeout(function() { 165 verifyQueueCompletion(); 166 }, 2000); 167 } 194 processNextBatch(); 195 }, 1000); 196 }); 197 198 }).catch(function(error) { 199 console.error('MxChat: Error fetching batch:', error); 200 // Verify queue status before retrying 201 setTimeout(function() { 202 verifyQueueCompletion(); 203 }, 2000); 168 204 }); 169 205 } … … 195 231 // Still has items, try to continue 196 232 //console.log('MxChat: Queue still has pending items, continuing...'); 197 processNext QueueItem();233 processNextBatch(); 198 234 } 199 235 } else { … … 213 249 /** 214 250 * Process a single queue item 215 * Never stops the queue - always continues regardless of success/failure251 * Returns a Promise that resolves when processing is complete 216 252 */ 217 253 function processQueueItem(item) { 218 $.ajax({254 return $.ajax({ 219 255 url: ajaxurl, 220 256 type: 'POST', … … 226 262 item_data: item.data, 227 263 bot_id: item.bot_id 228 }, 229 success: function(response) { 230 if (response.success) { 231 // Item processed successfully 232 //console.log('MxChat: Item processed successfully:', item.id); 233 234 // Update progress 235 updateQueueProgress(); 236 237 // Small delay to prevent server overload, then process next 238 setTimeout(function() { 239 processNextQueueItem(); 240 }, 500); // 500ms delay between items 241 242 } else { 243 // Item failed but we KEEP GOING 244 console.warn('MxChat: Item processing failed (will continue):', item.type, item.id); 245 console.warn('MxChat: Error details:', response.data); 246 247 // Update progress to reflect the attempt 248 updateQueueProgress(); 249 250 // Continue to next item regardless 251 setTimeout(function() { 252 processNextQueueItem(); 253 }, 500); 254 } 255 }, 256 error: function(xhr, status, error) { 257 // Network error - log it but KEEP GOING 258 console.error('MxChat: AJAX/Network error processing item:', item.id, error); 259 260 // Update progress 261 updateQueueProgress(); 262 263 // Wait a bit longer for network errors, then continue 264 setTimeout(function() { 265 processNextQueueItem(); 266 }, 1000); 267 } 264 } 265 }).then(function(response) { 266 if (response.success) { 267 // Item processed successfully 268 //console.log('MxChat: Item processed successfully:', item.id); 269 return true; 270 } else { 271 // Item failed but we KEEP GOING 272 console.warn('MxChat: Item processing failed (will continue):', item.type, item.id); 273 console.warn('MxChat: Error details:', response.data); 274 return false; 275 } 276 }).catch(function(xhr, status, error) { 277 // Network error - log it but KEEP GOING 278 console.error('MxChat: AJAX/Network error processing item:', item.id, error); 279 return false; 268 280 }); 269 281 } -
mxchat-basic/trunk/js/mxchat-admin.js
r3386482 r3392455 486 486 }); 487 487 }); 488 488 489 // *** ADD THIS: Refresh API key status after saving an API key *** 490 const isApiKeyField = name && ( 491 name === 'api_key' || 492 name === 'xai_api_key' || 493 name === 'claude_api_key' || 494 name === 'voyage_api_key' || 495 name === 'gemini_api_key' || 496 name === 'deepseek_api_key' || 497 name === 'openrouter_api_key' || 498 name.indexOf('_api_key') !== -1 499 ); 500 501 if (isApiKeyField && typeof window.mxchatRefreshAPIKeyStatus === 'function') { 502 window.mxchatRefreshAPIKeyStatus(); 503 } 504 489 505 // *** ADD THIS: Update Pinecone checkbox state after successful save *** 490 506 if (name && name.indexOf('mxchat_pinecone_addon_options[mxchat_use_pinecone]') !== -1) { … … 740 756 ].forEach(toggleVisibility); 741 757 742 // Handle API key visibility based on model selection743 function setupAPIKeyVisibility() {744 // Cache the selectors745 const $chatModelSelect = $('#model');746 const $embeddingModelSelect = $('#embedding_model');747 748 // First, locate and mark the API key rows749 setupAPIKeyRows();750 751 // Initial setup based on current selections752 updateApiKeyVisibility();753 754 // Listen for changes to the model selectors755 $chatModelSelect.on('change', updateApiKeyVisibility);756 $embeddingModelSelect.on('change', updateApiKeyVisibility);757 758 /**759 * Locate and mark rows that contain API key fields760 */761 function setupAPIKeyRows() {762 // Find key rows by their field IDs763 const providerMap = {764 'api_key': 'openai',765 'xai_api_key': 'xai',766 'claude_api_key': 'claude',767 'deepseek_api_key': 'deepseek',768 'voyage_api_key': 'voyage',769 'gemini_api_key': 'gemini' // Added Gemini API key mapping770 };771 772 $.each(providerMap, function(fieldId, provider) {773 const $field = $('#' + fieldId);774 if ($field.length) {775 const $row = $field.closest('tr');776 $row.addClass('mxchat-setting-row');777 $row.attr('data-provider', provider);778 }779 });780 }781 782 /**783 * Updates the visibility of API key fields based on current model selections784 */785 function updateApiKeyVisibility() {786 const chatModel = $chatModelSelect.val();787 const embeddingModel = $embeddingModelSelect.val();788 789 // Determine which providers are needed790 const isOpenAIChat = chatModel && chatModel.startsWith('gpt-');791 const isXAI = chatModel && chatModel.startsWith('grok-');792 const isClaude = chatModel && chatModel.startsWith('claude-');793 const isDeepSeek = chatModel && chatModel.startsWith('deepseek-');794 const isGemini = chatModel && chatModel.startsWith('gemini-'); // Added Gemini detection795 796 const isOpenAIEmbedding = embeddingModel && embeddingModel.startsWith('text-embedding-');797 const isVoyage = embeddingModel && embeddingModel.startsWith('voyage-');798 const isGeminiEmbedding = embeddingModel && embeddingModel.startsWith('gemini-embedding-');799 800 // Update API key visibility for each provider801 updateWrapperVisibility('openai', isOpenAIChat || isOpenAIEmbedding);802 updateWrapperVisibility('xai', isXAI);803 updateWrapperVisibility('claude', isClaude);804 updateWrapperVisibility('deepseek', isDeepSeek);805 updateWrapperVisibility('voyage', isVoyage);806 updateWrapperVisibility('gemini', isGemini || isGeminiEmbedding); // Updated Gemini visibility for both chat and embedding807 808 // Update provider-specific notices for OpenAI809 if (isOpenAIChat && isOpenAIEmbedding) {810 $('div[data-provider="openai"] .api-key-notice').text(811 'Required for your selected chat model and embedding model. Important: You must add credits before use.'812 );813 } else if (isOpenAIChat) {814 $('div[data-provider="openai"] .api-key-notice').text(815 'Required for your selected chat model. Important: You must add credits before use.'816 );817 } else if (isOpenAIEmbedding) {818 $('div[data-provider="openai"] .api-key-notice').text(819 'Required for your selected embedding model. Important: You must add credits before use.'820 );821 }822 823 // Update provider-specific notices for Gemini824 if (isGemini && isGeminiEmbedding) {825 $('div[data-provider="gemini"] .api-key-notice').text(826 'Required for your selected chat model and embedding model.'827 );828 } else if (isGemini) {829 $('div[data-provider="gemini"] .api-key-notice').text(830 'Required for your selected chat model.'831 );832 } else if (isGeminiEmbedding) {833 $('div[data-provider="gemini"] .api-key-notice').text(834 'Required for your selected embedding model.'835 );836 }837 }838 839 /**840 * Updates visibility of a specific provider's API key wrapper841 */842 function updateWrapperVisibility(provider, isVisible) {843 const $row = $('tr.mxchat-setting-row[data-provider="' + provider + '"]');844 845 if (!$row.length) {846 //console.warn('API key row not found for provider: ' + provider);847 return;848 }849 850 if (isVisible) {851 $row.show();852 if (!$row.hasClass('highlighted')) {853 $row.addClass('highlighted');854 setTimeout(() => {855 $row.removeClass('highlighted');856 }, 1500);857 }858 } else {859 $row.hide();860 }861 }862 }863 864 758 function setupMxChatModelSelector() { 865 759 const $modelSelect = $('#model'); … … 1749 1643 setupMxChatEmbeddingModelSelector(); 1750 1644 }); 1751 1752 // Initialize API key visibility 1753 setupAPIKeyVisibility(); 1754 1645 1755 1646 // Add Intent Form Submission 1756 1647 $('#mxchat-add-intent-form').on('submit', function(event) { … … 2688 2579 }); 2689 2580 }); 2581 2582 // Bot Selector Handler 2583 jQuery(document).ready(function($) { 2584 var saveTimer; 2585 2586 // Function to update bot_id in forms 2587 function updateBotIdInForm(formSelector) { 2588 var botId = $('#mxchat-bot-selector').val(); 2589 var form = $(formSelector); 2590 2591 if (form.length > 0) { 2592 // Remove existing bot_id hidden input 2593 form.find('input[name="bot_id"]').remove(); 2594 2595 // Add new bot_id hidden input if not default 2596 if (botId && botId !== 'default') { 2597 form.append('<input type="hidden" name="bot_id" value="' + botId + '">'); 2598 } 2599 } 2600 } 2601 2602 $('#mxchat-bot-selector').on('change', function() { 2603 var botId = $(this).val(); 2604 2605 // Clear any existing timer 2606 clearTimeout(saveTimer); 2607 2608 // Update all forms with new bot_id when bot selection changes 2609 updateBotIdInForm('#mxchat-url-form'); 2610 updateBotIdInForm('#mxchat-content-form'); 2611 2612 // Save the selection via AJAX 2613 $.ajax({ 2614 url: ajaxurl, 2615 type: 'POST', 2616 data: { 2617 action: 'mxchat_save_selected_bot', 2618 bot_id: botId, 2619 nonce: mxchatAdmin.setting_nonce 2620 }, 2621 success: function(response) { 2622 if (response.success) { 2623 // Show saved indicator 2624 $('#mxchat-bot-save-status').fadeIn().delay(2000).fadeOut(); 2625 2626 // Reload the page after a short delay to refresh content 2627 saveTimer = setTimeout(function() { 2628 var currentUrl = new URL(window.location.href); 2629 currentUrl.searchParams.set('bot_id', botId); 2630 currentUrl.searchParams.set('page', 'mxchat-prompts'); 2631 window.location.href = currentUrl.toString(); 2632 }, 500); 2633 } 2634 }, 2635 error: function() { 2636 console.error('Failed to save bot selection'); 2637 } 2638 }); 2639 }); 2640 2641 // Initialize forms with current bot_id when the page loads 2642 setTimeout(function() { 2643 updateBotIdInForm('#mxchat-url-form'); 2644 updateBotIdInForm('#mxchat-content-form'); 2645 }, 100); 2646 }); 2647 2648 // API Key Status Indicator for Chat Models 2649 jQuery(document).ready(function($) { 2650 function updateChatModelAPIStatus(apiKeyStatuses) { 2651 var selectedModel = $('#model').val(); 2652 2653 // Hide all status messages 2654 $('.mxchat-api-status').hide(); 2655 2656 // Return early if no model is selected 2657 if (!selectedModel) { 2658 return; 2659 } 2660 2661 // Map models to providers 2662 var provider = null; 2663 2664 if (selectedModel.startsWith('gpt-')) { 2665 provider = 'openai'; 2666 } else if (selectedModel.startsWith('claude-')) { 2667 provider = 'claude'; 2668 } else if (selectedModel.startsWith('grok-')) { 2669 provider = 'xai'; 2670 } else if (selectedModel.startsWith('deepseek-')) { 2671 provider = 'deepseek'; 2672 } else if (selectedModel.startsWith('gemini-')) { 2673 provider = 'gemini'; 2674 } else if (selectedModel === 'openrouter') { 2675 provider = 'openrouter'; 2676 } 2677 2678 // If we have fresh API key data, update the messages 2679 if (apiKeyStatuses && provider && apiKeyStatuses[provider] !== undefined) { 2680 var $statusElement = $('.mxchat-api-status[data-provider="' + provider + '"]'); 2681 var hasKey = apiKeyStatuses[provider]; 2682 2683 if (hasKey) { 2684 $statusElement.html('<span style="color: #00a32a;">✓ API key for ' + getProviderName(provider) + ' detected</span>'); 2685 } else { 2686 $statusElement.html('<span style="color: #d63638;">⚠ No API key for ' + getProviderName(provider) + ' detected. Please enter API key in API Keys tab.</span>'); 2687 } 2688 } 2689 2690 // Show the appropriate status message 2691 if (provider) { 2692 $('.mxchat-api-status[data-provider="' + provider + '"]').show(); 2693 } 2694 } 2695 2696 function updateEmbeddingModelAPIStatus(apiKeyStatuses) { 2697 var selectedModel = $('#embedding_model').val(); 2698 2699 // Hide all status messages 2700 $('.mxchat-embedding-api-status').hide(); 2701 2702 // Return early if no model is selected 2703 if (!selectedModel) { 2704 return; 2705 } 2706 2707 // Map models to providers 2708 var provider = null; 2709 2710 if (selectedModel.startsWith('text-embedding-')) { 2711 provider = 'openai'; 2712 } else if (selectedModel.startsWith('voyage-')) { 2713 provider = 'voyage'; 2714 } else if (selectedModel.startsWith('gemini-embedding-')) { 2715 provider = 'gemini'; 2716 } 2717 2718 // If we have fresh API key data, update the messages 2719 if (apiKeyStatuses && provider && apiKeyStatuses[provider] !== undefined) { 2720 var $statusElement = $('.mxchat-embedding-api-status[data-provider="' + provider + '"]'); 2721 var hasKey = apiKeyStatuses[provider]; 2722 2723 if (hasKey) { 2724 $statusElement.html('<span style="color: #00a32a;">✓ API key for ' + getProviderName(provider) + ' detected</span>'); 2725 } else { 2726 $statusElement.html('<span style="color: #d63638;">⚠ No API key for ' + getProviderName(provider) + ' detected. Please enter API key in API Keys tab.</span>'); 2727 } 2728 } 2729 2730 // Show the appropriate status message 2731 if (provider) { 2732 $('.mxchat-embedding-api-status[data-provider="' + provider + '"]').show(); 2733 } 2734 } 2735 2736 function getProviderName(provider) { 2737 var names = { 2738 'openai': 'OpenAI', 2739 'claude': 'Anthropic (Claude)', 2740 'xai': 'X.AI (Grok)', 2741 'deepseek': 'DeepSeek', 2742 'gemini': 'Google Gemini', 2743 'openrouter': 'OpenRouter', 2744 'voyage': 'Voyage AI' 2745 }; 2746 return names[provider] || provider; 2747 } 2748 2749 function refreshAPIKeyStatus() { 2750 $.ajax({ 2751 url: ajaxurl, 2752 type: 'POST', 2753 data: { 2754 action: 'mxchat_check_api_keys', 2755 nonce: mxchatAdmin.setting_nonce 2756 }, 2757 success: function(response) { 2758 if (response.success && response.data) { 2759 updateChatModelAPIStatus(response.data); 2760 updateEmbeddingModelAPIStatus(response.data); 2761 } 2762 } 2763 }); 2764 } 2765 2766 // Expose refresh function globally so auto-save can call it 2767 window.mxchatRefreshAPIKeyStatus = refreshAPIKeyStatus; 2768 2769 // Run on page load 2770 updateChatModelAPIStatus(); 2771 updateEmbeddingModelAPIStatus(); 2772 2773 // Check if we just saved settings (WordPress redirects with ?settings-updated=true) 2774 var urlParams = new URLSearchParams(window.location.search); 2775 if (urlParams.get('settings-updated') === 'true') { 2776 // Page was just reloaded after save, fetch fresh API key status 2777 refreshAPIKeyStatus(); 2778 } 2779 2780 // Run when model changes 2781 $('#model').on('change', function() { updateChatModelAPIStatus(); }); 2782 $('#embedding_model').on('change', function() { updateEmbeddingModelAPIStatus(); }); 2783 }); -
mxchat-basic/trunk/mxchat-basic.php
r3389316 r3392455 4 4 * Plugin URI: https://mxchat.ai/ 5 5 * Description: AI chatbot for WordPress with OpenAI, Claude, xAI, DeepSeek, live agent, PDF uploads, WooCommerce, and training on website data. 6 * Version: 2.5. 26 * Version: 2.5.3 7 7 * Author: MxChat 8 8 * Author URI: https://mxchat.ai … … 18 18 19 19 // Define plugin version constant for asset versioning 20 define('MXCHAT_VERSION', '2.5.2'); 20 // Reads version from plugin header automatically 21 if (!defined('MXCHAT_VERSION')) { 22 $plugin_data = get_file_data(__FILE__, array('Version' => 'Version'), 'plugin'); 23 define('MXCHAT_VERSION', $plugin_data['Version']); 24 } 21 25 22 26 function mxchat_load_textdomain() { … … 811 815 812 816 if (class_exists('MxChat_Integrator')) { 817 global $mxchat_integrator; 813 818 $mxchat_integrator = new MxChat_Integrator(); 814 819 } -
mxchat-basic/trunk/readme.txt
r3389316 r3392455 6 6 Tested up to: 6.8 7 7 Requires PHP: 7.2 8 Stable tag: 2.5. 28 Stable tag: 2.5.3 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 15 15 16 16 [Documentation](https://mxchat.ai/documentation/) 17 18 ### 📦 Optional Premium Add-Ons19 Extend 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 forms22 - [WooCommerce Add-On](https://mxchat.ai/woocommerce/) – AI-powered shopping assistance and product recommendations23 - [AI Theme Customizer Add-On](https://mxchat.ai/ai-theme-customizer/) – Instantly design chatbot themes with natural language24 - [Multi-Bot Add-On](https://mxchat.ai/multi-bot/) – Run unlimited AI chatbots with custom knowledge and personalities25 - [Image Analysis Add-On](https://mxchat.ai/image-analysis/) – Enable AI-powered image analysis and OCR inside chats26 27 👉 [Visit our website to view all add-ons](https://mxchat.ai)28 29 ### 🎥 Product Demo Videos30 [Explore all product videos on YouTube](https://www.youtube.com/@MxChat/videos)31 17 32 18 ## Why Choose MxChat AI Chatbot for Your WordPress Website? … … 39 25 ✅ **Extensive Add-On Ecosystem**: Forms, moderation, recommendations, theme customization, and more 40 26 41 ## 🔥 What's New in Version 2.5.2 27 ### 📦 Optional Premium Add-Ons 28 Extend the free plugin with these optional premium features: 29 30 - [Forms Action Add-On](https://mxchat.ai/forms-action/) – Capture leads and data with custom in-chat forms 31 - [WooCommerce Add-On](https://mxchat.ai/woocommerce/) – AI-powered shopping assistance and product recommendations 32 - [AI Theme Customizer Add-On](https://mxchat.ai/ai-theme-customizer/) – Instantly design chatbot themes with natural language 33 - [Multi-Bot Add-On](https://mxchat.ai/multi-bot/) – Run unlimited AI chatbots with custom knowledge and personalities 34 - [Image Analysis Add-On](https://mxchat.ai/image-analysis/) – Enable AI-powered image analysis and OCR inside chats 35 36 👉 [Visit our website to view all add-ons](https://mxchat.ai) 37 38 ### 🎥 Product Demo Videos 39 [Explore all product videos on YouTube](https://www.youtube.com/@MxChat/videos) 40 41 ## 🔥 What's New in Version 2.5.3 42 42 43 🚀 **New Features** 43 - **URL Hallucination Prevention System** - The AI now only cites URLs that exist in your knowledge base or system instructions. Any hallucinated or invented URLs are automatically removed from responses, ensuring users only receive valid, working links. Admins can view approved URLs in the debug panel for complete transparency. 44 - **Improved Background Processing System** - Replaced unreliable cron-based processing with a robust queue system for sitemap and PDF imports. Processing now runs directly in your browser tab with real-time progress tracking, ensuring reliable completion of large imports without server timeouts or missed jobs. 44 - **Dedicated API Key Management Tab** - All API keys now organized in one central tab for easier management and overview. 45 45 46 46 🔧 **Improvements** 47 - **Faster Response Times** - Optimized knowledge retrieval to use the top 3 most relevant documents (down from 5), resulting in quicker chatbot responses and improved answer accuracy by reducing information overload. 47 - **GPT-5 Performance Fix** - Significantly faster response times for all GPT-5 models by implementing minimal reasoning effort mode. 48 - **URL & PDF Link Fix** - Resolved encoding issues causing broken or unclickable links in chatbot responses. 49 - **Performance Enhancements** - Various optimizations for improved stability and faster processing. 48 50 49 51 ## Core Features That Set MxChat Apart … … 87 89 🟢 **Chat Moderation** – Advanced security with email/IP banning and content filtering 88 90 🟢 **Smart Recommender** – Intelligent recommendation flows with customizable matching algorithms 89 🟢 **Perplexity Integration** – Real-time web search with authoritative, well-sourced responses 91 🟢 **Perplexity Integration** – Real-time web search with authoritative, well-sourced responses 92 🟢 **Migration Tool** – Seamlessly switch embedding models and vector databases without losing data, with batch processing and real-time progress tracking 90 93 91 94 ## 📱 Mobile-Friendly & Fully Customizable … … 181 184 182 185 == Changelog == 186 187 = 2.5.3 - November 9, 2025 = 188 - New: Dedicated API Key Management Tab - All API keys organized in one central location for easier management 189 - Improvement: GPT-5 performance optimization with minimal reasoning effort mode for significantly faster response times 190 - Fix: Resolved URL and PDF link encoding issues causing broken or unclickable links in responses 191 - Improvement: Various performance enhancements for improved stability and faster processing 183 192 184 193 = 2.5.2 - November 3, 2025 = … … 579 588 == Upgrade Notice == 580 589 581 = 2.5.2 = 582 - New: URL Hallucination Prevention System - AI only cites URLs from knowledge base or system instructions, with automatic removal of invalid links 583 - Improvement: Brand new robust queue-based processing system for sitemap and PDF imports with real-time progress tracking 584 - Improvement: Optimized knowledge retrieval from 5 to 3 documents for faster response times and improved accuracy 585 - Improvement: Increased URL column size to TEXT type for support of long URLs and special characters (Hebrew, Arabic, etc.) 586 - Fix: Resolved URL double-encoding issue causing malformed PDF and document links 587 - Fix: Corrected citation-style bracket handling for AI responses containing [URL] format 588 - Fix: Fixed empty markdown link processing to prevent broken link generation 590 = 2.5.3 = 591 - New: Dedicated API Key Management Tab - All API keys organized in one central location for easier management 592 - Improvement: GPT-5 performance optimization with minimal reasoning effort mode for significantly faster response times 593 - Fix: Resolved URL and PDF link encoding issues causing broken or unclickable links in responses 594 - Improvement: Various performance enhancements for improved stability and faster processing 589 595 590 596 == License & Warranty ==
Note: See TracChangeset
for help on using the changeset viewer.