diff --git a/README.md b/README.md index 3853127..43a515b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ message meets a specified criterion. - **Advanced parameters** – tune generation settings like temperature, top‑p and more from the options page. - **Markdown conversion** – optionally convert HTML bodies to Markdown before sending them to the AI service. - **Debug logging** – optional colorized logs help troubleshoot interactions with the AI service. +- **Debug tab** – view the last request payload sent to the AI service. - **Light/Dark themes** – automatically match Thunderbird's appearance with optional manual override. - **Automatic rules** – create rules that tag, move, copy, forward, reply, delete, archive, mark read/unread or flag/unflag messages based on AI classification. Rules can optionally apply only to unread messages and can ignore messages outside a chosen age range. - **Rule ordering** – drag rules to prioritize them and optionally stop processing after a match. diff --git a/modules/AiClassifier.js b/modules/AiClassifier.js index b35cb2c..8313654 100644 --- a/modules/AiClassifier.js +++ b/modules/AiClassifier.js @@ -308,6 +308,11 @@ async function classifyText(text, criterion, cacheKey = null) { } const payload = buildPayload(text, criterion); + try { + await storage.local.set({ lastPayload: JSON.parse(payload) }); + } catch (e) { + aiLog('failed to save last payload', { level: 'warn' }, e); + } aiLog(`[AiClassifier] Sending classification request to ${gEndpoint}`, {debug: true}); aiLog(`[AiClassifier] Classification request payload:`, { debug: true }, payload); diff --git a/options/options.html b/options/options.html index 69158b1..d14ce99 100644 --- a/options/options.html +++ b/options/options.html @@ -47,6 +47,7 @@
  • Settings
  • Rules
  • Maintenance
  • + @@ -215,6 +216,11 @@ +
    + +
    @@ -273,6 +279,14 @@

    + + diff --git a/options/options.js b/options/options.js index ee2914a..ebd7497 100644 --- a/options/options.js +++ b/options/options.js @@ -19,7 +19,9 @@ document.addEventListener('DOMContentLoaded', async () => { 'tokenReduction', 'aiRules', 'aiCache', - 'theme' + 'theme', + 'showDebugTab', + 'lastPayload' ]); const tabButtons = document.querySelectorAll('#main-tabs li'); const tabs = document.querySelectorAll('.tab-content'); @@ -64,6 +66,10 @@ document.addEventListener('DOMContentLoaded', async () => { } await applyTheme(themeSelect.value); + const payloadDisplay = document.getElementById('payload-display'); + if (defaults.lastPayload) { + payloadDisplay.textContent = JSON.stringify(defaults.lastPayload, null, 2); + } themeSelect.addEventListener('change', async () => { markDirty(); await applyTheme(themeSelect.value); @@ -119,6 +125,16 @@ document.addEventListener('DOMContentLoaded', async () => { const tokenReductionToggle = document.getElementById('token-reduction'); tokenReductionToggle.checked = defaults.tokenReduction === true; + const debugTabToggle = document.getElementById('show-debug-tab'); + const debugTabBtn = document.getElementById('debug-tab-button'); + function updateDebugTab() { + const visible = debugTabToggle.checked; + debugTabBtn.classList.toggle('is-hidden', !visible); + } + debugTabToggle.checked = defaults.showDebugTab === true; + debugTabToggle.addEventListener('change', () => { updateDebugTab(); markDirty(); }); + updateDebugTab(); + const aiParams = Object.assign({}, DEFAULT_AI_PARAMS, defaults.aiParams || {}); for (const [key, val] of Object.entries(aiParams)) { @@ -797,8 +813,9 @@ document.addEventListener('DOMContentLoaded', async () => { const altTextImages = altTextToggle.checked; const collapseWhitespace = collapseWhitespaceToggle.checked; const tokenReduction = tokenReductionToggle.checked; + const showDebugTab = debugTabToggle.checked; const theme = themeSelect.value; - await storage.local.set({ endpoint, templateName, customTemplate: customTemplateText, customSystemPrompt, aiParams: aiParamsSave, debugLogging, htmlToMarkdown, stripUrlParams, altTextImages, collapseWhitespace, tokenReduction, aiRules: rules, theme }); + await storage.local.set({ endpoint, templateName, customTemplate: customTemplateText, customSystemPrompt, aiParams: aiParamsSave, debugLogging, htmlToMarkdown, stripUrlParams, altTextImages, collapseWhitespace, tokenReduction, aiRules: rules, theme, showDebugTab }); await applyTheme(theme); try { await AiClassifier.setConfig({ endpoint, templateName, customTemplate: customTemplateText, customSystemPrompt, aiParams: aiParamsSave, debugLogging });