Commit Graph

31 Commits

Author SHA1 Message Date
john kevin asprec
444060c3eb Add new agents and skills for enhanced project orchestration and review processes
- Introduced `critic`, an independent adversarial reviewer for security and correctness.
- Added `fable-orchestrator` to manage task routing and verification.
- Implemented `gauntlet-critic` for fresh-context evaluation of gauntlet rounds.
- Created `planner` for generating executable implementation plans with dependencies.
- Developed `security-auditor` for application security reviews and audits.
- Established `system-steward` to improve agent prompts and skills based on verified failures.
- Added `dev-loop` skill for autonomous development loops over repositories.
- Implemented `gauntlet-loop` skill for iterative quality benchmarking against reference standards.
- Updated project settings to utilize the new orchestrator agent.
- Created documentation for `GAUNTLET.md`, `PROGRESS.md`, and `REFERENCE_BAR.md` to track project status and quality benchmarks.
- Added detailed prompting style guide to enhance understanding of prompt patterns and agentic loops.
2026-08-08 16:49:07 +08:00
john kevin asprec
6aee260533 fix: never send an API key to the provider it wasn't entered for (v1.0.2)
All checks were successful
CI — Test & Build / Test & Build (push) Successful in 1m33s
A stored key carried no record of which provider it belonged to. Options
saves {provider, model} without the key whenever the field is blank (which
it always is after a save, since it shows the encrypted badge instead), so
switching provider left the previous provider's key attached to the new one.
Every call then failed with that provider's own "Invalid API Key" while the
UI still showed a key as configured.

- types.ts: new `keyProvider` storage field, added to CONFIG_STORAGE_KEYS
- background.ts: keyProviderMismatch() guards the chat, COPY_AS and
  stored-key LIST_MODELS paths; absent keyProvider (pre-upgrade) is allowed
- Options.tsx: stamps keyProvider on every save; drops the encrypted badge
  and requires a new key when the saved one belongs to another provider or
  is rejected; save-time guard messages are now actually rendered (they were
  gated on modelsStatus === 'error' and never drew, so Save looked dead)
- providers.ts: providerLabel(); settings hint appended to 401/403 only;
  listModels reports keyRejected and labels errors with the display name
- Anthropic: send anthropic-dangerous-direct-browser-access on the chat path

Docs: CLAUDE.md version-bump rule corrected — wxt.config.ts reads
pkg.version, so package.json is the only place to edit.

