Skip to content

Commit 9e63850

Browse files
authored
Merge pull request #105 from levelcodeai/feat/web-edition
feat(web): LevelCode in your browser — the same workbench and AI extension as a static site, signed in with a LevelCode account
2 parents 2568fc3 + ee3ca41 commit 9e63850

72 files changed

Lines changed: 9416 additions & 86 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/release.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ jobs:
4141
node-version: "24"
4242
- name: Extension unit tests
4343
# The gate itself lives in a script, so the pull-request workflow (test.yml) runs exactly what
44-
# this does. It discovers every extensions/*/test/*.test.js and modules/*/test/*.test.js, and
45-
# fails if it finds none.
44+
# this does. It discovers every extensions/*/test/*.test.js, modules/*/test/*.test.js and
45+
# web/test/unit/*.test.js, and fails if it finds none.
4646
run: ./scripts/test-extensions.sh
4747
- name: Open VSX still signs with a key this release trusts
4848
# The app verifies extensions against Open VSX's signing key, and the key is pinned in the app

‎.gitignore‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ node_modules/
3838
.DS_Store
3939
*.log
4040
out/
41+
42+
# LevelCode in your browser: the release directory scripts/build-web.mjs writes, and the bundle's
43+
# generated assets module (web/ai-extension/build.mjs removes it after bundling).
44+
/dist-web/
45+
/web/ai-extension/assets.generated.js

