| @@ -9772,8 +9772,36 @@ | ||
| 9772 | 9772 | isset($this->options['live_agent_bot_token']) ? esc_attr($this->options['live_agent_bot_token']) : '' |
| 9773 | 9773 | ); |
| 9774 | 9774 | echo '<button type="button" id="toggleBotTokenVisibility">' . esc_html__('Show', 'mxchat') . '</button>'; |
| 9775 | 9775 | echo '<p class="description">' . esc_html__('Your Slack Bot OAuth Token (starts with xoxb-). Keep this secure.', 'mxchat') . '</p>'; |
| 9776 | + | |
| 9777 | + // Surface the last live-agent post Slack refused (plan 2a4ab7). Slack | |
| 9778 | + // answers a refused post with HTTP 200, so before this existed a deleted | |
| 9779 | + // or archived channel or a revoked token failed with no trace anywhere. | |
| 9780 | + // The next successful post clears it. | |
| 9781 | + $slack_error = get_option('mxchat_slack_last_error'); | |
| 9782 | + if (is_array($slack_error) && !empty($slack_error['error'])) { | |
| 9783 | + $slack_error_time = !empty($slack_error['time']) | |
| 9784 | + ? wp_date(get_option('date_format') . ' ' . get_option('time_format'), (int) $slack_error['time']) | |
| 9785 | + : __('unknown time', 'mxchat'); | |
| 9786 | + if (!empty($slack_error['channel'])) { | |
| 9787 | + $slack_error_text = sprintf( | |
| 9788 | + /* translators: 1: Slack API error code, 2: Slack channel ID, 3: local date and time of the failure */ | |
| 9789 | + __('Slack said "%1$s" for channel %2$s (%3$s). The visitor was told the message could not be delivered. Check that the channel still exists and is not archived, that the bot is in it, and that the token above is still valid.', 'mxchat'), | |
| 9790 | + $slack_error['error'], | |
| 9791 | + $slack_error['channel'], | |
| 9792 | + $slack_error_time | |
| 9793 | + ); | |
| 9794 | + } else { | |
| 9795 | + $slack_error_text = sprintf( | |
| 9796 | + /* translators: 1: Slack API error code, 2: local date and time of the failure */ | |
| 9797 | + __('Slack said "%1$s" (%2$s). The visitor was told the message could not be delivered. Check that the token above is still valid.', 'mxchat'), | |
| 9798 | + $slack_error['error'], | |
| 9799 | + $slack_error_time | |
| 9800 | + ); | |
| 9801 | + } | |
| 9802 | + echo '<p class="description"><strong>' . esc_html__('⚠ Last delivery error', 'mxchat') . '</strong> — ' . esc_html($slack_error_text) . '</p>'; | |
| 9803 | + } | |
| 9776 | 9804 | } |
| 9777 | 9805 | |
| 9778 | 9806 | public function mxchat_live_agent_user_ids_callback() { |
| 9779 | 9807 | $user_ids = isset($this->options['live_agent_user_ids']) |
| @@ -10210,8 +10238,58 @@ | ||
| 10210 | 10238 | wp_enqueue_style('mxchat-content-selector-css', $plugin_url . 'css/content-selector.css', array(), $version); |
| 10211 | 10239 | wp_enqueue_script('mxchat-content-selector-js', $plugin_url . 'js/content-selector.js', array('jquery'), $version, true); |
| 10212 | 10240 | // Add the knowledge processing script (common script needed for WordPress dismiss functionality) |
| 10213 | 10241 | wp_enqueue_script('mxchat-knowledge-processing', $plugin_url . 'js/knowledge-processing.js', array('jquery', 'common'), $version, true); |
| 10242 | + // "Re-import affected entries" card (plan 89739b) | |
| 10243 | + wp_enqueue_script('mxchat-kb-reimport', $plugin_url . 'js/knowledge-reimport.js', array(), $version, true); | |
| 10244 | + wp_localize_script('mxchat-kb-reimport', 'mxchatKbReimport', array( | |
| 10245 | + 'ajaxUrl' => admin_url('admin-ajax.php'), | |
| 10246 | + 'requestFailed' => __('The request did not go through. Nothing is lost: try again.', 'mxchat'), | |
| 10247 | + /* translators: %s: number of entries checked so far */ | |
| 10248 | + 'checking' => __('Checking, %s entries so far', 'mxchat'), | |
| 10249 | + /* translators: 1: entries rewritten so far, 2: entries to rewrite */ | |
| 10250 | + 'rewriting' => __('Rewriting, %1$s of %2$s', 'mxchat'), | |
| 10251 | + /* translators: %s: number of entries */ | |
| 10252 | + 'countRepair' => __('%s to rewrite', 'mxchat'), | |
| 10253 | + /* translators: %s: number of entries */ | |
| 10254 | + 'countCorrect' => __('%s already correct', 'mxchat'), | |
| 10255 | + /* translators: %s: number of entries */ | |
| 10256 | + 'countChanged' => __('%s left alone', 'mxchat'), | |
| 10257 | + /* translators: %s: number of entries */ | |
| 10258 | + 'countSkipped' => __('%s skipped', 'mxchat'), | |
| 10259 | + /* translators: %s: number of entries */ | |
| 10260 | + 'countRewritten' => __('%s rewritten', 'mxchat'), | |
| 10261 | + /* translators: %s: number of entries */ | |
| 10262 | + 'countFailed' => __('%s not rewritten', 'mxchat'), | |
| 10263 | + /* translators: %s: number of further entries not shown in the list */ | |
| 10264 | + 'andMore' => __('and %s more', 'mxchat'), | |
| 10265 | + /* translators: %s: number of entries */ | |
| 10266 | + 'othersTitle' => __('Left alone or skipped (%s)', 'mxchat'), | |
| 10267 | + 'leftAlone' => __('Left alone', 'mxchat'), | |
| 10268 | + 'skipped' => __('Skipped', 'mxchat'), | |
| 10269 | + 'rewritten' => __('Rewritten', 'mxchat'), | |
| 10270 | + 'notRewritten' => __('Not rewritten', 'mxchat'), | |
| 10271 | + 'noLongerNeeded' => __('No longer needed', 'mxchat'), | |
| 10272 | + /* translators: %s: number of entries */ | |
| 10273 | + 'apply' => __('Rewrite %s entries', 'mxchat'), | |
| 10274 | + /* translators: %s: number of entries still to rewrite */ | |
| 10275 | + 'resume' => __('Continue, %s left', 'mxchat'), | |
| 10276 | + /* translators: %s: number of entries */ | |
| 10277 | + 'done' => __('%s entries rewritten and embedded again.', 'mxchat'), | |
| 10278 | + /* translators: 1: entries rewritten, 2: entries that could not be rewritten */ | |
| 10279 | + 'doneWithFailures' => __('%1$s entries rewritten. %2$s could not be rewritten and were left as they were.', 'mxchat'), | |
| 10280 | + 'nothingToDo' => __('Every entry checked is already correct. Nothing to rewrite.', 'mxchat'), | |
| 10281 | + /* translators: %s: the reason the check stopped */ | |
| 10282 | + 'scanStopped' => __('The check stopped early: %s', 'mxchat'), | |
| 10283 | + 'reasons' => array( | |
| 10284 | + 'entities' => __('HTML character codes', 'mxchat'), | |
| 10285 | + 'currency' => __('Currency signs', 'mxchat'), | |
| 10286 | + 'combining marks' => __('Accents and marks', 'mxchat'), | |
| 10287 | + 'symbols' => __('Symbols', 'mxchat'), | |
| 10288 | + 'joiners' => __('Joined letters', 'mxchat'), | |
| 10289 | + 'RTL' => __('Right-to-left order', 'mxchat'), | |
| 10290 | + ), | |
| 10291 | + )); | |
| 10214 | 10292 | // Per-entry "View indexed content" inspector (plan-d8cb4b) reuses the |
| 10215 | 10293 | // Testing tab's match-card / chunk-detail components, which are scoped |
| 10216 | 10294 | // under .mxch-testing-results. Load that stylesheet here so the inspector |
| 10217 | 10295 | // modal renders identically to the Testing tab. |
| @@ -11539,8 +11617,14 @@ | ||
| 11539 | 11617 | $error_messages[] = 'Failed to delete from WordPress database'; |
| 11540 | 11618 | } |
| 11541 | 11619 | } |
| 11542 | 11620 | |
| 11621 | + // Every media entry in scope is gone: their auto-sync signatures go too, | |
| 11622 | + // or each file is skipped as "unchanged" on its next save (b0ae54). | |
| 11623 | + if ($success && (empty($content_type_filter) || $content_type_filter === 'attachment')) { | |
| 11624 | + MxChat_Utils::forget_all_attachment_signatures($bot_id); | |
| 11625 | + } | |
| 11626 | + | |
| 11543 | 11627 | // Redirect back with a success message and bot_id |
| 11544 | 11628 | $redirect_url = add_query_arg(array( |
| 11545 | 11629 | 'page' => 'mxchat-prompts', |
| 11546 | 11630 | 'bot_id' => $bot_id, |
| @@ -11694,8 +11778,17 @@ | ||
| 11694 | 11778 | //error_log('[MXCHAT-EMBED] Starting embedding generation. Text length: ' . strlen($text) . ' bytes'); |
| 11695 | 11779 | //error_log('[MXCHAT-EMBED] Text preview: ' . substr($text, 0, 100) . '...'); |
| 11696 | 11780 | |
| 11697 | 11781 | $options = get_option('mxchat_options'); |
| 11782 | + | |
| 11783 | + // Custom Provider embeddings first, as the chat and the knowledge | |
| 11784 | + // importers do (plan 418afd): a phrase embedded with another model | |
| 11785 | + // can never match a question embedded with the custom one. Returns | |
| 11786 | + // the vector, or the error string this function returns on failure. | |
| 11787 | + if (is_array($options) && isset($options['custom_provider_for_embeddings']) && $options['custom_provider_for_embeddings'] === 'on') { | |
| 11788 | + return MxChat_Utils::generate_embedding_custom($text, $options); | |
| 11789 | + } | |
| 11790 | + | |
| 11698 | 11791 | $selected_model = $options['embedding_model'] ?? 'text-embedding-ada-002'; |
| 11699 | 11792 | //error_log('[MXCHAT-EMBED] Selected embedding model: ' . $selected_model); |
| 11700 | 11793 | |
| 11701 | 11794 | // Determine provider and endpoint |