typebulb 0.4.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -2
  2. package/dist/index.js +205 -32
  3. package/package.json +8 -3
package/README.md CHANGED
@@ -42,8 +42,8 @@ npm install -g typebulb
42
42
  ## Usage
43
43
 
44
44
  ```
45
- typebulb <file.bulb.md> Run a bulb
46
- typebulb . Find .bulb.md in current directory
45
+ typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
46
+ typebulb check [file.bulb.md] Type-check a bulb without running it
47
47
  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
@@ -58,9 +58,11 @@ typebulb --version Show version
58
58
  - **CLI logging** — `tb.server.log(...)` prints to the CLI's stdout
59
59
  - **Env files** — `.env` and `.env.local` auto-loaded from cwd
60
60
  - **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
+ - **Type-check without running** — `typebulb check <file>` runs `tsc --noEmit` against the bulb and exits non-zero on errors. Useful for AI editors / CI.
61
62
  - **Filesystem access** — `tb.fs.read()` and `tb.fs.write()` for local files
62
63
  - **Hot reload** — Recompiles on save and refreshes the browser (on by default; disable with `--no-watch`)
63
64
  - **Package resolution** — Client dependencies are automatically resolved by generating import maps (same resolver as typebulb.com). Server dependencies are automatically installed via npm.
65
+ - **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.
64
66
  - **AI calls** — `tb.ai()` for general-purpose AI (chatbots, agents, experiments). `tb.models()` lists available models. Set API keys in `.env` (see below).
65
67
 
66
68
  ## AI Setup
package/dist/index.js CHANGED
@@ -1,7 +1,178 @@
1
1
  #!/usr/bin/env node
2
- import*as w from"fs/promises";import{readFileSync as it,existsSync as Ie}from"fs";import*as y from"path";import{pathToFileURL as at}from"url";import{execFile as ct}from"child_process";import{promisify as lt}from"util";import{EventEmitter as ie}from"events";var Ce={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 W(n){try{let e=n.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 s=De(r);if(!s)return null;let o=new Map;for(;t<e.length;){let c=e[t]?.trim()?.match(/^\*\*(.+)\*\*$/);if(c){let d=c[1].trim();for(t++;t<e.length&&e[t]?.trim()==="";)t++;let f=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!f){t++;continue}let a=f[1];t++;let l=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${a}\\s*$`));)l.push(e[t]),t++;t++,o.set(d,l.join(`
4
- `))}else t++}return{frontmatter:s,files:o}}catch{return null}}function De(n){let e={};for(let t of n){let r=t.indexOf(":");if(r===-1)continue;let s=t.slice(0,r).trim(),o=t.slice(r+1).trim();switch(s){case"format":e.format=o;break;case"name":e.name=Be(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function Be(n){return n.startsWith('"')&&n.endsWith('"')?n.slice(1,-1).replace(/\\"/g,'"'):n.startsWith("'")&&n.endsWith("'")?n.slice(1,-1):n}function J(n){let e=t=>n.files.get(Ce[t].path)||"";return{name:n.frontmatter.name,code:e("code"),css:e("css"),html:e("html"),config:e("config"),notes:e("notes"),data:e("data"),infer:e("infer"),insight:e("insight"),server:e("server")}}function Ne(n){try{return JSON.parse(n),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(n)||/^---\s*$/m.test(n)||/^\w[\w\s]*:[ \t]/m.test(n))}function le(n){let e=n.trim();return e?Ne(e)?[e]:n.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function z(n){if(!n.trim())return{};try{return JSON.parse(n)}catch{return{}}}import{transform as pe}from"sucrase";function je(n,e){try{let{code:t}=pe(n,{transforms:["typescript","jsx"],jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:t}}catch(t){return{code:"",error:String(t)}}}function de(n,e={}){return je(n,e)}function ue(n){try{let{code:e}=pe(n,{transforms:["typescript"]});return{code:e}}catch(e){return{code:"",error:String(e)}}}var $="https://esm.sh",C="https://cdn.jsdelivr.net/npm/",K="https://data.jsdelivr.com/v1/package/npm/";function fe(n){let e=(n||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var g=class n{constructor(e,t,r){let s=typeof e=="string"?n.parse(e):e;this.name=s.name,this.version=k(t??s.version),this.subpath=k(r??s.subpath)}static parse(e){let t=fe(e||"");if(!t.length)return new n({name:""});if(t[0].startsWith("@")){let s=t[0],[o,i]=me(t[1]??""),c=k(t.slice(2).join("/"));return new n({name:`${s}/${o}`,version:i,subpath:c})}else{let[s,o]=me(t[0]),i=k(t.slice(1).join("/"));return new n({name:s,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),r=new URL($).host,s=new URL(C).host;if(t.host===r){let o=fe(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return n.parse(i)}if(t.host===s){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return n.parse(i)}return}catch{return}}static versionFromUrl(e){return n.fromUrl(e)?.version}format(){let e=this.version?`${this.name}@${this.version}`:this.name;return this.subpath?`${e}/${this.subpath}`:e}root(){return this.name}static rootOf(e){return n.parse(e).name}withVersion(e){return new n({name:this.name,version:k(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://")}},k=n=>n&&n.length?n:void 0,me=n=>{let e=n.indexOf("@");return e<0?[n,void 0]:[n.slice(0,e),k(n.slice(e+1))]};async function v(n){try{return await n()}catch{return}}var D=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=$,this.jsDelivrBase=C,this.jsDelivrMeta=K,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:s=!1,external:o}=t,i=new URLSearchParams({target:r});return s&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let r=this.buildEsmUrl(e,{target:t}),s=await v(()=>this.http.head(r));return s?.ok?s.url||r:void 0}async resolveExactVersion(e){let t=Date.now(),r=this.pinCache.get(e);if(r&&t-r.ts<this.pinMs)return r.value;let s=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:s,ts:t}),s}async tryResolveFromUrls(e){for(let t of e){let r=await v(()=>this.http.head(t)),s=this.parseVersionFromUrl(r?.url||t);if(s)return s}}async fetchVersionsIndex(e){if(await this.cache.isNegative(e))return;let t=await this.cache.getIndex(e);if(t&&Date.now()-t.updatedAt<this.versionsIndexMs)return{versions:t.versions,distTags:t.distTags};let r=await v(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let s=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,s),r}parseVersionFromUrl(e){let t=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:a,peerDependencies:l,peerDependenciesMeta:u}=r;return{name:e,version:t,dependencies:a,peerDependencies:l,peerDependenciesMeta:u}}let s=this.packageJson(new g(`${e}@${t}`)),o=await v(()=>this.http.getJson(s));if(!o)return;let i=a=>a&&Object.keys(a).length?a:void 0,c=i(o.dependencies),d=i(o.peerDependencies),f=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,c,d,f),{name:e,version:t,dependencies:c,peerDependencies:d,peerDependenciesMeta:f}}};var he=n=>n.startsWith("@types/"),B=n=>Object.keys(n?.peerDependencies||{}).filter(e=>!he(e)),Y=n=>Object.keys(n?.dependencies||{}).filter(e=>!he(e)),Fe=n=>B(n).filter(e=>!n?.peerDependenciesMeta?.[e]?.optional),N=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:s,autoAddedPeers:o}=await this.expandWithPeers(r,t),i=this.computeFlags(s);return{allRoots:s,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:r})=>({name:t,version:r,meta:await this.cdn.fetchPackageMeta(t,r)})))}async expandWithPeers(e,t){let r=new Map(e.map(o=>[o.name,o])),s=[];for(let o of e)for(let i of Fe(o.meta))!r.has(i)&&!s.some(c=>c.name===i)&&s.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of s)try{let c=await t(o),d=await this.cdn.fetchPackageMeta(o,c);r.set(o,{name:o,version:c,meta:d})}catch(c){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,c)}return{allRoots:[...r.values()],autoAddedPeers:s.filter(o=>r.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>B(o.meta))),r=new Map;for(let o of e)for(let i of Y(o.meta))r.set(i,(r.get(i)||0)+1);let s=new Set([...r.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:B(o.meta).length>0,isSharedDep:s.has(o.name)}]))}};var j=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 v(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let r=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(r)return r}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let r=await this.cache.getPinnedExact(e,t);if(r){if(this.semver.isExactVersion(r))return r;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",r)}let s=await v(()=>this.cdn.fetchVersionsIndex(e));if(s?.versions?.length){let i=this.selectVersionFromIndex(s.versions,t,s.distTags);if(i){if(this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let c=await v(()=>this.cdn.fetchVersionsIndex(e));if(c?.versions?.length){let d=this.selectVersionFromIndex(c.versions,t,c.distTags);if(d&&this.semver.isExactVersion(d))return await this.cache.setPinnedExact(e,t,d),d}}}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 g(e),s=r.root(),o=t[s],i=o?await v(()=>this.cache.getPinnedExact(s,o))??await v(()=>this.resolveExactForRoot(s,o)):void 0;return{effectivePackage:i?r.withVersion(i).format():e,root:s,range:o,pinned:i}}};import{init as Ue,parse as Le}from"es-module-lexer";var T=class n{constructor(e,t,r,s){this.version=e,this.cdn=t,this.peer=r,this.cache=s}extractImportsSync(e){let t=new Set;for(let r of n.importPatterns){r.lastIndex=0;for(let s of e.matchAll(r))g.isBare(s[1])&&t.add(s[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=s=>{g.isBare(s)&&t.add(s)};try{await Ue;let[s]=Le(e);s.forEach(o=>r(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t){let r=await this.extractImports(e),s=[...new Set(r.map(g.rootOf))],o=await Promise.all(s.map(async a=>({name:a,version:await this.resolveVersion(a,t)}))),{allRoots:i,flags:c,autoAddedPeers:d}=await this.peer.resolve(o,a=>this.resolveVersion(a,t)),f=this.buildEntries([...r,...d.map(a=>a.name)],i,c,t);return{importMap:{imports:Object.fromEntries(f)},prefetchUrls:f.map(([,a])=>a)}}async resolveVersion(e,t){let r=t[e],s=await this.version.resolveExactForRoot(e,r);if(!s){let o=r?`${e}@${r}`:e,i=await v(()=>this.cdn.pinEsmUrl(o));if(!i)throw new Error(`Cannot resolve version for ${e} - network may be unavailable.`);s=g.versionFromUrl(i),s&&r&&await v(()=>this.cache.setPinnedExact(e,r,s))}if(!s)throw new Error(`Cannot resolve version for ${e}`);return s}buildEntries(e,t,r,s){let o=new Map(t.map(p=>[p.name,p])),i=p=>{let m=o.get(g.rootOf(p));return new g(p).withPreferredVersion(m.version,s[m.name]).format()},c=new Set([...r.entries()].filter(([,p])=>p.isPeerRoot||p.isSharedDep).map(([p])=>p)),d=new Set(e.filter(p=>p!==g.rootOf(p)).map(g.rootOf)),f=[],a=new Set,l=new Set(e.filter(p=>p===g.rootOf(p))),u=new Set;for(let p of e){let m=g.rootOf(p),P=o.get(m),{isPeerRoot:x,hasPeers:R,isSharedDep:A}=r.get(m),H=d.has(m),I=p!==m,Me=!(x||A)&&(H||!R),G=this.singletonDepsOf(P,c),ce=I&&l.has(m);ce&&u.add(m);let $e=ce?[...G,m]:G.length?G:void 0;f.push([p,this.cdn.buildEsmUrl(i(p),{bundle:Me,external:$e})]),a.add(p)}let h=new Set([...c,...u]);for(let p of h)o.has(p)&&(a.has(p)||f.push([p,this.cdn.buildEsmUrl(i(p),{})]),f.push([`${p}/`,`${this.cdn.esmHost}/${i(p)}/`]));return f}singletonDepsOf(e,t){return[...new Set([...B(e.meta),...Y(e.meta)])].filter(r=>t.has(r))}};T.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as ge,satisfies as Ve,maxSatisfying as X,major as He,prerelease as We,rsort as Je,valid as qe}from"semver";var q=class{cmp(e,t){return e===t?0:ge(e,t)?1:ge(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Ve(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=X(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?Je(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",s=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(r,o))return o;if(s){let c=X(e,r,{includePrerelease:!1});if(c)return c}return X(e,r,{includePrerelease:!0})??void 0}majorOf(e){return He(e)}isPrerelease(e){return We(e)!==null}isExactVersion(e){return qe(e)!==null}},Z=new q;function ye(n,e){let t=new D(n,e),r=new N(t),s=new j(n,t,Z);return{packageService:new T(s,t,r,n),versionResolver:s,cdnClient:t,peerResolver:r}}var Q=class{pins=new Map;indexes=new Map;negatives=new Set;meta=new Map;async getPinnedExact(e,t){return this.pins.get(`${e}@${t}`)}async setPinnedExact(e,t,r){this.pins.set(`${e}@${t}`,r)}async getIndex(e){return this.indexes.get(e)}async setIndex(e,t,r){this.indexes.set(e,{versions:t,distTags:r,updatedAt:Date.now()})}async invalidateVersionsCache(e){this.indexes.delete(e)}async isNegative(e){return this.negatives.has(e)}async recordNegative(e){this.negatives.add(e)}async clearNegative(e){this.negatives.delete(e)}async getMeta(e,t){return this.meta.get(`${e}@${t}`)}async setMeta(e,t,r,s,o){this.meta.set(`${e}@${t}`,{dependencies:r,peerDependencies:s,peerDependenciesMeta:o,updatedAt:Date.now()})}},Ge={async getJson(n){try{let e=await fetch(n,{redirect:"follow"});return e.ok?await e.json():void 0}catch{return}},async head(n){try{let e=await fetch(n,{method:"HEAD",redirect:"follow"});return{ok:e.ok,url:e.url}}catch{return}}},ze=new Q,{packageService:we,versionResolver:rr,cdnClient:sr,peerResolver:nr}=ye(ze,Ge);var ve=`
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=`
5
+ /**
6
+ * Get raw data chunk from the Data tab.
7
+ * @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
8
+ */
9
+ data(index: number): string;
10
+ /**
11
+ * Get data chunk parsed as JSON (handles JSON-ish with unquoted keys).
12
+ * @param index - Chunk index (0-based)
13
+ * @throws If chunk is not valid JSON/JSON-ish
14
+ */
15
+ json<T = unknown>(index: number): T;`,Rt=`
16
+ /**
17
+ * Get the insight data produced by the inference layer.
18
+ *
19
+ * Returns the parsed JSON from insight.json, populated by the inference LLM.
20
+ * Use a type parameter to get typed access to the insight data.
21
+ *
22
+ * @returns The parsed insight JSON, or undefined if no insight is available
23
+ */
24
+ insight<T = unknown>(): T | undefined;`,Et=`
25
+ /**
26
+ * General-purpose AI call.
27
+ *
28
+ * @param options - Messages, system prompt, optional provider/model override
29
+ * @returns Promise resolving to { text: string }
30
+ * @throws On rate limit, network error, or provider error
31
+ */
32
+ ai(options: {
33
+ messages: Array<{ role: "user" | "assistant"; content: string }>;
34
+ system?: string;
35
+ /** Reasoning depth hint (0=min, 1=low, 2=med, 3=max). Mapped to provider-specific parameters (e.g. Anthropic adaptive thinking, OpenAI reasoning effort). Default: 0. */
36
+ reasoning?: 0 | 1 | 2 | 3;
37
+ provider?: string;
38
+ model?: string;
39
+ /** Enable/disable web search. Default: on for BYOK, always off for free model. */
40
+ webSearch?: boolean;
41
+ }): Promise<{ text: string }>;`,kt=`
42
+ /**
43
+ * Returns AI models available to the current user.
44
+ * Models are filtered by the user's configured API keys.
45
+ * If no keys are configured, returns only the courtesy model.
46
+ */
47
+ models(): Promise<Array<{
48
+ /** Provider protocol: "anthropic", "openai", "gemini", "openrouter" */
49
+ provider: string;
50
+ /** Model identifier, e.g. "claude-sonnet-4-6" */
51
+ name: string;
52
+ /** Human-readable display name, e.g. "Sonnet 4.6" */
53
+ friendlyName: string;
54
+ /** Provider display name, e.g. "Anthropic" */
55
+ providerName: string;
56
+ }>>;`,Tt=`
57
+ /**
58
+ * The mode this bulb is running in.
59
+ *
60
+ * - \`'local'\` \u2014 Running via the typebulb CLI
61
+ * - \`'editor'\` \u2014 Running in the typebulb.com editor
62
+ * - \`'published'\` \u2014 Running as a published/standalone bulb on typebulb.com
63
+ */
64
+ mode: 'local' | 'editor' | 'published';`,Ct=`
65
+ /**
66
+ * Local filesystem access (CLI only).
67
+ *
68
+ * Paths are resolved relative to the directory containing the bulb file.
69
+ * Throws in editor/published mode.
70
+ */
71
+ fs: {
72
+ /** Read a file as UTF-8 text. Path is relative to the bulb's directory. */
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=`
77
+ /**
78
+ * Server-side function proxy. The built-in \`log\` prints to CLI stdout
79
+ * (falls back to console.log on web). On the server side, this object only
80
+ * exposes \`log\` \u2014 server-to-server calls are not supported.
81
+ */
82
+ server: {
83
+ log(...args: any[]): Promise<void>;
84
+ };`,vr=`
85
+ /**
86
+ * Async value inspector for tensor-like objects.
87
+ *
88
+ * Materializes lazy values (like GPU tensors) and logs them with metadata.
89
+ * Handles objects with \`.js()\`, \`.data()\`, \`.array()\`, \`.arraySync()\`, etc.
90
+ *
91
+ * @remarks
92
+ * - Always use \`await\` - materialization may be async (GPU\u2192CPU readback)
93
+ * - Large values are truncated (max 1000 elements)
94
+ * - Promises are logged as \`[Promise]\` (not awaited - could hang)
95
+ */
96
+ dump(...args: any[]): Promise<void>;
97
+ /**
98
+ * Trigger inference to generate new insight data.
99
+ *
100
+ * Opens a confirmation modal showing the data to be analyzed, then streams
101
+ * the inference result. On success, updates the insight so subsequent
102
+ * \`tb.insight()\` calls return the new value.
103
+ *
104
+ * @param opts - Options for inference
105
+ * @param opts.data - Data to pre-populate in the modal (string or array of strings). If omitted, modal opens with empty textarea for user to paste.
106
+ * @returns Promise that resolves with the parsed insight JSON
107
+ * @throws If inference is already in progress, or on network/parse/rate limit errors
108
+ */
109
+ infer<T = unknown>(opts?: { data?: string | string[] }): Promise<T>;
110
+ /**
111
+ * Get the current inference state.
112
+ *
113
+ * @returns 'idle' | 'running' | 'complete' | 'error'
114
+ */
115
+ inferenceState(): 'idle' | 'running' | 'complete' | 'error';
116
+ /**
117
+ * Set a data chunk for the next inference call.
118
+ *
119
+ * Use this to programmatically set data that will be sent when \`tb.infer()\` is called
120
+ * without the \`data\` option.
121
+ *
122
+ * @param index - The chunk index (0-based)
123
+ * @param content - The content for this chunk
124
+ */
125
+ setData(index: number, content: string): void;
126
+ /**
127
+ * Proxy a CDN URL through the sandbox origin for Web Worker/WASM same-origin loading.
128
+ *
129
+ * In the sandbox, prepends \`/proxy/\` so the URL is served from the same origin.
130
+ * Outside the sandbox (exported HTML, CLI), returns the URL unchanged.
131
+ *
132
+ * @param url - Full HTTPS URL to an allowlisted CDN (esm.sh, unpkg.com, cdn.jsdelivr.net, cdnjs.cloudflare.com)
133
+ * @returns The proxied URL (sandbox) or the original URL (standalone/CLI)
134
+ */
135
+ proxy(url: string): string;
136
+ /**
137
+ * Copy text to clipboard.
138
+ * Must be called synchronously within a user gesture (click/keydown).
139
+ * @returns true if successful, false otherwise
140
+ */
141
+ copy(text: string): Promise<boolean>;
142
+ /**
143
+ * Get the canonical URL of this bulb.
144
+ *
145
+ * Returns the parent typebulb.com URL (including path, query, and \`#tb=\` fragment),
146
+ * resolving correctly from inside the cross-origin sandbox iframe.
147
+ * Use this instead of \`location.href\` or \`document.referrer\`.
148
+ *
149
+ * @returns The full canonical URL
150
+ */
151
+ url(): Promise<string>;`,br=`
152
+ /**
153
+ * Server-side function proxy.
154
+ *
155
+ * In the CLI, calls exported functions from the \`**server.ts**\` section.
156
+ * \`tb.server.log(...)\` is a built-in that prints to CLI stdout (falls back to console.log on web).
157
+ * User exports override built-ins of the same name.
158
+ */
159
+ server: Record<string, (...args: any[]) => Promise<any>>;`,Ge=`
160
+ /**
161
+ * Typebulb utilities namespace.
162
+ * Type \`tb.\` to discover available helpers.
163
+ */
164
+ declare const tb: {${St}${vr}${Rt}${br}${Et}${Ct}${kt}${Tt}
165
+ };
166
+ `,qe=`
167
+ /**
168
+ * Typebulb utilities namespace (server-side).
169
+ * Type \`tb.\` to discover available helpers.
170
+ */
171
+ declare const tb: {${St}${Rt}${Et}${Ct}${wr}${kt}${Tt}
172
+ };
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=`
5
176
  (() => {
6
177
  // JSON parser (handles jsonish - unquoted keys)
7
178
  const parseJson = (str) => {
@@ -149,14 +320,14 @@ import*as w from"fs/promises";import{readFileSync as it,existsSync as Ie}from"fs
149
320
  };
150
321
  }
151
322
  })();
152
- `;function be(n){let{name:e,code:t,css:r,html:s,data:o,insight:i,importMap:c,watch:d}=n,f=s.trim()||'<div id="app"></div>',a=l=>l.replace(/<\/script/gi,"<\\/script");return`<!DOCTYPE html>
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>
153
324
  <html>
154
325
  <head>
155
326
  <meta charset="utf-8">
156
327
  <meta name="viewport" content="width=device-width, initial-scale=1">
157
- <title>${Ke(e)} - typebulb</title>
328
+ <title>${Fr(e)} - typebulb</title>
158
329
  <script type="importmap">
159
- ${JSON.stringify(c,null,2)}
330
+ ${JSON.stringify(f,null,2)}
160
331
  </script>
161
332
  <style>
162
333
  /* Reset and base styles */
@@ -168,40 +339,42 @@ ${r}
168
339
  </style>
169
340
  </head>
170
341
  <body>
171
- ${f}
342
+ ${d}
172
343
 
173
- ${o.length>0?`<script>window.__TB_DATA__ = ${a(JSON.stringify(o))};</script>`:""}
174
- ${i?`<script>window.__TB_INSIGHT__ = ${a(JSON.stringify(i))};</script>`:""}
175
- ${d?"<script>window.__TYPEBULB_WATCH__ = true;</script>":""}
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>":""}
176
347
 
177
348
  <script>
178
- ${ve}
349
+ ${Bt}
179
350
  </script>
180
351
 
181
352
  <script type="module">
182
- ${a(t)}
353
+ ${u(t)}
183
354
  </script>
184
355
  </body>
185
- </html>`}function Ke(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}import{Hono as Xe}from"hono";import{serve as Ze}from"@hono/node-server";import{streamSSE as Qe}from"hono/streaming";import*as M from"fs/promises";import*as _ from"path";var b=class extends Error{constructor(e,t="unknown",r=!1){super(e),this.code=t,this.retryable=r}},S=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=`
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=`
186
357
 
187
- `){let r=e.filter(s=>s.role==="system").map(s=>s.content);return{system:r.length?r.join(t):void 0,conversationMessages:e.filter(s=>s.role!=="system")}}parseJsonError(e,t,r=!1){if(!e)return{message:`HTTP ${t}`};try{let s=JSON.parse(e);if(s.error&&typeof s.error=="object"){let o={message:s.error.message||`HTTP ${t}`,type:s.error.type};return r&&(o.code=s.error.code),o}return s.message?{message:s.message}:{message:e}}catch{return{message:e}}}checkAndThrowError(e){if("type"in e&&e.type==="error"&&"message"in e){let t=e.message,r=e.code||"unknown",s=!!e.retryable;throw new b(t,r,s)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new b(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 F=class extends S{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,s){let{system:o,conversationMessages:i}=this.extractSystemMessages(e),c={model:t,max_tokens:this.getMaxTokens(t),messages:i,stream:s};if(r?.webSearch!==!1&&(c.tools=[{type:"web_search_20250305",name:"web_search"}]),o&&(c.system=o),this.isReasoningEnabled(r)){let d=r.reasoning;if(this.isModernModel(t)){let f={0:"low",1:"low",2:"medium",3:"high"};c.thinking={type:"adaptive"},c.output_config={effort:f[d]}}else{let f={0:0,1:2048,2:4096,3:8192};c.thinking={type:"enabled",budget_tokens:f[d]}}}return c}parseError(e,t){return this.parseJsonError(e,t)}parseNonStreamingResponse(e){if(!this.isAnthropicResponse(e))return{text:""};let t=e.content.filter(s=>s.type==="text").map(s=>s.text).join(""),r=e.content.filter(s=>s.type==="thinking").map(s=>s.thinking).join(`
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(`
188
359
 
189
- `);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 U=class extends S{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,s){let o=this.convertMessagesToInput(e),i={model:t,input:o,stream:s};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 s of e.output)s.type==="reasoning"&&s.summary&&(r=s.summary.map(o=>o.text).join(`
190
- `)),!t&&s.type==="message"&&s.content&&(t=s.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 s=e.response?.error,o=s?.message||"Response failed",i=s?.code==="insufficient_quota"||s?.code==="rate_limit_exceeded";throw new b(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(`
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(`
191
362
 
192
- `)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var L=class extends S{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,s){let{system:o,conversationMessages:i}=this.extractSystemMessages(e,`
193
- `),d={contents:i.map(f=>({role:f.role==="assistant"?"model":"user",parts:[{text:f.content}]}))};return r?.webSearch!==!1&&(d.tools=[{google_search:{}}]),o&&(d.systemInstruction={role:"system",parts:[{text:o}]}),this.isReasoningEnabled(r)&&(d.generationConfig={temperature:.7+r.reasoning*.1}),d}parseError(e,t){if(!e)return{message:`HTTP ${t}`};try{let r=JSON.parse(e),s=Array.isArray(r)?r[0]?.error:r?.error;return s&&typeof s=="object"?{message:(s.message||`HTTP ${t}`).split(`
194
- `)[0],type:s.status,code:s.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,s="complete";return r==="MAX_TOKENS"?s="interrupted":(r==="SAFETY"||r==="RECITATION")&&(s="failed"),{text:t,status:s}}parseProviderStreamChunk(e){if(this.checkGeminiError(e),!this.isGeminiResponse(e))return null;let t=this.extractText(e);return t?{text:t}:null}isGeminiResponse(e){return typeof e=="object"&&e!==null&&"candidates"in e&&Array.isArray(e.candidates)}extractText(e){let t=e.candidates?.[0];if(t?.content?.parts)return t.content.parts.map(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 s=t;r=s.message||s.status||"Gemini returned an error"}else r="Gemini returned an error";throw new b(r)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new b(`Prompt blocked: ${t}`)}}};var V=class extends S{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,s){let o={model:t,messages:e,stream:s};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??"",s=t?.message?.reasoning??e.reasoning;return{text:r,reasoning:s}}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 s=r.content||void 0,o=r.reasoning||void 0;return!s&&!o?null:{text:s,reasoning:o}}hasChoices(e){return typeof e=="object"&&e!==null&&"choices"in e&&Array.isArray(e.choices)}};var Ye=new Map([["openai",new U],["openrouter",new V],["anthropic",new F],["gemini",new L]]);function E(n){let e=Ye.get(n);if(!e)throw new Error(`Unsupported protocol: ${n}`);return e}async function ee(n,e){let t=E(n.protocol),r=t.getPath(e.model,e.stream),s=new URL(r,n.baseUrl).toString(),o=t.buildHeaders(n.apiKey,e.origin),i=t.buildPayload(e.messages,e.model,{reasoning:e.reasoning,webSearch:e.webSearch},e.stream);return e.modifyPayload?.(i),fetch(s,{method:"POST",headers:o,body:JSON.stringify(i),signal:e.signal})}async function te(n,e){let t=E(e),r=await n.text().catch(()=>""),{message:s}=t.parseError(r,n.status),o=n.status,i="unknown";return o===429?i="rate_limit":o===413&&(i="context_exceeded"),{code:i,message:s,retryable:o===429}}function xe(n){let e=n.indexOf(`\r
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
195
366
  \r
196
- `),t=n.indexOf(`
367
+ `),t=s.indexOf(`
197
368
 
198
- `);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function re(n){let t=n.split(/\r?\n/).filter(s=>s.startsWith("data:"));if(!t.length)return null;let r=t.map(s=>s.replace(/^data:\s?/,"")).join(`
199
- `).trim();if(!r)return null;if(r==="[DONE]")return"done";try{return JSON.parse(r)}catch{return null}}async function Se(n,e,t){let r=new TextDecoder,s="",o=!1,i=t?new Promise((c,d)=>{t.aborted&&d(new Error("Aborted")),t.addEventListener("abort",()=>d(new Error("Aborted")),{once:!0})}):null;for(;;){let c=i?await Promise.race([n.read(),i]):await n.read(),{done:d,value:f}=c;if(d){if(s.trim()){let u=re(s);u!==null&&u!=="done"&&e(u)}break}o=!0,s+=r.decode(f,{stream:!0});let{pos:a,len:l}=xe(s);for(;a!==-1;){let u=s.slice(0,a);s=s.slice(a+l);let h=re(u);if(h==="done"){s="";break}h!==null&&e(h),{pos:a,len:l}=xe(s)}}return{receivedAnyData:o}}async function se(n,e){let t=e??(n.headers.get("X-Provider-Protocol")||"openai"),r=E(t);if(!n.body)throw new Error("Response body is missing");let s=n.body.getReader(),o="";return await Se(s,i=>{let c=r.parseStreamChunk(i);c?.text&&(o+=c.text)}),o}async function _e(n){let{getHtml:e,basePath:t,port:r,reloadEmitter:s,getServerExports:o}=n,i=new Xe;i.use("*",async(a,l)=>{await l(),a.res.headers.set("Cross-Origin-Opener-Policy","same-origin"),a.res.headers.set("Cross-Origin-Embedder-Policy","credentialless")}),i.get("/",a=>a.html(e())),i.post("/__fs/read",async a=>{try{let{path:l}=await a.req.json(),u=Ee(l,t),h=await M.readFile(u,"utf-8");return a.json({content:h})}catch(l){let u=l instanceof Error?l.message:"Unknown error";return a.json({error:u},400)}}),i.post("/__fs/write",async a=>{try{let{path:l,content:u}=await a.req.json(),h=Ee(l,t);return await M.mkdir(_.dirname(h),{recursive:!0}),await M.writeFile(h,u,"utf-8"),a.json({success:!0})}catch(l){let u=l instanceof Error?l.message:"Unknown error";return a.json({error:u},400)}});let c={log:console.log};i.post("/__api/:name",async a=>{try{let l=o?.(),u=a.req.param("name"),h=l?.[u]??c[u];if(!h||typeof h!="function")return a.json({error:`API function '${u}' not found`},404);let{args:p}=await a.req.json(),m=await h(...p||[]);return a.json({result:m})}catch(l){let u=l instanceof Error?l.message:"Unknown error";return a.json({error:u},500)}}),i.post("/__ai",async a=>{try{let{messages:l,system:u,reasoning:h,provider:p,model:m,webSearch:P}=await a.req.json();if(!l||!Array.isArray(l)||l.length===0)return a.json({message:"messages array is required",code:"unknown",retryable:!1},400);let x=et(p,m);if(typeof x=="string")return a.json({message:x,code:"unknown",retryable:!1},400);let R=[...u?[{role:"system",content:u}]:[],...l.map(I=>({role:I.role,content:I.content}))],A=await ee(x,{model:x.model,messages:R,stream:!0,reasoning:h??0,webSearch:P??!0});if(!A.ok){let I=await te(A,x.protocol);return a.json(I,A.status)}let H=await se(A,x.protocol);return H||console.warn("[tb.ai] Empty response from provider"),a.json({text:H})}catch(l){if(l instanceof b)return a.json({message:l.message,code:l.code,retryable:l.retryable},500);let u=l instanceof Error?l.message:"Unknown error";return a.json({message:u,code:"unknown",retryable:!1},500)}}),i.get("/__models",async a=>{try{let l=await st();return a.json(l)}catch{return a.json([],200)}});let d=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"];i.get("/proxy/*",async a=>{let l=a.req.path.slice(7),u=l.lastIndexOf("https://");if(u===-1)return a.text("Invalid proxy URL",400);let h=l.slice(u),p;try{p=new URL(h)}catch{return a.text("Invalid URL",400)}if(p.protocol!=="https:")return a.text("HTTPS only",400);if(!d.includes(p.hostname))return a.text("Host not allowed",403);try{let m=await fetch(h,{headers:{Accept:a.req.header("Accept")||"*/*"},redirect:"follow"});if(!m.ok)return a.text(`Upstream ${m.status}`,m.status);let P=new Headers,x=m.headers.get("Content-Type");x&&P.set("Content-Type",x);let R=m.headers.get("Cache-Control");return R&&P.set("Cache-Control",R),P.set("Access-Control-Allow-Origin","*"),P.set("Cross-Origin-Resource-Policy","cross-origin"),new Response(m.body,{status:m.status,headers:P})}catch(m){return a.text(`Proxy fetch failed: ${m instanceof Error?m.message:m}`,502)}}),s&&i.get("/__reload",a=>Qe(a,async l=>{let u=()=>{l.writeSSE({event:"reload",data:""})};for(s.on("reload",u),l.onAbort(()=>{s.removeListener("reload",u)});;)await l.sleep(3e4)}));let f=Ze({fetch:i.fetch,port:r});return{port:r,close:()=>f.close()}}var Re={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function et(n,e){let t=n??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 s;try{s=E(t)}catch{return`Unknown provider '${t}'.`}let o=Re[t],i=process.env[o];return i?{apiKey:i,baseUrl:s.defaultBaseUrl,protocol:t,model:r,isFreeModel:!1}:`No API key for '${t}'. Set ${o} in your .env file.`}var tt="https://api.typebulb.com/api/models",rt=1440*60*1e3,O=null;async function st(){if(!O||Date.now()-O.fetchedAt>rt){let n=await fetch(tt);if(!n.ok)return O?Pe(O.models):[];O={models:await n.json(),fetchedAt:Date.now()}}return Pe(O.models)}function Pe(n){let e=new Set(Object.entries(Re).filter(([,t])=>!!process.env[t]).map(([t])=>t));return n.filter(t=>e.has(t.provider))}function Ee(n,e){let t=_.resolve(e,n),r=_.normalize(e);if(!_.normalize(t).startsWith(r))throw new Error("Path traversal detected - access denied");return t}async function ne(n){let e=await import("net");return new Promise(t=>{let r=e.createServer();r.listen(n,()=>{let s=r.address(),o=typeof s=="object"&&s?s.port:n;r.close(()=>t(o))}),r.on("error",()=>{t(ne(n+1))})})}import nt from"open";async function Ae(n){await nt(n)}import ot from"chokidar";function oe(n){let{bulbPath:e,emitter:t}=n,r=ot.watch(e,{persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}});return r.on("change",()=>{t.emit("reload")}),()=>r.close()}var pt=lt(ct),dt="0.1.3";function ut(n){let e={file:"",port:3e3,watch:!0,open:!0,server:!1,help:!1,version:!1};for(let t=0;t<n.length;t++){let r=n[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 s=n[++t],o=parseInt(s,10);isNaN(o)&&(console.error(`Invalid port: ${s}`),process.exit(1)),e.port=o}else r.startsWith("-")||(e.file=r)}return e}function ft(){console.log(`
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+\/|@[^/]+\/[^@/]+@|[^@/]+@)/;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.0";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(`
200
373
  typebulb - Local bulb runner for Typebulb
201
374
 
202
375
  Usage:
203
- typebulb <file.bulb.md> Run a specific bulb file
204
- typebulb . Find and run .bulb.md in current directory
376
+ typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
377
+ typebulb check [file.bulb.md] Type-check a bulb without running it
205
378
 
206
379
  Options:
207
380
  --no-watch Disable hot reload (watch is on by default)
@@ -243,11 +416,11 @@ Examples:
243
416
  typebulb my-editor.bulb.md
244
417
  typebulb --no-watch --port 8080 my-editor.bulb.md
245
418
  typebulb .
246
- `)}async function mt(n){let t=(await w.readdir(n)).find(r=>r.endsWith(".bulb.md"));return t?y.join(n,t):null}function Te(){ae([".env",".env.local"],process.cwd(),!0)}function ae(n,e,t=!1){for(let r of n){let s=y.resolve(e,r);try{let o=it(s,"utf-8");for(let i of o.split(`
247
- `)){let c=i.trim();if(!c||c.startsWith("#"))continue;let d=c.indexOf("=");if(d===-1)continue;let f=c.slice(0,d).trim(),a=c.slice(d+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),process.env[f]??=a}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}function ht(n){let e=new Set,t=/\bimport\s+(?:[\s\S]*?\s+from\s+)?['"]([^./][^'"]*)['"]/g,r;for(;r=t.exec(n);){let s=r[1];if(s.startsWith("node:"))continue;let o=s.startsWith("@")?s.split("/").slice(0,2).join("/"):s.split("/")[0];e.add(o)}return[...e]}async function gt(n,e){let t=n.filter(s=>!Ie(y.join(e,"node_modules",s)));if(t.length===0)return;let r=y.join(e,"package.json");Ie(r)||await w.writeFile(r,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${t.join(", ")}`),await pt("npm",["install","--no-audit","--no-fund",...t],{cwd:e,shell:!0})}async function Oe(n,e){let t=ue(n);if(t.error)throw new Error(`Server compilation error: ${t.error}`);let r=y.join(e,".typebulb");await w.mkdir(r,{recursive:!0});let s=ht(t.code);s.length>0&&await gt(s,r);let o=y.join(r,"server.mjs");return await w.writeFile(o,t.code,"utf-8"),await import(`${at(o).href}?t=${Date.now()}`)}async function ke(n,e){let t=await w.readFile(n,"utf-8"),r=W(t);if(!r)throw new Error("Invalid .bulb.md file format");let s=J(r),o=z(s.config),i=le(s.data),c=de(s.code,{jsxImportSource:o.jsxImportSource});c.error&&console.error("Compilation error:",c.error);let{importMap:d}=await we.buildImportMap(c.code,o.dependencies??{}),f=be({name:s.name,code:c.code,css:s.css,html:s.html,data:i,insight:s.insight,importMap:d,watch:e}),a=y.dirname(n);o.env?.length&&ae(o.env,a);let l=null;return s.server&&(l=await Oe(s.server,a)),{html:f,bulb:s,serverExports:l}}async function yt(n,e){Te();let t=async()=>{let r=await w.readFile(n,"utf-8"),s=W(r);if(!s)throw new Error("Invalid .bulb.md file format");let o=J(s),i=z(o.config),c=y.dirname(n);i.env?.length&&ae(i.env,c),await Oe(o.server,c)};if(console.log(`Running ${y.basename(n)}...`),await t(),e){console.log(`Watching for changes...
248
- `);let r=new ie;r.on("reload",async()=>{try{console.log("Re-running..."),await t()}catch(s){console.error("Error:",s)}}),oe({bulbPath:n,emitter:r})}}async function wt(){let n=ut(process.argv.slice(2));n.version&&(console.log(`typebulb ${dt}`),process.exit(0)),n.help&&(ft(),process.exit(0));let e;if(!n.file||n.file==="."){let p=await mt(process.cwd());p||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=p}else e=y.resolve(n.file);try{await w.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=await w.readFile(e,"utf-8"),r=W(t);if(r){let p=J(r);if(p.server&&(!p.code||n.server)){await yt(e,n.watch);return}}let s=process.cwd(),o=n.watch?new ie:void 0;Te(),console.log(`Loading ${y.basename(e)}...`);let{html:i,bulb:c,serverExports:d}=await ke(e,n.watch),f=await ne(n.port),a=await _e({getHtml:()=>i,basePath:s,port:f,reloadEmitter:o,getServerExports:()=>d}),l=`http://localhost:${f}`;console.log(`
249
- ${c.name}`),console.log(` ${l}
250
- `),n.watch&&console.log(` Watching for changes...
251
- `);let u;if(n.watch&&o){let p=new ie;p.on("reload",async()=>{try{console.log("Recompiling...");let m=await ke(e,!0);i=m.html,d=m.serverExports,o.emit("reload"),console.log(`Done. Browser reloading...
252
- `)}catch(m){console.error("Compile error:",m)}}),u=oe({bulbPath:e,emitter:p})}n.open&&await Ae(l);let h=async()=>{console.log(`
253
- Shutting down...`),a.close(),u?.();let p=y.join(y.dirname(e),".typebulb","server.mjs");await w.rm(p,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",h),process.on("SIGTERM",h)}wt().catch(n=>{console.error("Error:",n.message),process.exit(1)});
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}
423
+ `),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)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebulb",
3
- "version": "0.4.5",
3
+ "version": "0.5.0",
4
4
  "description": "Local bulb runner CLI for Typebulb",
5
5
  "license": "MIT",
6
6
  "engines": { "node": ">=18" },
@@ -16,14 +16,18 @@
16
16
  "build": "tsc --build && node esbuild.config.mjs",
17
17
  "clean": "rimraf dist .tsbuild",
18
18
  "dev": "tsc --build && node dist/index.js",
19
- "prepublishOnly": "rimraf dist && node esbuild.config.mjs"
19
+ "prepublishOnly": "rimraf dist && tsc --build && node esbuild.config.mjs"
20
20
  },
21
21
  "dependencies": {
22
22
  "@hono/node-server": "^1.14.1",
23
23
  "chokidar": "^4.0.3",
24
24
  "es-module-lexer": "^1.7.0",
25
+ "fflate": "^0.8.2",
25
26
  "hono": "^4.7.5",
27
+ "lru-cache": "^11.2.2",
26
28
  "open": "^10.1.0",
29
+ "p-limit": "^7.2.0",
30
+ "resolve.exports": "^2.0.3",
27
31
  "semver": "^7.7.3",
28
32
  "sucrase": "^3.35.0"
29
33
  },
@@ -33,6 +37,7 @@
33
37
  "@typebulb/shared-types": "workspace:*",
34
38
  "esbuild": "^0.27.3",
35
39
  "rimraf": "^6.0.1",
36
- "typebulb-resolver": "workspace:*"
40
+ "typebulb-resolver": "workspace:*",
41
+ "typebulb-dts": "workspace:*"
37
42
  }
38
43
  }