feat: Implement Prompt Builder functionality in Popup and Options
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 39s

- 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.
This commit is contained in:
john kevin asprec
2026-07-15 15:27:41 +08:00
parent 0fef9848cb
commit acea99d7ad
40 changed files with 1971 additions and 177 deletions

27
docs/HANDOFF.md Normal file
View File

@@ -0,0 +1,27 @@
# 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.ts``callProvider` 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.