# Architecture ## Extension Structure (Manifest V2) ThunderAI runs as a standard Thunderbird WebExtension with three main execution contexts: ``` Background Page → mzta-background.html / mzta-background.js Popup → popup/mzta-popup.html / popup/mzta-popup.js Options Page → options/mzta-options.html / options/mzta-options.js Feature Pages → pages/*/ Content Script → js/lib/diff.js (injected into chatgpt.com) Web Workers → js/workers/model-worker-*.js (one per API provider) ``` ## Data Flow: User Action → AI Response ``` User clicks popup or presses Ctrl+Alt+A ↓ popup/mzta-popup.js (renders prompt list, handles selection) ↓ (sendMessage to background) mzta-background.js (orchestrates everything) ↓ js/mzta-placeholders.js (resolves {%placeholder%} values from email data) ↓ js/mzta-prompts.js (builds final prompt string) ↓ ┌─────────────────────────────────────────┐ │ Based on connection_type: │ │ chatgpt_web → js/mzta-chatgpt.js │ (opens ChatGPT window) │ chatgpt_api → Web Worker (openai) │ │ ollama_api → Web Worker (ollama) │ │ google_gemini → Web Worker (gemini) │ │ anthropic → Web Worker (anthropic)│ │ openai_comp → Web Worker (comp) │ └─────────────────────────────────────────┘ ↓ Result returned to background ↓ js/mzta-compose-script.js (inserts text into Thunderbird compose window) ``` ## Key Modules | File | Role | |------|------| | `mzta-background.js` | Main orchestrator: listens for messages, coordinates all features | | `js/mzta-menus.js` | Context menu creation and management | | `js/mzta-prompts.js` | Prompt definitions (built-in) and custom prompt loading | | `js/mzta-placeholders.js` | Placeholder definitions and resolution logic | | `js/mzta-utils.js` | General utilities (email parsing, storage helpers, etc.) | | `js/mzta-utils-prompt.js` | Prompt-specific utilities (text truncation, lang injection) | | `js/mzta-compose-script.js` | Injects AI response into Thunderbird compose window | | `js/mzta-chatgpt.js` | ChatGPT Web integration (opens browser window, reads DOM) | | `js/mzta-special-commands.js` | Handles special prompt actions (add_tags, calendar, task) | | `js/mzta-spamreport.js` | Spam filter logic | | `js/mzta-i18n.js` | i18n helper (wraps `browser.i18n.getMessage`) | | `js/mzta-logger.js` | Debug logging (gated by `do_debug` pref) | | `js/mzta-store.js` | Storage abstraction helpers | | `js/mzta-working-status.js` | Visual status indicator during AI processing | | `js/mzta-addatags-exclusion-list.js` | Tag exclusion list management | | `js/mzta-placeholders-autocomplete.js` | Autocomplete for placeholders in prompt editor | ## API Modules (`js/api/`) Each file handles HTTP communication for one provider: | File | Provider | |------|----------| | `anthropic.js` | Claude (Anthropic) API | | `google_gemini.js` | Google Gemini API | | `ollama.js` | Ollama (self-hosted) | | `openai_comp.js` | OpenAI-compatible APIs | | `openai_comp_configs.js` | Pre-configured providers (DeepSeek, Grok, Mistral, OpenRouter, Perplexity) | | `openai_responses.js` | OpenAI Responses API | ## Web Workers (`js/workers/`) Each API provider has a dedicated Web Worker so API calls don't block the UI: - `model-worker-anthropic.js` - `model-worker-google_gemini.js` - `model-worker-ollama.js` - `model-worker-openai_comp.js` - `model-worker-openai_responses.js` Workers receive a message with the prompt and settings, make the API call, and post back the result. ## Feature Pages (`pages/`) Each subdirectory is a self-contained settings/UI page for a specific feature: | Directory | Feature | |-----------|---------| | `addtags/` | Auto-tagging configuration | | `customprompts/` | Custom prompt editor | | `customdataplaceholders/` | Custom placeholder editor | | `get-calendar-event/` | Calendar event extraction settings | | `get-task/` | Task creation settings | | `spamfilter/` | Spam filter settings | | `summarize/` | Email summarization settings | | `onboarding/` | First-run welcome page | | `_lib/` | Shared libraries used by pages | ## Storage All preferences are stored via `browser.storage.local`. The keys and default values are defined in `options/mzta-options-default.js` (`prefs_default` export). Custom prompts and custom placeholders are stored separately in storage under their own keys.