Files
LexAI/docs/DECISIONS.md
john kevin asprec acea99d7ad
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 39s
feat: Implement Prompt Builder functionality in Popup and Options
- Added a new "Prompt Builder" tab in the Popup for generating AI prompts with customizable parameters.
- Introduced new state variables for managing prompt styles, personas, formats, and models.
- Enhanced the Options page to fetch and display models based on the provided API key.
- Updated the actions and types to include the new 'prompt' action and its associated parameters.
- Implemented migration logic for legacy plaintext API keys to encrypted storage.
- Updated the getSystemPrompt function to incorporate prompt parameters for better instruction generation.
- Added tests for the new functionality, including context menu entries and prompt generation logic.
2026-07-15 15:27:41 +08:00

5.6 KiB

Decisions — LexAI

Lightweight ADRs. One entry per material decision: what, why, what was rejected, when. Newest at top. Supersede rather than rewrite.

Log

D-2026-03-06-01 — BYO-LLM-key, no backend

  • Status: accepted
  • Context: Hosted writing assistants cost a subscription and route user text through a third party. Target users already hold LLM API keys.
  • Decision: No LexAI server. The background service worker calls the user's chosen provider (OpenAI/Anthropic/Groq/OpenRouter) directly with the user's key.
  • Alternatives considered: A thin proxy backend (rejected: adds cost, privacy surface, and an account system); on-device browser AI only (rejected: too limited across providers — noted as a Proofly reference pattern).
  • Consequences: Zero server cost and strong privacy story; shifts key handling and CORS entirely into the extension; no server-side rate limiting or abuse controls.
  • Verification: Manual — confirm no network calls leave the extension except to the selected provider endpoint.
  • Owner / date: Phase 1, 2026-03-06

D-2026-03-06-02 — Inline styles, no Tailwind

  • Status: accepted
  • Context: Content-script UI must not be broken by host-page CSS; WXT PostCSS/Tailwind integration was not wired.
  • Decision: Style all UI with inline style objects (Object.assign(el.style, …) / style={{…}}), using a dark Catppuccin-ish palette.
  • Alternatives considered: Tailwind (left in devDependencies but inactive); shadow DOM + stylesheet (deferred — see D-...-03).
  • Consequences: Reliable rendering on any host page; palette/button styles get duplicated across content/Options/Popup (refactor tracked in TASKS #5).
  • Verification: Visual check on multiple sites.
  • Owner / date: Phase 1, 2026-03-06

D-2026-03-06-03 — No shadow DOM; data-lexai guard instead

  • Status: accepted
  • Context: Injected toolbar/modal could collide with host-page styles or re-trigger LexAI's own handlers.
  • Decision: Inject directly into document.body; mark every LexAI node data-lexai="true" and skip events whose target is closest('[data-lexai="true"]'); use max z-index (2147483647).
  • Alternatives considered: Shadow DOM (rejected for now: added complexity; revisit if style isolation issues appear).
  • Consequences: Simple and working; weaker isolation than shadow DOM; highly customized editors (e.g. Google Docs) may not accept programmatic replace.
  • Verification: Manual across textarea/input/contenteditable sites.
  • Owner / date: Phase 1, 2026-03-06

D-2026-03-06-04 — Eager selection snapshot before async

  • Status: accepted
  • Context: Focus shifts to the toolbar and the live selection is gone by the time an async provider response returns.
  • Decision: Capture the active element + selection offsets eagerly (on mouseup and on button mousedown) and snapshot before any await; Replace uses the snapshot. Handle both textarea/input (selectionStart/End) and contenteditable/DOM (Range API).
  • Alternatives considered: Re-reading selection after the response (rejected: selection no longer exists).
  • Consequences: Replace works reliably; the pattern is fragile — editing content.ts must preserve snapshot-before-await. Zero automated coverage today (TASKS #10).
  • Owner / date: Phase 1, 2026-03-06

D-2026-03-06-05 — Dual ANALYZE_TEXT message shapes; return true listener

  • Status: accepted
  • Context: Content script/popup send { payload: {...} }; other call sites send flat { text, action, style }. Async responses need the message channel held open.
  • Decision: The handler accepts both shapes; the onMessage listener returns true. fix normalizes to grammar.
  • Consequences: Flexible but must be preserved in both forms; removing return true silently breaks all responses.
  • Owner / date: Phase 1, 2026-03-06

D-2026-xx-xx-06 — tweetnacl secretbox for the API key (obfuscation, not protection)

  • Status: accepted — flagged for revisit
  • Context: Storing the raw key in chrome.storage.local looked bad; added tweetnacl secretbox encryption (apiKeyEnc + encKey).
  • Decision: Prefer the encrypted path; keep plaintext apiKey as back-compat until a migration exists.
  • Known weakness: encKey is stored next to apiKeyEnc, so anyone who can read storage can decrypt. This is obfuscation, not protection (RECOMMENDATIONS #2).
  • Alternatives to consider: derive the key from chrome.storage.session / WebCrypto / a user passphrase; and be honest in the UI ("stored locally, obscured"). Tracked in TASKS #2.
  • Owner / date: post-Phase 1

D-2026-03-06-07 — Gitea CI + Chrome Web Store deploy

  • Status: accepted
  • Context: Project hosts CI on Gitea, not GitHub Actions.
  • Decision: .gitea/workflows/ci.yml (typecheck→test→build→zip to registry) and deploy-chrome.yml (on v*.*.* tag → CWS). Telegram notifications. Version must match in package.json and wxt.config.ts.
  • Known weakness: workflows git clone into /tmp and set http.sslVerify false (RECOMMENDATIONS #17). Revisit for speed/security.
  • Owner / date: Phase 1, 2026-03-06

Open / proposed

D-PROPOSED — Narrow host permissions from <all_urls>

  • Status: proposed (decide before serious Web Store push)
  • Context: Content script injects into every frame of every site, including banking/email/internal apps; also the #1 CWS review slowdown (RECOMMENDATIONS #1).
  • Options: activeTab + on-demand injection, or a user-configurable allowlist.
  • Verification: confirm actions still work after narrowing; measure review outcome.