typebulb 0.9.3 → 0.9.5
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 +4 -1
- package/dist/index.js +86 -60
- package/dist/render.js +23 -4
- package/dist/servers.d.ts +7 -0
- package/dist/servers.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ npm install -g typebulb
|
|
|
44
44
|
```
|
|
45
45
|
typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
|
|
46
46
|
typebulb check [file.bulb.md] Type-check a bulb without running it
|
|
47
|
+
typebulb predict [file] Report the capability a bulb probably needs, without running it
|
|
47
48
|
typebulb logs [file|pid] Print a running bulb's captured console (-f follow, -n N tail)
|
|
48
49
|
typebulb stop [file|pid] Stop a running bulb (no arg: list running servers)
|
|
49
50
|
typebulb trust [file] Remember a bulb as trusted (no arg: list trusted bulbs)
|
|
@@ -51,6 +52,7 @@ typebulb untrust <file> Forget a bulb's trust (back to sandboxed)
|
|
|
51
52
|
typebulb --no-watch <file> Disable hot reload
|
|
52
53
|
typebulb --port 3333 <file> Custom port
|
|
53
54
|
typebulb --no-open <file> Don't auto-open browser
|
|
55
|
+
typebulb --mode <name> <file> Also load .env.<name> on top of .env / .env.local
|
|
54
56
|
typebulb --trust <file> Grant filesystem + AI + server.ts for this run (default: sandboxed)
|
|
55
57
|
typebulb --no-trust <file> Force sandboxed even if the bulb is remembered-trusted
|
|
56
58
|
typebulb --server <file> Run server.ts only, no web server (needs --trust)
|
|
@@ -63,7 +65,7 @@ typebulb --version Show version
|
|
|
63
65
|
|
|
64
66
|
- **Server-side code** — Add a `**server.ts**` section; exported functions become callable from the browser via `tb.server.<name>()` (e.g., `export async function query(...)` → `await tb.server.query(...)`). Requires `--trust`.
|
|
65
67
|
- **CLI logging** — `tb.server.log(...)` prints to the CLI's stdout
|
|
66
|
-
- **Env files** — `.env`
|
|
68
|
+
- **Env files** — `.env` / `.env.local` load from cwd, `.env.local` overriding `.env` (an exported shell var wins over both). `--mode <name>` adds `.env.<name>` to switch environments (local/staging/prod); a startup line reports which keys loaded from where.
|
|
67
69
|
- **Server mode** — `--server` runs only the `**server.ts**` section in Node, skipping the web server. Bulbs with only `**server.ts**` (no `**code.tsx**`) use this mode automatically.
|
|
68
70
|
- **Type-check without running** — `typebulb check <file>` runs `tsc --noEmit` against the bulb and exits non-zero on errors. Useful for AI editors / CI.
|
|
69
71
|
- **Filesystem access** — `tb.fs.read()` (UTF-8 text), `tb.fs.readBytes()` (raw `Uint8Array`), and `tb.fs.write()` (text or bytes) for local files. Requires `--trust`.
|
|
@@ -73,6 +75,7 @@ typebulb --version Show version
|
|
|
73
75
|
- **Local caching** — Resolver metadata and CDN package bytes are cached under `~/.typebulb/cache/`, so repeat runs don't re-hit the network and warm runs work offline.
|
|
74
76
|
- **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`.
|
|
75
77
|
- **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.
|
|
78
|
+
- **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.
|
|
76
79
|
|
|
77
80
|
## AI Setup
|
|
78
81
|
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import*as
|
|
2
|
+
import*as st from"fs/promises";import*as P from"path";import{spawn as Xs}from"child_process";import{EventEmitter as Ht}from"events";import*as Gt from"fs/promises";import{existsSync as re,readFileSync as hn}from"fs";import*as R from"path";import{pathToFileURL as mn}from"url";import{resolve as at}from"resolve.exports";import{init as Kt,parse as Yt}from"es-module-lexer";function Xt(r,e){let t=R.join(r,"package.json");try{return JSON.parse(hn(t,"utf8"))}catch{throw new Error(`--replace package '${e}' has no readable package.json at ${t}`)}}var it=["browser","import","default"],zt=["node","import","default"];function Qt(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:R.resolve(n)}}async function Zt(r){let{name:e,dir:t}=r;if(!re(t))throw new Error(`--replace path for '${e}' does not exist: ${t}`);let n=Xt(t,e),s=gn(n,e),o=R.resolve(t,s);if(!re(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=R.dirname(o),a=`/local/${e}/${R.basename(o)}`,c=yn(n,t);return await bn(e,o,i),{name:e,dir:t,entryAbs:o,serveDir:i,entryUrl:a,typesAbs:c}}function gn(r,e){if(r.exports!==void 0){let n;try{n=at(r,".",{browser:!0,conditions:it})}catch(o){throw new Error(`--replace package '${e}' "exports" does not resolve a browser entry (conditions: ${it.join(", ")}): ${o instanceof Error?o.message:o}`)}let s=ct(n);if(!s)throw new Error(`--replace package '${e}' "exports" did not resolve "." to a single file (conditions: ${it.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 yn(r,e){if(r.exports!==void 0)try{let n=at(r,".",{conditions:["types"]}),s=ct(n);if(s){let o=R.resolve(e,s);if(re(o))return o}}catch{}let t=r.types??r.typings;if(t){let n=R.resolve(e,t);if(re(n))return n}}function ct(r){if(typeof r=="string")return r;if(Array.isArray(r))return r.find(e=>typeof e=="string")}async function bn(r,e,t){await Kt;let n=R.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 Gt.readFile(i,"utf8")}catch{continue}let c,l;try{[c,,,l]=Yt(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=vn(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 vn(r,e,t){let n=e.replace(/[?#].*$/,""),s=R.resolve(R.dirname(r),n),o=[s,s+".js",s+".mjs",R.join(s,"index.js"),R.join(s,"index.mjs")];for(let i of o)if(R.normalize(i).startsWith(t)&&re(i))return i}function wn(r,e,t){let n=Xt(r,e),s;if(n.exports!==void 0)try{s=ct(at(n,t,{conditions:zt}))}catch(i){throw new Error(`--replace package '${e}' "exports" does not resolve a node entry for '${t}' (conditions: ${zt.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=R.resolve(r,s);if(!re(o))throw new Error(`--replace package '${e}' built file not found: ${o} \u2014 did you build it (e.g. \`pnpm run build\`)?`);return mn(o).href}async function er(r,e){await Kt;let t;try{[t]=Yt(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=wn(e.dir,e.name,a);n+=r.slice(s,o.s)+c,s=o.e}return n+r.slice(s)}function tr(r){let e={subcommand:"run",file:"",port:3e3,watch:!0,open:!0,server:!1,trust:!1,noTrust:!1,follow:!1,help:!1,version:!1};["check","predict","logs","stop","trust","untrust"].includes(r[0])&&(e.subcommand=r[0],r=r.slice(1));for(let n=0;n<r.length;n++){let s=r[n];if(s==="--help"||s==="-h")e.help=!0;else if(s==="--version"||s==="-V")e.version=!0;else if(s==="--no-watch")e.watch=!1;else if(s==="--no-open")e.open=!1;else if(s==="--server")e.server=!0;else if(s==="--trust")e.trust=!0;else if(s==="--no-trust")e.noTrust=!0;else if(s==="--mode"){let o=r[++n];(!o||o.startsWith("-"))&&(console.error("Missing value for --mode (e.g. --mode staging)"),process.exit(1)),e.mode=o}else if(s==="--follow"||s==="-f")e.follow=!0;else if(s==="--lines"||s==="-n"){let o=parseInt(r[++n],10);(isNaN(o)||o<0)&&(console.error(`Invalid --lines value: ${r[n]}`),process.exit(1)),e.lines=o}else if(s==="--port"||s==="-p"){let o=r[++n],i=parseInt(o,10);isNaN(i)&&(console.error(`Invalid port: ${o}`),process.exit(1)),e.port=i}else if(s==="--replace"||s.startsWith("--replace=")){let o=s.startsWith("--replace=")?s.slice(10):r[++n]??"";try{let i=Qt(o);if(e.local)throw new Error(`--replace can only be used once (got '${e.local.name}' and '${i.name}')`);e.local=i}catch(i){console.error(i instanceof Error?i.message:String(i)),process.exit(1)}}else s.startsWith("-")||(e.file=s)}return e}function rr(){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
7
|
typebulb check [file.bulb.md] Type-check a bulb without running it
|
|
8
|
+
typebulb predict [file] Report the capability a bulb probably needs
|
|
9
|
+
(fs / AI / server.ts) without running it.
|
|
8
10
|
typebulb logs [file|pid] Print a running bulb server's captured console
|
|
9
11
|
(no arg: list running servers). For agents:
|
|
10
12
|
fetch tb.server.log / errors of a bulb you
|
|
@@ -29,6 +31,9 @@ Options:
|
|
|
29
31
|
trusted without this flag.
|
|
30
32
|
--no-trust Force Restricted for this run even if the bulb is
|
|
31
33
|
remembered-trusted (overrides the trust store).
|
|
34
|
+
--mode <name> Also load .env.<name> (+ .env.<name>.local) on top
|
|
35
|
+
of .env / .env.local. Free-form name; loads no mode
|
|
36
|
+
file by default.
|
|
32
37
|
--server Run server.ts only, no web server (needs --trust)
|
|
33
38
|
--replace <name>=<path> Replace a declared dependency with a local built
|
|
34
39
|
package folder instead of a CDN (dev only).
|
|
@@ -49,7 +54,7 @@ Server API:
|
|
|
49
54
|
Exported functions become callable from the browser:
|
|
50
55
|
// in **server.ts**: export async function query(sql) { ... }
|
|
51
56
|
// in **code.tsx**: const rows = await tb.server.query(sql)
|
|
52
|
-
.env
|
|
57
|
+
.env / .env.local load from the working directory; --mode <name> adds .env.<name>.
|
|
53
58
|
|
|
54
59
|
Built-in server functions (available without a **server.ts** section):
|
|
55
60
|
tb.server.log(...) Print to the CLI's stdout
|
|
@@ -71,10 +76,10 @@ Examples:
|
|
|
71
76
|
typebulb my-editor.bulb.md
|
|
72
77
|
typebulb --no-watch --port 8080 my-editor.bulb.md
|
|
73
78
|
typebulb .
|
|
74
|
-
`)}import{readFileSync as
|
|
75
|
-
`)){let
|
|
76
|
-
`),t=0;if(e[t]?.trim()!=="---")return null;t++;let
|
|
77
|
-
`))}else t++}return{frontmatter:s,files:o}}catch{return null}}function vn(n){let e={};for(let t of n){let r=t.indexOf(":");if(r===-1)continue;let s=t.slice(0,r).trim(),o=t.slice(r+1).trim();switch(s){case"format":e.format=o;break;case"name":e.name=xn(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function xn(n){return n.startsWith('"')&&n.endsWith('"')?n.slice(1,-1).replace(/\\"/g,'"'):n.startsWith("'")&&n.endsWith("'")?n.slice(1,-1):n}function rr(n){let e=t=>n.files.get(wn[t].path)||"";return{name:n.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 Sn(n){try{return JSON.parse(n),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(n)||/^---\s*$/m.test(n)||/^\w[\w\s]*:[ \t]/m.test(n))}function nr(n){let e=n.trim();return e?Sn(e)?[e]:n.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function sr(n){if(!n.trim())return{};try{return JSON.parse(n)}catch{return{}}}import{transform as Pn}from"sucrase";function lt(n,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:r}=Pn(n,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:r}}catch(r){return{code:"",error:String(r)}}}var he="https://esm.sh",me="https://cdn.jsdelivr.net/npm/",dt="https://data.jsdelivr.com/v1/package/npm/";function or(n){let e=(n||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var y=class n{constructor(e,t,r){let s=typeof e=="string"?n.parse(e):e;this.name=s.name,this.version=re(t??s.version),this.subpath=re(r??s.subpath)}static parse(e){let t=or(e||"");if(!t.length)return new n({name:""});if(t[0].startsWith("@")){let s=t[0],[o,i]=ir(t[1]??""),a=re(t.slice(2).join("/"));return new n({name:`${s}/${o}`,version:i,subpath:a})}else{let[s,o]=ir(t[0]),i=re(t.slice(1).join("/"));return new n({name:s,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),r=new URL(he).host,s=new URL(me).host;if(t.host===r){let o=or(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return n.parse(i)}if(t.host===s){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return n.parse(i)}return}catch{return}}static versionFromUrl(e){return n.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 n.parse(e).name}withVersion(e){return new n({name:this.name,version:re(e),subpath:this.subpath})}withPreferredVersion(e,t){let r=e||t;return r?this.withVersion(r):this}static isBare(e){if(!e||e.startsWith(".")||e.startsWith("/"))return!1;let t=e.toLowerCase();return!t.startsWith("http://")&&!t.startsWith("https://")}},re=n=>n&&n.length?n:void 0,ir=n=>{let e=n.indexOf("@");return e<0?[n,void 0]:[n.slice(0,e),re(n.slice(e+1))]};async function T(n){try{return await n()}catch{return}}var ge=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=he,this.jsDelivrBase=me,this.jsDelivrMeta=dt,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:r="es2022",bundle:s=!1,external:o}=t,i=new URLSearchParams({target:r});return s&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let r=this.buildEsmUrl(e,{target:t}),s=await T(()=>this.http.head(r));return s?.ok?s.url||r:void 0}async resolveExactVersion(e){let t=Date.now(),r=this.pinCache.get(e);if(r&&t-r.ts<this.pinMs)return r.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 r=await T(()=>this.http.head(t)),s=this.parseVersionFromUrl(r?.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 r=await T(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let s=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,s),r}parseVersionFromUrl(e){let t=y.fromUrl(e)?.version;return t&&/\d+\.\d+\.\d+/.test(t)?t:void 0}async fetchPackageMeta(e,t){let r=await this.cache.getMeta(e,t);if(r&&Date.now()-r.updatedAt<this.metaTtlMs){let{dependencies:d,peerDependencies:u,peerDependenciesMeta:h}=r;return{name:e,version:t,dependencies:d,peerDependencies:u,peerDependenciesMeta:h}}let s=this.packageJson(new y(`${e}@${t}`)),o=await T(()=>this.http.getJson(s));if(!o)return;let i=d=>d&&Object.keys(d).length?d: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 ar=n=>n.startsWith("@types/"),ye=n=>Object.keys(n?.peerDependencies||{}).filter(e=>!ar(e)),ut=n=>Object.keys(n?.dependencies||{}).filter(e=>!ar(e)),Rn=n=>ye(n).filter(e=>!n?.peerDependenciesMeta?.[e]?.optional),be=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:s,autoAddedPeers:o}=await this.expandWithPeers(r,t),i=this.computeFlags(s);return{allRoots:s,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:r})=>({name:t,version:r,meta:await this.cdn.fetchPackageMeta(t,r)})))}async expandWithPeers(e,t){let r=new Map(e.map(o=>[o.name,o])),s=[];for(let o of e)for(let i of Rn(o.meta))!r.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);r.set(o,{name:o,version:a,meta:c})}catch(a){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,a)}return{allRoots:[...r.values()],autoAddedPeers:s.filter(o=>r.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>ye(o.meta))),r=new Map;for(let o of e)for(let i of ut(o.meta))r.set(i,(r.get(i)||0)+1);let s=new Set([...r.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:ye(o.meta).length>0,isSharedDep:s.has(o.name)}]))}};var we=class{constructor(e,t,r){this.cache=e,this.cdn=t,this.semver=r}selectVersionFromIndex(e,t,r){return this.semver.selectBestVersion(e,{range:t,distTags:r})}async learnExactVersion(e){let t=await T(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let r=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(r)return r}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let r=await this.cache.getPinnedExact(e,t);if(r){if(this.semver.isExactVersion(r))return r;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",r)}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 r=new y(e),s=r.root(),o=t[s],i=o?await T(()=>this.cache.getPinnedExact(s,o))??await T(()=>this.resolveExactForRoot(s,o)):void 0;return{effectivePackage:i?r.withVersion(i).format():e,root:s,range:o,pinned:i}}};import{init as En,parse as kn}from"es-module-lexer";var ne=class n{constructor(e,t,r,s){this.version=e,this.cdn=t,this.peer=r,this.cache=s}extractImportsSync(e){let t=new Set;for(let r of n.importPatterns){r.lastIndex=0;for(let s of e.matchAll(r))y.isBare(s[1])&&t.add(s[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=s=>{y.isBare(s)&&t.add(s)};try{await En;let[s]=kn(e);s.forEach(o=>r(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t,r){let s=(await this.extractImports(e)).filter(u=>!r?.has(y.rootOf(u))),o=[...new Set(s.map(y.rootOf))],i=await Promise.all(o.map(async u=>({name:u,version:await this.resolveVersion(u,t)}))),{allRoots:a,flags:c,autoAddedPeers:l}=await this.peer.resolve(i,u=>this.resolveVersion(u,t)),d=this.buildEntries([...s,...l.map(u=>u.name)],a,c,t);return{importMap:{imports:Object.fromEntries(d)},prefetchUrls:d.map(([,u])=>u)}}async resolveVersion(e,t){let r=t[e],s=r?`${e}@${r}`:e,o=await this.version.resolveExactForRoot(e,r);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&&r&&await T(()=>this.cache.setPinnedExact(e,r,o))}if(!o)throw new Error(`Cannot resolve ${s}: no concrete version found.`);return o}buildEntries(e,t,r,s){let o=new Map(t.map(m=>[m.name,m])),i=m=>{let S=o.get(y.rootOf(m));return new y(m).withPreferredVersion(S.version,s[S.name]).format()},a=new Set([...r.entries()].filter(([,m])=>m.isPeerRoot||m.isSharedDep).map(([m])=>m)),c=new Set(e.filter(m=>m!==y.rootOf(m)).map(y.rootOf)),l=[],d=new Set,u=new Set(e.filter(m=>m===y.rootOf(m))),h=new Set;for(let m of e){let S=y.rootOf(m),O=o.get(S),{isPeerRoot:_,hasPeers:$,isSharedDep:p}=r.get(S),f=c.has(S),g=m!==S,w=!(_||p)&&(f||!$),C=this.singletonDepsOf(O,a),J=g&&u.has(S);J&&h.add(S);let L=J?[...C,S]:C.length?C:void 0;l.push([m,this.cdn.buildEsmUrl(i(m),{bundle:w,external:L})]),d.add(m)}let b=new Set([...a,...h]);for(let m of b)o.has(m)&&(d.has(m)||l.push([m,this.cdn.buildEsmUrl(i(m),{})]),l.push([`${m}/`,`${this.cdn.esmHost}/${i(m)}/`]));return l}singletonDepsOf(e,t){return[...new Set([...ye(e.meta),...ut(e.meta)])].filter(r=>t.has(r))}};ne.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as cr,satisfies as Tn,maxSatisfying as pt,major as _n,prerelease as Cn,rsort as On,valid as In}from"semver";var Ne=class{cmp(e,t){return e===t?0:cr(e,t)?1:cr(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Tn(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=pt(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?On(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",s=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(r,o))return o;if(s){let a=pt(e,r,{includePrerelease:!1});if(a)return a}return pt(e,r,{includePrerelease:!0})??void 0}majorOf(e){return _n(e)}isPrerelease(e){return Cn(e)!==null}isExactVersion(e){return In(e)!==null}},z=new Ne;function lr(n,e){let t=new ge(n,e),r=new be(t),s=new we(n,t,z);return{packageService:new ne(s,t,r,n),versionResolver:s,cdnClient:t,peerResolver:r}}import*as Rr from"fs/promises";import*as M from"path";var ft=[{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"}],ht=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var dr=`
|
|
79
|
+
`)}import{readFileSync as xn,existsSync as Sn}from"fs";import*as U from"path";function Rn(r){return[...r?[`.env.${r}.local`,`.env.${r}`]:[],".env.local",".env"]}function lt(r,e=process.cwd()){let t={},n=[];for(let s of Rn(r)){let o;try{o=xn(U.resolve(e,s),"utf-8")}catch{continue}n.push(s);for(let[i,a]of Pn(o))process.env[i]===void 0&&(process.env[i]=a,t[i]=s)}return{mode:r,sources:t,loaded:n}}function*Pn(r){for(let e of r.split(`
|
|
80
|
+
`)){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 En(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 dt(r,e,t){let{sources:n,mode:s,loaded:o}=r,i=process.cwd(),a=U.dirname(e),c=`(mode: ${s??"none"})`,l=t?En(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"])Sn(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 le from"path";import{pathToFileURL as ps}from"url";var kn={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 nr(r){try{let e=r.split(`
|
|
81
|
+
`),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=Tn(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(`
|
|
82
|
+
`))}else t++}return{frontmatter:s,files:o}}catch{return null}}function Tn(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=_n(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function _n(r){return r.startsWith('"')&&r.endsWith('"')?r.slice(1,-1).replace(/\\"/g,'"'):r.startsWith("'")&&r.endsWith("'")?r.slice(1,-1):r}function sr(r){let e=t=>r.files.get(kn[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 Cn(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 or(r){let e=r.trim();return e?Cn(e)?[e]:r.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function ir(r){if(!r.trim())return{};try{return JSON.parse(r)}catch{return{}}}import{transform as On}from"sucrase";function ut(r,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:n}=On(r,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:n}}catch(n){return{code:"",error:String(n)}}}var me="https://esm.sh",ge="https://cdn.jsdelivr.net/npm/",pt="https://data.jsdelivr.com/v1/package/npm/";function ar(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=ne(t??s.version),this.subpath=ne(n??s.subpath)}static parse(e){let t=ar(e||"");if(!t.length)return new r({name:""});if(t[0].startsWith("@")){let s=t[0],[o,i]=cr(t[1]??""),a=ne(t.slice(2).join("/"));return new r({name:`${s}/${o}`,version:i,subpath:a})}else{let[s,o]=cr(t[0]),i=ne(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(me).host,s=new URL(ge).host;if(t.host===n){let o=ar(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:ne(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://")}},ne=r=>r&&r.length?r:void 0,cr=r=>{let e=r.indexOf("@");return e<0?[r,void 0]:[r.slice(0,e),ne(r.slice(e+1))]};async function _(r){try{return await r()}catch{return}}var ye=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=me,this.jsDelivrBase=ge,this.jsDelivrMeta=pt,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 _(()=>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 _(()=>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 _(()=>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 _(()=>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 lr=r=>r.startsWith("@types/"),be=r=>Object.keys(r?.peerDependencies||{}).filter(e=>!lr(e)),ft=r=>Object.keys(r?.dependencies||{}).filter(e=>!lr(e)),In=r=>be(r).filter(e=>!r?.peerDependenciesMeta?.[e]?.optional),ve=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 In(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=>be(o.meta))),n=new Map;for(let o of e)for(let i of ft(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:be(o.meta).length>0,isSharedDep:s.has(o.name)}]))}};var we=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 _(()=>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 _(()=>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 _(()=>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 _(()=>this.cache.getPinnedExact(s,o))??await _(()=>this.resolveExactForRoot(s,o)):void 0;return{effectivePackage:i?n.withVersion(i).format():e,root:s,range:o,pinned:i}}};import{init as An,parse as Dn}from"es-module-lexer";var se=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 An;let[s]=Dn(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 _(()=>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 _(()=>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 S=o.get(b.rootOf(g));return new b(g).withPreferredVersion(S.version,s[S.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 S=b.rootOf(g),j=o.get(S),{isPeerRoot:B,hasPeers:T,isSharedDep:u}=n.get(S),f=c.has(S),y=g!==S,v=!(B||u)&&(f||!T),C=this.singletonDepsOf(j,a),V=y&&d.has(S);V&&h.add(S);let N=V?[...C,S]:C.length?C: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([...be(e.meta),...ft(e.meta)])].filter(n=>t.has(n))}};se.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as dr,satisfies as $n,maxSatisfying as ht,major as Mn,prerelease as Fn,rsort as jn,valid as Nn}from"semver";var je=class{cmp(e,t){return e===t?0:dr(e,t)?1:dr(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!$n(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let n=ht(e,t,{includePrerelease:!0});return n===null?void 0:n}pickLatest(e){return e?.length?jn(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=ht(e,n,{includePrerelease:!1});if(a)return a}return ht(e,n,{includePrerelease:!0})??void 0}majorOf(e){return Mn(e)}isPrerelease(e){return Fn(e)!==null}isExactVersion(e){return Nn(e)!==null}},K=new je;function ur(r,e){let t=new ye(r,e),n=new ve(t),s=new we(r,t,K);return{packageService:new se(s,t,n,r),versionResolver:s,cdnClient:t,peerResolver:n}}import*as kr from"fs/promises";import*as $ from"path";var mt=[{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"}],gt=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var pr=`
|
|
78
83
|
/**
|
|
79
84
|
* Get raw data chunk from the Data tab.
|
|
80
85
|
* @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
|
|
@@ -85,7 +90,7 @@ Examples:
|
|
|
85
90
|
* @param index - Chunk index (0-based)
|
|
86
91
|
* @throws If chunk is not valid JSON/JSON-ish
|
|
87
92
|
*/
|
|
88
|
-
json<T = unknown>(index: number): T;`,
|
|
93
|
+
json<T = unknown>(index: number): T;`,fr=`
|
|
89
94
|
/**
|
|
90
95
|
* Get the insight data produced by the inference layer.
|
|
91
96
|
*
|
|
@@ -94,7 +99,7 @@ Examples:
|
|
|
94
99
|
*
|
|
95
100
|
* @returns The parsed insight JSON, or undefined if no insight is available
|
|
96
101
|
*/
|
|
97
|
-
insight<T = unknown>(): T | undefined;`,
|
|
102
|
+
insight<T = unknown>(): T | undefined;`,hr=`
|
|
98
103
|
/**
|
|
99
104
|
* General-purpose AI call.
|
|
100
105
|
*
|
|
@@ -111,7 +116,7 @@ Examples:
|
|
|
111
116
|
model?: string;
|
|
112
117
|
/** Enable/disable web search. Default: on for BYOK, always off for free model. */
|
|
113
118
|
webSearch?: boolean;
|
|
114
|
-
}): Promise<{ text: string }>;`,
|
|
119
|
+
}): Promise<{ text: string }>;`,mr=`
|
|
115
120
|
/**
|
|
116
121
|
* Returns AI models available to the current user.
|
|
117
122
|
* Models are filtered by the user's configured API keys.
|
|
@@ -126,7 +131,7 @@ Examples:
|
|
|
126
131
|
friendlyName: string;
|
|
127
132
|
/** Provider display name, e.g. "Anthropic" */
|
|
128
133
|
providerName: string;
|
|
129
|
-
}>>;`,
|
|
134
|
+
}>>;`,Ln="\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;",gr=`
|
|
130
135
|
/**
|
|
131
136
|
* The mode this bulb is running in.
|
|
132
137
|
*
|
|
@@ -136,7 +141,7 @@ Examples:
|
|
|
136
141
|
* - \`'embedded'\` \u2014 Running as a bulb embedded inside another bulb (sandboxed,
|
|
137
142
|
* client-only: AI, filesystem, and server RPC are unavailable)
|
|
138
143
|
*/
|
|
139
|
-
mode: 'local' | 'editor' | 'published' | 'embedded';`,
|
|
144
|
+
mode: 'local' | 'editor' | 'published' | 'embedded';`,yr=`
|
|
140
145
|
/**
|
|
141
146
|
* Local filesystem access (CLI only).
|
|
142
147
|
*
|
|
@@ -150,7 +155,7 @@ Examples:
|
|
|
150
155
|
readBytes(path: string): Promise<Uint8Array>;
|
|
151
156
|
/** Write text or raw bytes to a file. Creates parent directories if needed. */
|
|
152
157
|
write(path: string, content: string | Uint8Array): Promise<boolean>;
|
|
153
|
-
};`,
|
|
158
|
+
};`,Bn=`
|
|
154
159
|
/**
|
|
155
160
|
* Server-side function proxy. The built-in \`log\` prints to CLI stdout
|
|
156
161
|
* (falls back to console.log on web). On the server side, this object only
|
|
@@ -158,7 +163,7 @@ Examples:
|
|
|
158
163
|
*/
|
|
159
164
|
server: {
|
|
160
165
|
log(...args: any[]): Promise<void>;
|
|
161
|
-
}
|
|
166
|
+
};`,Un=`
|
|
162
167
|
/**
|
|
163
168
|
* Async value inspector for tensor-like objects.
|
|
164
169
|
*
|
|
@@ -225,7 +230,7 @@ Examples:
|
|
|
225
230
|
*
|
|
226
231
|
* @returns The full canonical URL
|
|
227
232
|
*/
|
|
228
|
-
url(): Promise<string>;`,
|
|
233
|
+
url(): Promise<string>;`,Wn=`
|
|
229
234
|
/**
|
|
230
235
|
* Server-side function proxy.
|
|
231
236
|
*
|
|
@@ -233,23 +238,23 @@ Examples:
|
|
|
233
238
|
* \`tb.server.log(...)\` is a built-in that prints to CLI stdout (falls back to console.log on web).
|
|
234
239
|
* User exports override built-ins of the same name.
|
|
235
240
|
*/
|
|
236
|
-
server: Record<string, (...args: any[]) => Promise<any>>;`,
|
|
241
|
+
server: Record<string, (...args: any[]) => Promise<any>>;`,yt=`
|
|
237
242
|
/**
|
|
238
243
|
* Typebulb utilities namespace.
|
|
239
244
|
* Type \`tb.\` to discover available helpers.
|
|
240
245
|
*/
|
|
241
|
-
declare const tb: {${
|
|
246
|
+
declare const tb: {${pr}${Un}${fr}${Wn}${hr}${yr}${mr}${Ln}${gr}
|
|
242
247
|
};
|
|
243
|
-
`,
|
|
248
|
+
`,bt=`
|
|
244
249
|
/**
|
|
245
250
|
* Typebulb utilities namespace (server-side).
|
|
246
251
|
* Type \`tb.\` to discover available helpers.
|
|
247
252
|
*/
|
|
248
|
-
declare const tb: {${
|
|
253
|
+
declare const tb: {${pr}${fr}${hr}${yr}${Bn}${mr}${gr}
|
|
249
254
|
};
|
|
250
|
-
`;var K=class{constructor(e){this.store=e}async isNegative(e){let t=await je(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let r=((await je(()=>this.store.get(e)))?.attempts||0)+1;await je(()=>this.store.set(e,{until:Date.now()+Mn(r),attempts:r}))}async clearNegative(e){await je(()=>this.store.delete(e))}};function Mn(n){return Math.min(9e5*Math.pow(2,Math.max(0,n-1)),864e5)}async function je(n){try{return await n()}catch{return}}import Wn from"p-limit";import{resolve as gr}from"resolve.exports";var se=class{constructor(e){this.fetchDts=e}fetchDtsText(e){return this.tryUrls([e])}async tryUrls(e){for(let t of e){let r=await this.fetchDts(t);if(r&&(this.looksLikeDts(r.dts)||/\.(d\.ts|d\.mts)(?:[?#].*)?$/i.test(r.url)||/[?&]dts(?:[&#]|$)/i.test(r.url)))return r}}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},ve=["index.d.ts","index.d.mts"],xe=/\.d\.(ts|mts)$/i;function yt(n){if(xe.test(n))return!0;try{return new URL(n,"file://").search.includes("dts")}catch{return n.includes("?")&&n.includes("dts")}}function Le(n){return[`${n}.d.ts`,`${n}.d.mts`]}async function Se(n,{retries:e=2,timeoutMs:t=15e3,init:r}={}){for(let s=0;s<=e;s++){let o=new AbortController,i=setTimeout(()=>o.abort(),t);try{let a=await fetch(n,{...r,signal:o.signal});if(Nn(a.status)&&s<e)continue;return a}catch{if(s<e)continue;return}finally{clearTimeout(i)}}}function Nn(n){return n===408||n===429||n>=500&&n<600}var Pe=class extends se{constructor(e,t){super(e),this.cdnClient=t}async loadPackageAtVersionedRoot(e,t){let r=this.cdnClient.packageJson(new y({name:e,version:t})),s=await Se(r);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 r of e){let s=await t(r);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([...ve],t);if(!xe.test(s)){let o=await this.tryUntilSuccess(this.declarationCandidatesFor(s),t);if(o)return o}return t(s)}let r=this.declarationCandidatesFor(e.path);return this.tryUntilSuccess([...ve,...r],t)}toResolutionResult(e){return{kind:xe.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let r=t||".",s=e;try{let o=this.extractPathFromResult(gr(s,r,{conditions:["types"]}));if(o)return o}catch{}try{return this.extractPathFromResult(gr(s,r,{browser:!0,conditions:["import","default","module","browser","node"]}))}catch{return}}async resolve(e){try{let t=y.parse(e),{pkg:r,baseDir:s}=await this.loadPackageAtVersionedRoot(t.name,t.version)||{};if(!r||!s)return;let o={name:t.name,version:t.version},i=new y(o).format(),a=new y({...o,subpath:t.subpath}).format(),c=u=>this.fetchCandidateFrom(s,t.name,u);if(t.subpath){let u=this.cdnClient.ensureLeadingDotSlash(t.subpath),h=this.resolveExportsPath(r,u);if(h){let m=await this.resolveFromSelected(this.toResolutionResult(h),c);if(m)return{...m,resolvedPkg:a}}let b=await this.tryUntilSuccess(this.declarationCandidatesFor(u),c);if(b)return{...b,resolvedPkg:a}}let l=r.types??r.typings;if(l){let u=await this.resolveFromSelected({kind:"types",path:l},c);if(u)return{...u,resolvedPkg:i}}let d=this.resolveExportsPath(r,".");if(d){let u=await this.resolveFromSelected(this.toResolutionResult(d),c);if(u)return{...u,resolvedPkg:i}}return}catch{return}}async fetchCandidateFrom(e,t,r){let s=this.cdnClient.normalizeRelative(r),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[...ve];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),r=Le(t),s=t.endsWith("/")?t:`${t}/`;return r.push(...Le(`${s}index`)),r}};import{gunzipSync as jn}from"fflate";var oe=class{async fetchAndExtract(e,t){let r=this.getTarballUrl(e,t),s=await Se(r,{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\//,""),r=t.indexOf("/");return r>0?t.substring(r+1):t}extractDtsFiles(e){let t=new Map;try{let r=jn(e),s=new TextDecoder("utf-8"),o=0;for(;o<r.length-512;){let i=r.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(),d=i.slice(124,136),u=s.decode(d).trim().replace(/\0/g,""),h=parseInt(u,8)||0,b=String.fromCharCode(i[156]);if(o+=512,(b==="0"||b==="\0")&&(l.endsWith(".d.ts")||l.endsWith(".d.mts"))){let m=r.slice(o,o+h);t.set(this.normalizeTarPath(l),s.decode(m))}o+=Math.ceil(h/512)*512}}catch{}return t}},Ln=new oe;var Re=class extends se{constructor(e,t,r,s=new oe){super(e),this.cdnClient=t,this.cache=r,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,r){try{if(r){let o=z.majorOf(r),i=e.filter(a=>z.majorOf(a)===o);if(i.length)return i.sort((a,c)=>z.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 r=new y(e),s=r.version;if(!s)return;let o;try{o=await this.tarballFetcher.fetchAndExtract(r.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 r of this.typesNameCandidates(t.name)){let s=`@types/${r}`,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 Ee=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,r=(s,o)=>(t.add(s[o]),null);return this.matchAll(e,/(import|export)\s+[^'"\n]*from\s*['"]([^'"\n]+)['"]/,s=>r(s,2)),this.matchAll(e,/export\s*\*\s*from\s*['"]([^'"\n]+)['"]/,s=>r(s,1)),Array.from(t)}matchAll(e,t,r){let s=[];try{let o=new RegExp(t.source,"g"),i;for(;i=o.exec(e);){let a=r(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 yr="file:///node_modules",ke=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`${yr}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let r=Bn(t);return`${yr}/${this.epochDir()}/${e}/${r}`}};function Bn(n){let e=n||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as Un}from"lru-cache";function bt(n){let e=new Un({ttl:1e4,max:500}),t=new Map;return async function(s){try{if(await n.isNegative(s))return;let o=e.get(s);if(o&&Date.now()-o<1e4)return;let i=await n.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 n.recordNegative(s));return}let d=await l.text(),u=l.url||s;return await n.clearNegative(s),await n.setCachedFile(u,d),{dts:d,url:u}})();return t.set(s,c),await c.finally(()=>t.delete(s))}catch{return}}}var Be=class{constructor(e){this.inFlight=new Map,this.scanner=new Ee,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=bt(e.cache),this.typescriptProvider=new Pe(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new Re(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new ke}withInFlight(e,t){let r=this.inFlight.get(e);if(r)return r;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,r){e.some(s=>s.path===t)||e.push({path:t,content:r})}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 r=new y(e);return r.subpath?this.fetchRootDts(r.name,t):void 0}async fetchViaProviders(e){for(let t of[this.typescriptProvider,this.definitelyTypedProvider])try{let r=await t.resolve(e);if(r?.dts)return r}catch{}}subpathsMatch(e,t){return new y(e).subpath===new y(t).subpath}async fetchRootDts(e,t){let{effectivePackage:r,root:s,pinned:o}=await this.versionResolver.effectivePackage(e,t),i=await this.cache.getCachedDts(r);if(i?.content){let c=i.url??this.cdnClient.file(o?`${s}@${o}`:s,"index.d.ts");return{dts:i.content,url:c,resolvedPkg:r}}let a;try{a=await this.fetchViaProviders(r)}catch{return}if(!(!a?.dts||!a.url)){try{await this.cache.setCachedFile(a.url,a.dts)}catch{}if(this.subpathsMatch(r,a.resolvedPkg||r)){try{await this.cache.setCachedDts(r,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,r){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(r,s)}computeEntryPath(e,t){if(!e)return{mainPath:this.virtualFs.pathForMain(t),packageRootUrl:void 0};let r=new URL(e),s=this.extractPackageRootUrl(r);return{mainPath:this.toVirtualPath(s,r,t),packageRootUrl:s}}async expandRelativeRefs(e,t,r,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 d of l)await this.tryRelativeRef(d,c,i,r,s,o)}catch{}}async tryRelativeRef(e,t,r,s,o,i){try{let a=new URL(e,t),c=a.pathname+a.search,l=yt(c)?[c]:this.typescriptProvider.declarationCandidatesFor(c);for(let d of l){let h=new URL(d,a).toString();if(i.has(h))return;let b=await this.fetchDts(h);if(b?.dts){let m=this.toVirtualPath(r,new URL(b.url),s);this.pushFileIfNew(o,m,b.dts),await this.expandRelativeRefs(b.dts,b.url,s,o,i,r);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new y(e).name!==new y(t).name}ambientlyDeclares(e,t){for(let r of e.matchAll(/declare\s+module\s+['"]([^'"]+)['"]/g)){let s=r[1];if(s===t||s.endsWith("/*")&&t.startsWith(s.slice(0,-1)))return!0}return!1}markFileAmbient(e,t){let r=e.find(s=>s.path===t);r&&(r.ambient=!0)}async prefetchBareDeps(e,t,r,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=Wn(H.prefetchConcurrency);await Promise.all(i.map(l=>c(()=>this.prefetchBareDepsRecursive(l,r,s,H.maxBareDepth,a,o).catch(()=>{}))))}catch{}}async prefetchBareDepsRecursive(e,t,r,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):r.push({module:e,path:l}),a.url&&await this.expandRelativeRefs(a.dts,a.url,c,t);let d=this.capArray(this.scanner.collectBareModuleRefs(a.dts),H.maxBareDeps).filter(u=>!o.has(u));for(let u of d)await this.prefetchBareDepsRecursive(u,t,r,s-1,o,i)}async resolve(e,t,r){let s=await this.packageService.extractImports(e),o=r?[...s,...r]:s;return(await Promise.all(o.map(a=>this.resolveOne(a,t)))).filter(a=>!!a)}async resolveOne(e,t){let{effectivePackage:r}=await this.versionResolver.effectivePackage(e,t);return this.withInFlight(r,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,r,s){let{dts:o,url:i,resolvedPkg:a}=t,c=new y(a||r),l=c.version?`${c.name}@${c.version}`:c.name,{mainPath:d,packageRootUrl:u}=this.computeEntryPath(i,l),h=[{path:d,content:o}],b=[];i&&await this.expandRelativeRefs(o,i,l,h,void 0,u);let m=h.map($=>$.content).join(`
|
|
251
|
-
`);await this.prefetchBareDeps(
|
|
252
|
-
`,"utf8")}async function
|
|
255
|
+
`;var Y=class{constructor(e){this.store=e}async isNegative(e){let t=await Ne(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let n=((await Ne(()=>this.store.get(e)))?.attempts||0)+1;await Ne(()=>this.store.set(e,{until:Date.now()+Jn(n),attempts:n}))}async clearNegative(e){await Ne(()=>this.store.delete(e))}};function Jn(r){return Math.min(9e5*Math.pow(2,Math.max(0,r-1)),864e5)}async function Ne(r){try{return await r()}catch{return}}import Kn from"p-limit";import{resolve as br}from"resolve.exports";var oe=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},xe=["index.d.ts","index.d.mts"],Se=/\.d\.(ts|mts)$/i;function vt(r){if(Se.test(r))return!0;try{return new URL(r,"file://").search.includes("dts")}catch{return r.includes("?")&&r.includes("dts")}}function Le(r){return[`${r}.d.ts`,`${r}.d.mts`]}async function Re(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(Vn(a.status)&&s<e)continue;return a}catch{if(s<e)continue;return}finally{clearTimeout(i)}}}function Vn(r){return r===408||r===429||r>=500&&r<600}var Pe=class extends oe{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 Re(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([...xe],t);if(!Se.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([...xe,...n],t)}toResolutionResult(e){return{kind:Se.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let n=t||".",s=e;try{let o=this.extractPathFromResult(br(s,n,{conditions:["types"]}));if(o)return o}catch{}try{return this.extractPathFromResult(br(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[...xe];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),n=Le(t),s=t.endsWith("/")?t:`${t}/`;return n.push(...Le(`${s}index`)),n}};import{gunzipSync as Hn}from"fflate";var ie=class{async fetchAndExtract(e,t){let n=this.getTarballUrl(e,t),s=await Re(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=Hn(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}},qn=new ie;var Ee=class extends oe{constructor(e,t,n,s=new ie){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=K.majorOf(n),i=e.filter(a=>K.majorOf(a)===o);if(i.length)return i.sort((a,c)=>K.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 ke=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 vr="file:///node_modules",Te=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`${vr}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let n=zn(t);return`${vr}/${this.epochDir()}/${e}/${n}`}};function zn(r){let e=r||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as Gn}from"lru-cache";function wt(r){let e=new Gn({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 Be=class{constructor(e){this.inFlight=new Map,this.scanner=new ke,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=wt(e.cache),this.typescriptProvider=new Pe(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new Ee(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new Te}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>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=vt(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),H.maxBareDeps).filter(l=>this.isDifferentPackage(l,t));if(!i.length)return;let a=new Set([t]),c=Kn(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 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(T=>T.content).join(`
|
|
256
|
+
`);await this.prefetchBareDeps(g,l,h,m,s);let S=c.format(),j=e===S?[e]:[e,S],B=j.some(T=>this.ambientlyDeclares(o,T));return B?this.markFileAmbient(h,p):m.push(...j.map(T=>({module:T,path:p}))),{pkg:e,mainPath:p,files:h,shims:m,ambient:B}}};function xt(r){return new Be(r)}import*as L from"fs/promises";import*as W from"path";import*as Sr from"os";import*as St from"fs/promises";import*as wr from"crypto";function D(r){return wr.createHash("sha1").update(r).digest("hex")}async function X(r){try{return JSON.parse(await St.readFile(r,"utf8"))}catch{return}}async function Ue(r){try{return await St.readFile(r,"utf8")}catch{return}}var xr=1,q=W.join(Sr.homedir(),".typebulb","cache"),_e=W.join(q,"packages"),Ce=W.join(q,"proxy"),We=W.join(q,"dts"),Yn=W.join(q,"emit"),Rt;function x(){return Rt||(Rt=Xn()),Rt}function Je(r,e){return W.join(Yn,D(r),e)}async function Xn(){await L.mkdir(q,{recursive:!0});let r=W.join(q,"version.json");if((await Qn(r))?.version===xr)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:xr})+`
|
|
257
|
+
`,"utf8")}async function Qn(r){try{let e=await L.readFile(r,"utf8");return JSON.parse(e)}catch{return}}import*as z from"fs/promises";import*as Rr from"path";async function O(r,e){await z.mkdir(Rr.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 ae=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=X(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 O(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var Pt=$.join(_e,"indexes"),Pr=$.join(_e,"pinned"),Zn=$.join(_e,"meta"),es=$.join(_e,"negative.json"),ce=Symbol("missing"),He=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new Y(new ae(es));async getPinnedExact(e,t){let n=`${e}@${t}`,s=this.pinnedMem.get(n);if(s!==void 0)return s===ce?void 0:s;await x();let o=await Ue($.join(Pr,D(n)+".txt"));return this.pinnedMem.set(n,o??ce),o}async setPinnedExact(e,t,n){let s=`${e}@${t}`;this.pinnedMem.set(s,n),await x(),await O($.join(Pr,D(s)+".txt"),n)}async getIndex(e){let t=this.indexMem.get(e);if(t!==void 0)return t===ce?void 0:t;await x();let n=await X($.join(Pt,Ve(e)+".json"));return this.indexMem.set(e,n??ce),n}async setIndex(e,t,n){let s={versions:t,distTags:n,updatedAt:Date.now()};this.indexMem.set(e,s),await x(),await O($.join(Pt,Ve(e)+".json"),JSON.stringify(s))}async invalidateVersionsCache(e){this.indexMem.delete(e),await kr.rm($.join(Pt,Ve(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===ce?void 0:s;await x();let o=await X(Er(e,t));return this.metaMem.set(n,o??ce),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 O(Er(e,t),JSON.stringify(i))}};function Er(r,e){return $.join(Zn,Ve(r),encodeURIComponent(e)+".json")}function Ve(r){return r.replace(/\//g,"__")}var Tr={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 ts=new He,{packageService:qe,versionResolver:_r,cdnClient:Cr,peerResolver:da}=ur(ts,Tr);var Or=`
|
|
253
258
|
(() => {
|
|
254
259
|
// Embedded (bulb-in-a-bulb): runs inside a sandboxed iframe with no parent
|
|
255
260
|
// bridge, so privileged tb.* (AI, fs, server RPC) can't reach a host and would
|
|
@@ -459,12 +464,12 @@ declare const tb: {${dr}${ur}${pr}${mr}${Dn}${fr}${hr}
|
|
|
459
464
|
};
|
|
460
465
|
}
|
|
461
466
|
})();
|
|
462
|
-
`;function
|
|
467
|
+
`;function Ir(r){let{name:e,code:t,css:n,html:s,data:o,insight:i,importMap:a,watch:c,theme:l}=r,p=s.trim()||'<div id="app"></div>',d=m=>m.replace(/<\/script/gi,"<\\/script"),h={imports:ss(a.imports)};return`<!DOCTYPE html>
|
|
463
468
|
<html>
|
|
464
469
|
<head>
|
|
465
470
|
<meta charset="utf-8">
|
|
466
471
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
467
|
-
<title>${
|
|
472
|
+
<title>${ns(e)} - typebulb</title>
|
|
468
473
|
<script>
|
|
469
474
|
// Theme engine. Sets html[data-theme] before stylesheets paint (no flash) and
|
|
470
475
|
// exposes the tb.theme accessor via window.__tbTheme. The override is persisted
|
|
@@ -472,13 +477,13 @@ declare const tb: {${dr}${ur}${pr}${mr}${Dn}${fr}${hr}
|
|
|
472
477
|
// toggles the effective theme. See Specs/Theme.md.
|
|
473
478
|
(function() {
|
|
474
479
|
try {
|
|
475
|
-
var KEY = ${
|
|
480
|
+
var KEY = ${d(JSON.stringify("tb-theme:"+e))};
|
|
476
481
|
var doc = document.documentElement;
|
|
477
482
|
var mq = window.matchMedia('(prefers-color-scheme: dark)');
|
|
478
483
|
var os = function() { return mq.matches ? 'dark' : 'light'; };
|
|
479
484
|
// A host-forced theme (bulb-in-a-bulb) outranks the OS but not an explicit
|
|
480
485
|
// in-iframe override, so the user can still toggle the embed independently.
|
|
481
|
-
var FORCED = ${
|
|
486
|
+
var FORCED = ${d(JSON.stringify(l??null))};
|
|
482
487
|
var stored = function() {
|
|
483
488
|
try { var v = localStorage.getItem(KEY); return (v === 'dark' || v === 'light') ? v : undefined; }
|
|
484
489
|
catch (e) { return undefined; }
|
|
@@ -519,27 +524,27 @@ ${JSON.stringify(h,null,2)}
|
|
|
519
524
|
html[data-theme="light"] { color-scheme: light; }
|
|
520
525
|
</style>
|
|
521
526
|
<style>
|
|
522
|
-
${
|
|
527
|
+
${n}
|
|
523
528
|
</style>
|
|
524
529
|
</head>
|
|
525
530
|
<body>
|
|
526
|
-
${
|
|
531
|
+
${p}
|
|
527
532
|
|
|
528
|
-
${o.length>0?`<script>window.__TB_DATA__ = ${
|
|
529
|
-
${i?`<script>window.__TB_INSIGHT__ = ${
|
|
533
|
+
${o.length>0?`<script>window.__TB_DATA__ = ${d(JSON.stringify(o))};</script>`:""}
|
|
534
|
+
${i?`<script>window.__TB_INSIGHT__ = ${d(JSON.stringify(i))};</script>`:""}
|
|
530
535
|
${c?"<script>window.__TYPEBULB_WATCH__ = true;</script>":""}
|
|
531
536
|
|
|
532
537
|
<script>
|
|
533
|
-
${
|
|
538
|
+
${Or}
|
|
534
539
|
</script>
|
|
535
540
|
|
|
536
|
-
${
|
|
541
|
+
${rs}
|
|
537
542
|
|
|
538
543
|
<script type="module">
|
|
539
|
-
${
|
|
544
|
+
${d(t)}
|
|
540
545
|
</script>
|
|
541
546
|
</body>
|
|
542
|
-
</html>`}var
|
|
547
|
+
</html>`}var rs=`<script>
|
|
543
548
|
(function () {
|
|
544
549
|
if (window.parent === window) return;
|
|
545
550
|
var de = document.documentElement;
|
|
@@ -554,17 +559,36 @@ ${u(t)}
|
|
|
554
559
|
// viewport for a short bulb (so the frame shrinks to it), tracking the frame for a
|
|
555
560
|
// full-bleed one (so it self-stabilises at the host's initial height).
|
|
556
561
|
//
|
|
562
|
+
// Showing the Y scrollbar is DEFERRED; hiding it stays eager. Content grows (a new
|
|
563
|
+
// row, an expanded panel) synchronously, but the frame only grows a beat later, after
|
|
564
|
+
// the host receives the height message and resizes the iframe. In that gap body is
|
|
565
|
+
// taller than the still-old frame, so an eager overflow:auto flashes a scrollbar for
|
|
566
|
+
// exactly the round-trip. So when Y overflows we post the height and re-check after a
|
|
567
|
+
// short delay instead of flipping immediately: if the frame caught up the overflow is
|
|
568
|
+
// gone (no bar), and only an overflow that SURVIVES \u2014 a genuine host cap \u2014 gets auto.
|
|
569
|
+
// The host can't tell the iframe its cap (no host\u2192iframe channel), so this round-trip
|
|
570
|
+
// is how the embed distinguishes "frame about to grow" from "frame capped". X has no
|
|
571
|
+
// async resize (the host never grows width on content), so it flips inline.
|
|
572
|
+
//
|
|
557
573
|
// Coalesce to one rAF and only write an overflow value that actually changed: setting
|
|
558
574
|
// overflow adds/removes a scrollbar, which resizes the element and re-fires the
|
|
559
575
|
// observer \u2014 writing unconditionally ping-pongs (the "ResizeObserver loop" warning).
|
|
560
|
-
// The rAF + equality guard let it settle within a frame instead.
|
|
561
576
|
var raf = 0;
|
|
577
|
+
var confirm = 0;
|
|
578
|
+
var showYScroll = function () {
|
|
579
|
+
confirm = 0;
|
|
580
|
+
if (de.scrollHeight > de.clientHeight + 1 && de.style.overflowY !== 'auto') de.style.overflowY = 'auto';
|
|
581
|
+
};
|
|
562
582
|
var apply = function () {
|
|
563
583
|
raf = 0;
|
|
564
|
-
var
|
|
565
|
-
var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
|
|
566
|
-
if (de.style.overflowY !== oy) de.style.overflowY = oy;
|
|
584
|
+
var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
|
|
567
585
|
if (de.style.overflowX !== ox) de.style.overflowX = ox;
|
|
586
|
+
if (de.scrollHeight > de.clientHeight + 1) {
|
|
587
|
+
if (de.style.overflowY !== 'auto' && !confirm) confirm = setTimeout(showYScroll, 100);
|
|
588
|
+
} else {
|
|
589
|
+
if (confirm) { clearTimeout(confirm); confirm = 0; }
|
|
590
|
+
if (de.style.overflowY !== 'hidden') de.style.overflowY = 'hidden';
|
|
591
|
+
}
|
|
568
592
|
post({ __typebulbEmbed: true, kind: 'height', height: Math.ceil(document.body.scrollHeight) });
|
|
569
593
|
};
|
|
570
594
|
var update = function () { if (!raf) raf = requestAnimationFrame(apply); };
|
|
@@ -591,34 +615,36 @@ ${u(t)}
|
|
|
591
615
|
}
|
|
592
616
|
});
|
|
593
617
|
})();
|
|
594
|
-
</script>`;function
|
|
618
|
+
</script>`;function ns(r){return r.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function ss(r){let e={};for(let[t,n]of Object.entries(r))e[t]=n.startsWith("https://")?"/proxy/"+n:n;return e}import*as Ge from"fs/promises";import*as ze from"path";import{existsSync as Ar,readFileSync as os}from"fs";import{execFile as is}from"child_process";import{promisify as as}from"util";import{satisfies as cs}from"semver";var ls=as(is);async function Ke(r,e,t){let s=r.map(i=>ds(i,t)).filter(i=>!us(i,e));if(s.length===0)return;await Ge.mkdir(e,{recursive:!0});let o=ze.join(e,"package.json");Ar(o)||await Ge.writeFile(o,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${s.join(", ")}`),await ls("npm",["install","--no-audit","--no-fund",...s],{cwd:e,shell:!0})}function ds(r,e){if(!e||$r(r))return r;let t=e[r];return t?`${r}@${t}`:r}function us(r,e){let t=ze.join(e,"node_modules",Dr(r));if(!Ar(t))return!1;let n=$r(r);if(!n)return!0;try{let s=JSON.parse(os(ze.join(t,"package.json"),"utf-8")).version;return cs(s,n)}catch{return!1}}function Ye(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 Dr(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 $r(r){let e=Dr(r);return r.length>e.length?r.slice(e.length+1):""}async function Mr(r){let t=(await G.readdir(r)).find(n=>n.endsWith(".bulb.md"));return t?le.join(r,t):null}async function de(r){let e=await G.readFile(r,"utf-8"),t=nr(e);if(!t)throw new Error("Invalid .bulb.md file format");let n=sr(t);return{bulb:n,config:ir(n.config)}}async function Et(r,e,t,n){let s=ut(r,{serverOnly:!0});if(s.error)throw new Error(`Server compilation error: ${s.error}`);let o=s.code;t&&(o=await er(o,t));let i=le.join(e,".typebulb");await G.mkdir(i,{recursive:!0});let a=Ye(o);a.length>0&&await Ke(a,i,n);let c=le.join(i,"server.mjs");return await G.writeFile(c,o,"utf-8"),await import(`${ps(c).href}?t=${Date.now()}`)}async function kt(r,e,t,n){let{bulb:s,config:o}=await de(r),i=or(s.data),a=ut(s.code,{jsxImportSource:o.jsxImportSource});a.error&&console.error("Compilation error:",a.error);let{importMap:c}=await qe.buildImportMap(a.code,o.dependencies??{},n?new Set([n.name]):void 0);n&&(c.imports[n.name]=n.entryUrl);let l=Ir({name:s.name,code:a.code,css:s.css,html:s.html,data:i,insight:s.insight,importMap:c,watch:e}),p=le.dirname(r),d=null;return s.server&&t&&(d=await Et(s.server,p,n,o.dependencies)),{html:l,bulb:s,serverExports:d}}function Tt(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 xs}from"hono";import{serve as Ss}from"@hono/node-server";import{streamSSE as Rs}from"hono/streaming";import*as ee from"fs/promises";import*as F from"path";var I=class extends Error{constructor(e,t="unknown",n=!1){super(e),this.code=t,this.retryable=n}},M=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=`
|
|
595
619
|
|
|
596
|
-
`){let
|
|
620
|
+
`){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 I(t,n,s)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new I(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 Oe=class extends M{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(`
|
|
597
621
|
|
|
598
|
-
`);return{text:t,reasoning:
|
|
599
|
-
`)),!t&&s.type==="message"&&s.content&&(t=s.content.filter(o=>o.type==="output_text").map(o=>o.text).join(""));return{text:t,reasoning:
|
|
622
|
+
`);return{text:t,reasoning:n||void 0}}parseProviderStreamChunk(e){if(!("type"in e))return null;switch(e.type){case"content_block_delta":return e.delta.type==="text_delta"?{text:e.delta.text||""}:e.delta.type==="thinking_delta"?{reasoning:e.delta.thinking||""}:null;case"message_start":case"content_block_start":case"content_block_stop":case"message_delta":case"message_stop":case"ping":return null;default:return null}}withLastMessageCached(e){let t=e.length-1;return e.map((n,s)=>s===t?{role:n.role,content:[{type:"text",text:n.content,cache_control:{type:"ephemeral"}}]}:n)}isAnthropicResponse(e){return"content"in e&&Array.isArray(e.content)&&"type"in e&&e.type==="message"}isModernModel(e){let t=e.match(/^claude-\w+-(\d+)-(\d+)/);return!!t&&(+t[1]>4||+t[1]==4&&+t[2]>=6)}getMaxTokens(e){return this.isModernModel(e)?64e3:32e3}};var Ie=class extends M{constructor(){super(...arguments),this.providerName="OpenAI",this.defaultBaseUrl="https://api.openai.com",this.path="/v1/responses",this.effortMap={0:"minimal",1:"low",2:"medium",3:"high"}}buildHeaders(e){return{Authorization:`Bearer ${e}`,"Content-Type":"application/json",Accept:"application/json"}}buildPayload(e,t,n,s){let o=this.convertMessagesToInput(e),i={model:t,input:o,stream:s};return n?.webSearch!==!1&&(i.tools=[{type:"web_search"}]),this.isReasoningEnabled(n)&&(i.reasoning={effort:this.effortMap[n.reasoning],summary:"auto"}),i}parseError(e,t){return this.parseJsonError(e,t,!0)}parseNonStreamingResponse(e){if(!this.isResponsesApiResponse(e))return{text:""};let t=e.output_text||"",n;if(e.output&&Array.isArray(e.output))for(let s of e.output)s.type==="reasoning"&&s.summary&&(n=s.summary.map(o=>o.text).join(`
|
|
623
|
+
`)),!t&&s.type==="message"&&s.content&&(t=s.content.filter(o=>o.type==="output_text").map(o=>o.text).join(""));return{text:t,reasoning:n}}parseProviderStreamChunk(e){if(!this.isResponsesApiEvent(e))return null;switch(e.type){case"error":return null;case"response.failed":{let s=e.response?.error,o=s?.message||"Response failed",i=s?.code==="insufficient_quota"||s?.code==="rate_limit_exceeded";throw new I(o,i?"rate_limit":"unknown",i)}case"response.output_text.delta":return{text:e.delta};case"response.reasoning_summary_text.delta":return{reasoning:e.delta};case"response.created":case"response.in_progress":case"response.output_item.added":case"response.output_item.done":case"response.content_part.added":case"response.content_part.done":case"response.output_text.done":case"response.output_text.annotation.added":case"response.reasoning_summary_text.done":case"response.completed":case"response.web_search_call.in_progress":case"response.web_search_call.searching":case"response.web_search_call.completed":return null;default:return null}}convertMessagesToInput(e){return e.map(t=>t.role==="system"?`System: ${t.content}`:t.role==="user"?`User: ${t.content}`:t.role==="assistant"?`Assistant: ${t.content}`:t.content).join(`
|
|
600
624
|
|
|
601
|
-
`)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var Ae=class extends
|
|
602
|
-
`),c={contents:i.map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.content}]}))};return
|
|
603
|
-
`)[0],type:s.status,code:s.code?.toString()}:
|
|
625
|
+
`)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var Ae=class extends M{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,`
|
|
626
|
+
`),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(`
|
|
627
|
+
`)[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 I(n)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new I(`Prompt blocked: ${t}`)}}};var De=class extends M{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 fs=new Map([["openai",new Ie],["openrouter",new De],["anthropic",new Oe],["gemini",new Ae]]);function Q(r){let e=fs.get(r);if(!e)throw new Error(`Unsupported protocol: ${r}`);return e}async function _t(r,e){let t=Q(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 Ct(r,e){let t=Q(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 Fr(r){let e=r.indexOf(`\r
|
|
604
628
|
\r
|
|
605
|
-
`),t=
|
|
606
|
-
|
|
607
|
-
`);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function
|
|
608
|
-
`).trim();if(!
|
|
609
|
-
${c}`:"";return
|
|
610
|
-
`,"utf8"),await k.writeFile(E.join(e,"code.tsx"),
|
|
611
|
-
`,"utf8"),{dir:e}}function
|
|
612
|
-
`);let
|
|
613
|
-
${
|
|
629
|
+
`),t=r.indexOf(`
|
|
630
|
+
|
|
631
|
+
`);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function Ot(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(`
|
|
632
|
+
`).trim();if(!n)return null;if(n==="[DONE]")return"done";try{return JSON.parse(n)}catch{return null}}async function jr(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=Ot(s);h!==null&&h!=="done"&&e(h)}break}o=!0,s+=n.decode(l,{stream:!0});let{pos:p,len:d}=Fr(s);for(;p!==-1;){let h=s.slice(0,p);s=s.slice(p+d);let m=Ot(h);if(m==="done"){s="";break}m!==null&&e(m),{pos:p,len:d}=Fr(s)}}return{receivedAnyData:o}}async function It(r,e){let t=e??(r.headers.get("X-Provider-Protocol")||"openai"),n=Q(t);if(!r.body)throw new Error("Response body is missing");let s=r.body.getReader(),o="";return await jr(s,i=>{let a=n.parseStreamChunk(i);a?.text&&(o+=a.text)}),o}import*as At from"fs/promises";import*as $e from"path";var Xe=class{async get(e){let t=D(e),n=$e.join(Ce,t+".bin"),s=$e.join(Ce,t+".json");try{let[o,i]=await Promise.all([At.readFile(n),At.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=D(e),s=$e.join(Ce,n+".bin"),o=$e.join(Ce,n+".json"),i={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([O(s,t.body),O(o,JSON.stringify(i))])}};import{readdir as gs,readFile as Br,writeFile as Ur,unlink as Me,mkdir as ys}from"fs/promises";import{mkdirSync as bs,writeFileSync as Nr,appendFileSync as vs,readFileSync as Wr}from"fs";import*as pe from"path";import{join as Dt,resolve as hs}from"path";import{homedir as ms}from"os";function Qe(){let r=process.env.TYPEBULB_SERVERS_DIR;return r?Dt(r,".."):Dt(ms(),".typebulb")}function Z(){return process.env.TYPEBULB_SERVERS_DIR||Dt(Qe(),"servers")}function ue(r){let e=hs(r);return(process.platform==="win32"?e.toLowerCase():e).replace(/\\/g,"/")}var Lr=1e6;function $t(r){return pe.join(Z(),`${r}.json`)}function Ze(r){return pe.join(Z(),`${r}.log`)}function Jr(r){let e=Ze(r);try{bs(Z(),{recursive:!0}),Nr(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(vs(e,c),s+=c.length,s>2*Lr){let l=Wr(e),p=l.subarray(Math.max(0,l.length-Lr));Nr(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 Mt(r,e=0){try{let t=Wr(Ze(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 ws(r){try{return process.kill(r,0),!0}catch(e){return e.code==="EPERM"}}async function Vr(r){await ys(Z(),{recursive:!0}),await Ur($t(r.pid),JSON.stringify(r))}async function Hr(r,e){let t=$t(r);try{let n=JSON.parse(await Br(t,"utf8"));if(n.denied===e)return;n.denied=e,await Ur(t,JSON.stringify(n))}catch{}}async function Ft(r){await Me($t(r)).catch(()=>{}),await Me(Ze(r)).catch(()=>{})}async function jt(){let r;try{r=await gs(Z())}catch{return[]}let e=[];return await Promise.all(r.map(async t=>{if(!t.endsWith(".json"))return;let n=pe.join(Z(),t),s;try{s=JSON.parse(await Br(n,"utf8"))}catch{await Me(n).catch(()=>{});return}s&&typeof s.pid=="number"&&ws(s.pid)?e.push(s):(await Me(n).catch(()=>{}),s?.pid&&await Me(Ze(s.pid)).catch(()=>{}))})),e.sort((t,n)=>t.startedAt-n.startedAt)}async function qr(r){try{process.kill(r,"SIGTERM")}catch{}await Ft(r)}var Kr="127.0.0.1",Ps=new Set(["localhost","127.0.0.1","::1"]);function Es(r){if(r)try{return new URL(r.includes("://")?r:`http://${r}`).hostname}catch{return}}function zr(r){let e=Es(r);return!!e&&Ps.has(e)}function et(r){return r instanceof Error?r.message:"Unknown error"}async function Yr(r){let{getHtml:e,basePath:t,port:n,reloadEmitter:s,getServerExports:o,localOverride:i,trusted:a=!1,trustHint:c}=r,l=new xs;l.use("*",async(u,f)=>{if(!zr(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 y=new URL(u.req.url).pathname,w=y.startsWith("/__fs")?"the filesystem":y==="/__ai"?"AI (your API keys)":"server-side code (server.ts)";Hr(process.pid,w);let v=c?`
|
|
633
|
+
${c}`:"";return u.text(`Forbidden: this capability requires --trust.${v}`,403)}await f()},h=async(u,f)=>{let y=u.req.header("sec-fetch-site");if(y){if(y==="cross-site")return u.text("Forbidden: cross-site request",403)}else{let w=u.req.header("origin");if(w&&!zr(w))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(),y=Lt(f,t),w=await ee.readFile(y);return new Response(new Uint8Array(w),{headers:{"Content-Type":"application/octet-stream"}})}catch(f){let y=et(f);return u.json({error:y},400)}}),l.post("/__fs/write",async u=>{try{let f=u.req.query("path");if(!f)return u.json({error:"Missing path"},400);let y=Lt(f,t);return await ee.mkdir(F.dirname(y),{recursive:!0}),await ee.writeFile(y,Buffer.from(await u.req.arrayBuffer())),u.json({success:!0})}catch(f){let y=et(f);return u.json({error:y},400)}});let m={log:console.log};l.post("/__api/:name",async u=>{try{let f=o?.(),y=u.req.param("name"),w=f?.[y]??m[y];if(!w||typeof w!="function")return u.json({error:`API function '${y}' not found`},404);let{args:v}=await u.req.json(),C=await w(...v||[]);return u.json({result:C})}catch(f){let y=et(f);return u.json({error:y},500)}}),l.post("/__ai",async u=>{try{let{messages:f,system:y,reasoning:w,provider:v,model:C,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=ks(v,C);if(typeof N=="string")return u.json({message:N,code:"unknown",retryable:!1},400);let ot=[...y?[{role:"system",content:y}]:[],...f.map(Fe=>({role:Fe.role,content:Fe.content}))],te=await _t(N,{model:N.model,messages:ot,stream:!0,reasoning:w??0,webSearch:V??!0});if(!te.ok){let Fe=await Ct(te,N.protocol);return u.json(Fe,te.status)}let qt=await It(te,N.protocol);return qt||console.warn("[tb.ai] Empty response from provider"),u.json({text:qt})}catch(f){if(f instanceof I)return u.json({message:f.message,code:f.code,retryable:f.retryable},500);let y=et(f);return u.json({message:y,code:"unknown",retryable:!1},500)}}),l.get("/__models",async u=>{try{let f=await Cs();return u.json(f)}catch{return u.json([],200)}});let g=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"],S=new Xe;if(l.get("/proxy/*",async u=>{let f=new URL(u.req.url),w=(f.pathname+f.search).slice(7),v=w.lastIndexOf("https://");return v===-1?u.text("Invalid proxy URL",400):j(u,w.slice(v))}),i){let u=`/local/${i.name}/`;l.get("/local/*",async f=>{let{pathname:y}=new URL(f.req.url);if(!y.startsWith(u))return f.text("Not Found",404);let w=decodeURIComponent(y.slice(u.length));try{let v=Lt(w,i.serveDir),C=await ee.readFile(v);return new Response(C,{headers:{"Content-Type":Os(v)}})}catch{return f.text("Not Found",404)}})}async function j(u,f){let y;try{y=new URL(f)}catch{return u.text("Invalid URL",400)}if(y.protocol!=="https:")return u.text("HTTPS only",400);if(!g.includes(y.hostname))return u.text("Host not allowed",403);let w=await S.get(f);if(w)return new Response(w.body,{status:200,headers:Nt(w.contentType,w.cacheControl)});try{let v=await fetch(f,{headers:{Accept:u.req.header("Accept")||"*/*"},redirect:"follow"});if(!v.ok)return u.text(`Upstream ${v.status}`,v.status);let C=v.headers.get("Content-Type")||void 0,V=v.headers.get("Cache-Control")||void 0;if(v.body){let[N,ot]=v.body.tee();return(async()=>{try{let te=await new Response(ot).arrayBuffer();await S.set(f,{body:Buffer.from(te),contentType:C,cacheControl:V})}catch{}})(),new Response(N,{status:v.status,headers:Nt(C,V)})}return new Response(null,{status:v.status,headers:Nt(C,V)})}catch(v){return u.text(`Proxy fetch failed: ${v instanceof Error?v.message:v}`,502)}}s&&l.get("/__reload",u=>Rs(u,async f=>{let y=()=>{f.writeSSE({event:"reload",data:""})};for(s.on("reload",y),f.onAbort(()=>{s.removeListener("reload",y)});;)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 T=Ss({fetch:l.fetch,port:n,hostname:Kr});return{port:n,close:()=>T.close()}}var Xr={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function ks(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=Q(t)}catch{return`Unknown provider '${t}'.`}let o=Xr[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 Ts="https://api.typebulb.com/api/models",_s=1440*60*1e3,fe=null;async function Cs(){if(!fe||Date.now()-fe.fetchedAt>_s){let r=await fetch(Ts);if(!r.ok)return fe?Gr(fe.models):[];fe={models:await r.json(),fetchedAt:Date.now()}}return Gr(fe.models)}function Gr(r){let e=new Set(Object.entries(Xr).filter(([,t])=>!!process.env[t]).map(([t])=>t));return r.filter(t=>e.has(t.provider))}function Nt(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 Os(r){switch(F.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 Lt(r,e){let t=F.resolve(e,r),n=F.normalize(e),s=F.normalize(t);if(s!==n&&!s.startsWith(n+F.sep))throw new Error("Path traversal detected - access denied");return t}async function Bt(r){let e=await import("net");return new Promise(t=>{let n=e.createServer();n.listen(r,Kr,()=>{let s=n.address(),o=typeof s=="object"&&s?s.port:r;n.close(()=>t(o))}),n.on("error",()=>{t(Bt(r+1))})})}import Is from"open";async function Qr(r){await Is(r)}import Zr from"chokidar";var en={persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}};function Ut(r){let{bulbPath:e,emitter:t}=r,n=Zr.watch(e,en);return n.on("change",()=>{t.emit("reload")}),()=>n.close()}function tn(r){let{dir:e,onChange:t,debounceMs:n=150}=r,s,o=Zr.watch(e,en);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 he from"path";var As=he.join(We,"pkg"),Ds=he.join(We,"files"),$s=he.join(We,"negative.json"),rt=class{pkgMem=new Map;fileMem=new Map;negativeCache=new Y(new ae($s));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await x();let t=await X(rn(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 tt(async()=>{await x(),await O(rn(e),JSON.stringify(s))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await x();let t=await Ue(nn(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await tt(async()=>{await x(),await O(nn(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await tt(async()=>{await x(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return tt(()=>this.negativeCache.clearNegative(e))}};async function tt(r){try{await r()}catch{}}function rn(r){return he.join(As,D(r)+".json")}function nn(r){return he.join(Ds,D(r)+".txt")}var Wt;function Ms(){return Wt||(Wt=xt({cache:new rt,cdnClient:Cr,packageService:qe,versionResolver:_r})),Wt}var sn="file:///node_modules/";async function on(r){let e=Je(r.emitKey,"typecheck");await x(),await k.rm(e,{recursive:!0,force:!0}),await k.mkdir(e,{recursive:!0});let t=Ls(r.jsxImportSource,r.dependencies),n=await Ms().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=nt(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=nt(d.path);h&&(a[d.module]=[`./node_modules/${h}`])}for(let p of o){if(p.ambient)continue;let d=nt(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=nt(d.path);h&&c.add(`node_modules/${h}`)}if(r.local){delete a[r.local.name];let p=await Bs(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=Fs(r.jsxImportSource,a,[...c]);return await k.writeFile(E.join(e,"tsconfig.json"),JSON.stringify(l,null,2)+`
|
|
634
|
+
`,"utf8"),await k.writeFile(E.join(e,"code.tsx"),r.code,"utf8"),await k.writeFile(E.join(e,"tb.d.ts"),yt,"utf8"),{dir:e}}function Fs(r,e,t=[]){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"bundler",lib:js([...mt,...gt]),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 js(r){return r.filter(e=>!e.since).map(e=>Ns(e.name))}function Ns(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 Ls(r,e){let t=r??("react"in e?"react":void 0);return t?[`${t}/jsx-runtime`,`${t}/jsx-dev-runtime`]:[]}function nt(r){if(!r.startsWith(sn))return;let e=r.slice(sn.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}async function Bs(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 Us(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 Us(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 A from"fs/promises";import*as J from"path";import{existsSync as Ws}from"fs";var Js="^22";async function an(r){let e=Je(r.emitKey,"typecheck-server");await x(),await A.rm(e,{recursive:!0,force:!0}),await A.mkdir(e,{recursive:!0});let t=J.join(r.bulbDir,".typebulb"),n=Ye(r.server).filter(i=>i!==r.local?.name);await Ke([`@types/node@${Js}`,...n],t,r.dependencies);let s=J.join(t,"node_modules"),o=J.join(e,"node_modules");return await Hs(s,o),await A.writeFile(J.join(e,"server.ts"),r.server,"utf8"),await A.writeFile(J.join(e,"tb.d.ts"),bt,"utf8"),await A.writeFile(J.join(e,"tsconfig.json"),JSON.stringify(Vs(r.local),null,2)+`
|
|
635
|
+
`,"utf8"),{dir:e}}function Vs(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 Hs(r,e){if(!Ws(r)){await A.mkdir(e,{recursive:!0});return}await A.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await A.symlink(r,e,t)}import{readFileSync as qs,writeFileSync as zs,mkdirSync as Gs}from"fs";import{join as Ks}from"path";function cn(){return Ks(Qe(),"trust.json")}function Jt(){try{let r=JSON.parse(qs(cn(),"utf8"));return new Set(Array.isArray(r)?r:[])}catch{return new Set}}function Ys(r){Gs(Qe(),{recursive:!0}),zs(cn(),JSON.stringify([...r]))}function Vt(r){return Jt().has(ue(r))}function ln(r,e){let t=Jt(),n=ue(r);(e?t.has(n):!t.has(n))||(e?t.add(n):t.delete(n),Ys(t))}function dn(){return[...Jt()]}var Qs="0.9.5";async function Zs(r,e){let{bulb:t,config:n}=await de(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 on({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 an({server:t.server,bulbDir:P.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 to(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 eo(r,e){let{bulb:t}=await de(r),n=Tt(t);if(Vt(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 to(r){return new Promise(e=>{let t=Xs("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 ro(r,e,t,n){let s=lt(t),o=P.dirname(r),i=!1,a=async()=>{let{bulb:c,config:l}=await de(r);i||(dt(s,r,c.server),i=!0),await Et(c.server,o,n,l.dependencies)};if(console.log(`Running ${P.basename(r)}...`),await a(),e){console.log(`Watching for changes...
|
|
636
|
+
`);let c=new Ht;c.on("reload",async()=>{try{console.log("Re-running..."),await a()}catch(l){console.error("Error:",l)}}),Ut({bulbPath:r,emitter:c})}}async function no(r,e,t,n){let s=process.cwd(),o=Jr(process.pid),i=e.watch?new Ht:void 0,a=lt(e.mode);console.log(`Loading ${P.basename(r)}...`);let{html:c,bulb:l,serverExports:p}=await kt(r,e.watch,e.trust,n);dt(a,r,l.server);let d=await Bt(e.port),h=await Yr({getHtml:()=>c,basePath:s,port:d,reloadEmitter:i,getServerExports:()=>p,localOverride:n?{name:n.name,serveDir:n.serveDir}:void 0,trusted:e.trust,trustHint:t}),m=`http://localhost:${d}`,g=e.trust?void 0:Tt(l);await Vr({pid:process.pid,port:d,url:m,file:r,startedAt:Date.now(),trust:e.trust,predicted:g}),console.log(`
|
|
637
|
+
${l.name}`),console.log(` ${m}`),e.trust?console.log(" trust: granted (filesystem, AI, server.ts enabled)"):console.log(g?` trust: sandboxed \u2014 this bulb appears to use ${g}; re-run with --trust to enable it:
|
|
638
|
+
${t}
|
|
639
|
+
`:` trust: sandboxed \u2014 re-run with --trust to enable filesystem / AI / server.ts
|
|
614
640
|
`),e.watch&&console.log(` Watching for changes...
|
|
615
|
-
`);let
|
|
616
|
-
`)}catch(
|
|
617
|
-
`),i.emit("reload")}})}}e.open&&await
|
|
618
|
-
Shutting down...`),
|
|
619
|
-
`+e)}function
|
|
641
|
+
`);let S,j;if(e.watch&&i){let T=new Ht;if(T.on("reload",async()=>{try{console.log("Recompiling...");let u=await kt(r,!0,e.trust,n);c=u.html,p=u.serverExports,i.emit("reload"),console.log(`Done. Browser reloading...
|
|
642
|
+
`)}catch(u){console.error("Compile error:",u)}}),S=Ut({bulbPath:r,emitter:T}),n){let{name:u,serveDir:f}=n;j=tn({dir:f,onChange:()=>{console.log(`Local package '${u}' changed. Browser reloading...
|
|
643
|
+
`),i.emit("reload")}})}}e.open&&await Qr(m);let B=async()=>{console.log(`
|
|
644
|
+
Shutting down...`),h.close(),S?.(),j?.(),o(),await Ft(process.pid);let T=P.join(P.dirname(r),".typebulb","server.mjs");await st.rm(T,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",B),process.on("SIGTERM",B)}function so(r,e){return/^\d+$/.test(e)?r.find(t=>t.pid===parseInt(e,10)):r.find(t=>ue(t.file)===ue(e))}function un(r,e){for(let t of r)e(` ${t.url} pid ${t.pid} ${t.trust?"trusted":"restricted"} ${t.file}`)}function pn(r,e){if(!r.length){console.log("No running bulb servers.");return}console.log("Running bulb servers:"),un(r,t=>console.log(t)),console.log(`
|
|
645
|
+
`+e)}function fn(r,e,t){let n=so(r,e);if(n)return n;console.error(`No running server for '${e}'.`),r.length?(console.error(`Running servers (try \`typebulb ${t} <file|pid>\`):`),un(r,s=>console.error(s))):console.error("No bulb servers are running."),process.exit(1)}async function oo(r,e){let t=await jt();if(!r){pn(t,"Run `typebulb logs <file|pid>` to print one server's console.");return}let n=fn(t,r,"logs"),s=Mt(n.pid),o=s.text;if(e.lines&&e.lines>0){let i=o.split(`
|
|
620
646
|
`);i.length&&i[i.length-1]===""&&i.pop(),o=i.slice(-e.lines).join(`
|
|
621
647
|
`)}if(process.stdout.write(o),o&&!o.endsWith(`
|
|
622
648
|
`)&&process.stdout.write(`
|
|
623
|
-
`),e.follow){let i=s.offset,a=setInterval(()=>{let l=
|
|
624
|
-
${
|
|
649
|
+
`),e.follow){let i=s.offset,a=setInterval(()=>{let l=Mt(n.pid,i);i=l.offset,l.text&&process.stdout.write(l.text)},500),c=()=>{clearInterval(a),process.exit(0)};process.on("SIGINT",c),process.on("SIGTERM",c),await new Promise(()=>{})}}async function io(r){let e=await jt();if(!r){pn(e,"Run `typebulb stop <file|pid>` to stop one.");return}let t=fn(e,r,"stop");await qr(t.pid),console.log(`Stopped ${P.basename(t.file)} (pid ${t.pid}, ${t.url}).`)}async function ao(r,e){if(!r){e||(console.error("Usage: typebulb untrust <file.bulb.md>"),process.exit(1));let n=dn();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=P.resolve(r);t.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1)),ln(t,e),console.log(e?`Trusted ${P.basename(t)} \u2014 runs with fs / AI / server.ts (no --trust needed).`:`Untrusted ${P.basename(t)} \u2014 runs Restricted.`),console.log(` ${t}`)}async function co(){let r=tr(process.argv.slice(2));if(r.version&&(console.log(`typebulb ${Qs}`),process.exit(0)),r.help&&(rr(),process.exit(0)),r.subcommand==="logs"){await oo(r.file||void 0,{follow:r.follow,lines:r.lines});return}if(r.subcommand==="stop"){await io(r.file||void 0);return}if(r.subcommand==="trust"||r.subcommand==="untrust"){await ao(r.file||void 0,r.subcommand==="trust");return}let e;if(!r.file||r.file==="."){let a=await Mr(process.cwd());a||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=a}else e=P.resolve(r.file);try{await st.access(e)}catch{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 t=r.file&&r.file!=="."?r.file:P.relative(process.cwd(),e)||P.basename(e),n=`npx typebulb --trust ${t.includes(" ")?`"${t}"`:t}`;if(r.subcommand==="predict"){await eo(e,n);return}let s=!r.noTrust&&Vt(e);s&&!r.trust&&console.log("trust: granted from memory (run `typebulb untrust` to revoke)"),r.trust=r.noTrust?!1:r.trust||s;let o;try{o=await de(e)}catch{}let i;if(r.local){o&&!(r.local.name in(o.config.dependencies??{}))&&(console.error(`--replace: '${r.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),o&&(!o.bulb.code||r.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{i=await Zt(r.local)}catch(a){console.error(a instanceof Error?a.message:String(a)),process.exit(1)}console.log(`replace: ${i.name} \u2192 ${P.relative(process.cwd(),i.dir)||"."}`)}if(r.subcommand==="check"){await Zs(e,i);return}if(o&&o.bulb.server&&(!o.bulb.code||r.server)){r.trust||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
|
|
650
|
+
${n}`),process.exit(1)),await ro(e,r.watch,r.mode,i);return}await no(e,r,n,i)}co().catch(r=>{console.error("Error:",r.message),process.exit(1)});
|
package/dist/render.js
CHANGED
|
@@ -439,17 +439,36 @@ ${A(s)}
|
|
|
439
439
|
// viewport for a short bulb (so the frame shrinks to it), tracking the frame for a
|
|
440
440
|
// full-bleed one (so it self-stabilises at the host's initial height).
|
|
441
441
|
//
|
|
442
|
+
// Showing the Y scrollbar is DEFERRED; hiding it stays eager. Content grows (a new
|
|
443
|
+
// row, an expanded panel) synchronously, but the frame only grows a beat later, after
|
|
444
|
+
// the host receives the height message and resizes the iframe. In that gap body is
|
|
445
|
+
// taller than the still-old frame, so an eager overflow:auto flashes a scrollbar for
|
|
446
|
+
// exactly the round-trip. So when Y overflows we post the height and re-check after a
|
|
447
|
+
// short delay instead of flipping immediately: if the frame caught up the overflow is
|
|
448
|
+
// gone (no bar), and only an overflow that SURVIVES \u2014 a genuine host cap \u2014 gets auto.
|
|
449
|
+
// The host can't tell the iframe its cap (no host\u2192iframe channel), so this round-trip
|
|
450
|
+
// is how the embed distinguishes "frame about to grow" from "frame capped". X has no
|
|
451
|
+
// async resize (the host never grows width on content), so it flips inline.
|
|
452
|
+
//
|
|
442
453
|
// Coalesce to one rAF and only write an overflow value that actually changed: setting
|
|
443
454
|
// overflow adds/removes a scrollbar, which resizes the element and re-fires the
|
|
444
455
|
// observer \u2014 writing unconditionally ping-pongs (the "ResizeObserver loop" warning).
|
|
445
|
-
// The rAF + equality guard let it settle within a frame instead.
|
|
446
456
|
var raf = 0;
|
|
457
|
+
var confirm = 0;
|
|
458
|
+
var showYScroll = function () {
|
|
459
|
+
confirm = 0;
|
|
460
|
+
if (de.scrollHeight > de.clientHeight + 1 && de.style.overflowY !== 'auto') de.style.overflowY = 'auto';
|
|
461
|
+
};
|
|
447
462
|
var apply = function () {
|
|
448
463
|
raf = 0;
|
|
449
|
-
var
|
|
450
|
-
var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
|
|
451
|
-
if (de.style.overflowY !== oy) de.style.overflowY = oy;
|
|
464
|
+
var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
|
|
452
465
|
if (de.style.overflowX !== ox) de.style.overflowX = ox;
|
|
466
|
+
if (de.scrollHeight > de.clientHeight + 1) {
|
|
467
|
+
if (de.style.overflowY !== 'auto' && !confirm) confirm = setTimeout(showYScroll, 100);
|
|
468
|
+
} else {
|
|
469
|
+
if (confirm) { clearTimeout(confirm); confirm = 0; }
|
|
470
|
+
if (de.style.overflowY !== 'hidden') de.style.overflowY = 'hidden';
|
|
471
|
+
}
|
|
453
472
|
post({ __typebulbEmbed: true, kind: 'height', height: Math.ceil(document.body.scrollHeight) });
|
|
454
473
|
};
|
|
455
474
|
var update = function () { if (!raf) raf = requestAnimationFrame(apply); };
|
package/dist/servers.d.ts
CHANGED
|
@@ -11,6 +11,9 @@ export interface BulbServer {
|
|
|
11
11
|
startedAt: number
|
|
12
12
|
/** Launched with --trust (filesystem / AI / server.ts enabled)? */
|
|
13
13
|
trust?: boolean
|
|
14
|
+
/** Human label of a capability the proactive scan predicts this untrusted bulb will need
|
|
15
|
+
* (set at register time; probabilistic, not enforcement). */
|
|
16
|
+
predicted?: string
|
|
14
17
|
/** Human label of a privileged capability this untrusted server denied (set by the gate). */
|
|
15
18
|
denied?: string
|
|
16
19
|
}
|
|
@@ -46,6 +49,10 @@ export interface BulbFileInfo {
|
|
|
46
49
|
* each with its frontmatter name (or filename stem) and mtime. */
|
|
47
50
|
export declare function listBulbFiles(cwd: string): BulbFileInfo[]
|
|
48
51
|
|
|
52
|
+
/** Scan a `.bulb.md` and return the privileged capability it probably needs (or undefined),
|
|
53
|
+
* so a host can offer --trust before launching. Probabilistic hint, never enforcement. */
|
|
54
|
+
export declare function predictBulbTrust(file: string): Promise<string | undefined>
|
|
55
|
+
|
|
49
56
|
/** The bulb's `name:` from its leading frontmatter, or undefined if absent. */
|
|
50
57
|
export declare function bulbName(source: string): string | undefined
|
|
51
58
|
|
package/dist/servers.js
CHANGED
|
@@ -1 +1,3 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as v}from"child_process";import{readdir as L,readFile as N,writeFile as pt,unlink as c,mkdir as mt}from"fs/promises";import{mkdirSync as gt,writeFileSync as bt,appendFileSync as ht,readFileSync as k}from"fs";import*as o from"path";import{join as g,resolve as _}from"path";import{homedir as E}from"os";function p(){let e=process.env.TYPEBULB_SERVERS_DIR;return e?g(e,".."):g(E(),".typebulb")}function u(){return process.env.TYPEBULB_SERVERS_DIR||g(p(),"servers")}function b(e){let t=_(e);return(process.platform==="win32"?t.toLowerCase():t).replace(/\\/g,"/")}function $(e){return o.join(u(),`${e}.json`)}function m(e){return o.join(u(),`${e}.log`)}function O(e,t=0){try{let r=k(m(e)),n=t>=0&&t<=r.length?t:0;return{text:r.subarray(n).toString("utf8"),offset:r.length}}catch{return{text:"",offset:0}}}function R(e){try{return process.kill(e,0),!0}catch(t){return t.code==="EPERM"}}async function A(e){await c($(e)).catch(()=>{}),await c(m(e)).catch(()=>{})}async function h(){let e;try{e=await L(u())}catch{return[]}let t=[];return await Promise.all(e.map(async r=>{if(!r.endsWith(".json"))return;let n=o.join(u(),r),s;try{s=JSON.parse(await N(n,"utf8"))}catch{await c(n).catch(()=>{});return}s&&typeof s.pid=="number"&&R(s.pid)?t.push(s):(await c(n).catch(()=>{}),s?.pid&&await c(m(s.pid)).catch(()=>{}))})),t.sort((r,n)=>r.startedAt-n.startedAt)}async function I(e){try{process.kill(e,"SIGTERM")}catch{}await A(e)}var J=e=>new Promise(t=>setTimeout(t,e));async function M(e,t={}){let r=t.cwd??process.cwd(),n=o.resolve(r,e),s=(await h()).find(a=>a.file===n);if(s)return s;let i=["typebulb",...t.trust?["--trust"]:[],e,...t.open===!1?["--no-open"]:[]];(process.platform==="win32"?v("cmd",["/c","start","","/b","npx",...i],{cwd:r,stdio:"ignore",windowsHide:!0}):v("npx",i,{cwd:r,detached:!0,stdio:"ignore"})).unref();let l=Date.now()+2e4;for(;Date.now()<l;){await J(150);let a=(await h()).find(f=>f.file===n);if(a)return a}throw new Error(`Launched ${o.basename(e)} but it did not register within 20s.`)}import{readdirSync as K,readFileSync as z,statSync as H}from"fs";import{join as S,basename as U}from"path";function d(e){let t=/^---[^\n]*\n([\s\S]*?)\n---/.exec(e),r=t?/^\s*name:\s*(.+?)\s*$/m.exec(t[1]):null;return r?r[1].replace(/^["']|["']$/g,""):void 0}function W(e){return(d(e)??"bulb").toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"bulb"}function C(e){return e.replace(/^---[^\n]*\r?\n[\s\S]*?\r?\n---[^\n]*\r?\n?/,"").replace(/^\r?\n+/,"")}function x(e,t,r){if(t>8)return r;let n;try{n=K(e,{withFileTypes:!0})}catch{return r}for(let s of n)if(s.isDirectory()){if(s.name.startsWith(".")||s.name==="node_modules")continue;x(S(e,s.name),t+1,r)}else s.isFile()&&s.name.endsWith(".bulb.md")&&r.push(S(e,s.name));return r}function Y(e){return x(e,0,[]).map(t=>{let r=0;try{r=H(t).mtimeMs}catch{}let n;try{n=d(z(t,"utf8").slice(0,1024))}catch{}return{path:t,name:n??U(t).replace(/\.bulb\.md$/,""),mtime:r}})}import{readFile as Q}from"fs/promises";var G={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 B(e){try{let t=e.split(`
|
|
2
|
+
`),r=0;if(t[r]?.trim()!=="---")return null;r++;let n=[];for(;r<t.length&&t[r]?.trim()!=="---";)n.push(t[r]),r++;if(t[r]?.trim()!=="---")return null;r++;let s=V(n);if(!s)return null;let i=new Map;for(;r<t.length;){let l=t[r]?.trim()?.match(/^\*\*(.+)\*\*$/);if(l){let a=l[1].trim();for(r++;r<t.length&&t[r]?.trim()==="";)r++;let f=t[r]?.match(/^(`{3,})(\w*)\s*$/);if(!f){r++;continue}let T=f[1];r++;let w=[];for(;r<t.length&&!t[r]?.match(new RegExp(`^${T}\\s*$`));)w.push(t[r]),r++;r++,i.set(a,w.join(`
|
|
3
|
+
`))}else r++}return{frontmatter:s,files:i}}catch{return null}}function V(e){let t={};for(let r of e){let n=r.indexOf(":");if(n===-1)continue;let s=r.slice(0,n).trim(),i=r.slice(n+1).trim();switch(s){case"format":t.format=i;break;case"name":t.name=q(i);break}}return!t.format?.startsWith("typebulb")||!t.name?null:t}function q(e){return e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1).replace(/\\"/g,'"'):e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function F(e){let t=r=>e.files.get(G[r].path)||"";return{name:e.frontmatter.name,code:t("code"),css:t("css"),html:t("html"),config:t("config"),notes:t("notes"),data:t("data"),infer:t("infer"),insight:t("insight"),server:t("server")}}function P(e){if(e.server.trim())return"server-side code (server.ts)";let t=e.code;if(/\btb\s*\.\s*fs\b/.test(t)||t.includes("/__fs"))return"the filesystem";if(/\btb\s*\.\s*ai\b/.test(t)||t.includes("/__ai"))return"AI (your API keys)";if(/\btb\s*\.\s*server\s*\.\s*(?!log\b)\w/.test(t)||t.includes("/__api"))return"server-side code (server.ts)"}async function X(e){try{let t=B(await Q(e,"utf-8"));return t?P(F(t)):void 0}catch{return}}import{readFileSync as Z,writeFileSync as tt,mkdirSync as et}from"fs";import{join as rt}from"path";function j(){return rt(p(),"trust.json")}function y(){try{let e=JSON.parse(Z(j(),"utf8"));return new Set(Array.isArray(e)?e:[])}catch{return new Set}}function nt(e){et(p(),{recursive:!0}),tt(j(),JSON.stringify([...e]))}function st(e){return y().has(b(e))}function it(e,t){let r=y(),n=b(e);(t?r.has(n):!r.has(n))||(t?r.add(n):r.delete(n),nt(r))}function ot(){return[...y()]}export{d as bulbName,st as isBulbTrusted,M as launchBulbServer,Y as listBulbFiles,h as listBulbServers,ot as listTrustedBulbs,X as predictBulbTrust,O as readServerLog,m as serverLogPath,it as setBulbTrusted,W as slugifyBulbName,I as stopBulbServer,C as stripFrontmatter};
|