typebulb 0.39.3 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/dist/agents/claude/client.js +214 -194
- package/dist/agents/claude/styles.css +35 -20
- package/dist/agents/pi/client.js +242 -222
- package/dist/agents/pi/matchu-patchu.ts +1 -1
- package/dist/agents/pi/styles.css +35 -20
- package/dist/dts/tbTypings.d.ts +4 -3
- package/dist/dts/tbTypings.d.ts.map +1 -1
- package/dist/dts/tbTypings.js +21 -6
- package/dist/dts/tbTypings.js.map +1 -1
- package/dist/format/parse.d.ts +7 -0
- package/dist/format/parse.d.ts.map +1 -1
- package/dist/format/parse.js +4 -1
- package/dist/format/parse.js.map +1 -1
- package/dist/index.js +329 -307
- package/dist/lint/codeView.d.ts +24 -0
- package/dist/lint/codeView.d.ts.map +1 -0
- package/dist/lint/codeView.js +128 -0
- package/dist/lint/codeView.js.map +1 -0
- package/dist/lint/index.d.ts +7 -0
- package/dist/lint/index.d.ts.map +1 -1
- package/dist/lint/index.js +33 -17
- package/dist/lint/index.js.map +1 -1
- package/dist/render.js +159 -139
- package/dist/servers.js +599 -95
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ This document is dedicated to the typebulb CLI. At its core, it compiles and ser
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
18
|
- **Server-side code** — Add a `**server.ts**` section; exported functions become callable from the browser via `tb.server.<name>()` (e.g., `export async function query(...)` → `await tb.server.query(...)`). An `export async function*` **streams**: consume it with `for await (const chunk of tb.server.gen())`. Requires `--trust`.
|
|
19
|
-
- **CLI logging** — `tb.
|
|
19
|
+
- **CLI logging** — `tb.log(...)` prints to the CLI's stdout, from `code.tsx` and `server.ts` alike (no trust needed)
|
|
20
20
|
- **Wake-on-event** — `typebulb wait <file|agent>` blocks until the target server logs a new line, prints it, and exits. Run in the background, that exit *is* an agent's wake-up: a user action a bulb logs, or an embed's render outcome — no polling.
|
|
21
21
|
- **Env files** — `.env` / `.env.local` load from cwd, `.env.local` overriding `.env` (an exported shell var wins over both). `--mode <name>` adds `.env.<name>` to switch environments (local/staging/prod); a startup line reports which keys loaded from where.
|
|
22
22
|
- **Server mode** — `--server` runs only the `**server.ts**` section in Node, skipping the web server. Bulbs with only `**server.ts**` (no `**code.tsx**`) use this mode automatically.
|
|
@@ -61,7 +61,7 @@ typebulb stop --global Stop every running bulb and mirror, all projects
|
|
|
61
61
|
typebulb trust [file] Remember a bulb as trusted (no arg: list trusted bulbs)
|
|
62
62
|
typebulb untrust <file> Forget a bulb's trust (back to Restricted)
|
|
63
63
|
typebulb --no-watch <file> Disable hot reload
|
|
64
|
-
typebulb --port 3333 <file>
|
|
64
|
+
typebulb --port 3333 <file> Bind this exact port (fails if taken)
|
|
65
65
|
typebulb --no-open <file> Don't auto-open browser
|
|
66
66
|
typebulb --mode <name> <file> Also load .env.<name> on top of .env / .env.local
|
|
67
67
|
typebulb --batch <name> <file> Scope tb.dir + relative tb.fs paths to <bulb-folder>/batches/<name> (batch runs)
|
|
@@ -190,6 +190,7 @@ everywhere.
|
|
|
190
190
|
| `tb.url()` | Get the bulb URL (the served localhost URL, locally) | |
|
|
191
191
|
| `tb.models()` | List available AI models (for dynamic model selectors); the `.env` default is flagged (`default: true`); returns `[]` when embedded (no host AI) | |
|
|
192
192
|
| `tb.hasOwnKeys()` | Whether the user's own AI keys back `tb.ai` — `false` means courtesy model only; always `false` embedded | |
|
|
193
|
+
| `tb.log(...)` | Print to the CLI's stdout (read back with `typebulb logs`); falls back to the browser console when no CLI serves the page | |
|
|
193
194
|
| `tb.onMessage(cb)` | Receive a value pushed in from the terminal by `typebulb send`; a non-`undefined` return becomes the reply `send --wait` prints — inert when embedded (no sender) | |
|
|
194
195
|
| `tb.fs.read/readBytes/write` | Read and write local files | yes |
|
|
195
196
|
| `tb.dir` | The bulb's folder (absolute path), where relative `tb.fs` paths land | |
|
|
@@ -242,13 +243,13 @@ The agent mirror turns that block into a live, sandboxed app, with a *breakout
|
|
|
242
243
|
|
|
243
244
|
### Emitting a local bulb
|
|
244
245
|
|
|
245
|
-
- **Launch once,
|
|
246
|
+
- **Launch once, and share the printed link.** `npx typebulb foo.bulb.md` starts the server and opens a tab (in VS Code's terminal it prints the link for the user to click instead). The link stays good — a bulb keeps its port across runs.
|
|
246
247
|
|
|
247
248
|
### Iterating on a local bulb
|
|
248
249
|
|
|
249
250
|
That one launch *is* the loop: the server watches the file, so every save recompiles and reloads the page (`server.ts` included) — editing the file is the iteration.
|
|
250
251
|
|
|
251
|
-
- **Don't relaunch, and don't wrap it in `timeout`.** A relaunch
|
|
252
|
+
- **Don't relaunch, and don't wrap it in `timeout`.** A relaunch replaces the running server (one per bulb file), reclaiming the same port so the open tab reloads itself — it costs the page's in-memory state and nothing else. `timeout` kills it outright, and the racing relaunch is what spawns extra windows.
|
|
252
253
|
- **What needs a restart:** a `.env` change (read once at boot) and in-memory `server.ts` state (reset on each reload).
|
|
253
254
|
- **Each reload re-runs the bulb.** A save re-executes `code.tsx` from scratch, so work you start on mount repeats every edit — re-spending GPU/network, re-firing side effects, flooding the log. Put expensive or side-effecting work behind a trigger: `tb.onMessage(() => start())`, then `typebulb send <file>` when ready (also a general terminal→page channel — pass params, drive a loop).
|
|
254
255
|
- **Reading the log:** it appends across every reload, so `typebulb logs --run latest <file>` shows just the current run (no need to clear).
|
|
@@ -261,13 +262,13 @@ That one launch *is* the loop: the server watches the file, so every save recomp
|
|
|
261
262
|
- **Structured selftest** — a handler that returns `{ count, verdict }` beats one that logs prose: `typebulb send <file> selftest --wait` prints the object as JSON, and you assert on fields instead of parsing `logs`. At most one handler, in one page, may return a value; a slow check needs `--wait=<ms>` above the 5s default.
|
|
262
263
|
- **Rendered truth** — `typebulb send <file> tb:snapshot` prints the page's accessibility outline (roles, names, visible text) without disturbing its state. Use it when logs say ok but the screen might not, and as the first probe on a live page in a state you can't reproduce — a save would hot-reload and destroy it. (`tb:` messages are answered by the runtime, never your handlers, and imply `--wait`.)
|
|
263
264
|
- **Poking state** — to tweak a value in a live page (a save hot-reloads and destroys its state), author a set-handler up front: a `tb.onMessage` branch that takes a data payload (JSON arrives parsed), applies it to your state — committing the change if your framework needs an explicit step — and returns the new state: `typebulb send <file> '{"set":"speed","value":2}' --wait` prints it. In React, register it in an effect so it closes over the setters (the returned unsubscribe is the cleanup). Adding the handler later is itself the edit that destroys the state.
|
|
264
|
-
- **A page must be open** — `send`
|
|
265
|
+
- **A page must be open** — the CLI runs no browser of its own, so every client-side check waits on a real window (and `--no-open` means there isn't one). `send` says which case it is: nobody has ever connected (share the link), or a page dropped and hasn't returned (it's stale — reload it).
|
|
265
266
|
|
|
266
267
|
### Emitting a server-only bulb
|
|
267
268
|
|
|
268
269
|
A `**server.ts**` block with no `**code.tsx**` is a headless bulb — no UI, no port, absent from the launcher. Under `--trust` its code can use `tb.fs`, and call `tb.ai`, `tb.ai.stream`, and `tb.models` against your `.env` keys.
|
|
269
270
|
|
|
270
|
-
- **Invoke one export with `typebulb call <file> <fn> [args…] --trust`.** It boots, runs that export, prints the `return` as JSON to stdout, and exits — a fresh boot per call.
|
|
271
|
+
- **Invoke one export with `typebulb call <file> <fn> [args…] --trust`.** It boots, runs that export, prints the `return` as JSON to stdout, and exits — a fresh boot per call. Under `call`, logs (`console.log` / `tb.log`) go to stderr, so the JSON result owns stdout.
|
|
271
272
|
|
|
272
273
|
## Sizing
|
|
273
274
|
|
|
@@ -290,7 +291,8 @@ The host owns a bulb's **width**; you own its **height**.
|
|
|
290
291
|
- **A bulb's working files land beside it automatically** — relative `tb.fs` paths resolve to the bulb's folder, in `code.tsx` and `server.ts` alike: `tb.fs.write('run.json')`, no path prefix, no mkdir.
|
|
291
292
|
- **Images & media: an `assets/` subfolder of the bulb's folder** (`birds.bulb.md` → `birds/assets/robin.png`) — `<img src="assets/robin.png">` just works (always that relative form, never `/assets/…`), every tier except embedded.
|
|
292
293
|
- **Batch runs: scope with `--batch`, don't hand-roll plumbing** — `--batch pilot` on a run or `call` lands `tb.dir` and relative `tb.fs` paths in `<bulb-folder>/batches/pilot/`; the bulb's code stays batch-unaware, an unscoped run sees `batches/` as an ordinary subfolder, and the agent mirror lists a bulb's batches on its launcher row (play opens the newest).
|
|
293
|
-
- **
|
|
294
|
+
- **See what's already running** — `typebulb logs` with no argument lists every running bulb and mirror; check it before launching anything.
|
|
295
|
+
- **Self-testing a local bulb** — To confirm a bulb works, run it, instrument with `tb.log(...)`, and read it back with `typebulb logs`. That's the loop to verify behaviour without asking the user to copy-paste console output. `tb.fs.write(...)` is handy for dumping large outputs.
|
|
294
296
|
- **Self-testing client code** — gate checks behind `tb.onMessage(m => { if (m === 'selftest') return run() })`, trigger with `typebulb send <file> selftest --wait`, and assert on the JSON reply — see [Interrogating the live page](#interrogating-the-live-page).
|
|
295
297
|
- **Testing a `server.ts` export directly** — `typebulb call <file> <fn> [arg…]` boots `server.ts`, invokes one export, and prints its return as JSON to stdout (logs/errors to stderr, so `… | jq` works). Args after `<fn>` are JSON-or-string; `--args '<json-array>'` (or `--args -` for stdin) escapes tricky quoting. Needs `--trust`.
|
|
296
298
|
- **Mount to the container your `index.html` declares.** The corpus convention is `<div id="root"></div>` with `createRoot(document.getElementById("root")!)`.
|