typebulb 0.9.8 → 0.9.9
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 +31 -52
- package/dist/bulbs/claude.bulb.md +32 -21
- package/dist/index.js +38 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Run single-file markdown apps that execute in many execution contexts:
|
|
|
10
10
|
|
|
11
11
|
A `.bulb.md` file bundles code, styles, data, and config in one file.
|
|
12
12
|
|
|
13
|
-
>
|
|
13
|
+
>This whole document doubles as a skill: it is written so an LLM agent can read it and successfully write and run bulbs with the typebulb CLI.
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
@@ -27,22 +27,7 @@ A `.bulb.md` file bundles code, styles, data, and config in one file.
|
|
|
27
27
|
- **AI calls** — `tb.ai()` for general-purpose AI (chatbots, agents, experiments). `tb.models()` lists available models. Set API keys in `.env` (see below). Requires `--trust`.
|
|
28
28
|
- **Sandboxed by default** — A plain `npx typebulb my-app.bulb.md` runs with no filesystem or `server.ts` (like typebulb.com); `--trust` grants those for a run. Trust is **remembered**: `typebulb trust <file>` elevates a bulb once so later plain runs are trusted, `untrust` revokes it, and `--no-trust` forces sandboxed for a single run.
|
|
29
29
|
- **Predict trust** — `typebulb predict <file>` reports the capability a bulb will likely need (fs / AI / `server.ts`) without running it, so you can decide on `--trust` up front rather than after a mid-run permission failure.
|
|
30
|
-
- **Agent
|
|
31
|
-
|
|
32
|
-
## Claude
|
|
33
|
-
|
|
34
|
-
If the user has Claude Code, consider running `npx typebulb agent:claude`. You can call `npx typebulb agent` to:
|
|
35
|
-
|
|
36
|
-
* determine if it's already running (its stderr reports the running agent viewer, its exit code 0/1 says whether one is up).
|
|
37
|
-
* get a dump of this readme in skill format.
|
|
38
|
-
|
|
39
|
-
This gives the user a great scratchpad experience:
|
|
40
|
-
|
|
41
|
-
* a view over any Claude Code Session, where assistant messages containing bulbs are rendered as sandboxed embedded bulbs inline in the conversation, as well as KaTeX math and mermaid diagrams.
|
|
42
|
-
* the ability to run and stop any bulb in their project.
|
|
43
|
-
* the ability to promote any embedded bulb to a bulb.md file in the typebulbs folder.
|
|
44
|
-
|
|
45
|
-
One hitch: this will open a browser window, but not within VS Code, so the experience is poorly integrated. However there's a workaround: the user can click on the localhost link you give them, and it will open in VS Code. So to avoid the browser opening initially, use the `--no-open` flag.
|
|
30
|
+
- **Agent viewer** — `typebulb agent:claude` opens the agent viewer, a browser view over a Claude Code session that renders embedded bulbs, KaTeX, and mermaid live inline, plus runs/stops local bulbs (see [Claude](#claude)). `typebulb agent` (no target) is the first command an agent runs: it tells the agent how to show a bulb inline or build one locally. `typebulb skill` prints this whole README as an Agent Skill the agent can read and save.
|
|
46
31
|
|
|
47
32
|
## Quick Start
|
|
48
33
|
|
|
@@ -132,8 +117,9 @@ npm install -g typebulb
|
|
|
132
117
|
|
|
133
118
|
```
|
|
134
119
|
typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
|
|
135
|
-
typebulb agent:claude Open the
|
|
136
|
-
typebulb agent
|
|
120
|
+
typebulb agent:claude Open the agent viewer (a Claude Code session)
|
|
121
|
+
typebulb agent Start here — how to show a bulb inline or build one locally
|
|
122
|
+
typebulb skill Print this README as an Agent Skill on stdout
|
|
137
123
|
typebulb check [file.bulb.md] Type-check a bulb without running it
|
|
138
124
|
typebulb predict [file] Report the capability a bulb probably needs, without running it
|
|
139
125
|
typebulb logs [file|pid] Print a running bulb's captured console (-f follow, -n N tail)
|
|
@@ -192,18 +178,6 @@ const { text } = await tb.ai({
|
|
|
192
178
|
|
|
193
179
|
Provider support varies — the level is mapped to provider-specific parameters (e.g. Anthropic's adaptive thinking, OpenAI's reasoning effort).
|
|
194
180
|
|
|
195
|
-
## Limitations
|
|
196
|
-
|
|
197
|
-
- **Inference** — `tb.infer()` is not supported locally. Bulbs that use inference will render but cannot run inference calls. Use `tb.ai()` for programmatic AI access instead.
|
|
198
|
-
|
|
199
|
-
---
|
|
200
|
-
|
|
201
|
-
## Local or embedded?
|
|
202
|
-
|
|
203
|
-
- **First, is anyone watching?** An embed only renders live when the user has the Typebulb agent viewer open; with none it shows as raw text. Run `typebulb agent`: its stderr shows `agent: claude` and it exits 0 when a viewer is up, so embed away; `agent: none` / exit 1 means go **local**. (Its stdout is this authoring skill.)
|
|
204
|
-
- **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **embedded**: emit it in a `bulb` block so it renders live inline.
|
|
205
|
-
- **A tool worth keeping** — something to reuse, run on its own, or refine over several turns. → **local**: write a `.bulb.md` file run with `npx typebulb`. An embedded block is throwaway and can't be edited in place, so it's the wrong fit for anything iterative.
|
|
206
|
-
|
|
207
181
|
## Blocks
|
|
208
182
|
|
|
209
183
|
A bulb is a single **markdown** file — the minimum viable structure for a small sandboxed app. Its named **blocks** hold the code, plus optional styles, data, and config. Every block except `code.tsx` is optional. Mechanically, each block is a `**name**` header on its own line followed by a fenced code block, and the file opens with YAML frontmatter (`format: typebulb/v1`, `name:`).
|
|
@@ -219,17 +193,6 @@ A bulb is a single **markdown** file — the minimum viable structure for a smal
|
|
|
219
193
|
| `**notes.md**` | Persistent context for the AI assistant, carried across conversations and clones. Not run. |
|
|
220
194
|
| `**server.ts**` | Node.js code; its exports become `tb.server.<name>()` in the browser. **Local only.** |
|
|
221
195
|
|
|
222
|
-
Extra notes:
|
|
223
|
-
|
|
224
|
-
- **`data.txt` — why keep data here rather than inline in code or a prompt?** Correctness and auditability: forcing the code to *process* the data means you can verify the output, instead of trusting an LLM not to paraphrase, abridge, or distort values pasted straight into a prompt.
|
|
225
|
-
- **`notes.md`** is useful for API docs, examples, or skills the LLM needs to author the bulb.
|
|
226
|
-
|
|
227
|
-
## Writing the code
|
|
228
|
-
|
|
229
|
-
- **Mount to the container your `index.html` declares.** The corpus convention is `<div id="root"></div>` with `createRoot(document.getElementById("root")!)`.
|
|
230
|
-
- **All imports at the top of `code.tsx`.** Bare imports (`react`, `d3`, `three`, …) auto-resolve from a CDN — no install step. Declare them in `config.json` `dependencies` anyway: that's what lets `npx typebulb check` fetch type defs (without it you get errors like `TS2875: react/jsx-runtime`) and pins versions.
|
|
231
|
-
- **Theme-aware styling.** Style off CSS variables / `currentColor` so the bulb reads correctly in both light and dark; the host sets the theme.
|
|
232
|
-
|
|
233
196
|
## The `tb.*` API, by target
|
|
234
197
|
|
|
235
198
|
`tb` is a pre-declared global your code can use without importing. What each call does, and where it works:
|
|
@@ -252,11 +215,29 @@ Extra notes:
|
|
|
252
215
|
|
|
253
216
|
- **❌ (embedded):** the call throws `"not available in an embedded bulb"` — an embed is a client-only sandboxed iframe with **no persistent storage** either (`localStorage`, `IndexedDB`, cookies, same-origin Workers all fail), so keep state in memory. `tb.mode === 'embedded'` lets a bulb detect this and self-adjust.
|
|
254
217
|
|
|
255
|
-
##
|
|
218
|
+
## Portability back to typebulb.com
|
|
219
|
+
|
|
220
|
+
A local `.bulb.md` can be re-imported into typebulb.com. If it has a `**server.ts**` block you'll be warned on import, since `server.ts` is only meaningful locally.
|
|
221
|
+
|
|
222
|
+
## Claude
|
|
256
223
|
|
|
257
|
-
|
|
224
|
+
The agent viewer currently supports Claude Code only. `npx typebulb agent:claude` gives the user a great scratchpad experience:
|
|
258
225
|
|
|
259
|
-
|
|
226
|
+
* a view over the Claude Code session, where assistant messages containing bulbs render as sandboxed embedded bulbs inline in the conversation, alongside KaTeX math and mermaid diagrams.
|
|
227
|
+
* run and stop any bulb in their project.
|
|
228
|
+
* promote any embedded bulb to a `.bulb.md` file in the `typebulbs/` folder.
|
|
229
|
+
|
|
230
|
+
It opens a browser window outside VS Code, so start it yourself with `npx typebulb agent:claude --no-open` and give the user the localhost link to open in VS Code — don't wait for the user to run it.
|
|
231
|
+
|
|
232
|
+
To keep this skill on hand across sessions, run `npx typebulb skill` and copy its output into your skills folder (for Claude Code, `.claude/skills/typebulb/SKILL.md`) — only if the user asks.
|
|
233
|
+
|
|
234
|
+
### When Claude should output local vs embedded bulbs
|
|
235
|
+
|
|
236
|
+
- **First, is anyone watching?** An embed only renders live when the agent viewer is open; with none it shows as raw text. `typebulb agent` tells you which case you're in. If no viewer is up and you want to show something inline, start it yourself — `npx typebulb agent:claude --no-open` — and share the link; don't make the user do it.
|
|
237
|
+
- **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **embedded**: emit it in a `bulb` block so it renders live inline.
|
|
238
|
+
- **A tool worth keeping** — something to reuse, run on its own, or refine over several turns. → **local**: write a `.bulb.md` file run with `npx typebulb`. An embedded block is throwaway and can't be edited in place, so it's the wrong fit for anything iterative.
|
|
239
|
+
|
|
240
|
+
### Emitting an embedded bulb
|
|
260
241
|
|
|
261
242
|
To render a bulb live inline, wrap the **entire** bulb — frontmatter and all blocks — in a fenced code block whose opening line is **four backticks immediately followed by `bulb`**, and whose closing line is four backticks. Four, not three, so the bulb's own triple-backtick code fences nest inside without prematurely closing the outer block.
|
|
262
243
|
|
|
@@ -270,14 +251,12 @@ The agent viewer turns that block into a live, sandboxed app, with a *breakout
|
|
|
270
251
|
.wrap { margin: 0 auto; padding: 24px 16px; } /* not: margin: 24px auto */
|
|
271
252
|
```
|
|
272
253
|
|
|
273
|
-
##
|
|
274
|
-
|
|
275
|
-
A local `.bulb.md` can be re-imported into typebulb.com. If it has a `**server.ts**` block you'll be warned on import, since `server.ts` is only meaningful locally.
|
|
276
|
-
|
|
277
|
-
## Authoring details
|
|
278
|
-
|
|
279
|
-
Smaller facts from the bulb authoring docs that apply to local bulbs too:
|
|
254
|
+
## Tips for Agents
|
|
280
255
|
|
|
256
|
+
- **Self-testing a local bulb** — To confirm a bulb works, run it, instrument with `tb.server.log(...)` (prints to the server's stdout, captured in the log — and works **even on a sandboxed bulb**), 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.
|
|
257
|
+
- **Mount to the container your `index.html` declares.** The corpus convention is `<div id="root"></div>` with `createRoot(document.getElementById("root")!)`.
|
|
258
|
+
- **All imports at the top of `code.tsx`.** Bare imports (`react`, `d3`, `three`, …) auto-resolve from a CDN — no install step. Declare them in `config.json` `dependencies` anyway: that's what lets `npx typebulb check` fetch type defs (without it you get errors like `TS2875: react/jsx-runtime`) and pins versions.
|
|
259
|
+
- **Theme-aware styling.** Style off CSS variables / `currentColor` so the bulb reads correctly in both light and dark; the host sets the theme.
|
|
281
260
|
- **`tb.ai()` takes more than the basics** — the full shape is `tb.ai({ messages, system?, reasoning?, provider?, model?, webSearch? })` → `Promise<{ text }>` (non-streaming). `webSearch` defaults **on** in the CLI (you supply your own key); pass `webSearch: false` to turn it off.
|
|
282
261
|
- **`tb.theme` drives the `html[data-theme]` attribute** — style off that selector (`html[data-theme="dark"] { … }`); don't read `tb.theme` to branch your rendering.
|
|
283
262
|
- **`color-scheme` is set for you** — the host always applies `html[data-theme="dark"] { color-scheme: dark }` / `html[data-theme="light"] { color-scheme: light }` on top of your `styles.css`.
|
|
@@ -370,19 +370,32 @@ const INTERNAL_PATTERNS = [
|
|
|
370
370
|
/^No response requested\.?$/i,
|
|
371
371
|
/^<task-notification\b/i, // harness protocol envelopes, not human-facing
|
|
372
372
|
/^<system-reminder\b/i,
|
|
373
|
-
/^<ide_[a-z_]+>[\s\S]*<\/ide_[a-z_]+>$/i, // whole IDE-injected context block (opened-file, selection, …)
|
|
374
373
|
]
|
|
375
374
|
function isInternal(text: string): boolean {
|
|
376
375
|
const t = text.trim()
|
|
377
376
|
return !!t && INTERNAL_PATTERNS.some(p => p.test(t))
|
|
378
377
|
}
|
|
379
378
|
|
|
380
|
-
//
|
|
381
|
-
//
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
|
|
385
|
-
|
|
379
|
+
// IDE-injected context (opened-file, selection, …) the editor integration splices into the user's
|
|
380
|
+
// text block — sometimes as the whole block, often inline beside what the user typed. Unlike the
|
|
381
|
+
// envelopes above it can't be anchored start-to-end, so strip the tag spans wherever they sit; what
|
|
382
|
+
// the user actually typed survives. A wholly-IDE block strips to '' and drops out entirely.
|
|
383
|
+
const IDE_CONTEXT = /<ide_[a-z_]+>[\s\S]*?<\/ide_[a-z_]+>/gi
|
|
384
|
+
function stripIdeContext(text: string): string {
|
|
385
|
+
return text.replace(IDE_CONTEXT, '')
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// The display-ready text of a user message: IDE context stripped out, internal/synthetic noise
|
|
389
|
+
// reduced to ''. Empty ⇒ nothing human-authored to show. Shared by applyEntry (the transcript), the
|
|
390
|
+
// queued-command path, and readPreview (the picker) — so an "<ide_opened_file>" block is neither
|
|
391
|
+
// rendered nor mistaken for the kickoff prompt.
|
|
392
|
+
function cleanUserText(text: string): string {
|
|
393
|
+
const t = stripIdeContext(text).trim()
|
|
394
|
+
return t && !isInternal(t) ? t : ''
|
|
395
|
+
}
|
|
396
|
+
// Same, for an array-shaped `type:'text'` block; '' for non-text blocks.
|
|
397
|
+
function userTextBlock(b: ContentBlock | undefined): string {
|
|
398
|
+
return b?.type === 'text' && typeof b.text === 'string' ? cleanUserText(b.text) : ''
|
|
386
399
|
}
|
|
387
400
|
|
|
388
401
|
// Guard the per-entry dispatch: it runs inside the watchFile callback, so an
|
|
@@ -399,15 +412,15 @@ function applyEntry(entry: JsonlEntry) {
|
|
|
399
412
|
if (entry.type === 'user') {
|
|
400
413
|
const content = entry.message?.content
|
|
401
414
|
if (typeof content === 'string') {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
415
|
+
const text = cleanUserText(content)
|
|
416
|
+
if (text) s.buffer.push({ type: 'user', text })
|
|
405
417
|
} else if (Array.isArray(content)) {
|
|
406
418
|
for (const b of content) {
|
|
407
419
|
if (b?.type === 'tool_result') {
|
|
408
420
|
s.buffer.push({ type: 'tool_result', id: b.tool_use_id ?? '', content: toText(b.content), isError: !!b.is_error })
|
|
409
|
-
} else
|
|
410
|
-
|
|
421
|
+
} else {
|
|
422
|
+
const text = userTextBlock(b)
|
|
423
|
+
if (text) s.buffer.push({ type: 'user', text })
|
|
411
424
|
}
|
|
412
425
|
}
|
|
413
426
|
}
|
|
@@ -415,10 +428,8 @@ function applyEntry(entry: JsonlEntry) {
|
|
|
415
428
|
// A message the user queued while CC was mid-turn. CC records it here, not as
|
|
416
429
|
// a user turn, and never re-emits it — so without this branch it's lost from
|
|
417
430
|
// the view. (Other attachment subtypes, e.g. 'selection', stay hidden.)
|
|
418
|
-
const text = toText(entry.attachment.prompt) // string in current CC; toText also tolerates older array shapes
|
|
419
|
-
if (text
|
|
420
|
-
s.buffer.push({ type: 'user', text })
|
|
421
|
-
}
|
|
431
|
+
const text = cleanUserText(toText(entry.attachment.prompt)) // string in current CC; toText also tolerates older array shapes
|
|
432
|
+
if (text) s.buffer.push({ type: 'user', text })
|
|
422
433
|
} else if (entry.type === 'assistant') {
|
|
423
434
|
const content = entry.message?.content
|
|
424
435
|
const blocks: ContentBlock[] = Array.isArray(content) ? content : []
|
|
@@ -537,11 +548,11 @@ function readPreview(file: string): string {
|
|
|
537
548
|
const content = e.message?.content
|
|
538
549
|
let extracted = ''
|
|
539
550
|
if (typeof content === 'string') {
|
|
540
|
-
|
|
551
|
+
extracted = cleanUserText(content)
|
|
541
552
|
} else if (Array.isArray(content)) {
|
|
542
|
-
// Concatenate the real user-text blocks;
|
|
543
|
-
// an "<ide_opened_file>" entry isn't mistaken for the kickoff prompt — we fall through
|
|
544
|
-
extracted = content.
|
|
553
|
+
// Concatenate the real user-text blocks; userTextBlock strips IDE context / drops internal
|
|
554
|
+
// ones so an "<ide_opened_file>" entry isn't mistaken for the kickoff prompt — we fall through.
|
|
555
|
+
extracted = content.map(userTextBlock).filter(Boolean).join(' ')
|
|
545
556
|
}
|
|
546
557
|
const cleaned = extracted.replace(/\s+/g, ' ').trim()
|
|
547
558
|
// Strip the fixed reincarnation lead-in so those sessions surface their distinctive summary.
|
|
@@ -3256,7 +3267,7 @@ a.server-port:hover { color: var(--accent); text-decoration: underline; }
|
|
|
3256
3267
|
"beautiful-mermaid": "^1.1.3",
|
|
3257
3268
|
"dompurify": "^3.2.6",
|
|
3258
3269
|
"highlight.js": "^11.10.0",
|
|
3259
|
-
"typebulb": "^0.9.
|
|
3270
|
+
"typebulb": "^0.9.9"
|
|
3260
3271
|
}
|
|
3261
3272
|
}
|
|
3262
3273
|
```
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import*as ge from"fs/promises";import*as S from"path";import{fileURLToPath as
|
|
2
|
+
import*as ge from"fs/promises";import*as S from"path";import{fileURLToPath as io}from"url";import{spawn as ao}from"child_process";import{EventEmitter as Yt}from"events";import*as Qt from"fs/promises";import{existsSync as se,readFileSync as xn}from"fs";import*as P from"path";import{pathToFileURL as Sn}from"url";import{resolve as dt}from"resolve.exports";import{init as Zt,parse as er}from"es-module-lexer";function tr(r,e){let t=P.join(r,"package.json");try{return JSON.parse(xn(t,"utf8"))}catch{throw new Error(`--replace package '${e}' has no readable package.json at ${t}`)}}var lt=["browser","import","default"],Xt=["node","import","default"];function rr(r){let e=r.indexOf("=");if(e===-1)throw new Error(`--replace must be <name>=<path> (got '${r}')`);let t=r.slice(0,e).trim(),n=r.slice(e+1).trim();if(!t)throw new Error(`--replace missing package name (got '${r}')`);if(!n)throw new Error(`--replace missing path for '${t}'`);if(t.startsWith("@"))throw new Error(`--replace does not support scoped names yet; '${t}' is scoped`);return{name:t,dir:P.resolve(n)}}async function nr(r){let{name:e,dir:t}=r;if(!se(t))throw new Error(`--replace path for '${e}' does not exist: ${t}`);let n=tr(t,e),s=Rn(n,e),o=P.resolve(t,s);if(!se(o))throw new Error(`--replace package '${e}' entry not found on disk: ${o} \u2014 did you build it (e.g. \`pnpm run build\`)?`);let i=P.dirname(o),a=`/local/${e}/${P.basename(o)}`,c=Pn(n,t);return await En(e,o,i),{name:e,dir:t,entryAbs:o,serveDir:i,entryUrl:a,typesAbs:c}}function Rn(r,e){if(r.exports!==void 0){let n;try{n=dt(r,".",{browser:!0,conditions:lt})}catch(o){throw new Error(`--replace package '${e}' "exports" does not resolve a browser entry (conditions: ${lt.join(", ")}): ${o instanceof Error?o.message:o}`)}let s=ut(n);if(!s)throw new Error(`--replace package '${e}' "exports" did not resolve "." to a single file (conditions: ${lt.join(", ")}); too complex to override.`);return s}let t=r.module??r.main;if(!t)throw new Error(`--replace package '${e}' has no "exports", "module", or "main" entry to resolve.`);return t}function Pn(r,e){if(r.exports!==void 0)try{let n=dt(r,".",{conditions:["types"]}),s=ut(n);if(s){let o=P.resolve(e,s);if(se(o))return o}}catch{}let t=r.types??r.typings;if(t){let n=P.resolve(e,t);if(se(n))return n}}function ut(r){if(typeof r=="string")return r;if(Array.isArray(r))return r.find(e=>typeof e=="string")}async function En(r,e,t){await Zt;let n=P.normalize(t),s=new Set,o=[e];for(;o.length;){let i=o.shift();if(s.has(i))continue;s.add(i);let a;try{a=await Qt.readFile(i,"utf8")}catch{continue}let c,l;try{[c,,,l]=er(a,i)}catch{continue}if(i===e&&!l)throw new Error(`override package '${r}' entry is not an ES module (no import/export syntax); CommonJS or non-module entries aren't supported (esm.sh would have to transform it).`);for(let p of c){if(p.d===-2)continue;let d=p.n;if(d&&!d.startsWith("node:")){if(d.startsWith("./")||d.startsWith("../")||d.startsWith("/")){let h=kn(i,d,n);h&&!s.has(h)&&o.push(h);continue}throw new Error(`override package must ship self-contained (bundle its dependencies); ${r} externalizes '${d}'`)}}}}function kn(r,e,t){let n=e.replace(/[?#].*$/,""),s=P.resolve(P.dirname(r),n),o=[s,s+".js",s+".mjs",P.join(s,"index.js"),P.join(s,"index.mjs")];for(let i of o)if(P.normalize(i).startsWith(t)&&se(i))return i}function Tn(r,e,t){let n=tr(r,e),s;if(n.exports!==void 0)try{s=ut(dt(n,t,{conditions:Xt}))}catch(i){throw new Error(`--replace package '${e}' "exports" does not resolve a node entry for '${t}' (conditions: ${Xt.join(", ")}): ${i instanceof Error?i.message:i}`)}else t==="."&&(s=n.main??n.module);if(!s)throw new Error(`--replace package '${e}' has no node export for '${t}'.`);let o=P.resolve(r,s);if(!se(o))throw new Error(`--replace package '${e}' built file not found: ${o} \u2014 did you build it (e.g. \`pnpm run build\`)?`);return Sn(o).href}async function sr(r,e){await Zt;let t;try{[t]=er(r)}catch{return r}let n="",s=0;for(let o of t){if(o.d!==-1)continue;let i=o.n;if(!i||i!==e.name&&!i.startsWith(e.name+"/"))continue;let a=i===e.name?".":"."+i.slice(e.name.length),c=Tn(e.dir,e.name,a);n+=r.slice(s,o.s)+c,s=o.e}return n+r.slice(s)}function or(r){let e={subcommand:"run",file:"",port:3e3,watch:!0,open:!0,server:!1,trust:!1,noTrust:!1,follow:!1,help:!1,version:!1},t=["check","predict","logs","stop","trust","untrust","skill"],n=r[0];if(n==="agent"||n?.startsWith("agent:")){e.subcommand="agent";let s=n.indexOf(":");if(s!==-1){let o=n.slice(s+1);o&&(e.agentTarget=o)}r=r.slice(1)}else n&&t.includes(n)&&(e.subcommand=n,r=r.slice(1));for(let s=0;s<r.length;s++){let o=r[s];if(o==="--help"||o==="-h")e.help=!0;else if(o==="--version"||o==="-V")e.version=!0;else if(o==="--no-watch")e.watch=!1;else if(o==="--no-open")e.open=!1;else if(o==="--server")e.server=!0;else if(o==="--trust")e.trust=!0;else if(o==="--no-trust")e.noTrust=!0;else if(o==="--mode"){let i=r[++s];(!i||i.startsWith("-"))&&(console.error("Missing value for --mode (e.g. --mode staging)"),process.exit(1)),e.mode=i}else if(o==="--follow"||o==="-f")e.follow=!0;else if(o==="--lines"||o==="-n"){let i=parseInt(r[++s],10);(isNaN(i)||i<0)&&(console.error(`Invalid --lines value: ${r[s]}`),process.exit(1)),e.lines=i}else if(o==="--port"||o==="-p"){let i=r[++s],a=parseInt(i,10);isNaN(a)&&(console.error(`Invalid port: ${i}`),process.exit(1)),e.port=a}else if(o==="--replace"||o.startsWith("--replace=")){let i=o.startsWith("--replace=")?o.slice(10):r[++s]??"";try{let a=rr(i);if(e.local)throw new Error(`--replace can only be used once (got '${e.local.name}' and '${a.name}')`);e.local=a}catch(a){console.error(a instanceof Error?a.message:String(a)),process.exit(1)}}else o.startsWith("-")||(e.file=o)}return e}function ir(){console.log(`
|
|
3
3
|
typebulb - Local bulb runner for Typebulb
|
|
4
4
|
|
|
5
5
|
Usage:
|
|
6
6
|
typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
|
|
7
|
-
typebulb agent
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
typebulb agent Start here \u2014 tells the agent how to show a bulb inline
|
|
8
|
+
or build one locally; exit 0 if a viewer is up, else 1.
|
|
9
|
+
typebulb agent:claude Open the agent viewer (a browser view over a Claude
|
|
10
|
+
Code session; 'agent:<name>' selects which agent).
|
|
11
|
+
typebulb skill Print this README as an Agent Skill (stdout), for the
|
|
12
|
+
agent to read and copy into its own skills folder.
|
|
12
13
|
typebulb check [file.bulb.md] Type-check a bulb without running it
|
|
13
14
|
typebulb predict [file] Report the capability a bulb probably needs
|
|
14
15
|
(fs / AI / server.ts) without running it.
|
|
@@ -83,9 +84,9 @@ Examples:
|
|
|
83
84
|
typebulb --no-watch --port 8080 my-editor.bulb.md
|
|
84
85
|
typebulb .
|
|
85
86
|
`)}import{readFileSync as _n,existsSync as Cn}from"fs";import*as U from"path";function An(r){return[...r?[`.env.${r}.local`,`.env.${r}`]:[],".env.local",".env"]}function pt(r,e=process.cwd()){let t={},n=[];for(let s of An(r)){let o;try{o=_n(U.resolve(e,s),"utf-8")}catch{continue}n.push(s);for(let[i,a]of On(o))process.env[i]===void 0&&(process.env[i]=a,t[i]=s)}return{mode:r,sources:t,loaded:n}}function*On(r){for(let e of r.split(`
|
|
86
|
-
`)){let t=e.trim();if(!t||t.startsWith("#"))continue;let n=t.indexOf("=");if(n===-1)continue;let s=t.slice(0,n).trim(),o=t.slice(n+1).trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),yield[s,o]}}function In(r){let e=new Set,t=/process\.env\.([A-Za-z_$][\w$]*)|process\.env\[\s*['"]([^'"]+)['"]\s*\]/g;for(let n;n=t.exec(r);)e.add(n[1]??n[2]);return[...e]}function ft(r,e,t){let{sources:n,mode:s,loaded:o}=r,i=process.cwd(),a=U.dirname(e),c=`(mode: ${s??"none"})`,l=t?In(t):[],p=l.filter(m=>n[m]).map(m=>`${m} \u2190 ${n[m]}`);p.length?console.log(`env: ${p.join(", ")} ${c}`):o.length&&console.log(`env: loaded ${o.join(", ")} ${c}`),s&&!o.some(m=>m===`.env.${s}`||m===`.env.${s}.local`)&&console.log(`env: mode=${s} \u2014 no .env.${s} found; using .env`);let d=U.resolve(a)!==U.resolve(i);if(d)for(let m of[".env.local",".env"])Cn(U.join(a,m))&&console.log(`env: ${U.join(a,m)} present but not loaded (cwd is ${i})`);let h=l.filter(m=>process.env[m]===void 0);if(h.length){let m=d?` \u2014 try running from ${a}`:"";console.log(`env: server.ts reads ${h.join(", ")} but ${h.length>1?"they are":"it's"} unset${m}`)}}import*as G from"fs/promises";import*as et from"path";import{pathToFileURL as
|
|
87
|
+
`)){let t=e.trim();if(!t||t.startsWith("#"))continue;let n=t.indexOf("=");if(n===-1)continue;let s=t.slice(0,n).trim(),o=t.slice(n+1).trim();(o.startsWith('"')&&o.endsWith('"')||o.startsWith("'")&&o.endsWith("'"))&&(o=o.slice(1,-1)),yield[s,o]}}function In(r){let e=new Set,t=/process\.env\.([A-Za-z_$][\w$]*)|process\.env\[\s*['"]([^'"]+)['"]\s*\]/g;for(let n;n=t.exec(r);)e.add(n[1]??n[2]);return[...e]}function ft(r,e,t){let{sources:n,mode:s,loaded:o}=r,i=process.cwd(),a=U.dirname(e),c=`(mode: ${s??"none"})`,l=t?In(t):[],p=l.filter(m=>n[m]).map(m=>`${m} \u2190 ${n[m]}`);p.length?console.log(`env: ${p.join(", ")} ${c}`):o.length&&console.log(`env: loaded ${o.join(", ")} ${c}`),s&&!o.some(m=>m===`.env.${s}`||m===`.env.${s}.local`)&&console.log(`env: mode=${s} \u2014 no .env.${s} found; using .env`);let d=U.resolve(a)!==U.resolve(i);if(d)for(let m of[".env.local",".env"])Cn(U.join(a,m))&&console.log(`env: ${U.join(a,m)} present but not loaded (cwd is ${i})`);let h=l.filter(m=>process.env[m]===void 0);if(h.length){let m=d?` \u2014 try running from ${a}`:"";console.log(`env: server.ts reads ${h.join(", ")} but ${h.length>1?"they are":"it's"} unset${m}`)}}import*as G from"fs/promises";import*as et from"path";import{pathToFileURL as ws}from"url";var $n={code:{path:"code.tsx",language:"typescript"},css:{path:"styles.css",language:"css"},html:{path:"index.html",language:"html"},config:{path:"config.json",language:"json"},notes:{path:"notes.md",language:"markdown"},data:{path:"data.txt",language:"text"},infer:{path:"infer.md",language:"markdown"},insight:{path:"insight.json",language:"json"},server:{path:"server.ts",language:"typescript"}};function ar(r){try{let e=r.split(`
|
|
87
88
|
`),t=0;if(e[t]?.trim()!=="---")return null;t++;let n=[];for(;t<e.length&&e[t]?.trim()!=="---";)n.push(e[t]),t++;if(e[t]?.trim()!=="---")return null;t++;let s=Dn(n);if(!s)return null;let o=new Map;for(;t<e.length;){let a=e[t]?.trim()?.match(/^\*\*(.+)\*\*$/);if(a){let c=a[1].trim();for(t++;t<e.length&&e[t]?.trim()==="";)t++;let l=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!l){t++;continue}let p=l[1];t++;let d=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${p}\\s*$`));)d.push(e[t]),t++;t++,o.set(c,d.join(`
|
|
88
|
-
`))}else t++}return{frontmatter:s,files:o}}catch{return null}}function Dn(r){let e={};for(let t of r){let n=t.indexOf(":");if(n===-1)continue;let s=t.slice(0,n).trim(),o=t.slice(n+1).trim();switch(s){case"format":e.format=o;break;case"name":e.name=Fn(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function Fn(r){return r.startsWith('"')&&r.endsWith('"')?r.slice(1,-1).replace(/\\"/g,'"'):r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function cr(r){let e=t=>r.files.get($n[t].path)||"";return{name:r.frontmatter.name,code:e("code"),css:e("css"),html:e("html"),config:e("config"),notes:e("notes"),data:e("data"),infer:e("infer"),insight:e("insight"),server:e("server")}}function Mn(r){try{return JSON.parse(r),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(r)||/^---\s*$/m.test(r)||/^\w[\w\s]*:[ \t]/m.test(r))}function lr(r){let e=r.trim();return e?Mn(e)?[e]:r.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function dr(r){if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}import{transform as jn}from"sucrase";function ht(r,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:n}=jn(r,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:n}}catch(n){return{code:"",error:String(n)}}}var ye="https://esm.sh",be="https://cdn.jsdelivr.net/npm/",mt="https://data.jsdelivr.com/v1/package/npm/";function ur(r){let e=(r||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var b=class r{constructor(e,t,n){let s=typeof e=="string"?r.parse(e):e;this.name=s.name,this.version=oe(t??s.version),this.subpath=oe(n??s.subpath)}static parse(e){let t=ur(e||"");if(!t.length)return new r({name:""});if(t[0].startsWith("@")){let s=t[0],[o,i]=pr(t[1]??""),a=oe(t.slice(2).join("/"));return new r({name:`${s}/${o}`,version:i,subpath:a})}else{let[s,o]=pr(t[0]),i=oe(t.slice(1).join("/"));return new r({name:s,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),n=new URL(ye).host,s=new URL(be).host;if(t.host===n){let o=ur(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return r.parse(i)}if(t.host===s){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return r.parse(i)}return}catch{return}}static versionFromUrl(e){return r.fromUrl(e)?.version}format(){let e=this.version?`${this.name}@${this.version}`:this.name;return this.subpath?`${e}/${this.subpath}`:e}root(){return this.name}static rootOf(e){return r.parse(e).name}withVersion(e){return new r({name:this.name,version:oe(e),subpath:this.subpath})}withPreferredVersion(e,t){let n=e||t;return n?this.withVersion(n):this}static isBare(e){if(!e||e.startsWith(".")||e.startsWith("/"))return!1;let t=e.toLowerCase();return!t.startsWith("http://")&&!t.startsWith("https://")}},oe=r=>r&&r.length?r:void 0,pr=r=>{let e=r.indexOf("@");return e<0?[r,void 0]:[r.slice(0,e),oe(r.slice(e+1))]};async function T(r){try{return await r()}catch{return}}var ve=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=ye,this.jsDelivrBase=be,this.jsDelivrMeta=mt,this.pinMs=1e4,this.versionsIndexMs=1440*60*1e3,this.metaTtlMs=10080*60*1e3,this.pinCache=new Map}normalizeRelative(e){let t=e||"";return t.startsWith("./")?t.slice(2):t.replace(/^\/+/,"")}ensureLeadingDotSlash(e){return e.startsWith("./")?e:`./${e}`}baseDir(e){let t=typeof e=="string"?new b(e):e;return`${this.jsDelivrBase}${t.name}${t.version?`@${t.version}`:""}/`}file(e,t){return new URL(this.normalizeRelative(t),this.baseDir(e)).toString()}packageJson(e){return this.file(e,"package.json")}buildEsmUrl(e,t={}){let{target:n="es2022",bundle:s=!1,external:o}=t,i=new URLSearchParams({target:n});return s&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let n=this.buildEsmUrl(e,{target:t}),s=await T(()=>this.http.head(n));return s?.ok?s.url||n:void 0}async resolveExactVersion(e){let t=Date.now(),n=this.pinCache.get(e);if(n&&t-n.ts<this.pinMs)return n.value;let s=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:s,ts:t}),s}async tryResolveFromUrls(e){for(let t of e){let n=await T(()=>this.http.head(t)),s=this.parseVersionFromUrl(n?.url||t);if(s)return s}}async fetchVersionsIndex(e){if(await this.cache.isNegative(e))return;let t=await this.cache.getIndex(e);if(t&&Date.now()-t.updatedAt<this.versionsIndexMs)return{versions:t.versions,distTags:t.distTags};let n=await T(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!n?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let s=n.distTags&&Object.keys(n.distTags).length?n.distTags:void 0;return await this.cache.setIndex(e,n.versions,s),n}parseVersionFromUrl(e){let t=b.fromUrl(e)?.version;return t&&/\d+\.\d+\.\d+/.test(t)?t:void 0}async fetchPackageMeta(e,t){let n=await this.cache.getMeta(e,t);if(n&&Date.now()-n.updatedAt<this.metaTtlMs){let{dependencies:p,peerDependencies:d,peerDependenciesMeta:h}=n;return{name:e,version:t,dependencies:p,peerDependencies:d,peerDependenciesMeta:h}}let s=this.packageJson(new b(`${e}@${t}`)),o=await T(()=>this.http.getJson(s));if(!o)return;let i=p=>p&&Object.keys(p).length?p:void 0,a=i(o.dependencies),c=i(o.peerDependencies),l=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,a,c,l),{name:e,version:t,dependencies:a,peerDependencies:c,peerDependenciesMeta:l}}};var fr=r=>r.startsWith("@types/"),we=r=>Object.keys(r?.peerDependencies||{}).filter(e=>!fr(e)),gt=r=>Object.keys(r?.dependencies||{}).filter(e=>!fr(e)),Nn=r=>we(r).filter(e=>!r?.peerDependenciesMeta?.[e]?.optional),xe=class{constructor(e){this.cdn=e}async resolve(e,t){let n=await this.fetchMeta(e),{allRoots:s,autoAddedPeers:o}=await this.expandWithPeers(n,t),i=this.computeFlags(s);return{allRoots:s,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:n})=>({name:t,version:n,meta:await this.cdn.fetchPackageMeta(t,n)})))}async expandWithPeers(e,t){let n=new Map(e.map(o=>[o.name,o])),s=[];for(let o of e)for(let i of Nn(o.meta))!n.has(i)&&!s.some(a=>a.name===i)&&s.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of s)try{let a=await t(o),c=await this.cdn.fetchPackageMeta(o,a);n.set(o,{name:o,version:a,meta:c})}catch(a){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,a)}return{allRoots:[...n.values()],autoAddedPeers:s.filter(o=>n.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>we(o.meta))),n=new Map;for(let o of e)for(let i of gt(o.meta))n.set(i,(n.get(i)||0)+1);let s=new Set([...n.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:we(o.meta).length>0,isSharedDep:s.has(o.name)}]))}};var Se=class{constructor(e,t,n){this.cache=e,this.cdn=t,this.semver=n}selectVersionFromIndex(e,t,n){return this.semver.selectBestVersion(e,{range:t,distTags:n})}async learnExactVersion(e){let t=await T(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let n=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(n)return n}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let n=await this.cache.getPinnedExact(e,t);if(n){if(this.semver.isExactVersion(n))return n;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",n)}let s=await T(()=>this.cdn.fetchVersionsIndex(e));if(s?.versions?.length){let i=this.selectVersionFromIndex(s.versions,t,s.distTags);if(i){if(this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let a=await T(()=>this.cdn.fetchVersionsIndex(e));if(a?.versions?.length){let c=this.selectVersionFromIndex(a.versions,t,a.distTags);if(c&&this.semver.isExactVersion(c))return await this.cache.setPinnedExact(e,t,c),c}}}let o=await this.cdn.resolveExactVersion(`${e}@${t}`);if(o&&this.semver.isExactVersion(o))return await this.cache.setPinnedExact(e,t,o),o}async effectivePackage(e,t){let n=new b(e),s=n.root(),o=t[s],i=o?await T(()=>this.cache.getPinnedExact(s,o))??await T(()=>this.resolveExactForRoot(s,o)):void 0;return{effectivePackage:i?n.withVersion(i).format():e,root:s,range:o,pinned:i}}};import{init as Ln,parse as Bn}from"es-module-lexer";var ie=class r{constructor(e,t,n,s){this.version=e,this.cdn=t,this.peer=n,this.cache=s}extractImportsSync(e){let t=new Set;for(let n of r.importPatterns){n.lastIndex=0;for(let s of e.matchAll(n))b.isBare(s[1])&&t.add(s[1])}return Array.from(t)}async extractImports(e){let t=new Set,n=s=>{b.isBare(s)&&t.add(s)};try{await Ln;let[s]=Bn(e);s.forEach(o=>n(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t,n){let s=(await this.extractImports(e)).filter(d=>!n?.has(b.rootOf(d))),o=[...new Set(s.map(b.rootOf))],i=await Promise.all(o.map(async d=>({name:d,version:await this.resolveVersion(d,t)}))),{allRoots:a,flags:c,autoAddedPeers:l}=await this.peer.resolve(i,d=>this.resolveVersion(d,t)),p=this.buildEntries([...s,...l.map(d=>d.name)],a,c,t);return{importMap:{imports:Object.fromEntries(p)},prefetchUrls:p.map(([,d])=>d)}}async resolveVersion(e,t){let n=t[e],s=n?`${e}@${n}`:e,o=await this.version.resolveExactForRoot(e,n);if(!o){let i=await T(()=>this.cdn.pinEsmUrl(s));if(!i)throw new Error(`Cannot resolve ${s}: no matching version is published (the package or version may not exist, or the registry was unreachable).`);o=b.versionFromUrl(i),o&&n&&await T(()=>this.cache.setPinnedExact(e,n,o))}if(!o)throw new Error(`Cannot resolve ${s}: no concrete version found.`);return o}buildEntries(e,t,n,s){let o=new Map(t.map(g=>[g.name,g])),i=g=>{let R=o.get(b.rootOf(g));return new b(g).withPreferredVersion(R.version,s[R.name]).format()},a=new Set([...n.entries()].filter(([,g])=>g.isPeerRoot||g.isSharedDep).map(([g])=>g)),c=new Set(e.filter(g=>g!==b.rootOf(g)).map(b.rootOf)),l=[],p=new Set,d=new Set(e.filter(g=>g===b.rootOf(g))),h=new Set;for(let g of e){let R=b.rootOf(g),j=o.get(R),{isPeerRoot:B,hasPeers:C,isSharedDep:u}=n.get(R),f=c.has(R),y=g!==R,v=!(B||u)&&(f||!C),_=this.singletonDepsOf(j,a),H=y&&d.has(R);H&&h.add(R);let N=H?[..._,R]:_.length?_:void 0;l.push([g,this.cdn.buildEsmUrl(i(g),{bundle:v,external:N})]),p.add(g)}let m=new Set([...a,...h]);for(let g of m)o.has(g)&&(p.has(g)||l.push([g,this.cdn.buildEsmUrl(i(g),{})]),l.push([`${g}/`,`${this.cdn.esmHost}/${i(g)}/`]));return l}singletonDepsOf(e,t){return[...new Set([...we(e.meta),...gt(e.meta)])].filter(n=>t.has(n))}};ie.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as hr,satisfies as Un,maxSatisfying as yt,major as Wn,prerelease as Jn,rsort as Hn,valid as Vn}from"semver";var Be=class{cmp(e,t){return e===t?0:hr(e,t)?1:hr(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Un(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let n=yt(e,t,{includePrerelease:!0});return n===null?void 0:n}pickLatest(e){return e?.length?Hn(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let n=t?.range?.trim()||"*",s=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(n,o))return o;if(s){let a=yt(e,n,{includePrerelease:!1});if(a)return a}return yt(e,n,{includePrerelease:!0})??void 0}majorOf(e){return Wn(e)}isPrerelease(e){return Jn(e)!==null}isExactVersion(e){return Vn(e)!==null}},X=new Be;function mr(r,e){let t=new ve(r,e),n=new xe(t),s=new Se(r,t,X);return{packageService:new ie(s,t,n,r),versionResolver:s,cdnClient:t,peerResolver:n}}import*as Ar from"fs/promises";import*as D from"path";var bt=[{name:"es5"},{name:"es2015.core"},{name:"es2015.collection"},{name:"es2015.promise"},{name:"es2015.iterable"},{name:"es2015.symbol"},{name:"es2015.symbol.wellknown"},{name:"es2015.generator"},{name:"es2015.proxy"},{name:"es2015.reflect"},{name:"es2016.array.include"},{name:"es2016.intl"},{name:"es2017.object"},{name:"es2017.string"},{name:"es2017.sharedmemory"},{name:"es2017.typedarrays"},{name:"es2017.date"},{name:"es2017.intl"},{name:"es2018.asynciterable"},{name:"es2018.asyncgenerator"},{name:"es2018.promise"},{name:"es2018.regexp"},{name:"es2018.intl"},{name:"es2019.array"},{name:"es2019.object"},{name:"es2019.string"},{name:"es2019.symbol"},{name:"es2019.intl"},{name:"es2020.bigint"},{name:"es2020.promise"},{name:"es2020.string"},{name:"es2020.sharedmemory"},{name:"es2020.date"},{name:"es2020.number"},{name:"es2020.symbol.wellknown"},{name:"es2020.intl"},{name:"es2021.promise"},{name:"es2021.string"},{name:"es2021.weakref"},{name:"es2021.intl"},{name:"es2022.array"},{name:"es2022.object"},{name:"es2022.error"},{name:"es2022.string"},{name:"es2022.regexp"},{name:"es2022.intl"},{name:"es2023.array"},{name:"es2023.collection"},{name:"es2023.intl",since:"5.5"},{name:"es2024.arraybuffer",since:"5.5"},{name:"es2024.collection",since:"5.5"},{name:"es2024.object",since:"5.5"},{name:"es2024.promise",since:"5.5"},{name:"es2024.regexp",since:"5.5"},{name:"es2024.sharedmemory",since:"5.5"},{name:"es2024.string",since:"5.5"},{name:"esnext.array",since:"5.5"},{name:"esnext.collection"},{name:"esnext.decorators"},{name:"esnext.disposable"},{name:"esnext.error",since:"5.5"},{name:"esnext.float16",since:"5.5"},{name:"esnext.iterator",since:"5.5"},{name:"esnext.object"},{name:"esnext.promise"},{name:"esnext.sharedmemory",since:"5.5"},{name:"esnext.intl"}],vt=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var gr=`
|
|
89
|
+
`))}else t++}return{frontmatter:s,files:o}}catch{return null}}function Dn(r){let e={};for(let t of r){let n=t.indexOf(":");if(n===-1)continue;let s=t.slice(0,n).trim(),o=t.slice(n+1).trim();switch(s){case"format":e.format=o;break;case"name":e.name=Fn(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function Fn(r){return r.startsWith('"')&&r.endsWith('"')?r.slice(1,-1).replace(/\\"/g,'"'):r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function cr(r){let e=t=>r.files.get($n[t].path)||"";return{name:r.frontmatter.name,code:e("code"),css:e("css"),html:e("html"),config:e("config"),notes:e("notes"),data:e("data"),infer:e("infer"),insight:e("insight"),server:e("server")}}function Mn(r){try{return JSON.parse(r),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(r)||/^---\s*$/m.test(r)||/^\w[\w\s]*:[ \t]/m.test(r))}function lr(r){let e=r.trim();return e?Mn(e)?[e]:r.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function dr(r){if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}import{transform as jn}from"sucrase";function ht(r,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:n}=jn(r,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:n}}catch(n){return{code:"",error:String(n)}}}var be="https://esm.sh",ye="https://cdn.jsdelivr.net/npm/",mt="https://data.jsdelivr.com/v1/package/npm/";function ur(r){let e=(r||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var y=class r{constructor(e,t,n){let s=typeof e=="string"?r.parse(e):e;this.name=s.name,this.version=oe(t??s.version),this.subpath=oe(n??s.subpath)}static parse(e){let t=ur(e||"");if(!t.length)return new r({name:""});if(t[0].startsWith("@")){let s=t[0],[o,i]=pr(t[1]??""),a=oe(t.slice(2).join("/"));return new r({name:`${s}/${o}`,version:i,subpath:a})}else{let[s,o]=pr(t[0]),i=oe(t.slice(1).join("/"));return new r({name:s,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),n=new URL(be).host,s=new URL(ye).host;if(t.host===n){let o=ur(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return r.parse(i)}if(t.host===s){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return r.parse(i)}return}catch{return}}static versionFromUrl(e){return r.fromUrl(e)?.version}format(){let e=this.version?`${this.name}@${this.version}`:this.name;return this.subpath?`${e}/${this.subpath}`:e}root(){return this.name}static rootOf(e){return r.parse(e).name}withVersion(e){return new r({name:this.name,version:oe(e),subpath:this.subpath})}withPreferredVersion(e,t){let n=e||t;return n?this.withVersion(n):this}static isBare(e){if(!e||e.startsWith(".")||e.startsWith("/"))return!1;let t=e.toLowerCase();return!t.startsWith("http://")&&!t.startsWith("https://")}},oe=r=>r&&r.length?r:void 0,pr=r=>{let e=r.indexOf("@");return e<0?[r,void 0]:[r.slice(0,e),oe(r.slice(e+1))]};async function T(r){try{return await r()}catch{return}}var we=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=be,this.jsDelivrBase=ye,this.jsDelivrMeta=mt,this.pinMs=1e4,this.versionsIndexMs=1440*60*1e3,this.metaTtlMs=10080*60*1e3,this.pinCache=new Map}normalizeRelative(e){let t=e||"";return t.startsWith("./")?t.slice(2):t.replace(/^\/+/,"")}ensureLeadingDotSlash(e){return e.startsWith("./")?e:`./${e}`}baseDir(e){let t=typeof e=="string"?new y(e):e;return`${this.jsDelivrBase}${t.name}${t.version?`@${t.version}`:""}/`}file(e,t){return new URL(this.normalizeRelative(t),this.baseDir(e)).toString()}packageJson(e){return this.file(e,"package.json")}buildEsmUrl(e,t={}){let{target:n="es2022",bundle:s=!1,external:o}=t,i=new URLSearchParams({target:n});return s&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let n=this.buildEsmUrl(e,{target:t}),s=await T(()=>this.http.head(n));return s?.ok?s.url||n:void 0}async resolveExactVersion(e){let t=Date.now(),n=this.pinCache.get(e);if(n&&t-n.ts<this.pinMs)return n.value;let s=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:s,ts:t}),s}async tryResolveFromUrls(e){for(let t of e){let n=await T(()=>this.http.head(t)),s=this.parseVersionFromUrl(n?.url||t);if(s)return s}}async fetchVersionsIndex(e){if(await this.cache.isNegative(e))return;let t=await this.cache.getIndex(e);if(t&&Date.now()-t.updatedAt<this.versionsIndexMs)return{versions:t.versions,distTags:t.distTags};let n=await T(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!n?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let s=n.distTags&&Object.keys(n.distTags).length?n.distTags:void 0;return await this.cache.setIndex(e,n.versions,s),n}parseVersionFromUrl(e){let t=y.fromUrl(e)?.version;return t&&/\d+\.\d+\.\d+/.test(t)?t:void 0}async fetchPackageMeta(e,t){let n=await this.cache.getMeta(e,t);if(n&&Date.now()-n.updatedAt<this.metaTtlMs){let{dependencies:p,peerDependencies:d,peerDependenciesMeta:h}=n;return{name:e,version:t,dependencies:p,peerDependencies:d,peerDependenciesMeta:h}}let s=this.packageJson(new y(`${e}@${t}`)),o=await T(()=>this.http.getJson(s));if(!o)return;let i=p=>p&&Object.keys(p).length?p:void 0,a=i(o.dependencies),c=i(o.peerDependencies),l=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,a,c,l),{name:e,version:t,dependencies:a,peerDependencies:c,peerDependenciesMeta:l}}};var fr=r=>r.startsWith("@types/"),ve=r=>Object.keys(r?.peerDependencies||{}).filter(e=>!fr(e)),gt=r=>Object.keys(r?.dependencies||{}).filter(e=>!fr(e)),Nn=r=>ve(r).filter(e=>!r?.peerDependenciesMeta?.[e]?.optional),xe=class{constructor(e){this.cdn=e}async resolve(e,t){let n=await this.fetchMeta(e),{allRoots:s,autoAddedPeers:o}=await this.expandWithPeers(n,t),i=this.computeFlags(s);return{allRoots:s,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:n})=>({name:t,version:n,meta:await this.cdn.fetchPackageMeta(t,n)})))}async expandWithPeers(e,t){let n=new Map(e.map(o=>[o.name,o])),s=[];for(let o of e)for(let i of Nn(o.meta))!n.has(i)&&!s.some(a=>a.name===i)&&s.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of s)try{let a=await t(o),c=await this.cdn.fetchPackageMeta(o,a);n.set(o,{name:o,version:a,meta:c})}catch(a){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,a)}return{allRoots:[...n.values()],autoAddedPeers:s.filter(o=>n.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>ve(o.meta))),n=new Map;for(let o of e)for(let i of gt(o.meta))n.set(i,(n.get(i)||0)+1);let s=new Set([...n.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:ve(o.meta).length>0,isSharedDep:s.has(o.name)}]))}};var Se=class{constructor(e,t,n){this.cache=e,this.cdn=t,this.semver=n}selectVersionFromIndex(e,t,n){return this.semver.selectBestVersion(e,{range:t,distTags:n})}async learnExactVersion(e){let t=await T(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let n=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(n)return n}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let n=await this.cache.getPinnedExact(e,t);if(n){if(this.semver.isExactVersion(n))return n;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",n)}let s=await T(()=>this.cdn.fetchVersionsIndex(e));if(s?.versions?.length){let i=this.selectVersionFromIndex(s.versions,t,s.distTags);if(i){if(this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let a=await T(()=>this.cdn.fetchVersionsIndex(e));if(a?.versions?.length){let c=this.selectVersionFromIndex(a.versions,t,a.distTags);if(c&&this.semver.isExactVersion(c))return await this.cache.setPinnedExact(e,t,c),c}}}let o=await this.cdn.resolveExactVersion(`${e}@${t}`);if(o&&this.semver.isExactVersion(o))return await this.cache.setPinnedExact(e,t,o),o}async effectivePackage(e,t){let n=new y(e),s=n.root(),o=t[s],i=o?await T(()=>this.cache.getPinnedExact(s,o))??await T(()=>this.resolveExactForRoot(s,o)):void 0;return{effectivePackage:i?n.withVersion(i).format():e,root:s,range:o,pinned:i}}};import{init as Ln,parse as Bn}from"es-module-lexer";var ie=class r{constructor(e,t,n,s){this.version=e,this.cdn=t,this.peer=n,this.cache=s}extractImportsSync(e){let t=new Set;for(let n of r.importPatterns){n.lastIndex=0;for(let s of e.matchAll(n))y.isBare(s[1])&&t.add(s[1])}return Array.from(t)}async extractImports(e){let t=new Set,n=s=>{y.isBare(s)&&t.add(s)};try{await Ln;let[s]=Bn(e);s.forEach(o=>n(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t,n){let s=(await this.extractImports(e)).filter(d=>!n?.has(y.rootOf(d))),o=[...new Set(s.map(y.rootOf))],i=await Promise.all(o.map(async d=>({name:d,version:await this.resolveVersion(d,t)}))),{allRoots:a,flags:c,autoAddedPeers:l}=await this.peer.resolve(i,d=>this.resolveVersion(d,t)),p=this.buildEntries([...s,...l.map(d=>d.name)],a,c,t);return{importMap:{imports:Object.fromEntries(p)},prefetchUrls:p.map(([,d])=>d)}}async resolveVersion(e,t){let n=t[e],s=n?`${e}@${n}`:e,o=await this.version.resolveExactForRoot(e,n);if(!o){let i=await T(()=>this.cdn.pinEsmUrl(s));if(!i)throw new Error(`Cannot resolve ${s}: no matching version is published (the package or version may not exist, or the registry was unreachable).`);o=y.versionFromUrl(i),o&&n&&await T(()=>this.cache.setPinnedExact(e,n,o))}if(!o)throw new Error(`Cannot resolve ${s}: no concrete version found.`);return o}buildEntries(e,t,n,s){let o=new Map(t.map(g=>[g.name,g])),i=g=>{let R=o.get(y.rootOf(g));return new y(g).withPreferredVersion(R.version,s[R.name]).format()},a=new Set([...n.entries()].filter(([,g])=>g.isPeerRoot||g.isSharedDep).map(([g])=>g)),c=new Set(e.filter(g=>g!==y.rootOf(g)).map(y.rootOf)),l=[],p=new Set,d=new Set(e.filter(g=>g===y.rootOf(g))),h=new Set;for(let g of e){let R=y.rootOf(g),j=o.get(R),{isPeerRoot:B,hasPeers:C,isSharedDep:u}=n.get(R),f=c.has(R),b=g!==R,w=!(B||u)&&(f||!C),_=this.singletonDepsOf(j,a),V=b&&d.has(R);V&&h.add(R);let N=V?[..._,R]:_.length?_:void 0;l.push([g,this.cdn.buildEsmUrl(i(g),{bundle:w,external:N})]),p.add(g)}let m=new Set([...a,...h]);for(let g of m)o.has(g)&&(p.has(g)||l.push([g,this.cdn.buildEsmUrl(i(g),{})]),l.push([`${g}/`,`${this.cdn.esmHost}/${i(g)}/`]));return l}singletonDepsOf(e,t){return[...new Set([...ve(e.meta),...gt(e.meta)])].filter(n=>t.has(n))}};ie.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as hr,satisfies as Un,maxSatisfying as bt,major as Wn,prerelease as Jn,rsort as Vn,valid as Hn}from"semver";var Be=class{cmp(e,t){return e===t?0:hr(e,t)?1:hr(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Un(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let n=bt(e,t,{includePrerelease:!0});return n===null?void 0:n}pickLatest(e){return e?.length?Vn(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let n=t?.range?.trim()||"*",s=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(n,o))return o;if(s){let a=bt(e,n,{includePrerelease:!1});if(a)return a}return bt(e,n,{includePrerelease:!0})??void 0}majorOf(e){return Wn(e)}isPrerelease(e){return Jn(e)!==null}isExactVersion(e){return Hn(e)!==null}},X=new Be;function mr(r,e){let t=new we(r,e),n=new xe(t),s=new Se(r,t,X);return{packageService:new ie(s,t,n,r),versionResolver:s,cdnClient:t,peerResolver:n}}import*as Ar from"fs/promises";import*as D from"path";var yt=[{name:"es5"},{name:"es2015.core"},{name:"es2015.collection"},{name:"es2015.promise"},{name:"es2015.iterable"},{name:"es2015.symbol"},{name:"es2015.symbol.wellknown"},{name:"es2015.generator"},{name:"es2015.proxy"},{name:"es2015.reflect"},{name:"es2016.array.include"},{name:"es2016.intl"},{name:"es2017.object"},{name:"es2017.string"},{name:"es2017.sharedmemory"},{name:"es2017.typedarrays"},{name:"es2017.date"},{name:"es2017.intl"},{name:"es2018.asynciterable"},{name:"es2018.asyncgenerator"},{name:"es2018.promise"},{name:"es2018.regexp"},{name:"es2018.intl"},{name:"es2019.array"},{name:"es2019.object"},{name:"es2019.string"},{name:"es2019.symbol"},{name:"es2019.intl"},{name:"es2020.bigint"},{name:"es2020.promise"},{name:"es2020.string"},{name:"es2020.sharedmemory"},{name:"es2020.date"},{name:"es2020.number"},{name:"es2020.symbol.wellknown"},{name:"es2020.intl"},{name:"es2021.promise"},{name:"es2021.string"},{name:"es2021.weakref"},{name:"es2021.intl"},{name:"es2022.array"},{name:"es2022.object"},{name:"es2022.error"},{name:"es2022.string"},{name:"es2022.regexp"},{name:"es2022.intl"},{name:"es2023.array"},{name:"es2023.collection"},{name:"es2023.intl",since:"5.5"},{name:"es2024.arraybuffer",since:"5.5"},{name:"es2024.collection",since:"5.5"},{name:"es2024.object",since:"5.5"},{name:"es2024.promise",since:"5.5"},{name:"es2024.regexp",since:"5.5"},{name:"es2024.sharedmemory",since:"5.5"},{name:"es2024.string",since:"5.5"},{name:"esnext.array",since:"5.5"},{name:"esnext.collection"},{name:"esnext.decorators"},{name:"esnext.disposable"},{name:"esnext.error",since:"5.5"},{name:"esnext.float16",since:"5.5"},{name:"esnext.iterator",since:"5.5"},{name:"esnext.object"},{name:"esnext.promise"},{name:"esnext.sharedmemory",since:"5.5"},{name:"esnext.intl"}],wt=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var gr=`
|
|
89
90
|
/**
|
|
90
91
|
* Get raw data chunk from the Data tab.
|
|
91
92
|
* @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
|
|
@@ -96,7 +97,7 @@ Examples:
|
|
|
96
97
|
* @param index - Chunk index (0-based)
|
|
97
98
|
* @throws If chunk is not valid JSON/JSON-ish
|
|
98
99
|
*/
|
|
99
|
-
json<T = unknown>(index: number): T;`,
|
|
100
|
+
json<T = unknown>(index: number): T;`,br=`
|
|
100
101
|
/**
|
|
101
102
|
* Get the insight data produced by the inference layer.
|
|
102
103
|
*
|
|
@@ -105,7 +106,7 @@ Examples:
|
|
|
105
106
|
*
|
|
106
107
|
* @returns The parsed insight JSON, or undefined if no insight is available
|
|
107
108
|
*/
|
|
108
|
-
insight<T = unknown>(): T | undefined;`,
|
|
109
|
+
insight<T = unknown>(): T | undefined;`,yr=`
|
|
109
110
|
/**
|
|
110
111
|
* General-purpose AI call.
|
|
111
112
|
*
|
|
@@ -122,7 +123,7 @@ Examples:
|
|
|
122
123
|
model?: string;
|
|
123
124
|
/** Enable/disable web search. Default: on for BYOK, always off for free model. */
|
|
124
125
|
webSearch?: boolean;
|
|
125
|
-
}): Promise<{ text: string }>;`,
|
|
126
|
+
}): Promise<{ text: string }>;`,wr=`
|
|
126
127
|
/**
|
|
127
128
|
* Returns AI models available to the current user.
|
|
128
129
|
* Models are filtered by the user's configured API keys.
|
|
@@ -137,7 +138,7 @@ Examples:
|
|
|
137
138
|
friendlyName: string;
|
|
138
139
|
/** Provider display name, e.g. "Anthropic" */
|
|
139
140
|
providerName: string;
|
|
140
|
-
}>>;`,qn="\n /**\n * The bulb's theme override (`<html data-theme>`).\n *\n * - Get: the current override \u2014 `'dark'` | `'light'`, or `undefined` when\n * following the OS preference.\n * - Set `'dark'`/`'light'` to force and persist it (per-bulb); set\n * `undefined` to clear the override and follow the OS again.\n *\n * Drives `<html data-theme>`, so render off `html[data-theme=\"\u2026\"]` selectors\n * (or observe the attribute) rather than reading `tb.theme`.\n */\n theme: 'light' | 'dark' | undefined;",
|
|
141
|
+
}>>;`,qn="\n /**\n * The bulb's theme override (`<html data-theme>`).\n *\n * - Get: the current override \u2014 `'dark'` | `'light'`, or `undefined` when\n * following the OS preference.\n * - Set `'dark'`/`'light'` to force and persist it (per-bulb); set\n * `undefined` to clear the override and follow the OS again.\n *\n * Drives `<html data-theme>`, so render off `html[data-theme=\"\u2026\"]` selectors\n * (or observe the attribute) rather than reading `tb.theme`.\n */\n theme: 'light' | 'dark' | undefined;",vr=`
|
|
141
142
|
/**
|
|
142
143
|
* The mode this bulb is running in.
|
|
143
144
|
*
|
|
@@ -236,7 +237,7 @@ Examples:
|
|
|
236
237
|
*
|
|
237
238
|
* @returns The full canonical URL
|
|
238
239
|
*/
|
|
239
|
-
url(): Promise<string>;`,
|
|
240
|
+
url(): Promise<string>;`,Yn=`
|
|
240
241
|
/**
|
|
241
242
|
* Server-side function proxy.
|
|
242
243
|
*
|
|
@@ -244,23 +245,23 @@ Examples:
|
|
|
244
245
|
* \`tb.server.log(...)\` is a built-in that prints to CLI stdout (falls back to console.log on web).
|
|
245
246
|
* User exports override built-ins of the same name.
|
|
246
247
|
*/
|
|
247
|
-
server: Record<string, (...args: any[]) => Promise<any>>;`,
|
|
248
|
+
server: Record<string, (...args: any[]) => Promise<any>>;`,vt=`
|
|
248
249
|
/**
|
|
249
250
|
* Typebulb utilities namespace.
|
|
250
251
|
* Type \`tb.\` to discover available helpers.
|
|
251
252
|
*/
|
|
252
|
-
declare const tb: {${gr}${Gn}${
|
|
253
|
+
declare const tb: {${gr}${Gn}${br}${Yn}${yr}${xr}${wr}${qn}${vr}
|
|
253
254
|
};
|
|
254
255
|
`,xt=`
|
|
255
256
|
/**
|
|
256
257
|
* Typebulb utilities namespace (server-side).
|
|
257
258
|
* Type \`tb.\` to discover available helpers.
|
|
258
259
|
*/
|
|
259
|
-
declare const tb: {${gr}${
|
|
260
|
+
declare const tb: {${gr}${br}${yr}${xr}${zn}${wr}${vr}
|
|
260
261
|
};
|
|
261
|
-
`;var Q=class{constructor(e){this.store=e}async isNegative(e){let t=await Ue(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let n=((await Ue(()=>this.store.get(e)))?.attempts||0)+1;await Ue(()=>this.store.set(e,{until:Date.now()+Yn(n),attempts:n}))}async clearNegative(e){await Ue(()=>this.store.delete(e))}};function Yn(r){return Math.min(9e5*Math.pow(2,Math.max(0,r-1)),864e5)}async function Ue(r){try{return await r()}catch{return}}import rs from"p-limit";import{resolve as Sr}from"resolve.exports";var ae=class{constructor(e){this.fetchDts=e}fetchDtsText(e){return this.tryUrls([e])}async tryUrls(e){for(let t of e){let n=await this.fetchDts(t);if(n&&(this.looksLikeDts(n.dts)||/\.(d\.ts|d\.mts)(?:[?#].*)?$/i.test(n.url)||/[?&]dts(?:[&#]|$)/i.test(n.url)))return n}}looksLikeDts(e){return/^\s*export\s*\{\s*\}\s*;?\s*$/m.test(e)?!0:/declare\s+(module|namespace|class|interface|function|const|var|let)/.test(e)||/interface\s+\w+/.test(e)||/type\s+\w+\s*=/.test(e)}};var V={maxRelativeTypeRefs:500,maxBareDeps:8,maxBareDepth:3,prefetchConcurrency:4,negativeTtlMs:1e4},Re=["index.d.ts","index.d.mts"],Pe=/\.d\.(ts|mts)$/i;function St(r){if(Pe.test(r))return!0;try{return new URL(r,"file://").search.includes("dts")}catch{return r.includes("?")&&r.includes("dts")}}function We(r){return[`${r}.d.ts`,`${r}.d.mts`]}async function Ee(r,{retries:e=2,timeoutMs:t=15e3,init:n}={}){for(let s=0;s<=e;s++){let o=new AbortController,i=setTimeout(()=>o.abort(),t);try{let a=await fetch(r,{...n,signal:o.signal});if(Xn(a.status)&&s<e)continue;return a}catch{if(s<e)continue;return}finally{clearTimeout(i)}}}function Xn(r){return r===408||r===429||r>=500&&r<600}var ke=class extends ae{constructor(e,t){super(e),this.cdnClient=t}async loadPackageAtVersionedRoot(e,t){let n=this.cdnClient.packageJson(new b({name:e,version:t})),s=await Ee(n);if(!s?.ok)return;let o;try{o=await s.json()}catch{return}if(o)return{pkg:o,baseDir:this.cdnClient.baseDir(new b({name:e,version:t??o.version})),version:t}}extractPathFromResult(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.find(t=>typeof t=="string")}async tryUntilSuccess(e,t){for(let n of e){let s=await t(n);if(s)return s}}async resolveFromSelected(e,t){if(e.kind==="types"){let s=this.cdnClient.normalizeRelative(e.path);if(!s||s==="/"||s===".")return this.tryUntilSuccess([...Re],t);if(!Pe.test(s)){let o=await this.tryUntilSuccess(this.declarationCandidatesFor(s),t);if(o)return o}return t(s)}let n=this.declarationCandidatesFor(e.path);return this.tryUntilSuccess([...Re,...n],t)}toResolutionResult(e){return{kind:Pe.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let n=t||".",s=e;try{let o=this.extractPathFromResult(Sr(s,n,{conditions:["types"]}));if(o)return o}catch{}try{return this.extractPathFromResult(Sr(s,n,{browser:!0,conditions:["import","default","module","browser","node"]}))}catch{return}}async resolve(e){try{let t=b.parse(e),{pkg:n,baseDir:s}=await this.loadPackageAtVersionedRoot(t.name,t.version)||{};if(!n||!s)return;let o={name:t.name,version:t.version},i=new b(o).format(),a=new b({...o,subpath:t.subpath}).format(),c=d=>this.fetchCandidateFrom(s,t.name,d);if(t.subpath){let d=this.cdnClient.ensureLeadingDotSlash(t.subpath),h=this.resolveExportsPath(n,d);if(h){let g=await this.resolveFromSelected(this.toResolutionResult(h),c);if(g)return{...g,resolvedPkg:a}}let m=await this.tryUntilSuccess(this.declarationCandidatesFor(d),c);if(m)return{...m,resolvedPkg:a}}let l=n.types??n.typings;if(l){let d=await this.resolveFromSelected({kind:"types",path:l},c);if(d)return{...d,resolvedPkg:i}}let p=this.resolveExportsPath(n,".");if(p){let d=await this.resolveFromSelected(this.toResolutionResult(p),c);if(d)return{...d,resolvedPkg:i}}return}catch{return}}async fetchCandidateFrom(e,t,n){let s=this.cdnClient.normalizeRelative(n),o=new URL(s,e).toString(),i=await this.fetchDtsText(o);return i?{dts:i.dts,url:i.url,resolvedPkg:t}:void 0}declarationCandidatesFor(e){if(!e||e==="./"||e==="/")return[...Re];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),n=We(t),s=t.endsWith("/")?t:`${t}/`;return n.push(...We(`${s}index`)),n}};import{gunzipSync as Qn}from"fflate";var ce=class{async fetchAndExtract(e,t){let n=this.getTarballUrl(e,t),s=await Ee(n,{timeoutMs:3e4});if(!s?.ok)return new Map;let o=new Uint8Array(await s.arrayBuffer());return this.extractDtsFiles(o)}getTarballUrl(e,t){return`https://registry.npmjs.org/${e.replace("/","%2F")}/-/${e.split("/").pop()}-${t}.tgz`}normalizeTarPath(e){let t=e.replace(/^package\//,""),n=t.indexOf("/");return n>0?t.substring(n+1):t}extractDtsFiles(e){let t=new Map;try{let n=Qn(e),s=new TextDecoder("utf-8"),o=0;for(;o<n.length-512;){let i=n.slice(o,o+512);if(i[0]===0)break;let a=i.slice(0,100),c=a.indexOf(0),l=s.decode(a.slice(0,c>0?c:100)).trim(),p=i.slice(124,136),d=s.decode(p).trim().replace(/\0/g,""),h=parseInt(d,8)||0,m=String.fromCharCode(i[156]);if(o+=512,(m==="0"||m==="\0")&&(l.endsWith(".d.ts")||l.endsWith(".d.mts"))){let g=n.slice(o,o+h);t.set(this.normalizeTarPath(l),s.decode(g))}o+=Math.ceil(h/512)*512}}catch{}return t}},Zn=new ce;var Te=class extends ae{constructor(e,t,n,s=new ce){super(e),this.cdnClient=t,this.cache=n,this.tarballFetcher=s}typesNameCandidates(e){let t=e.startsWith("@")?e.slice(1).replace("/","__"):e;return t.includes(".")?[t,t.split(".").join("-"),t.split(".").join("")]:[t]}selectTypesVersion(e,t,n){try{if(n){let o=X.majorOf(n),i=e.filter(a=>X.majorOf(a)===o);if(i.length)return i.sort((a,c)=>X.cmp(c,a))[0]}let s=t?.latest;return s&&e.includes(s)?s:e[0]}catch{return e[0]}}async fetchFromVersionedRoot(e,t){let n=new b(e),s=n.version;if(!s)return;let o;try{o=await this.tarballFetcher.fetchAndExtract(n.name,s)}catch{return}if(!o||o.size===0)return;for(let[a,c]of o.entries()){let l=this.cdnClient.file(e,a);try{await this.cache.setCachedFile(l,c)}catch{}}let i=t.subpath?[t.subpath+".d.ts",t.subpath+"/index.d.ts"]:["index.d.ts"];for(let a of i){let c=o.get(a);if(c)return{dts:c,url:this.cdnClient.file(e,a),resolvedPkg:t.subpath?new b(t).format():t.name}}}async resolve(e){let t=b.parse(e);if(t.name)for(let n of this.typesNameCandidates(t.name)){let s=`@types/${n}`,o;try{o=await this.cdnClient.fetchVersionsIndex(s)}catch{continue}if(!o?.versions?.length)continue;let i=this.selectTypesVersion(o.versions,o.distTags,t.version),a=await this.fetchFromVersionedRoot(`${s}@${i}`,t);if(a)return a}}};var _e=class{collectRelativeTypeRefs(e){return this.collectRefs(e).filter(t=>t.startsWith("./")||t.startsWith("../"))}collectBareModuleRefs(e){return this.collectRefs(e).filter(t=>this.isBare(t))}collectRefs(e){let t=new Set,n=(s,o)=>(t.add(s[o]),null);return this.matchAll(e,/(import|export)\s+[^'"\n]*from\s*['"]([^'"\n]+)['"]/,s=>n(s,2)),this.matchAll(e,/export\s*\*\s*from\s*['"]([^'"\n]+)['"]/,s=>n(s,1)),Array.from(t)}matchAll(e,t,n){let s=[];try{let o=new RegExp(t.source,"g"),i;for(;i=o.exec(e);){let a=n(i);a!==null&&s.push(a)}}catch{}return s}isBare(e){return!(e.startsWith("./")||e.startsWith("../")||e.startsWith("file:")||e.startsWith("http://")||e.startsWith("https://"))}};var Rr="file:///node_modules",Ce=class{constructor(){this.epoch=0,this.listeners=new Set}getEpoch(){return this.epoch}bumpEpoch(){this.epoch+=1;for(let e of this.listeners)try{e(this.epoch)}catch{}return this.epoch}onEpochChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}epochDir(){return`__tsepoch_${this.epoch}`}pathForMain(e){return`${Rr}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let n=es(t);return`${Rr}/${this.epochDir()}/${e}/${n}`}};function es(r){let e=r||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as ts}from"lru-cache";function Rt(r){let e=new ts({ttl:1e4,max:500}),t=new Map;return async function(s){try{if(await r.isNegative(s))return;let o=e.get(s);if(o&&Date.now()-o<1e4)return;let i=await r.getCachedFile(s);if(i)return{dts:i,url:s};let a=t.get(s);if(a)return a;let c=(async()=>{let l=await fetch(s,{cache:"no-store"});if(!l.ok){l.status===404&&(e.set(s,Date.now()),await r.recordNegative(s));return}let p=await l.text(),d=l.url||s;return await r.clearNegative(s),await r.setCachedFile(d,p),{dts:p,url:d}})();return t.set(s,c),await c.finally(()=>t.delete(s))}catch{return}}}var Je=class{constructor(e){this.inFlight=new Map,this.scanner=new _e,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=Rt(e.cache),this.typescriptProvider=new ke(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new Te(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new Ce}withInFlight(e,t){let n=this.inFlight.get(e);if(n)return n;let s=t().finally(()=>this.inFlight.delete(e));return this.inFlight.set(e,s),s}invalidate(){this.virtualFs.bumpEpoch(),this.inFlight.clear()}capArray(e,t){return e.length<=t?e:e.slice(0,t)}pushFileIfNew(e,t,n){e.some(s=>s.path===t)||e.push({path:t,content:n})}createStubDef(e){let t=this.virtualFs.pathForMain(e);return{pkg:e,mainPath:t,files:[{path:t,content:"export const _shim: any; export default _shim;"}],shims:[{module:e,path:t}]}}async trySubpathWithRootFallback(e,t){let n=new b(e);return n.subpath?this.fetchRootDts(n.name,t):void 0}async fetchViaProviders(e){for(let t of[this.typescriptProvider,this.definitelyTypedProvider])try{let n=await t.resolve(e);if(n?.dts)return n}catch{}}subpathsMatch(e,t){return new b(e).subpath===new b(t).subpath}async fetchRootDts(e,t){let{effectivePackage:n,root:s,pinned:o}=await this.versionResolver.effectivePackage(e,t),i=await this.cache.getCachedDts(n);if(i?.content){let c=i.url??this.cdnClient.file(o?`${s}@${o}`:s,"index.d.ts");return{dts:i.content,url:c,resolvedPkg:n}}let a;try{a=await this.fetchViaProviders(n)}catch{return}if(!(!a?.dts||!a.url)){try{await this.cache.setCachedFile(a.url,a.dts)}catch{}if(this.subpathsMatch(n,a.resolvedPkg||n)){try{await this.cache.setCachedDts(n,a.dts,a.url)}catch{}return a}}}extractPackageRootUrl(e){let t=e.pathname.match(/^(.+@[^/]+\/)/);return t?new URL(t[1],e.origin):new URL("./",e)}toVirtualPath(e,t,n){let s=t.pathname.startsWith(e.pathname)?t.pathname.slice(e.pathname.length):`__deps__/${encodeURIComponent(t.toString()).replace(/%/g,"_")}.d.ts`;return this.virtualFs.pathFor(n,s)}computeEntryPath(e,t){if(!e)return{mainPath:this.virtualFs.pathForMain(t),packageRootUrl:void 0};let n=new URL(e),s=this.extractPackageRootUrl(n);return{mainPath:this.toVirtualPath(s,n,t),packageRootUrl:s}}async expandRelativeRefs(e,t,n,s,o=new Set,i){if(!o.has(t)&&(o.add(t),!(o.size>V.maxRelativeTypeRefs)))try{let a=new URL(t),c=new URL("./",a);i??(i=this.extractPackageRootUrl(a));let l=this.capArray(this.scanner.collectRelativeTypeRefs(e),V.maxRelativeTypeRefs);for(let p of l)await this.tryRelativeRef(p,c,i,n,s,o)}catch{}}async tryRelativeRef(e,t,n,s,o,i){try{let a=new URL(e,t),c=a.pathname+a.search,l=St(c)?[c]:this.typescriptProvider.declarationCandidatesFor(c);for(let p of l){let h=new URL(p,a).toString();if(i.has(h))return;let m=await this.fetchDts(h);if(m?.dts){let g=this.toVirtualPath(n,new URL(m.url),s);this.pushFileIfNew(o,g,m.dts),await this.expandRelativeRefs(m.dts,m.url,s,o,i,n);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new b(e).name!==new b(t).name}ambientlyDeclares(e,t){for(let n of e.matchAll(/declare\s+module\s+['"]([^'"]+)['"]/g)){let s=n[1];if(s===t||s.endsWith("/*")&&t.startsWith(s.slice(0,-1)))return!0}return!1}markFileAmbient(e,t){let n=e.find(s=>s.path===t);n&&(n.ambient=!0)}async prefetchBareDeps(e,t,n,s,o){try{let i=this.capArray(this.scanner.collectBareModuleRefs(e),V.maxBareDeps).filter(l=>this.isDifferentPackage(l,t));if(!i.length)return;let a=new Set([t]),c=rs(V.prefetchConcurrency);await Promise.all(i.map(l=>c(()=>this.prefetchBareDepsRecursive(l,n,s,V.maxBareDepth,a,o).catch(()=>{}))))}catch{}}async prefetchBareDepsRecursive(e,t,n,s,o,i){if(s<=0||o.has(e))return;o.add(e);let a=await this.fetchRootDts(e,i);if(!a?.dts)return;let c=a.resolvedPkg||e,l=this.virtualFs.pathForMain(c);this.pushFileIfNew(t,l,a.dts),this.ambientlyDeclares(a.dts,e)?this.markFileAmbient(t,l):n.push({module:e,path:l}),a.url&&await this.expandRelativeRefs(a.dts,a.url,c,t);let p=this.capArray(this.scanner.collectBareModuleRefs(a.dts),V.maxBareDeps).filter(d=>!o.has(d));for(let d of p)await this.prefetchBareDepsRecursive(d,t,n,s-1,o,i)}async resolve(e,t,n){let s=await this.packageService.extractImports(e),o=n?[...s,...n]:s;return(await Promise.all(o.map(a=>this.resolveOne(a,t)))).filter(a=>!!a)}async resolveOne(e,t){let{effectivePackage:n}=await this.versionResolver.effectivePackage(e,t);return this.withInFlight(n,async()=>{let s=await this.fetchRootDts(e,t)??await this.trySubpathWithRootFallback(e,t);return s?this.buildDefFromContent(e,s,s.resolvedPkg||e,t):this.createStubDef(e)})}async buildDefFromContent(e,t,n,s){let{dts:o,url:i,resolvedPkg:a}=t,c=new b(a||n),l=c.version?`${c.name}@${c.version}`:c.name,{mainPath:p,packageRootUrl:d}=this.computeEntryPath(i,l),h=[{path:p,content:o}],m=[];i&&await this.expandRelativeRefs(o,i,l,h,void 0,d);let g=h.map(C=>C.content).join(`
|
|
262
|
-
`);await this.prefetchBareDeps(g,l,h,m,s);let R=c.format(),j=e===R?[e]:[e,R],B=j.some(C=>this.ambientlyDeclares(o,C));return B?this.markFileAmbient(h,p):m.push(...j.map(C=>({module:C,path:p}))),{pkg:e,mainPath:p,files:h,shims:m,ambient:B}}};function Pt(r){return new Je(r)}import*as L from"fs/promises";import*as W from"path";import*as kr from"os";import*as Et from"fs/promises";import*as Pr from"crypto";function $(r){return Pr.createHash("sha1").update(r).digest("hex")}async function Z(r){try{return JSON.parse(await Et.readFile(r,"utf8"))}catch{return}}async function
|
|
263
|
-
`,"utf8")}async function os(r){try{let e=await L.readFile(r,"utf8");return JSON.parse(e)}catch{return}}import*as z from"fs/promises";import*as Tr from"path";async function A(r,e){await z.mkdir(Tr.dirname(r),{recursive:!0});let t=`${r}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await z.writeFile(t,e,"utf8"),await z.rename(t,r).catch(async n=>{throw await z.rm(t,{force:!0}).catch(()=>{}),n})}var le=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=Z(this.filePath).then(e=>(this.mem=new Map(Object.entries(e??{})),this.mem))),this.loadPromise)}async get(e){return(await this.load()).get(e)}async set(e,t){let n=await this.load();n.set(e,t),await this.persist(n)}async delete(e){let t=await this.load();t.delete(e)&&await this.persist(t)}async persist(e){await A(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var Tt=D.join(Ae,"indexes"),_r=D.join(Ae,"pinned"),is=D.join(Ae,"meta"),as=D.join(Ae,"negative.json"),de=Symbol("missing"),Ge=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new Q(new le(as));async getPinnedExact(e,t){let n=`${e}@${t}`,s=this.pinnedMem.get(n);if(s!==void 0)return s===de?void 0:s;await x();let o=await
|
|
262
|
+
`;var Q=class{constructor(e){this.store=e}async isNegative(e){let t=await Ue(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let n=((await Ue(()=>this.store.get(e)))?.attempts||0)+1;await Ue(()=>this.store.set(e,{until:Date.now()+Kn(n),attempts:n}))}async clearNegative(e){await Ue(()=>this.store.delete(e))}};function Kn(r){return Math.min(9e5*Math.pow(2,Math.max(0,r-1)),864e5)}async function Ue(r){try{return await r()}catch{return}}import rs from"p-limit";import{resolve as Sr}from"resolve.exports";var ae=class{constructor(e){this.fetchDts=e}fetchDtsText(e){return this.tryUrls([e])}async tryUrls(e){for(let t of e){let n=await this.fetchDts(t);if(n&&(this.looksLikeDts(n.dts)||/\.(d\.ts|d\.mts)(?:[?#].*)?$/i.test(n.url)||/[?&]dts(?:[&#]|$)/i.test(n.url)))return n}}looksLikeDts(e){return/^\s*export\s*\{\s*\}\s*;?\s*$/m.test(e)?!0:/declare\s+(module|namespace|class|interface|function|const|var|let)/.test(e)||/interface\s+\w+/.test(e)||/type\s+\w+\s*=/.test(e)}};var H={maxRelativeTypeRefs:500,maxBareDeps:8,maxBareDepth:3,prefetchConcurrency:4,negativeTtlMs:1e4},Re=["index.d.ts","index.d.mts"],Pe=/\.d\.(ts|mts)$/i;function St(r){if(Pe.test(r))return!0;try{return new URL(r,"file://").search.includes("dts")}catch{return r.includes("?")&&r.includes("dts")}}function We(r){return[`${r}.d.ts`,`${r}.d.mts`]}async function Ee(r,{retries:e=2,timeoutMs:t=15e3,init:n}={}){for(let s=0;s<=e;s++){let o=new AbortController,i=setTimeout(()=>o.abort(),t);try{let a=await fetch(r,{...n,signal:o.signal});if(Xn(a.status)&&s<e)continue;return a}catch{if(s<e)continue;return}finally{clearTimeout(i)}}}function Xn(r){return r===408||r===429||r>=500&&r<600}var ke=class extends ae{constructor(e,t){super(e),this.cdnClient=t}async loadPackageAtVersionedRoot(e,t){let n=this.cdnClient.packageJson(new y({name:e,version:t})),s=await Ee(n);if(!s?.ok)return;let o;try{o=await s.json()}catch{return}if(o)return{pkg:o,baseDir:this.cdnClient.baseDir(new y({name:e,version:t??o.version})),version:t}}extractPathFromResult(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.find(t=>typeof t=="string")}async tryUntilSuccess(e,t){for(let n of e){let s=await t(n);if(s)return s}}async resolveFromSelected(e,t){if(e.kind==="types"){let s=this.cdnClient.normalizeRelative(e.path);if(!s||s==="/"||s===".")return this.tryUntilSuccess([...Re],t);if(!Pe.test(s)){let o=await this.tryUntilSuccess(this.declarationCandidatesFor(s),t);if(o)return o}return t(s)}let n=this.declarationCandidatesFor(e.path);return this.tryUntilSuccess([...Re,...n],t)}toResolutionResult(e){return{kind:Pe.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let n=t||".",s=e;try{let o=this.extractPathFromResult(Sr(s,n,{conditions:["types"]}));if(o)return o}catch{}try{return this.extractPathFromResult(Sr(s,n,{browser:!0,conditions:["import","default","module","browser","node"]}))}catch{return}}async resolve(e){try{let t=y.parse(e),{pkg:n,baseDir:s}=await this.loadPackageAtVersionedRoot(t.name,t.version)||{};if(!n||!s)return;let o={name:t.name,version:t.version},i=new y(o).format(),a=new y({...o,subpath:t.subpath}).format(),c=d=>this.fetchCandidateFrom(s,t.name,d);if(t.subpath){let d=this.cdnClient.ensureLeadingDotSlash(t.subpath),h=this.resolveExportsPath(n,d);if(h){let g=await this.resolveFromSelected(this.toResolutionResult(h),c);if(g)return{...g,resolvedPkg:a}}let m=await this.tryUntilSuccess(this.declarationCandidatesFor(d),c);if(m)return{...m,resolvedPkg:a}}let l=n.types??n.typings;if(l){let d=await this.resolveFromSelected({kind:"types",path:l},c);if(d)return{...d,resolvedPkg:i}}let p=this.resolveExportsPath(n,".");if(p){let d=await this.resolveFromSelected(this.toResolutionResult(p),c);if(d)return{...d,resolvedPkg:i}}return}catch{return}}async fetchCandidateFrom(e,t,n){let s=this.cdnClient.normalizeRelative(n),o=new URL(s,e).toString(),i=await this.fetchDtsText(o);return i?{dts:i.dts,url:i.url,resolvedPkg:t}:void 0}declarationCandidatesFor(e){if(!e||e==="./"||e==="/")return[...Re];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),n=We(t),s=t.endsWith("/")?t:`${t}/`;return n.push(...We(`${s}index`)),n}};import{gunzipSync as Qn}from"fflate";var ce=class{async fetchAndExtract(e,t){let n=this.getTarballUrl(e,t),s=await Ee(n,{timeoutMs:3e4});if(!s?.ok)return new Map;let o=new Uint8Array(await s.arrayBuffer());return this.extractDtsFiles(o)}getTarballUrl(e,t){return`https://registry.npmjs.org/${e.replace("/","%2F")}/-/${e.split("/").pop()}-${t}.tgz`}normalizeTarPath(e){let t=e.replace(/^package\//,""),n=t.indexOf("/");return n>0?t.substring(n+1):t}extractDtsFiles(e){let t=new Map;try{let n=Qn(e),s=new TextDecoder("utf-8"),o=0;for(;o<n.length-512;){let i=n.slice(o,o+512);if(i[0]===0)break;let a=i.slice(0,100),c=a.indexOf(0),l=s.decode(a.slice(0,c>0?c:100)).trim(),p=i.slice(124,136),d=s.decode(p).trim().replace(/\0/g,""),h=parseInt(d,8)||0,m=String.fromCharCode(i[156]);if(o+=512,(m==="0"||m==="\0")&&(l.endsWith(".d.ts")||l.endsWith(".d.mts"))){let g=n.slice(o,o+h);t.set(this.normalizeTarPath(l),s.decode(g))}o+=Math.ceil(h/512)*512}}catch{}return t}},Zn=new ce;var Te=class extends ae{constructor(e,t,n,s=new ce){super(e),this.cdnClient=t,this.cache=n,this.tarballFetcher=s}typesNameCandidates(e){let t=e.startsWith("@")?e.slice(1).replace("/","__"):e;return t.includes(".")?[t,t.split(".").join("-"),t.split(".").join("")]:[t]}selectTypesVersion(e,t,n){try{if(n){let o=X.majorOf(n),i=e.filter(a=>X.majorOf(a)===o);if(i.length)return i.sort((a,c)=>X.cmp(c,a))[0]}let s=t?.latest;return s&&e.includes(s)?s:e[0]}catch{return e[0]}}async fetchFromVersionedRoot(e,t){let n=new y(e),s=n.version;if(!s)return;let o;try{o=await this.tarballFetcher.fetchAndExtract(n.name,s)}catch{return}if(!o||o.size===0)return;for(let[a,c]of o.entries()){let l=this.cdnClient.file(e,a);try{await this.cache.setCachedFile(l,c)}catch{}}let i=t.subpath?[t.subpath+".d.ts",t.subpath+"/index.d.ts"]:["index.d.ts"];for(let a of i){let c=o.get(a);if(c)return{dts:c,url:this.cdnClient.file(e,a),resolvedPkg:t.subpath?new y(t).format():t.name}}}async resolve(e){let t=y.parse(e);if(t.name)for(let n of this.typesNameCandidates(t.name)){let s=`@types/${n}`,o;try{o=await this.cdnClient.fetchVersionsIndex(s)}catch{continue}if(!o?.versions?.length)continue;let i=this.selectTypesVersion(o.versions,o.distTags,t.version),a=await this.fetchFromVersionedRoot(`${s}@${i}`,t);if(a)return a}}};var _e=class{collectRelativeTypeRefs(e){return this.collectRefs(e).filter(t=>t.startsWith("./")||t.startsWith("../"))}collectBareModuleRefs(e){return this.collectRefs(e).filter(t=>this.isBare(t))}collectRefs(e){let t=new Set,n=(s,o)=>(t.add(s[o]),null);return this.matchAll(e,/(import|export)\s+[^'"\n]*from\s*['"]([^'"\n]+)['"]/,s=>n(s,2)),this.matchAll(e,/export\s*\*\s*from\s*['"]([^'"\n]+)['"]/,s=>n(s,1)),Array.from(t)}matchAll(e,t,n){let s=[];try{let o=new RegExp(t.source,"g"),i;for(;i=o.exec(e);){let a=n(i);a!==null&&s.push(a)}}catch{}return s}isBare(e){return!(e.startsWith("./")||e.startsWith("../")||e.startsWith("file:")||e.startsWith("http://")||e.startsWith("https://"))}};var Rr="file:///node_modules",Ce=class{constructor(){this.epoch=0,this.listeners=new Set}getEpoch(){return this.epoch}bumpEpoch(){this.epoch+=1;for(let e of this.listeners)try{e(this.epoch)}catch{}return this.epoch}onEpochChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}epochDir(){return`__tsepoch_${this.epoch}`}pathForMain(e){return`${Rr}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let n=es(t);return`${Rr}/${this.epochDir()}/${e}/${n}`}};function es(r){let e=r||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as ts}from"lru-cache";function Rt(r){let e=new ts({ttl:1e4,max:500}),t=new Map;return async function(s){try{if(await r.isNegative(s))return;let o=e.get(s);if(o&&Date.now()-o<1e4)return;let i=await r.getCachedFile(s);if(i)return{dts:i,url:s};let a=t.get(s);if(a)return a;let c=(async()=>{let l=await fetch(s,{cache:"no-store"});if(!l.ok){l.status===404&&(e.set(s,Date.now()),await r.recordNegative(s));return}let p=await l.text(),d=l.url||s;return await r.clearNegative(s),await r.setCachedFile(d,p),{dts:p,url:d}})();return t.set(s,c),await c.finally(()=>t.delete(s))}catch{return}}}var Je=class{constructor(e){this.inFlight=new Map,this.scanner=new _e,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=Rt(e.cache),this.typescriptProvider=new ke(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new Te(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new Ce}withInFlight(e,t){let n=this.inFlight.get(e);if(n)return n;let s=t().finally(()=>this.inFlight.delete(e));return this.inFlight.set(e,s),s}invalidate(){this.virtualFs.bumpEpoch(),this.inFlight.clear()}capArray(e,t){return e.length<=t?e:e.slice(0,t)}pushFileIfNew(e,t,n){e.some(s=>s.path===t)||e.push({path:t,content:n})}createStubDef(e){let t=this.virtualFs.pathForMain(e);return{pkg:e,mainPath:t,files:[{path:t,content:"export const _shim: any; export default _shim;"}],shims:[{module:e,path:t}]}}async trySubpathWithRootFallback(e,t){let n=new y(e);return n.subpath?this.fetchRootDts(n.name,t):void 0}async fetchViaProviders(e){for(let t of[this.typescriptProvider,this.definitelyTypedProvider])try{let n=await t.resolve(e);if(n?.dts)return n}catch{}}subpathsMatch(e,t){return new y(e).subpath===new y(t).subpath}async fetchRootDts(e,t){let{effectivePackage:n,root:s,pinned:o}=await this.versionResolver.effectivePackage(e,t),i=await this.cache.getCachedDts(n);if(i?.content){let c=i.url??this.cdnClient.file(o?`${s}@${o}`:s,"index.d.ts");return{dts:i.content,url:c,resolvedPkg:n}}let a;try{a=await this.fetchViaProviders(n)}catch{return}if(!(!a?.dts||!a.url)){try{await this.cache.setCachedFile(a.url,a.dts)}catch{}if(this.subpathsMatch(n,a.resolvedPkg||n)){try{await this.cache.setCachedDts(n,a.dts,a.url)}catch{}return a}}}extractPackageRootUrl(e){let t=e.pathname.match(/^(.+@[^/]+\/)/);return t?new URL(t[1],e.origin):new URL("./",e)}toVirtualPath(e,t,n){let s=t.pathname.startsWith(e.pathname)?t.pathname.slice(e.pathname.length):`__deps__/${encodeURIComponent(t.toString()).replace(/%/g,"_")}.d.ts`;return this.virtualFs.pathFor(n,s)}computeEntryPath(e,t){if(!e)return{mainPath:this.virtualFs.pathForMain(t),packageRootUrl:void 0};let n=new URL(e),s=this.extractPackageRootUrl(n);return{mainPath:this.toVirtualPath(s,n,t),packageRootUrl:s}}async expandRelativeRefs(e,t,n,s,o=new Set,i){if(!o.has(t)&&(o.add(t),!(o.size>H.maxRelativeTypeRefs)))try{let a=new URL(t),c=new URL("./",a);i??(i=this.extractPackageRootUrl(a));let l=this.capArray(this.scanner.collectRelativeTypeRefs(e),H.maxRelativeTypeRefs);for(let p of l)await this.tryRelativeRef(p,c,i,n,s,o)}catch{}}async tryRelativeRef(e,t,n,s,o,i){try{let a=new URL(e,t),c=a.pathname+a.search,l=St(c)?[c]:this.typescriptProvider.declarationCandidatesFor(c);for(let p of l){let h=new URL(p,a).toString();if(i.has(h))return;let m=await this.fetchDts(h);if(m?.dts){let g=this.toVirtualPath(n,new URL(m.url),s);this.pushFileIfNew(o,g,m.dts),await this.expandRelativeRefs(m.dts,m.url,s,o,i,n);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new y(e).name!==new y(t).name}ambientlyDeclares(e,t){for(let n of e.matchAll(/declare\s+module\s+['"]([^'"]+)['"]/g)){let s=n[1];if(s===t||s.endsWith("/*")&&t.startsWith(s.slice(0,-1)))return!0}return!1}markFileAmbient(e,t){let n=e.find(s=>s.path===t);n&&(n.ambient=!0)}async prefetchBareDeps(e,t,n,s,o){try{let i=this.capArray(this.scanner.collectBareModuleRefs(e),H.maxBareDeps).filter(l=>this.isDifferentPackage(l,t));if(!i.length)return;let a=new Set([t]),c=rs(H.prefetchConcurrency);await Promise.all(i.map(l=>c(()=>this.prefetchBareDepsRecursive(l,n,s,H.maxBareDepth,a,o).catch(()=>{}))))}catch{}}async prefetchBareDepsRecursive(e,t,n,s,o,i){if(s<=0||o.has(e))return;o.add(e);let a=await this.fetchRootDts(e,i);if(!a?.dts)return;let c=a.resolvedPkg||e,l=this.virtualFs.pathForMain(c);this.pushFileIfNew(t,l,a.dts),this.ambientlyDeclares(a.dts,e)?this.markFileAmbient(t,l):n.push({module:e,path:l}),a.url&&await this.expandRelativeRefs(a.dts,a.url,c,t);let p=this.capArray(this.scanner.collectBareModuleRefs(a.dts),H.maxBareDeps).filter(d=>!o.has(d));for(let d of p)await this.prefetchBareDepsRecursive(d,t,n,s-1,o,i)}async resolve(e,t,n){let s=await this.packageService.extractImports(e),o=n?[...s,...n]:s;return(await Promise.all(o.map(a=>this.resolveOne(a,t)))).filter(a=>!!a)}async resolveOne(e,t){let{effectivePackage:n}=await this.versionResolver.effectivePackage(e,t);return this.withInFlight(n,async()=>{let s=await this.fetchRootDts(e,t)??await this.trySubpathWithRootFallback(e,t);return s?this.buildDefFromContent(e,s,s.resolvedPkg||e,t):this.createStubDef(e)})}async buildDefFromContent(e,t,n,s){let{dts:o,url:i,resolvedPkg:a}=t,c=new y(a||n),l=c.version?`${c.name}@${c.version}`:c.name,{mainPath:p,packageRootUrl:d}=this.computeEntryPath(i,l),h=[{path:p,content:o}],m=[];i&&await this.expandRelativeRefs(o,i,l,h,void 0,d);let g=h.map(C=>C.content).join(`
|
|
263
|
+
`);await this.prefetchBareDeps(g,l,h,m,s);let R=c.format(),j=e===R?[e]:[e,R],B=j.some(C=>this.ambientlyDeclares(o,C));return B?this.markFileAmbient(h,p):m.push(...j.map(C=>({module:C,path:p}))),{pkg:e,mainPath:p,files:h,shims:m,ambient:B}}};function Pt(r){return new Je(r)}import*as L from"fs/promises";import*as W from"path";import*as kr from"os";import*as Et from"fs/promises";import*as Pr from"crypto";function $(r){return Pr.createHash("sha1").update(r).digest("hex")}async function Z(r){try{return JSON.parse(await Et.readFile(r,"utf8"))}catch{return}}async function Ve(r){try{return await Et.readFile(r,"utf8")}catch{return}}var Er=1,q=W.join(kr.homedir(),".typebulb","cache"),Ae=W.join(q,"packages"),Oe=W.join(q,"proxy"),He=W.join(q,"dts"),ns=W.join(q,"emit"),kt;function x(){return kt||(kt=ss()),kt}function qe(r,e){return W.join(ns,$(r),e)}async function ss(){await L.mkdir(q,{recursive:!0});let r=W.join(q,"version.json");if((await os(r))?.version===Er)return;let t=await L.readdir(q).catch(()=>[]);await Promise.all(t.map(n=>L.rm(W.join(q,n),{recursive:!0,force:!0}))),await L.writeFile(r,JSON.stringify({version:Er})+`
|
|
264
|
+
`,"utf8")}async function os(r){try{let e=await L.readFile(r,"utf8");return JSON.parse(e)}catch{return}}import*as z from"fs/promises";import*as Tr from"path";async function A(r,e){await z.mkdir(Tr.dirname(r),{recursive:!0});let t=`${r}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await z.writeFile(t,e,"utf8"),await z.rename(t,r).catch(async n=>{throw await z.rm(t,{force:!0}).catch(()=>{}),n})}var le=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=Z(this.filePath).then(e=>(this.mem=new Map(Object.entries(e??{})),this.mem))),this.loadPromise)}async get(e){return(await this.load()).get(e)}async set(e,t){let n=await this.load();n.set(e,t),await this.persist(n)}async delete(e){let t=await this.load();t.delete(e)&&await this.persist(t)}async persist(e){await A(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var Tt=D.join(Ae,"indexes"),_r=D.join(Ae,"pinned"),is=D.join(Ae,"meta"),as=D.join(Ae,"negative.json"),de=Symbol("missing"),Ge=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new Q(new le(as));async getPinnedExact(e,t){let n=`${e}@${t}`,s=this.pinnedMem.get(n);if(s!==void 0)return s===de?void 0:s;await x();let o=await Ve(D.join(_r,$(n)+".txt"));return this.pinnedMem.set(n,o??de),o}async setPinnedExact(e,t,n){let s=`${e}@${t}`;this.pinnedMem.set(s,n),await x(),await A(D.join(_r,$(s)+".txt"),n)}async getIndex(e){let t=this.indexMem.get(e);if(t!==void 0)return t===de?void 0:t;await x();let n=await Z(D.join(Tt,ze(e)+".json"));return this.indexMem.set(e,n??de),n}async setIndex(e,t,n){let s={versions:t,distTags:n,updatedAt:Date.now()};this.indexMem.set(e,s),await x(),await A(D.join(Tt,ze(e)+".json"),JSON.stringify(s))}async invalidateVersionsCache(e){this.indexMem.delete(e),await Ar.rm(D.join(Tt,ze(e)+".json"),{force:!0})}async isNegative(e){return await x(),this.negativeCache.isNegative(e)}async recordNegative(e){await x(),await this.negativeCache.recordNegative(e)}async clearNegative(e){await this.negativeCache.clearNegative(e)}async getMeta(e,t){let n=`${e}@${t}`,s=this.metaMem.get(n);if(s!==void 0)return s===de?void 0:s;await x();let o=await Z(Cr(e,t));return this.metaMem.set(n,o??de),o}async setMeta(e,t,n,s,o){let i={dependencies:n,peerDependencies:s,peerDependenciesMeta:o,updatedAt:Date.now()};this.metaMem.set(`${e}@${t}`,i),await x(),await A(Cr(e,t),JSON.stringify(i))}};function Cr(r,e){return D.join(is,ze(r),encodeURIComponent(e)+".json")}function ze(r){return r.replace(/\//g,"__")}var Or={async getJson(r){try{let e=await fetch(r,{redirect:"follow"});return e.ok?await e.json():void 0}catch{return}},async head(r){try{let e=await fetch(r,{method:"HEAD",redirect:"follow"});return{ok:e.ok,url:e.url}}catch{return}}};var cs=new Ge,{packageService:Ye,versionResolver:Ir,cdnClient:$r,peerResolver:Sa}=mr(cs,Or);var Dr=`
|
|
264
265
|
(() => {
|
|
265
266
|
// Embedded (bulb-in-a-bulb): runs inside a sandboxed iframe with no parent
|
|
266
267
|
// bridge, so privileged tb.* (AI, fs, server RPC) can't reach a host and would
|
|
@@ -621,7 +622,7 @@ ${d(t)}
|
|
|
621
622
|
}
|
|
622
623
|
});
|
|
623
624
|
})();
|
|
624
|
-
</script>`;function ds(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function us(r){let e={};for(let[t,n]of Object.entries(r))e[t]=n.startsWith("https://")?"/proxy/"+n:n;return e}import*as Xe from"fs/promises";import*as
|
|
625
|
+
</script>`;function ds(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function us(r){let e={};for(let[t,n]of Object.entries(r))e[t]=n.startsWith("https://")?"/proxy/"+n:n;return e}import*as Xe from"fs/promises";import*as Ke from"path";import{existsSync as Mr,readFileSync as ps}from"fs";import{execFile as fs}from"child_process";import{promisify as hs}from"util";import{satisfies as ms}from"semver";var gs=hs(fs);async function Qe(r,e,t){let s=r.map(i=>bs(i,t)).filter(i=>!ys(i,e));if(s.length===0)return;await Xe.mkdir(e,{recursive:!0});let o=Ke.join(e,"package.json");Mr(o)||await Xe.writeFile(o,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${s.join(", ")}`),await gs("npm",["install","--no-audit","--no-fund",...s],{cwd:e,shell:!0})}function bs(r,e){if(!e||Nr(r))return r;let t=e[r];return t?`${r}@${t}`:r}function ys(r,e){let t=Ke.join(e,"node_modules",jr(r));if(!Mr(t))return!1;let n=Nr(r);if(!n)return!0;try{let s=JSON.parse(ps(Ke.join(t,"package.json"),"utf-8")).version;return ms(s,n)}catch{return!1}}function Ze(r){let e=new Set,t=/\bimport\s+(?:[\s\S]*?\s+from\s+)?['"]([^./][^'"]*)['"]/g,n;for(;n=t.exec(r);){let s=n[1];if(s.includes(":"))continue;let o=s.startsWith("@")?s.split("/").slice(0,2).join("/"):s.split("/")[0];e.add(o)}return[...e]}function jr(r){if(r.startsWith("@")){let t=r.indexOf("/");if(t<0)return r;let n=r.indexOf("@",t+1);return n<0?r:r.slice(0,n)}let e=r.indexOf("@");return e<0?r:r.slice(0,e)}function Nr(r){let e=jr(r);return r.length>e.length?r.slice(e.length+1):""}async function Lr(r){let t=(await G.readdir(r)).find(n=>n.endsWith(".bulb.md"));return t?et.join(r,t):null}async function ue(r){let e=await G.readFile(r,"utf-8"),t=ar(e);if(!t)throw new Error("Invalid .bulb.md file format");let n=cr(t);return{bulb:n,config:dr(n.config)}}async function _t(r,e,t,n){let s=ht(r,{serverOnly:!0});if(s.error)throw new Error(`Server compilation error: ${s.error}`);let o=s.code;t&&(o=await sr(o,t));let i=et.join(e,".typebulb");await G.mkdir(i,{recursive:!0});let a=Ze(o);a.length>0&&await Qe(a,i,n);let c=et.join(i,"server.mjs");return await G.writeFile(c,o,"utf-8"),await import(`${ws(c).href}?t=${Date.now()}`)}async function Ct(r,e,t,n,s){let{bulb:o,config:i}=await ue(r),a=lr(o.data),c=ht(o.code,{jsxImportSource:i.jsxImportSource});c.error&&console.error("Compilation error:",c.error);let{importMap:l}=await Ye.buildImportMap(c.code,i.dependencies??{},n?new Set([n.name]):void 0);n&&(l.imports[n.name]=n.entryUrl);let p=Fr({name:o.name,code:c.code,css:o.css,html:o.html,data:a,insight:o.insight,importMap:l,watch:e}),d=null;return o.server&&t&&(d=await _t(o.server,s,n,i.dependencies)),{html:p,bulb:o,serverExports:d}}function At(r){if(r.server.trim())return"server-side code (server.ts)";let e=r.code;if(/\btb\s*\.\s*fs\b/.test(e)||e.includes("/__fs"))return"the filesystem";if(/\btb\s*\.\s*ai\b/.test(e)||e.includes("/__ai"))return"AI (your API keys)";if(/\btb\s*\.\s*server\s*\.\s*(?!log\b)\w/.test(e)||e.includes("/__api"))return"server-side code (server.ts)"}import{Hono as _s}from"hono";import{serve as Cs}from"@hono/node-server";import{streamSSE as As}from"hono/streaming";import*as re from"fs/promises";import*as M from"path";var O=class extends Error{constructor(e,t="unknown",n=!1){super(e),this.code=t,this.retryable=n}},F=class{getPath(e,t){return this.path}parseStreamChunk(e){return this.checkAndThrowError(e),this.parseProviderStreamChunk(e)}isReasoningEnabled(e){return e?.reasoning!==void 0&&e.reasoning>0}extractSystemMessages(e,t=`
|
|
625
626
|
|
|
626
627
|
`){let n=e.filter(s=>s.role==="system").map(s=>s.content);return{system:n.length?n.join(t):void 0,conversationMessages:e.filter(s=>s.role!=="system")}}parseJsonError(e,t,n=!1){if(!e)return{message:`HTTP ${t}`};try{let s=JSON.parse(e);if(s.error&&typeof s.error=="object"){let o={message:s.error.message||`HTTP ${t}`,type:s.error.type};return n&&(o.code=s.error.code),o}return s.message?{message:s.message}:{message:e}}catch{return{message:e}}}checkAndThrowError(e){if("type"in e&&e.type==="error"&&"message"in e){let t=e.message,n=e.code||"unknown",s=!!e.retryable;throw new O(t,n,s)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new O(t)}}extractErrorMessage(e){if(typeof e=="string")try{let t=JSON.parse(e);return t.error?.message||t.message||e}catch{return e}return typeof e=="object"&&e!==null?e.message||JSON.stringify(e):`${this.providerName} returned an error`}};var Ie=class extends F{constructor(){super(...arguments),this.providerName="Anthropic",this.defaultBaseUrl="https://api.anthropic.com",this.path="/v1/messages"}buildHeaders(e){return{"x-api-key":e,"anthropic-version":"2023-06-01","Content-Type":"application/json",Accept:"application/json"}}buildPayload(e,t,n,s){let{system:o,conversationMessages:i}=this.extractSystemMessages(e),a={model:t,max_tokens:this.getMaxTokens(t),messages:this.withLastMessageCached(i),stream:s};if(n?.webSearch!==!1&&(a.tools=[{type:"web_search_20250305",name:"web_search"}]),o&&(a.system=[{type:"text",text:o,cache_control:{type:"ephemeral"}}]),this.isReasoningEnabled(n)){let c=n.reasoning;if(this.isModernModel(t)){let l={0:"low",1:"low",2:"medium",3:"high"};a.thinking={type:"adaptive"},a.output_config={effort:l[c]}}else{let l={0:0,1:2048,2:4096,3:8192};a.thinking={type:"enabled",budget_tokens:l[c]}}}return a}parseError(e,t){return this.parseJsonError(e,t)}parseNonStreamingResponse(e){if(!this.isAnthropicResponse(e))return{text:""};let t=e.content.filter(s=>s.type==="text").map(s=>s.text).join(""),n=e.content.filter(s=>s.type==="thinking").map(s=>s.thinking).join(`
|
|
627
628
|
|
|
@@ -630,32 +631,32 @@ ${d(t)}
|
|
|
630
631
|
|
|
631
632
|
`)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var De=class extends F{constructor(){super(...arguments),this.providerName="Gemini",this.defaultBaseUrl="https://generativelanguage.googleapis.com",this.path="/v1beta/models"}getPath(e,t){return`/v1beta/models/${e}:${t?"streamGenerateContent":"generateContent"}${t?"?alt=sse":""}`}buildHeaders(e){return{"Content-Type":"application/json","x-goog-api-key":e}}buildPayload(e,t,n,s){let{system:o,conversationMessages:i}=this.extractSystemMessages(e,`
|
|
632
633
|
`),c={contents:i.map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.content}]}))};return n?.webSearch!==!1&&(c.tools=[{google_search:{}}]),o&&(c.systemInstruction={role:"system",parts:[{text:o}]}),this.isReasoningEnabled(n)&&(c.generationConfig={temperature:.7+n.reasoning*.1}),c}parseError(e,t){if(!e)return{message:`HTTP ${t}`};try{let n=JSON.parse(e),s=Array.isArray(n)?n[0]?.error:n?.error;return s&&typeof s=="object"?{message:(s.message||`HTTP ${t}`).split(`
|
|
633
|
-
`)[0],type:s.status,code:s.code?.toString()}:n.message?{message:n.message}:{message:e}}catch{return{message:e}}}parseNonStreamingResponse(e){if(this.checkGeminiError(e),!this.isGeminiResponse(e))return{text:"",status:"failed",error:"Invalid response format"};let t=this.extractText(e)||"",n=e.candidates?.[0]?.finishReason,s="complete";return n==="MAX_TOKENS"?s="interrupted":(n==="SAFETY"||n==="RECITATION")&&(s="failed"),{text:t,status:s}}parseProviderStreamChunk(e){if(this.checkGeminiError(e),!this.isGeminiResponse(e))return null;let t=this.extractText(e);return t?{text:t}:null}isGeminiResponse(e){return typeof e=="object"&&e!==null&&"candidates"in e&&Array.isArray(e.candidates)}extractText(e){let t=e.candidates?.[0];if(t?.content?.parts)return t.content.parts.map(n=>n.text).filter(Boolean).join("")}checkGeminiError(e){if(typeof e=="object"&&e!==null&&"error"in e){let t=e.error,n;if(typeof t=="string")n=t;else if(typeof t=="object"&&t!==null){let s=t;n=s.message||s.status||"Gemini returned an error"}else n="Gemini returned an error";throw new O(n)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new O(`Prompt blocked: ${t}`)}}};var Fe=class extends F{constructor(){super(...arguments),this.providerName="OpenRouter",this.defaultBaseUrl="https://openrouter.ai/api",this.path="/api/v1/chat/completions",this.effortMap={0:"low",1:"low",2:"medium",3:"high"}}buildHeaders(e,t){let n={Authorization:`Bearer ${e}`,"x-api-key":e,"Content-Type":"application/json",Accept:"application/json","X-Title":"Typebulb"};return t&&(n["HTTP-Referer"]=t,n.Referer=t,n.Origin=t),n}buildPayload(e,t,n,s){let o={model:t,messages:e,stream:s};return n?.webSearch===!0&&(o.plugins=[{id:"web"}]),this.isReasoningEnabled(n)&&(o.reasoning={effort:this.effortMap[n.reasoning]}),o}parseError(e,t){return this.parseJsonError(e,t,!0)}parseNonStreamingResponse(e){if(!this.hasChoices(e))return{text:""};let t=e.choices[0],n=t?.message?.content??t?.text??"",s=t?.message?.reasoning??e.reasoning;return{text:n,reasoning:s}}parseProviderStreamChunk(e){if(!this.hasChoices(e))return null;let t=e.choices[0];if(!t)return null;let n=t.delta||t.message;if(!n)return null;let s=n.content||void 0,o=n.reasoning||void 0;return!s&&!o?null:{text:s,reasoning:o}}hasChoices(e){return typeof e=="object"&&e!==null&&"choices"in e&&Array.isArray(e.choices)}};var
|
|
634
|
+
`)[0],type:s.status,code:s.code?.toString()}:n.message?{message:n.message}:{message:e}}catch{return{message:e}}}parseNonStreamingResponse(e){if(this.checkGeminiError(e),!this.isGeminiResponse(e))return{text:"",status:"failed",error:"Invalid response format"};let t=this.extractText(e)||"",n=e.candidates?.[0]?.finishReason,s="complete";return n==="MAX_TOKENS"?s="interrupted":(n==="SAFETY"||n==="RECITATION")&&(s="failed"),{text:t,status:s}}parseProviderStreamChunk(e){if(this.checkGeminiError(e),!this.isGeminiResponse(e))return null;let t=this.extractText(e);return t?{text:t}:null}isGeminiResponse(e){return typeof e=="object"&&e!==null&&"candidates"in e&&Array.isArray(e.candidates)}extractText(e){let t=e.candidates?.[0];if(t?.content?.parts)return t.content.parts.map(n=>n.text).filter(Boolean).join("")}checkGeminiError(e){if(typeof e=="object"&&e!==null&&"error"in e){let t=e.error,n;if(typeof t=="string")n=t;else if(typeof t=="object"&&t!==null){let s=t;n=s.message||s.status||"Gemini returned an error"}else n="Gemini returned an error";throw new O(n)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new O(`Prompt blocked: ${t}`)}}};var Fe=class extends F{constructor(){super(...arguments),this.providerName="OpenRouter",this.defaultBaseUrl="https://openrouter.ai/api",this.path="/api/v1/chat/completions",this.effortMap={0:"low",1:"low",2:"medium",3:"high"}}buildHeaders(e,t){let n={Authorization:`Bearer ${e}`,"x-api-key":e,"Content-Type":"application/json",Accept:"application/json","X-Title":"Typebulb"};return t&&(n["HTTP-Referer"]=t,n.Referer=t,n.Origin=t),n}buildPayload(e,t,n,s){let o={model:t,messages:e,stream:s};return n?.webSearch===!0&&(o.plugins=[{id:"web"}]),this.isReasoningEnabled(n)&&(o.reasoning={effort:this.effortMap[n.reasoning]}),o}parseError(e,t){return this.parseJsonError(e,t,!0)}parseNonStreamingResponse(e){if(!this.hasChoices(e))return{text:""};let t=e.choices[0],n=t?.message?.content??t?.text??"",s=t?.message?.reasoning??e.reasoning;return{text:n,reasoning:s}}parseProviderStreamChunk(e){if(!this.hasChoices(e))return null;let t=e.choices[0];if(!t)return null;let n=t.delta||t.message;if(!n)return null;let s=n.content||void 0,o=n.reasoning||void 0;return!s&&!o?null:{text:s,reasoning:o}}hasChoices(e){return typeof e=="object"&&e!==null&&"choices"in e&&Array.isArray(e.choices)}};var vs=new Map([["openai",new $e],["openrouter",new Fe],["anthropic",new Ie],["gemini",new De]]);function ee(r){let e=vs.get(r);if(!e)throw new Error(`Unsupported protocol: ${r}`);return e}async function Ot(r,e){let t=ee(r.protocol),n=t.getPath(e.model,e.stream),s=new URL(n,r.baseUrl).toString(),o=t.buildHeaders(r.apiKey,e.origin),i=t.buildPayload(e.messages,e.model,{reasoning:e.reasoning,webSearch:e.webSearch},e.stream);return e.modifyPayload?.(i),fetch(s,{method:"POST",headers:o,body:JSON.stringify(i),signal:e.signal})}async function It(r,e){let t=ee(e),n=await r.text().catch(()=>""),{message:s}=t.parseError(n,r.status),o=r.status,i="unknown";return o===429?i="rate_limit":o===413&&(i="context_exceeded"),{code:i,message:s,retryable:o===429}}function Br(r){let e=r.indexOf(`\r
|
|
634
635
|
\r
|
|
635
636
|
`),t=r.indexOf(`
|
|
636
637
|
|
|
637
638
|
`);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function $t(r){let t=r.split(/\r?\n/).filter(s=>s.startsWith("data:"));if(!t.length)return null;let n=t.map(s=>s.replace(/^data:\s?/,"")).join(`
|
|
638
|
-
`).trim();if(!n)return null;if(n==="[DONE]")return"done";try{return JSON.parse(n)}catch{return null}}async function Ur(r,e,t){let n=new TextDecoder,s="",o=!1,i=t?new Promise((a,c)=>{t.aborted&&c(new Error("Aborted")),t.addEventListener("abort",()=>c(new Error("Aborted")),{once:!0})}):null;for(;;){let a=i?await Promise.race([r.read(),i]):await r.read(),{done:c,value:l}=a;if(c){if(s.trim()){let h=$t(s);h!==null&&h!=="done"&&e(h)}break}o=!0,s+=n.decode(l,{stream:!0});let{pos:p,len:d}=Br(s);for(;p!==-1;){let h=s.slice(0,p);s=s.slice(p+d);let m=$t(h);if(m==="done"){s="";break}m!==null&&e(m),{pos:p,len:d}=Br(s)}}return{receivedAnyData:o}}async function Dt(r,e){let t=e??(r.headers.get("X-Provider-Protocol")||"openai"),n=ee(t);if(!r.body)throw new Error("Response body is missing");let s=r.body.getReader(),o="";return await Ur(s,i=>{let a=n.parseStreamChunk(i);a?.text&&(o+=a.text)}),o}import*as Ft from"fs/promises";import*as Me from"path";var tt=class{async get(e){let t=$(e),n=Me.join(Oe,t+".bin"),s=Me.join(Oe,t+".json");try{let[o,i]=await Promise.all([Ft.readFile(n),Ft.readFile(s,"utf8")]),a=JSON.parse(i);return{body:o,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await x();let n=$(e),s=Me.join(Oe,n+".bin"),o=Me.join(Oe,n+".json"),i={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([A(s,t.body),A(o,JSON.stringify(i))])}};import{readdir as Rs,readFile as
|
|
639
|
-
${c}`:"";return u.text(`Forbidden: this capability requires --trust.${
|
|
640
|
-
`,"utf8"),await k.writeFile(E.join(e,"code.tsx"),r.code,"utf8"),await k.writeFile(E.join(e,"tb.d.ts"),
|
|
641
|
-
`,"utf8"),{dir:e}}function Xs(r){let e={target:"es2023",module:"esnext",moduleResolution:"bundler",lib:["ES2023"],types:["node"],strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0};if(r?.typesAbs){let t=o=>o.replace(/\\/g,"/"),n=t(J.dirname(r.typesAbs)),s=t(r.typesAbs).replace(/\.d\.ts$/,"");e.baseUrl=".",e.paths={[r.name]:[s],[`${r.name}/*`]:[`${n}/*`]}}return{compilerOptions:e,include:["server.ts","tb.d.ts"]}}async function Qs(r,e){if(!
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
${
|
|
645
|
-
`
|
|
646
|
-
`);let c=new Kt;c.on("reload",async()=>{try{console.log("Re-running..."),await a()}catch(l){console.error("Error:",l)}}),Jt({bulbPath:r,emitter:c})}}async function mo(r,e,t,n,s){let o=process.cwd(),i=Gr(process.pid),a=e.watch?new Kt:void 0,c=pt(e.mode);console.log(`Loading ${S.basename(r)}...`);let{html:l,bulb:p,serverExports:d}=await Ct(r,e.watch,e.trust,n,s);ft(c,r,p.server);let h=await Wt(e.port),m=await tn({getHtml:()=>l,basePath:o,port:h,reloadEmitter:a,getServerExports:()=>d,localOverride:n?{name:n.name,serveDir:n.serveDir}:void 0,trusted:e.trust,trustHint:t}),g=`http://localhost:${h}`,R=e.trust?void 0:At(p);await Kr({pid:process.pid,port:h,url:g,file:r,startedAt:Date.now(),trust:e.trust,predicted:R}),console.log(`
|
|
639
|
+
`).trim();if(!n)return null;if(n==="[DONE]")return"done";try{return JSON.parse(n)}catch{return null}}async function Ur(r,e,t){let n=new TextDecoder,s="",o=!1,i=t?new Promise((a,c)=>{t.aborted&&c(new Error("Aborted")),t.addEventListener("abort",()=>c(new Error("Aborted")),{once:!0})}):null;for(;;){let a=i?await Promise.race([r.read(),i]):await r.read(),{done:c,value:l}=a;if(c){if(s.trim()){let h=$t(s);h!==null&&h!=="done"&&e(h)}break}o=!0,s+=n.decode(l,{stream:!0});let{pos:p,len:d}=Br(s);for(;p!==-1;){let h=s.slice(0,p);s=s.slice(p+d);let m=$t(h);if(m==="done"){s="";break}m!==null&&e(m),{pos:p,len:d}=Br(s)}}return{receivedAnyData:o}}async function Dt(r,e){let t=e??(r.headers.get("X-Provider-Protocol")||"openai"),n=ee(t);if(!r.body)throw new Error("Response body is missing");let s=r.body.getReader(),o="";return await Ur(s,i=>{let a=n.parseStreamChunk(i);a?.text&&(o+=a.text)}),o}import*as Ft from"fs/promises";import*as Me from"path";var tt=class{async get(e){let t=$(e),n=Me.join(Oe,t+".bin"),s=Me.join(Oe,t+".json");try{let[o,i]=await Promise.all([Ft.readFile(n),Ft.readFile(s,"utf8")]),a=JSON.parse(i);return{body:o,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await x();let n=$(e),s=Me.join(Oe,n+".bin"),o=Me.join(Oe,n+".json"),i={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([A(s,t.body),A(o,JSON.stringify(i))])}};import{readdir as Rs,readFile as Hr,writeFile as qr,unlink as je,mkdir as Ps}from"fs/promises";import{mkdirSync as Es,writeFileSync as Jr,appendFileSync as ks,readFileSync as zr}from"fs";import*as pe from"path";import{join as Mt,resolve as xs}from"path";import{homedir as Ss}from"os";function rt(){let r=process.env.TYPEBULB_SERVERS_DIR;return r?Mt(r,".."):Mt(Ss(),".typebulb")}function te(){return process.env.TYPEBULB_SERVERS_DIR||Mt(rt(),"servers")}function Y(r){let e=xs(r);return(process.platform==="win32"?e.toLowerCase():e).replace(/\\/g,"/")}function Wr(r,e){let t=Y(r),n=Y(e);return t.startsWith(n.endsWith("/")?n:n+"/")?!t.includes("/node_modules/"):!1}var Vr=1e6;function jt(r){return pe.join(te(),`${r}.json`)}function nt(r){return pe.join(te(),`${r}.log`)}function Gr(r){let e=nt(r);try{Es(te(),{recursive:!0}),Jr(e,"")}catch{return()=>{}}let t=process.stdout.write.bind(process.stdout),n=process.stderr.write.bind(process.stderr),s=0,o=!1,i=a=>{if(!o)try{let c=typeof a=="string"?Buffer.from(a,"utf8"):Buffer.from(a);if(ks(e,c),s+=c.length,s>2*Vr){let l=zr(e),p=l.subarray(Math.max(0,l.length-Vr));Jr(e,p),s=p.length}}catch{o=!0}};return process.stdout.write=((a,...c)=>(i(a),t(a,...c))),process.stderr.write=((a,...c)=>(i(a),n(a,...c))),()=>{process.stdout.write=t,process.stderr.write=n}}function Nt(r,e=0){try{let t=zr(nt(r)),n=e>=0&&e<=t.length?e:0;return{text:t.subarray(n).toString("utf8"),offset:t.length}}catch{return{text:"",offset:0}}}function Ts(r){try{return process.kill(r,0),!0}catch(e){return e.code==="EPERM"}}async function Yr(r){await Ps(te(),{recursive:!0}),await qr(jt(r.pid),JSON.stringify(r))}async function Kr(r,e){let t=jt(r);try{let n=JSON.parse(await Hr(t,"utf8"));if(n.denied===e)return;n.denied=e,await qr(t,JSON.stringify(n))}catch{}}async function Lt(r){await je(jt(r)).catch(()=>{}),await je(nt(r)).catch(()=>{})}async function fe(r){let e;try{e=await Rs(te())}catch{return[]}let t=[];return await Promise.all(e.map(async s=>{if(!s.endsWith(".json"))return;let o=pe.join(te(),s),i;try{i=JSON.parse(await Hr(o,"utf8"))}catch{await je(o).catch(()=>{});return}i&&typeof i.pid=="number"&&Ts(i.pid)?t.push(i):(await je(o).catch(()=>{}),i?.pid&&await je(nt(i.pid)).catch(()=>{}))})),(r?t.filter(s=>Wr(s.file,r)):t).sort((s,o)=>s.startedAt-o.startedAt)}async function Xr(r){try{process.kill(r,"SIGTERM")}catch{}await Lt(r)}var en="127.0.0.1",Os=new Set(["localhost","127.0.0.1","::1"]);function Is(r){if(r)try{return new URL(r.includes("://")?r:`http://${r}`).hostname}catch{return}}function Qr(r){let e=Is(r);return!!e&&Os.has(e)}function st(r){return r instanceof Error?r.message:"Unknown error"}async function tn(r){let{getHtml:e,basePath:t,port:n,reloadEmitter:s,getServerExports:o,localOverride:i,trusted:a=!1,trustHint:c}=r,l=new _s;l.use("*",async(u,f)=>{if(!Qr(u.req.header("host")))return u.text("Forbidden: untrusted Host",403);await f()}),l.use("*",async(u,f)=>{await f(),u.res.headers.set("Cross-Origin-Opener-Policy","same-origin"),u.res.headers.set("Cross-Origin-Embedder-Policy","credentialless")});let p=["/__fs/*","/__api/*","/__ai"],d=async(u,f)=>{if(!a){let b=new URL(u.req.url).pathname,v=b.startsWith("/__fs")?"the filesystem":b==="/__ai"?"AI (your API keys)":"server-side code (server.ts)";Kr(process.pid,v);let w=c?`
|
|
640
|
+
${c}`:"";return u.text(`Forbidden: this capability requires --trust.${w}`,403)}await f()},h=async(u,f)=>{let b=u.req.header("sec-fetch-site");if(b){if(b==="cross-site")return u.text("Forbidden: cross-site request",403)}else{let v=u.req.header("origin");if(v&&!Qr(v))return u.text("Forbidden: cross-origin request",403)}await f()};for(let u of p)l.use(u,d),l.use(u,h);l.use("/__log",h),l.post("/__log",async u=>{try{let{args:f}=await u.req.json();console.log(...f||[])}catch{}return u.json({ok:!0})}),l.get("/",u=>u.html(e())),l.post("/__fs/read",async u=>{try{let{path:f}=await u.req.json(),b=Ut(f,t),v=await re.readFile(b);return new Response(new Uint8Array(v),{headers:{"Content-Type":"application/octet-stream"}})}catch(f){let b=st(f);return u.json({error:b},400)}}),l.post("/__fs/write",async u=>{try{let f=u.req.query("path");if(!f)return u.json({error:"Missing path"},400);let b=Ut(f,t);return await re.mkdir(M.dirname(b),{recursive:!0}),await re.writeFile(b,Buffer.from(await u.req.arrayBuffer())),u.json({success:!0})}catch(f){let b=st(f);return u.json({error:b},400)}});let m={log:console.log};l.post("/__api/:name",async u=>{try{let f=o?.(),b=u.req.param("name"),v=f?.[b]??m[b];if(!v||typeof v!="function")return u.json({error:`API function '${b}' not found`},404);let{args:w}=await u.req.json(),_=await v(...w||[]);return u.json({result:_})}catch(f){let b=st(f);return u.json({error:b},500)}}),l.post("/__ai",async u=>{try{let{messages:f,system:b,reasoning:v,provider:w,model:_,webSearch:V}=await u.req.json();if(!f||!Array.isArray(f)||f.length===0)return u.json({message:"messages array is required",code:"unknown",retryable:!1},400);let N=$s(w,_);if(typeof N=="string")return u.json({message:N,code:"unknown",retryable:!1},400);let ct=[...b?[{role:"system",content:b}]:[],...f.map(Le=>({role:Le.role,content:Le.content}))],ne=await Ot(N,{model:N.model,messages:ct,stream:!0,reasoning:v??0,webSearch:V??!0});if(!ne.ok){let Le=await It(ne,N.protocol);return u.json(Le,ne.status)}let Kt=await Dt(ne,N.protocol);return Kt||console.warn("[tb.ai] Empty response from provider"),u.json({text:Kt})}catch(f){if(f instanceof O)return u.json({message:f.message,code:f.code,retryable:f.retryable},500);let b=st(f);return u.json({message:b,code:"unknown",retryable:!1},500)}}),l.get("/__models",async u=>{try{let f=await Ms();return u.json(f)}catch{return u.json([],200)}});let g=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"],R=new tt;if(l.get("/proxy/*",async u=>{let f=new URL(u.req.url),v=(f.pathname+f.search).slice(7),w=v.lastIndexOf("https://");return w===-1?u.text("Invalid proxy URL",400):j(u,v.slice(w))}),i){let u=`/local/${i.name}/`;l.get("/local/*",async f=>{let{pathname:b}=new URL(f.req.url);if(!b.startsWith(u))return f.text("Not Found",404);let v=decodeURIComponent(b.slice(u.length));try{let w=Ut(v,i.serveDir),_=await re.readFile(w);return new Response(_,{headers:{"Content-Type":js(w)}})}catch{return f.text("Not Found",404)}})}async function j(u,f){let b;try{b=new URL(f)}catch{return u.text("Invalid URL",400)}if(b.protocol!=="https:")return u.text("HTTPS only",400);if(!g.includes(b.hostname))return u.text("Host not allowed",403);let v=await R.get(f);if(v)return new Response(v.body,{status:200,headers:Bt(v.contentType,v.cacheControl)});try{let w=await fetch(f,{headers:{Accept:u.req.header("Accept")||"*/*"},redirect:"follow"});if(!w.ok)return u.text(`Upstream ${w.status}`,w.status);let _=w.headers.get("Content-Type")||void 0,V=w.headers.get("Cache-Control")||void 0;if(w.body){let[N,ct]=w.body.tee();return(async()=>{try{let ne=await new Response(ct).arrayBuffer();await R.set(f,{body:Buffer.from(ne),contentType:_,cacheControl:V})}catch{}})(),new Response(N,{status:w.status,headers:Bt(_,V)})}return new Response(null,{status:w.status,headers:Bt(_,V)})}catch(w){return u.text(`Proxy fetch failed: ${w instanceof Error?w.message:w}`,502)}}s&&l.get("/__reload",u=>As(u,async f=>{let b=()=>{f.writeSSE({event:"reload",data:""})};for(s.on("reload",b),f.onAbort(()=>{s.removeListener("reload",b)});;)await f.sleep(3e4)}));let B=/^\/(v\d+\/|stable\/|node\/|gh\/|@[^/]+\/[^@/]+@|[^@/]+@)/;l.notFound(async u=>{if(u.req.method!=="GET")return u.text("Not Found",404);let f=new URL(u.req.url);return B.test(f.pathname)?j(u,"https://esm.sh"+f.pathname+f.search):u.text("Not Found",404)});let C=Cs({fetch:l.fetch,port:n,hostname:en});return{port:n,close:()=>C.close()}}var rn={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function $s(r,e){let t=r??process.env.TB_AI_PROVIDER,n=e??process.env.TB_AI_MODEL;if(!t)return"No provider specified. Set TB_AI_PROVIDER in your .env file or pass provider in the tb.ai() call.";if(!n)return"No model specified. Set TB_AI_MODEL in your .env file or pass model in the tb.ai() call.";let s;try{s=ee(t)}catch{return`Unknown provider '${t}'.`}let o=rn[t],i=process.env[o];return i?{apiKey:i,baseUrl:s.defaultBaseUrl,protocol:t,model:n,isFreeModel:!1}:`No API key for '${t}'. Set ${o} in your .env file.`}var Ds="https://api.typebulb.com/api/models",Fs=1440*60*1e3,he=null;async function Ms(){if(!he||Date.now()-he.fetchedAt>Fs){let r=await fetch(Ds);if(!r.ok)return he?Zr(he.models):[];he={models:await r.json(),fetchedAt:Date.now()}}return Zr(he.models)}function Zr(r){let e=new Set(Object.entries(rn).filter(([,t])=>!!process.env[t]).map(([t])=>t));return r.filter(t=>e.has(t.provider))}function Bt(r,e){let t=new Headers;return r&&t.set("Content-Type",r),e&&t.set("Cache-Control",e),t.set("Access-Control-Allow-Origin","*"),t.set("Cross-Origin-Resource-Policy","cross-origin"),t}function js(r){switch(M.extname(r).toLowerCase()){case".js":case".mjs":return"text/javascript";case".wasm":return"application/wasm";case".json":case".map":return"application/json";default:return"application/octet-stream"}}function Ut(r,e){let t=M.resolve(e,r),n=M.normalize(e),s=M.normalize(t);if(s!==n&&!s.startsWith(n+M.sep))throw new Error("Path traversal detected - access denied");return t}async function Wt(r){let e=await import("net");return new Promise(t=>{let n=e.createServer();n.listen(r,en,()=>{let s=n.address(),o=typeof s=="object"&&s?s.port:r;n.close(()=>t(o))}),n.on("error",()=>{t(Wt(r+1))})})}import Ns from"open";async function nn(r){await Ns(r)}import sn from"chokidar";var on={persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}};function Jt(r){let{bulbPath:e,emitter:t}=r,n=sn.watch(e,on);return n.on("change",()=>{t.emit("reload")}),()=>n.close()}function an(r){let{dir:e,onChange:t,debounceMs:n=150}=r,s,o=sn.watch(e,on);return o.on("all",()=>{s&&clearTimeout(s),s=setTimeout(t,n)}),()=>{s&&clearTimeout(s),o.close()}}import*as k from"fs/promises";import*as E from"path";import*as me from"path";var Ls=me.join(He,"pkg"),Bs=me.join(He,"files"),Us=me.join(He,"negative.json"),it=class{pkgMem=new Map;fileMem=new Map;negativeCache=new Q(new le(Us));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await x();let t=await Z(cn(e));return this.pkgMem.set(e,t),t}async setCachedDts(e,t,n){let s={content:t,url:n};this.pkgMem.set(e,s),await ot(async()=>{await x(),await A(cn(e),JSON.stringify(s))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await x();let t=await Ve(ln(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await ot(async()=>{await x(),await A(ln(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await ot(async()=>{await x(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return ot(()=>this.negativeCache.clearNegative(e))}};async function ot(r){try{await r()}catch{}}function cn(r){return me.join(Ls,$(r)+".json")}function ln(r){return me.join(Bs,$(r)+".txt")}var Vt;function Ws(){return Vt||(Vt=Pt({cache:new it,cdnClient:$r,packageService:Ye,versionResolver:Ir})),Vt}var dn="file:///node_modules/";async function un(r){let e=qe(r.emitKey,"typecheck");await x(),await k.rm(e,{recursive:!0,force:!0}),await k.mkdir(e,{recursive:!0});let t=qs(r.jsxImportSource,r.dependencies),n=await Ws().resolve(r.code,r.dependencies,t),s=r.local?.name,o=s?n.filter(p=>p.pkg!==s):n,i=new Set;for(let p of o)for(let d of p.files){let h=at(d.path);if(!h||i.has(h))continue;i.add(h);let m=E.join(e,"node_modules",h);await k.mkdir(E.dirname(m),{recursive:!0}),await k.writeFile(m,d.content,"utf8")}let a={};for(let p of o)for(let d of p.shims){let h=at(d.path);h&&(a[d.module]=[`./node_modules/${h}`])}for(let p of o){if(p.ambient)continue;let d=at(p.mainPath);d&&(a[p.pkg]=[`./node_modules/${d}`])}let c=new Set;for(let p of o)for(let d of p.files){if(!d.ambient)continue;let h=at(d.path);h&&c.add(`node_modules/${h}`)}if(r.local){delete a[r.local.name];let p=await zs(r.local,e);p?a[r.local.name]=[`./node_modules/${r.local.name}/${p}`]:console.warn(` local: '${r.local.name}' ships no type defs; check cannot type against it.`)}let l=Js(r.jsxImportSource,a,[...c]);return await k.writeFile(E.join(e,"tsconfig.json"),JSON.stringify(l,null,2)+`
|
|
641
|
+
`,"utf8"),await k.writeFile(E.join(e,"code.tsx"),r.code,"utf8"),await k.writeFile(E.join(e,"tb.d.ts"),vt,"utf8"),{dir:e}}function Js(r,e,t=[]){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"bundler",lib:Vs([...yt,...wt]),jsx:"react-jsx",jsxImportSource:r??"react",strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0,baseUrl:".",paths:e},include:["code.tsx","tb.d.ts",...t]}}function Vs(r){return r.filter(e=>!e.since).map(e=>Hs(e.name))}function Hs(r){return r.split(".").map(e=>/^es\d+$/i.test(e)?e.toUpperCase():e==="dom"?"DOM":e==="esnext"?"ESNext":e.charAt(0).toUpperCase()+e.slice(1)).join(".")}function qs(r,e){let t=r??("react"in e?"react":void 0);return t?[`${t}/jsx-runtime`,`${t}/jsx-dev-runtime`]:[]}function at(r){if(!r.startsWith(dn))return;let e=r.slice(dn.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}async function zs(r,e){if(!r.typesAbs)return;let t=E.dirname(r.typesAbs),n=E.join(e,"node_modules",r.name);for(let s of await Gs(t)){let o=E.join(n,E.relative(t,s));await k.mkdir(E.dirname(o),{recursive:!0}),await k.copyFile(s,o)}return E.basename(r.typesAbs)}async function Gs(r){let e=[];async function t(n){let s=await k.readdir(n,{withFileTypes:!0});for(let o of s){let i=E.join(n,o.name);o.isDirectory()?await t(i):/\.d\.ts(\.map)?$/.test(o.name)&&e.push(i)}}return await t(r),e}import*as I from"fs/promises";import*as J from"path";import{existsSync as Ys}from"fs";var Ks="^22";async function pn(r){let e=qe(r.emitKey,"typecheck-server");await x(),await I.rm(e,{recursive:!0,force:!0}),await I.mkdir(e,{recursive:!0});let t=J.join(r.bulbDir,".typebulb"),n=Ze(r.server).filter(i=>i!==r.local?.name);await Qe([`@types/node@${Ks}`,...n],t,r.dependencies);let s=J.join(t,"node_modules"),o=J.join(e,"node_modules");return await Qs(s,o),await I.writeFile(J.join(e,"server.ts"),r.server,"utf8"),await I.writeFile(J.join(e,"tb.d.ts"),xt,"utf8"),await I.writeFile(J.join(e,"tsconfig.json"),JSON.stringify(Xs(r.local),null,2)+`
|
|
642
|
+
`,"utf8"),{dir:e}}function Xs(r){let e={target:"es2023",module:"esnext",moduleResolution:"bundler",lib:["ES2023"],types:["node"],strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0};if(r?.typesAbs){let t=o=>o.replace(/\\/g,"/"),n=t(J.dirname(r.typesAbs)),s=t(r.typesAbs).replace(/\.d\.ts$/,"");e.baseUrl=".",e.paths={[r.name]:[s],[`${r.name}/*`]:[`${n}/*`]}}return{compilerOptions:e,include:["server.ts","tb.d.ts"]}}async function Qs(r,e){if(!Ys(r)){await I.mkdir(e,{recursive:!0});return}await I.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await I.symlink(r,e,t)}import{readFileSync as Zs,writeFileSync as eo,mkdirSync as to}from"fs";import{join as ro}from"path";function fn(){return ro(rt(),"trust.json")}function Ht(){try{let r=JSON.parse(Zs(fn(),"utf8"));return new Set(Array.isArray(r)?r:[])}catch{return new Set}}function no(r){to(rt(),{recursive:!0}),eo(fn(),JSON.stringify([...r]))}function qt(r){return Ht().has(Y(r))}function hn(r,e){let t=Ht(),n=Y(r);(e?t.has(n):!t.has(n))||(e?t.add(n):t.delete(n),no(t))}function mn(){return[...Ht()]}import*as K from"path";import{fileURLToPath as so}from"url";var zt={claude:{file:"claude.bulb.md",srcEnv:"TYPEBULB_CLAUDE_SRC",viewer:!0}};function Ne(r){let e=zt[r];if(!e)return;let t=e.srcEnv?process.env[e.srcEnv]:void 0;return t?K.resolve(t):K.join(K.dirname(so(import.meta.url)),"bulbs",e.file)}function gn(r){let e=K.basename(r).toLowerCase();for(let[t,n]of Object.entries(zt))if(n.viewer&&n.file.toLowerCase()===e)return t}function Gt(){return Object.entries(zt).filter(([,r])=>r.viewer).map(([r])=>r)}var oo="---\nname: typebulb\ndescription: Author and run Typebulb bulbs \u2014 single-file markdown apps (TypeScript/TSX: charts, simulations, diagrams, calculators, interactive UIs) that run locally via `npx typebulb` or render live inline in a Claude Code session through claude.bulb. Covers the bulb format, the `tb.*` API, trust, and the local run/embed workflow. Use when the user wants a bulb, a quick local interactive tool, or something visual rendered inline in the conversation.\n---";function bn(r){return`${oo}
|
|
643
|
+
|
|
644
|
+
${r.trim()}
|
|
645
|
+
`}var co="0.9.9";async function lo(r,e){let{bulb:t,config:n}=await ue(r);!t.code&&!t.server&&(console.error("Bulb has neither **code.tsx** nor **server.ts**; nothing to check."),process.exit(1));let s=[];if(t.code){let{dir:i}=await un({code:t.code,dependencies:n.dependencies??{},jsxImportSource:n.jsxImportSource,emitKey:r,local:e});s.push({role:"client",dir:i})}if(t.server){let{dir:i}=await pn({server:t.server,bulbDir:S.dirname(r),emitKey:r,local:e?{name:e.name,typesAbs:e.typesAbs}:void 0,dependencies:n.dependencies});s.push({role:"server",dir:i})}let o=!1;for(let{role:i,dir:a}of s){let{stdout:c,exitCode:l}=await po(a);for(let p of c.split(/\r?\n/))p.trim()&&console.log(`${i} ${p}`);l!==0&&(o=!0)}o&&process.exit(1)}async function uo(r,e){let{bulb:t}=await ue(r),n=At(t);if(qt(r)){console.log("remembered-trusted \u2014 runs with filesystem / AI / server.ts automatically (`typebulb untrust` to revoke)."),n&&console.log(` (it uses ${n})`);return}n?(console.log(`This bulb appears to use ${n}; it runs Restricted unless you grant trust:`),console.log(` ${e}`)):console.log("No privileged capability detected \u2014 runs Restricted by default. (A clean scan is a hint, not a guarantee.)")}function po(r){return new Promise(e=>{let t=ao("npx",["tsc","--noEmit"],{cwd:r,shell:!0}),n="";t.stdout?.on("data",s=>{n+=s.toString()}),t.stderr?.on("data",s=>{n+=s.toString()}),t.on("close",s=>e({stdout:n,exitCode:s??1}))})}async function fo(r,e,t,n,s){let o=pt(t),i=!1,a=async()=>{let{bulb:c,config:l}=await ue(r);i||(ft(o,r,c.server),i=!0),await _t(c.server,s,n,l.dependencies)};if(console.log(`Running ${S.basename(r)}...`),await a(),e){console.log(`Watching for changes...
|
|
646
|
+
`);let c=new Yt;c.on("reload",async()=>{try{console.log("Re-running..."),await a()}catch(l){console.error("Error:",l)}}),Jt({bulbPath:r,emitter:c})}}async function ho(r,e,t,n,s){let o=process.cwd(),i=Gr(process.pid),a=e.watch?new Yt:void 0,c=pt(e.mode);console.log(`Loading ${S.basename(r)}...`);let{html:l,bulb:p,serverExports:d}=await Ct(r,e.watch,e.trust,n,s);ft(c,r,p.server);let h=await Wt(e.port),m=await tn({getHtml:()=>l,basePath:o,port:h,reloadEmitter:a,getServerExports:()=>d,localOverride:n?{name:n.name,serveDir:n.serveDir}:void 0,trusted:e.trust,trustHint:t}),g=`http://localhost:${h}`,R=e.trust?void 0:At(p);await Yr({pid:process.pid,port:h,url:g,file:r,startedAt:Date.now(),trust:e.trust,predicted:R}),console.log(`
|
|
647
647
|
${p.name}`),console.log(` ${g}`),e.trust?console.log(" trust: granted (filesystem, AI, server.ts enabled)"):console.log(R?` trust: sandboxed \u2014 this bulb appears to use ${R}; re-run with --trust to enable it:
|
|
648
648
|
${t}
|
|
649
649
|
`:` trust: sandboxed \u2014 re-run with --trust to enable filesystem / AI / server.ts
|
|
650
650
|
`),e.watch&&console.log(` Watching for changes...
|
|
651
|
-
`);let j,B;if(e.watch&&a){let u=new
|
|
652
|
-
`)}catch(f){console.error("Compile error:",f)}}),j=Jt({bulbPath:r,emitter:u}),n){let{name:f,serveDir:
|
|
651
|
+
`);let j,B;if(e.watch&&a){let u=new Yt;if(u.on("reload",async()=>{try{console.log("Recompiling...");let f=await Ct(r,!0,e.trust,n,s);l=f.html,d=f.serverExports,a.emit("reload"),console.log(`Done. Browser reloading...
|
|
652
|
+
`)}catch(f){console.error("Compile error:",f)}}),j=Jt({bulbPath:r,emitter:u}),n){let{name:f,serveDir:b}=n;B=an({dir:b,onChange:()=>{console.log(`Local package '${f}' changed. Browser reloading...
|
|
653
653
|
`),a.emit("reload")}})}}e.open&&await nn(g);let C=async()=>{console.log(`
|
|
654
|
-
Shutting down...`),m.close(),j?.(),B?.(),i(),await Lt(process.pid);let u=S.join(S.dirname(r),".typebulb","server.mjs");await ge.rm(u,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",C),process.on("SIGTERM",C)}function
|
|
655
|
-
`+e)}function
|
|
654
|
+
Shutting down...`),m.close(),j?.(),B?.(),i(),await Lt(process.pid);let u=S.join(S.dirname(r),".typebulb","server.mjs");await ge.rm(u,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",C),process.on("SIGTERM",C)}function mo(r,e){return/^\d+$/.test(e)?r.find(t=>t.pid===parseInt(e,10)):r.find(t=>Y(t.file)===Y(e))}function yn(r,e){for(let t of r)e(` ${t.url} pid ${t.pid} ${t.trust?"trusted":"restricted"} ${t.file}`)}function wn(r,e){if(!r.length){console.log("No running bulb servers.");return}console.log("Running bulb servers:"),yn(r,t=>console.log(t)),console.log(`
|
|
655
|
+
`+e)}function vn(r,e,t){let n=mo(r,e);if(n)return n;console.error(`No running server for '${e}'.`),r.length?(console.error(`Running servers (try \`typebulb ${t} <file|pid>\`):`),yn(r,s=>console.error(s))):console.error("No bulb servers are running."),process.exit(1)}async function go(r,e){if(!r){wn(await fe(process.cwd()),"Run `typebulb logs <file|pid>` to print one server's console.");return}let t=vn(await fe(),Ne(r)??r,"logs"),n=Nt(t.pid),s=n.text;if(e.lines&&e.lines>0){let o=s.split(`
|
|
656
656
|
`);o.length&&o[o.length-1]===""&&o.pop(),s=o.slice(-e.lines).join(`
|
|
657
657
|
`)}if(process.stdout.write(s),s&&!s.endsWith(`
|
|
658
658
|
`)&&process.stdout.write(`
|
|
659
|
-
`),e.follow){let o=n.offset,i=setInterval(()=>{let c=Nt(t.pid,o);o=c.offset,c.text&&process.stdout.write(c.text)},500),a=()=>{clearInterval(i),process.exit(0)};process.on("SIGINT",a),process.on("SIGTERM",a),await new Promise(()=>{})}}async function bo(r){if(!r){
|
|
660
|
-
`)
|
|
661
|
-
|
|
659
|
+
`),e.follow){let o=n.offset,i=setInterval(()=>{let c=Nt(t.pid,o);o=c.offset,c.text&&process.stdout.write(c.text)},500),a=()=>{clearInterval(i),process.exit(0)};process.on("SIGINT",a),process.on("SIGTERM",a),await new Promise(()=>{})}}async function bo(r){if(!r){wn(await fe(process.cwd()),"Run `typebulb stop <file|pid>` to stop one.");return}let e=vn(await fe(),Ne(r)??r,"stop");await Xr(e.pid),console.log(`Stopped ${S.basename(e.file)} (pid ${e.pid}, ${e.url}).`)}async function yo(r,e){if(!r){e||(console.error("Usage: typebulb untrust <file.bulb.md>"),process.exit(1));let n=mn();if(!n.length){console.log("No bulbs are remembered as trusted.");return}console.log("Trusted bulbs (run with fs/AI/server.ts without --trust):");for(let s of n)console.log(` ${s}`);return}let t=S.resolve(r);t.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1)),hn(t,e),console.log(e?`Trusted ${S.basename(t)} \u2014 runs with fs / AI / server.ts (no --trust needed).`:`Untrusted ${S.basename(t)} \u2014 runs Restricted.`),console.log(` ${t}`)}async function wo(){let r=await fe(),e;for(let s of r){let o=gn(s.file);if(o){e=o;break}}let t=e?"output a bulb block; it renders live here":"start the viewer yourself \u2014 `npx typebulb agent:claude --no-open` \u2014 share the localhost link it prints, then output a bulb block",n=[e?`You ran \`typebulb agent\`. Viewer '${e}' is up.`:"You ran `typebulb agent`. No viewer is running.",`- To show a bulb inline in this chat: ${t}.`,"- To make a bulb to keep and iterate on: write a .bulb.md and run `npx typebulb my-bulb.bulb.md`.","Working with bulbs? Run `npx typebulb skill` and copy its output to your skills folder."];process.stdout.write(n.join(`
|
|
660
|
+
`)+`
|
|
661
|
+
`),process.exitCode=e?0:1}async function vo(){let r=S.join(S.dirname(io(import.meta.url)),"..","README.md"),e;try{e=await ge.readFile(r,"utf8")}catch{console.error(`Could not read the bundled README (expected at ${r}).`),process.exit(1)}process.stdout.write(bn(e))}async function xo(){let r=or(process.argv.slice(2));if(r.version&&(console.log(`typebulb ${co}`),process.exit(0)),r.help&&(ir(),process.exit(0)),r.subcommand==="logs"){await go(r.file||void 0,{follow:r.follow,lines:r.lines});return}if(r.subcommand==="stop"){await bo(r.file||void 0);return}if(r.subcommand==="skill"){await vo();return}if(r.subcommand==="agent"){if(!r.agentTarget){await wo();return}Ne(r.agentTarget)||(console.error(`Unknown agent '${r.agentTarget}'. Known: ${Gt().join(", ")}.`),process.exit(1)),r.file=r.agentTarget,r.subcommand="run"}if(r.subcommand==="trust"||r.subcommand==="untrust"){await yo(r.file||void 0,r.subcommand==="trust");return}let e,t=!1;if(!r.file||r.file==="."){let l=await Lr(process.cwd());l||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=l}else e=S.resolve(r.file);if(!await ge.access(e).then(()=>!0,()=>!1)){let l=r.agentTarget?Ne(r.file):void 0;l?(e=l,t=!0):Gt().includes(r.file)?(console.error(`To open the ${r.file} agent viewer, run: npx typebulb agent:${r.file}`),process.exit(1)):(console.error(`File not found: ${e}`),process.exit(1))}e.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1));let s=r.file&&r.file!=="."?r.file:S.relative(process.cwd(),e)||S.basename(e),o=`npx typebulb --trust ${s.includes(" ")?`"${s}"`:s}`;if(r.subcommand==="predict"){await uo(e,o);return}if(t)r.trust=!r.noTrust,r.trust&&console.log("trust: granted (built-in bulb)");else{let l=!r.noTrust&&qt(e);l&&!r.trust&&console.log("trust: granted from memory (run `typebulb untrust` to revoke)"),r.trust=r.noTrust?!1:r.trust||l}let i;try{i=await ue(e)}catch{}let a;if(r.local){i&&!(r.local.name in(i.config.dependencies??{}))&&(console.error(`--replace: '${r.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),i&&(!i.bulb.code||r.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{a=await nr(r.local)}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exit(1)}console.log(`replace: ${a.name} \u2192 ${S.relative(process.cwd(),a.dir)||"."}`)}if(r.subcommand==="check"){await lo(e,a);return}let c=t?process.cwd():S.dirname(e);if(process.env.TYPEBULB_BULB_PATH=e,i&&i.bulb.server&&(!i.bulb.code||r.server)){r.trust||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
|
|
662
|
+
${o}`),process.exit(1)),await fo(e,r.watch,r.mode,a,c);return}await ho(e,r,o,a,c)}xo().catch(r=>{console.error("Error:",r.message),process.exit(1)});
|