feat(cli): add initial CLI implementation with argument parsing and prompt handling
- Created package.json and package-lock.json for CLI package. - Implemented argument parsing in args.ts to handle various flags and commands. - Developed main CLI logic in cli.ts to execute commands and handle errors. - Added configuration loading from a JSON file in config.ts, with environment variable support. - Implemented prompt resolution and provider interaction in prompt.ts. - Added usage documentation for the CLI. - Configured TypeScript settings in tsconfig.json for the CLI package. - Updated README in vscode package to reflect the new CLI functionality. - Refactored root tsconfig.json to streamline project structure.
This commit is contained in:
49
packages/chrome/README.md
Normal file
49
packages/chrome/README.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# LexAI for Chrome
|
||||
|
||||
Grammarly-like **Manifest V3** writing assistant powered by **your own LLM API key**. No LexAI account, no subscription, no LexAI servers.
|
||||
|
||||
**Chrome Web Store:** [LexAI — AI Writing Assistant](https://chromewebstore.google.com/detail/bagpcheidbkfgijnnmolnkgagibbjfnk)
|
||||
|
||||
## Features
|
||||
|
||||
- Select text on any page → **Fix / Rephrase / Shorten / Expand / Explain / Make Prompt**
|
||||
- Writing styles: Formal, Casual, Academic, Creative, Concise
|
||||
- Floating toolbar + right-click context menu + popup editor
|
||||
- Prompt Builder (patterns, persona, format)
|
||||
- Providers: OpenAI · Anthropic · Groq · OpenRouter
|
||||
- API key encrypted locally (`tweetnacl` secretbox)
|
||||
|
||||
## Develop
|
||||
|
||||
From the **repo root**:
|
||||
|
||||
```bash
|
||||
npm run chrome:install
|
||||
npm run chrome:dev # hot reload
|
||||
npm run chrome:build # → packages/chrome/.output/chrome-mv3/
|
||||
npm run chrome:zip # store package
|
||||
npm run chrome:test
|
||||
npm run chrome:typecheck
|
||||
```
|
||||
|
||||
Or inside this package:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Load unpacked
|
||||
|
||||
1. `npm run chrome:build`
|
||||
2. Chrome → `chrome://extensions` → Developer Mode
|
||||
3. **Load unpacked** → select `packages/chrome/.output/chrome-mv3`
|
||||
|
||||
## Shared core
|
||||
|
||||
Provider adapters and prompts live in [`../../src/lib`](../../src/lib) (`@lib/*`). Do not import `@lib/crypto` or `@lib/messaging` from the VS Code or CLI packages.
|
||||
|
||||
## Version
|
||||
|
||||
Bump `version` in this package’s `package.json` only — the extension manifest follows it via `wxt.config.ts`.
|
||||
7018
packages/chrome/package-lock.json
generated
Normal file
7018
packages/chrome/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
packages/chrome/package.json
Normal file
35
packages/chrome/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "lexai-chrome",
|
||||
"version": "1.1.0",
|
||||
"description": "LexAI Chrome extension (Manifest V3) — BYO-LLM writing assistant",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=22"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "wxt",
|
||||
"build": "wxt build",
|
||||
"zip": "wxt zip",
|
||||
"postinstall": "wxt prepare",
|
||||
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
||||
"test": "vitest",
|
||||
"test:e2e": "playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wxt-dev/module-react": "^1.1.5",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"tweetnacl": "^1.0.3",
|
||||
"wxt": "^0.20.18"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.50.1",
|
||||
"@types/chrome": "^0.1.37",
|
||||
"@types/react": "^18.3.1",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"jsdom": "^28.1.0",
|
||||
"typescript": "^5.7.3",
|
||||
"vitest": "^3.0.7"
|
||||
}
|
||||
}
|
||||
23
packages/chrome/playwright.config.ts
Normal file
23
packages/chrome/playwright.config.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
||||
export default defineConfig({
|
||||
testDir: '../../tests/e2e',
|
||||
timeout: 30000,
|
||||
use: {
|
||||
channel: 'chrome',
|
||||
},
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium-extension',
|
||||
use: {
|
||||
browserName: 'chromium',
|
||||
launchOptions: {
|
||||
args: [
|
||||
'--disable-extensions-except=.output/chrome-mv3',
|
||||
'--load-extension=.output/chrome-mv3',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
28
packages/chrome/tsconfig.json
Normal file
28
packages/chrome/tsconfig.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Bundler",
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true,
|
||||
"types": ["chrome"],
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"paths": {
|
||||
"@lib/*": ["../../src/lib/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"entrypoints/**/*",
|
||||
"../../src/lib/**/*",
|
||||
".wxt/types/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
".output"
|
||||
]
|
||||
}
|
||||
10
packages/chrome/tsconfig.test.json
Normal file
10
packages/chrome/tsconfig.test.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["chrome", "vitest/globals"]
|
||||
},
|
||||
"include": [
|
||||
"../../tests/**/*",
|
||||
"../../src/lib/**/*"
|
||||
]
|
||||
}
|
||||
17
packages/chrome/vitest.config.ts
Normal file
17
packages/chrome/vitest.config.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@lib': fileURLToPath(new URL('../../src/lib', import.meta.url)),
|
||||
},
|
||||
},
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
globals: true,
|
||||
setupFiles: ['../../tests/unit/setup.ts'],
|
||||
include: ['../../tests/unit/**/*.test.ts'],
|
||||
exclude: ['../../tests/e2e/**/*'],
|
||||
},
|
||||
});
|
||||
@@ -5,16 +5,15 @@ import pkg from './package.json';
|
||||
export default defineConfig({
|
||||
extensionApi: 'chrome',
|
||||
// Shared-code alias. Deliberately NOT "~" or "@" — WXT force-overwrites those
|
||||
// to srcDir (the project root here), so they cannot point at ./src.
|
||||
// to srcDir, so they cannot point at the monorepo shared lib.
|
||||
alias: {
|
||||
'@lib': resolve(__dirname, 'src/lib'),
|
||||
'@lib': resolve(__dirname, '../../src/lib'),
|
||||
},
|
||||
modules: ['@wxt-dev/module-react'],
|
||||
manifest: {
|
||||
name: 'LexAI - AI Writing Assistant',
|
||||
description: 'Grammar checking and writing assistance powered by your own LLM API key',
|
||||
// Single source of truth: manifest version always follows package.json,
|
||||
// so a release bump is a one-file edit and versions can never drift.
|
||||
// Single source of truth: manifest version always follows package.json.
|
||||
version: pkg.version,
|
||||
icons: {
|
||||
'16': 'icon-16.png',
|
||||
|
||||
Reference in New Issue
Block a user