typebulb 0.5.1 → 0.6.1

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.
Files changed (3) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +82 -66
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -48,6 +48,7 @@ typebulb --no-watch <file> Disable hot reload
48
48
  typebulb --port 3333 <file> Custom port
49
49
  typebulb --no-open <file> Don't auto-open browser
50
50
  typebulb --server <file> Run server.ts only, no web server
51
+ typebulb --replace <name>=<path> Replace a dependency with a local build
51
52
  typebulb --help Show help
52
53
  typebulb --version Show version
53
54
  ```
@@ -59,9 +60,10 @@ typebulb --version Show version
59
60
  - **Env files** — `.env` and `.env.local` auto-loaded from cwd
60
61
  - **Server mode** — `--server` runs only the `**server.ts**` section in Node, skipping the web server. Bulbs with only `**server.ts**` (no `**code.tsx**`) use this mode automatically.
61
62
  - **Type-check without running** — `typebulb check <file>` runs `tsc --noEmit` against the bulb and exits non-zero on errors. Useful for AI editors / CI.
62
- - **Filesystem access** — `tb.fs.read()` and `tb.fs.write()` for local files
63
+ - **Filesystem access** — `tb.fs.read()` (UTF-8 text), `tb.fs.readBytes()` (raw `Uint8Array`), and `tb.fs.write()` (text or bytes) for local files
63
64
  - **Hot reload** — Recompiles on save and refreshes the browser (on by default; disable with `--no-watch`)
64
65
  - **Package resolution** — Client dependencies are automatically resolved by generating import maps (same resolver as typebulb.com). Server dependencies are automatically installed via npm.
66
+ - **Replace dependency** — `--replace <name>=<path>` replaces a declared dependency with a local *built* package folder (browser-ready ESM, no external bare imports) instead of a CDN, for testing an unpublished build. Supplies both runtime bytes and types; applies to `run` and `check`. Under `--watch` the folder is watched and the browser reloads on rebuild (`--no-watch` freezes it). Dev-only; nothing is written to the bulb.
65
67
  - **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.
66
68
  - **AI calls** — `tb.ai()` for general-purpose AI (chatbots, agents, experiments). `tb.models()` lists available models. Set API keys in `.env` (see below).
67
69
 
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b from"path";import{pathToFileURL as un}from"url";import{execFile as mn,spawn as fn}from"child_process";import{promisify as hn}from"util";import{EventEmitter as pt}from"events";var ir={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 ft(s){try{let e=s.split(`
3
- `),t=0;if(e[t]?.trim()!=="---")return null;t++;let r=[];for(;t<e.length&&e[t]?.trim()!=="---";)r.push(e[t]),t++;if(e[t]?.trim()!=="---")return null;t++;let n=or(r);if(!n)return null;let i=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 d=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!d){t++;continue}let u=d[1];t++;let f=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${u}\\s*$`));)f.push(e[t]),t++;t++,i.set(c,f.join(`
4
- `))}else t++}return{frontmatter:n,files:i}}catch{return null}}function or(s){let e={};for(let t of s){let r=t.indexOf(":");if(r===-1)continue;let n=t.slice(0,r).trim(),i=t.slice(r+1).trim();switch(n){case"format":e.format=i;break;case"name":e.name=ar(i);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function ar(s){return s.startsWith('"')&&s.endsWith('"')?s.slice(1,-1).replace(/\\"/g,'"'):s.startsWith("'")&&s.endsWith("'")?s.slice(1,-1):s}function ht(s){let e=t=>s.files.get(ir[t].path)||"";return{name:s.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 cr(s){try{return JSON.parse(s),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(s)||/^---\s*$/m.test(s)||/^\w[\w\s]*:[ \t]/m.test(s))}function gt(s){let e=s.trim();return e?cr(e)?[e]:s.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function yt(s){if(!s.trim())return{};try{return JSON.parse(s)}catch{return{}}}import{transform as lr}from"sucrase";function Be(s,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:r}=lr(s,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:r}}catch(r){return{code:"",error:String(r)}}}var ne="https://esm.sh",se="https://cdn.jsdelivr.net/npm/",Le="https://data.jsdelivr.com/v1/package/npm/";function wt(s){let e=(s||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var g=class s{constructor(e,t,r){let n=typeof e=="string"?s.parse(e):e;this.name=n.name,this.version=q(t??n.version),this.subpath=q(r??n.subpath)}static parse(e){let t=wt(e||"");if(!t.length)return new s({name:""});if(t[0].startsWith("@")){let n=t[0],[i,o]=vt(t[1]??""),a=q(t.slice(2).join("/"));return new s({name:`${n}/${i}`,version:o,subpath:a})}else{let[n,i]=vt(t[0]),o=q(t.slice(1).join("/"));return new s({name:n,version:i,subpath:o})}}static fromUrl(e){try{let t=new URL(e),r=new URL(ne).host,n=new URL(se).host;if(t.host===r){let i=wt(t.pathname.replace(/^\/v\d+\//,"/"));if(!i.length)return;let o=i[0].startsWith("@")?`${i[0]}/${i[1]??""}`:i[0];return s.parse(o)}if(t.host===n){let i=t.pathname.split("/npm/")[1];if(!i)return;let o=i.split("/")[0]||"";return s.parse(o)}return}catch{return}}static versionFromUrl(e){return s.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 s.parse(e).name}withVersion(e){return new s({name:this.name,version:q(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://")}},q=s=>s&&s.length?s:void 0,vt=s=>{let e=s.indexOf("@");return e<0?[s,void 0]:[s.slice(0,e),q(s.slice(e+1))]};async function x(s){try{return await s()}catch{return}}var ie=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=ne,this.jsDelivrBase=se,this.jsDelivrMeta=Le,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 g(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:n=!1,external:i}=t,o=new URLSearchParams({target:r});return n&&o.append("bundle",""),i?.length&&o.append("external",i.join(",")),`${this.esmHost}/${e}?${o.toString()}`}async pinEsmUrl(e,t="es2022"){let r=this.buildEsmUrl(e,{target:t}),n=await x(()=>this.http.head(r));return n?.ok?n.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 n=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:n,ts:t}),n}async tryResolveFromUrls(e){for(let t of e){let r=await x(()=>this.http.head(t)),n=this.parseVersionFromUrl(r?.url||t);if(n)return n}}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 x(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let n=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,n),r}parseVersionFromUrl(e){let t=g.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:u,peerDependencies:f,peerDependenciesMeta:h}=r;return{name:e,version:t,dependencies:u,peerDependencies:f,peerDependenciesMeta:h}}let n=this.packageJson(new g(`${e}@${t}`)),i=await x(()=>this.http.getJson(n));if(!i)return;let o=u=>u&&Object.keys(u).length?u:void 0,a=o(i.dependencies),c=o(i.peerDependencies),d=o(i.peerDependenciesMeta);return await this.cache.setMeta(e,t,a,c,d),{name:e,version:t,dependencies:a,peerDependencies:c,peerDependenciesMeta:d}}};var bt=s=>s.startsWith("@types/"),oe=s=>Object.keys(s?.peerDependencies||{}).filter(e=>!bt(e)),We=s=>Object.keys(s?.dependencies||{}).filter(e=>!bt(e)),dr=s=>oe(s).filter(e=>!s?.peerDependenciesMeta?.[e]?.optional),ae=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:n,autoAddedPeers:i}=await this.expandWithPeers(r,t),o=this.computeFlags(n);return{allRoots:n,flags:o,autoAddedPeers:i}}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(i=>[i.name,i])),n=[];for(let i of e)for(let o of dr(i.meta))!r.has(o)&&!n.some(a=>a.name===o)&&n.push({name:o,requiredBy:i.name});for(let{name:i,requiredBy:o}of n)try{let a=await t(i),c=await this.cdn.fetchPackageMeta(i,a);r.set(i,{name:i,version:a,meta:c})}catch(a){console.warn(`[typebulb] Failed to resolve peer "${i}" for "${o}":`,a)}return{allRoots:[...r.values()],autoAddedPeers:n.filter(i=>r.has(i.name))}}computeFlags(e){let t=new Set(e.flatMap(i=>oe(i.meta))),r=new Map;for(let i of e)for(let o of We(i.meta))r.set(o,(r.get(o)||0)+1);let n=new Set([...r.entries()].filter(([,i])=>i>=2).map(([i])=>i));return new Map(e.map(i=>[i.name,{isPeerRoot:t.has(i.name),hasPeers:oe(i.meta).length>0,isSharedDep:n.has(i.name)}]))}};var ce=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 x(()=>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 n=await x(()=>this.cdn.fetchVersionsIndex(e));if(n?.versions?.length){let o=this.selectVersionFromIndex(n.versions,t,n.distTags);if(o){if(this.semver.isExactVersion(o))return await this.cache.setPinnedExact(e,t,o),o}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let a=await x(()=>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 i=await this.cdn.resolveExactVersion(`${e}@${t}`);if(i&&this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}async effectivePackage(e,t){let r=new g(e),n=r.root(),i=t[n],o=i?await x(()=>this.cache.getPinnedExact(n,i))??await x(()=>this.resolveExactForRoot(n,i)):void 0;return{effectivePackage:o?r.withVersion(o).format():e,root:n,range:i,pinned:o}}};import{init as pr,parse as ur}from"es-module-lexer";var z=class s{constructor(e,t,r,n){this.version=e,this.cdn=t,this.peer=r,this.cache=n}extractImportsSync(e){let t=new Set;for(let r of s.importPatterns){r.lastIndex=0;for(let n of e.matchAll(r))g.isBare(n[1])&&t.add(n[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=n=>{g.isBare(n)&&t.add(n)};try{await pr;let[n]=ur(e);n.forEach(i=>r(e.slice(i.s,i.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t){let r=await this.extractImports(e),n=[...new Set(r.map(g.rootOf))],i=await Promise.all(n.map(async u=>({name:u,version:await this.resolveVersion(u,t)}))),{allRoots:o,flags:a,autoAddedPeers:c}=await this.peer.resolve(i,u=>this.resolveVersion(u,t)),d=this.buildEntries([...r,...c.map(u=>u.name)],o,a,t);return{importMap:{imports:Object.fromEntries(d)},prefetchUrls:d.map(([,u])=>u)}}async resolveVersion(e,t){let r=t[e],n=await this.version.resolveExactForRoot(e,r);if(!n){let i=r?`${e}@${r}`:e,o=await x(()=>this.cdn.pinEsmUrl(i));if(!o)throw new Error(`Cannot resolve version for ${e} - network may be unavailable.`);n=g.versionFromUrl(o),n&&r&&await x(()=>this.cache.setPinnedExact(e,r,n))}if(!n)throw new Error(`Cannot resolve version for ${e}`);return n}buildEntries(e,t,r,n){let i=new Map(t.map(l=>[l.name,l])),o=l=>{let m=i.get(g.rootOf(l));return new g(l).withPreferredVersion(m.version,n[m.name]).format()},a=new Set([...r.entries()].filter(([,l])=>l.isPeerRoot||l.isSharedDep).map(([l])=>l)),c=new Set(e.filter(l=>l!==g.rootOf(l)).map(g.rootOf)),d=[],u=new Set,f=new Set(e.filter(l=>l===g.rootOf(l))),h=new Set;for(let l of e){let m=g.rootOf(l),w=i.get(m),{isPeerRoot:y,hasPeers:A,isSharedDep:$}=r.get(m),_=c.has(m),re=l!==m,Se=!(y||$)&&(_||!A),O=this.singletonDepsOf(w,a),mt=re&&f.has(m);mt&&h.add(m);let sr=mt?[...O,m]:O.length?O:void 0;d.push([l,this.cdn.buildEsmUrl(o(l),{bundle:Se,external:sr})]),u.add(l)}let p=new Set([...a,...h]);for(let l of p)i.has(l)&&(u.has(l)||d.push([l,this.cdn.buildEsmUrl(o(l),{})]),d.push([`${l}/`,`${this.cdn.esmHost}/${o(l)}/`]));return d}singletonDepsOf(e,t){return[...new Set([...oe(e.meta),...We(e.meta)])].filter(r=>t.has(r))}};z.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as xt,satisfies as mr,maxSatisfying as Ve,major as fr,prerelease as hr,rsort as gr,valid as yr}from"semver";var Re=class{cmp(e,t){return e===t?0:xt(e,t)?1:xt(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!mr(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=Ve(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?gr(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",n=t?.preferStable??!0,i=t?.distTags?.latest;if(i&&e.includes(i)&&this.satisfies(r,i))return i;if(n){let a=Ve(e,r,{includePrerelease:!1});if(a)return a}return Ve(e,r,{includePrerelease:!0})??void 0}majorOf(e){return fr(e)}isPrerelease(e){return hr(e)!==null}isExactVersion(e){return yr(e)!==null}},B=new Re;function Pt(s,e){let t=new ie(s,e),r=new ae(t),n=new ce(s,t,B);return{packageService:new z(n,t,r,s),versionResolver:n,cdnClient:t,peerResolver:r}}import*as Nt from"fs/promises";import*as T from"path";var Je=[{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"}],He=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var St=`
2
+ import*as D from"fs/promises";import{readFileSync as In}from"fs";import*as P from"path";import{pathToFileURL as _n}from"url";import{execFile as On,spawn as An}from"child_process";import{promisify as Mn}from"util";import{EventEmitter as yt}from"events";var gr={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 vt(s){try{let e=s.split(`
3
+ `),t=0;if(e[t]?.trim()!=="---")return null;t++;let r=[];for(;t<e.length&&e[t]?.trim()!=="---";)r.push(e[t]),t++;if(e[t]?.trim()!=="---")return null;t++;let n=yr(r);if(!n)return null;let o=new Map;for(;t<e.length;){let a=e[t]?.trim()?.match(/^\*\*(.+)\*\*$/);if(a){let l=a[1].trim();for(t++;t<e.length&&e[t]?.trim()==="";)t++;let d=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!d){t++;continue}let p=d[1];t++;let f=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${p}\\s*$`));)f.push(e[t]),t++;t++,o.set(l,f.join(`
4
+ `))}else t++}return{frontmatter:n,files:o}}catch{return null}}function yr(s){let e={};for(let t of s){let r=t.indexOf(":");if(r===-1)continue;let n=t.slice(0,r).trim(),o=t.slice(r+1).trim();switch(n){case"format":e.format=o;break;case"name":e.name=wr(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function wr(s){return s.startsWith('"')&&s.endsWith('"')?s.slice(1,-1).replace(/\\"/g,'"'):s.startsWith("'")&&s.endsWith("'")?s.slice(1,-1):s}function bt(s){let e=t=>s.files.get(gr[t].path)||"";return{name:s.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 vr(s){try{return JSON.parse(s),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(s)||/^---\s*$/m.test(s)||/^\w[\w\s]*:[ \t]/m.test(s))}function xt(s){let e=s.trim();return e?vr(e)?[e]:s.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function Pt(s){if(!s.trim())return{};try{return JSON.parse(s)}catch{return{}}}import{transform as br}from"sucrase";function Je(s,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:r}=br(s,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:r}}catch(r){return{code:"",error:String(r)}}}var oe="https://esm.sh",ie="https://cdn.jsdelivr.net/npm/",Ve="https://data.jsdelivr.com/v1/package/npm/";function Rt(s){let e=(s||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var h=class s{constructor(e,t,r){let n=typeof e=="string"?s.parse(e):e;this.name=n.name,this.version=X(t??n.version),this.subpath=X(r??n.subpath)}static parse(e){let t=Rt(e||"");if(!t.length)return new s({name:""});if(t[0].startsWith("@")){let n=t[0],[o,i]=St(t[1]??""),a=X(t.slice(2).join("/"));return new s({name:`${n}/${o}`,version:i,subpath:a})}else{let[n,o]=St(t[0]),i=X(t.slice(1).join("/"));return new s({name:n,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),r=new URL(oe).host,n=new URL(ie).host;if(t.host===r){let o=Rt(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return s.parse(i)}if(t.host===n){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return s.parse(i)}return}catch{return}}static versionFromUrl(e){return s.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 s.parse(e).name}withVersion(e){return new s({name:this.name,version:X(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://")}},X=s=>s&&s.length?s:void 0,St=s=>{let e=s.indexOf("@");return e<0?[s,void 0]:[s.slice(0,e),X(s.slice(e+1))]};async function E(s){try{return await s()}catch{return}}var ae=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=oe,this.jsDelivrBase=ie,this.jsDelivrMeta=Ve,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 h(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:n=!1,external:o}=t,i=new URLSearchParams({target:r});return n&&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}),n=await E(()=>this.http.head(r));return n?.ok?n.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 n=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:n,ts:t}),n}async tryResolveFromUrls(e){for(let t of e){let r=await E(()=>this.http.head(t)),n=this.parseVersionFromUrl(r?.url||t);if(n)return n}}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 E(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let n=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,n),r}parseVersionFromUrl(e){let t=h.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:p,peerDependencies:f,peerDependenciesMeta:m}=r;return{name:e,version:t,dependencies:p,peerDependencies:f,peerDependenciesMeta:m}}let n=this.packageJson(new h(`${e}@${t}`)),o=await E(()=>this.http.getJson(n));if(!o)return;let i=p=>p&&Object.keys(p).length?p:void 0,a=i(o.dependencies),l=i(o.peerDependencies),d=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,a,l,d),{name:e,version:t,dependencies:a,peerDependencies:l,peerDependenciesMeta:d}}};var Et=s=>s.startsWith("@types/"),ce=s=>Object.keys(s?.peerDependencies||{}).filter(e=>!Et(e)),He=s=>Object.keys(s?.dependencies||{}).filter(e=>!Et(e)),xr=s=>ce(s).filter(e=>!s?.peerDependenciesMeta?.[e]?.optional),le=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:n,autoAddedPeers:o}=await this.expandWithPeers(r,t),i=this.computeFlags(n);return{allRoots:n,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])),n=[];for(let o of e)for(let i of xr(o.meta))!r.has(i)&&!n.some(a=>a.name===i)&&n.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of n)try{let a=await t(o),l=await this.cdn.fetchPackageMeta(o,a);r.set(o,{name:o,version:a,meta:l})}catch(a){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,a)}return{allRoots:[...r.values()],autoAddedPeers:n.filter(o=>r.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>ce(o.meta))),r=new Map;for(let o of e)for(let i of He(o.meta))r.set(i,(r.get(i)||0)+1);let n=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:ce(o.meta).length>0,isSharedDep:n.has(o.name)}]))}};var de=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 E(()=>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 n=await E(()=>this.cdn.fetchVersionsIndex(e));if(n?.versions?.length){let i=this.selectVersionFromIndex(n.versions,t,n.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 E(()=>this.cdn.fetchVersionsIndex(e));if(a?.versions?.length){let l=this.selectVersionFromIndex(a.versions,t,a.distTags);if(l&&this.semver.isExactVersion(l))return await this.cache.setPinnedExact(e,t,l),l}}}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 h(e),n=r.root(),o=t[n],i=o?await E(()=>this.cache.getPinnedExact(n,o))??await E(()=>this.resolveExactForRoot(n,o)):void 0;return{effectivePackage:i?r.withVersion(i).format():e,root:n,range:o,pinned:i}}};import{init as Pr,parse as Rr}from"es-module-lexer";var Q=class s{constructor(e,t,r,n){this.version=e,this.cdn=t,this.peer=r,this.cache=n}extractImportsSync(e){let t=new Set;for(let r of s.importPatterns){r.lastIndex=0;for(let n of e.matchAll(r))h.isBare(n[1])&&t.add(n[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=n=>{h.isBare(n)&&t.add(n)};try{await Pr;let[n]=Rr(e);n.forEach(o=>r(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t){let r=await this.extractImports(e),n=[...new Set(r.map(h.rootOf))],o=await Promise.all(n.map(async p=>({name:p,version:await this.resolveVersion(p,t)}))),{allRoots:i,flags:a,autoAddedPeers:l}=await this.peer.resolve(o,p=>this.resolveVersion(p,t)),d=this.buildEntries([...r,...l.map(p=>p.name)],i,a,t);return{importMap:{imports:Object.fromEntries(d)},prefetchUrls:d.map(([,p])=>p)}}async resolveVersion(e,t){let r=t[e],n=await this.version.resolveExactForRoot(e,r);if(!n){let o=r?`${e}@${r}`:e,i=await E(()=>this.cdn.pinEsmUrl(o));if(!i)throw new Error(`Cannot resolve version for ${e} - network may be unavailable.`);n=h.versionFromUrl(i),n&&r&&await E(()=>this.cache.setPinnedExact(e,r,n))}if(!n)throw new Error(`Cannot resolve version for ${e}`);return n}buildEntries(e,t,r,n){let o=new Map(t.map(c=>[c.name,c])),i=c=>{let u=o.get(h.rootOf(c));return new h(c).withPreferredVersion(u.version,n[u.name]).format()},a=new Set([...r.entries()].filter(([,c])=>c.isPeerRoot||c.isSharedDep).map(([c])=>c)),l=new Set(e.filter(c=>c!==h.rootOf(c)).map(h.rootOf)),d=[],p=new Set,f=new Set(e.filter(c=>c===h.rootOf(c))),m=new Set;for(let c of e){let u=h.rootOf(c),g=o.get(u),{isPeerRoot:v,hasPeers:w,isSharedDep:I}=r.get(u),W=l.has(u),$=c!==u,N=!(v||I)&&(W||!w),Y=this.singletonDepsOf(g,a),J=$&&f.has(u);J&&m.add(u);let hr=J?[...Y,u]:Y.length?Y:void 0;d.push([c,this.cdn.buildEsmUrl(i(c),{bundle:N,external:hr})]),p.add(c)}let y=new Set([...a,...m]);for(let c of y)o.has(c)&&(p.has(c)||d.push([c,this.cdn.buildEsmUrl(i(c),{})]),d.push([`${c}/`,`${this.cdn.esmHost}/${i(c)}/`]));return d}singletonDepsOf(e,t){return[...new Set([...ce(e.meta),...He(e.meta)])].filter(r=>t.has(r))}};Q.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as kt,satisfies as Sr,maxSatisfying as qe,major as Er,prerelease as kr,rsort as Tr,valid as Cr}from"semver";var Ce=class{cmp(e,t){return e===t?0:kt(e,t)?1:kt(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Sr(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=qe(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?Tr(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",n=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(r,o))return o;if(n){let a=qe(e,r,{includePrerelease:!1});if(a)return a}return qe(e,r,{includePrerelease:!0})??void 0}majorOf(e){return Er(e)}isPrerelease(e){return kr(e)!==null}isExactVersion(e){return Cr(e)!==null}},V=new Ce;function Tt(s,e){let t=new ae(s,e),r=new le(t),n=new de(s,t,V);return{packageService:new Q(n,t,r,s),versionResolver:n,cdnClient:t,peerResolver:r}}import*as Wt from"fs/promises";import*as O from"path";var Ge=[{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"}],ze=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var Ct=`
5
5
  /**
6
6
  * Get raw data chunk from the Data tab.
7
7
  * @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
@@ -12,7 +12,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
12
12
  * @param index - Chunk index (0-based)
13
13
  * @throws If chunk is not valid JSON/JSON-ish
14
14
  */
15
- json<T = unknown>(index: number): T;`,Rt=`
15
+ json<T = unknown>(index: number): T;`,Dt=`
16
16
  /**
17
17
  * Get the insight data produced by the inference layer.
18
18
  *
@@ -21,7 +21,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
21
21
  *
22
22
  * @returns The parsed insight JSON, or undefined if no insight is available
23
23
  */
24
- insight<T = unknown>(): T | undefined;`,Et=`
24
+ insight<T = unknown>(): T | undefined;`,It=`
25
25
  /**
26
26
  * General-purpose AI call.
27
27
  *
@@ -38,7 +38,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
38
38
  model?: string;
39
39
  /** Enable/disable web search. Default: on for BYOK, always off for free model. */
40
40
  webSearch?: boolean;
41
- }): Promise<{ text: string }>;`,kt=`
41
+ }): Promise<{ text: string }>;`,_t=`
42
42
  /**
43
43
  * Returns AI models available to the current user.
44
44
  * Models are filtered by the user's configured API keys.
@@ -53,7 +53,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
53
53
  friendlyName: string;
54
54
  /** Provider display name, e.g. "Anthropic" */
55
55
  providerName: string;
56
- }>>;`,Tt=`
56
+ }>>;`,Ot=`
57
57
  /**
58
58
  * The mode this bulb is running in.
59
59
  *
@@ -61,7 +61,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
61
61
  * - \`'editor'\` \u2014 Running in the typebulb.com editor
62
62
  * - \`'published'\` \u2014 Running as a published/standalone bulb on typebulb.com
63
63
  */
64
- mode: 'local' | 'editor' | 'published';`,Ct=`
64
+ mode: 'local' | 'editor' | 'published';`,At=`
65
65
  /**
66
66
  * Local filesystem access (CLI only).
67
67
  *
@@ -69,11 +69,13 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
69
69
  * Throws in editor/published mode.
70
70
  */
71
71
  fs: {
72
- /** Read a file as UTF-8 text. Path is relative to the bulb's directory. */
72
+ /** Read a file as UTF-8 text. Throws if the file is not valid UTF-8 \u2014 use readBytes for binary. */
73
73
  read(path: string): Promise<string>;
74
- /** Write UTF-8 text to a file. Creates parent directories if needed. */
75
- write(path: string, content: string): Promise<boolean>;
76
- };`,wr=`
74
+ /** Read a file as raw bytes. */
75
+ readBytes(path: string): Promise<Uint8Array>;
76
+ /** Write text or raw bytes to a file. Creates parent directories if needed. */
77
+ write(path: string, content: string | Uint8Array): Promise<boolean>;
78
+ };`,Dr=`
77
79
  /**
78
80
  * Server-side function proxy. The built-in \`log\` prints to CLI stdout
79
81
  * (falls back to console.log on web). On the server side, this object only
@@ -81,7 +83,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
81
83
  */
82
84
  server: {
83
85
  log(...args: any[]): Promise<void>;
84
- };`,vr=`
86
+ };`,Ir=`
85
87
  /**
86
88
  * Async value inspector for tensor-like objects.
87
89
  *
@@ -148,7 +150,7 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
148
150
  *
149
151
  * @returns The full canonical URL
150
152
  */
151
- url(): Promise<string>;`,br=`
153
+ url(): Promise<string>;`,_r=`
152
154
  /**
153
155
  * Server-side function proxy.
154
156
  *
@@ -156,23 +158,23 @@ import*as E from"fs/promises";import{readFileSync as pn}from"fs";import*as b fro
156
158
  * \`tb.server.log(...)\` is a built-in that prints to CLI stdout (falls back to console.log on web).
157
159
  * User exports override built-ins of the same name.
158
160
  */
159
- server: Record<string, (...args: any[]) => Promise<any>>;`,Ge=`
161
+ server: Record<string, (...args: any[]) => Promise<any>>;`,Ke=`
160
162
  /**
161
163
  * Typebulb utilities namespace.
162
164
  * Type \`tb.\` to discover available helpers.
163
165
  */
164
- declare const tb: {${St}${vr}${Rt}${br}${Et}${Ct}${kt}${Tt}
166
+ declare const tb: {${Ct}${Ir}${Dt}${_r}${It}${At}${_t}${Ot}
165
167
  };
166
- `,qe=`
168
+ `,Ye=`
167
169
  /**
168
170
  * Typebulb utilities namespace (server-side).
169
171
  * Type \`tb.\` to discover available helpers.
170
172
  */
171
- declare const tb: {${St}${Rt}${Et}${Ct}${wr}${kt}${Tt}
173
+ declare const tb: {${Ct}${Dt}${It}${At}${Dr}${_t}${Ot}
172
174
  };
173
- `;var L=class{constructor(e){this.store=e}async isNegative(e){let t=await Ee(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let r=((await Ee(()=>this.store.get(e)))?.attempts||0)+1;await Ee(()=>this.store.set(e,{until:Date.now()+xr(r),attempts:r}))}async clearNegative(e){await Ee(()=>this.store.delete(e))}};function xr(s){return Math.min(9e5*Math.pow(2,Math.max(0,s-1)),864e5)}async function Ee(s){try{return await s()}catch{return}}import Tr from"p-limit";import{resolve as _t}from"resolve.exports";var K=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 F={maxRelativeTypeRefs:500,maxBareDeps:8,maxBareDepth:3,prefetchConcurrency:4,negativeTtlMs:1e4},le=["index.d.ts","index.d.mts"],de=/\.d\.(ts|mts)$/i;function ze(s){if(de.test(s))return!0;try{return new URL(s,"file://").search.includes("dts")}catch{return s.includes("?")&&s.includes("dts")}}function ke(s){return[`${s}.d.ts`,`${s}.d.mts`]}async function pe(s,{retries:e=2,timeoutMs:t=15e3,init:r}={}){for(let n=0;n<=e;n++){let i=new AbortController,o=setTimeout(()=>i.abort(),t);try{let a=await fetch(s,{...r,signal:i.signal});if(Pr(a.status)&&n<e)continue;return a}catch{if(n<e)continue;return}finally{clearTimeout(o)}}}function Pr(s){return s===408||s===429||s>=500&&s<600}var ue=class extends K{constructor(e,t){super(e),this.cdnClient=t}async loadPackageAtVersionedRoot(e,t){let r=this.cdnClient.packageJson(new g({name:e,version:t})),n=await pe(r);if(!n?.ok)return;let i;try{i=await n.json()}catch{return}if(i)return{pkg:i,baseDir:this.cdnClient.baseDir(new g({name:e,version:t??i.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 n=await t(r);if(n)return n}}async resolveFromSelected(e,t){if(e.kind==="types"){let n=this.cdnClient.normalizeRelative(e.path);if(!n||n==="/"||n===".")return this.tryUntilSuccess([...le],t);if(!de.test(n)){let i=await this.tryUntilSuccess(this.declarationCandidatesFor(n),t);if(i)return i}return t(n)}let r=this.declarationCandidatesFor(e.path);return this.tryUntilSuccess([...le,...r],t)}toResolutionResult(e){return{kind:de.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let r=t||".",n=e;try{let i=this.extractPathFromResult(_t(n,r,{conditions:["types"]}));if(i)return i}catch{}try{return this.extractPathFromResult(_t(n,r,{browser:!0,conditions:["import","default","module","browser","node"]}))}catch{return}}async resolve(e){try{let t=g.parse(e),{pkg:r,baseDir:n}=await this.loadPackageAtVersionedRoot(t.name,t.version)||{};if(!r||!n)return;let i={name:t.name,version:t.version},o=new g(i).format(),a=new g({...i,subpath:t.subpath}).format(),c=f=>this.fetchCandidateFrom(n,t.name,f);if(t.subpath){let f=this.cdnClient.ensureLeadingDotSlash(t.subpath),h=this.resolveExportsPath(r,f);if(h){let l=await this.resolveFromSelected(this.toResolutionResult(h),c);if(l)return{...l,resolvedPkg:a}}let p=await this.tryUntilSuccess(this.declarationCandidatesFor(f),c);if(p)return{...p,resolvedPkg:a}}let d=r.types??r.typings;if(d){let f=await this.resolveFromSelected({kind:"types",path:d},c);if(f)return{...f,resolvedPkg:o}}let u=this.resolveExportsPath(r,".");if(u){let f=await this.resolveFromSelected(this.toResolutionResult(u),c);if(f)return{...f,resolvedPkg:o}}return}catch{return}}async fetchCandidateFrom(e,t,r){let n=this.cdnClient.normalizeRelative(r),i=new URL(n,e).toString(),o=await this.fetchDtsText(i);return o?{dts:o.dts,url:o.url,resolvedPkg:t}:void 0}declarationCandidatesFor(e){if(!e||e==="./"||e==="/")return[...le];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),r=ke(t),n=t.endsWith("/")?t:`${t}/`;return r.push(...ke(`${n}index`)),r}};import{gunzipSync as Sr}from"fflate";var Y=class{async fetchAndExtract(e,t){let r=this.getTarballUrl(e,t),n=await pe(r,{timeoutMs:3e4});if(!n?.ok)return new Map;let i=new Uint8Array(await n.arrayBuffer());return this.extractDtsFiles(i)}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=Sr(e),n=new TextDecoder("utf-8"),i=0;for(;i<r.length-512;){let o=r.slice(i,i+512);if(o[0]===0)break;let a=o.slice(0,100),c=a.indexOf(0),d=n.decode(a.slice(0,c>0?c:100)).trim(),u=o.slice(124,136),f=n.decode(u).trim().replace(/\0/g,""),h=parseInt(f,8)||0,p=String.fromCharCode(o[156]);if(i+=512,(p==="0"||p==="\0")&&(d.endsWith(".d.ts")||d.endsWith(".d.mts"))){let l=r.slice(i,i+h);t.set(this.normalizeTarPath(d),n.decode(l))}i+=Math.ceil(h/512)*512}}catch{}return t}},Rr=new Y;var me=class extends K{constructor(e,t,r,n=new Y){super(e),this.cdnClient=t,this.cache=r,this.tarballFetcher=n}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 i=B.majorOf(r),o=e.filter(a=>B.majorOf(a)===i);if(o.length)return o.sort((a,c)=>B.cmp(c,a))[0]}let n=t?.latest;return n&&e.includes(n)?n:e[0]}catch{return e[0]}}async fetchFromVersionedRoot(e,t){let r=new g(e),n=r.version;if(!n)return;let i;try{i=await this.tarballFetcher.fetchAndExtract(r.name,n)}catch{return}if(!i||i.size===0)return;for(let[a,c]of i.entries()){let d=this.cdnClient.file(e,a);try{await this.cache.setCachedFile(d,c)}catch{}}let o=t.subpath?[t.subpath+".d.ts",t.subpath+"/index.d.ts"]:["index.d.ts"];for(let a of o){let c=i.get(a);if(c)return{dts:c,url:this.cdnClient.file(e,a),resolvedPkg:t.subpath?new g(t).format():t.name}}}async resolve(e){let t=g.parse(e);if(t.name)for(let r of this.typesNameCandidates(t.name)){let n=`@types/${r}`,i;try{i=await this.cdnClient.fetchVersionsIndex(n)}catch{continue}if(!i?.versions?.length)continue;let o=this.selectTypesVersion(i.versions,i.distTags,t.version),a=await this.fetchFromVersionedRoot(`${n}@${o}`,t);if(a)return a}}};var fe=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=(n,i)=>(t.add(n[i]),null);return this.matchAll(e,/(import|export)\s+[^'"\n]*from\s*['"]([^'"\n]+)['"]/,n=>r(n,2)),this.matchAll(e,/export\s*\*\s*from\s*['"]([^'"\n]+)['"]/,n=>r(n,1)),Array.from(t)}matchAll(e,t,r){let n=[];try{let i=new RegExp(t.source,"g"),o;for(;o=i.exec(e);){let a=r(o);a!==null&&n.push(a)}}catch{}return n}isBare(e){return!(e.startsWith("./")||e.startsWith("../")||e.startsWith("file:")||e.startsWith("http://")||e.startsWith("https://"))}};var It="file:///node_modules",he=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`${It}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let r=Er(t);return`${It}/${this.epochDir()}/${e}/${r}`}};function Er(s){let e=s||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as kr}from"lru-cache";function Ke(s){let e=new kr({ttl:1e4,max:500}),t=new Map;return async function(n){try{if(await s.isNegative(n))return;let i=e.get(n);if(i&&Date.now()-i<1e4)return;let o=await s.getCachedFile(n);if(o)return{dts:o,url:n};let a=t.get(n);if(a)return a;let c=(async()=>{let d=await fetch(n,{cache:"no-store"});if(!d.ok){d.status===404&&(e.set(n,Date.now()),await s.recordNegative(n));return}let u=await d.text(),f=d.url||n;return await s.clearNegative(n),await s.setCachedFile(f,u),{dts:u,url:f}})();return t.set(n,c),await c.finally(()=>t.delete(n))}catch{return}}}var Te=class{constructor(e){this.inFlight=new Map,this.scanner=new fe,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=Ke(e.cache),this.typescriptProvider=new ue(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new me(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new he}withInFlight(e,t){let r=this.inFlight.get(e);if(r)return r;let n=t().finally(()=>this.inFlight.delete(e));return this.inFlight.set(e,n),n}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(n=>n.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 g(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 g(e).subpath===new g(t).subpath}async fetchRootDts(e,t){let{effectivePackage:r,root:n,pinned:i}=await this.versionResolver.effectivePackage(e,t),o=await this.cache.getCachedDts(r);if(o?.content){let c=o.url??this.cdnClient.file(i?`${n}@${i}`:n,"index.d.ts");return{dts:o.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 n=t.pathname.startsWith(e.pathname)?t.pathname.slice(e.pathname.length):`__deps__/${encodeURIComponent(t.toString()).replace(/%/g,"_")}.d.ts`;return this.virtualFs.pathFor(r,n)}computeEntryPath(e,t){if(!e)return{mainPath:this.virtualFs.pathForMain(t),packageRootUrl:void 0};let r=new URL(e),n=this.extractPackageRootUrl(r);return{mainPath:this.toVirtualPath(n,r,t),packageRootUrl:n}}async expandRelativeRefs(e,t,r,n,i=new Set,o){if(!i.has(t)&&(i.add(t),!(i.size>F.maxRelativeTypeRefs)))try{let a=new URL(t),c=new URL("./",a);o??(o=this.extractPackageRootUrl(a));let d=this.capArray(this.scanner.collectRelativeTypeRefs(e),F.maxRelativeTypeRefs);for(let u of d)await this.tryRelativeRef(u,c,o,r,n,i)}catch{}}async tryRelativeRef(e,t,r,n,i,o){try{let a=new URL(e,t),c=a.pathname+a.search,d=ze(c)?[c]:this.typescriptProvider.declarationCandidatesFor(c);for(let u of d){let h=new URL(u,a).toString();if(o.has(h))return;let p=await this.fetchDts(h);if(p?.dts){let l=this.toVirtualPath(r,new URL(p.url),n);this.pushFileIfNew(i,l,p.dts),await this.expandRelativeRefs(p.dts,p.url,n,i,o,r);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new g(e).name!==new g(t).name}async prefetchBareDeps(e,t,r,n,i){try{let o=this.capArray(this.scanner.collectBareModuleRefs(e),F.maxBareDeps).filter(d=>this.isDifferentPackage(d,t));if(!o.length)return;let a=new Set([t]),c=Tr(F.prefetchConcurrency);await Promise.all(o.map(d=>c(()=>this.prefetchBareDepsRecursive(d,r,n,F.maxBareDepth,a,i).catch(()=>{}))))}catch{}}async prefetchBareDepsRecursive(e,t,r,n,i,o){if(n<=0||i.has(e))return;i.add(e);let a=await this.fetchRootDts(e,o);if(!a?.dts)return;let c=a.resolvedPkg||e,d=this.virtualFs.pathForMain(c);this.pushFileIfNew(t,d,a.dts),r.push({module:e,path:d}),a.url&&await this.expandRelativeRefs(a.dts,a.url,c,t);let u=this.capArray(this.scanner.collectBareModuleRefs(a.dts),F.maxBareDeps).filter(f=>!i.has(f));for(let f of u)await this.prefetchBareDepsRecursive(f,t,r,n-1,i,o)}async resolve(e,t,r){let n=await this.packageService.extractImports(e),i=r?[...n,...r]:n;return(await Promise.all(i.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 n=await this.fetchRootDts(e,t)??await this.trySubpathWithRootFallback(e,t);return n?this.buildDefFromContent(e,n,n.resolvedPkg||e,t):this.createStubDef(e)})}async buildDefFromContent(e,t,r,n){let{dts:i,url:o,resolvedPkg:a}=t,c=new g(a||r),d=c.version?`${c.name}@${c.version}`:c.name,{mainPath:u,packageRootUrl:f}=this.computeEntryPath(o,d),h=[{path:u,content:i}],p=[];o&&await this.expandRelativeRefs(i,o,d,h,void 0,f);let l=h.map(y=>y.content).join(`
174
- `);await this.prefetchBareDeps(l,d,h,p,n);let m=c.format(),w=e===m?[e]:[e,m];return p.push(...w.map(y=>({module:y,path:u}))),{pkg:e,mainPath:u,files:h,shims:p}}};function Ye(s){return new Te(s)}import*as I from"fs/promises";import*as M from"path";import*as Mt from"os";import*as Xe from"fs/promises";import*as Dt from"crypto";function k(s){return Dt.createHash("sha1").update(s).digest("hex")}async function W(s){try{return JSON.parse(await Xe.readFile(s,"utf8"))}catch{return}}async function Ce(s){try{return await Xe.readFile(s,"utf8")}catch{return}}var At=1,j=M.join(Mt.homedir(),".typebulb","cache"),ge=M.join(j,"packages"),ye=M.join(j,"proxy"),_e=M.join(j,"dts"),Cr=M.join(j,"emit"),Qe;function v(){return Qe||(Qe=_r()),Qe}function Ie(s,e){return M.join(Cr,k(s),e)}async function _r(){await I.mkdir(j,{recursive:!0});let s=M.join(j,"version.json");if((await Ir(s))?.version===At)return;let t=await I.readdir(j).catch(()=>[]);await Promise.all(t.map(r=>I.rm(M.join(j,r),{recursive:!0,force:!0}))),await I.writeFile(s,JSON.stringify({version:At})+`
175
- `,"utf8")}async function Ir(s){try{let e=await I.readFile(s,"utf8");return JSON.parse(e)}catch{return}}import*as N from"fs/promises";import*as Ot from"path";async function P(s,e){await N.mkdir(Ot.dirname(s),{recursive:!0});let t=`${s}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await N.writeFile(t,e,"utf8"),await N.rename(t,s).catch(async r=>{throw await N.rm(t,{force:!0}).catch(()=>{}),r})}var X=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=W(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 r=await this.load();r.set(e,t),await this.persist(r)}async delete(e){let t=await this.load();t.delete(e)&&await this.persist(t)}async persist(e){await P(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var Ze=T.join(ge,"indexes"),Ft=T.join(ge,"pinned"),Dr=T.join(ge,"meta"),Ar=T.join(ge,"negative.json"),Q=Symbol("missing"),Ae=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new L(new X(Ar));async getPinnedExact(e,t){let r=`${e}@${t}`,n=this.pinnedMem.get(r);if(n!==void 0)return n===Q?void 0:n;await v();let i=await Ce(T.join(Ft,k(r)+".txt"));return this.pinnedMem.set(r,i??Q),i}async setPinnedExact(e,t,r){let n=`${e}@${t}`;this.pinnedMem.set(n,r),await v(),await P(T.join(Ft,k(n)+".txt"),r)}async getIndex(e){let t=this.indexMem.get(e);if(t!==void 0)return t===Q?void 0:t;await v();let r=await W(T.join(Ze,De(e)+".json"));return this.indexMem.set(e,r??Q),r}async setIndex(e,t,r){let n={versions:t,distTags:r,updatedAt:Date.now()};this.indexMem.set(e,n),await v(),await P(T.join(Ze,De(e)+".json"),JSON.stringify(n))}async invalidateVersionsCache(e){this.indexMem.delete(e),await Nt.rm(T.join(Ze,De(e)+".json"),{force:!0})}async isNegative(e){return await v(),this.negativeCache.isNegative(e)}async recordNegative(e){await v(),await this.negativeCache.recordNegative(e)}async clearNegative(e){await this.negativeCache.clearNegative(e)}async getMeta(e,t){let r=`${e}@${t}`,n=this.metaMem.get(r);if(n!==void 0)return n===Q?void 0:n;await v();let i=await W(jt(e,t));return this.metaMem.set(r,i??Q),i}async setMeta(e,t,r,n,i){let o={dependencies:r,peerDependencies:n,peerDependenciesMeta:i,updatedAt:Date.now()};this.metaMem.set(`${e}@${t}`,o),await v(),await P(jt(e,t),JSON.stringify(o))}};function jt(s,e){return T.join(Dr,De(s),encodeURIComponent(e)+".json")}function De(s){return s.replace(/\//g,"__")}var Mr={async getJson(s){try{let e=await fetch(s,{redirect:"follow"});return e.ok?await e.json():void 0}catch{return}},async head(s){try{let e=await fetch(s,{method:"HEAD",redirect:"follow"});return{ok:e.ok,url:e.url}}catch{return}}},Or=new Ae,{packageService:Me,versionResolver:$t,cdnClient:Ut,peerResolver:fi}=Pt(Or,Mr);var Bt=`
175
+ `;var H=class{constructor(e){this.store=e}async isNegative(e){let t=await De(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let r=((await De(()=>this.store.get(e)))?.attempts||0)+1;await De(()=>this.store.set(e,{until:Date.now()+Or(r),attempts:r}))}async clearNegative(e){await De(()=>this.store.delete(e))}};function Or(s){return Math.min(9e5*Math.pow(2,Math.max(0,s-1)),864e5)}async function De(s){try{return await s()}catch{return}}import Nr from"p-limit";import{resolve as Mt}from"resolve.exports";var Z=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 L={maxRelativeTypeRefs:500,maxBareDeps:8,maxBareDepth:3,prefetchConcurrency:4,negativeTtlMs:1e4},pe=["index.d.ts","index.d.mts"],ue=/\.d\.(ts|mts)$/i;function Xe(s){if(ue.test(s))return!0;try{return new URL(s,"file://").search.includes("dts")}catch{return s.includes("?")&&s.includes("dts")}}function Ie(s){return[`${s}.d.ts`,`${s}.d.mts`]}async function fe(s,{retries:e=2,timeoutMs:t=15e3,init:r}={}){for(let n=0;n<=e;n++){let o=new AbortController,i=setTimeout(()=>o.abort(),t);try{let a=await fetch(s,{...r,signal:o.signal});if(Ar(a.status)&&n<e)continue;return a}catch{if(n<e)continue;return}finally{clearTimeout(i)}}}function Ar(s){return s===408||s===429||s>=500&&s<600}var me=class extends Z{constructor(e,t){super(e),this.cdnClient=t}async loadPackageAtVersionedRoot(e,t){let r=this.cdnClient.packageJson(new h({name:e,version:t})),n=await fe(r);if(!n?.ok)return;let o;try{o=await n.json()}catch{return}if(o)return{pkg:o,baseDir:this.cdnClient.baseDir(new h({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 n=await t(r);if(n)return n}}async resolveFromSelected(e,t){if(e.kind==="types"){let n=this.cdnClient.normalizeRelative(e.path);if(!n||n==="/"||n===".")return this.tryUntilSuccess([...pe],t);if(!ue.test(n)){let o=await this.tryUntilSuccess(this.declarationCandidatesFor(n),t);if(o)return o}return t(n)}let r=this.declarationCandidatesFor(e.path);return this.tryUntilSuccess([...pe,...r],t)}toResolutionResult(e){return{kind:ue.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let r=t||".",n=e;try{let o=this.extractPathFromResult(Mt(n,r,{conditions:["types"]}));if(o)return o}catch{}try{return this.extractPathFromResult(Mt(n,r,{browser:!0,conditions:["import","default","module","browser","node"]}))}catch{return}}async resolve(e){try{let t=h.parse(e),{pkg:r,baseDir:n}=await this.loadPackageAtVersionedRoot(t.name,t.version)||{};if(!r||!n)return;let o={name:t.name,version:t.version},i=new h(o).format(),a=new h({...o,subpath:t.subpath}).format(),l=f=>this.fetchCandidateFrom(n,t.name,f);if(t.subpath){let f=this.cdnClient.ensureLeadingDotSlash(t.subpath),m=this.resolveExportsPath(r,f);if(m){let c=await this.resolveFromSelected(this.toResolutionResult(m),l);if(c)return{...c,resolvedPkg:a}}let y=await this.tryUntilSuccess(this.declarationCandidatesFor(f),l);if(y)return{...y,resolvedPkg:a}}let d=r.types??r.typings;if(d){let f=await this.resolveFromSelected({kind:"types",path:d},l);if(f)return{...f,resolvedPkg:i}}let p=this.resolveExportsPath(r,".");if(p){let f=await this.resolveFromSelected(this.toResolutionResult(p),l);if(f)return{...f,resolvedPkg:i}}return}catch{return}}async fetchCandidateFrom(e,t,r){let n=this.cdnClient.normalizeRelative(r),o=new URL(n,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[...pe];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),r=Ie(t),n=t.endsWith("/")?t:`${t}/`;return r.push(...Ie(`${n}index`)),r}};import{gunzipSync as Mr}from"fflate";var ee=class{async fetchAndExtract(e,t){let r=this.getTarballUrl(e,t),n=await fe(r,{timeoutMs:3e4});if(!n?.ok)return new Map;let o=new Uint8Array(await n.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=Mr(e),n=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),l=a.indexOf(0),d=n.decode(a.slice(0,l>0?l:100)).trim(),p=i.slice(124,136),f=n.decode(p).trim().replace(/\0/g,""),m=parseInt(f,8)||0,y=String.fromCharCode(i[156]);if(o+=512,(y==="0"||y==="\0")&&(d.endsWith(".d.ts")||d.endsWith(".d.mts"))){let c=r.slice(o,o+m);t.set(this.normalizeTarPath(d),n.decode(c))}o+=Math.ceil(m/512)*512}}catch{}return t}},$r=new ee;var he=class extends Z{constructor(e,t,r,n=new ee){super(e),this.cdnClient=t,this.cache=r,this.tarballFetcher=n}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=V.majorOf(r),i=e.filter(a=>V.majorOf(a)===o);if(i.length)return i.sort((a,l)=>V.cmp(l,a))[0]}let n=t?.latest;return n&&e.includes(n)?n:e[0]}catch{return e[0]}}async fetchFromVersionedRoot(e,t){let r=new h(e),n=r.version;if(!n)return;let o;try{o=await this.tarballFetcher.fetchAndExtract(r.name,n)}catch{return}if(!o||o.size===0)return;for(let[a,l]of o.entries()){let d=this.cdnClient.file(e,a);try{await this.cache.setCachedFile(d,l)}catch{}}let i=t.subpath?[t.subpath+".d.ts",t.subpath+"/index.d.ts"]:["index.d.ts"];for(let a of i){let l=o.get(a);if(l)return{dts:l,url:this.cdnClient.file(e,a),resolvedPkg:t.subpath?new h(t).format():t.name}}}async resolve(e){let t=h.parse(e);if(t.name)for(let r of this.typesNameCandidates(t.name)){let n=`@types/${r}`,o;try{o=await this.cdnClient.fetchVersionsIndex(n)}catch{continue}if(!o?.versions?.length)continue;let i=this.selectTypesVersion(o.versions,o.distTags,t.version),a=await this.fetchFromVersionedRoot(`${n}@${i}`,t);if(a)return a}}};var ge=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=(n,o)=>(t.add(n[o]),null);return this.matchAll(e,/(import|export)\s+[^'"\n]*from\s*['"]([^'"\n]+)['"]/,n=>r(n,2)),this.matchAll(e,/export\s*\*\s*from\s*['"]([^'"\n]+)['"]/,n=>r(n,1)),Array.from(t)}matchAll(e,t,r){let n=[];try{let o=new RegExp(t.source,"g"),i;for(;i=o.exec(e);){let a=r(i);a!==null&&n.push(a)}}catch{}return n}isBare(e){return!(e.startsWith("./")||e.startsWith("../")||e.startsWith("file:")||e.startsWith("http://")||e.startsWith("https://"))}};var $t="file:///node_modules",ye=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`${$t}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let r=Fr(t);return`${$t}/${this.epochDir()}/${e}/${r}`}};function Fr(s){let e=s||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as jr}from"lru-cache";function Qe(s){let e=new jr({ttl:1e4,max:500}),t=new Map;return async function(n){try{if(await s.isNegative(n))return;let o=e.get(n);if(o&&Date.now()-o<1e4)return;let i=await s.getCachedFile(n);if(i)return{dts:i,url:n};let a=t.get(n);if(a)return a;let l=(async()=>{let d=await fetch(n,{cache:"no-store"});if(!d.ok){d.status===404&&(e.set(n,Date.now()),await s.recordNegative(n));return}let p=await d.text(),f=d.url||n;return await s.clearNegative(n),await s.setCachedFile(f,p),{dts:p,url:f}})();return t.set(n,l),await l.finally(()=>t.delete(n))}catch{return}}}var _e=class{constructor(e){this.inFlight=new Map,this.scanner=new ge,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=Qe(e.cache),this.typescriptProvider=new me(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new he(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new ye}withInFlight(e,t){let r=this.inFlight.get(e);if(r)return r;let n=t().finally(()=>this.inFlight.delete(e));return this.inFlight.set(e,n),n}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(n=>n.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 h(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 h(e).subpath===new h(t).subpath}async fetchRootDts(e,t){let{effectivePackage:r,root:n,pinned:o}=await this.versionResolver.effectivePackage(e,t),i=await this.cache.getCachedDts(r);if(i?.content){let l=i.url??this.cdnClient.file(o?`${n}@${o}`:n,"index.d.ts");return{dts:i.content,url:l,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 n=t.pathname.startsWith(e.pathname)?t.pathname.slice(e.pathname.length):`__deps__/${encodeURIComponent(t.toString()).replace(/%/g,"_")}.d.ts`;return this.virtualFs.pathFor(r,n)}computeEntryPath(e,t){if(!e)return{mainPath:this.virtualFs.pathForMain(t),packageRootUrl:void 0};let r=new URL(e),n=this.extractPackageRootUrl(r);return{mainPath:this.toVirtualPath(n,r,t),packageRootUrl:n}}async expandRelativeRefs(e,t,r,n,o=new Set,i){if(!o.has(t)&&(o.add(t),!(o.size>L.maxRelativeTypeRefs)))try{let a=new URL(t),l=new URL("./",a);i??(i=this.extractPackageRootUrl(a));let d=this.capArray(this.scanner.collectRelativeTypeRefs(e),L.maxRelativeTypeRefs);for(let p of d)await this.tryRelativeRef(p,l,i,r,n,o)}catch{}}async tryRelativeRef(e,t,r,n,o,i){try{let a=new URL(e,t),l=a.pathname+a.search,d=Xe(l)?[l]:this.typescriptProvider.declarationCandidatesFor(l);for(let p of d){let m=new URL(p,a).toString();if(i.has(m))return;let y=await this.fetchDts(m);if(y?.dts){let c=this.toVirtualPath(r,new URL(y.url),n);this.pushFileIfNew(o,c,y.dts),await this.expandRelativeRefs(y.dts,y.url,n,o,i,r);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new h(e).name!==new h(t).name}async prefetchBareDeps(e,t,r,n,o){try{let i=this.capArray(this.scanner.collectBareModuleRefs(e),L.maxBareDeps).filter(d=>this.isDifferentPackage(d,t));if(!i.length)return;let a=new Set([t]),l=Nr(L.prefetchConcurrency);await Promise.all(i.map(d=>l(()=>this.prefetchBareDepsRecursive(d,r,n,L.maxBareDepth,a,o).catch(()=>{}))))}catch{}}async prefetchBareDepsRecursive(e,t,r,n,o,i){if(n<=0||o.has(e))return;o.add(e);let a=await this.fetchRootDts(e,i);if(!a?.dts)return;let l=a.resolvedPkg||e,d=this.virtualFs.pathForMain(l);this.pushFileIfNew(t,d,a.dts),r.push({module:e,path:d}),a.url&&await this.expandRelativeRefs(a.dts,a.url,l,t);let p=this.capArray(this.scanner.collectBareModuleRefs(a.dts),L.maxBareDeps).filter(f=>!o.has(f));for(let f of p)await this.prefetchBareDepsRecursive(f,t,r,n-1,o,i)}async resolve(e,t,r){let n=await this.packageService.extractImports(e),o=r?[...n,...r]:n;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 n=await this.fetchRootDts(e,t)??await this.trySubpathWithRootFallback(e,t);return n?this.buildDefFromContent(e,n,n.resolvedPkg||e,t):this.createStubDef(e)})}async buildDefFromContent(e,t,r,n){let{dts:o,url:i,resolvedPkg:a}=t,l=new h(a||r),d=l.version?`${l.name}@${l.version}`:l.name,{mainPath:p,packageRootUrl:f}=this.computeEntryPath(i,d),m=[{path:p,content:o}],y=[];i&&await this.expandRelativeRefs(o,i,d,m,void 0,f);let c=m.map(v=>v.content).join(`
176
+ `);await this.prefetchBareDeps(c,d,m,y,n);let u=l.format(),g=e===u?[e]:[e,u];return y.push(...g.map(v=>({module:v,path:p}))),{pkg:e,mainPath:p,files:m,shims:y}}};function Ze(s){return new _e(s)}import*as F from"fs/promises";import*as j from"path";import*as Nt from"os";import*as et from"fs/promises";import*as Ft from"crypto";function _(s){return Ft.createHash("sha1").update(s).digest("hex")}async function q(s){try{return JSON.parse(await et.readFile(s,"utf8"))}catch{return}}async function Oe(s){try{return await et.readFile(s,"utf8")}catch{return}}var jt=1,U=j.join(Nt.homedir(),".typebulb","cache"),we=j.join(U,"packages"),ve=j.join(U,"proxy"),Ae=j.join(U,"dts"),Lr=j.join(U,"emit"),tt;function b(){return tt||(tt=Ur()),tt}function Me(s,e){return j.join(Lr,_(s),e)}async function Ur(){await F.mkdir(U,{recursive:!0});let s=j.join(U,"version.json");if((await Br(s))?.version===jt)return;let t=await F.readdir(U).catch(()=>[]);await Promise.all(t.map(r=>F.rm(j.join(U,r),{recursive:!0,force:!0}))),await F.writeFile(s,JSON.stringify({version:jt})+`
177
+ `,"utf8")}async function Br(s){try{let e=await F.readFile(s,"utf8");return JSON.parse(e)}catch{return}}import*as B from"fs/promises";import*as Lt from"path";async function k(s,e){await B.mkdir(Lt.dirname(s),{recursive:!0});let t=`${s}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await B.writeFile(t,e,"utf8"),await B.rename(t,s).catch(async r=>{throw await B.rm(t,{force:!0}).catch(()=>{}),r})}var te=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=q(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 r=await this.load();r.set(e,t),await this.persist(r)}async delete(e){let t=await this.load();t.delete(e)&&await this.persist(t)}async persist(e){await k(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var rt=O.join(we,"indexes"),Ut=O.join(we,"pinned"),Wr=O.join(we,"meta"),Jr=O.join(we,"negative.json"),re=Symbol("missing"),Fe=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new H(new te(Jr));async getPinnedExact(e,t){let r=`${e}@${t}`,n=this.pinnedMem.get(r);if(n!==void 0)return n===re?void 0:n;await b();let o=await Oe(O.join(Ut,_(r)+".txt"));return this.pinnedMem.set(r,o??re),o}async setPinnedExact(e,t,r){let n=`${e}@${t}`;this.pinnedMem.set(n,r),await b(),await k(O.join(Ut,_(n)+".txt"),r)}async getIndex(e){let t=this.indexMem.get(e);if(t!==void 0)return t===re?void 0:t;await b();let r=await q(O.join(rt,$e(e)+".json"));return this.indexMem.set(e,r??re),r}async setIndex(e,t,r){let n={versions:t,distTags:r,updatedAt:Date.now()};this.indexMem.set(e,n),await b(),await k(O.join(rt,$e(e)+".json"),JSON.stringify(n))}async invalidateVersionsCache(e){this.indexMem.delete(e),await Wt.rm(O.join(rt,$e(e)+".json"),{force:!0})}async isNegative(e){return await b(),this.negativeCache.isNegative(e)}async recordNegative(e){await b(),await this.negativeCache.recordNegative(e)}async clearNegative(e){await this.negativeCache.clearNegative(e)}async getMeta(e,t){let r=`${e}@${t}`,n=this.metaMem.get(r);if(n!==void 0)return n===re?void 0:n;await b();let o=await q(Bt(e,t));return this.metaMem.set(r,o??re),o}async setMeta(e,t,r,n,o){let i={dependencies:r,peerDependencies:n,peerDependenciesMeta:o,updatedAt:Date.now()};this.metaMem.set(`${e}@${t}`,i),await b(),await k(Bt(e,t),JSON.stringify(i))}};function Bt(s,e){return O.join(Wr,$e(s),encodeURIComponent(e)+".json")}function $e(s){return s.replace(/\//g,"__")}var Vr={async getJson(s){try{let e=await fetch(s,{redirect:"follow"});return e.ok?await e.json():void 0}catch{return}},async head(s){try{let e=await fetch(s,{method:"HEAD",redirect:"follow"});return{ok:e.ok,url:e.url}}catch{return}}},Hr=new Fe,{packageService:je,versionResolver:Jt,cdnClient:Vt,peerResolver:Mo}=Tt(Hr,Vr);var Ht=`
176
178
  (() => {
177
179
  // JSON parser (handles jsonish - unquoted keys)
178
180
  const parseJson = (str) => {
@@ -187,31 +189,38 @@ declare const tb: {${St}${Rt}${Et}${Ct}${wr}${kt}${Tt}
187
189
  // Read from window each time so updates are visible
188
190
  const getData = () => window.__TB_DATA__ || [];
189
191
 
190
- // Filesystem API - calls back to the local server
192
+ // Filesystem API - calls back to the local server.
193
+ // The server returns raw bytes (no JSON envelope); read() decodes as UTF-8.
194
+ const failIfNotOk = async (resp, action, path) => {
195
+ if (resp.ok) return;
196
+ const err = await resp.json().catch(() => ({}));
197
+ throw new Error(err.error || 'Failed to ' + action + ' file: ' + path);
198
+ };
199
+ const fetchFileBytes = async (path) => {
200
+ const resp = await fetch('/__fs/read', {
201
+ method: 'POST',
202
+ headers: { 'Content-Type': 'application/json' },
203
+ body: JSON.stringify({ path })
204
+ });
205
+ await failIfNotOk(resp, 'read', path);
206
+ return resp.arrayBuffer();
207
+ };
191
208
  const fs = {
192
209
  read: async (path) => {
193
- const resp = await fetch('/__fs/read', {
194
- method: 'POST',
195
- headers: { 'Content-Type': 'application/json' },
196
- body: JSON.stringify({ path })
197
- });
198
- if (!resp.ok) {
199
- const err = await resp.json().catch(() => ({ error: 'Failed to read file' }));
200
- throw new Error(err.error || 'Failed to read file: ' + path);
210
+ const buf = await fetchFileBytes(path);
211
+ try {
212
+ return new TextDecoder('utf-8', { fatal: true }).decode(buf);
213
+ } catch {
214
+ throw new Error('File is not valid UTF-8 text: ' + path + ' \u2014 use tb.fs.readBytes() for binary files.');
201
215
  }
202
- const { content } = await resp.json();
203
- return content;
204
216
  },
217
+ readBytes: async (path) => new Uint8Array(await fetchFileBytes(path)),
205
218
  write: async (path, content) => {
206
- const resp = await fetch('/__fs/write', {
219
+ const resp = await fetch('/__fs/write?path=' + encodeURIComponent(path), {
207
220
  method: 'POST',
208
- headers: { 'Content-Type': 'application/json' },
209
- body: JSON.stringify({ path, content })
221
+ body: content
210
222
  });
211
- if (!resp.ok) {
212
- const err = await resp.json().catch(() => ({ error: 'Failed to write file' }));
213
- throw new Error(err.error || 'Failed to write file: ' + path);
214
- }
223
+ await failIfNotOk(resp, 'write', path);
215
224
  return true;
216
225
  }
217
226
  };
@@ -320,12 +329,12 @@ declare const tb: {${St}${Rt}${Et}${Ct}${wr}${kt}${Tt}
320
329
  };
321
330
  }
322
331
  })();
323
- `;function Lt(s){let{name:e,code:t,css:r,html:n,data:i,insight:o,importMap:a,watch:c}=s,d=n.trim()||'<div id="app"></div>',u=h=>h.replace(/<\/script/gi,"<\\/script"),f={imports:jr(a.imports)};return`<!DOCTYPE html>
332
+ `;function qt(s){let{name:e,code:t,css:r,html:n,data:o,insight:i,importMap:a,watch:l}=s,d=n.trim()||'<div id="app"></div>',p=m=>m.replace(/<\/script/gi,"<\\/script"),f={imports:Gr(a.imports)};return`<!DOCTYPE html>
324
333
  <html>
325
334
  <head>
326
335
  <meta charset="utf-8">
327
336
  <meta name="viewport" content="width=device-width, initial-scale=1">
328
- <title>${Fr(e)} - typebulb</title>
337
+ <title>${qr(e)} - typebulb</title>
329
338
  <script type="importmap">
330
339
  ${JSON.stringify(f,null,2)}
331
340
  </script>
@@ -341,35 +350,35 @@ ${r}
341
350
  <body>
342
351
  ${d}
343
352
 
344
- ${i.length>0?`<script>window.__TB_DATA__ = ${u(JSON.stringify(i))};</script>`:""}
345
- ${o?`<script>window.__TB_INSIGHT__ = ${u(JSON.stringify(o))};</script>`:""}
346
- ${c?"<script>window.__TYPEBULB_WATCH__ = true;</script>":""}
353
+ ${o.length>0?`<script>window.__TB_DATA__ = ${p(JSON.stringify(o))};</script>`:""}
354
+ ${i?`<script>window.__TB_INSIGHT__ = ${p(JSON.stringify(i))};</script>`:""}
355
+ ${l?"<script>window.__TYPEBULB_WATCH__ = true;</script>":""}
347
356
 
348
357
  <script>
349
- ${Bt}
358
+ ${Ht}
350
359
  </script>
351
360
 
352
361
  <script type="module">
353
- ${u(t)}
362
+ ${p(t)}
354
363
  </script>
355
364
  </body>
356
- </html>`}function Fr(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function jr(s){let e={};for(let[t,r]of Object.entries(s))e[t]=r.startsWith("https://")?"/proxy/"+r:r;return e}import{Hono as $r}from"hono";import{serve as Ur}from"@hono/node-server";import{streamSSE as Br}from"hono/streaming";import*as ee from"fs/promises";import*as J from"path";var S=class extends Error{constructor(e,t="unknown",r=!1){super(e),this.code=t,this.retryable=r}},C=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=`
365
+ </html>`}function qr(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Gr(s){let e={};for(let[t,r]of Object.entries(s))e[t]=r.startsWith("https://")?"/proxy/"+r:r;return e}import{Hono as Kr}from"hono";import{serve as Yr}from"@hono/node-server";import{streamSSE as Xr}from"hono/streaming";import*as z from"fs/promises";import*as M from"path";var T=class extends Error{constructor(e,t="unknown",r=!1){super(e),this.code=t,this.retryable=r}},A=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=`
357
366
 
358
- `){let r=e.filter(n=>n.role==="system").map(n=>n.content);return{system:r.length?r.join(t):void 0,conversationMessages:e.filter(n=>n.role!=="system")}}parseJsonError(e,t,r=!1){if(!e)return{message:`HTTP ${t}`};try{let n=JSON.parse(e);if(n.error&&typeof n.error=="object"){let i={message:n.error.message||`HTTP ${t}`,type:n.error.type};return r&&(i.code=n.error.code),i}return n.message?{message:n.message}:{message:e}}catch{return{message:e}}}checkAndThrowError(e){if("type"in e&&e.type==="error"&&"message"in e){let t=e.message,r=e.code||"unknown",n=!!e.retryable;throw new S(t,r,n)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new S(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 we=class extends C{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,r,n){let{system:i,conversationMessages:o}=this.extractSystemMessages(e),a={model:t,max_tokens:this.getMaxTokens(t),messages:o,stream:n};if(r?.webSearch!==!1&&(a.tools=[{type:"web_search_20250305",name:"web_search"}]),i&&(a.system=i),this.isReasoningEnabled(r)){let c=r.reasoning;if(this.isModernModel(t)){let d={0:"low",1:"low",2:"medium",3:"high"};a.thinking={type:"adaptive"},a.output_config={effort:d[c]}}else{let d={0:0,1:2048,2:4096,3:8192};a.thinking={type:"enabled",budget_tokens:d[c]}}}return a}parseError(e,t){return this.parseJsonError(e,t)}parseNonStreamingResponse(e){if(!this.isAnthropicResponse(e))return{text:""};let t=e.content.filter(n=>n.type==="text").map(n=>n.text).join(""),r=e.content.filter(n=>n.type==="thinking").map(n=>n.thinking).join(`
367
+ `){let r=e.filter(n=>n.role==="system").map(n=>n.content);return{system:r.length?r.join(t):void 0,conversationMessages:e.filter(n=>n.role!=="system")}}parseJsonError(e,t,r=!1){if(!e)return{message:`HTTP ${t}`};try{let n=JSON.parse(e);if(n.error&&typeof n.error=="object"){let o={message:n.error.message||`HTTP ${t}`,type:n.error.type};return r&&(o.code=n.error.code),o}return n.message?{message:n.message}:{message:e}}catch{return{message:e}}}checkAndThrowError(e){if("type"in e&&e.type==="error"&&"message"in e){let t=e.message,r=e.code||"unknown",n=!!e.retryable;throw new T(t,r,n)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new T(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 be=class extends A{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,r,n){let{system:o,conversationMessages:i}=this.extractSystemMessages(e),a={model:t,max_tokens:this.getMaxTokens(t),messages:i,stream:n};if(r?.webSearch!==!1&&(a.tools=[{type:"web_search_20250305",name:"web_search"}]),o&&(a.system=o),this.isReasoningEnabled(r)){let l=r.reasoning;if(this.isModernModel(t)){let d={0:"low",1:"low",2:"medium",3:"high"};a.thinking={type:"adaptive"},a.output_config={effort:d[l]}}else{let d={0:0,1:2048,2:4096,3:8192};a.thinking={type:"enabled",budget_tokens:d[l]}}}return a}parseError(e,t){return this.parseJsonError(e,t)}parseNonStreamingResponse(e){if(!this.isAnthropicResponse(e))return{text:""};let t=e.content.filter(n=>n.type==="text").map(n=>n.text).join(""),r=e.content.filter(n=>n.type==="thinking").map(n=>n.thinking).join(`
359
368
 
360
- `);return{text:t,reasoning:r||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}}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 ve=class extends C{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,r,n){let i=this.convertMessagesToInput(e),o={model:t,input:i,stream:n};return r?.webSearch!==!1&&(o.tools=[{type:"web_search"}]),this.isReasoningEnabled(r)&&(o.reasoning={effort:this.effortMap[r.reasoning],summary:"auto"}),o}parseError(e,t){return this.parseJsonError(e,t,!0)}parseNonStreamingResponse(e){if(!this.isResponsesApiResponse(e))return{text:""};let t=e.output_text||"",r;if(e.output&&Array.isArray(e.output))for(let n of e.output)n.type==="reasoning"&&n.summary&&(r=n.summary.map(i=>i.text).join(`
361
- `)),!t&&n.type==="message"&&n.content&&(t=n.content.filter(i=>i.type==="output_text").map(i=>i.text).join(""));return{text:t,reasoning:r}}parseProviderStreamChunk(e){if(!this.isResponsesApiEvent(e))return null;switch(e.type){case"error":return null;case"response.failed":{let n=e.response?.error,i=n?.message||"Response failed",o=n?.code==="insufficient_quota"||n?.code==="rate_limit_exceeded";throw new S(i,o?"rate_limit":"unknown",o)}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(`
369
+ `);return{text:t,reasoning:r||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}}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 xe=class extends A{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,r,n){let o=this.convertMessagesToInput(e),i={model:t,input:o,stream:n};return r?.webSearch!==!1&&(i.tools=[{type:"web_search"}]),this.isReasoningEnabled(r)&&(i.reasoning={effort:this.effortMap[r.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||"",r;if(e.output&&Array.isArray(e.output))for(let n of e.output)n.type==="reasoning"&&n.summary&&(r=n.summary.map(o=>o.text).join(`
370
+ `)),!t&&n.type==="message"&&n.content&&(t=n.content.filter(o=>o.type==="output_text").map(o=>o.text).join(""));return{text:t,reasoning:r}}parseProviderStreamChunk(e){if(!this.isResponsesApiEvent(e))return null;switch(e.type){case"error":return null;case"response.failed":{let n=e.response?.error,o=n?.message||"Response failed",i=n?.code==="insufficient_quota"||n?.code==="rate_limit_exceeded";throw new T(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(`
362
371
 
363
- `)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var be=class extends C{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,r,n){let{system:i,conversationMessages:o}=this.extractSystemMessages(e,`
364
- `),c={contents:o.map(d=>({role:d.role==="assistant"?"model":"user",parts:[{text:d.content}]}))};return r?.webSearch!==!1&&(c.tools=[{google_search:{}}]),i&&(c.systemInstruction={role:"system",parts:[{text:i}]}),this.isReasoningEnabled(r)&&(c.generationConfig={temperature:.7+r.reasoning*.1}),c}parseError(e,t){if(!e)return{message:`HTTP ${t}`};try{let r=JSON.parse(e),n=Array.isArray(r)?r[0]?.error:r?.error;return n&&typeof n=="object"?{message:(n.message||`HTTP ${t}`).split(`
365
- `)[0],type:n.status,code:n.code?.toString()}:r.message?{message:r.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)||"",r=e.candidates?.[0]?.finishReason,n="complete";return r==="MAX_TOKENS"?n="interrupted":(r==="SAFETY"||r==="RECITATION")&&(n="failed"),{text:t,status:n}}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(r=>r.text).filter(Boolean).join("")}checkGeminiError(e){if(typeof e=="object"&&e!==null&&"error"in e){let t=e.error,r;if(typeof t=="string")r=t;else if(typeof t=="object"&&t!==null){let n=t;r=n.message||n.status||"Gemini returned an error"}else r="Gemini returned an error";throw new S(r)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new S(`Prompt blocked: ${t}`)}}};var xe=class extends C{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 r={Authorization:`Bearer ${e}`,"x-api-key":e,"Content-Type":"application/json",Accept:"application/json","X-Title":"Typebulb"};return t&&(r["HTTP-Referer"]=t,r.Referer=t,r.Origin=t),r}buildPayload(e,t,r,n){let i={model:t,messages:e,stream:n};return r?.webSearch===!0&&(i.plugins=[{id:"web"}]),this.isReasoningEnabled(r)&&(i.reasoning={effort:this.effortMap[r.reasoning]}),i}parseError(e,t){return this.parseJsonError(e,t,!0)}parseNonStreamingResponse(e){if(!this.hasChoices(e))return{text:""};let t=e.choices[0],r=t?.message?.content??t?.text??"",n=t?.message?.reasoning??e.reasoning;return{text:r,reasoning:n}}parseProviderStreamChunk(e){if(!this.hasChoices(e))return null;let t=e.choices[0];if(!t)return null;let r=t.delta||t.message;if(!r)return null;let n=r.content||void 0,i=r.reasoning||void 0;return!n&&!i?null:{text:n,reasoning:i}}hasChoices(e){return typeof e=="object"&&e!==null&&"choices"in e&&Array.isArray(e.choices)}};var Nr=new Map([["openai",new ve],["openrouter",new xe],["anthropic",new we],["gemini",new be]]);function V(s){let e=Nr.get(s);if(!e)throw new Error(`Unsupported protocol: ${s}`);return e}async function et(s,e){let t=V(s.protocol),r=t.getPath(e.model,e.stream),n=new URL(r,s.baseUrl).toString(),i=t.buildHeaders(s.apiKey,e.origin),o=t.buildPayload(e.messages,e.model,{reasoning:e.reasoning,webSearch:e.webSearch},e.stream);return e.modifyPayload?.(o),fetch(n,{method:"POST",headers:i,body:JSON.stringify(o),signal:e.signal})}async function tt(s,e){let t=V(e),r=await s.text().catch(()=>""),{message:n}=t.parseError(r,s.status),i=s.status,o="unknown";return i===429?o="rate_limit":i===413&&(o="context_exceeded"),{code:o,message:n,retryable:i===429}}function Wt(s){let e=s.indexOf(`\r
372
+ `)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var Pe=class extends A{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,r,n){let{system:o,conversationMessages:i}=this.extractSystemMessages(e,`
373
+ `),l={contents:i.map(d=>({role:d.role==="assistant"?"model":"user",parts:[{text:d.content}]}))};return r?.webSearch!==!1&&(l.tools=[{google_search:{}}]),o&&(l.systemInstruction={role:"system",parts:[{text:o}]}),this.isReasoningEnabled(r)&&(l.generationConfig={temperature:.7+r.reasoning*.1}),l}parseError(e,t){if(!e)return{message:`HTTP ${t}`};try{let r=JSON.parse(e),n=Array.isArray(r)?r[0]?.error:r?.error;return n&&typeof n=="object"?{message:(n.message||`HTTP ${t}`).split(`
374
+ `)[0],type:n.status,code:n.code?.toString()}:r.message?{message:r.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)||"",r=e.candidates?.[0]?.finishReason,n="complete";return r==="MAX_TOKENS"?n="interrupted":(r==="SAFETY"||r==="RECITATION")&&(n="failed"),{text:t,status:n}}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(r=>r.text).filter(Boolean).join("")}checkGeminiError(e){if(typeof e=="object"&&e!==null&&"error"in e){let t=e.error,r;if(typeof t=="string")r=t;else if(typeof t=="object"&&t!==null){let n=t;r=n.message||n.status||"Gemini returned an error"}else r="Gemini returned an error";throw new T(r)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new T(`Prompt blocked: ${t}`)}}};var Re=class extends A{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 r={Authorization:`Bearer ${e}`,"x-api-key":e,"Content-Type":"application/json",Accept:"application/json","X-Title":"Typebulb"};return t&&(r["HTTP-Referer"]=t,r.Referer=t,r.Origin=t),r}buildPayload(e,t,r,n){let o={model:t,messages:e,stream:n};return r?.webSearch===!0&&(o.plugins=[{id:"web"}]),this.isReasoningEnabled(r)&&(o.reasoning={effort:this.effortMap[r.reasoning]}),o}parseError(e,t){return this.parseJsonError(e,t,!0)}parseNonStreamingResponse(e){if(!this.hasChoices(e))return{text:""};let t=e.choices[0],r=t?.message?.content??t?.text??"",n=t?.message?.reasoning??e.reasoning;return{text:r,reasoning:n}}parseProviderStreamChunk(e){if(!this.hasChoices(e))return null;let t=e.choices[0];if(!t)return null;let r=t.delta||t.message;if(!r)return null;let n=r.content||void 0,o=r.reasoning||void 0;return!n&&!o?null:{text:n,reasoning:o}}hasChoices(e){return typeof e=="object"&&e!==null&&"choices"in e&&Array.isArray(e.choices)}};var zr=new Map([["openai",new xe],["openrouter",new Re],["anthropic",new be],["gemini",new Pe]]);function G(s){let e=zr.get(s);if(!e)throw new Error(`Unsupported protocol: ${s}`);return e}async function nt(s,e){let t=G(s.protocol),r=t.getPath(e.model,e.stream),n=new URL(r,s.baseUrl).toString(),o=t.buildHeaders(s.apiKey,e.origin),i=t.buildPayload(e.messages,e.model,{reasoning:e.reasoning,webSearch:e.webSearch},e.stream);return e.modifyPayload?.(i),fetch(n,{method:"POST",headers:o,body:JSON.stringify(i),signal:e.signal})}async function st(s,e){let t=G(e),r=await s.text().catch(()=>""),{message:n}=t.parseError(r,s.status),o=s.status,i="unknown";return o===429?i="rate_limit":o===413&&(i="context_exceeded"),{code:i,message:n,retryable:o===429}}function Gt(s){let e=s.indexOf(`\r
366
375
  \r
367
376
  `),t=s.indexOf(`
368
377
 
369
- `);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function rt(s){let t=s.split(/\r?\n/).filter(n=>n.startsWith("data:"));if(!t.length)return null;let r=t.map(n=>n.replace(/^data:\s?/,"")).join(`
370
- `).trim();if(!r)return null;if(r==="[DONE]")return"done";try{return JSON.parse(r)}catch{return null}}async function Vt(s,e,t){let r=new TextDecoder,n="",i=!1,o=t?new Promise((a,c)=>{t.aborted&&c(new Error("Aborted")),t.addEventListener("abort",()=>c(new Error("Aborted")),{once:!0})}):null;for(;;){let a=o?await Promise.race([s.read(),o]):await s.read(),{done:c,value:d}=a;if(c){if(n.trim()){let h=rt(n);h!==null&&h!=="done"&&e(h)}break}i=!0,n+=r.decode(d,{stream:!0});let{pos:u,len:f}=Wt(n);for(;u!==-1;){let h=n.slice(0,u);n=n.slice(u+f);let p=rt(h);if(p==="done"){n="";break}p!==null&&e(p),{pos:u,len:f}=Wt(n)}}return{receivedAnyData:i}}async function nt(s,e){let t=e??(s.headers.get("X-Provider-Protocol")||"openai"),r=V(t);if(!s.body)throw new Error("Response body is missing");let n=s.body.getReader(),i="";return await Vt(n,o=>{let a=r.parseStreamChunk(o);a?.text&&(i+=a.text)}),i}import*as st from"fs/promises";import*as Pe from"path";var Oe=class{async get(e){let t=k(e),r=Pe.join(ye,t+".bin"),n=Pe.join(ye,t+".json");try{let[i,o]=await Promise.all([st.readFile(r),st.readFile(n,"utf8")]),a=JSON.parse(o);return{body:i,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await v();let r=k(e),n=Pe.join(ye,r+".bin"),i=Pe.join(ye,r+".json"),o={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([P(n,t.body),P(i,JSON.stringify(o))])}};async function Gt(s){let{getHtml:e,basePath:t,port:r,reloadEmitter:n,getServerExports:i}=s,o=new $r;o.use("*",async(p,l)=>{await l(),p.res.headers.set("Cross-Origin-Opener-Policy","same-origin"),p.res.headers.set("Cross-Origin-Embedder-Policy","credentialless")}),o.get("/",p=>p.html(e())),o.post("/__fs/read",async p=>{try{let{path:l}=await p.req.json(),m=Ht(l,t),w=await ee.readFile(m,"utf-8");return p.json({content:w})}catch(l){let m=l instanceof Error?l.message:"Unknown error";return p.json({error:m},400)}}),o.post("/__fs/write",async p=>{try{let{path:l,content:m}=await p.req.json(),w=Ht(l,t);return await ee.mkdir(J.dirname(w),{recursive:!0}),await ee.writeFile(w,m,"utf-8"),p.json({success:!0})}catch(l){let m=l instanceof Error?l.message:"Unknown error";return p.json({error:m},400)}});let a={log:console.log};o.post("/__api/:name",async p=>{try{let l=i?.(),m=p.req.param("name"),w=l?.[m]??a[m];if(!w||typeof w!="function")return p.json({error:`API function '${m}' not found`},404);let{args:y}=await p.req.json(),A=await w(...y||[]);return p.json({result:A})}catch(l){let m=l instanceof Error?l.message:"Unknown error";return p.json({error:m},500)}}),o.post("/__ai",async p=>{try{let{messages:l,system:m,reasoning:w,provider:y,model:A,webSearch:$}=await p.req.json();if(!l||!Array.isArray(l)||l.length===0)return p.json({message:"messages array is required",code:"unknown",retryable:!1},400);let _=Lr(y,A);if(typeof _=="string")return p.json({message:_,code:"unknown",retryable:!1},400);let re=[...m?[{role:"system",content:m}]:[],...l.map(O=>({role:O.role,content:O.content}))],U=await et(_,{model:_.model,messages:re,stream:!0,reasoning:w??0,webSearch:$??!0});if(!U.ok){let O=await tt(U,_.protocol);return p.json(O,U.status)}let Se=await nt(U,_.protocol);return Se||console.warn("[tb.ai] Empty response from provider"),p.json({text:Se})}catch(l){if(l instanceof S)return p.json({message:l.message,code:l.code,retryable:l.retryable},500);let m=l instanceof Error?l.message:"Unknown error";return p.json({message:m,code:"unknown",retryable:!1},500)}}),o.get("/__models",async p=>{try{let l=await Jr();return p.json(l)}catch{return p.json([],200)}});let c=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"],d=new Oe;o.get("/proxy/*",async p=>{let l=new URL(p.req.url),w=(l.pathname+l.search).slice(7),y=w.lastIndexOf("https://");return y===-1?p.text("Invalid proxy URL",400):u(p,w.slice(y))});async function u(p,l){let m;try{m=new URL(l)}catch{return p.text("Invalid URL",400)}if(m.protocol!=="https:")return p.text("HTTPS only",400);if(!c.includes(m.hostname))return p.text("Host not allowed",403);let w=await d.get(l);if(w)return new Response(w.body,{status:200,headers:it(w.contentType,w.cacheControl)});try{let y=await fetch(l,{headers:{Accept:p.req.header("Accept")||"*/*"},redirect:"follow"});if(!y.ok)return p.text(`Upstream ${y.status}`,y.status);let A=y.headers.get("Content-Type")||void 0,$=y.headers.get("Cache-Control")||void 0;if(y.body){let[_,re]=y.body.tee();return(async()=>{try{let U=await new Response(re).arrayBuffer();await d.set(l,{body:Buffer.from(U),contentType:A,cacheControl:$})}catch{}})(),new Response(_,{status:y.status,headers:it(A,$)})}return new Response(null,{status:y.status,headers:it(A,$)})}catch(y){return p.text(`Proxy fetch failed: ${y instanceof Error?y.message:y}`,502)}}n&&o.get("/__reload",p=>Br(p,async l=>{let m=()=>{l.writeSSE({event:"reload",data:""})};for(n.on("reload",m),l.onAbort(()=>{n.removeListener("reload",m)});;)await l.sleep(3e4)}));let f=/^\/(v\d+\/|stable\/|node\/|gh\/|@[^/]+\/[^@/]+@|[^@/]+@)/;o.notFound(async p=>{if(p.req.method!=="GET")return p.text("Not Found",404);let l=new URL(p.req.url);return f.test(l.pathname)?u(p,"https://esm.sh"+l.pathname+l.search):p.text("Not Found",404)});let h=Ur({fetch:o.fetch,port:r});return{port:r,close:()=>h.close()}}var qt={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function Lr(s,e){let t=s??process.env.TB_AI_PROVIDER,r=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(!r)return"No model specified. Set TB_AI_MODEL in your .env file or pass model in the tb.ai() call.";let n;try{n=V(t)}catch{return`Unknown provider '${t}'.`}let i=qt[t],o=process.env[i];return o?{apiKey:o,baseUrl:n.defaultBaseUrl,protocol:t,model:r,isFreeModel:!1}:`No API key for '${t}'. Set ${i} in your .env file.`}var Wr="https://api.typebulb.com/api/models",Vr=1440*60*1e3,Z=null;async function Jr(){if(!Z||Date.now()-Z.fetchedAt>Vr){let s=await fetch(Wr);if(!s.ok)return Z?Jt(Z.models):[];Z={models:await s.json(),fetchedAt:Date.now()}}return Jt(Z.models)}function Jt(s){let e=new Set(Object.entries(qt).filter(([,t])=>!!process.env[t]).map(([t])=>t));return s.filter(t=>e.has(t.provider))}function it(s,e){let t=new Headers;return s&&t.set("Content-Type",s),e&&t.set("Cache-Control",e),t.set("Access-Control-Allow-Origin","*"),t.set("Cross-Origin-Resource-Policy","cross-origin"),t}function Ht(s,e){let t=J.resolve(e,s),r=J.normalize(e);if(!J.normalize(t).startsWith(r))throw new Error("Path traversal detected - access denied");return t}async function ot(s){let e=await import("net");return new Promise(t=>{let r=e.createServer();r.listen(s,()=>{let n=r.address(),i=typeof n=="object"&&n?n.port:s;r.close(()=>t(i))}),r.on("error",()=>{t(ot(s+1))})})}import Hr from"open";async function zt(s){await Hr(s)}import Gr from"chokidar";function at(s){let{bulbPath:e,emitter:t}=s,r=Gr.watch(e,{persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});return r.on("change",()=>{t.emit("reload")}),()=>r.close()}import*as D from"fs/promises";import*as H from"path";import*as te from"path";var qr=te.join(_e,"pkg"),zr=te.join(_e,"files"),Kr=te.join(_e,"negative.json"),je=class{pkgMem=new Map;fileMem=new Map;negativeCache=new L(new X(Kr));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await v();let t=await W(Kt(e));return this.pkgMem.set(e,t),t}async setCachedDts(e,t,r){let n={content:t,url:r};this.pkgMem.set(e,n),await Fe(async()=>{await v(),await P(Kt(e),JSON.stringify(n))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await v();let t=await Ce(Yt(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await Fe(async()=>{await v(),await P(Yt(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await Fe(async()=>{await v(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return Fe(()=>this.negativeCache.clearNegative(e))}};async function Fe(s){try{await s()}catch{}}function Kt(s){return te.join(qr,k(s)+".json")}function Yt(s){return te.join(zr,k(s)+".txt")}var ct;function Yr(){return ct||(ct=Ye({cache:new je,cdnClient:Ut,packageService:Me,versionResolver:$t})),ct}var Xt="file:///node_modules/";async function Qt(s){let e=Ie(s.emitKey,"typecheck");await v(),await D.rm(e,{recursive:!0,force:!0}),await D.mkdir(e,{recursive:!0});let t=en(s.jsxImportSource,s.dependencies),r=await Yr().resolve(s.code,s.dependencies,t),n=new Set;for(let a of r)for(let c of a.files){let d=lt(c.path);if(!d||n.has(d))continue;n.add(d);let u=H.join(e,"node_modules",d);await D.mkdir(H.dirname(u),{recursive:!0}),await D.writeFile(u,c.content,"utf8")}let i={};for(let a of r)for(let c of a.shims){let d=lt(c.path);d&&(i[c.module]=[`./node_modules/${d}`])}for(let a of r){let c=lt(a.mainPath);c&&(i[a.pkg]=[`./node_modules/${c}`])}let o=Xr(s.jsxImportSource,i);return await D.writeFile(H.join(e,"tsconfig.json"),JSON.stringify(o,null,2)+`
371
- `,"utf8"),await D.writeFile(H.join(e,"code.tsx"),s.code,"utf8"),await D.writeFile(H.join(e,"tb.d.ts"),Ge,"utf8"),{dir:e}}function Xr(s,e){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"bundler",lib:Qr([...Je,...He]),jsx:"react-jsx",jsxImportSource:s??"react",strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0,baseUrl:".",paths:e},include:["code.tsx","tb.d.ts"]}}function Qr(s){return s.filter(e=>!e.since).map(e=>Zr(e.name))}function Zr(s){return s.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 en(s,e){let t=s??("react"in e?"react":void 0);return t?[`${t}/jsx-runtime`,`${t}/jsx-dev-runtime`]:[]}function lt(s){if(!s.startsWith(Xt))return;let e=s.slice(Xt.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}import*as R from"fs/promises";import*as G from"path";import{existsSync as an}from"fs";import*as Ne from"fs/promises";import*as dt from"path";import{existsSync as Zt}from"fs";import{execFile as tn}from"child_process";import{promisify as rn}from"util";var nn=rn(tn);async function $e(s,e){let t=s.filter(n=>!sn(n,e));if(t.length===0)return;await Ne.mkdir(e,{recursive:!0});let r=dt.join(e,"package.json");Zt(r)||await Ne.writeFile(r,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${t.join(", ")}`),await nn("npm",["install","--no-audit","--no-fund",...t],{cwd:e,shell:!0})}function sn(s,e){return Zt(dt.join(e,"node_modules",on(s)))}function on(s){if(s.startsWith("@")){let t=s.indexOf("/");if(t<0)return s;let r=s.indexOf("@",t+1);return r<0?s:s.slice(0,r)}let e=s.indexOf("@");return e<0?s:s.slice(0,e)}var cn="^22";async function er(s){let e=Ie(s.emitKey,"typecheck-server");await v(),await R.rm(e,{recursive:!0,force:!0}),await R.mkdir(e,{recursive:!0});let t=G.join(s.bulbDir,".typebulb");await $e([`@types/node@${cn}`],t);let r=G.join(t,"node_modules"),n=G.join(e,"node_modules");return await dn(r,n),await R.writeFile(G.join(e,"server.ts"),s.server,"utf8"),await R.writeFile(G.join(e,"tb.d.ts"),qe,"utf8"),await R.writeFile(G.join(e,"tsconfig.json"),JSON.stringify(ln(),null,2)+`
372
- `,"utf8"),{dir:e}}function ln(){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"node",lib:["ES2023"],types:["node"],strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0},include:["server.ts","tb.d.ts"]}}async function dn(s,e){if(!an(s)){await R.mkdir(e,{recursive:!0});return}await R.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await R.symlink(s,e,t)}var Io=hn(mn),gn="0.5.1";function yn(s){let e={subcommand:"run",file:"",port:3e3,watch:!0,open:!0,server:!1,help:!1,version:!1};s[0]==="check"&&(e.subcommand="check",s=s.slice(1));for(let t=0;t<s.length;t++){let r=s[t];if(r==="--help"||r==="-h")e.help=!0;else if(r==="--version"||r==="-V")e.version=!0;else if(r==="--no-watch")e.watch=!1;else if(r==="--no-open")e.open=!1;else if(r==="--server")e.server=!0;else if(r==="--port"||r==="-p"){let n=s[++t],i=parseInt(n,10);isNaN(i)&&(console.error(`Invalid port: ${n}`),process.exit(1)),e.port=i}else r.startsWith("-")||(e.file=r)}return e}function wn(){console.log(`
378
+ `);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function ot(s){let t=s.split(/\r?\n/).filter(n=>n.startsWith("data:"));if(!t.length)return null;let r=t.map(n=>n.replace(/^data:\s?/,"")).join(`
379
+ `).trim();if(!r)return null;if(r==="[DONE]")return"done";try{return JSON.parse(r)}catch{return null}}async function zt(s,e,t){let r=new TextDecoder,n="",o=!1,i=t?new Promise((a,l)=>{t.aborted&&l(new Error("Aborted")),t.addEventListener("abort",()=>l(new Error("Aborted")),{once:!0})}):null;for(;;){let a=i?await Promise.race([s.read(),i]):await s.read(),{done:l,value:d}=a;if(l){if(n.trim()){let m=ot(n);m!==null&&m!=="done"&&e(m)}break}o=!0,n+=r.decode(d,{stream:!0});let{pos:p,len:f}=Gt(n);for(;p!==-1;){let m=n.slice(0,p);n=n.slice(p+f);let y=ot(m);if(y==="done"){n="";break}y!==null&&e(y),{pos:p,len:f}=Gt(n)}}return{receivedAnyData:o}}async function it(s,e){let t=e??(s.headers.get("X-Provider-Protocol")||"openai"),r=G(t);if(!s.body)throw new Error("Response body is missing");let n=s.body.getReader(),o="";return await zt(n,i=>{let a=r.parseStreamChunk(i);a?.text&&(o+=a.text)}),o}import*as at from"fs/promises";import*as Se from"path";var Ne=class{async get(e){let t=_(e),r=Se.join(ve,t+".bin"),n=Se.join(ve,t+".json");try{let[o,i]=await Promise.all([at.readFile(r),at.readFile(n,"utf8")]),a=JSON.parse(i);return{body:o,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await b();let r=_(e),n=Se.join(ve,r+".bin"),o=Se.join(ve,r+".json"),i={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([k(n,t.body),k(o,JSON.stringify(i))])}};async function Yt(s){let{getHtml:e,basePath:t,port:r,reloadEmitter:n,getServerExports:o,localOverride:i}=s,a=new Kr;a.use("*",async(c,u)=>{await u(),c.res.headers.set("Cross-Origin-Opener-Policy","same-origin"),c.res.headers.set("Cross-Origin-Embedder-Policy","credentialless")}),a.get("/",c=>c.html(e())),a.post("/__fs/read",async c=>{try{let{path:u}=await c.req.json(),g=lt(u,t),v=await z.readFile(g);return new Response(new Uint8Array(v),{headers:{"Content-Type":"application/octet-stream"}})}catch(u){let g=u instanceof Error?u.message:"Unknown error";return c.json({error:g},400)}}),a.post("/__fs/write",async c=>{try{let u=c.req.query("path");if(!u)return c.json({error:"Missing path"},400);let g=lt(u,t);return await z.mkdir(M.dirname(g),{recursive:!0}),await z.writeFile(g,Buffer.from(await c.req.arrayBuffer())),c.json({success:!0})}catch(u){let g=u instanceof Error?u.message:"Unknown error";return c.json({error:g},400)}});let l={log:console.log};a.post("/__api/:name",async c=>{try{let u=o?.(),g=c.req.param("name"),v=u?.[g]??l[g];if(!v||typeof v!="function")return c.json({error:`API function '${g}' not found`},404);let{args:w}=await c.req.json(),I=await v(...w||[]);return c.json({result:I})}catch(u){let g=u instanceof Error?u.message:"Unknown error";return c.json({error:g},500)}}),a.post("/__ai",async c=>{try{let{messages:u,system:g,reasoning:v,provider:w,model:I,webSearch:W}=await c.req.json();if(!u||!Array.isArray(u)||u.length===0)return c.json({message:"messages array is required",code:"unknown",retryable:!1},400);let $=Qr(w,I);if(typeof $=="string")return c.json({message:$,code:"unknown",retryable:!1},400);let Te=[...g?[{role:"system",content:g}]:[],...u.map(J=>({role:J.role,content:J.content}))],N=await nt($,{model:$.model,messages:Te,stream:!0,reasoning:v??0,webSearch:W??!0});if(!N.ok){let J=await st(N,$.protocol);return c.json(J,N.status)}let Y=await it(N,$.protocol);return Y||console.warn("[tb.ai] Empty response from provider"),c.json({text:Y})}catch(u){if(u instanceof T)return c.json({message:u.message,code:u.code,retryable:u.retryable},500);let g=u instanceof Error?u.message:"Unknown error";return c.json({message:g,code:"unknown",retryable:!1},500)}}),a.get("/__models",async c=>{try{let u=await tn();return c.json(u)}catch{return c.json([],200)}});let d=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"],p=new Ne;if(a.get("/proxy/*",async c=>{let u=new URL(c.req.url),v=(u.pathname+u.search).slice(7),w=v.lastIndexOf("https://");return w===-1?c.text("Invalid proxy URL",400):f(c,v.slice(w))}),i){let c=`/local/${i.name}/`;a.get("/local/*",async u=>{let{pathname:g}=new URL(u.req.url);if(!g.startsWith(c))return u.text("Not Found",404);let v=decodeURIComponent(g.slice(c.length));try{let w=lt(v,i.serveDir),I=await z.readFile(w);return new Response(I,{headers:{"Content-Type":rn(w)}})}catch{return u.text("Not Found",404)}})}async function f(c,u){let g;try{g=new URL(u)}catch{return c.text("Invalid URL",400)}if(g.protocol!=="https:")return c.text("HTTPS only",400);if(!d.includes(g.hostname))return c.text("Host not allowed",403);let v=await p.get(u);if(v)return new Response(v.body,{status:200,headers:ct(v.contentType,v.cacheControl)});try{let w=await fetch(u,{headers:{Accept:c.req.header("Accept")||"*/*"},redirect:"follow"});if(!w.ok)return c.text(`Upstream ${w.status}`,w.status);let I=w.headers.get("Content-Type")||void 0,W=w.headers.get("Cache-Control")||void 0;if(w.body){let[$,Te]=w.body.tee();return(async()=>{try{let N=await new Response(Te).arrayBuffer();await p.set(u,{body:Buffer.from(N),contentType:I,cacheControl:W})}catch{}})(),new Response($,{status:w.status,headers:ct(I,W)})}return new Response(null,{status:w.status,headers:ct(I,W)})}catch(w){return c.text(`Proxy fetch failed: ${w instanceof Error?w.message:w}`,502)}}n&&a.get("/__reload",c=>Xr(c,async u=>{let g=()=>{u.writeSSE({event:"reload",data:""})};for(n.on("reload",g),u.onAbort(()=>{n.removeListener("reload",g)});;)await u.sleep(3e4)}));let m=/^\/(v\d+\/|stable\/|node\/|gh\/|@[^/]+\/[^@/]+@|[^@/]+@)/;a.notFound(async c=>{if(c.req.method!=="GET")return c.text("Not Found",404);let u=new URL(c.req.url);return m.test(u.pathname)?f(c,"https://esm.sh"+u.pathname+u.search):c.text("Not Found",404)});let y=Yr({fetch:a.fetch,port:r});return{port:r,close:()=>y.close()}}var Xt={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function Qr(s,e){let t=s??process.env.TB_AI_PROVIDER,r=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(!r)return"No model specified. Set TB_AI_MODEL in your .env file or pass model in the tb.ai() call.";let n;try{n=G(t)}catch{return`Unknown provider '${t}'.`}let o=Xt[t],i=process.env[o];return i?{apiKey:i,baseUrl:n.defaultBaseUrl,protocol:t,model:r,isFreeModel:!1}:`No API key for '${t}'. Set ${o} in your .env file.`}var Zr="https://api.typebulb.com/api/models",en=1440*60*1e3,ne=null;async function tn(){if(!ne||Date.now()-ne.fetchedAt>en){let s=await fetch(Zr);if(!s.ok)return ne?Kt(ne.models):[];ne={models:await s.json(),fetchedAt:Date.now()}}return Kt(ne.models)}function Kt(s){let e=new Set(Object.entries(Xt).filter(([,t])=>!!process.env[t]).map(([t])=>t));return s.filter(t=>e.has(t.provider))}function ct(s,e){let t=new Headers;return s&&t.set("Content-Type",s),e&&t.set("Cache-Control",e),t.set("Access-Control-Allow-Origin","*"),t.set("Cross-Origin-Resource-Policy","cross-origin"),t}function rn(s){switch(M.extname(s).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(s,e){let t=M.resolve(e,s),r=M.normalize(e),n=M.normalize(t);if(n!==r&&!n.startsWith(r+M.sep))throw new Error("Path traversal detected - access denied");return t}async function dt(s){let e=await import("net");return new Promise(t=>{let r=e.createServer();r.listen(s,()=>{let n=r.address(),o=typeof n=="object"&&n?n.port:s;r.close(()=>t(o))}),r.on("error",()=>{t(dt(s+1))})})}import nn from"open";async function Qt(s){await nn(s)}import Zt from"chokidar";var er={persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}};function pt(s){let{bulbPath:e,emitter:t}=s,r=Zt.watch(e,er);return r.on("change",()=>{t.emit("reload")}),()=>r.close()}function tr(s){let{dir:e,onChange:t,debounceMs:r=150}=s,n,o=Zt.watch(e,er);return o.on("all",()=>{n&&clearTimeout(n),n=setTimeout(t,r)}),()=>{n&&clearTimeout(n),o.close()}}import*as S from"fs/promises";import*as R from"path";import*as se from"path";var sn=se.join(Ae,"pkg"),on=se.join(Ae,"files"),an=se.join(Ae,"negative.json"),Ue=class{pkgMem=new Map;fileMem=new Map;negativeCache=new H(new te(an));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await b();let t=await q(rr(e));return this.pkgMem.set(e,t),t}async setCachedDts(e,t,r){let n={content:t,url:r};this.pkgMem.set(e,n),await Le(async()=>{await b(),await k(rr(e),JSON.stringify(n))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await b();let t=await Oe(nr(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await Le(async()=>{await b(),await k(nr(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await Le(async()=>{await b(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return Le(()=>this.negativeCache.clearNegative(e))}};async function Le(s){try{await s()}catch{}}function rr(s){return se.join(sn,_(s)+".json")}function nr(s){return se.join(on,_(s)+".txt")}var ut;function cn(){return ut||(ut=Ze({cache:new Ue,cdnClient:Vt,packageService:je,versionResolver:Jt})),ut}var sr="file:///node_modules/";async function or(s){let e=Me(s.emitKey,"typecheck");await b(),await S.rm(e,{recursive:!0,force:!0}),await S.mkdir(e,{recursive:!0});let t=un(s.jsxImportSource,s.dependencies),r=await cn().resolve(s.code,s.dependencies,t),n=s.local?.name,o=n?r.filter(d=>d.pkg!==n):r,i=new Set;for(let d of o)for(let p of d.files){let f=ft(p.path);if(!f||i.has(f))continue;i.add(f);let m=R.join(e,"node_modules",f);await S.mkdir(R.dirname(m),{recursive:!0}),await S.writeFile(m,p.content,"utf8")}let a={};for(let d of o)for(let p of d.shims){let f=ft(p.path);f&&(a[p.module]=[`./node_modules/${f}`])}for(let d of o){let p=ft(d.mainPath);p&&(a[d.pkg]=[`./node_modules/${p}`])}if(s.local){delete a[s.local.name];let d=await fn(s.local,e);d?a[s.local.name]=[`./node_modules/${s.local.name}/${d}`]:console.warn(` local: '${s.local.name}' ships no type defs; check cannot type against it.`)}let l=ln(s.jsxImportSource,a);return await S.writeFile(R.join(e,"tsconfig.json"),JSON.stringify(l,null,2)+`
380
+ `,"utf8"),await S.writeFile(R.join(e,"code.tsx"),s.code,"utf8"),await S.writeFile(R.join(e,"tb.d.ts"),Ke,"utf8"),{dir:e}}function ln(s,e){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"bundler",lib:dn([...Ge,...ze]),jsx:"react-jsx",jsxImportSource:s??"react",strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0,baseUrl:".",paths:e},include:["code.tsx","tb.d.ts"]}}function dn(s){return s.filter(e=>!e.since).map(e=>pn(e.name))}function pn(s){return s.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 un(s,e){let t=s??("react"in e?"react":void 0);return t?[`${t}/jsx-runtime`,`${t}/jsx-dev-runtime`]:[]}function ft(s){if(!s.startsWith(sr))return;let e=s.slice(sr.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}async function fn(s,e){if(!s.typesAbs)return;let t=R.dirname(s.typesAbs),r=R.join(e,"node_modules",s.name);for(let n of await mn(t)){let o=R.join(r,R.relative(t,n));await S.mkdir(R.dirname(o),{recursive:!0}),await S.copyFile(n,o)}return R.basename(s.typesAbs)}async function mn(s){let e=[];async function t(r){let n=await S.readdir(r,{withFileTypes:!0});for(let o of n){let i=R.join(r,o.name);o.isDirectory()?await t(i):/\.d\.ts(\.map)?$/.test(o.name)&&e.push(i)}}return await t(s),e}import*as C from"fs/promises";import*as K from"path";import{existsSync as bn}from"fs";import*as Be from"fs/promises";import*as mt from"path";import{existsSync as ir}from"fs";import{execFile as hn}from"child_process";import{promisify as gn}from"util";var yn=gn(hn);async function We(s,e){let t=s.filter(n=>!wn(n,e));if(t.length===0)return;await Be.mkdir(e,{recursive:!0});let r=mt.join(e,"package.json");ir(r)||await Be.writeFile(r,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${t.join(", ")}`),await yn("npm",["install","--no-audit","--no-fund",...t],{cwd:e,shell:!0})}function wn(s,e){return ir(mt.join(e,"node_modules",vn(s)))}function vn(s){if(s.startsWith("@")){let t=s.indexOf("/");if(t<0)return s;let r=s.indexOf("@",t+1);return r<0?s:s.slice(0,r)}let e=s.indexOf("@");return e<0?s:s.slice(0,e)}var xn="^22";async function ar(s){let e=Me(s.emitKey,"typecheck-server");await b(),await C.rm(e,{recursive:!0,force:!0}),await C.mkdir(e,{recursive:!0});let t=K.join(s.bulbDir,".typebulb");await We([`@types/node@${xn}`],t);let r=K.join(t,"node_modules"),n=K.join(e,"node_modules");return await Rn(r,n),await C.writeFile(K.join(e,"server.ts"),s.server,"utf8"),await C.writeFile(K.join(e,"tb.d.ts"),Ye,"utf8"),await C.writeFile(K.join(e,"tsconfig.json"),JSON.stringify(Pn(),null,2)+`
381
+ `,"utf8"),{dir:e}}function Pn(){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"node",lib:["ES2023"],types:["node"],strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0},include:["server.ts","tb.d.ts"]}}async function Rn(s,e){if(!bn(s)){await C.mkdir(e,{recursive:!0});return}await C.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await C.symlink(s,e,t)}import*as gt from"fs/promises";import{existsSync as Ee}from"fs";import*as x from"path";import{resolve as cr}from"resolve.exports";import{init as Sn,parse as En}from"es-module-lexer";var ht=["browser","import","default"];function lr(s){let e=s.indexOf("=");if(e===-1)throw new Error(`--replace must be <name>=<path> (got '${s}')`);let t=s.slice(0,e).trim(),r=s.slice(e+1).trim();if(!t)throw new Error(`--replace missing package name (got '${s}')`);if(!r)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:x.resolve(r)}}async function dr(s){let{name:e,dir:t}=s;if(!Ee(t))throw new Error(`--replace path for '${e}' does not exist: ${t}`);let r=x.join(t,"package.json"),n;try{n=JSON.parse(await gt.readFile(r,"utf8"))}catch{throw new Error(`--replace package '${e}' has no readable package.json at ${r}`)}let o=kn(n,e),i=x.resolve(t,o);if(!Ee(i))throw new Error(`--replace package '${e}' entry not found on disk: ${i} \u2014 did you build it (e.g. \`pnpm run build\`)?`);let a=x.dirname(i),l=`/local/${e}/${x.basename(i)}`,d=Tn(n,t);return await Cn(e,i,a),{name:e,dir:t,entryAbs:i,serveDir:a,entryUrl:l,typesAbs:d}}function kn(s,e){if(s.exports!==void 0){let r;try{r=cr(s,".",{browser:!0,conditions:ht})}catch(o){throw new Error(`--replace package '${e}' "exports" does not resolve a browser entry (conditions: ${ht.join(", ")}): ${o instanceof Error?o.message:o}`)}let n=pr(r);if(!n)throw new Error(`--replace package '${e}' "exports" did not resolve "." to a single file (conditions: ${ht.join(", ")}); too complex to override.`);return n}let t=s.module??s.main;if(!t)throw new Error(`--replace package '${e}' has no "exports", "module", or "main" entry to resolve.`);return t}function Tn(s,e){if(s.exports!==void 0)try{let r=cr(s,".",{conditions:["types"]}),n=pr(r);if(n){let o=x.resolve(e,n);if(Ee(o))return o}}catch{}let t=s.types??s.typings;if(t){let r=x.resolve(e,t);if(Ee(r))return r}}function pr(s){if(typeof s=="string")return s;if(Array.isArray(s))return s.find(e=>typeof e=="string")}async function Cn(s,e,t){await Sn;let r=x.normalize(t),n=new Set,o=[e];for(;o.length;){let i=o.shift();if(n.has(i))continue;n.add(i);let a;try{a=await gt.readFile(i,"utf8")}catch{continue}let l,d;try{[l,,,d]=En(a,i)}catch{continue}if(i===e&&!d)throw new Error(`override package '${s}' 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 l){if(p.d===-2)continue;let f=p.n;if(f&&!f.startsWith("node:")){if(f.startsWith("./")||f.startsWith("../")||f.startsWith("/")){let m=Dn(i,f,r);m&&!n.has(m)&&o.push(m);continue}throw new Error(`override package must ship self-contained (bundle its dependencies); ${s} externalizes '${f}'`)}}}}function Dn(s,e,t){let r=e.replace(/[?#].*$/,""),n=x.resolve(x.dirname(s),r),o=[n,n+".js",n+".mjs",x.join(n,"index.js"),x.join(n,"index.mjs")];for(let i of o)if(x.normalize(i).startsWith(t)&&Ee(i))return i}var Zi=Mn(On),$n="0.6.1";function Fn(s){let e={subcommand:"run",file:"",port:3e3,watch:!0,open:!0,server:!1,help:!1,version:!1};s[0]==="check"&&(e.subcommand="check",s=s.slice(1));for(let t=0;t<s.length;t++){let r=s[t];if(r==="--help"||r==="-h")e.help=!0;else if(r==="--version"||r==="-V")e.version=!0;else if(r==="--no-watch")e.watch=!1;else if(r==="--no-open")e.open=!1;else if(r==="--server")e.server=!0;else if(r==="--port"||r==="-p"){let n=s[++t],o=parseInt(n,10);isNaN(o)&&(console.error(`Invalid port: ${n}`),process.exit(1)),e.port=o}else if(r==="--replace"||r.startsWith("--replace=")){let n=r.startsWith("--replace=")?r.slice(10):s[++t]??"";try{let o=lr(n);if(e.local)throw new Error(`--replace can only be used once (got '${e.local.name}' and '${o.name}')`);e.local=o}catch(o){console.error(o instanceof Error?o.message:String(o)),process.exit(1)}}else r.startsWith("-")||(e.file=r)}return e}function jn(){console.log(`
373
382
  typebulb - Local bulb runner for Typebulb
374
383
 
375
384
  Usage:
@@ -381,13 +390,19 @@ Options:
381
390
  -p, --port <port> Use a specific port (default: 3000)
382
391
  --no-open Don't auto-open browser
383
392
  --server Run server.ts only, no web server
393
+ --replace <name>=<path> Replace a declared dependency with a local built
394
+ package folder instead of a CDN (dev only).
395
+ Applies to both run and check. Watched for
396
+ rebuilds under --watch; --no-watch freezes it.
397
+ e.g. --replace tensorgrad=../tensorgrad
384
398
  -V, --version Show version number
385
399
  -h, --help Show this help message
386
400
 
387
401
  Filesystem API:
388
402
  Bulbs can read and write local files via tb.fs:
389
- await tb.fs.read('file.txt')
390
- await tb.fs.write('output.html', content)
403
+ await tb.fs.read('file.txt') // UTF-8 text (throws on non-UTF-8)
404
+ await tb.fs.readBytes('image.png') // raw bytes (Uint8Array)
405
+ await tb.fs.write('output.html', content) // text or bytes
391
406
 
392
407
  Server API:
393
408
  Add a **server.ts** section to run Node.js code server-side.
@@ -416,11 +431,12 @@ Examples:
416
431
  typebulb my-editor.bulb.md
417
432
  typebulb --no-watch --port 8080 my-editor.bulb.md
418
433
  typebulb .
419
- `)}async function vn(s){let t=(await E.readdir(s)).find(r=>r.endsWith(".bulb.md"));return t?b.join(s,t):null}function rr(){ut([".env",".env.local"],process.cwd(),!0)}function ut(s,e,t=!1){for(let r of s){let n=b.resolve(e,r);try{let i=pn(n,"utf-8");for(let o of i.split(`
420
- `)){let a=o.trim();if(!a||a.startsWith("#"))continue;let c=a.indexOf("=");if(c===-1)continue;let d=a.slice(0,c).trim(),u=a.slice(c+1).trim();(u.startsWith('"')&&u.endsWith('"')||u.startsWith("'")&&u.endsWith("'"))&&(u=u.slice(1,-1)),process.env[d]??=u}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}function bn(s){let e=new Set,t=/\bimport\s+(?:[\s\S]*?\s+from\s+)?['"]([^./][^'"]*)['"]/g,r;for(;r=t.exec(s);){let n=r[1];if(n.startsWith("node:"))continue;let i=n.startsWith("@")?n.split("/").slice(0,2).join("/"):n.split("/")[0];e.add(i)}return[...e]}async function nr(s,e){let t=Be(s,{serverOnly:!0});if(t.error)throw new Error(`Server compilation error: ${t.error}`);let r=b.join(e,".typebulb");await E.mkdir(r,{recursive:!0});let n=bn(t.code);n.length>0&&await $e(n,r);let i=b.join(r,"server.mjs");return await E.writeFile(i,t.code,"utf-8"),await import(`${un(i).href}?t=${Date.now()}`)}async function Ue(s){let e=await E.readFile(s,"utf-8"),t=ft(e);if(!t)throw new Error("Invalid .bulb.md file format");let r=ht(t);return{bulb:r,config:yt(r.config)}}async function tr(s,e){let{bulb:t,config:r}=await Ue(s),n=gt(t.data),i=Be(t.code,{jsxImportSource:r.jsxImportSource});i.error&&console.error("Compilation error:",i.error);let{importMap:o}=await Me.buildImportMap(i.code,r.dependencies??{}),a=Lt({name:t.name,code:i.code,css:t.css,html:t.html,data:n,insight:t.insight,importMap:o,watch:e}),c=b.dirname(s);r.env?.length&&ut(r.env,c);let d=null;return t.server&&(d=await nr(t.server,c)),{html:a,bulb:t,serverExports:d}}async function xn(s){let{bulb:e,config:t}=await Ue(s);!e.code&&!e.server&&(console.error("Bulb has neither **code.tsx** nor **server.ts**; nothing to check."),process.exit(1));let r=[];if(e.code){let{dir:i}=await Qt({code:e.code,dependencies:t.dependencies??{},jsxImportSource:t.jsxImportSource,emitKey:s});r.push({role:"client",dir:i})}if(e.server){let{dir:i}=await er({server:e.server,bulbDir:b.dirname(s),emitKey:s});r.push({role:"server",dir:i})}let n=!1;for(let{role:i,dir:o}of r){let{stdout:a,exitCode:c}=await Pn(o);for(let d of a.split(/\r?\n/))d.trim()&&console.log(`${i} ${d}`);c!==0&&(n=!0)}n&&process.exit(1)}function Pn(s){return new Promise(e=>{let t=fn("npx",["tsc","--noEmit"],{cwd:s,shell:!0}),r="";t.stdout?.on("data",n=>{r+=n.toString()}),t.stderr?.on("data",n=>{r+=n.toString()}),t.on("close",n=>e({stdout:r,exitCode:n??1}))})}async function Sn(s,e){rr();let t=async()=>{let{bulb:r,config:n}=await Ue(s),i=b.dirname(s);n.env?.length&&ut(n.env,i),await nr(r.server,i)};if(console.log(`Running ${b.basename(s)}...`),await t(),e){console.log(`Watching for changes...
421
- `);let r=new pt;r.on("reload",async()=>{try{console.log("Re-running..."),await t()}catch(n){console.error("Error:",n)}}),at({bulbPath:s,emitter:r})}}async function Rn(){let s=yn(process.argv.slice(2));s.version&&(console.log(`typebulb ${gn}`),process.exit(0)),s.help&&(wn(),process.exit(0));let e;if(!s.file||s.file==="."){let h=await vn(process.cwd());h||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=h}else e=b.resolve(s.file);try{await E.access(e)}catch{console.error(`File not found: ${e}`),process.exit(1)}if(e.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1)),s.subcommand==="check"){await xn(e);return}try{let{bulb:h}=await Ue(e);if(h.server&&(!h.code||s.server)){await Sn(e,s.watch);return}}catch{}let t=process.cwd(),r=s.watch?new pt:void 0;rr(),console.log(`Loading ${b.basename(e)}...`);let{html:n,bulb:i,serverExports:o}=await tr(e,s.watch),a=await ot(s.port),c=await Gt({getHtml:()=>n,basePath:t,port:a,reloadEmitter:r,getServerExports:()=>o}),d=`http://localhost:${a}`;console.log(`
422
- ${i.name}`),console.log(` ${d}
434
+ `)}async function Nn(s){let t=(await D.readdir(s)).find(r=>r.endsWith(".bulb.md"));return t?P.join(s,t):null}function fr(){wt([".env",".env.local"],process.cwd(),!0)}function wt(s,e,t=!1){for(let r of s){let n=P.resolve(e,r);try{let o=In(n,"utf-8");for(let i of o.split(`
435
+ `)){let a=i.trim();if(!a||a.startsWith("#"))continue;let l=a.indexOf("=");if(l===-1)continue;let d=a.slice(0,l).trim(),p=a.slice(l+1).trim();(p.startsWith('"')&&p.endsWith('"')||p.startsWith("'")&&p.endsWith("'"))&&(p=p.slice(1,-1)),process.env[d]??=p}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}function Ln(s){let e=new Set,t=/\bimport\s+(?:[\s\S]*?\s+from\s+)?['"]([^./][^'"]*)['"]/g,r;for(;r=t.exec(s);){let n=r[1];if(n.startsWith("node:"))continue;let o=n.startsWith("@")?n.split("/").slice(0,2).join("/"):n.split("/")[0];e.add(o)}return[...e]}async function mr(s,e){let t=Je(s,{serverOnly:!0});if(t.error)throw new Error(`Server compilation error: ${t.error}`);let r=P.join(e,".typebulb");await D.mkdir(r,{recursive:!0});let n=Ln(t.code);n.length>0&&await We(n,r);let o=P.join(r,"server.mjs");return await D.writeFile(o,t.code,"utf-8"),await import(`${_n(o).href}?t=${Date.now()}`)}async function ke(s){let e=await D.readFile(s,"utf-8"),t=vt(e);if(!t)throw new Error("Invalid .bulb.md file format");let r=bt(t);return{bulb:r,config:Pt(r.config)}}async function ur(s,e,t){let{bulb:r,config:n}=await ke(s),o=xt(r.data),i=Je(r.code,{jsxImportSource:n.jsxImportSource});i.error&&console.error("Compilation error:",i.error);let{importMap:a}=await je.buildImportMap(i.code,n.dependencies??{});t&&(a.imports[t.name]=t.entryUrl);let l=qt({name:r.name,code:i.code,css:r.css,html:r.html,data:o,insight:r.insight,importMap:a,watch:e}),d=P.dirname(s);n.env?.length&&wt(n.env,d);let p=null;return r.server&&(p=await mr(r.server,d)),{html:l,bulb:r,serverExports:p}}async function Un(s,e){let{bulb:t,config:r}=await ke(s);!t.code&&!t.server&&(console.error("Bulb has neither **code.tsx** nor **server.ts**; nothing to check."),process.exit(1));let n=[];if(t.code){let{dir:i}=await or({code:t.code,dependencies:r.dependencies??{},jsxImportSource:r.jsxImportSource,emitKey:s,local:e});n.push({role:"client",dir:i})}if(t.server){let{dir:i}=await ar({server:t.server,bulbDir:P.dirname(s),emitKey:s});n.push({role:"server",dir:i})}let o=!1;for(let{role:i,dir:a}of n){let{stdout:l,exitCode:d}=await Bn(a);for(let p of l.split(/\r?\n/))p.trim()&&console.log(`${i} ${p}`);d!==0&&(o=!0)}o&&process.exit(1)}function Bn(s){return new Promise(e=>{let t=An("npx",["tsc","--noEmit"],{cwd:s,shell:!0}),r="";t.stdout?.on("data",n=>{r+=n.toString()}),t.stderr?.on("data",n=>{r+=n.toString()}),t.on("close",n=>e({stdout:r,exitCode:n??1}))})}async function Wn(s,e){fr();let t=async()=>{let{bulb:r,config:n}=await ke(s),o=P.dirname(s);n.env?.length&&wt(n.env,o),await mr(r.server,o)};if(console.log(`Running ${P.basename(s)}...`),await t(),e){console.log(`Watching for changes...
436
+ `);let r=new yt;r.on("reload",async()=>{try{console.log("Re-running..."),await t()}catch(n){console.error("Error:",n)}}),pt({bulbPath:s,emitter:r})}}async function Jn(){let s=Fn(process.argv.slice(2));s.version&&(console.log(`typebulb ${$n}`),process.exit(0)),s.help&&(jn(),process.exit(0));let e;if(!s.file||s.file==="."){let c=await Nn(process.cwd());c||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=c}else e=P.resolve(s.file);try{await D.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;if(s.local){let c;try{c=await ke(e)}catch{}c&&!(s.local.name in(c.config.dependencies??{}))&&(console.error(`--replace: '${s.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),c&&(!c.bulb.code||s.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{t=await dr(s.local)}catch(u){console.error(u instanceof Error?u.message:String(u)),process.exit(1)}console.log(`replace: ${t.name} \u2192 ${P.relative(process.cwd(),t.dir)||"."}`)}if(s.subcommand==="check"){await Un(e,t);return}try{let{bulb:c}=await ke(e);if(c.server&&(!c.code||s.server)){await Wn(e,s.watch);return}}catch{}let r=process.cwd(),n=s.watch?new yt:void 0;fr(),console.log(`Loading ${P.basename(e)}...`);let{html:o,bulb:i,serverExports:a}=await ur(e,s.watch,t),l=await dt(s.port),d=await Yt({getHtml:()=>o,basePath:r,port:l,reloadEmitter:n,getServerExports:()=>a,localOverride:t?{name:t.name,serveDir:t.serveDir}:void 0}),p=`http://localhost:${l}`;console.log(`
437
+ ${i.name}`),console.log(` ${p}
423
438
  `),s.watch&&console.log(` Watching for changes...
424
- `);let u;if(s.watch&&r){let h=new pt;h.on("reload",async()=>{try{console.log("Recompiling...");let p=await tr(e,!0);n=p.html,o=p.serverExports,r.emit("reload"),console.log(`Done. Browser reloading...
425
- `)}catch(p){console.error("Compile error:",p)}}),u=at({bulbPath:e,emitter:h})}s.open&&await zt(d);let f=async()=>{console.log(`
426
- Shutting down...`),c.close(),u?.();let h=b.join(b.dirname(e),".typebulb","server.mjs");await E.rm(h,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",f),process.on("SIGTERM",f)}Rn().catch(s=>{console.error("Error:",s.message),process.exit(1)});
439
+ `);let f,m;if(s.watch&&n){let c=new yt;if(c.on("reload",async()=>{try{console.log("Recompiling...");let u=await ur(e,!0,t);o=u.html,a=u.serverExports,n.emit("reload"),console.log(`Done. Browser reloading...
440
+ `)}catch(u){console.error("Compile error:",u)}}),f=pt({bulbPath:e,emitter:c}),t){let{name:u,serveDir:g}=t;m=tr({dir:g,onChange:()=>{console.log(`Local package '${u}' changed. Browser reloading...
441
+ `),n.emit("reload")}})}}s.open&&await Qt(p);let y=async()=>{console.log(`
442
+ Shutting down...`),d.close(),f?.(),m?.();let c=P.join(P.dirname(e),".typebulb","server.mjs");await D.rm(c,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",y),process.on("SIGTERM",y)}Jn().catch(s=>{console.error("Error:",s.message),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebulb",
3
- "version": "0.5.1",
3
+ "version": "0.6.1",
4
4
  "description": "Local bulb runner CLI for Typebulb",
5
5
  "license": "MIT",
6
6
  "engines": { "node": ">=18" },
@@ -13,6 +13,7 @@
13
13
  ],
14
14
  "scripts": {
15
15
  "typecheck": "tsc --build",
16
+ "test": "vitest run",
16
17
  "build": "tsc --build && node esbuild.config.mjs",
17
18
  "clean": "rimraf dist .tsbuild",
18
19
  "dev": "tsc --build && node dist/index.js",
@@ -38,6 +39,7 @@
38
39
  "esbuild": "^0.27.3",
39
40
  "rimraf": "^6.0.1",
40
41
  "typebulb-resolver": "workspace:*",
41
- "typebulb-dts": "workspace:*"
42
+ "typebulb-dts": "workspace:*",
43
+ "vitest": "^2.1.9"
42
44
  }
43
45
  }