Files
LexAI/docs/HANDOFF.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

7.4 KiB

Handoff — LexAI

Current state

  • Outcome: Phase 1 complete (7 workitems, 2026-03-06). Codebase reviewed 2026-07-13 (RECOMMENDATIONS.md). Operating-system docs + agent roster aligned to the template 2026-07-15.
  • Delivered: working MV3 extension — selection detection (textarea/input/contenteditable), floating toolbar, background LLM proxy with OpenAI/Anthropic/Groq/OpenRouter, Options page, result modal with Replace/Copy. Build ~166 KB.
  • Verified (Phase 1): npm run build clean. Note: unit tests currently exercise the storage mock, not the real handlers; e2e has [EXTENSION_ID] placeholders and won't pass as-is.
  • Verified (2026-07-15 finalize/build): npm run typecheck clean, npm test -- --run 46/46 passing (actions, messaging, crypto, providers), npm run build clean → .output/chrome-mv3/ (265.82 kB) ready for load-unpacked testing. Recent refactor series (crypto consolidation, provider adapter table, context-menu registry, dev-gated debug logs) all pass gates; real-page Replace verification still pending on the user's load-unpacked check.
  • Fix (2026-07-15): OpenAI adapter now sends max_completion_tokens instead of the legacy max_tokens (newer OpenAI models reject it) and omits temperature for reasoning models (o*/gpt-5*, which only accept the default). Groq/OpenRouter unchanged (they still expect max_tokens). Pinned tests updated + new reasoning-model test; typecheck/47 tests/build all green; rebuilt .output/chrome-mv3/.
  • Feature (2026-07-15): Options form reordered to Provider → API Key → Model (model list is fetched with the key). New prompt action ("Make Prompt", prompt-engineer): added to ACTIONS/labels (context menus follow automatically), prompt-engineer system prompt in getSystemPrompt with a prompt-directed style modifier, toolbar button (🪄 Prompt) in content.ts, popup button. Tests updated (registry count now derived; new getSystemPrompt cases); typecheck/48 tests/build green.
  • Feature (2026-07-15, Prompt Builder): dedicated popup section for the prompt action with its own parameters — Prompt Style (Auto/Instructional/Role-play/Step-by-step/Few-shot/Structured), Persona (presets + Custom free text + None), Output Format (Auto/Plain/Markdown/Bulleted/Numbered/JSON/Table). Constants in src/lib/actions.ts, PromptParams added to AnalyzePayload (both message shapes still supported), composed into the system prompt by promptParamModifiers in providers.ts (prompt action only; 'Auto' = no-op). Params persist in chrome.storage.local. Toolbar 🪄 Prompt keeps Auto defaults. typecheck/49 tests/build green.
  • Feature (2026-07-15, popup tabs + model picker): popup restructured into two tabs — "✍ Writing" (style + fix/rephrase/shorten/expand) and "🪄 Prompt Builder" (prompt params + Make Prompt). Prompt Builder gained a Model picker: fetched via LIST_MODELS on first tab open, '' = configured default; selection sent as new optional model override on AnalyzePayload (both message shapes), applied in background's handleAnalyzeText. Tab + model persist in storage. typecheck/49 tests/build green.
  • Tweak (2026-07-15): model picker's "Default (model)" label → plain "Default" (badge already shows the model). Toolbar/context-menu prompt requests now inherit the saved Prompt Builder settings: background's handleAnalyzeText loads promptStyle/promptPersona/customPersona/promptFormat/promptModel from storage when the payload has no promptParams (popup still sends explicit ones); persona resolution shared via resolvePromptPersona in actions.ts. typecheck/49 tests/build green.
  • Feature (2026-07-15, in-page Prompt Builder dialog): toolbar 🪄 Prompt and context-menu "Make Prompt" now open an on-page dialog (content.ts showPromptBuilderDialog) with the popup's parameters (Style/Persona+custom/Format/Model); selections persist to the shared storage keys, then the request runs without explicit params (background applies saved). Context menu: prompt is now a single item (no style children — registry excludes it; tests updated). LIST_MODELS resolves provider from storage when omitted. Toolbar re-clamps position using its real width so the last buttons stay on-screen. typecheck/49 tests/build green. Needs a real-page check (dialog + replace are DOM-timing-sensitive).
  • Fix (2026-07-15, prompt UX chain): Make Prompt no longer closes the dialog silently — the dialog becomes a "⟳ Building your prompt…" spinner and runAction closes it (closePromptBuilder) at every completion path (success, error, invalidated-context). Prompt result modal is prompt-specific: "🪄 Engineered Prompt" title, and the writing-style selector row is replaced by "✎ Edit Parameters" (reopens the builder dialog) + Regenerate (re-runs with saved builder params). typecheck/49 tests/build green.
  • Security/perf pass (2026-07-15, goal-driven audit): reviewed key safety, user-text privacy, and content-script performance; fixed:
    • src/lib/crypto.ts — new migratePlaintextApiKey(): background auto-encrypts a legacy plaintext apiKey on worker start and removes the plaintext (write-and-await key material before delete; verify-decrypt before dropping plaintext when an encrypted key already exists; re-check for a concurrent Options save before writing). Read-path plaintext fallback in resolveApiKey retained per invariant.
    • entrypoints/background.ts — calls the migration on startup; sender.id !== chrome.runtime.id guard on onMessage (defense-in-depth; internal senders unaffected).
    • entrypoints/content.ts — fixed unbounded document-listener leak: showToolbar added click/scroll listeners per selection and never removed them; now unregistered in hideToolbar (also closes an orphaned More-menu). Error toast gained data-lexai; mouseup threshold now uses MIN_SELECTION_LENGTH (was hardcoded <= 10, which ate exactly-10-char selections); same sender guard on its listener.
    • src/lib/providers.tscallProvider guards res.json() so non-JSON gateway errors (HTML 502) surface as "<Provider> error: HTTP <status>" instead of a raw SyntaxError.
    • Verified: typecheck clean, 54/54 tests (6 new: 4 migration, 1 non-JSON error, plus existing), build clean (280.3 kB). security-auditor reviewed the key-path diff: PASS; its two P3 hardening notes (await encKey persistence, concurrent-save re-check) were implemented and re-gated. User-text privacy audited clean: no persistence of analyzed text, debug logs dev-gated, key/text travel only to the chosen provider. Real-page load-unpacked check of toolbar/replace still recommended (DOM-timing paths untouched except listener cleanup).
  • Changed paths (this alignment): added docs/ (brief, architecture, decisions, tasks, evals, lessons, handoff, self-model, attacksurface), ported .claude/agents/* roster + .claude/skills/*, kept lexai-extension-dev, updated .claude/AGENTS.md. CLAUDE.md restructured to the operating-system format (all original LexAI rules preserved).
  • Open risks (ranked):
    1. <all_urls> host permission — privacy surface + CWS review blocker (TASKS #1).
    2. Key "encryption" is obfuscation (encKey co-located) — TASKS #2.
    3. Tests don't cover real code paths (TASKS #8) or DOM replace (TASKS #10).
  • Next smallest action: run the quick wins in order — T-03 (gate debug logs), then T-06/T-09/T-15/T-16 — each is small and independent. Do T-01/T-02 before any Chrome Web Store push.