typecheck clean, 58/58 tests, build clean (281.72 kB, manifest 1.0.2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-23 15:50:07 +08:00
john kevin asprec
acea99d7ad 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.
2026-07-15 15:27:41 +08:00
john kevin asprec
d0c4cc947d refactor: declarative context-menu registry; named selection threshold
CONTEXT_MENU_ENTRIES maps every menu id to {action, style, parentId,
title}, replacing the split('-') id parsing that only worked because no
name contained a hyphen. Foreign menu ids are now ignored explicitly.
Parity pinned by tests enumerating all 30 previous ids. The 10-char
toolbar trigger threshold is now the named MIN_SELECTION_LENGTH.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:44:16 +08:00
john kevin asprec
f0962471b4 refactor: collapse 8 provider functions into one adapter table
src/lib/providers.ts holds a per-provider spec (url, headers, body,
extractor, default model) and a single callProvider() covering both the
action-prompt and custom-prompt families (~250 lines -> one path).
getSystemPrompt, fetchWithTimeout, and listModels move along with it;
background.ts drops from 553 to 130 lines.

Behavior pinned by 20 parity tests written from the old functions
(request shapes, headers, defaults, error strings). One deliberate
change: max_tokens now scales with input length (1024-8192) instead of
a hard-coded 1024, so Expand no longer truncates long selections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:42:39 +08:00
john kevin asprec
c4634d4965 refactor: consolidate API-key crypto into src/lib/crypto with compat tests
Encrypt (Options) and decrypt (background) now share one module; wire
format unchanged. Tests include fixtures proving values encrypted by the
old inline Options code still decrypt, plus tamper/wrong-key cases. The
module documents the honest threat model (key co-located with ciphertext
= obfuscation, not encryption).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:38:42 +08:00
john kevin asprec
47d9152bda refactor: single source for writing styles + action labels; add theme module
- src/lib/actions.ts: canonical ACTIONS/ACTION_LABELS/WRITING_STYLES;
  context-menu styles derived (WRITING_STYLES minus Default). Replaces
  the three duplicated style arrays in popup, content, and background.
- src/lib/theme.ts: canonical palette. Existing hex literals in the
  entrypoints are swapped wholesale when light/dark theming lands, so
  the color plumbing is only rewritten once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:35:54 +08:00
john kevin asprec
324cfcc486 refactor: extract shared types + safe chrome wrappers into src/lib
- src/lib/types.ts: message contract (both ANALYZE_TEXT shapes preserved),
  config/response types, storage-key constants.
- src/lib/messaging.ts: single safeStorageGet/safeStorageSet/safeSendMessage/
  isExtensionValid implementation replacing the three divergent copies in
  Options, Popup, and content. Content script keeps its refresh-toast
  behavior via an onContextInvalidated callback.
- New '@lib' import alias (wxt force-overwrites '~' and '@' to srcDir, so
  those cannot point at ./src); wired in wxt.config, tsconfig, vitest.
- tests/unit/messaging.test.ts: 14 unit tests over the wrappers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:33:56 +08:00
john kevin asprec
04a4a2dc99 chore: remove unused deps, pin toolchain, single-source version, quarantine e2e
- Uninstall zustand, tailwindcss, autoprefixer, tweetnacl-util (all
  unused); README no longer advertises Tailwind/Zustand.
- Fix stale 'Tone' -> 'Explain' copy in Options.
- Add .nvmrc/engines/packageManager (Node 22 to match CI).
- wxt.config.ts reads manifest version from package.json so the two
  can never drift.
- Ignore *.zip build artifacts.
- Skip the two e2e specs with literal [EXTENSION_ID] placeholders
  (cannot pass; TODO references the e2e-ID-resolution task).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:26:51 +08:00
john kevin asprec
a5608e7b09 fix: gate content-script debug logging behind dev mode
Selection text substrings no longer reach the host page's console in
production builds; logs only fire under 'wxt' dev serve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 21:26:21 +08:00
john kevin asprec
f7fcd41341 feat: implement API key resolution and live model listing for providers
All checks were successful
CI — Test & Build / Test & Build (push) Successful in 59s
2026-07-13 13:56:48 +08:00
Forge
1239e5a90e fix: reduce Options page padding and margins - tighter form layout
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 50s
2026-03-06 15:57:31 +08:00
Forge
b0f79566e6 feat: LEXAI-15 writing style selector in modal, popup, and right-click menu
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 47s
2026-03-06 15:43:10 +08:00
Forge
2bc73d5fc9 feat: LEXAI-23 move Copy As + Download into More dropdown on toolbar
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 45s
2026-03-06 15:30:48 +08:00
Forge
1490e6641f feat: replace Tone Analysis with Explain - simplifies highlighted text in plain language
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 49s
2026-03-06 15:27:40 +08:00
Forge
e3b4925ef5 feat: LEXAI-16 request timeout (fetchWithTimeout), LEXAI-19 Copy As, LEXAI-20 Download
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
2026-03-06 15:25:45 +08:00
Forge
209a26c09c fix: LEXAI-21 popup message type mismatch - use ANALYZE_TEXT to match background handler
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 45s
2026-03-06 15:21:06 +08:00
Forge
58b6728332 fix: popup configured check — also detect apiKeyEnc (encrypted key)
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 49s
2026-03-06 15:12:24 +08:00
Forge
0273356f4d feat: LEXAI-13 API encryption, LEXAI-11 context menu, LEXAI-12 tone analysis
- LEXAI-13: TweetNaCl secretbox encryption for API keys in Options + background
  - getOrCreateEncKey() generates per-device 32-byte key stored in chrome.storage.local
  - Keys saved as nonce+ciphertext (base64) under apiKeyEnc
  - Backward compat: falls back to plaintext apiKey if no encrypted key found
  - Lock icon 🔒 shown in Options label when key is encrypted
- LEXAI-11: Right-click context menu with Fix, Rephrase, Shorten, Expand, Tone
  - Registered via onInstalled in background service worker
  - Sends lexai-context-menu message to content script
  - Content script listener added at bottom of main()
- LEXAI-12: Tone analysis button added to floating toolbar (teal #2dd4bf)
  - Analysis-only: showModal called with null originalText = no Replace button
  - Tone system prompt updated to pure analysis (no rewrite)
2026-03-06 15:06:43 +08:00
Forge
9604bef3a4 feat: LEXAI-21 popup text input with quick action buttons
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
2026-03-06 15:01:29 +08:00
Forge
ec3ece0ea1 fix: simplify contenteditable replace - restore selection + execCommand, no manual delete
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 47s
2026-03-06 14:45:34 +08:00
Forge
8d3887a0af fix: use execCommand insertText for contenteditable replace - fixes delete-without-paste bug
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 43s
2026-03-06 14:44:05 +08:00
Forge
ec98bac146 fix: capture selection on toolbar button mousedown - definitive replace fix
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
Root cause (dual bugs):
1. SCOPE BUG: snapStart/snapEnd/snapElement/snapRange were local vars inside
   runAction() but showModal() is a sibling function — those snap vars were
   never in scope inside the Replace button handler. The condition always
   silently fell through, doing nothing.

2. TIMING BUG: Selection was only captured on document mouseup, which could
   race against focus changes when clicking the toolbar.

Fix:
- showModal() now accepts snapStart/snapEnd/snapElement/snapRange as explicit
  parameters — guaranteed in-scope, no closure ambiguity
- Each toolbar button mousedown calls captureForButton() BEFORE any focus
  shift can occur (belt-and-suspenders, works even if e.preventDefault fails)
- Added console.log debug lines to Replace handler and runAction snapshot
- selectionLocked reset on Escape and overlay click (was missing)
2026-03-06 14:36:48 +08:00
Forge
1936d6a7b5 fix: lock stored selection during modal - prevents mouseup from resetting on Replace click
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 44s
2026-03-06 14:15:41 +08:00
Forge
a0b00c6d87 fix: comprehensive extension context invalidated handling
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
2026-03-06 13:56:30 +08:00
Forge
050e291f73 fix: add tsconfig.json, @types/chrome, fix TS errors - CI typecheck now passes
Some checks failed
CI — Test & Build / Test & Build (push) Failing after 9s
2026-03-06 13:47:24 +08:00
Forge
e34f4aba4b fix: handle extension context invalidated error gracefully 2026-03-06 13:43:57 +08:00
Forge
b54cfc87cf feat: auto-show toolbar on text selection, position above selection 2026-03-06 13:40:50 +08:00
Forge
aa75e8d8ac fix: replace clears text field - store selection before toolbar shows
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
2026-03-06 13:38:13 +08:00
Forge
c35ef08531 feat: fix WXT setup — install @wxt-dev/module-react, fix sandbox imports, clean build (closes #1)
Some checks failed
CI — Test & Build / Unit Tests (push) Failing after 34s
CI — Test & Build / Build Extension (push) Has been skipped
2026-03-06 13:11:19 +08:00
Nemo
b04076081c feat: initial LexAI Chrome extension scaffold
Some checks failed
CI — Test & Build / Unit Tests (push) Failing after 54s
CI — Test & Build / Build Extension (push) Has been skipped
- WXT + React 18 + TypeScript setup
- Background service worker (LLM API proxy)
- Content script (floating toolbar + text selection)
- Options page (provider/model/API key config)
- Popup UI
- Gitea Actions workflows (CI, preview, release)
- Vitest unit tests + Playwright E2E setup
- Supports: OpenAI, Anthropic, Groq, OpenRouter
2026-03-06 09:34:15 +08:00