diff --git a/.codex/environments/environment.toml b/.codex/environments/environment.toml new file mode 100644 index 0000000..9f123a6 --- /dev/null +++ b/.codex/environments/environment.toml @@ -0,0 +1,31 @@ +# THIS IS AUTOGENERATED. DO NOT EDIT MANUALLY +version = 1 +name = "mp-silma-ai-aide" + +[setup] +script = "npm run codex:setup" + +[[actions]] +name = "Run Dev" +icon = "run" +command = "npm run dev:codex" + +[[actions]] +name = "Build" +icon = "tool" +command = "npm run build:codex" + +[[actions]] +name = "Preview Dist" +icon = "run" +command = "npm run preview" + +[[actions]] +name = "Verify Dist" +icon = "tool" +command = "npm run verify:dist" + +[[actions]] +name = "Install" +icon = "tool" +command = "npm ci" diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..d70a880 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,26 @@ +name: Build + +on: + push: + branches: + - main + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Build deployable extension + run: npm run build diff --git a/AGENTS.md b/AGENTS.md index 08fae43..ce7ae20 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,10 +6,14 @@ ## Commands -- Install dependencies: `npm install` +- Install dependencies: `npm ci` +- Codex setup: `npm run codex:setup` - Run local Vite dev server: `npm run dev` +- Run app in Codex: `npm run dev:codex` - Build extension: `npm run build` +- Build extension in Codex: `npm run build:codex` - Preview build output: `npm run preview` +- Verify generated extension output: `npm run verify:dist` ## Environment @@ -25,7 +29,9 @@ Use `.env.local` for local secrets. Keep `.env.local` and any real token-bearing ## Extension Build Notes - `vite.config.ts` emits `dist/manifest.json` during production builds. +- `dist/` is the deployable output directory. Deployment or Chrome load-unpacked flows should point directly at `dist/`. - `dist/` is generated output and should not be edited directly. +- `npm run build` runs `scripts/verify-dist.mjs` after Vite to ensure the generated output has the required extension files. - Host permissions are derived from `VITE_GITEA_BASE_URL`. Rebuild after changing the base URL. - Runtime API calls are centralized in `src/api.ts`. - Popup state is centralized in the vanilla Zustand store at `src/store.ts`. diff --git a/README.md b/README.md index 8aafcf3..eec1780 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,13 @@ Context-aware AI aide — project-agnostic tooling to give Silma better context Install dependencies: ```bash -npm install +npm ci +``` + +Run the Vite dev server: + +```bash +npm run dev ``` Build the Chrome extension: @@ -16,4 +22,13 @@ Build the Chrome extension: npm run build ``` -Load the generated `dist/` folder in Chrome as an unpacked extension. +The deployable extension output is `dist/`. Load `dist/` in Chrome as an unpacked extension, or point deployment tooling at that folder. `npm run build` runs TypeScript, Vite, and a post-build check that verifies `dist/manifest.json` and the popup entry exist. + +## Codex + +Codex setup and action commands are declared in `.codex/environments/environment.toml`: + +- Setup: `npm ci` +- Dev: `npm run dev:codex` +- Build: `npm run build:codex` +- Preview: `npm run preview` diff --git a/llm.txt b/llm.txt index 4586da4..7d0f6b0 100644 --- a/llm.txt +++ b/llm.txt @@ -13,7 +13,14 @@ Important files: - `src/main.ts`: Popup UI behavior. - `index.html`: Popup document. -Build with `npm run build`. Load the generated `dist/` folder in Chrome as an unpacked extension. Do not edit `dist/` directly. +Build with `npm run build`. The deployable output directory is `dist/`; load that folder in Chrome as an unpacked extension or point deployment tooling at it. Do not edit `dist/` directly. + +Codex commands: + +- Setup: `npm run codex:setup` +- Dev: `npm run dev:codex` +- Build: `npm run build:codex` +- Verify output: `npm run verify:dist` Required env variables: diff --git a/manifest.llm.json b/manifest.llm.json index 0e9a7de..9cb0d88 100644 --- a/manifest.llm.json +++ b/manifest.llm.json @@ -5,6 +5,11 @@ "project_type": "chrome-extension", "language": "typescript", "package_manager": "npm", + "deployable_output": { + "path": "dist/", + "type": "chrome-extension", + "description": "Build output is self-contained and can be loaded directly as an unpacked Chrome extension." + }, "entrypoints": { "popup_html": "index.html", "popup_script": "src/main.ts", @@ -14,10 +19,14 @@ "generated_manifest": "dist/manifest.json" }, "commands": { - "install": "npm install", + "install": "npm ci", + "codex_setup": "npm run codex:setup", "dev": "npm run dev", + "codex_dev": "npm run dev:codex", "build": "npm run build", - "preview": "npm run preview" + "codex_build": "npm run build:codex", + "preview": "npm run preview", + "verify_dist": "npm run verify:dist" }, "environment": { "example_file": ".env.example", diff --git a/package.json b/package.json index cbe48ce..a414469 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,20 @@ "private": true, "type": "module", "scripts": { - "dev": "vite", - "build": "tsc --noEmit && vite build", - "preview": "vite preview" + "codex:setup": "npm ci", + "dev": "vite --host 0.0.0.0", + "dev:codex": "npm run dev", + "build": "tsc --noEmit && vite build && npm run verify:dist", + "build:codex": "npm run build", + "preview": "vite preview --host 0.0.0.0", + "verify:dist": "node scripts/verify-dist.mjs" }, "keywords": [], "author": "", "license": "ISC", + "deploy": { + "outputDir": "dist" + }, "dependencies": { "axios": "^1.18.1", "dotenv": "^17.4.2", diff --git a/scripts/verify-dist.mjs b/scripts/verify-dist.mjs new file mode 100644 index 0000000..be6fd98 --- /dev/null +++ b/scripts/verify-dist.mjs @@ -0,0 +1,33 @@ +import { existsSync, readFileSync } from "node:fs"; +import { join } from "node:path"; + +const distDir = "dist"; +const manifestPath = join(distDir, "manifest.json"); + +function fail(message) { + console.error(message); + process.exitCode = 1; +} + +if (!existsSync(distDir)) { + fail("Missing dist/ output directory. Run vite build first."); +} else if (!existsSync(manifestPath)) { + fail("Missing dist/manifest.json. The built folder is not loadable as a Chrome extension."); +} else { + const manifest = JSON.parse(readFileSync(manifestPath, "utf8")); + const popup = manifest.action?.default_popup; + + if (manifest.manifest_version !== 3) { + fail("dist/manifest.json must be a Manifest V3 extension manifest."); + } + + if (!popup) { + fail("dist/manifest.json is missing action.default_popup."); + } else if (!existsSync(join(distDir, popup))) { + fail(`dist/${popup} does not exist.`); + } +} + +if (!process.exitCode) { + console.log("dist/ is ready to load as an unpacked Chrome extension."); +}