‎CLAUDE.md‎

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ extensions/levelcode-sync/ 'levelcode' auth provider that lights up the bu
4242
extensions/levelcode-updater/ notify-only update checker (polls the update feed; never auto-applies)
4343
modules/extension-signature/ Open VSX signature verifier the built app loads as @vscode/vsce-sign, + the signing keys it trusts
4444
patches/levelcode-core.patch our core source edits, applied on bootstrap
45-
scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, editor-identity.mjs, extension-signature.mjs, build-macos.sh, make-dmg.sh, make-icon.sh; atom (CLI launcher) + install-level.sh
45+
scripts/ bootstrap.sh, apply-branding.mjs, run-dev.sh, editor-identity.mjs, extension-signature.mjs, build-macos.sh, make-dmg.sh, make-icon.sh, build-web.mjs; atom (CLI launcher) + install-level.sh
4646
tools/ dependency-free reference servers: sync-server (/v1 Settings-Sync), update-server (/api/update feed)
47+
web/ LevelCode in a browser tab: page entry + callback, scratch-workspace extension, layout, themes + chat skin, browser build of levelcode-ai, dev server, tests (docs/WEB.md)
4748
vscode/ GITIGNORED upstream Code-OSS checkout (generated)
4849
```
4950

@@ -111,6 +112,39 @@ module for that slot. Full account + runbooks: `docs/EXTENSION-SIGNATURES.md`.
111112
- Its tests live in `modules/extension-signature/test/` — outside `extensions/`, whose `test/` folders
112113
ship in the app. `scripts/test-extensions.sh` discovers `modules/*/test/*.test.js` too.
113114

115+
## LevelCode in a tab (`web/`) — read `docs/WEB.md` first
116+
117+
The same `extensions/levelcode-ai` source runs in a browser tab (web-worker extension host). Rules that keep
118+
the desktop app exactly as it was:
119+
120+
- **A workspace read or write goes through `extensions/levelcode-ai/host.js`**, never `fs` on a workspace path:
121+
in a tab the workspace is whatever the editor's file-system provider says, and every read is asynchronous.
122+
On the desktop each `host` function does what the call site did before, behind `await`.
123+
- **Nothing outside `host.js` asks "am I in a browser?"** — a call site asks for a capability (`host.caps.shell`,
124+
`.mcpStdio`, `.ripgrep`) or calls a function that already knows. A new tool that needs a shell/disk/process is
125+
listed in `NEEDS_SHELL` (agent.js) so the browser neither offers it nor promises it.
126+
- The browser build is `web/ai-extension/` (esbuild + shims for `fs`/`path`/`os`/`crypto`/`child_process`).
127+
Strings that are true on a Mac and false in a tab are rewritten by `web/ai-extension/copy.js`, which fails the
128+
build when the desktop text it expects is gone — change both together. `manifest.js` drops the commands and
129+
settings a tab cannot honour.
130+
- `web/main.js` is a plain ES module with a **top-level `await`**: a `const` declared lower in the file is not
131+
initialised until that await finishes (this cleared a saved session once). Declare constants above the
132+
`try`, and use function declarations for helpers it calls.
133+
- **The look is web-only and lives in `web/`** (theme package, `chrome.css`, the chat skin, the layout commands;
134+
`docs/WEB.md` "The look and the layout"). The chat skin is cut into the browser build's **copy** of
135+
`media/chat.html` by `web/ai-extension/skin.js`; never edit the desktop file for it (its suites pin the page).
136+
Every skin rule is under `body.lc-web`. An extension's `configurationDefaults` outrank the embedder's, so
137+
`levelcode-themes`' pinned default theme is stripped from the staged copy (`withoutConfigurationDefaults`).
138+
`node web/test/e2e-look.mjs --dist dist-web --stub-port <port>` is the check; look at its screenshots (`--shots`).
139+
The embedder's command API is the module's `commands` (`api.commands.executeCommand`): `create()` returns a
140+
disposable, so `workbench.commands` is `undefined` — a helper that used it ran inside a `try` and silently did
141+
nothing until a browser test asked for its effect.
142+
- The session store (`createSecretStorage`) belongs to every tab: no cache, one-key read-modify-write under a
143+
Web Lock. The refresh token is rotated on use; do not reintroduce a start-up snapshot.
144+
- Build: `node scripts/build-web.mjs --account <origin>` → `dist-web/`; serve with `node web/serve.mjs --dist dist-web`.
145+
Tests: the unit gate (`scripts/test-extensions.sh` includes `web/test/unit/*.test.js`) and the end-to-end checks in
146+
`web/test/e2e*.mjs` (headless Chrome, stand-in backend; Node 22+). What was not run is listed in `docs/WEB.md`.
147+
114148
## Toolchain (hard requirements — these bit us)
115149

116150
- **Node = `vscode/.nvmrc` (currently 24.15.0)**. Older majors fail to compile native modules.
@@ -242,7 +276,7 @@ big-file mode badge. Files: extension.js + fileOps/lineOps/columnOps/encodingEol
242276
is not in the editor until you load it: `./scripts/run-dev.sh --extensionDevelopmentPath=<worktree>/extensions/levelcode-ai`
243277
(from the main checkout; the dev extension replaces the built-in one). Uncommitted work is not "on the branch" —
244278
checking the branch out somewhere else gets none of it. Run it in the editor before telling anyone to try it.
245-
- Commit `extensions/`, `modules/`, `patches/`, `branding/`, `scripts/`, `docs/`, `PLAN.md`, `CLAUDE.md`. Never commit `vscode/`.
279+
- Commit `extensions/`, `modules/`, `patches/`, `branding/`, `scripts/`, `web/`, `docs/`, `PLAN.md`, `CLAUDE.md`. Never commit `vscode/` or `dist-web/`.
246280
- `extensions/levelcode-ai/diagram/` modules listed in `bundle.FILES` are pasted INTO a script block in `chat.html`.
247281
They must never contain the text of a script tag or an HTML comment opener — not even in a comment — or the block
248282
ends early; `bundle.js` refuses to build if one does. Keep them dependency-free and free of `require('vscode')`/`fs`.

‎README.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ LevelCode is a **clean overlay on top of Code-OSS**, not a vendored copy of the
3636
- `branding/` — the LevelCode identity (`product.overlay.json`) + icons, deep-merged onto upstream `product.json`; the extension gallery wired to **Open VSX**.
3737
- `modules/` — what ships in the app outside an extension: the Open VSX signature verifier and the signing keys it trusts.
3838
- `patches/` — the small set of core source patches (each tagged `// [LevelCode]`).
39-
- `scripts/` — bootstrap / run-dev / build / dmg / icon.
39+
- `scripts/` — bootstrap / run-dev / build / dmg / icon, and `build-web.mjs` (LevelCode in a browser tab).
40+
- `web/` — LevelCode in your browser: the same workbench and AI extension as a static site you can host; sign in with a LevelCode account or use your own key. See [`docs/WEB.md`](docs/WEB.md).
4041
- `tools/` — dependency-free reference servers (Settings-Sync feed, update feed).
4142
- `PLAN.md`, `docs/`, `CLAUDE.md` — the vision, roadmap, and repo map.
4243

0 commit comments

Comments
 (0)