diff --git a/background.js b/background.js index b5667e6..58a5de5 100644 --- a/background.js +++ b/background.js @@ -33,6 +33,7 @@ let userTheme = 'auto'; let currentTheme = 'light'; let detectSystemTheme; let errorPending = false; +let showDebugTab = false; const ERROR_NOTIFICATION_ID = 'sortana-error'; function normalizeRules(rules) { @@ -262,12 +263,16 @@ async function processMessage(id) { try { const full = await messenger.messages.getFull(id); let text = buildEmailText(full); + const originalText = text; if (tokenReduction && maxTokens > 0) { const limit = Math.floor(maxTokens * 0.9); if (text.length > limit) { text = text.slice(0, limit); } } + if (showDebugTab) { + await storage.local.set({ lastFullText: originalText, lastPromptText: text }); + } let hdr; let currentTags = []; let alreadyRead = false; @@ -425,7 +430,7 @@ async function clearCacheForMessages(idsInput) { } try { - const store = await storage.local.get(["endpoint", "templateName", "customTemplate", "customSystemPrompt", "aiParams", "debugLogging", "htmlToMarkdown", "stripUrlParams", "altTextImages", "collapseWhitespace", "tokenReduction", "aiRules", "theme", "errorPending"]); + const store = await storage.local.get(["endpoint", "templateName", "customTemplate", "customSystemPrompt", "aiParams", "debugLogging", "htmlToMarkdown", "stripUrlParams", "altTextImages", "collapseWhitespace", "tokenReduction", "aiRules", "theme", "errorPending", "showDebugTab"]); logger.setDebug(store.debugLogging); await AiClassifier.setConfig(store); userTheme = store.theme || 'auto'; @@ -440,6 +445,7 @@ async function clearCacheForMessages(idsInput) { maxTokens = parseInt(store.aiParams.max_tokens) || maxTokens; } errorPending = store.errorPending === true; + showDebugTab = store.showDebugTab === true; const savedStats = await storage.local.get('classifyStats'); if (savedStats.classifyStats && typeof savedStats.classifyStats === 'object') { Object.assign(timingStats, savedStats.classifyStats); @@ -494,6 +500,9 @@ async function clearCacheForMessages(idsInput) { tokenReduction = changes.tokenReduction.newValue === true; logger.aiLog("tokenReduction updated from storage change", { debug: true }, tokenReduction); } + if (changes.showDebugTab) { + showDebugTab = changes.showDebugTab.newValue === true; + } if (changes.errorPending) { errorPending = changes.errorPending.newValue === true; updateActionIcon(); diff --git a/options/options.html b/options/options.html index d14ce99..3618a20 100644 --- a/options/options.html +++ b/options/options.html @@ -31,6 +31,10 @@ .tag { --bulma-tag-h: 318; } + #diff-display { + white-space: pre-wrap; + font-family: monospace; + } @@ -286,9 +290,11 @@ Debug

+                
+ diff --git a/options/options.js b/options/options.js index ebd7497..3a09d37 100644 --- a/options/options.js +++ b/options/options.js @@ -21,7 +21,9 @@ document.addEventListener('DOMContentLoaded', async () => { 'aiCache', 'theme', 'showDebugTab', - 'lastPayload' + 'lastPayload', + 'lastFullText', + 'lastPromptText' ]); const tabButtons = document.querySelectorAll('#main-tabs li'); const tabs = document.querySelectorAll('.tab-content'); @@ -67,9 +69,17 @@ document.addEventListener('DOMContentLoaded', async () => { await applyTheme(themeSelect.value); const payloadDisplay = document.getElementById('payload-display'); + const diffDisplay = document.getElementById('diff-display'); if (defaults.lastPayload) { payloadDisplay.textContent = JSON.stringify(defaults.lastPayload, null, 2); } + if (defaults.lastFullText && defaults.lastPromptText && diff_match_patch) { + const dmp = new diff_match_patch(); + dmp.Diff_EditCost = 4; + const diffs = dmp.diff_main(defaults.lastFullText, defaults.lastPromptText); + dmp.diff_cleanupEfficiency(diffs); + diffDisplay.innerHTML = dmp.diff_prettyHtml(diffs); + } themeSelect.addEventListener('change', async () => { markDirty(); await applyTheme(themeSelect.value);