PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 3.2.0
MxChat – AI Chatbot & Content Generation for WordPress v3.2.0
3.2.21 3.2.20 3.2.19 3.2.18 3.2.17 3.2.16 3.2.15 3.2.14 3.2.12 3.2.13 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 3.2.6 3.2.5 3.2.4 3.2.3 3.2.2 3.2.1 2.0.3 2.0.4 2.0.5 2.0.6 All 152 releases
← All changes | js/mxchat-admin.js +48 -162 3.2.83.2.0 View file →
@@ -994,9 +994,8 @@
994 994 <button class="mxchat-model-category-btn" data-category="openai">OpenAI</button>
995 995 <button class="mxchat-model-category-btn" data-category="claude">Claude</button>
996 996 <button class="mxchat-model-category-btn" data-category="xai">X.AI</button>
997 997 <button class="mxchat-model-category-btn" data-category="deepseek">DeepSeek</button>
998 - <button class="mxchat-model-category-btn" data-category="custom">Custom / Local</button>
999 998 </div>
1000 999 <div class="mxchat-model-selector-grid" id="mxchat_models_grid"></div>
1001 1000 </div>
1002 1001 <div class="mxchat-model-selector-modal-footer">
@@ -1011,37 +1010,59 @@
1011 1010 // MOVE THIS OUTSIDE - Make it a property of the window object so it's accessible globally
1012 1011 window.populateModelsGrid = function(filter = '', category = 'all') {
1013 1012 const $grid = $('#mxchat_models_grid');
1014 1013 $grid.empty();
1015 -
1016 - // Catalog refactor (plan-d14e89): when class-mxchat-model-catalog.php
1017 - // is loaded (via wp_localize_script as mxchatChatModelCatalog), use
1018 - // its data so a single edit there flows to this picker grid. The
1019 - // inline fallback below keeps the picker working if for some reason
1020 - // the localize hasn't run (e.g. legacy admin page bootstrap order).
1021 - const models = (typeof mxchatChatModelCatalog === 'object' && mxchatChatModelCatalog) ? mxchatChatModelCatalog : {
1014 +
1015 + const models = {
1022 1016 openrouter: [
1023 1017 { value: 'openrouter', label: 'OpenRouter', description: 'Access 100+ models from multiple providers (add API key to browse)' }
1024 1018 ],
1025 1019 gemini: [
1026 - { value: 'gemini-3.5-flash', label: 'Gemini 3.5 Flash', description: 'Stable — newest Flash generation, recommended default' },
1020 + { value: 'gemini-3-pro-preview', label: 'Gemini 3 Pro', description: 'Most intelligent model - multimodal understanding & agentic' },
1021 + { value: 'gemini-3-flash-preview', label: 'Gemini 3 Flash', description: 'Most balanced - speed, scale & frontier intelligence' },
1022 + { value: 'gemini-2.5-pro', label: 'Gemini 2.5 Pro', description: 'Advanced thinking - code, math, STEM & long context' },
1023 + { value: 'gemini-2.5-flash', label: 'Gemini 2.5 Flash', description: 'Best price-performance with thinking capabilities' },
1024 + { value: 'gemini-2.5-flash-lite', label: 'Gemini 2.5 Flash-Lite', description: 'Ultra fast - optimized for cost & high throughput' },
1025 + { value: 'gemini-2.0-flash', label: 'Gemini 2.0 Flash', description: 'Deprecated March 2026' },
1026 + { value: 'gemini-2.0-flash-lite', label: 'Gemini 2.0 Flash-Lite', description: 'Deprecated March 2026' },
1027 + { value: 'gemini-1.5-pro', label: 'Gemini 1.5 Pro', description: 'Deprecated September 2025' },
1028 + { value: 'gemini-1.5-flash', label: 'Gemini 1.5 Flash', description: 'Deprecated September 2025' },
1027 1029 ],
1028 1030 openai: [
1031 + { value: 'gpt-5.4', label: 'GPT-5.4', description: 'Flagship reasoning and coding model' },
1032 + { value: 'gpt-5.4-mini', label: 'GPT-5.4 Mini', description: 'Fast and affordable with 400K context' },
1033 + { value: 'gpt-5.4-nano', label: 'GPT-5.4 Nano', description: 'Fastest and cheapest for lightweight tasks' },
1034 + { value: 'gpt-5.3-chat-latest', label: 'GPT-5.3 Chat', description: 'Optimized for natural conversations with reduced hallucinations' },
1035 + { value: 'gpt-5.2', label: 'GPT-5.2', description: 'Best general-purpose & agentic model with fast responses' },
1029 1036 { value: 'gpt-5.1-chat-latest', label: 'GPT-5.1 Chat Latest', description: 'Recommended for most use cases' },
1037 + { value: 'gpt-5.1-2025-11-13', label: 'GPT-5.1', description: 'Flagship for coding & agentic tasks with low reasoning (400K context)' },
1038 + { value: 'gpt-5', label: 'GPT-5', description: 'Flagship for coding, reasoning, and agentic tasks across domains' },
1039 + { value: 'gpt-5-mini', label: 'GPT-5 Mini', description: 'Fast and lightweight' },
1040 + { value: 'gpt-5-nano', label: 'GPT-5 Nano', description: 'Fastest and cheapest; ideal for summarization and classification' },
1030 1041 ],
1031 1042 claude: [
1032 - { value: 'claude-opus-4-8', label: 'Claude Opus 4.8', description: 'Latest Flagship — newest Anthropic flagship model' },
1033 - { value: 'claude-opus-4-7', label: 'Claude Opus 4.7', description: 'Previous Anthropic flagship model' },
1043 + { value: 'claude-opus-4-6', label: 'Claude Opus 4.6', description: 'Most capable Claude model - recommended' },
1044 + { value: 'claude-sonnet-4-6', label: 'Claude Sonnet 4.6', description: 'Latest Sonnet - excellent balance of speed and capability' },
1045 + { value: 'claude-opus-4-5', label: 'Claude Opus 4.5', description: 'Highly capable for complex tasks' },
1046 + { value: 'claude-sonnet-4-5-20250929', label: 'Claude Sonnet 4.5', description: 'Best for complex agents and coding' },
1047 + { value: 'claude-opus-4-1-20250805', label: 'Claude Opus 4.1', description: 'Exceptional for specialized complex tasks' },
1048 + { value: 'claude-haiku-4-5-20251001', label: 'Claude Haiku 4.5', description: 'Fastest and most intelligent Haiku' },
1049 + { value: 'claude-opus-4-20250514', label: 'Claude 4 Opus', description: 'Complex tasks' },
1050 + { value: 'claude-sonnet-4-20250514', label: 'Claude 4 Sonnet', description: 'High performance' },
1034 1051 ],
1035 1052 xai: [
1036 - { value: 'grok-4-0709', label: 'Grok 4', description: 'Latest flagship model' },
1053 + { value: 'grok-4-1-fast-reasoning', label: 'Grok 4.1 Fast (Reasoning)', description: '2M context window and reasoning' },
1054 + { value: 'grok-4-1-fast-non-reasoning', label: 'Grok 4.1 Fast (Non-Reasoning)', description: '2M context window and faster responses' },
1055 + { value: 'grok-4-0709', label: 'Grok 4', description: 'Latest flagship model - unparalleled performance in natural language, math and reasoning' },
1056 + { value: 'grok-3-beta', label: 'Grok-3', description: 'Powerful model with 131K context' },
1057 + { value: 'grok-3-fast-beta', label: 'Grok-3 Fast', description: 'High performance with faster responses' },
1058 + { value: 'grok-3-mini-beta', label: 'Grok-3 Mini', description: 'Affordable model with good performance' },
1059 + { value: 'grok-3-mini-fast-beta', label: 'Grok-3 Mini Fast', description: 'Quick and cost-effective' },
1060 + { value: 'grok-2', label: 'Grok 2', description: 'Latest X.AI model' },
1037 1061 ],
1038 1062 deepseek: [
1039 1063 { value: 'deepseek-chat', label: 'DeepSeek-V3', description: 'Advanced AI assistant' },
1040 1064 ],
1041 - custom: [
1042 - { value: 'custom-provider', label: 'Custom Provider', description: 'OpenAI-compatible local LLM — configure in API Keys tab' },
1043 - ],
1044 1065 };
1045 1066
1046 1067 let allModels = [];
1047 1068 Object.keys(models).forEach(key => {
@@ -1082,9 +1103,8 @@
1082 1103 if (modelValue.startsWith('gemini-')) return '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" class="mxchat-model-icon-gemini"><defs><path id="a" d="M44.5 20H24v8.5h11.8C34.7 33.9 30.1 37 24 37c-7.2 0-13-5.8-13-13s5.8-13 13-13c3.1 0 5.9 1.1 8.1 2.9l6.4-6.4C34.6 4.1 29.6 2 24 2 11.8 2 2 11.8 2 24s9.8 22 22 22c11 0 21-8 21-22 0-1.3-.2-2.7-.5-4z"></path></defs><clipPath id="b"><use xlink:href="#a" overflow="visible"></use></clipPath><path clip-path="url(#b)" fill="#FBBC05" d="M0 37V11l17 13z"></path><path clip-path="url(#b)" fill="#EA4335" d="M0 11l17 13 7-6.1L48 14V0H0z"></path><path clip-path="url(#b)" fill="#34A853" d="M0 37l30-23 7.9 1L48 0v48H0z"></path><path clip-path="url(#b)" fill="#4285F4" d="M48 48L17 24l-4-3 35-10z"></path></svg>';
1083 1104 if (modelValue.startsWith('gpt-')) return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 320" class="mxchat-model-icon-openai"><path fill="currentColor" d="M297 131a80.6 80.6 0 0 0-93.7-104.2 80.6 80.6 0 0 0-137 29A80.6 80.6 0 0 0 23 189a80.6 80.6 0 0 0 93.7 104.2 80.6 80.6 0 0 0 137-29A80.7 80.7 0 0 0 297.1 131zM176.9 299c-14 .1-27.6-4.8-38.4-13.8l1.9-1 63.7-36.9c3.3-1.8 5.3-5.3 5.2-9v-89.9l27 15.6c.3.1.4.4.5.7v74.4a60 60 0 0 1-60 60zM47.9 244a59.7 59.7 0 0 1-7.1-40.1l1.9 1.1 63.7 36.8c3.2 1.9 7.2 1.9 10.5 0l77.8-45V228c0 .3-.2.6-.4.8L129.9 266a60 60 0 0 1-82-22zM31.2 105c7-12.2 18-21.5 31.2-26.3v75.8c0 3.7 2 7.2 5.2 9l77.8 45-27 15.5a1 1 0 0 1-.9 0L53.1 187a60 60 0 0 1-22-82zm221.2 51.5-77.8-45 27-15.5a1 1 0 0 1 .9 0l64.4 37.1a60 60 0 0 1-9.3 108.2v-75.8c0-3.7-2-7.2-5.2-9zm26.8-40.4-1.9-1.1-63.7-36.8a10.4 10.4 0 0 0-10.5 0L125.4 123V92c0-.3 0-.6.3-.8L190.1 54a60 60 0 0 1 89.1 62.1zm-168.5 55.4-27-15.5a1 1 0 0 1-.4-.7V80.9a60 60 0 0 1 98.3-46.1l-1.9 1L116 72.8a10.3 10.3 0 0 0-5.2 9v89.8zm14.6-31.5 34.7-20 34.6 20v40L160 200l-34.7-20z"></path></svg>';
1084 1105 if (modelValue.startsWith('claude-')) return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 176" fill="none" class="mxchat-model-icon-claude"><path fill="currentColor" d="m147.487 0l70.081 175.78H256L185.919 0zM66.183 106.221l23.98-61.774l23.98 61.774zM70.07 0L0 175.78h39.18l14.33-36.914h73.308l14.328 36.914h39.179L110.255 0z"></path></svg>';
1085 1106 if (modelValue.startsWith('grok-')) return '<svg fill="currentColor" fill-rule="evenodd" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="mxchat-model-icon-xai"><path d="M6.469 8.776L16.512 23h-4.464L2.005 8.776H6.47zm-.004 7.9l2.233 3.164L6.467 23H2l4.465-6.324zM22 2.582V23h-3.659V7.764L22 2.582zM22 1l-9.952 14.095-2.233-3.163L17.533 1H22z"></path></svg>';
1086 - if (modelValue === 'custom-provider' || modelValue.startsWith('custom-')) return '<span class="dashicons dashicons-admin-site-alt3" style="font-size: 24px; color: #2c8a3d;"></span>';
1087 1107 if (modelValue.startsWith('deepseek-')) return '<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" class="mxchat-model-icon-deepseek"><path d="M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z" fill="currentColor"></path></svg>';
1088 1108 return '<span class="dashicons dashicons-admin-generic mxchat-model-icon-generic"></span>';
1089 1109 }
1090 1110
@@ -1597,71 +1617,8 @@
1597 1617 });
1598 1618
1599 1619 }
1600 1620
1601 -// 3.2.3: Confirmation dialog shown when the user attempts to switch embedding
1602 -// models after they've already embedded content with a different model. Mixing
1603 -// embeddings from two models silently breaks similarity matching.
1604 -function showEmbeddingSwitchWarning(data, newValue, onChoice) {
1605 - $('#mxchat_embedding_switch_warning').remove();
1606 -
1607 - const dimsBlock = data.dims_differ ? `
1608 - <div class="mxchat-embed-warn-dims">
1609 - <strong>Dimension mismatch:</strong>
1610 - Existing vectors are ${data.active_dims}-dimensional, but ${data.new_label}
1611 - produces ${data.new_dims}-dimensional vectors.
1612 - If you use Pinecone, your index will reject queries entirely until you re-embed.
1613 - </div>` : '';
1614 -
1615 - const $modal = $(`
1616 - <div id="mxchat_embedding_switch_warning" class="mxchat-embed-warn-overlay">
1617 - <div class="mxchat-embed-warn-dialog">
1618 - <div class="mxchat-embed-warn-header">
1619 - <span class="mxchat-embed-warn-icon">⚠️</span>
1620 - <h3>Switching embedding models will break similarity matching</h3>
1621 - </div>
1622 - <div class="mxchat-embed-warn-body">
1623 - <p>
1624 - Your knowledge base and actions are currently embedded with
1625 - <code>${data.active_label}</code>. Switching to
1626 - <code>${data.new_label}</code> means new queries are embedded with
1627 - a different model than the stored vectors — the chatbot will return
1628 - inaccurate results or fail to match anything.
1629 - </p>
1630 - ${dimsBlock}
1631 - <p><strong>To switch safely:</strong></p>
1632 - <ol>
1633 - <li>Go to <em>Knowledge Base</em> and delete all existing entries.</li>
1634 - <li>Go to <em>Actions</em> and delete all existing actions.</li>
1635 - <li>Come back here, switch the model, then re-import your content and re-add your actions.</li>
1636 - </ol>
1637 - </div>
1638 - <div class="mxchat-embed-warn-footer">
1639 - <button type="button" class="button button-secondary" id="mxchat_embed_warn_cancel">Cancel — keep ${data.active_label}</button>
1640 - <button type="button" class="button button-primary mxchat-embed-warn-danger" id="mxchat_embed_warn_continue">Switch anyway (I'll handle it)</button>
1641 - </div>
1642 - </div>
1643 - </div>
1644 - `);
1645 -
1646 - $('body').append($modal);
1647 -
1648 - let resolved = false;
1649 - function resolve(confirmed) {
1650 - if (resolved) return;
1651 - resolved = true;
1652 - $modal.remove();
1653 - if (typeof onChoice === 'function') onChoice(confirmed);
1654 - }
1655 -
1656 - // Click on the overlay background dismisses (cancel)
1657 - $modal.on('click', function(e) {
1658 - if (e.target === $modal[0]) resolve(false);
1659 - });
1660 - $modal.find('#mxchat_embed_warn_cancel').on('click', function() { resolve(false); });
1661 - $modal.find('#mxchat_embed_warn_continue').on('click', function() { resolve(true); });
1662 -}
1663 -
1664 1621 // Embedding model selector - completely separate from chat model selector
1665 1622 function setupMxChatEmbeddingModelSelector() {
1666 1623 const $embeddingModelSelect = $('#embedding_model');
1667 1624
@@ -1842,53 +1799,25 @@
1842 1799 const activeCategory = $('.mxchat-embedding-model-selector-categories .mxchat-embedding-model-category-btn.active').data('category');
1843 1800 populateEmbeddingModelsGrid(searchTerm, activeCategory);
1844 1801 });
1845 1802
1846 - // 3.2.3: Commit a model change — same as the original click handler, just
1847 - // factored out so it can be invoked from both the safe path and the
1848 - // post-confirmation path.
1849 - function commitEmbeddingModelChange(modelValue) {
1803 + // Use a direct selector to avoid conflicts with other card elements
1804 + $(document).on('click.embeddingModelSelector', '.mxchat-embedding-model-selector-grid .mxchat-embedding-model-selector-card', function(e) {
1805 + e.stopPropagation(); // Prevent event bubbling
1806 + const modelValue = $(this).data('value');
1807 +
1808 + // Important: Only update this specific select element
1850 1809 $embeddingModelSelect.val(modelValue);
1810 +
1811 + // Manually trigger change only on this element
1851 1812 const changeEvent = new Event('change', { bubbles: true });
1852 1813 $embeddingModelSelect[0].dispatchEvent(changeEvent);
1814 +
1815 + // Update button text
1853 1816 updateButtonText();
1817 +
1818 + // Hide modal
1854 1819 $('#' + embeddingModalId).hide();
1855 - }
1856 -
1857 - // Use a direct selector to avoid conflicts with other card elements
1858 - $(document).on('click.embeddingModelSelector', '.mxchat-embedding-model-selector-grid .mxchat-embedding-model-selector-card', function(e) {
1859 - e.stopPropagation(); // Prevent event bubbling
1860 - const modelValue = $(this).data('value');
1861 - const previousValue = $embeddingModelSelect.val();
1862 -
1863 - // No-op if the user clicked the already-selected card
1864 - if (modelValue === previousValue) {
1865 - $('#' + embeddingModalId).hide();
1866 - return;
1867 - }
1868 -
1869 - // 3.2.3: Preflight — if the user has content embedded with a different
1870 - // model, surface a confirmation dialog before committing the switch.
1871 - $.post(ajaxurl, {
1872 - action: 'mxchat_check_embedding_switch',
1873 - security: (typeof mxchatAdmin !== 'undefined' ? mxchatAdmin.nonce : ''),
1874 - new_model: modelValue
1875 - }).done(function(resp) {
1876 - if (resp && resp.success && resp.data && resp.data.is_mismatch) {
1877 - showEmbeddingSwitchWarning(resp.data, modelValue, function(confirmed) {
1878 - if (confirmed) {
1879 - commitEmbeddingModelChange(modelValue);
1880 - }
1881 - });
1882 - } else {
1883 - commitEmbeddingModelChange(modelValue);
1884 - }
1885 - }).fail(function() {
1886 - // If preflight fails, fall back to the original behavior so a network
1887 - // hiccup doesn't block legitimate model switches.
1888 - commitEmbeddingModelChange(modelValue);
1889 - });
1890 - return;
1891 1820 });
1892 1821
1893 1822 // Close modal when clicking outside - use namespaced events
1894 1823 $(window).on('click.embeddingModelSelector', function(event) {
@@ -3602,49 +3531,6 @@
3602 3531
3603 3532 // Also refresh when switching to optimization tab
3604 3533 $(document).on('click', '[data-section="optimization"]', function() {
3605 3534 setTimeout(refreshDebugLog, 100);
3606 - });
3607 -});
3608 -
3609 -// Global rate-limit usage: "Reset counter" button (plan-mxchat-20260603-e9b3f9)
3610 -jQuery(document).ready(function($) {
3611 - var $usage = $('#mxch-global-usage');
3612 - if (!$usage.length) {
3613 - return;
3614 - }
3615 -
3616 - $('#mxch-global-usage-reset').on('click', function() {
3617 - var $btn = $(this);
3618 - if (!window.confirm('Reset the global usage counter to zero now? This clears how many messages have been used in the current window.')) {
3619 - return;
3620 - }
3621 -
3622 - var original = $btn.text();
3623 - $btn.prop('disabled', true).text('Resetting…');
3624 -
3625 - $.ajax({
3626 - url: mxchatAdmin.ajax_url,
3627 - type: 'POST',
3628 - data: {
3629 - action: 'mxchat_reset_global_rate_limit',
3630 - bot_id: $usage.data('bot-id') || 'default',
3631 - _ajax_nonce: $usage.data('reset-nonce')
3632 - },
3633 - success: function(response) {
3634 - $btn.prop('disabled', false).text(original);
3635 - if (response && response.success) {
3636 - $('#mxch-global-usage-fill').css('width', (response.data.pct || 0) + '%');
3637 - if (response.data.text) {
3638 - $('#mxch-global-usage-text').text(response.data.text);
3639 - }
3640 - } else {
3641 - window.alert((response && response.data && response.data.message) || 'Reset failed. Please try again.');
3642 - }
3643 - },
3644 - error: function() {
3645 - $btn.prop('disabled', false).text(original);
3646 - window.alert('Reset failed. Please try again.');
3647 - }
3648 - });
3649 3535 });
3650 3536 });