PluginProbe
MxChat – AI Chatbot & Content Generation for WordPress / 2.0.7
MxChat – AI Chatbot & Content Generation for WordPress v2.0.7
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 | includes/class-mxchat-admin.php +837 -506 2.0.32.0.7 View file →
@@ -45,8 +45,9 @@
45 45 add_action('post_updated', array($this, 'handle_post_update'), 10, 3);
46 46 add_action('wp_ajax_mxchat_save_setting', array($this, 'mxchat_save_setting_callback'));
47 47 add_action('wp_trash_post', array($this, 'mxchat_handle_post_delete'));
48 48 add_action('before_delete_post', array($this, 'mxchat_handle_post_delete'));
49 + add_action('wp_ajax_mxchat_export_transcripts', array($this, 'export_chat_transcripts'));
49 50 add_action('wp_ajax_mxchat_save_prompts_setting', array($this, 'mxchat_save_prompts_setting_callback'));
50 51 if (isset($this->options['enable_woocommerce_integration']) &&
51 52 ($this->options['enable_woocommerce_integration'] === '1' ||
52 53 $this->options['enable_woocommerce_integration'] === 'on')) {
@@ -70,8 +71,10 @@
70 71 'api_key' => '',
71 72 'xai_api_key' => '',
72 73 'claude_api_key' => '',
73 74 'deepseek_api_key' => '',
75 + 'voyage_api_key' => '',
76 + 'embedding_model' => 'text-embedding-ada-002',
74 77 'system_prompt_instructions' => esc_html__('[EXAMPLE INSTRUCTIONS] You are an AI Chatbot assistant for this website. The primary subject you should focus on is [insert proper subject here]. Your main goal is to assist visitors with questions related to this specific topic. Here are some key things to keep in mind:
75 78 - Your name is [Chatbot Name].
76 79 - Stay focused on topics related to [insert proper subject here]. If a visitor asks about an unrelated topic, politely redirect the conversation to how you can assist them with this subject.
77 80 - Do not make up links to pages. Only use specific links you see in your knowledgebase from [insert your domain]. Do not make assumptions or make up URLs.
@@ -114,8 +117,10 @@
114 117 'pdf_intent_trigger_text' => esc_html__("Please provide the URL to the PDF you'd like to discuss.", 'mxchat'),
115 118 'pdf_intent_success_text' => esc_html__("I've processed the PDF. What questions do you have about it?", 'mxchat'),
116 119 'pdf_intent_error_text' => esc_html__("Sorry, I couldn't process the PDF. Please ensure it's a valid file.", 'mxchat'),
117 120 'pdf_max_pages' => 69,
121 + 'show_pdf_upload_button' => 'on',
122 + 'show_word_upload_button' => 'on',
118 123
119 124 // Live Agent Integration
120 125 'live_agent_webhook_url' => '',
121 126 'live_agent_secret_key' => '',
@@ -173,26 +178,24 @@
173 178 'mxchat-prompts',
174 179 array($this, 'mxchat_create_prompts_page')
175 180 );
176 181
177 - // Submenu page for Chat Transcripts
178 182 add_submenu_page(
179 - 'mxchat-max', // Corrected parent slug to match the main menu
183 + 'mxchat-max',
180 184 esc_html__('Chat Transcripts', 'mxchat'),
181 185 esc_html__('Transcripts', 'mxchat'),
182 186 'manage_options',
183 187 'mxchat-transcripts',
184 - array($this, 'mxchat_create_transcripts_page') // Prefixed function name with mxchat_
188 + array($this, 'mxchat_create_transcripts_page')
185 189 );
186 190
187 - // Submenu page for Intents
188 191 add_submenu_page(
189 - 'mxchat-max', // Parent slug
190 - esc_html__('MxChat Intents', 'mxchat'), // Page title
191 - esc_html__('Intents', 'mxchat'), // Menu title
192 - 'manage_options', // Capability
193 - 'mxchat-intents', // Menu slug
194 - array($this, 'mxchat_intents_page_html') // Callback function
192 + 'mxchat-max',
193 + esc_html__('MxChat Intents', 'mxchat'),
194 + esc_html__('Intents', 'mxchat'),
195 + 'manage_options',
196 + 'mxchat-intents',
197 + array($this, 'mxchat_intents_page_html')
195 198 );
196 199
197 200 add_submenu_page(
198 201 'mxchat-max',
@@ -288,9 +291,11 @@
288 291 if (strpos($name, 'toggle') !== false || in_array($name, [
289 292 'chat_persistence_toggle',
290 293 'privacy_toggle',
291 294 'complianz_toggle',
292 - 'chat_toolbar_toggle' // Removed live_agent_status from here
295 + 'chat_toolbar_toggle',
296 + 'show_pdf_upload_button',
297 + 'show_word_upload_button'
293 298 ])) {
294 299 $options[$name] = ($value === 'on') ? 'on' : 'off';
295 300 } else {
296 301 // Store all other values directly
@@ -312,9 +317,8 @@
312 317 } else {
313 318 wp_send_json_error(['message' => esc_html__('Update failed or no changes', 'mxchat')]);
314 319 }
315 320 }
316 -
317 321 /**
318 322 * Handles AJAX auto-save for prompts and auto-sync settings.
319 323 */
320 324 public function mxchat_save_prompts_setting_callback() {
@@ -410,9 +414,9 @@
410 414 <?php endif; ?>
411 415
412 416 <div class="mxchat-agents-banner">
413 417 <p>
414 - <strong><?php echo esc_html__('The MxChat Add-Ons Platform', 'mxchat'); ?></strong><?php echo esc_html__(' is here! Pro users get unlimited access to our growing collection of powerful add-ons. ', 'mxchat'); ?><a href="<?php echo admin_url('admin.php?page=mxchat-addons'); ?>"><?php echo esc_html__('Explore all add-ons', 'mxchat'); ?></a><?php echo esc_html__(' including Forms Builder, Theme Customizer, Content Moderation, and more – all included with your lifetime Pro license!', 'mxchat'); ?>
418 + <strong><?php echo esc_html__('The MxChat Add-Ons Platform', 'mxchat'); ?></strong><?php echo esc_html__(' is here! Pro users get unlimited access to our growing collection of powerful add-ons. ', 'mxchat'); ?><a href="<?php echo admin_url('admin.php?page=mxchat-addons'); ?>"><?php echo esc_html__('Explore all add-ons', 'mxchat'); ?></a><?php echo esc_html__(' including Forms Builder, Theme Customizer, WooCommerce, Perplexity, and more – all included with your lifetime Pro license!', 'mxchat'); ?>
415 419 </p>
416 420 </div>
417 421
418 422 <h2 class="mxchat-nav-tab-wrapper">
@@ -417,9 +421,9 @@
417 421
418 422 <h2 class="mxchat-nav-tab-wrapper">
419 423 <a href="#chatbot" class="mxchat-nav-tab mxchat-nav-tab-active" data-tab="chatbot"><?php echo esc_html__('Chatbot', 'mxchat'); ?></a>
420 424 <a href="#embed" class="mxchat-nav-tab" data-tab="embed"><?php echo esc_html__('Integrations', 'mxchat'); ?></a>
421 - <a href="#general" class="mxchat-nav-tab" data-tab="general"><?php echo esc_html__('FAQ', 'mxchat'); ?></a>
425 + <a href="#general" class="mxchat-nav-tab" data-tab="general"><?php echo esc_html__('YouTube Tutorials', 'mxchat'); ?></a>
422 426 </h2>
423 427
424 428 <div id="chatbot" class="mxchat-tab-content active">
425 429 <div class="mxchat-autosave-section">
@@ -428,15 +432,8 @@
428 432 </div>
429 433
430 434 <div id="embed" class="mxchat-tab-content">
431 435 <div class="mxchat-autosave-section">
432 - <div class="mxchat-settings-section">
433 - <h2><?php echo esc_html__('WooCommerce Settings', 'mxchat'); ?></h2>
434 - <table class="form-table">
435 - <?php do_settings_fields('mxchat-embed', 'mxchat_woocommerce_section'); ?>
436 - </table>
437 - </div>
438 - <div class="section-divider"></div>
439 436
440 437 <div class="mxchat-settings-section">
441 438 <h2><?php echo esc_html__('Loops Settings', 'mxchat'); ?></h2>
442 439 <table class="form-table">
@@ -477,109 +474,131 @@
477 474
478 475
479 476 <div id="general" class="mxchat-tab-content">
480 477 <?php do_settings_sections('mxchat-general'); ?>
481 - <p>
482 - <?php echo esc_html__('If you’re having trouble with setup or getting the responses you need, we encourage you to review our', 'mxchat'); ?>
483 - <a href="https://mxchat.ai/documentation/" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('documentation', 'mxchat'); ?></a> <?php echo esc_html__('or', 'mxchat'); ?>
484 - <a href="https://wordpress.org/support/plugin/mxchat-basic/" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('create a support ticket', 'mxchat'); ?></a>.
485 - </p>
486 - <p>
487 - <?php echo esc_html__('If you like our plugin, please consider', 'mxchat'); ?> <a href="https://wordpress.org/plugins/mxchat-basic/#reviews" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('leaving us a review', 'mxchat'); ?></a>.
488 - </p>
478 +<div class="video-tutorials-section">
489 479
490 - <div class="faq-item">
491 - <h3><?php echo esc_html__('How does the Claude API integration work?', 'mxchat'); ?></h3>
492 - <p>
493 - <?php echo esc_html__('The Claude API, provided by Anthropic, allows for intelligent, context-aware chatbot responses in MxChat. To use it, you will need both an OpenAI API key and a Claude API key. This is necessary because the system utilizes OpenAI for vector embedding in the Retrieval-Augmented Generation (RAG) process, as Claude does not currently offer an embedding API.', 'mxchat'); ?>
494 - </p>
495 - <p>
496 - <?php echo esc_html__('When using the Claude API, your custom content is sent to Claude for generating responses, while the embeddings are processed through OpenAI. This ensures your chatbot provides accurate and engaging responses while maintaining knowledge relevant to your website.', 'mxchat'); ?>
497 - </p>
498 - <p>
499 - <?php echo esc_html__('You can obtain your Claude API key by signing up on the', 'mxchat'); ?> <a href="https://www.anthropic.com/api" target="_blank" rel="noopener"><?php echo esc_html__('Anthropic API page', 'mxchat'); ?></a>.
500 - </p>
480 + <div class="tutorial-grid">
481 + <div class="tutorial-item">
482 + <h3><?php echo esc_html__('MxChat Forms Tutorial', 'mxchat'); ?></h3>
483 + <div class="video-description">
484 + <p><?php echo esc_html__('Learn how to create and manage smart forms that automatically trigger during chat conversations.', 'mxchat'); ?></p>
485 + <a href="https://www.youtube.com/watch?v=3MrWy5dRalA" target="_blank" rel="noopener" class="video-link">
486 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
487 + <?php echo esc_html__('Watch MxChat Forms Tutorial', 'mxchat'); ?>
488 + </a>
501 489 </div>
490 + </div>
502 491
503 - <div class="faq-item">
504 - <h3><?php echo esc_html__('How does the X.AI API integration work?', 'mxchat'); ?></h3>
505 - <p>
506 - <?php echo esc_html__('The X.AI API, released on 10.21.24, is currently in beta. To use it, you will need both an OpenAI API key and an X.AI API key. This is because OpenAI handles vector embeddings in the Retrieval-Augmented Generation (RAG) process, as X.AI does not yet provide an embedding API.', 'mxchat'); ?>
507 - </p>
508 - <p>
509 - <?php echo esc_html__('Custom content is sent to the X.AI API for generating responses, while OpenAI processes the embeddings. This allows the chatbot to provide advanced responses while maintaining context from your website. You can get your X.AI API key from the', 'mxchat'); ?> <a href="https://docs.x.ai/docs" target="_blank" rel="noopener"><?php echo esc_html__('X.AI API documentation', 'mxchat'); ?></a>.
510 - </p>
492 + <div class="tutorial-item">
493 + <h3><?php echo esc_html__('Intent Tester Guide', 'mxchat'); ?></h3>
494 + <div class="video-description">
495 + <p><?php echo esc_html__('Discover how to use the Intent Tester to fine-tune your chatbot\'s responses and ensure it accurately understands user queries.', 'mxchat'); ?></p>
496 + <a href="https://www.youtube.com/watch?v=uTr14tn59Hc" target="_blank" rel="noopener" class="video-link">
497 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
498 + <?php echo esc_html__('Watch Intent Tester Tutorial', 'mxchat'); ?>
499 + </a>
511 500 </div>
501 + </div>
512 502
513 - <div class="faq-item">
514 - <h3><?php echo esc_html__('Do I need an OpenAI API key to use the chatbot?', 'mxchat'); ?></h3>
515 - <p>
516 - <?php echo esc_html__('Yes, you will need an OpenAI API key to power the chatbot. You can obtain an API key by signing up on the', 'mxchat'); ?> <a href="https://platform.openai.com/signup" target="_blank" rel="noopener"><?php echo esc_html__('OpenAI platform', 'mxchat'); ?></a>. <?php echo esc_html__('After signing up, you must add credits to your account—typically, $5 in credits is sufficient to get started.', 'mxchat'); ?>
517 - </p>
518 - <p>
519 - <?php echo esc_html__('Once you have your API key, simply enter it in the chatbot\'s settings to enable functionality. The chatbot relies on OpenAI’s models for generating responses, so having sufficient credits in your OpenAI account is essential for smooth operation.', 'mxchat'); ?>
520 - </p>
503 + <div class="tutorial-item">
504 + <h3><?php echo esc_html__('WooCommerce Integration', 'mxchat'); ?></h3>
505 + <div class="video-description">
506 + <p><?php echo esc_html__('See how to integrate MxChat with your WooCommerce store to provide product recommendations and shopping assistance to your customers.', 'mxchat'); ?></p>
507 + <a href="https://www.youtube.com/watch?v=WsqAppHRGdA" target="_blank" rel="noopener" class="video-link">
508 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
509 + <?php echo esc_html__('Watch WooCommerce Integration Tutorial', 'mxchat'); ?>
510 + </a>
521 511 </div>
512 + </div>
522 513
523 - <div class="faq-item">
524 - <h3><?php echo esc_html__('How do I add the chatbot to my site?', 'mxchat'); ?></h3>
525 - <p>
526 - <?php echo esc_html__('You can add the chatbot using the shortcode', 'mxchat'); ?> <code>[mxchat_chatbot floating="yes"]</code> <?php echo esc_html__('or', 'mxchat'); ?> <code>[mxchat_chatbot floating="no"]</code>. <?php echo esc_html__('For initial testing and styling, it\'s best to use the shortcode on a draft or non-public page. Once you’re ready to go live, enable the “Append Chat Widget to Body” option in the settings for site-wide integration (recommended) or add shortcode to the footer.', 'mxchat'); ?>
527 - </p>
514 + <div class="tutorial-item">
515 + <h3><?php echo esc_html__('Knowledge Base Setup', 'mxchat'); ?></h3>
516 + <div class="video-description">
517 + <p><?php echo esc_html__('Learn how to set up your knowledge base using PDFs, sitemaps, and manual entries to enhance your chatbot\'s responses with site-specific information.', 'mxchat'); ?></p>
518 + <p><small><?php echo esc_html__('Note: This tutorial uses an older UI, but the process remains the same.', 'mxchat'); ?></small></p>
519 + <a href="https://www.youtube.com/watch?v=8Ztjs66-VTo" target="_blank" rel="noopener" class="video-link">
520 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
521 + <?php echo esc_html__('Watch Knowledge Base Setup Tutorial', 'mxchat'); ?>
522 + </a>
528 523 </div>
524 + </div>
529 525
530 - <div class="faq-item">
531 - <h3><?php echo esc_html__('How does the chatbot use my content to generate responses?', 'mxchat'); ?></h3>
532 - <p>
533 - <?php echo esc_html__('The chatbot uses AI and vector embeddings to connect users with relevant information. When you submit content, it converts it into a mathematical format. When a user asks a question, the bot matches it to your stored content and generates a response based on relevance. For example, submitting "Our phone number is 910-123-4567" allows the bot to retrieve this information when asked about contact details. To ensure related information is provided together, submit it in one entry.', 'mxchat'); ?>
534 - </p>
526 + <div class="tutorial-item">
527 + <h3><?php echo esc_html__('Toolbar Chat with Documents', 'mxchat'); ?></h3>
528 + <div class="video-description">
529 + <p><?php echo esc_html__('See how to use the MxChat toolbar to chat with PDF and Word documents for enhanced document analysis and information retrieval.', 'mxchat'); ?></p>
530 + <a href="https://www.youtube.com/watch?v=j_c45WWCTG0" target="_blank" rel="noopener" class="video-link">
531 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
532 + <?php echo esc_html__('Watch Document Chat Tutorial', 'mxchat'); ?>
533 + </a>
535 534 </div>
536 -
537 - <div class="faq-item">
538 - <h3><?php echo esc_html__('Why does the chatbot sometimes make up links or information?', 'mxchat'); ?></h3>
539 - <p>
540 - <?php echo esc_html__('Occasionally, the chatbot may generate inaccurate links or information, known as "hallucinations." To minimize this, you can add system instructions to guide its behavior. For example, include an instruction like: "Only provide links you directly have access to or retrieve from the knowledge base. Do not make up links or information that you do not have direct access to." This helps the bot stay aligned with your content.', 'mxchat'); ?>
541 - </p>
535 + </div>
536 +
537 + <div class="tutorial-item">
538 + <h3><?php echo esc_html__('Perplexity Integration', 'mxchat'); ?></h3>
539 + <div class="video-description">
540 + <p><?php echo esc_html__('Learn how to integrate Perplexity with your chatbot for real-time web search capabilities. This tutorial covers intent recognition, the toolbar toggle button, and how to enable your chatbot to search the web and provide up-to-date information to your visitors.', 'mxchat'); ?></p>
541 + <a href="https://youtu.be/wpKkbt24-bo" target="_blank" rel="noopener" class="video-link">
542 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
543 + <?php echo esc_html__('Watch Perplexity Integration Tutorial', 'mxchat'); ?>
544 + </a>
542 545 </div>
546 + </div>
543 547
544 - <div class="faq-item">
545 - <h3><?php echo esc_html__('How do intents work in MxChat?', 'mxchat'); ?></h3>
546 - <p>
547 - <?php echo esc_html__('Intents allow MxChat to recognize user requests and trigger specific actions, such as capturing emails or displaying product information. This helps provide a more interactive and responsive experience. For a detailed explanation of each intent, please refer to our', 'mxchat'); ?> <a href="https://mxchat.ai/documentation/#intents" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('Intents Documentation', 'mxchat'); ?></a>.
548 - </p>
548 + <div class="tutorial-item">
549 + <h3><?php echo esc_html__('Brave Search Intent', 'mxchat'); ?></h3>
550 + <div class="video-description">
551 + <p><?php echo esc_html__('Learn how to leverage Brave Search intent capabilities to improve your chatbot\'s understanding of user queries and provide more accurate responses.', 'mxchat'); ?></p>
552 + <a href="https://www.youtube.com/watch?v=7vDL5H7vToc" target="_blank" rel="noopener" class="video-link">
553 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
554 + <?php echo esc_html__('Watch Brave Search Intent Tutorial', 'mxchat'); ?>
555 + </a>
549 556 </div>
557 + </div>
550 558
551 - <div class="faq-item">
552 - <h3><?php echo esc_html__('How does the Complianz integration work?', 'mxchat'); ?></h3>
553 - <p>
554 - <?php echo esc_html__('The Pro version offers direct integration with the Complianz GDPR plugin, making it easy to stay compliant with GDPR. If Complianz is enabled on your website, users must accept consent before the chatbot widget appears. The chatbot will only display once the user has accepted, ensuring compliance with data privacy regulations.', 'mxchat'); ?>
555 - </p>
559 + <div class="tutorial-item">
560 + <h3><?php echo esc_html__('Loops Email Capture', 'mxchat'); ?></h3>
561 + <div class="video-description">
562 + <p><?php echo esc_html__('Discover how to set up email capture with MxChat using Loops to grow your mailing list while providing value through your chatbot.', 'mxchat'); ?></p>
563 + <p><small><?php echo esc_html__('Note: This tutorial uses an older UI, but the process remains the same.', 'mxchat'); ?></small></p>
564 + <a href="https://www.youtube.com/watch?v=CNgm5TYDyTc" target="_blank" rel="noopener" class="video-link">
565 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
566 + <?php echo esc_html__('Watch Loops Email Capture Tutorial', 'mxchat'); ?>
567 + </a>
556 568 </div>
569 + </div>
557 570
558 - <div class="faq-item">
559 - <h3><?php echo esc_html__('How does the WooCommerce integration work?', 'mxchat'); ?></h3>
560 - <p>
561 - <?php echo esc_html__('With WooCommerce integration, the chatbot automatically embeds new products and updates existing ones. For already-published products, you can click update or submit the product sitemap. The “Order History Access” setting allows the bot to access users\' order history (requires login) and assist with order inquiries. To enable the “Add to Cart” feature, add this system instruction: “After discussing a product, ask if the user wants to add it to their cart. The user must say \'Add to cart\' exactly.” Currently, this feature supports English only, with more languages coming soon.', 'mxchat'); ?>
562 - </p>
571 + <div class="tutorial-item">
572 + <h3><?php echo esc_html__('MxChat AI Agent Testing Service', 'mxchat'); ?></h3>
573 + <div class="video-description">
574 + <p><?php echo esc_html__('Learn how to use the MxChat AI Agent Testing Service to evaluate and improve your chatbot\'s performance and accuracy.', 'mxchat'); ?></p>
575 + <p><small><?php echo esc_html__('Note: This tutorial uses an older UI, but the process remains the same.', 'mxchat'); ?></small></p>
576 + <a href="https://www.youtube.com/watch?v=A0jowbpyX54" target="_blank" rel="noopener" class="video-link">
577 + <span class="video-icon"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19c-2.3 0-6.4-.2-8.1-.6-.7-.2-1.2-.7-1.4-1.4-.3-1.1-.5-3.4-.5-5s.2-3.9.5-5c.2-.7.7-1.2 1.4-1.4C5.6 5.2 9.7 5 12 5s6.4.2 8.1.6c.7.2 1.2.7 1.4 1.4.3 1.1.5 3.4.5 5s-.2 3.9-.5 5c-.2.7-.7 1.2-1.4 1.4-1.7.4-5.8.6-8.1.6z"></path><polygon points="10 15 15 12 10 9 10 15"></polygon></svg></span>
578 + <?php echo esc_html__('Watch AI Agent Testing Tutorial', 'mxchat'); ?>
579 + </a>
563 580 </div>
581 + </div>
582 + </div>
564 583
565 - <div class="faq-item">
566 - <h3><?php echo esc_html__('Why isn\'t my chatbot responding as expected?', 'mxchat'); ?></h3>
584 + <div class="support-section">
585 + <h3><?php echo esc_html__('Need Help?', 'mxchat'); ?></h3>
586 + <div class="support-content">
567 587 <p>
568 - <?php echo esc_html__('AI chatbots can sometimes behave in unexpected ways, especially if you\'re new to configuring AI for specific tasks. We\'re committed to helping you get the most out of your chatbot experience. While we’re working on comprehensive guides and video tutorials, our team is here to assist you directly. If your chatbot isn\'t delivering the responses you need, please don’t hesitate to', 'mxchat'); ?> <a href="https://mxchat.ai/contact/" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('contact us', 'mxchat'); ?></a> <?php echo esc_html__('for personalized support.', 'mxchat'); ?>
588 + <?php echo esc_html__('If you\'re having trouble with setup or getting the responses you need, we encourage you to review our', 'mxchat'); ?>
589 + <a href="https://mxchat.ai/documentation/" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('documentation', 'mxchat'); ?></a> <?php echo esc_html__('or', 'mxchat'); ?>
590 + <a href="https://wordpress.org/support/plugin/mxchat-basic/" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('create a support ticket', 'mxchat'); ?></a>.
569 591 </p>
570 592 <p>
571 - <?php echo esc_html__('We’re dedicated to your success and ready to guide you in aligning the AI\'s behavior to meet your goals.', 'mxchat'); ?>
593 + <?php echo esc_html__('If you like our plugin, please consider', 'mxchat'); ?> <a href="https://wordpress.org/plugins/mxchat-basic/#reviews" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('leaving us a review', 'mxchat'); ?></a>.
572 594 </p>
573 595 </div>
596 + </div>
597 +
598 +
599 + </div>
574 600
575 - <div class="faq-item">
576 - <h3><?php echo esc_html__('What is Loops, and how do I get an API key?', 'mxchat'); ?></h3>
577 - <p>
578 - <?php echo esc_html__('Loops is a powerful SaaS email service that helps you automate and enhance your email marketing campaigns, making it easy to reach and engage with your audience. To integrate Loops with MxChat, you’ll need an API key from Loops. You can obtain this key by logging into your Loops account and navigating to the API settings. Visit the', 'mxchat'); ?> <a href="https://loops.so" target="_blank" rel="noopener noreferrer"><?php echo esc_html__('Loops website', 'mxchat'); ?></a> <?php echo esc_html__('to get started or to sign up for an account.', 'mxchat'); ?>
579 - </p>
580 - </div>
581 -
582 601 </div>
583 602 </div>
584 603 <?php
585 604 }
@@ -584,73 +603,348 @@
584 603 <?php
585 604 }
586 605
587 606
588 -
589 607 public function mxchat_create_transcripts_page() {
590 608 global $wpdb;
591 609 $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
592 -
610 +
593 611 // Get basic stats
594 612 $total_chats = $wpdb->get_var("SELECT COUNT(DISTINCT session_id) FROM $table_name");
595 613 $total_messages = $wpdb->get_var("SELECT COUNT(*) FROM $table_name");
596 - $total_users = $wpdb->get_var("SELECT COUNT(DISTINCT user_email) FROM $table_name WHERE user_email != ''");
614 +
615 + // Count unique users with detailed breakdown
616 + $total_users = $wpdb->get_var("
617 + SELECT COUNT(DISTINCT
618 + CASE
619 + WHEN user_email != '' AND user_email IS NOT NULL THEN user_email
620 + WHEN user_id != 0 THEN CONCAT('user_', user_id)
621 + WHEN user_identifier NOT LIKE 'Tech-Savvy User'
622 + AND user_identifier NOT LIKE 'Detail-Oriented User'
623 + AND user_identifier NOT LIKE 'Language Learner'
624 + AND user_identifier NOT LIKE 'Casual Browser'
625 + AND user_identifier NOT LIKE 'Policy Enforcer'
626 + AND user_identifier NOT LIKE 'Researcher'
627 + AND user_identifier NOT LIKE 'Loyalty Member'
628 + AND user_identifier NOT LIKE 'Gift Buyer'
629 + AND user_identifier NOT LIKE 'Parent or Caregiver'
630 + THEN user_identifier
631 + ELSE session_id
632 + END
633 + )
634 + FROM $table_name
635 + WHERE role != 'assistant'
636 + ");
637 +
638 + // Get user type breakdown
639 + $registered_users = $wpdb->get_var("
640 + SELECT COUNT(DISTINCT user_email)
641 + FROM $table_name
642 + WHERE user_email != '' AND user_email IS NOT NULL
643 + ");
644 +
645 + $guest_users = $wpdb->get_var("
646 + SELECT COUNT(DISTINCT user_identifier)
647 + FROM $table_name
648 + WHERE (user_email = '' OR user_email IS NULL)
649 + AND role != 'assistant'
650 + AND user_identifier NOT LIKE 'Tech-Savvy User'
651 + AND user_identifier NOT LIKE 'Detail-Oriented User'
652 + AND user_identifier NOT LIKE 'Language Learner'
653 + AND user_identifier NOT LIKE 'Casual Browser'
654 + AND user_identifier NOT LIKE 'Policy Enforcer'
655 + AND user_identifier NOT LIKE 'Researcher'
656 + AND user_identifier NOT LIKE 'Loyalty Member'
657 + AND user_identifier NOT LIKE 'Gift Buyer'
658 + AND user_identifier NOT LIKE 'Parent or Caregiver'
659 + ");
660 +
661 + // Get agent test messages count
662 + $agent_tests = $wpdb->get_var("
663 + SELECT COUNT(DISTINCT session_id)
664 + FROM $table_name
665 + WHERE user_identifier IN (
666 + 'Tech-Savvy User',
667 + 'Detail-Oriented User',
668 + 'Language Learner',
669 + 'Casual Browser',
670 + 'Policy Enforcer',
671 + 'Researcher',
672 + 'Loyalty Member',
673 + 'Gift Buyer',
674 + 'Parent or Caregiver'
675 + )
676 + ");
597 677 ?>
598 - <div class="wrap mxchat-admin">
599 - <!-- Stats Cards -->
600 - <div class="mxchat-stats-grid">
601 - <div class="mxchat-stat-card">
602 - <div class="stat-icon">💬</div>
603 - <div class="stat-content">
604 - <span class="stat-value"><?php echo esc_html($total_chats); ?></span>
605 - <span class="stat-label"><?php esc_html_e('Total Chats', 'mxchat'); ?></span>
678 + <div class="wrap mxchat-transcripts-wrapper">
679 + <!-- Hero Section -->
680 + <div class="mxchat-transcripts-hero">
681 + <h1 class="mxchat-main-title">
682 + Chat <span class="mxchat-gradient-text">Transcripts</span>
683 + </h1>
684 + <p class="mxchat-hero-subtitle">
685 + <?php esc_html_e('Review and manage your chatbot conversations with detailed message history.', 'mxchat'); ?>
686 + </p>
687 + </div>
688 + <div class="mxchat-content">
689 + <!-- Stats Cards -->
690 + <div class="mxchat-stats-grid">
691 + <div class="mxchat-stat-card">
692 + <div class="stat-icon">💬</div>
693 + <div class="stat-content">
694 + <span class="stat-value"><?php echo esc_html($total_chats); ?></span>
695 + <span class="stat-label"><?php esc_html_e('Total Chats', 'mxchat'); ?></span>
696 + </div>
606 697 </div>
607 - </div>
608 - <div class="mxchat-stat-card">
609 - <div class="stat-icon">📝</div>
610 - <div class="stat-content">
611 - <span class="stat-value"><?php echo esc_html($total_messages); ?></span>
612 - <span class="stat-label"><?php esc_html_e('Total Messages', 'mxchat'); ?></span>
698 + <div class="mxchat-stat-card">
699 + <div class="stat-icon">📝</div>
700 + <div class="stat-content">
701 + <span class="stat-value"><?php echo esc_html($total_messages); ?></span>
702 + <span class="stat-label"><?php esc_html_e('Total Messages', 'mxchat'); ?></span>
703 + </div>
613 704 </div>
705 + <div class="mxchat-stat-card">
706 + <div class="stat-icon">👥</div>
707 + <div class="stat-content">
708 + <span class="stat-value"><?php echo esc_html($total_users); ?></span>
709 + <span class="stat-label"><?php esc_html_e('Unique Users', 'mxchat'); ?></span>
710 + <span class="stat-sublabel">
711 + <?php
712 + echo sprintf(
713 + esc_html__('%d registered, %d guests, %d agent tests', 'mxchat'),
714 + $registered_users,
715 + $guest_users,
716 + $agent_tests
717 + );
718 + ?>
719 + </span>
720 + </div>
721 + </div>
614 722 </div>
615 - <div class="mxchat-stat-card">
616 - <div class="stat-icon">👥</div>
617 - <div class="stat-content">
618 - <span class="stat-value"><?php echo esc_html($total_users); ?></span>
619 - <span class="stat-label"><?php esc_html_e('Unique Users', 'mxchat'); ?></span>
723 + <!-- Search and Filter Controls -->
724 + <div class="mxchat-controls-wrapper">
725 + <div class="mxchat-search-box">
726 + <input type="text" id="mxchat-search-transcripts"
727 + placeholder="<?php esc_attr_e('Search transcripts...', 'mxchat'); ?>"
728 + class="regular-text">
620 729 </div>
730 + <form id="mxchat-delete-form" method="post">
731 + <?php wp_nonce_field('mxchat_delete_chat_history', 'mxchat_delete_chat_nonce'); ?>
732 + <div class="mxchat-controls">
733 + <button type="button" id="mxchat-export-transcripts" class="mxchat-action-button">
734 + <span class="dashicons dashicons-download"></span>
735 + <?php esc_html_e('Export All Chats', 'mxchat'); ?>
736 + </button>
737 + <button type="button" id="mxchat-select-all-transcripts" class="mxchat-select-button">
738 + <span class="dashicons dashicons-yes-alt"></span>
739 + <span class="button-text"><?php esc_html_e('Select All', 'mxchat'); ?></span>
740 + </button>
741 + <button type="submit" class="button delete-chats-button">
742 + <span class="dashicons dashicons-trash"></span>
743 + <?php esc_html_e('Delete Selected', 'mxchat'); ?>
744 + </button>
745 + </div>
746 + </form>
621 747 </div>
748 + <!-- Transcripts Container -->
749 + <div id="mxchat-transcripts"></div>
622 750 </div>
751 + </div>
752 + <?php
753 +}
623 754
624 - <!-- Search and Filter Controls -->
625 - <div class="mxchat-controls-wrapper">
626 - <div class="mxchat-search-box">
627 - <input type="text" id="mxchat-search-transcripts"
628 - placeholder="<?php esc_attr_e('Search transcripts...', 'mxchat'); ?>"
629 - class="regular-text">
630 - </div>
755 +public function export_chat_transcripts() {
756 + if (!current_user_can('manage_options')) {
757 + wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'mxchat'));
758 + }
631 759
632 - <form id="mxchat-delete-form" method="post">
633 - <?php wp_nonce_field('mxchat_delete_chat_history', 'mxchat_delete_chat_nonce'); ?>
634 - <div class="mxchat-controls">
635 - <button type="button" id="mxchat-select-all-transcripts" class="mxchat-select-button">
636 - <span class="dashicons dashicons-yes-alt"></span>
637 - <span class="button-text"><?php esc_html_e('Select All', 'mxchat'); ?></span>
638 - </button>
639 - <button type="submit" class="button delete-chats-button">
640 - <span class="dashicons dashicons-trash"></span>
641 - <?php esc_html_e('Delete Selected', 'mxchat'); ?>
642 - </button>
643 - </div>
644 - </form>
645 - </div>
760 + check_ajax_referer('mxchat_export_transcripts', 'security');
646 761
647 - <!-- Transcripts Container -->
648 - <div id="mxchat-transcripts"></div>
649 - </div>
650 - <?php
762 + global $wpdb;
763 + $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
764 +
765 + // Get all transcripts ordered by session and timestamp
766 + $results = $wpdb->get_results(
767 + "SELECT session_id, user_email, user_identifier, role, message, timestamp
768 + FROM {$table_name}
769 + ORDER BY session_id, timestamp ASC"
770 + );
771 +
772 + if (empty($results)) {
773 + wp_send_json_error(array('message' => 'No transcripts found.'));
774 + wp_die();
775 + }
776 +
777 + // Set headers for CSV download
778 + header('Content-Type: text/csv');
779 + header('Content-Disposition: attachment; filename="chat-transcripts-' . date('Y-m-d') . '.csv"');
780 + header('Pragma: no-cache');
781 + header('Expires: 0');
782 +
783 + // Create output stream
784 + $output = fopen('php://output', 'w');
785 +
786 + // Add UTF-8 BOM for proper Excel encoding
787 + fputs($output, "\xEF\xBB\xBF");
788 +
789 + // Add CSV headers
790 + fputcsv($output, array(
791 + 'Session ID',
792 + 'Email',
793 + 'User Identifier',
794 + 'Role',
795 + 'Message',
796 + 'Timestamp'
797 + ));
798 +
799 + // Add data rows
800 + foreach ($results as $row) {
801 + fputcsv($output, array(
802 + $row->session_id,
803 + $row->user_email,
804 + $row->user_identifier,
805 + $row->role,
806 + $row->message,
807 + $row->timestamp
808 + ));
809 + }
810 +
811 + fclose($output);
812 + wp_die();
651 813 }
652 814
815 +public function mxchat_fetch_chat_history() {
816 + global $wpdb;
817 + $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
818 +
819 + if (!current_user_can('manage_options')) {
820 + wp_die(esc_html__('You do not have sufficient permissions to view this page.', 'mxchat'));
821 + }
822 +
823 + // First get unique session IDs ordered by most recent message in each session
824 + $session_ids = $wpdb->get_col(
825 + $wpdb->prepare(
826 + "SELECT DISTINCT session_id
827 + FROM {$table_name}
828 + GROUP BY session_id
829 + ORDER BY MAX(timestamp) DESC"
830 + )
831 + );
832 +
833 + if (empty($session_ids)) {
834 + wp_die(esc_html__('No chat history available.', 'mxchat'));
835 + }
836 +
837 + ob_start();
838 + echo '<div class="mxchat-transcript">';
839 +
840 + // Iterate through sessions from newest to oldest
841 + foreach ($session_ids as $session_id) {
842 + // Get the email associated with this session (if available)
843 + $email = $wpdb->get_var(
844 + $wpdb->prepare(
845 + "SELECT user_email
846 + FROM {$table_name}
847 + WHERE session_id = %s AND user_email != ''
848 + ORDER BY timestamp ASC
849 + LIMIT 1",
850 + $session_id
851 + )
852 + );
853 +
854 + // Debug: Check email retrieval
855 + if (empty($email)) {
856 + //error_log("No email found for session {$session_id}");
857 + } else {
858 + //error_log("Email for session {$session_id}: " . $email);
859 + }
860 +
861 + // Get messages for this session ordered by timestamp
862 + $messages = $wpdb->get_results(
863 + $wpdb->prepare(
864 + "SELECT * FROM {$table_name}
865 + WHERE session_id = %s
866 + ORDER BY timestamp ASC",
867 + $session_id
868 + )
869 + );
870 +
871 + // Start session block
872 + echo '<div class="mxchat-session">';
873 + echo '<div class="mxchat-session-header">';
874 + // Wrap checkbox and session ID in one block
875 + echo '<div class="mxchat-session-id">';
876 + echo '<input type="checkbox" name="delete_session_ids[]" value="' . esc_attr($session_id) . '"> ';
877 + echo '<strong>' . esc_html__('Session ID:', 'mxchat') . '</strong> ' . esc_html($session_id);
878 + echo '</div>';
879 +
880 + // Place email directly below the session ID block
881 + if (!empty($email)) {
882 + echo '<div class="mxchat-session-email">';
883 + echo '<strong>' . esc_html__('Email:', 'mxchat') . '</strong> ' . esc_html($email);
884 + echo '</div>';
885 + }
886 + echo '</div>';
887 +
888 + echo '<div class="mxchat-messages">';
889 +
890 + // Display messages for this session
891 + foreach ($messages as $transcript) {
892 + $formatted_timestamp = date_i18n('F j, Y g:i a', strtotime($transcript->timestamp));
893 +
894 + // Determine message styling
895 + switch ($transcript->role) {
896 + case 'assistant':
897 + case 'bot':
898 + $message_class = 'bot-message';
899 + $display_role = esc_html__('Chatbot', 'mxchat');
900 + break;
901 + case 'user':
902 + $message_class = 'user-message';
903 + $display_role = !empty($transcript->user_identifier)
904 + ? sanitize_text_field($transcript->user_identifier)
905 + : esc_html__('User', 'mxchat');
906 + break;
907 + case 'agent':
908 + $message_class = 'agent-message';
909 + $display_role = esc_html__('Agent', 'mxchat');
910 + break;
911 + default:
912 + $message_class = 'unknown-message';
913 + $display_role = esc_html__('Unknown', 'mxchat');
914 + }
915 +
916 + // Process message content
917 + $message_content = wp_kses(
918 + stripslashes($transcript->message),
919 + [
920 + 'b' => [], 'strong' => [], 'i' => [], 'em' => [], 'u' => [],
921 + 'br' => [], 'p' => [], 'ul' => [], 'ol' => [], 'li' => [],
922 + 'a' => ['href' => [], 'title' => []]
923 + ]
924 + );
925 + $message_content = nl2br($message_content);
926 +
927 + // Render message
928 + echo '<div class="mxchat-message ' . esc_attr($message_class) . '">';
929 + echo '<div class="mxchat-message-header">' . esc_html($display_role) . '</div>';
930 + echo '<div class="mxchat-message-content">' . $message_content . '</div>';
931 + echo '<div class="mxchat-timestamp">' . esc_html($formatted_timestamp) . '</div>';
932 + echo '</div>';
933 + }
934 +
935 + // Close session block
936 + echo '</div></div>';
937 + }
938 +
939 + echo '</div>';
940 + $output = ob_get_clean();
941 + echo $output;
942 + wp_die();
943 +}
944 +
945 +
946 +
653 947 public function mxchat_create_prompts_page() {
654 948 global $wpdb;
655 949 $table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
656 950
@@ -781,10 +1075,9 @@
781 1075 <!-- Import Methods -->
782 1076 <div class="mxchat-import-methods">
783 1077 <div class="mxchat-method-card">
784 1078 <h4><?php esc_html_e('Sitemap Import', 'mxchat'); ?></h4>
785 - <p><?php esc_html_e('Import all content from your sitemap automatically.', 'mxchat'); ?></p>
786 - </div>
1079 + <p><span class="red-warning">IMPORTANT:</span> <?php esc_html_e('Use a content-specific sub-sitemap, not the sitemap index.', 'mxchat'); ?></p> </div>
787 1080 <div class="mxchat-method-card">
788 1081 <h4><?php esc_html_e('PDF Import', 'mxchat'); ?></h4>
789 1082 <p><?php esc_html_e('Import knowledge directly from PDF documents.', 'mxchat'); ?></p>
790 1083 </div>
@@ -1091,30 +1384,127 @@
1091 1384
1092 1385 wp_safe_redirect(add_query_arg(array('page' => 'mxchat-prompts', 'deleted' => 'true'), admin_url('admin.php')));
1093 1386 exit;
1094 1387 }
1095 -public function mxchat_generate_embedding($text) {
1096 - $options = get_option('mxchat_options');
1097 - $api_key = $options['api_key'] ?? esc_html__('default_api_key', 'mxchat');
1098 1388
1099 - $response = wp_remote_post('https://api.openai.com/v1/embeddings', array(
1100 - 'body' => wp_json_encode(array(
1101 - 'model' => esc_html__('text-embedding-ada-002', 'mxchat'),
1102 - 'input' => $text
1103 - )),
1104 - 'headers' => array(
1105 - 'Authorization' => 'Bearer ' . $api_key,
1106 - 'Content-Type' => esc_html__('application/json', 'mxchat')
1107 - ),
1108 - ));
1109 1389
1110 - if (is_wp_error($response)) {
1111 - return null;
1390 +public function mxchat_generate_embedding($text) {
1391 + //error_log('[MXCHAT-EMBED] Starting embedding generation. Text length: ' . strlen($text) . ' bytes');
1392 + //error_log('[MXCHAT-EMBED] Text preview: ' . substr($text, 0, 100) . '...');
1393 +
1394 + $options = get_option('mxchat_options');
1395 + $selected_model = $options['embedding_model'] ?? 'text-embedding-ada-002';
1396 + //error_log('[MXCHAT-EMBED] Selected embedding model: ' . $selected_model);
1397 +
1398 + // Determine provider and endpoint
1399 + if (strpos($selected_model, 'voyage') === 0) {
1400 + $api_key = $options['voyage_api_key'] ?? '';
1401 + $endpoint = 'https://api.voyageai.com/v1/embeddings';
1402 + //error_log('[MXCHAT-EMBED] Using Voyage AI API');
1403 + } else {
1404 + $api_key = $options['api_key'] ?? '';
1405 + $endpoint = 'https://api.openai.com/v1/embeddings';
1406 + //error_log('[MXCHAT-EMBED] Using OpenAI API');
1407 + }
1408 +
1409 + //error_log('[MXCHAT-EMBED] Using endpoint: ' . $endpoint);
1410 +
1411 + if (empty($api_key)) {
1412 + //error_log('[MXCHAT-EMBED] Error: API key not configured');
1413 + return null;
1414 + }
1415 +
1416 + // Check if text is too long (for OpenAI, roughly estimate tokens as words/0.75)
1417 + $estimated_tokens = ceil(str_word_count($text) / 0.75);
1418 + //error_log('[MXCHAT-EMBED] Estimated token count: ~' . $estimated_tokens);
1419 +
1420 + if ($estimated_tokens > 8000 && strpos($selected_model, 'voyage') === false) {
1421 + //error_log('[MXCHAT-EMBED] Warning: Text may exceed OpenAI token limits (8K for most models)');
1422 + // Consider truncating text here
1423 + }
1424 +
1425 + // Prepare request body
1426 + $request_body = array(
1427 + 'model' => $selected_model,
1428 + 'input' => $text
1429 + );
1430 +
1431 + // Add output_dimension for voyage-3-large model
1432 + if ($selected_model === 'voyage-3-large') {
1433 + $request_body['output_dimension'] = 2048;
1434 + }
1435 +
1436 + //error_log('[MXCHAT-EMBED] Request prepared with model: ' . $selected_model);
1437 +
1438 + // Make API request
1439 + //error_log('[MXCHAT-EMBED] Sending API request to: ' . $endpoint);
1440 + $response = wp_remote_post($endpoint, array(
1441 + 'body' => wp_json_encode($request_body),
1442 + 'headers' => array(
1443 + 'Authorization' => 'Bearer ' . $api_key,
1444 + 'Content-Type' => 'application/json'
1445 + ),
1446 + 'timeout' => 60 // Increased timeout for large inputs
1447 + ));
1448 +
1449 + // Handle wp_remote_post errors
1450 + if (is_wp_error($response)) {
1451 + //error_log('[MXCHAT-EMBED] WP Remote Post Error: ' . $response->get_error_message());
1452 + return null;
1453 + }
1454 +
1455 + // Get and check HTTP response code
1456 + $http_code = wp_remote_retrieve_response_code($response);
1457 + //error_log('[MXCHAT-EMBED] API Response Code: ' . $http_code);
1458 +
1459 + if ($http_code !== 200) {
1460 + $error_body = wp_remote_retrieve_body($response);
1461 + //error_log('[MXCHAT-EMBED] API Error Response Body: ' . $error_body);
1462 +
1463 + // Try to parse error for more details
1464 + $error_json = json_decode($error_body, true);
1465 + if (json_last_error() === JSON_ERROR_NONE && isset($error_json['error'])) {
1466 + //error_log('[MXCHAT-EMBED] API Error Type: ' . ($error_json['error']['type'] ?? 'unknown'));
1467 + //error_log('[MXCHAT-EMBED] API Error Message: ' . ($error_json['error']['message'] ?? 'No message'));
1112 1468 }
1113 -
1114 - $response_data = json_decode(wp_remote_retrieve_body($response), true);
1115 - return $response_data['data'][0]['embedding'] ?? null;
1469 +
1470 + return null;
1116 1471 }
1472 +
1473 + // Parse response body
1474 + $response_body = wp_remote_retrieve_body($response);
1475 + //error_log('[MXCHAT-EMBED] Received response length: ' . strlen($response_body) . ' bytes');
1476 +
1477 + $response_data = json_decode($response_body, true);
1478 +
1479 + if (json_last_error() !== JSON_ERROR_NONE) {
1480 + //error_log('[MXCHAT-EMBED] JSON Parse Error: ' . json_last_error_msg());
1481 + //error_log('[MXCHAT-EMBED] Response preview: ' . substr($response_body, 0, 200));
1482 + return null;
1483 + }
1484 +
1485 + // Both APIs use the same structure, so we can extract the embedding the same way
1486 + if (isset($response_data['data'][0]['embedding'])) {
1487 + $embedding_dimensions = count($response_data['data'][0]['embedding']);
1488 + //error_log('[MXCHAT-EMBED] Successfully extracted embedding with ' . $embedding_dimensions . ' dimensions');
1489 +
1490 + // Check if embedding dimensions are as expected
1491 + if (($selected_model === 'text-embedding-ada-002' && $embedding_dimensions !== 1536) ||
1492 + ($selected_model === 'voyage-3-large' && $embedding_dimensions !== 2048)) {
1493 + }
1494 +
1495 + return $response_data['data'][0]['embedding'];
1496 + } else {
1497 + //error_log('[MXCHAT-EMBED] Error: No embedding found in response');
1498 + //error_log('[MXCHAT-EMBED] Response structure: ' . wp_json_encode(array_keys($response_data)));
1499 +
1500 + if (isset($response_data['error'])) {
1501 + //error_log('[MXCHAT-EMBED] API Error in response: ' . wp_json_encode($response_data['error']));
1502 + }
1503 +
1504 + return null;
1505 + }
1506 +}
1117 1507 public function mxchat_delete_chat_history() {
1118 1508 if (!current_user_can('manage_options')) {
1119 1509 echo wp_json_encode(['error' => esc_html__('You do not have sufficient permissions.', 'mxchat')]);
1120 1510 wp_die();
@@ -1339,8 +1729,10 @@
1339 1729 'success' => true,
1340 1730 'message' => 'Successfully stored in Pinecone'
1341 1731 );
1342 1732 }
1733 +
1734 +
1343 1735 // Helper method for WordPress DB storage
1344 1736 private function store_in_wordpress_db($content, $url, $embedding_vector) {
1345 1737 global $wpdb;
1346 1738 $table_name = $wpdb->prefix . 'mxchat_system_prompt_content';
@@ -1716,19 +2108,26 @@
1716 2108 'status' => sanitize_text_field($status['status']),
1717 2109 'last_update' => human_time_diff(absint($status['last_update']), time()) . ' ' . esc_html__('ago', 'mxchat')
1718 2110 );
1719 2111 }
2112 +
1720 2113 public function mxchat_handle_sitemap_submission() {
2114 + // Start logging the submission process
2115 + //error_log('[MXCHAT-URL] ===== Starting URL submission process =====');
2116 +
1721 2117 // Check if the form was submitted and verify permissions
1722 2118 if (!isset($_POST['submit_sitemap']) || !current_user_can('manage_options')) {
2119 + //error_log('[MXCHAT-URL] Error: Unauthorized access or form not submitted properly');
1723 2120 wp_die(esc_html__('Unauthorized access', 'mxchat'));
1724 2121 }
1725 2122
1726 2123 // Verify nonce
2124 + //error_log('[MXCHAT-URL] Verifying nonce');
1727 2125 check_admin_referer('mxchat_submit_sitemap_action', 'mxchat_submit_sitemap_nonce');
1728 2126
1729 2127 // Validate URL
1730 2128 if (!isset($_POST['sitemap_url']) || empty($_POST['sitemap_url'])) {
2129 + //error_log('[MXCHAT-URL] Error: Empty or missing URL');
1731 2130 set_transient('mxchat_admin_notice_error',
1732 2131 esc_html__('Please provide a valid URL.', 'mxchat'),
1733 2132 30
1734 2133 );
@@ -1736,12 +2135,16 @@
1736 2135 exit;
1737 2136 }
1738 2137
1739 2138 $submitted_url = esc_url_raw($_POST['sitemap_url']);
2139 + //error_log('[MXCHAT-URL] Processing URL: ' . $submitted_url);
2140 +
2141 + //error_log('[MXCHAT-URL] Fetching URL content');
1740 2142 $response = wp_remote_get($submitted_url, array('timeout' => 30));
1741 2143
1742 2144 if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
1743 - $error_message = is_wp_error($response) ? $response->get_error_message() : __('Failed to fetch URL', 'mxchat');
2145 + $error_message = is_wp_error($response) ? $response->get_error_message() : 'HTTP Status: ' . wp_remote_retrieve_response_code($response);
2146 + //error_log('[MXCHAT-URL] Error fetching URL: ' . $error_message);
1744 2147 set_transient('mxchat_admin_notice_error',
1745 2148 sprintf(
1746 2149 esc_html__('Failed to fetch the URL: %s', 'mxchat'),
1747 2150 esc_html($error_message)
@@ -1752,11 +2155,13 @@
1752 2155 exit;
1753 2156 }
1754 2157
1755 2158 $content_type = wp_remote_retrieve_header($response, 'content-type');
2159 + //error_log('[MXCHAT-URL] Content type: ' . $content_type);
1756 2160 $body_content = wp_remote_retrieve_body($response);
1757 2161
1758 2162 if (empty($body_content)) {
2163 + //error_log('[MXCHAT-URL] Error: Empty response body');
1759 2164 set_transient('mxchat_admin_notice_error',
1760 2165 esc_html__('Empty response received from URL.', 'mxchat'),
1761 2166 30
1762 2167 );
@@ -1762,12 +2167,15 @@
1762 2167 );
1763 2168 wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
1764 2169 exit;
1765 2170 }
2171 + //error_log('[MXCHAT-URL] Retrieved body content length: ' . strlen($body_content) . ' bytes');
1766 2172
1767 2173 // Handle PDF URL
1768 2174 if ($this->is_pdf_url($submitted_url, $response)) {
2175 + //error_log('[MXCHAT-URL] Detected PDF URL, handling PDF for knowledge base');
1769 2176 $result = $this->handle_pdf_for_knowledge_base($submitted_url, $response);
2177 + //error_log('[MXCHAT-URL] PDF handling result: ' . $result);
1770 2178
1771 2179 if ($result === 'scheduled') {
1772 2180 set_transient(
1773 2181 'mxchat_last_pdf_url',
@@ -1790,8 +2198,9 @@
1790 2198 }
1791 2199
1792 2200 // Handle Sitemap XML
1793 2201 if (strpos($content_type, 'xml') !== false || strpos($body_content, '<urlset') !== false) {
2202 + //error_log('[MXCHAT-URL] Detected XML content, processing as sitemap');
1794 2203 libxml_use_internal_errors(true);
1795 2204 $xml = simplexml_load_string($body_content);
1796 2205 $xml_errors = libxml_get_errors();
1797 2206 libxml_clear_errors();
@@ -1796,8 +2205,15 @@
1796 2205 $xml_errors = libxml_get_errors();
1797 2206 libxml_clear_errors();
1798 2207
1799 2208 if ($xml === false || !empty($xml_errors)) {
2209 + //error_log('[MXCHAT-URL] Error: Invalid XML format');
2210 + if (!empty($xml_errors)) {
2211 + foreach ($xml_errors as $error) {
2212 + //error_log('[MXCHAT-URL] XML Error: ' . $error->message);
2213 + }
2214 + }
2215 +
1800 2216 set_transient('mxchat_admin_notice_error',
1801 2217 esc_html__('Invalid sitemap XML. Please provide a valid sitemap.', 'mxchat'),
1802 2218 30
1803 2219 );
@@ -1804,9 +2220,11 @@
1804 2220 wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
1805 2221 exit;
1806 2222 }
1807 2223
2224 + //error_log('[MXCHAT-URL] Valid XML found, handling sitemap for knowledge base');
1808 2225 $result = $this->handle_sitemap_for_knowledge_base($xml, $submitted_url);
2226 + //error_log('[MXCHAT-URL] Sitemap handling result: ' . $result);
1809 2227
1810 2228 if ($result === 'scheduled') {
1811 2229 set_transient(
1812 2230 'mxchat_last_sitemap_url',
@@ -1828,12 +2246,17 @@
1828 2246 exit;
1829 2247 }
1830 2248
1831 2249 // Handle Regular URL
2250 + //error_log('[MXCHAT-URL] Processing as regular webpage');
1832 2251 $page_content = $this->mxchat_extract_main_content($body_content);
2252 + //error_log('[MXCHAT-URL] Extracted content length: ' . strlen($page_content) . ' bytes');
2253 +
1833 2254 $sanitized_content = $this->mxchat_sanitize_content_for_api($page_content);
2255 + //error_log('[MXCHAT-URL] Sanitized content length: ' . strlen($sanitized_content) . ' bytes');
1834 2256
1835 2257 if (empty($sanitized_content)) {
2258 + //error_log('[MXCHAT-URL] Error: No valid content after sanitization');
1836 2259 set_transient('mxchat_admin_notice_error',
1837 2260 esc_html__('No valid content found on the provided URL.', 'mxchat'),
1838 2261 30
1839 2262 );
@@ -1840,20 +2263,33 @@
1840 2263 wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
1841 2264 exit;
1842 2265 }
1843 2266
2267 + //error_log('[MXCHAT-URL] Generating embedding for content');
1844 2268 $embedding_vector = $this->mxchat_generate_embedding($sanitized_content);
2269 +
1845 2270 if (is_array($embedding_vector)) {
1846 - MxChat_Utils::submit_content_to_db(
2271 + //error_log('[MXCHAT-URL] Successfully generated embedding with ' . count($embedding_vector) . ' dimensions');
2272 +
2273 + //error_log('[MXCHAT-URL] Submitting content to database');
2274 + $db_result = MxChat_Utils::submit_content_to_db(
1847 2275 $sanitized_content,
1848 2276 $submitted_url,
1849 2277 $this->options['api_key']
1850 2278 );
2279 +
2280 + if ($db_result) {
2281 + //error_log('[MXCHAT-URL] Successfully stored content in database');
2282 + } else {
2283 + //error_log('[MXCHAT-URL] Error: Failed to store content in database');
2284 + }
2285 +
1851 2286 set_transient('mxchat_admin_notice_success',
1852 2287 esc_html__('URL content successfully submitted!', 'mxchat'),
1853 2288 30
1854 2289 );
1855 2290 } else {
2291 + //error_log('[MXCHAT-URL] Error: Failed to generate embedding. Result: ' . (is_string($embedding_vector) ? $embedding_vector : gettype($embedding_vector)));
1856 2292 set_transient('mxchat_admin_notice_error',
1857 2293 esc_html__('Failed to generate embedding for the URL content. Please check your API key and try again.', 'mxchat'),
1858 2294 30
1859 2295 );
@@ -1858,11 +2294,14 @@
1858 2294 30
1859 2295 );
1860 2296 }
1861 2297
2298 + //error_log('[MXCHAT-URL] ===== Completed URL submission process =====');
1862 2299 wp_safe_redirect(esc_url(admin_url('admin.php?page=mxchat-prompts')));
1863 2300 exit;
1864 2301 }
2302 +
2303 +
1865 2304 private function handle_sitemap_for_knowledge_base($xml, $sitemap_url) {
1866 2305 if (!current_user_can('manage_options')) {
1867 2306 //error_log(esc_html__('Unauthorized sitemap processing attempt', 'mxchat'));
1868 2307 return false;
@@ -1975,9 +2414,9 @@
1975 2414
1976 2415 $batch_stats['processed']++;
1977 2416 } else {
1978 2417 $batch_stats['failed']++;
1979 - $batch_stats['last_error'] = 'Failed to generate embedding. Please check OpenAI API key.';
2418 + $batch_stats['last_error'] = 'Failed to generate embedding. Please check embedding API key.';
1980 2419 }
1981 2420 }
1982 2421
1983 2422 $status['processed_urls'] = absint($i + 1);
@@ -2206,8 +2645,9 @@
2206 2645 $wpdb->delete($table_name, array('source_url' => $source_url), array('%s'));
2207 2646 }
2208 2647 }
2209 2648
2649 +
2210 2650 /**
2211 2651 * Delete vectors from Pinecone by source URL
2212 2652 *
2213 2653 * @param array $urls Array of source URLs to delete
@@ -2296,139 +2736,11 @@
2296 2736 );
2297 2737 }
2298 2738
2299 2739
2300 -public function mxchat_fetch_chat_history() {
2301 - global $wpdb;
2302 - $table_name = $wpdb->prefix . 'mxchat_chat_transcripts';
2303 2740
2304 - if (!current_user_can('manage_options')) {
2305 - wp_die(esc_html__('You do not have sufficient permissions to view this page.', 'mxchat'));
2306 - }
2307 2741
2308 - // First get unique session IDs ordered by most recent message in each session
2309 - $session_ids = $wpdb->get_col(
2310 - $wpdb->prepare(
2311 - "SELECT DISTINCT session_id
2312 - FROM {$table_name}
2313 - GROUP BY session_id
2314 - ORDER BY MAX(timestamp) DESC"
2315 - )
2316 - );
2317 2742
2318 - if (empty($session_ids)) {
2319 - wp_die(esc_html__('No chat history available.', 'mxchat'));
2320 - }
2321 -
2322 - ob_start();
2323 - echo '<div class="mxchat-transcript">';
2324 -
2325 - // Iterate through sessions from newest to oldest
2326 - foreach ($session_ids as $session_id) {
2327 - // Get the email associated with this session (if available)
2328 - $email = $wpdb->get_var(
2329 - $wpdb->prepare(
2330 - "SELECT user_email
2331 - FROM {$table_name}
2332 - WHERE session_id = %s AND user_email != ''
2333 - ORDER BY timestamp ASC
2334 - LIMIT 1",
2335 - $session_id
2336 - )
2337 - );
2338 -
2339 - // Debug: Check email retrieval
2340 - if (empty($email)) {
2341 - //error_log("No email found for session {$session_id}");
2342 - } else {
2343 - //error_log("Email for session {$session_id}: " . $email);
2344 - }
2345 -
2346 - // Get messages for this session ordered by timestamp
2347 - $messages = $wpdb->get_results(
2348 - $wpdb->prepare(
2349 - "SELECT * FROM {$table_name}
2350 - WHERE session_id = %s
2351 - ORDER BY timestamp ASC",
2352 - $session_id
2353 - )
2354 - );
2355 -
2356 - // Start session block
2357 - echo '<div class="mxchat-session">';
2358 - echo '<div class="mxchat-session-header">';
2359 - // Wrap checkbox and session ID in one block
2360 - echo '<div class="mxchat-session-id">';
2361 - echo '<input type="checkbox" name="delete_session_ids[]" value="' . esc_attr($session_id) . '"> ';
2362 - echo '<strong>' . esc_html__('Session ID:', 'mxchat') . '</strong> ' . esc_html($session_id);
2363 - echo '</div>';
2364 -
2365 - // Place email directly below the session ID block
2366 - if (!empty($email)) {
2367 - echo '<div class="mxchat-session-email">';
2368 - echo '<strong>' . esc_html__('Email:', 'mxchat') . '</strong> ' . esc_html($email);
2369 - echo '</div>';
2370 - }
2371 - echo '</div>';
2372 -
2373 - echo '<div class="mxchat-messages">';
2374 -
2375 - // Display messages for this session
2376 - foreach ($messages as $transcript) {
2377 - $formatted_timestamp = date_i18n('F j, Y g:i a', strtotime($transcript->timestamp));
2378 -
2379 - // Determine message styling
2380 - switch ($transcript->role) {
2381 - case 'assistant':
2382 - case 'bot':
2383 - $message_class = 'bot-message';
2384 - $display_role = esc_html__('Chatbot', 'mxchat');
2385 - break;
2386 - case 'user':
2387 - $message_class = 'user-message';
2388 - $display_role = !empty($transcript->user_identifier)
2389 - ? sanitize_text_field($transcript->user_identifier)
2390 - : esc_html__('User', 'mxchat');
2391 - break;
2392 - case 'agent':
2393 - $message_class = 'agent-message';
2394 - $display_role = esc_html__('Agent', 'mxchat');
2395 - break;
2396 - default:
2397 - $message_class = 'unknown-message';
2398 - $display_role = esc_html__('Unknown', 'mxchat');
2399 - }
2400 -
2401 - // Process message content
2402 - $message_content = wp_kses(
2403 - stripslashes($transcript->message),
2404 - [
2405 - 'b' => [], 'strong' => [], 'i' => [], 'em' => [], 'u' => [],
2406 - 'br' => [], 'p' => [], 'ul' => [], 'ol' => [], 'li' => [],
2407 - 'a' => ['href' => [], 'title' => []]
2408 - ]
2409 - );
2410 - $message_content = nl2br($message_content);
2411 -
2412 - // Render message
2413 - echo '<div class="mxchat-message ' . esc_attr($message_class) . '">';
2414 - echo '<div class="mxchat-message-header">' . esc_html($display_role) . '</div>';
2415 - echo '<div class="mxchat-message-content">' . $message_content . '</div>';
2416 - echo '<div class="mxchat-timestamp">' . esc_html($formatted_timestamp) . '</div>';
2417 - echo '</div>';
2418 - }
2419 -
2420 - // Close session block
2421 - echo '</div></div>';
2422 - }
2423 -
2424 - echo '</div>';
2425 - $output = ob_get_clean();
2426 - echo $output;
2427 - wp_die();
2428 -}
2429 -
2430 -
2431 2743 public function mxchat_create_activation_page() {
2432 2744 $license_status = get_option('mxchat_license_status', 'inactive');
2433 2745 $license_error = get_option('mxchat_license_error', '');
2434 2746 ?>
@@ -3037,22 +3349,12 @@
3037 3349
3038 3350 private function mxchat_get_available_callbacks($grouped = false) {
3039 3351 $callbacks = [
3040 3352 'mxchat_handle_email_capture' => [
3041 - 'label' => __('Email Capture', 'mxchat'),
3353 + 'label' => __('Loops Email Capture', 'mxchat'),
3042 3354 'pro_only' => false,
3043 3355 'group' => __('Customer Engagement', 'mxchat'),
3044 3356 ],
3045 - 'mxchat_handle_product_inquiry' => [
3046 - 'label' => __('Show Product Card', 'mxchat'),
3047 - 'pro_only' => true,
3048 - 'group' => __('WooCommerce Features', 'mxchat'),
3049 - ],
3050 - 'mxchat_handle_order_history' => [
3051 - 'label' => __('Order History', 'mxchat'),
3052 - 'pro_only' => true,
3053 - 'group' => __('WooCommerce Features', 'mxchat'),
3054 - ],
3055 3357 'mxchat_generate_image' => [
3056 3358 'label' => __('Generate Image', 'mxchat'),
3057 3359 'pro_only' => true,
3058 3360 'group' => __('Other Features', 'mxchat'),
@@ -3066,28 +3368,13 @@
3066 3368 'label' => __('Brave Image Search', 'mxchat'),
3067 3369 'pro_only' => false,
3068 3370 'group' => __('Search Features', 'mxchat'),
3069 3371 ],
3070 - 'mxchat_handle_add_to_cart_intent' => [
3071 - 'label' => __('Add to Cart', 'mxchat'),
3072 - 'pro_only' => true,
3073 - 'group' => __('WooCommerce Features', 'mxchat'),
3074 - ],
3075 - 'mxchat_handle_checkout_intent' => [
3076 - 'label' => __('Proceed to Checkout', 'mxchat'),
3077 - 'pro_only' => true,
3078 - 'group' => __('WooCommerce Features', 'mxchat'),
3079 - ],
3080 3372 'mxchat_handle_pdf_discussion' => [
3081 3373 'label' => __('Chat with PDF', 'mxchat'),
3082 3374 'pro_only' => true,
3083 3375 'group' => __('Other Features', 'mxchat'),
3084 3376 ],
3085 - 'mxchat_handle_product_recommendations' => [
3086 - 'label' => __('Product Recommendations', 'mxchat'),
3087 - 'pro_only' => true,
3088 - 'group' => __('WooCommerce Features', 'mxchat'),
3089 - ],
3090 3377 'mxchat_live_agent_handover' => [
3091 3378 'label' => __('Live Agent', 'mxchat'),
3092 3379 'pro_only' => true,
3093 3380 'group' => __('Customer Engagement', 'mxchat'),
@@ -3098,8 +3385,11 @@
3098 3385 'group' => __('Customer Engagement', 'mxchat'),
3099 3386 ],
3100 3387 ];
3101 3388
3389 + // Allow other plugins to add their callbacks
3390 + $callbacks = apply_filters('mxchat_available_callbacks', $callbacks);
3391 +
3102 3392 // Return grouped structure if requested
3103 3393 if ($grouped) {
3104 3394 $grouped_callbacks = [];
3105 3395 foreach ($callbacks as $key => $data) {
@@ -3110,14 +3400,12 @@
3110 3400 ];
3111 3401 }
3112 3402 return $grouped_callbacks;
3113 3403 }
3114 -
3115 3404 return $callbacks;
3116 3405 }
3117 3406
3118 3407
3119 -
3120 3408 private function mxchat_average_vectors($vectors) {
3121 3409 $vector_length = count($vectors[0]);
3122 3410 $sum_vector = array_fill(0, $vector_length, 0);
3123 3411
@@ -3234,10 +3522,36 @@
3234 3522 array($this, 'deepseek_api_key_callback'),
3235 3523 'mxchat-chatbot',
3236 3524 'mxchat_chatbot_section'
3237 3525 );
3526 +
3527 + add_settings_field(
3528 + 'voyage_api_key',
3529 + esc_html__('Voyage AI API Key', 'mxchat'),
3530 + array($this, 'voyage_api_key_callback'),
3531 + 'mxchat-chatbot',
3532 + 'mxchat_chatbot_section'
3533 + );
3534 +
3238 3535
3239 3536 add_settings_field(
3537 + 'model',
3538 + esc_html__('Chat Model', 'mxchat'),
3539 + array($this, 'mxchat_model_callback'),
3540 + 'mxchat-chatbot',
3541 + 'mxchat_chatbot_section'
3542 + );
3543 +
3544 + // Add the settings field
3545 + add_settings_field(
3546 + 'embedding_model',
3547 + esc_html__('Embedding Model', 'mxchat'),
3548 + array($this, 'embedding_model_callback'),
3549 + 'mxchat-chatbot',
3550 + 'mxchat_chatbot_section'
3551 + );
3552 +
3553 + add_settings_field(
3240 3554 'system_prompt_instructions',
3241 3555 esc_html__('AI Instructions (Behavior)', 'mxchat'),
3242 3556 array($this, 'system_prompt_instructions_callback'),
3243 3557 'mxchat-chatbot',
@@ -3243,15 +3557,8 @@
3243 3557 'mxchat-chatbot',
3244 3558 'mxchat_chatbot_section'
3245 3559 );
3246 3560
3247 - add_settings_field(
3248 - 'model',
3249 - esc_html__('Model', 'mxchat'),
3250 - array($this, 'mxchat_model_callback'),
3251 - 'mxchat-chatbot',
3252 - 'mxchat_chatbot_section'
3253 - );
3254 3561
3255 3562 add_settings_field(
3256 3563 'top_bar_title',
3257 3564 esc_html__('Top Bar Title', 'mxchat'),
@@ -3365,9 +3672,9 @@
3365 3672 );
3366 3673
3367 3674 add_settings_field(
3368 3675 'popular_question_1',
3369 - esc_html__('Popular Question 1', 'mxchat'),
3676 + esc_html__('Quick Question 1', 'mxchat'),
3370 3677 array($this, 'mxchat_popular_question_1_callback'),
3371 3678 'mxchat-chatbot',
3372 3679 'mxchat_chatbot_section'
3373 3680 );
@@ -3373,9 +3680,9 @@
3373 3680 );
3374 3681
3375 3682 add_settings_field(
3376 3683 'popular_question_2',
3377 - esc_html__('Popular Question 2', 'mxchat'),
3684 + esc_html__('Quick Question 2', 'mxchat'),
3378 3685 array($this, 'mxchat_popular_question_2_callback'),
3379 3686 'mxchat-chatbot',
3380 3687 'mxchat_chatbot_section'
3381 3688 );
@@ -3381,9 +3688,9 @@
3381 3688 );
3382 3689
3383 3690 add_settings_field(
3384 3691 'popular_question_3',
3385 - esc_html__('Popular Question 3', 'mxchat'),
3692 + esc_html__('Quick Question 3', 'mxchat'),
3386 3693 array($this, 'mxchat_popular_question_3_callback'),
3387 3694 'mxchat-chatbot',
3388 3695 'mxchat_chatbot_section'
3389 3696 );
@@ -3389,21 +3696,14 @@
3389 3696 );
3390 3697
3391 3698 add_settings_field(
3392 3699 'additional_popular_questions',
3393 - esc_html__('Additional Popular Questions', 'mxchat'),
3700 + esc_html__('Additional Quick Questions', 'mxchat'),
3394 3701 array($this, 'mxchat_additional_popular_questions_callback'),
3395 3702 'mxchat-chatbot',
3396 3703 'mxchat_chatbot_section'
3397 3704 );
3398 3705
3399 - // WooCommerce Settings Section
3400 - add_settings_section(
3401 - 'mxchat_woocommerce_section',
3402 - esc_html__('WooCommerce Settings', 'mxchat'),
3403 - null,
3404 - 'mxchat-embed'
3405 - );
3406 3706
3407 3707 // Loops Settings Section
3408 3708 add_settings_section(
3409 3709 'mxchat_loops_section',
@@ -3411,33 +3711,8 @@
3411 3711 null,
3412 3712 'mxchat-embed'
3413 3713 );
3414 3714
3415 - // WooCommerce Settings Fields
3416 - add_settings_field(
3417 - 'enable_woocommerce_integration',
3418 - esc_html__('Automatically Embed Products', 'mxchat'),
3419 - array($this, 'mxchat_enable_woocommerce_integration_callback'),
3420 - 'mxchat-embed',
3421 - 'mxchat_woocommerce_section'
3422 - );
3423 -
3424 - add_settings_field(
3425 - 'woocommerce_consumer_key',
3426 - esc_html__('WooCommerce Consumer Key', 'mxchat'),
3427 - array($this, 'mxchat_woocommerce_consumer_key_callback'),
3428 - 'mxchat-embed',
3429 - 'mxchat_woocommerce_section'
3430 - );
3431 -
3432 - add_settings_field(
3433 - 'woocommerce_consumer_secret',
3434 - esc_html__('WooCommerce Consumer Secret', 'mxchat'),
3435 - array($this, 'mxchat_woocommerce_consumer_secret_callback'),
3436 - 'mxchat-embed',
3437 - 'mxchat_woocommerce_section'
3438 - );
3439 -
3440 3715 // Loops Settings Fields
3441 3716 add_settings_field(
3442 3717 'loops_api_key',
3443 3718 esc_html__('Loops API Key', 'mxchat'),
@@ -3540,8 +3815,26 @@
3540 3815 array($this, 'mxchat_chat_toolbar_toggle_callback'),
3541 3816 'mxchat-embed',
3542 3817 'mxchat_pdf_intent_section'
3543 3818 );
3819 +
3820 + // PDF Upload Button Toggle
3821 + add_settings_field(
3822 + 'show_pdf_upload_button',
3823 + __('Show PDF Upload Button', 'mxchat'),
3824 + array($this, 'mxchat_show_pdf_upload_button_callback'),
3825 + 'mxchat-embed',
3826 + 'mxchat_pdf_intent_section'
3827 + );
3828 +
3829 + // Word Upload Button Toggle
3830 + add_settings_field(
3831 + 'show_word_upload_button',
3832 + __('Show Word Upload Button', 'mxchat'),
3833 + array($this, 'mxchat_show_word_upload_button_callback'),
3834 + 'mxchat-embed',
3835 + 'mxchat_pdf_intent_section'
3836 + );
3544 3837
3545 3838 add_settings_field(
3546 3839 'pdf_intent_trigger_text',
3547 3840 __('Intent Trigger Text', 'mxchat'),
@@ -3638,9 +3931,9 @@
3638 3931
3639 3932 // General Settings Section
3640 3933 add_settings_section(
3641 3934 'mxchat_general_section',
3642 - esc_html__('Frequently Asked Questions (FAQ)', 'mxchat'),
3935 + esc_html__('YouTube Tutorials', 'mxchat'),
3643 3936 null,
3644 3937 'mxchat-general'
3645 3938 );
3646 3939 }
@@ -3883,52 +4176,8 @@
3883 4176 echo '</div>';
3884 4177 }
3885 4178
3886 4179
3887 -public function mxchat_enable_woocommerce_integration_callback() {
3888 - // Load from mxchat_options array
3889 - $options = get_option('mxchat_options', []);
3890 -
3891 - // Get WooCommerce integration status with backwards compatibility
3892 - $woo_integration = isset($options['enable_woocommerce_integration'])
3893 - ? $options['enable_woocommerce_integration']
3894 - : '';
3895 -
3896 - // Support both old ('1') and new ('on') values
3897 - $checked = ($woo_integration === 'on' || $woo_integration === '1') ? 'checked' : '';
3898 -
3899 - // Check if the feature is activated (paid feature)
3900 - $disabled = $this->is_activated ? '' : 'disabled';
3901 - $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
3902 -
3903 - echo '<div class="' . esc_attr($class) . '">';
3904 -
3905 - echo '<label class="toggle-switch">';
3906 - echo sprintf(
3907 - '<input type="checkbox" id="enable_woocommerce_integration" name="enable_woocommerce_integration" value="on" %s %s />',
3908 - esc_attr($checked),
3909 - esc_attr($disabled)
3910 - );
3911 - echo '<span class="slider"></span>';
3912 - echo '</label>';
3913 -
3914 - echo '<p class="description">' . esc_html__('Automatically syncs new product additions, updates, and removals to the knowledge base. For existing products, submit your product sitemap in the Knowledge Base section to add them initially.', 'mxchat') . '</p>';
3915 -
3916 - // Pro feature overlay for non-activated users
3917 - if (!$this->is_activated) {
3918 - echo '<div class="pro-feature-overlay">';
3919 - echo '<a href="https://mxchat.ai/" target="_blank">';
3920 - echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />';
3921 - echo '</a>';
3922 - echo '</div>';
3923 - }
3924 -
3925 - echo '</div>';
3926 -}
3927 -
3928 -
3929 -
3930 -
3931 4180 private function mxchat_add_option_field($id, $title, $callback = '') {
3932 4181 add_settings_field(
3933 4182 $id,
3934 4183 __($title, 'mxchat'),
@@ -3945,9 +4194,8 @@
3945 4194
3946 4195 // Notice we changed the name to "api_key" (no array notation).
3947 4196 echo '<input type="password" id="api_key" name="api_key" value="' . $apiKey . '" class="regular-text" />';
3948 4197 echo '<button type="button" id="toggleApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>';
3949 - echo '<p class="description">' . esc_html__('The OpenAI API key is required even when using other models as it is used for vector embedding functionality. You must add credits to your OpenAI billing account before use.', 'mxchat') . '</p>';
3950 4198 }
3951 4199 public function xai_api_key_callback() {
3952 4200 // Check if the feature is activated (paid feature)
3953 4201 $disabled = $this->is_activated ? '' : 'disabled'; // Disable input if not activated
@@ -4007,79 +4255,11 @@
4007 4255 echo '<button type="button" id="toggleDeepSeekApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>';
4008 4256 }
4009 4257
4010 4258
4011 -public function mxchat_woocommerce_consumer_key_callback() {
4012 - // Load the entire 'mxchat_options' array
4013 - $all_options = get_option('mxchat_options', []);
4014 4259
4015 - // Retrieve the WooCommerce consumer key or set a default
4016 - $consumer_key = isset($all_options['woocommerce_consumer_key']) ? $all_options['woocommerce_consumer_key'] : '';
4017 4260
4018 - // Check if the feature is activated (paid feature)
4019 - $disabled = $this->is_activated ? '' : 'disabled';
4020 - $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
4021 4261
4022 - echo '<div class="' . esc_attr($class) . '">';
4023 -
4024 - // Render the input field
4025 - printf(
4026 - '<input type="text" id="woocommerce_consumer_key" name="woocommerce_consumer_key" value="%s" class="regular-text" %s />',
4027 - esc_attr($consumer_key),
4028 - esc_attr($disabled)
4029 - );
4030 -
4031 - // Description for the input field
4032 - echo '<p class="description">' . esc_html__('Enter your WooCommerce consumer key for integration.', 'mxchat') . '</p>';
4033 -
4034 - // Pro feature overlay for non-activated users
4035 - if (!$this->is_activated) {
4036 - echo '<div class="pro-feature-overlay">';
4037 - echo '<a href="https://mxchat.ai/" target="_blank"><img src="' . plugin_dir_url(__FILE__) . '../images/pro-only-dark.png" alt="' . esc_attr__('Pro Only', 'mxchat') . '" /></a>';
4038 - echo '</div>';
4039 - }
4040 -
4041 - echo '</div>';
4042 -}
4043 -
4044 -public function mxchat_woocommerce_consumer_secret_callback() {
4045 - // Get value with fallback
4046 - $consumer_secret = isset($this->options['woocommerce_consumer_secret'])
4047 - ? esc_attr($this->options['woocommerce_consumer_secret'])
4048 - : '';
4049 -
4050 - // Check if the feature is activated (paid feature)
4051 - $disabled = $this->is_activated ? '' : 'disabled';
4052 - $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
4053 -
4054 - echo '<div class="' . esc_attr($class) . '">';
4055 -
4056 - // Output the password input
4057 - echo sprintf(
4058 - '<input type="password"
4059 - id="woocommerce_consumer_secret"
4060 - name="woocommerce_consumer_secret"
4061 - value="%s"
4062 - class="regular-text"
4063 - %s />',
4064 - $consumer_secret,
4065 - esc_attr($disabled)
4066 - );
4067 -
4068 - // Add show/hide button
4069 - echo '<button type="button" id="toggleWooCommerceSecretVisibility">' . esc_html__('Show', 'mxchat') . '</button>';
4070 -
4071 - // Pro feature overlay
4072 - if (!$this->is_activated) {
4073 - echo '<div class="pro-feature-overlay">';
4074 - echo '<a href="https://mxchat.ai/" target="_blank">';
4075 - echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />';
4076 - echo '</a>';
4077 - echo '</div>';
4078 - }
4079 -
4080 - echo '</div>';
4081 -}
4082 4262 public function mxchat_loops_api_key_callback() {
4083 4263 // Support both old and new format
4084 4264 $loops_api_key = isset($this->options['loops_api_key']) ? esc_attr($this->options['loops_api_key']) : '';
4085 4265
@@ -4089,9 +4269,9 @@
4089 4269 $loops_api_key
4090 4270 );
4091 4271 echo '<button type="button" id="toggleLoopsApiKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>';
4092 4272 echo '</div>';
4093 - echo '<p class="description">' . esc_html__('Enter your Loops API Key here. (See FAQ for details)', 'mxchat') . '</p>';
4273 + 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>';
4094 4274 }
4095 4275
4096 4276 public function mxchat_loops_mailing_list_callback() {
4097 4277 // Add error handling and type checking
@@ -4200,9 +4380,10 @@
4200 4380 esc_html__('DeepSeek Models', 'mxchat') => array(
4201 4381 'deepseek-chat' => esc_html__('DeepSeek-V3', 'mxchat'),
4202 4382 ),
4203 4383 esc_html__('Claude Models', 'mxchat') => array(
4204 - 'claude-3-5-sonnet-20241022' => esc_html__('Claude 3.5 Sonnet (Most Intelligent)', 'mxchat'),
4384 + 'claude-3-7-sonnet-20250219' => esc_html__('Claude 3.7 Sonnet (Most Intelligent)', 'mxchat'),
4385 + 'claude-3-5-sonnet-20241022' => esc_html__('Claude 3.5 Sonnet (Intelligent)', 'mxchat'),
4205 4386 'claude-3-opus-20240229' => esc_html__('Claude 3 Opus (Highly Complex Tasks)', 'mxchat'),
4206 4387 'claude-3-sonnet-20240229' => esc_html__('Claude 3 Sonnet (Balanced)', 'mxchat'),
4207 4388 'claude-3-haiku-20240307' => esc_html__('Claude 3 Haiku (Fastest)', 'mxchat')
4208 4389 ),
@@ -4240,13 +4421,46 @@
4240 4421 // Close the select dropdown
4241 4422 echo '</select>';
4242 4423
4243 4424 // Add a description below the dropdown
4244 - echo '<p class="description">' . esc_html__('Select the AI model to use for your chatbot. Pro-only models are marked accordingly.', 'mxchat') . '</p>';
4425 + echo '<p class="description">' . esc_html__('Select the AI model your chatbot will use for chatting. Pro-only models are marked accordingly.', 'mxchat') . '</p>';
4245 4426 }
4246 4427
4428 +public function voyage_api_key_callback() {
4429 + $apiKey = isset($this->options['voyage_api_key']) ? esc_attr($this->options['voyage_api_key']) : '';
4430 + echo '<input type="password" id="voyage_api_key" name="voyage_api_key" value="' . $apiKey . '" class="regular-text" />';
4431 + echo '<button type="button" id="toggleVoyageAPIKeyVisibility">' . esc_html__('Show', 'mxchat') . '</button>';
4432 +}
4247 4433
4434 +// Callback function for embedding model selection
4435 +public function embedding_model_callback() {
4436 + $models = array(
4437 + esc_html__('OpenAI Embeddings', 'mxchat') => array(
4438 + 'text-embedding-3-small' => esc_html__('TE3 Small (1536, Efficient)', 'mxchat'),
4439 + 'text-embedding-ada-002' => esc_html__('Ada 2 (1536, Original)', 'mxchat'),
4440 + 'text-embedding-3-large' => esc_html__('TE3 Large (3072, Powerful)', 'mxchat'),
4441 + ),
4442 + esc_html__('Voyage AI Embeddings', 'mxchat') => array(
4443 + 'voyage-3-large' => esc_html__('Voyage-3 Large (2048, Most Capable)', 'mxchat'),
4444 + )
4445 + );
4248 4446
4447 + $selected_model = isset($this->options['embedding_model']) ? esc_attr($this->options['embedding_model']) : 'text-embedding-ada-002';
4448 +
4449 + echo '<select id="embedding_model" name="embedding_model">';
4450 + foreach ($models as $group_label => $group_models) {
4451 + echo '<optgroup label="' . esc_attr($group_label) . '">';
4452 + foreach ($group_models as $model_value => $model_label) {
4453 + echo '<option value="' . esc_attr($model_value) . '" ' . selected($selected_model, $model_value, false) . '>' . esc_html($model_label) . '</option>';
4454 + }
4455 + echo '</optgroup>';
4456 + }
4457 + echo '</select>';
4458 +echo '<p class="description"><span class="red-warning">IMPORTANT:</span> Select the model for vector embeddings. Changing models is not recommended; if you do, you must delete all existing knowledge & intent data and reconfigure them.</p>';
4459 +
4460 +}
4461 +
4462 +
4249 4463 public function mxchat_top_bar_title_callback() {
4250 4464 // Retrieve the current value of the top bar title from saved options
4251 4465 $top_bar_title = isset($this->options['top_bar_title']) ? esc_attr($this->options['top_bar_title']) : '';
4252 4466
@@ -4909,13 +5123,13 @@
4909 5123 // Render the input field
4910 5124 printf(
4911 5125 '<input type="text" id="popular_question_1" name="popular_question_1" value="%s" placeholder="%s" class="regular-text" />',
4912 5126 esc_attr($popular_question_1),
4913 - esc_attr__('Enter Popular Question 1', 'mxchat')
5127 + esc_attr__('Enter Quick Question 1', 'mxchat')
4914 5128 );
4915 5129
4916 5130 // Add a description for the field
4917 - echo '<p class="description">' . esc_html__('This will be the first popular question in the chatbot.', 'mxchat') . '</p>';
5131 + echo '<p class="description">' . esc_html__('This will be the first Quick Question in the chatbot, displayed above the input field.', 'mxchat') . '</p>';
4918 5132 }
4919 5133
4920 5134
4921 5135 public function mxchat_popular_question_2_callback() {
@@ -4928,13 +5142,13 @@
4928 5142 // Render the input field
4929 5143 printf(
4930 5144 '<input type="text" id="popular_question_2" name="popular_question_2" value="%s" placeholder="%s" class="regular-text" />',
4931 5145 esc_attr($popular_question_2),
4932 - esc_attr__('Enter Popular Question 2', 'mxchat')
5146 + esc_attr__('Enter Quick Question 2', 'mxchat')
4933 5147 );
4934 5148
4935 5149 // Add a description for the field
4936 - echo '<p class="description">' . esc_html__('This will be the second popular question in the chatbot.', 'mxchat') . '</p>';
5150 + echo '<p class="description">' . esc_html__('This will be the second Quick Question in the chatbot.', 'mxchat') . '</p>';
4937 5151 }
4938 5152
4939 5153
4940 5154 public function mxchat_popular_question_3_callback() {
@@ -4947,13 +5161,13 @@
4947 5161 // Render the input field
4948 5162 printf(
4949 5163 '<input type="text" id="popular_question_3" name="popular_question_3" value="%s" placeholder="%s" class="regular-text" />',
4950 5164 esc_attr($popular_question_3),
4951 - esc_attr(__('Enter Popular Question 3', 'mxchat'))
5165 + esc_attr(__('Enter Quick Question 3', 'mxchat'))
4952 5166 );
4953 5167
4954 5168 // Add a description for the field
4955 - echo '<p class="description">' . esc_html__('This will be the third popular question in the chatbot.', 'mxchat') . '</p>';
5169 + echo '<p class="description">' . esc_html__('This will be the third Quick Question in the chatbot.', 'mxchat') . '</p>';
4956 5170 }
4957 5171
4958 5172 public function mxchat_additional_popular_questions_callback() {
4959 5173 $options = get_option('mxchat_options', []);
@@ -4974,9 +5188,9 @@
4974 5188 <button type="button" class="button mxchat-remove-question"
4975 5189 aria-label="%s">%s</button>
4976 5190 </div>',
4977 5191 esc_attr($question),
4978 - esc_attr(sprintf(__('Enter Additional Popular Question %d', 'mxchat'), $index + 4)),
5192 + esc_attr(sprintf(__('Enter Additional Quick Question %d', 'mxchat'), $index + 4)),
4979 5193 $index,
4980 5194 esc_attr(__('Remove question', 'mxchat')),
4981 5195 esc_html__('Remove', 'mxchat')
4982 5196 );
@@ -4991,9 +5205,9 @@
4991 5205 data-question-index="0" />
4992 5206 <button type="button" class="button mxchat-remove-question"
4993 5207 aria-label="%s">%s</button>
4994 5208 </div>',
4995 - esc_attr(__('Enter Additional Popular Question 4', 'mxchat')),
5209 + esc_attr(__('Enter Additional Quick Question 4', 'mxchat')),
4996 5210 esc_attr(__('Remove question', 'mxchat')),
4997 5211 esc_html__('Remove', 'mxchat')
4998 5212 );
4999 5213 }
@@ -5002,9 +5216,9 @@
5002 5216 '<button type="button" class="button mxchat-add-question" aria-label="%s">%s</button>',
5003 5217 esc_attr(__('Add question', 'mxchat')),
5004 5218 esc_html__('Add Question', 'mxchat')
5005 5219 );
5006 - echo '<p class="description">' . esc_html__('Add as many popular questions as you need.', 'mxchat') . '</p>';
5220 + echo '<p class="description">' . esc_html__('Add as many Quick Questions as you need.', 'mxchat') . '</p>';
5007 5221 echo '</div>';
5008 5222 }
5009 5223
5010 5224 public function mxchat_brave_api_key_callback() {
@@ -5136,9 +5350,78 @@
5136 5350 echo '</div>';
5137 5351 echo '<p class="description">' . esc_html__('Enable to display the chat toolbar, adding two icons below the chatbot input field for uploading PDF and Word documents (default is hidden).', 'mxchat') . '</p>';
5138 5352 }
5139 5353
5354 +/**
5355 + * Callback for PDF upload button toggle setting
5356 + */
5357 +public function mxchat_show_pdf_upload_button_callback() {
5358 + // Get toggle value with fallback
5359 + $show_pdf_button = isset($this->options['show_pdf_upload_button']) ? $this->options['show_pdf_upload_button'] : 'on';
5360 + $checked = ($show_pdf_button === 'on') ? 'checked' : '';
5361 + // Check if the plugin is activated (paid feature)
5362 + $disabled = $this->is_activated ? '' : 'disabled';
5363 + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
5364 +
5365 + echo '<div class="' . esc_attr($class) . '">';
5366 + // Output the toggle switch
5367 + echo '<label class="toggle-switch">';
5368 + echo sprintf(
5369 + '<input type="checkbox" id="show_pdf_upload_button" name="show_pdf_upload_button" value="on" %s %s />',
5370 + esc_attr($checked),
5371 + esc_attr($disabled)
5372 + );
5373 + echo '<span class="slider"></span>';
5374 + echo '</label>';
5375 +
5376 + // Pro feature overlay if needed
5377 + if (!$this->is_activated) {
5378 + echo '<div class="pro-feature-overlay">';
5379 + echo '<a href="https://mxchat.ai/" target="_blank">';
5380 + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />';
5381 + echo '</a>';
5382 + echo '</div>';
5383 + }
5384 +
5385 + echo '</div>';
5386 + echo '<p class="description">' . esc_html__('Enable to show the PDF upload button in the chatbot toolbar. Disable to hide it.', 'mxchat') . '</p>';
5387 +}
5140 5388
5389 +/**
5390 + * Callback for Word upload button toggle setting
5391 + */
5392 +public function mxchat_show_word_upload_button_callback() {
5393 + // Get toggle value with fallback
5394 + $show_word_button = isset($this->options['show_word_upload_button']) ? $this->options['show_word_upload_button'] : 'on';
5395 + $checked = ($show_word_button === 'on') ? 'checked' : '';
5396 + // Check if the plugin is activated (paid feature)
5397 + $disabled = $this->is_activated ? '' : 'disabled';
5398 + $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
5399 +
5400 + echo '<div class="' . esc_attr($class) . '">';
5401 + // Output the toggle switch
5402 + echo '<label class="toggle-switch">';
5403 + echo sprintf(
5404 + '<input type="checkbox" id="show_word_upload_button" name="show_word_upload_button" value="on" %s %s />',
5405 + esc_attr($checked),
5406 + esc_attr($disabled)
5407 + );
5408 + echo '<span class="slider"></span>';
5409 + echo '</label>';
5410 +
5411 + // Pro feature overlay if needed
5412 + if (!$this->is_activated) {
5413 + echo '<div class="pro-feature-overlay">';
5414 + echo '<a href="https://mxchat.ai/" target="_blank">';
5415 + echo '<img src="' . esc_url(plugin_dir_url(__FILE__) . '../images/pro-only-dark.png') . '" alt="' . esc_attr__('Pro Only', 'mxchat') . '" />';
5416 + echo '</a>';
5417 + echo '</div>';
5418 + }
5419 +
5420 + echo '</div>';
5421 + echo '<p class="description">' . esc_html__('Enable to show the Word document upload button in the chatbot toolbar. Disable to hide it.', 'mxchat') . '</p>';
5422 +}
5423 +
5141 5424 public function mxchat_pdf_intent_trigger_text_callback() {
5142 5425 $disabled = $this->is_activated ? '' : 'disabled';
5143 5426 $class = $this->is_activated ? 'pro-feature-wrapper active' : 'pro-feature-wrapper inactive';
5144 5427 $default_text = __("Please provide the URL to the PDF you'd like to discuss.", 'mxchat');
@@ -5374,9 +5657,9 @@
5374 5657 echo sprintf(
5375 5658 '<input type="range"
5376 5659 id="similarity_threshold"
5377 5660 name="similarity_threshold"
5378 - min="70"
5661 + min="20"
5379 5662 max="85"
5380 5663 step="1"
5381 5664 value="%s"
5382 5665 class="range-slider" />',
@@ -5388,9 +5671,9 @@
5388 5671 );
5389 5672 echo '</div>';
5390 5673
5391 5674 echo '<p class="description">';
5392 - echo esc_html__('Set the similarity threshold (recommended: 75) to balance accuracy; too high might limit your bot\'s ability to find relevant knowledge.', 'mxchat');
5675 + echo esc_html__('Set the similarity threshold (recommended: 75) to balance accuracy; too high might limit your bot\'s ability to find relevant knowledge. If your bot is not matching content, move to lowest setting to test.', 'mxchat');
5393 5676 echo '</p>';
5394 5677 }
5395 5678
5396 5679
@@ -5440,9 +5723,9 @@
5440 5723 public function mxchat_enqueue_admin_assets() {
5441 5724 wp_enqueue_style('wp-color-picker');
5442 5725
5443 5726 // Get the plugin version or file modification time for cache busting
5444 - $plugin_version = '2.0.3'; // Replace this with your plugin's version
5727 + $plugin_version = '2.0.7'; // Replace this with your plugin's version
5445 5728
5446 5729 // File paths
5447 5730 $color_picker_js_path = plugin_dir_path(__FILE__) . '../js/my-color-picker.js';
5448 5731 $embedding_check_js_path = plugin_dir_path(__FILE__) . '../js/embedding-check.js';
@@ -5448,10 +5731,12 @@
5448 5731 $embedding_check_js_path = plugin_dir_path(__FILE__) . '../js/embedding-check.js';
5449 5732 $admin_css_path = plugin_dir_path(__FILE__) . '../css/admin-style.css';
5450 5733 $knowledge_css_path = plugin_dir_path(__FILE__) . '../css/knowledge-style.css';
5451 5734 $intent_css_path = plugin_dir_path(__FILE__) . '../css/intent-style.css';
5735 + $transcripts_css_path = plugin_dir_path(__FILE__) . '../css/chat-transcripts.css';
5452 5736 $transcripts_js_path = plugin_dir_path(__FILE__) . '../js/mxchat_transcripts.js';
5453 5737
5738 +
5454 5739 // Check if files exist and get modification times
5455 5740 $color_picker_version = file_exists($color_picker_js_path) ? filemtime($color_picker_js_path) : $plugin_version;
5456 5741 $embedding_check_version = file_exists($embedding_check_js_path) ? filemtime($embedding_check_js_path) : $plugin_version;
5457 5742 $admin_css_version = file_exists($admin_css_path) ? filemtime($admin_css_path) : $plugin_version;
@@ -5456,10 +5741,12 @@
5456 5741 $embedding_check_version = file_exists($embedding_check_js_path) ? filemtime($embedding_check_js_path) : $plugin_version;
5457 5742 $admin_css_version = file_exists($admin_css_path) ? filemtime($admin_css_path) : $plugin_version;
5458 5743 $knowledge_css_version = file_exists($knowledge_css_path) ? filemtime($knowledge_css_path) : $plugin_version;
5459 5744 $intent_css_version = file_exists($intent_css_path) ? filemtime($intent_css_path) : $plugin_version;
5745 + $transcripts_css_version = file_exists($transcripts_css_path) ? filemtime($transcripts_css_path) : $plugin_version;
5460 5746 $transcripts_js_version = file_exists($transcripts_js_path) ? filemtime($transcripts_js_path) : $plugin_version;
5461 5747
5748 +
5462 5749 // Enqueue scripts and styles with corrected paths
5463 5750 wp_enqueue_script(
5464 5751 'mxchat-color-picker',
5465 5752 plugin_dir_url(__FILE__) . '../js/my-color-picker.js',
@@ -5476,16 +5763,8 @@
5476 5763 true
5477 5764 );
5478 5765
5479 5766 wp_enqueue_script(
5480 - 'mxchat-transcripts-js',
5481 - plugin_dir_url(__FILE__) . '../js/mxchat_transcripts.js',
5482 - array('jquery'),
5483 - $transcripts_js_version,
5484 - true
5485 - );
5486 -
5487 - wp_enqueue_script(
5488 5767 'mxchat-admin-js',
5489 5768 plugin_dir_url(__FILE__) . '../js/mxchat-admin.js',
5490 5769 array('jquery'),
5491 5770 $plugin_version,
@@ -5496,8 +5775,9 @@
5496 5775 'ajax_url' => admin_url('admin-ajax.php'),
5497 5776 'license_nonce' => wp_create_nonce('mxchat_activate_license_nonce'),
5498 5777 'inline_edit_nonce' => wp_create_nonce('mxchat_save_inline_nonce'),
5499 5778 'setting_nonce' => wp_create_nonce('mxchat_save_setting_nonce'),
5779 + 'export_nonce' => wp_create_nonce('mxchat_export_transcripts'),
5500 5780 ));
5501 5781
5502 5782 // Enqueue the admin CSS
5503 5783 wp_enqueue_style(
@@ -5505,9 +5785,26 @@
5505 5785 plugin_dir_url(__FILE__) . '../css/admin-style.css',
5506 5786 array(),
5507 5787 $admin_css_version
5508 5788 );
5509 -
5789 +
5790 + if (isset($_GET['page']) && $_GET['page'] === 'mxchat-transcripts') {
5791 + wp_enqueue_style(
5792 + 'mxchat-chat-transcripts-css',
5793 + plugin_dir_url(__FILE__) . '../css/chat-transcripts.css',
5794 + array(),
5795 + $transcripts_css_version
5796 + );
5797 +
5798 + wp_enqueue_script(
5799 + 'mxchat-transcripts-js',
5800 + plugin_dir_url(__FILE__) . '../js/mxchat_transcripts.js',
5801 + array('jquery'),
5802 + $transcripts_js_version,
5803 + true
5804 + );
5805 + }
5806 +
5510 5807 wp_enqueue_style(
5511 5808 'mxchat-knowledge-css',
5512 5809 plugin_dir_url(__FILE__) . '../css/knowledge-style.css',
5513 5810 array(),
@@ -5557,8 +5854,10 @@
5557 5854 'live_agent_bot_token' => $this->options['live_agent_bot_token'] ?? '',
5558 5855 'live_agent_message_bg_color' => $this->options['live_agent_message_bg_color'] ?? '#ffffff',
5559 5856 'live_agent_message_font_color' => $this->options['live_agent_message_font_color'] ?? '#333333',
5560 5857 'chat_toolbar_toggle' => $this->options['chat_toolbar_toggle'] ?? 'off',
5858 + 'show_pdf_upload_button' => $this->options['show_pdf_upload_button'] ?? 'on', // Add this line
5859 + 'show_word_upload_button' => $this->options['show_word_upload_button'] ?? 'on', // Add this line
5561 5860 'mode_indicator_bg_color' => $this->options['mode_indicator_bg_color'] ?? '#767676',
5562 5861 'mode_indicator_font_color' => $this->options['mode_indicator_font_color'] ?? '#ffffff',
5563 5862 'toolbar_icon_color' => $this->options['toolbar_icon_color'] ?? '#212121',
5564 5863 ));
@@ -5573,9 +5872,9 @@
5573 5872 }
5574 5873
5575 5874 if (isset($input['similarity_threshold'])) {
5576 5875 $new_input['similarity_threshold'] = absint($input['similarity_threshold']); // Ensure it's an integer
5577 - $new_input['similarity_threshold'] = min(max($new_input['similarity_threshold'], 70), 85); // Enforce range
5876 + $new_input['similarity_threshold'] = min(max($new_input['similarity_threshold'], 20), 85); // Enforce range
5578 5877 }
5579 5878
5580 5879 if (isset($input['xai_api_key'])) {
5581 5880 $new_input['xai_api_key'] = sanitize_text_field($input['xai_api_key']);
@@ -5679,8 +5978,25 @@
5679 5978
5680 5979 if (isset($input['pre_chat_message'])) {
5681 5980 $new_input['pre_chat_message'] = sanitize_textarea_field($input['pre_chat_message']);
5682 5981 }
5982 +
5983 + if (isset($input['voyage_api_key'])) {
5984 + $new_input['voyage_api_key'] = sanitize_text_field($input['voyage_api_key']);
5985 + }
5986 +
5987 + // Add to your sanitize function
5988 + if (isset($input['embedding_model'])) {
5989 + $allowed_models = array(
5990 + 'text-embedding-ada-002',
5991 + 'text-embedding-3-small',
5992 + 'text-embedding-3-large',
5993 + 'voyage-3-large'
5994 + );
5995 + if (in_array($input['embedding_model'], $allowed_models)) {
5996 + $new_input['embedding_model'] = sanitize_text_field($input['embedding_model']);
5997 + }
5998 + }
5683 5999
5684 6000 if (isset($input['model'])) {
5685 6001 $allowed_models = array(
5686 6002 'grok-beta',
@@ -5685,8 +6001,9 @@
5685 6001 $allowed_models = array(
5686 6002 'grok-beta',
5687 6003 'grok-2',
5688 6004 'deepseek-chat',
6005 + 'claude-3-7-sonnet-20250219',
5689 6006 'claude-3-5-sonnet-20241022',
5690 6007 'claude-3-opus-20240229',
5691 6008 'claude-3-sonnet-20240229',
5692 6009 'claude-3-haiku-20240307',
@@ -5854,8 +6171,22 @@
5854 6171 }
5855 6172
5856 6173 if (isset($input['chat_toolbar_toggle'])) {
5857 6174 $new_input['chat_toolbar_toggle'] = $input['chat_toolbar_toggle'] === 'on' ? 'on' : 'off';
6175 + }
6176 +
6177 + // Sanitize PDF upload button toggle
6178 + if (isset($input['show_pdf_upload_button'])) {
6179 + $new_input['show_pdf_upload_button'] = $input['show_pdf_upload_button'] === 'on' ? 'on' : 'off';
6180 + } else {
6181 + $new_input['show_pdf_upload_button'] = 'off'; // If checkbox is unchecked
6182 + }
6183 +
6184 + // Sanitize Word upload button toggle
6185 + if (isset($input['show_word_upload_button'])) {
6186 + $new_input['show_word_upload_button'] = $input['show_word_upload_button'] === 'on' ? 'on' : 'off';
6187 + } else {
6188 + $new_input['show_word_upload_button'] = 'off'; // If checkbox is unchecked
5858 6189 }
5859 6190
5860 6191 if (isset($input['pdf_intent_trigger_text'])) {
5861 6192 $new_input['pdf_intent_trigger_text'] = sanitize_text_field($input['pdf_intent_trigger_text']);