typebulb 0.9.1 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,80 @@
1
1
  #!/usr/bin/env node
2
- import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S from"path";import{pathToFileURL as Jn}from"url";import{execFile as Vn,spawn as qn}from"child_process";import{promisify as Gn}from"util";import{EventEmitter as Rt}from"events";var Tr={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 Tt(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=_r(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 l=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!l){t++;continue}let d=l[1];t++;let p=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${d}\\s*$`));)p.push(e[t]),t++;t++,i.set(c,p.join(`
4
- `))}else t++}return{frontmatter:n,files:i}}catch{return null}}function _r(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=Cr(i);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function Cr(s){return s.startsWith('"')&&s.endsWith('"')?s.slice(1,-1).replace(/\\"/g,'"'):s.startsWith("'")&&s.endsWith("'")?s.slice(1,-1):s}function _t(s){let e=t=>s.files.get(Tr[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 Ir(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 Ct(s){let e=s.trim();return e?Ir(e)?[e]:s.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function It(s){if(!s.trim())return{};try{return JSON.parse(s)}catch{return{}}}import{transform as Or}from"sucrase";function Ye(s,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:r}=Or(s,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:r}}catch(r){return{code:"",error:String(r)}}}var ce="https://esm.sh",le="https://cdn.jsdelivr.net/npm/",Xe="https://data.jsdelivr.com/v1/package/npm/";function Ot(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=ee(t??n.version),this.subpath=ee(r??n.subpath)}static parse(e){let t=Ot(e||"");if(!t.length)return new s({name:""});if(t[0].startsWith("@")){let n=t[0],[i,o]=Dt(t[1]??""),a=ee(t.slice(2).join("/"));return new s({name:`${n}/${i}`,version:o,subpath:a})}else{let[n,i]=Dt(t[0]),o=ee(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(ce).host,n=new URL(le).host;if(t.host===r){let i=Ot(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:ee(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://")}},ee=s=>s&&s.length?s:void 0,Dt=s=>{let e=s.indexOf("@");return e<0?[s,void 0]:[s.slice(0,e),ee(s.slice(e+1))]};async function C(s){try{return await s()}catch{return}}var de=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=ce,this.jsDelivrBase=le,this.jsDelivrMeta=Xe,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 C(()=>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 C(()=>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 C(()=>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:d,peerDependencies:p,peerDependenciesMeta:h}=r;return{name:e,version:t,dependencies:d,peerDependencies:p,peerDependenciesMeta:h}}let n=this.packageJson(new g(`${e}@${t}`)),i=await C(()=>this.http.getJson(n));if(!i)return;let o=d=>d&&Object.keys(d).length?d:void 0,a=o(i.dependencies),c=o(i.peerDependencies),l=o(i.peerDependenciesMeta);return await this.cache.setMeta(e,t,a,c,l),{name:e,version:t,dependencies:a,peerDependencies:c,peerDependenciesMeta:l}}};var At=s=>s.startsWith("@types/"),pe=s=>Object.keys(s?.peerDependencies||{}).filter(e=>!At(e)),Qe=s=>Object.keys(s?.dependencies||{}).filter(e=>!At(e)),Dr=s=>pe(s).filter(e=>!s?.peerDependenciesMeta?.[e]?.optional),ue=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=>pe(i.meta))),r=new Map;for(let i of e)for(let o of Qe(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:pe(i.meta).length>0,isSharedDep:n.has(i.name)}]))}};var he=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 C(()=>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 C(()=>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 C(()=>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 C(()=>this.cache.getPinnedExact(n,i))??await C(()=>this.resolveExactForRoot(n,i)):void 0;return{effectivePackage:o?r.withVersion(o).format():e,root:n,range:i,pinned:o}}};import{init as Ar,parse as Mr}from"es-module-lexer";var te=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 Ar;let[n]=Mr(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,r){let n=(await this.extractImports(e)).filter(p=>!r?.has(g.rootOf(p))),i=[...new Set(n.map(g.rootOf))],o=await Promise.all(i.map(async p=>({name:p,version:await this.resolveVersion(p,t)}))),{allRoots:a,flags:c,autoAddedPeers:l}=await this.peer.resolve(o,p=>this.resolveVersion(p,t)),d=this.buildEntries([...n,...l.map(p=>p.name)],a,c,t);return{importMap:{imports:Object.fromEntries(d)},prefetchUrls:d.map(([,p])=>p)}}async resolveVersion(e,t){let r=t[e],n=r?`${e}@${r}`:e,i=await this.version.resolveExactForRoot(e,r);if(!i){let o=await C(()=>this.cdn.pinEsmUrl(n));if(!o)throw new Error(`Cannot resolve ${n}: no matching version is published (the package or version may not exist, or the registry was unreachable).`);i=g.versionFromUrl(o),i&&r&&await C(()=>this.cache.setPinnedExact(e,r,i))}if(!i)throw new Error(`Cannot resolve ${n}: no concrete version found.`);return i}buildEntries(e,t,r,n){let i=new Map(t.map(f=>[f.name,f])),o=f=>{let R=i.get(g.rootOf(f));return new g(f).withPreferredVersion(R.version,n[R.name]).format()},a=new Set([...r.entries()].filter(([,f])=>f.isPeerRoot||f.isSharedDep).map(([f])=>f)),c=new Set(e.filter(f=>f!==g.rootOf(f)).map(g.rootOf)),l=[],d=new Set,p=new Set(e.filter(f=>f===g.rootOf(f))),h=new Set;for(let f of e){let R=g.rootOf(f),v=i.get(R),{isPeerRoot:k,hasPeers:$,isSharedDep:u}=r.get(R),m=c.has(R),y=f!==R,b=!(k||u)&&(m||!$),I=this.singletonDepsOf(v,a),H=y&&p.has(R);H&&h.add(R);let B=H?[...I,R]:I.length?I:void 0;l.push([f,this.cdn.buildEsmUrl(o(f),{bundle:b,external:B})]),d.add(f)}let w=new Set([...a,...h]);for(let f of w)i.has(f)&&(d.has(f)||l.push([f,this.cdn.buildEsmUrl(o(f),{})]),l.push([`${f}/`,`${this.cdn.esmHost}/${o(f)}/`]));return l}singletonDepsOf(e,t){return[...new Set([...pe(e.meta),...Qe(e.meta)])].filter(r=>t.has(r))}};te.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as Mt,satisfies as $r,maxSatisfying as Ze,major as Fr,prerelease as jr,rsort as Nr,valid as Lr}from"semver";var Oe=class{cmp(e,t){return e===t?0:Mt(e,t)?1:Mt(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!$r(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=Ze(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?Nr(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=Ze(e,r,{includePrerelease:!1});if(a)return a}return Ze(e,r,{includePrerelease:!0})??void 0}majorOf(e){return Fr(e)}isPrerelease(e){return jr(e)!==null}isExactVersion(e){return Lr(e)!==null}},G=new Oe;function $t(s,e){let t=new de(s,e),r=new ue(t),n=new he(s,t,G);return{packageService:new te(n,t,r,s),versionResolver:n,cdnClient:t,peerResolver:r}}import*as Yt from"fs/promises";import*as j from"path";var et=[{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"}],tt=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var Ft=`
2
+ import*as nt from"fs/promises";import*as R from"path";import{spawn as Ws}from"child_process";import{EventEmitter as Wt}from"events";import*as Vt from"fs/promises";import{existsSync as te,readFileSync as un}from"fs";import*as P from"path";import{pathToFileURL as pn}from"url";import{resolve as it}from"resolve.exports";import{init as qt,parse as Gt}from"es-module-lexer";function zt(n,e){let t=P.join(n,"package.json");try{return JSON.parse(un(t,"utf8"))}catch{throw new Error(`--replace package '${e}' has no readable package.json at ${t}`)}}var ot=["browser","import","default"],Ht=["node","import","default"];function Kt(n){let e=n.indexOf("=");if(e===-1)throw new Error(`--replace must be <name>=<path> (got '${n}')`);let t=n.slice(0,e).trim(),r=n.slice(e+1).trim();if(!t)throw new Error(`--replace missing package name (got '${n}')`);if(!r)throw new Error(`--replace missing path for '${t}'`);if(t.startsWith("@"))throw new Error(`--replace does not support scoped names yet; '${t}' is scoped`);return{name:t,dir:P.resolve(r)}}async function Yt(n){let{name:e,dir:t}=n;if(!te(t))throw new Error(`--replace path for '${e}' does not exist: ${t}`);let r=zt(t,e),s=fn(r,e),o=P.resolve(t,s);if(!te(o))throw new Error(`--replace package '${e}' entry not found on disk: ${o} \u2014 did you build it (e.g. \`pnpm run build\`)?`);let i=P.dirname(o),a=`/local/${e}/${P.basename(o)}`,c=hn(r,t);return await mn(e,o,i),{name:e,dir:t,entryAbs:o,serveDir:i,entryUrl:a,typesAbs:c}}function fn(n,e){if(n.exports!==void 0){let r;try{r=it(n,".",{browser:!0,conditions:ot})}catch(o){throw new Error(`--replace package '${e}' "exports" does not resolve a browser entry (conditions: ${ot.join(", ")}): ${o instanceof Error?o.message:o}`)}let s=at(r);if(!s)throw new Error(`--replace package '${e}' "exports" did not resolve "." to a single file (conditions: ${ot.join(", ")}); too complex to override.`);return s}let t=n.module??n.main;if(!t)throw new Error(`--replace package '${e}' has no "exports", "module", or "main" entry to resolve.`);return t}function hn(n,e){if(n.exports!==void 0)try{let r=it(n,".",{conditions:["types"]}),s=at(r);if(s){let o=P.resolve(e,s);if(te(o))return o}}catch{}let t=n.types??n.typings;if(t){let r=P.resolve(e,t);if(te(r))return r}}function at(n){if(typeof n=="string")return n;if(Array.isArray(n))return n.find(e=>typeof e=="string")}async function mn(n,e,t){await qt;let r=P.normalize(t),s=new Set,o=[e];for(;o.length;){let i=o.shift();if(s.has(i))continue;s.add(i);let a;try{a=await Vt.readFile(i,"utf8")}catch{continue}let c,l;try{[c,,,l]=Gt(a,i)}catch{continue}if(i===e&&!l)throw new Error(`override package '${n}' entry is not an ES module (no import/export syntax); CommonJS or non-module entries aren't supported (esm.sh would have to transform it).`);for(let d of c){if(d.d===-2)continue;let u=d.n;if(u&&!u.startsWith("node:")){if(u.startsWith("./")||u.startsWith("../")||u.startsWith("/")){let h=gn(i,u,r);h&&!s.has(h)&&o.push(h);continue}throw new Error(`override package must ship self-contained (bundle its dependencies); ${n} externalizes '${u}'`)}}}}function gn(n,e,t){let r=e.replace(/[?#].*$/,""),s=P.resolve(P.dirname(n),r),o=[s,s+".js",s+".mjs",P.join(s,"index.js"),P.join(s,"index.mjs")];for(let i of o)if(P.normalize(i).startsWith(t)&&te(i))return i}function yn(n,e,t){let r=zt(n,e),s;if(r.exports!==void 0)try{s=at(it(r,t,{conditions:Ht}))}catch(i){throw new Error(`--replace package '${e}' "exports" does not resolve a node entry for '${t}' (conditions: ${Ht.join(", ")}): ${i instanceof Error?i.message:i}`)}else t==="."&&(s=r.main??r.module);if(!s)throw new Error(`--replace package '${e}' has no node export for '${t}'.`);let o=P.resolve(n,s);if(!te(o))throw new Error(`--replace package '${e}' built file not found: ${o} \u2014 did you build it (e.g. \`pnpm run build\`)?`);return pn(o).href}async function Xt(n,e){await qt;let t;try{[t]=Gt(n)}catch{return n}let r="",s=0;for(let o of t){if(o.d!==-1)continue;let i=o.n;if(!i||i!==e.name&&!i.startsWith(e.name+"/"))continue;let a=i===e.name?".":"."+i.slice(e.name.length),c=yn(e.dir,e.name,a);r+=n.slice(s,o.s)+c,s=o.e}return r+n.slice(s)}function Qt(n){let e={subcommand:"run",file:"",port:3e3,watch:!0,open:!0,server:!1,trust:!1,noTrust:!1,follow:!1,help:!1,version:!1};["check","logs","stop","trust","untrust"].includes(n[0])&&(e.subcommand=n[0],n=n.slice(1));for(let r=0;r<n.length;r++){let s=n[r];if(s==="--help"||s==="-h")e.help=!0;else if(s==="--version"||s==="-V")e.version=!0;else if(s==="--no-watch")e.watch=!1;else if(s==="--no-open")e.open=!1;else if(s==="--server")e.server=!0;else if(s==="--trust")e.trust=!0;else if(s==="--no-trust")e.noTrust=!0;else if(s==="--follow"||s==="-f")e.follow=!0;else if(s==="--lines"||s==="-n"){let o=parseInt(n[++r],10);(isNaN(o)||o<0)&&(console.error(`Invalid --lines value: ${n[r]}`),process.exit(1)),e.lines=o}else if(s==="--port"||s==="-p"){let o=n[++r],i=parseInt(o,10);isNaN(i)&&(console.error(`Invalid port: ${o}`),process.exit(1)),e.port=i}else if(s==="--replace"||s.startsWith("--replace=")){let o=s.startsWith("--replace=")?s.slice(10):n[++r]??"";try{let i=Kt(o);if(e.local)throw new Error(`--replace can only be used once (got '${e.local.name}' and '${i.name}')`);e.local=i}catch(i){console.error(i instanceof Error?i.message:String(i)),process.exit(1)}}else s.startsWith("-")||(e.file=s)}return e}function Zt(){console.log(`
3
+ typebulb - Local bulb runner for Typebulb
4
+
5
+ Usage:
6
+ typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
7
+ typebulb check [file.bulb.md] Type-check a bulb without running it
8
+ typebulb logs [file|pid] Print a running bulb server's captured console
9
+ (no arg: list running servers). For agents:
10
+ fetch tb.server.log / errors of a bulb you
11
+ launched without watching its terminal.
12
+ typebulb stop [file|pid] Stop a running bulb server (no arg: list them).
13
+ typebulb trust [file] Remember a bulb as Trusted, so a later run grants
14
+ fs/AI/server.ts without --trust (no arg: list the
15
+ remembered-trusted bulbs).
16
+ typebulb untrust <file> Forget a bulb's trust (back to Restricted).
17
+
18
+ Options:
19
+ -f, --follow Stream new log output until interrupted (logs)
20
+ -n, --lines <n> Print only the last n lines (logs)
21
+ --no-watch Disable hot reload (watch is on by default)
22
+ -p, --port <port> Use a specific port (default: 3000)
23
+ --no-open Don't auto-open browser
24
+ --trust Grant privileged capabilities (filesystem, AI,
25
+ and server.ts) for this run. Without it a bulb runs
26
+ sandboxed: tb.fs / tb.ai / tb.server are blocked and
27
+ the page shows the exact --trust command to unlock
28
+ them. A bulb remembered via 'typebulb trust' runs
29
+ trusted without this flag.
30
+ --no-trust Force Restricted for this run even if the bulb is
31
+ remembered-trusted (overrides the trust store).
32
+ --server Run server.ts only, no web server (needs --trust)
33
+ --replace <name>=<path> Replace a declared dependency with a local built
34
+ package folder instead of a CDN (dev only).
35
+ Applies to both run and check. Watched for
36
+ rebuilds under --watch; --no-watch freezes it.
37
+ e.g. --replace tensorgrad=../tensorgrad
38
+ -V, --version Show version number
39
+ -h, --help Show this help message
40
+
41
+ Filesystem API:
42
+ Bulbs can read and write local files via tb.fs:
43
+ await tb.fs.read('file.txt') // UTF-8 text (throws on non-UTF-8)
44
+ await tb.fs.readBytes('image.png') // raw bytes (Uint8Array)
45
+ await tb.fs.write('output.html', content) // text or bytes
46
+
47
+ Server API:
48
+ Add a **server.ts** section to run Node.js code server-side.
49
+ Exported functions become callable from the browser:
50
+ // in **server.ts**: export async function query(sql) { ... }
51
+ // in **code.tsx**: const rows = await tb.server.query(sql)
52
+ .env and .env.local are auto-loaded from the working directory.
53
+
54
+ Built-in server functions (available without a **server.ts** section):
55
+ tb.server.log(...) Print to the CLI's stdout
56
+
57
+ AI API:
58
+ Bulbs can call AI providers via tb.ai(). Set API keys in .env:
59
+ ANTHROPIC_API_KEY=sk-ant-...
60
+ OPENAI_API_KEY=sk-...
61
+ GOOGLE_API_KEY=AIza...
62
+ OPENROUTER_API_KEY=sk-or-...
63
+ Set provider and model (required):
64
+ TB_AI_PROVIDER=anthropic
65
+ TB_AI_MODEL=claude-haiku-4-5-20251001
66
+ Both can be overridden per-call: tb.ai({ provider: "openai", model: "gpt-4o", ... })
67
+ Optional reasoning depth (0=min, 1=low, 2=med, 3=max):
68
+ tb.ai({ ..., reasoning: 2 })
69
+
70
+ Examples:
71
+ typebulb my-editor.bulb.md
72
+ typebulb --no-watch --port 8080 my-editor.bulb.md
73
+ typebulb .
74
+ `)}import{readFileSync as bn}from"fs";import*as er from"path";function ct(){fe([".env",".env.local"],process.cwd(),!0)}function fe(n,e,t=!1){for(let r of n){let s=er.resolve(e,r);try{let o=bn(s,"utf-8");for(let i of o.split(`
75
+ `)){let a=i.trim();if(!a||a.startsWith("#"))continue;let c=a.indexOf("=");if(c===-1)continue;let l=a.slice(0,c).trim(),d=a.slice(c+1).trim();(d.startsWith('"')&&d.endsWith('"')||d.startsWith("'")&&d.endsWith("'"))&&(d=d.slice(1,-1)),process.env[l]??=d}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}import*as G from"fs/promises";import*as ce from"path";import{pathToFileURL as ns}from"url";var wn={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 tr(n){try{let e=n.split(`
76
+ `),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=vn(r);if(!s)return null;let o=new Map;for(;t<e.length;){let a=e[t]?.trim()?.match(/^\*\*(.+)\*\*$/);if(a){let c=a[1].trim();for(t++;t<e.length&&e[t]?.trim()==="";)t++;let l=e[t]?.match(/^(`{3,})(\w*)\s*$/);if(!l){t++;continue}let d=l[1];t++;let u=[];for(;t<e.length&&!e[t]?.match(new RegExp(`^${d}\\s*$`));)u.push(e[t]),t++;t++,o.set(c,u.join(`
77
+ `))}else t++}return{frontmatter:s,files:o}}catch{return null}}function vn(n){let e={};for(let t of n){let r=t.indexOf(":");if(r===-1)continue;let s=t.slice(0,r).trim(),o=t.slice(r+1).trim();switch(s){case"format":e.format=o;break;case"name":e.name=xn(o);break}}return!e.format?.startsWith("typebulb")||!e.name?null:e}function xn(n){return n.startsWith('"')&&n.endsWith('"')?n.slice(1,-1).replace(/\\"/g,'"'):n.startsWith("'")&&n.endsWith("'")?n.slice(1,-1):n}function rr(n){let e=t=>n.files.get(wn[t].path)||"";return{name:n.frontmatter.name,code:e("code"),css:e("css"),html:e("html"),config:e("config"),notes:e("notes"),data:e("data"),infer:e("infer"),insight:e("insight"),server:e("server")}}function Sn(n){try{return JSON.parse(n),!0}catch{}return!!(/^\s*<[\s\S]*>/.test(n)||/^---\s*$/m.test(n)||/^\w[\w\s]*:[ \t]/m.test(n))}function nr(n){let e=n.trim();return e?Sn(e)?[e]:n.split(/\n\n\n+/).map(t=>t.trim()).filter(Boolean):[]}function sr(n){if(!n.trim())return{};try{return JSON.parse(n)}catch{return{}}}import{transform as Pn}from"sucrase";function lt(n,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:r}=Pn(n,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:r}}catch(r){return{code:"",error:String(r)}}}var he="https://esm.sh",me="https://cdn.jsdelivr.net/npm/",dt="https://data.jsdelivr.com/v1/package/npm/";function or(n){let e=(n||"").replace(/^\/+/,"").replace(/\/+$/,"");return e?e.split("/"):[]}var y=class n{constructor(e,t,r){let s=typeof e=="string"?n.parse(e):e;this.name=s.name,this.version=re(t??s.version),this.subpath=re(r??s.subpath)}static parse(e){let t=or(e||"");if(!t.length)return new n({name:""});if(t[0].startsWith("@")){let s=t[0],[o,i]=ir(t[1]??""),a=re(t.slice(2).join("/"));return new n({name:`${s}/${o}`,version:i,subpath:a})}else{let[s,o]=ir(t[0]),i=re(t.slice(1).join("/"));return new n({name:s,version:o,subpath:i})}}static fromUrl(e){try{let t=new URL(e),r=new URL(he).host,s=new URL(me).host;if(t.host===r){let o=or(t.pathname.replace(/^\/v\d+\//,"/"));if(!o.length)return;let i=o[0].startsWith("@")?`${o[0]}/${o[1]??""}`:o[0];return n.parse(i)}if(t.host===s){let o=t.pathname.split("/npm/")[1];if(!o)return;let i=o.split("/")[0]||"";return n.parse(i)}return}catch{return}}static versionFromUrl(e){return n.fromUrl(e)?.version}format(){let e=this.version?`${this.name}@${this.version}`:this.name;return this.subpath?`${e}/${this.subpath}`:e}root(){return this.name}static rootOf(e){return n.parse(e).name}withVersion(e){return new n({name:this.name,version:re(e),subpath:this.subpath})}withPreferredVersion(e,t){let r=e||t;return r?this.withVersion(r):this}static isBare(e){if(!e||e.startsWith(".")||e.startsWith("/"))return!1;let t=e.toLowerCase();return!t.startsWith("http://")&&!t.startsWith("https://")}},re=n=>n&&n.length?n:void 0,ir=n=>{let e=n.indexOf("@");return e<0?[n,void 0]:[n.slice(0,e),re(n.slice(e+1))]};async function T(n){try{return await n()}catch{return}}var ge=class{constructor(e,t){this.cache=e,this.http=t,this.esmHost=he,this.jsDelivrBase=me,this.jsDelivrMeta=dt,this.pinMs=1e4,this.versionsIndexMs=1440*60*1e3,this.metaTtlMs=10080*60*1e3,this.pinCache=new Map}normalizeRelative(e){let t=e||"";return t.startsWith("./")?t.slice(2):t.replace(/^\/+/,"")}ensureLeadingDotSlash(e){return e.startsWith("./")?e:`./${e}`}baseDir(e){let t=typeof e=="string"?new y(e):e;return`${this.jsDelivrBase}${t.name}${t.version?`@${t.version}`:""}/`}file(e,t){return new URL(this.normalizeRelative(t),this.baseDir(e)).toString()}packageJson(e){return this.file(e,"package.json")}buildEsmUrl(e,t={}){let{target:r="es2022",bundle:s=!1,external:o}=t,i=new URLSearchParams({target:r});return s&&i.append("bundle",""),o?.length&&i.append("external",o.join(",")),`${this.esmHost}/${e}?${i.toString()}`}async pinEsmUrl(e,t="es2022"){let r=this.buildEsmUrl(e,{target:t}),s=await T(()=>this.http.head(r));return s?.ok?s.url||r:void 0}async resolveExactVersion(e){let t=Date.now(),r=this.pinCache.get(e);if(r&&t-r.ts<this.pinMs)return r.value;let s=await this.tryResolveFromUrls([this.buildEsmUrl(e),`${this.esmHost}/${e}`]);return this.pinCache.set(e,{value:s,ts:t}),s}async tryResolveFromUrls(e){for(let t of e){let r=await T(()=>this.http.head(t)),s=this.parseVersionFromUrl(r?.url||t);if(s)return s}}async fetchVersionsIndex(e){if(await this.cache.isNegative(e))return;let t=await this.cache.getIndex(e);if(t&&Date.now()-t.updatedAt<this.versionsIndexMs)return{versions:t.versions,distTags:t.distTags};let r=await T(()=>this.http.getJson(`${this.jsDelivrMeta}${encodeURIComponent(e)}`));if(!r?.versions?.length){await this.cache.recordNegative(e);return}await this.cache.clearNegative(e);let s=r.distTags&&Object.keys(r.distTags).length?r.distTags:void 0;return await this.cache.setIndex(e,r.versions,s),r}parseVersionFromUrl(e){let t=y.fromUrl(e)?.version;return t&&/\d+\.\d+\.\d+/.test(t)?t:void 0}async fetchPackageMeta(e,t){let r=await this.cache.getMeta(e,t);if(r&&Date.now()-r.updatedAt<this.metaTtlMs){let{dependencies:d,peerDependencies:u,peerDependenciesMeta:h}=r;return{name:e,version:t,dependencies:d,peerDependencies:u,peerDependenciesMeta:h}}let s=this.packageJson(new y(`${e}@${t}`)),o=await T(()=>this.http.getJson(s));if(!o)return;let i=d=>d&&Object.keys(d).length?d:void 0,a=i(o.dependencies),c=i(o.peerDependencies),l=i(o.peerDependenciesMeta);return await this.cache.setMeta(e,t,a,c,l),{name:e,version:t,dependencies:a,peerDependencies:c,peerDependenciesMeta:l}}};var ar=n=>n.startsWith("@types/"),ye=n=>Object.keys(n?.peerDependencies||{}).filter(e=>!ar(e)),ut=n=>Object.keys(n?.dependencies||{}).filter(e=>!ar(e)),Rn=n=>ye(n).filter(e=>!n?.peerDependenciesMeta?.[e]?.optional),be=class{constructor(e){this.cdn=e}async resolve(e,t){let r=await this.fetchMeta(e),{allRoots:s,autoAddedPeers:o}=await this.expandWithPeers(r,t),i=this.computeFlags(s);return{allRoots:s,flags:i,autoAddedPeers:o}}async fetchMeta(e){return Promise.all(e.map(async({name:t,version:r})=>({name:t,version:r,meta:await this.cdn.fetchPackageMeta(t,r)})))}async expandWithPeers(e,t){let r=new Map(e.map(o=>[o.name,o])),s=[];for(let o of e)for(let i of Rn(o.meta))!r.has(i)&&!s.some(a=>a.name===i)&&s.push({name:i,requiredBy:o.name});for(let{name:o,requiredBy:i}of s)try{let a=await t(o),c=await this.cdn.fetchPackageMeta(o,a);r.set(o,{name:o,version:a,meta:c})}catch(a){console.warn(`[typebulb] Failed to resolve peer "${o}" for "${i}":`,a)}return{allRoots:[...r.values()],autoAddedPeers:s.filter(o=>r.has(o.name))}}computeFlags(e){let t=new Set(e.flatMap(o=>ye(o.meta))),r=new Map;for(let o of e)for(let i of ut(o.meta))r.set(i,(r.get(i)||0)+1);let s=new Set([...r.entries()].filter(([,o])=>o>=2).map(([o])=>o));return new Map(e.map(o=>[o.name,{isPeerRoot:t.has(o.name),hasPeers:ye(o.meta).length>0,isSharedDep:s.has(o.name)}]))}};var we=class{constructor(e,t,r){this.cache=e,this.cdn=t,this.semver=r}selectVersionFromIndex(e,t,r){return this.semver.selectBestVersion(e,{range:t,distTags:r})}async learnExactVersion(e){let t=await T(()=>this.cdn.fetchVersionsIndex(e));if(t?.versions?.length){let r=this.semver.selectBestVersion(t.versions,{distTags:t.distTags});if(r)return r}return this.cdn.resolveExactVersion(e)}async resolveExactForRoot(e,t){if(!t)return this.learnExactVersion(e);let r=await this.cache.getPinnedExact(e,t);if(r){if(this.semver.isExactVersion(r))return r;console.warn("[versionResolver] Rejecting invalid cached version for",e,":",r)}let s=await T(()=>this.cdn.fetchVersionsIndex(e));if(s?.versions?.length){let i=this.selectVersionFromIndex(s.versions,t,s.distTags);if(i){if(this.semver.isExactVersion(i))return await this.cache.setPinnedExact(e,t,i),i}else{console.warn("[versionResolver] Invalidating stale versions cache for",e,"- range",t,"not satisfied"),await this.cache.invalidateVersionsCache(e);let a=await T(()=>this.cdn.fetchVersionsIndex(e));if(a?.versions?.length){let c=this.selectVersionFromIndex(a.versions,t,a.distTags);if(c&&this.semver.isExactVersion(c))return await this.cache.setPinnedExact(e,t,c),c}}}let o=await this.cdn.resolveExactVersion(`${e}@${t}`);if(o&&this.semver.isExactVersion(o))return await this.cache.setPinnedExact(e,t,o),o}async effectivePackage(e,t){let r=new y(e),s=r.root(),o=t[s],i=o?await T(()=>this.cache.getPinnedExact(s,o))??await T(()=>this.resolveExactForRoot(s,o)):void 0;return{effectivePackage:i?r.withVersion(i).format():e,root:s,range:o,pinned:i}}};import{init as En,parse as kn}from"es-module-lexer";var ne=class n{constructor(e,t,r,s){this.version=e,this.cdn=t,this.peer=r,this.cache=s}extractImportsSync(e){let t=new Set;for(let r of n.importPatterns){r.lastIndex=0;for(let s of e.matchAll(r))y.isBare(s[1])&&t.add(s[1])}return Array.from(t)}async extractImports(e){let t=new Set,r=s=>{y.isBare(s)&&t.add(s)};try{await En;let[s]=kn(e);s.forEach(o=>r(e.slice(o.s,o.e).trim()))}catch{return this.extractImportsSync(e)}return Array.from(t)}async buildImportMap(e,t,r){let s=(await this.extractImports(e)).filter(u=>!r?.has(y.rootOf(u))),o=[...new Set(s.map(y.rootOf))],i=await Promise.all(o.map(async u=>({name:u,version:await this.resolveVersion(u,t)}))),{allRoots:a,flags:c,autoAddedPeers:l}=await this.peer.resolve(i,u=>this.resolveVersion(u,t)),d=this.buildEntries([...s,...l.map(u=>u.name)],a,c,t);return{importMap:{imports:Object.fromEntries(d)},prefetchUrls:d.map(([,u])=>u)}}async resolveVersion(e,t){let r=t[e],s=r?`${e}@${r}`:e,o=await this.version.resolveExactForRoot(e,r);if(!o){let i=await T(()=>this.cdn.pinEsmUrl(s));if(!i)throw new Error(`Cannot resolve ${s}: no matching version is published (the package or version may not exist, or the registry was unreachable).`);o=y.versionFromUrl(i),o&&r&&await T(()=>this.cache.setPinnedExact(e,r,o))}if(!o)throw new Error(`Cannot resolve ${s}: no concrete version found.`);return o}buildEntries(e,t,r,s){let o=new Map(t.map(m=>[m.name,m])),i=m=>{let S=o.get(y.rootOf(m));return new y(m).withPreferredVersion(S.version,s[S.name]).format()},a=new Set([...r.entries()].filter(([,m])=>m.isPeerRoot||m.isSharedDep).map(([m])=>m)),c=new Set(e.filter(m=>m!==y.rootOf(m)).map(y.rootOf)),l=[],d=new Set,u=new Set(e.filter(m=>m===y.rootOf(m))),h=new Set;for(let m of e){let S=y.rootOf(m),O=o.get(S),{isPeerRoot:_,hasPeers:$,isSharedDep:p}=r.get(S),f=c.has(S),g=m!==S,w=!(_||p)&&(f||!$),C=this.singletonDepsOf(O,a),J=g&&u.has(S);J&&h.add(S);let L=J?[...C,S]:C.length?C:void 0;l.push([m,this.cdn.buildEsmUrl(i(m),{bundle:w,external:L})]),d.add(m)}let b=new Set([...a,...h]);for(let m of b)o.has(m)&&(d.has(m)||l.push([m,this.cdn.buildEsmUrl(i(m),{})]),l.push([`${m}/`,`${this.cdn.esmHost}/${i(m)}/`]));return l}singletonDepsOf(e,t){return[...new Set([...ye(e.meta),...ut(e.meta)])].filter(r=>t.has(r))}};ne.importPatterns=[/\bimport\s+(?:[^'";]*?from\s*)?['"]([^'"]+)['"]/g,/\bexport\s+[^'";]*?from\s*['"]([^'"]+)['"]/g];import{gt as cr,satisfies as Tn,maxSatisfying as pt,major as _n,prerelease as Cn,rsort as On,valid as In}from"semver";var Ne=class{cmp(e,t){return e===t?0:cr(e,t)?1:cr(t,e)?-1:0}satisfies(e,t){return!e||!e.trim()?!0:!!Tn(t,e,{includePrerelease:!0})}pickMaxSatisfying(e,t){if(!e?.length)return;let r=pt(e,t,{includePrerelease:!0});return r===null?void 0:r}pickLatest(e){return e?.length?On(e)[0]:void 0}selectBestVersion(e,t){if(!e?.length)return;let r=t?.range?.trim()||"*",s=t?.preferStable??!0,o=t?.distTags?.latest;if(o&&e.includes(o)&&this.satisfies(r,o))return o;if(s){let a=pt(e,r,{includePrerelease:!1});if(a)return a}return pt(e,r,{includePrerelease:!0})??void 0}majorOf(e){return _n(e)}isPrerelease(e){return Cn(e)!==null}isExactVersion(e){return In(e)!==null}},z=new Ne;function lr(n,e){let t=new ge(n,e),r=new be(t),s=new we(n,t,z);return{packageService:new ne(s,t,r,n),versionResolver:s,cdnClient:t,peerResolver:r}}import*as Rr from"fs/promises";import*as M from"path";var ft=[{name:"es5"},{name:"es2015.core"},{name:"es2015.collection"},{name:"es2015.promise"},{name:"es2015.iterable"},{name:"es2015.symbol"},{name:"es2015.symbol.wellknown"},{name:"es2015.generator"},{name:"es2015.proxy"},{name:"es2015.reflect"},{name:"es2016.array.include"},{name:"es2016.intl"},{name:"es2017.object"},{name:"es2017.string"},{name:"es2017.sharedmemory"},{name:"es2017.typedarrays"},{name:"es2017.date"},{name:"es2017.intl"},{name:"es2018.asynciterable"},{name:"es2018.asyncgenerator"},{name:"es2018.promise"},{name:"es2018.regexp"},{name:"es2018.intl"},{name:"es2019.array"},{name:"es2019.object"},{name:"es2019.string"},{name:"es2019.symbol"},{name:"es2019.intl"},{name:"es2020.bigint"},{name:"es2020.promise"},{name:"es2020.string"},{name:"es2020.sharedmemory"},{name:"es2020.date"},{name:"es2020.number"},{name:"es2020.symbol.wellknown"},{name:"es2020.intl"},{name:"es2021.promise"},{name:"es2021.string"},{name:"es2021.weakref"},{name:"es2021.intl"},{name:"es2022.array"},{name:"es2022.object"},{name:"es2022.error"},{name:"es2022.string"},{name:"es2022.regexp"},{name:"es2022.intl"},{name:"es2023.array"},{name:"es2023.collection"},{name:"es2023.intl",since:"5.5"},{name:"es2024.arraybuffer",since:"5.5"},{name:"es2024.collection",since:"5.5"},{name:"es2024.object",since:"5.5"},{name:"es2024.promise",since:"5.5"},{name:"es2024.regexp",since:"5.5"},{name:"es2024.sharedmemory",since:"5.5"},{name:"es2024.string",since:"5.5"},{name:"esnext.array",since:"5.5"},{name:"esnext.collection"},{name:"esnext.decorators"},{name:"esnext.disposable"},{name:"esnext.error",since:"5.5"},{name:"esnext.float16",since:"5.5"},{name:"esnext.iterator",since:"5.5"},{name:"esnext.object"},{name:"esnext.promise"},{name:"esnext.sharedmemory",since:"5.5"},{name:"esnext.intl"}],ht=[{name:"dom"},{name:"dom.iterable"},{name:"dom.asynciterable"}];var dr=`
5
78
  /**
6
79
  * Get raw data chunk from the Data tab.
7
80
  * @param index - Chunk index (0-based). Separate chunks with 2 blank lines.
@@ -12,7 +85,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
12
85
  * @param index - Chunk index (0-based)
13
86
  * @throws If chunk is not valid JSON/JSON-ish
14
87
  */
15
- json<T = unknown>(index: number): T;`,jt=`
88
+ json<T = unknown>(index: number): T;`,ur=`
16
89
  /**
17
90
  * Get the insight data produced by the inference layer.
18
91
  *
@@ -21,7 +94,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
21
94
  *
22
95
  * @returns The parsed insight JSON, or undefined if no insight is available
23
96
  */
24
- insight<T = unknown>(): T | undefined;`,Nt=`
97
+ insight<T = unknown>(): T | undefined;`,pr=`
25
98
  /**
26
99
  * General-purpose AI call.
27
100
  *
@@ -38,7 +111,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
38
111
  model?: string;
39
112
  /** Enable/disable web search. Default: on for BYOK, always off for free model. */
40
113
  webSearch?: boolean;
41
- }): Promise<{ text: string }>;`,Lt=`
114
+ }): Promise<{ text: string }>;`,fr=`
42
115
  /**
43
116
  * Returns AI models available to the current user.
44
117
  * Models are filtered by the user's configured API keys.
@@ -53,7 +126,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
53
126
  friendlyName: string;
54
127
  /** Provider display name, e.g. "Anthropic" */
55
128
  providerName: string;
56
- }>>;`,Br="\n /**\n * The bulb's theme override (`<html data-theme>`).\n *\n * - Get: the current override \u2014 `'dark'` | `'light'`, or `undefined` when\n * following the OS preference.\n * - Set `'dark'`/`'light'` to force and persist it (per-bulb); set\n * `undefined` to clear the override and follow the OS again.\n *\n * Drives `<html data-theme>`, so render off `html[data-theme=\"\u2026\"]` selectors\n * (or observe the attribute) rather than reading `tb.theme`.\n */\n theme: 'light' | 'dark' | undefined;",Bt=`
129
+ }>>;`,An="\n /**\n * The bulb's theme override (`<html data-theme>`).\n *\n * - Get: the current override \u2014 `'dark'` | `'light'`, or `undefined` when\n * following the OS preference.\n * - Set `'dark'`/`'light'` to force and persist it (per-bulb); set\n * `undefined` to clear the override and follow the OS again.\n *\n * Drives `<html data-theme>`, so render off `html[data-theme=\"\u2026\"]` selectors\n * (or observe the attribute) rather than reading `tb.theme`.\n */\n theme: 'light' | 'dark' | undefined;",hr=`
57
130
  /**
58
131
  * The mode this bulb is running in.
59
132
  *
@@ -63,7 +136,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
63
136
  * - \`'embedded'\` \u2014 Running as a bulb embedded inside another bulb (sandboxed,
64
137
  * client-only: AI, filesystem, and server RPC are unavailable)
65
138
  */
66
- mode: 'local' | 'editor' | 'published' | 'embedded';`,Ut=`
139
+ mode: 'local' | 'editor' | 'published' | 'embedded';`,mr=`
67
140
  /**
68
141
  * Local filesystem access (CLI only).
69
142
  *
@@ -77,7 +150,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
77
150
  readBytes(path: string): Promise<Uint8Array>;
78
151
  /** Write text or raw bytes to a file. Creates parent directories if needed. */
79
152
  write(path: string, content: string | Uint8Array): Promise<boolean>;
80
- };`,Ur=`
153
+ };`,Dn=`
81
154
  /**
82
155
  * Server-side function proxy. The built-in \`log\` prints to CLI stdout
83
156
  * (falls back to console.log on web). On the server side, this object only
@@ -85,7 +158,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
85
158
  */
86
159
  server: {
87
160
  log(...args: any[]): Promise<void>;
88
- };`,Wr=`
161
+ };`,$n=`
89
162
  /**
90
163
  * Async value inspector for tensor-like objects.
91
164
  *
@@ -152,7 +225,7 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
152
225
  *
153
226
  * @returns The full canonical URL
154
227
  */
155
- url(): Promise<string>;`,Hr=`
228
+ url(): Promise<string>;`,Fn=`
156
229
  /**
157
230
  * Server-side function proxy.
158
231
  *
@@ -160,23 +233,23 @@ import*as M from"fs/promises";import{readFileSync as Hn}from"fs";import*as S fro
160
233
  * \`tb.server.log(...)\` is a built-in that prints to CLI stdout (falls back to console.log on web).
161
234
  * User exports override built-ins of the same name.
162
235
  */
163
- server: Record<string, (...args: any[]) => Promise<any>>;`,rt=`
236
+ server: Record<string, (...args: any[]) => Promise<any>>;`,mt=`
164
237
  /**
165
238
  * Typebulb utilities namespace.
166
239
  * Type \`tb.\` to discover available helpers.
167
240
  */
168
- declare const tb: {${Ft}${Wr}${jt}${Hr}${Nt}${Ut}${Lt}${Br}${Bt}
241
+ declare const tb: {${dr}${$n}${ur}${Fn}${pr}${mr}${fr}${An}${hr}
169
242
  };
170
- `,nt=`
243
+ `,gt=`
171
244
  /**
172
245
  * Typebulb utilities namespace (server-side).
173
246
  * Type \`tb.\` to discover available helpers.
174
247
  */
175
- declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
248
+ declare const tb: {${dr}${ur}${pr}${mr}${Dn}${fr}${hr}
176
249
  };
177
- `;var z=class{constructor(e){this.store=e}async isNegative(e){let t=await De(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let r=((await De(()=>this.store.get(e)))?.attempts||0)+1;await De(()=>this.store.set(e,{until:Date.now()+Jr(r),attempts:r}))}async clearNegative(e){await De(()=>this.store.delete(e))}};function Jr(s){return Math.min(9e5*Math.pow(2,Math.max(0,s-1)),864e5)}async function De(s){try{return await s()}catch{return}}import Yr from"p-limit";import{resolve as Wt}from"resolve.exports";var re=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 J={maxRelativeTypeRefs:500,maxBareDeps:8,maxBareDepth:3,prefetchConcurrency:4,negativeTtlMs:1e4},me=["index.d.ts","index.d.mts"],fe=/\.d\.(ts|mts)$/i;function st(s){if(fe.test(s))return!0;try{return new URL(s,"file://").search.includes("dts")}catch{return s.includes("?")&&s.includes("dts")}}function Ae(s){return[`${s}.d.ts`,`${s}.d.mts`]}async function ge(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(Vr(a.status)&&n<e)continue;return a}catch{if(n<e)continue;return}finally{clearTimeout(o)}}}function Vr(s){return s===408||s===429||s>=500&&s<600}var ye=class extends re{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 ge(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([...me],t);if(!fe.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([...me,...r],t)}toResolutionResult(e){return{kind:fe.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let r=t||".",n=e;try{let i=this.extractPathFromResult(Wt(n,r,{conditions:["types"]}));if(i)return i}catch{}try{return this.extractPathFromResult(Wt(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=p=>this.fetchCandidateFrom(n,t.name,p);if(t.subpath){let p=this.cdnClient.ensureLeadingDotSlash(t.subpath),h=this.resolveExportsPath(r,p);if(h){let f=await this.resolveFromSelected(this.toResolutionResult(h),c);if(f)return{...f,resolvedPkg:a}}let w=await this.tryUntilSuccess(this.declarationCandidatesFor(p),c);if(w)return{...w,resolvedPkg:a}}let l=r.types??r.typings;if(l){let p=await this.resolveFromSelected({kind:"types",path:l},c);if(p)return{...p,resolvedPkg:o}}let d=this.resolveExportsPath(r,".");if(d){let p=await this.resolveFromSelected(this.toResolutionResult(d),c);if(p)return{...p,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[...me];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),r=Ae(t),n=t.endsWith("/")?t:`${t}/`;return r.push(...Ae(`${n}index`)),r}};import{gunzipSync as qr}from"fflate";var ne=class{async fetchAndExtract(e,t){let r=this.getTarballUrl(e,t),n=await ge(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=qr(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),l=n.decode(a.slice(0,c>0?c:100)).trim(),d=o.slice(124,136),p=n.decode(d).trim().replace(/\0/g,""),h=parseInt(p,8)||0,w=String.fromCharCode(o[156]);if(i+=512,(w==="0"||w==="\0")&&(l.endsWith(".d.ts")||l.endsWith(".d.mts"))){let f=r.slice(i,i+h);t.set(this.normalizeTarPath(l),n.decode(f))}i+=Math.ceil(h/512)*512}}catch{}return t}},Gr=new ne;var we=class extends re{constructor(e,t,r,n=new ne){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=G.majorOf(r),o=e.filter(a=>G.majorOf(a)===i);if(o.length)return o.sort((a,c)=>G.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 l=this.cdnClient.file(e,a);try{await this.cache.setCachedFile(l,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 be=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 Ht="file:///node_modules",ve=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`${Ht}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let r=zr(t);return`${Ht}/${this.epochDir()}/${e}/${r}`}};function zr(s){let e=s||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as Kr}from"lru-cache";function it(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 l=await fetch(n,{cache:"no-store"});if(!l.ok){l.status===404&&(e.set(n,Date.now()),await s.recordNegative(n));return}let d=await l.text(),p=l.url||n;return await s.clearNegative(n),await s.setCachedFile(p,d),{dts:d,url:p}})();return t.set(n,c),await c.finally(()=>t.delete(n))}catch{return}}}var Me=class{constructor(e){this.inFlight=new Map,this.scanner=new be,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=it(e.cache),this.typescriptProvider=new ye(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new we(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new ve}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>J.maxRelativeTypeRefs)))try{let a=new URL(t),c=new URL("./",a);o??(o=this.extractPackageRootUrl(a));let l=this.capArray(this.scanner.collectRelativeTypeRefs(e),J.maxRelativeTypeRefs);for(let d of l)await this.tryRelativeRef(d,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,l=st(c)?[c]:this.typescriptProvider.declarationCandidatesFor(c);for(let d of l){let h=new URL(d,a).toString();if(o.has(h))return;let w=await this.fetchDts(h);if(w?.dts){let f=this.toVirtualPath(r,new URL(w.url),n);this.pushFileIfNew(i,f,w.dts),await this.expandRelativeRefs(w.dts,w.url,n,i,o,r);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new g(e).name!==new g(t).name}ambientlyDeclares(e,t){for(let r of e.matchAll(/declare\s+module\s+['"]([^'"]+)['"]/g)){let n=r[1];if(n===t||n.endsWith("/*")&&t.startsWith(n.slice(0,-1)))return!0}return!1}markFileAmbient(e,t){let r=e.find(n=>n.path===t);r&&(r.ambient=!0)}async prefetchBareDeps(e,t,r,n,i){try{let o=this.capArray(this.scanner.collectBareModuleRefs(e),J.maxBareDeps).filter(l=>this.isDifferentPackage(l,t));if(!o.length)return;let a=new Set([t]),c=Yr(J.prefetchConcurrency);await Promise.all(o.map(l=>c(()=>this.prefetchBareDepsRecursive(l,r,n,J.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,l=this.virtualFs.pathForMain(c);this.pushFileIfNew(t,l,a.dts),this.ambientlyDeclares(a.dts,e)?this.markFileAmbient(t,l):r.push({module:e,path:l}),a.url&&await this.expandRelativeRefs(a.dts,a.url,c,t);let d=this.capArray(this.scanner.collectBareModuleRefs(a.dts),J.maxBareDeps).filter(p=>!i.has(p));for(let p of d)await this.prefetchBareDepsRecursive(p,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),l=c.version?`${c.name}@${c.version}`:c.name,{mainPath:d,packageRootUrl:p}=this.computeEntryPath(o,l),h=[{path:d,content:i}],w=[];o&&await this.expandRelativeRefs(i,o,l,h,void 0,p);let f=h.map($=>$.content).join(`
178
- `);await this.prefetchBareDeps(f,l,h,w,n);let R=c.format(),v=e===R?[e]:[e,R],k=v.some($=>this.ambientlyDeclares(i,$));return k?this.markFileAmbient(h,d):w.push(...v.map($=>({module:$,path:d}))),{pkg:e,mainPath:d,files:h,shims:w,ambient:k}}};function ot(s){return new Me(s)}import*as U from"fs/promises";import*as W from"path";import*as qt from"os";import*as at from"fs/promises";import*as Jt from"crypto";function F(s){return Jt.createHash("sha1").update(s).digest("hex")}async function K(s){try{return JSON.parse(await at.readFile(s,"utf8"))}catch{return}}async function $e(s){try{return await at.readFile(s,"utf8")}catch{return}}var Vt=1,V=W.join(qt.homedir(),".typebulb","cache"),xe=W.join(V,"packages"),Pe=W.join(V,"proxy"),Fe=W.join(V,"dts"),Xr=W.join(V,"emit"),ct;function P(){return ct||(ct=Qr()),ct}function je(s,e){return W.join(Xr,F(s),e)}async function Qr(){await U.mkdir(V,{recursive:!0});let s=W.join(V,"version.json");if((await Zr(s))?.version===Vt)return;let t=await U.readdir(V).catch(()=>[]);await Promise.all(t.map(r=>U.rm(W.join(V,r),{recursive:!0,force:!0}))),await U.writeFile(s,JSON.stringify({version:Vt})+`
179
- `,"utf8")}async function Zr(s){try{let e=await U.readFile(s,"utf8");return JSON.parse(e)}catch{return}}import*as q from"fs/promises";import*as Gt from"path";async function O(s,e){await q.mkdir(Gt.dirname(s),{recursive:!0});let t=`${s}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await q.writeFile(t,e,"utf8"),await q.rename(t,s).catch(async r=>{throw await q.rm(t,{force:!0}).catch(()=>{}),r})}var se=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=K(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 O(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var lt=j.join(xe,"indexes"),zt=j.join(xe,"pinned"),en=j.join(xe,"meta"),tn=j.join(xe,"negative.json"),ie=Symbol("missing"),Le=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new z(new se(tn));async getPinnedExact(e,t){let r=`${e}@${t}`,n=this.pinnedMem.get(r);if(n!==void 0)return n===ie?void 0:n;await P();let i=await $e(j.join(zt,F(r)+".txt"));return this.pinnedMem.set(r,i??ie),i}async setPinnedExact(e,t,r){let n=`${e}@${t}`;this.pinnedMem.set(n,r),await P(),await O(j.join(zt,F(n)+".txt"),r)}async getIndex(e){let t=this.indexMem.get(e);if(t!==void 0)return t===ie?void 0:t;await P();let r=await K(j.join(lt,Ne(e)+".json"));return this.indexMem.set(e,r??ie),r}async setIndex(e,t,r){let n={versions:t,distTags:r,updatedAt:Date.now()};this.indexMem.set(e,n),await P(),await O(j.join(lt,Ne(e)+".json"),JSON.stringify(n))}async invalidateVersionsCache(e){this.indexMem.delete(e),await Yt.rm(j.join(lt,Ne(e)+".json"),{force:!0})}async isNegative(e){return await P(),this.negativeCache.isNegative(e)}async recordNegative(e){await P(),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===ie?void 0:n;await P();let i=await K(Kt(e,t));return this.metaMem.set(r,i??ie),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 P(),await O(Kt(e,t),JSON.stringify(o))}};function Kt(s,e){return j.join(en,Ne(s),encodeURIComponent(e)+".json")}function Ne(s){return s.replace(/\//g,"__")}var Xt={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}}};var rn=new Le,{packageService:Be,versionResolver:Qt,cdnClient:Zt,peerResolver:Gi}=$t(rn,Xt);var er=`
250
+ `;var K=class{constructor(e){this.store=e}async isNegative(e){let t=await je(()=>this.store.get(e));return!!t&&t.until>Date.now()}async recordNegative(e){let r=((await je(()=>this.store.get(e)))?.attempts||0)+1;await je(()=>this.store.set(e,{until:Date.now()+Mn(r),attempts:r}))}async clearNegative(e){await je(()=>this.store.delete(e))}};function Mn(n){return Math.min(9e5*Math.pow(2,Math.max(0,n-1)),864e5)}async function je(n){try{return await n()}catch{return}}import Wn from"p-limit";import{resolve as gr}from"resolve.exports";var se=class{constructor(e){this.fetchDts=e}fetchDtsText(e){return this.tryUrls([e])}async tryUrls(e){for(let t of e){let r=await this.fetchDts(t);if(r&&(this.looksLikeDts(r.dts)||/\.(d\.ts|d\.mts)(?:[?#].*)?$/i.test(r.url)||/[?&]dts(?:[&#]|$)/i.test(r.url)))return r}}looksLikeDts(e){return/^\s*export\s*\{\s*\}\s*;?\s*$/m.test(e)?!0:/declare\s+(module|namespace|class|interface|function|const|var|let)/.test(e)||/interface\s+\w+/.test(e)||/type\s+\w+\s*=/.test(e)}};var H={maxRelativeTypeRefs:500,maxBareDeps:8,maxBareDepth:3,prefetchConcurrency:4,negativeTtlMs:1e4},ve=["index.d.ts","index.d.mts"],xe=/\.d\.(ts|mts)$/i;function yt(n){if(xe.test(n))return!0;try{return new URL(n,"file://").search.includes("dts")}catch{return n.includes("?")&&n.includes("dts")}}function Le(n){return[`${n}.d.ts`,`${n}.d.mts`]}async function Se(n,{retries:e=2,timeoutMs:t=15e3,init:r}={}){for(let s=0;s<=e;s++){let o=new AbortController,i=setTimeout(()=>o.abort(),t);try{let a=await fetch(n,{...r,signal:o.signal});if(Nn(a.status)&&s<e)continue;return a}catch{if(s<e)continue;return}finally{clearTimeout(i)}}}function Nn(n){return n===408||n===429||n>=500&&n<600}var Pe=class extends se{constructor(e,t){super(e),this.cdnClient=t}async loadPackageAtVersionedRoot(e,t){let r=this.cdnClient.packageJson(new y({name:e,version:t})),s=await Se(r);if(!s?.ok)return;let o;try{o=await s.json()}catch{return}if(o)return{pkg:o,baseDir:this.cdnClient.baseDir(new y({name:e,version:t??o.version})),version:t}}extractPathFromResult(e){if(typeof e=="string")return e;if(Array.isArray(e))return e.find(t=>typeof t=="string")}async tryUntilSuccess(e,t){for(let r of e){let s=await t(r);if(s)return s}}async resolveFromSelected(e,t){if(e.kind==="types"){let s=this.cdnClient.normalizeRelative(e.path);if(!s||s==="/"||s===".")return this.tryUntilSuccess([...ve],t);if(!xe.test(s)){let o=await this.tryUntilSuccess(this.declarationCandidatesFor(s),t);if(o)return o}return t(s)}let r=this.declarationCandidatesFor(e.path);return this.tryUntilSuccess([...ve,...r],t)}toResolutionResult(e){return{kind:xe.test(e)?"types":"probe",path:e}}resolveExportsPath(e,t){let r=t||".",s=e;try{let o=this.extractPathFromResult(gr(s,r,{conditions:["types"]}));if(o)return o}catch{}try{return this.extractPathFromResult(gr(s,r,{browser:!0,conditions:["import","default","module","browser","node"]}))}catch{return}}async resolve(e){try{let t=y.parse(e),{pkg:r,baseDir:s}=await this.loadPackageAtVersionedRoot(t.name,t.version)||{};if(!r||!s)return;let o={name:t.name,version:t.version},i=new y(o).format(),a=new y({...o,subpath:t.subpath}).format(),c=u=>this.fetchCandidateFrom(s,t.name,u);if(t.subpath){let u=this.cdnClient.ensureLeadingDotSlash(t.subpath),h=this.resolveExportsPath(r,u);if(h){let m=await this.resolveFromSelected(this.toResolutionResult(h),c);if(m)return{...m,resolvedPkg:a}}let b=await this.tryUntilSuccess(this.declarationCandidatesFor(u),c);if(b)return{...b,resolvedPkg:a}}let l=r.types??r.typings;if(l){let u=await this.resolveFromSelected({kind:"types",path:l},c);if(u)return{...u,resolvedPkg:i}}let d=this.resolveExportsPath(r,".");if(d){let u=await this.resolveFromSelected(this.toResolutionResult(d),c);if(u)return{...u,resolvedPkg:i}}return}catch{return}}async fetchCandidateFrom(e,t,r){let s=this.cdnClient.normalizeRelative(r),o=new URL(s,e).toString(),i=await this.fetchDtsText(o);return i?{dts:i.dts,url:i.url,resolvedPkg:t}:void 0}declarationCandidatesFor(e){if(!e||e==="./"||e==="/")return[...ve];let t=e.replace(/\.(mjs|cjs|js|mts|cts|ts)$/i,""),r=Le(t),s=t.endsWith("/")?t:`${t}/`;return r.push(...Le(`${s}index`)),r}};import{gunzipSync as jn}from"fflate";var oe=class{async fetchAndExtract(e,t){let r=this.getTarballUrl(e,t),s=await Se(r,{timeoutMs:3e4});if(!s?.ok)return new Map;let o=new Uint8Array(await s.arrayBuffer());return this.extractDtsFiles(o)}getTarballUrl(e,t){return`https://registry.npmjs.org/${e.replace("/","%2F")}/-/${e.split("/").pop()}-${t}.tgz`}normalizeTarPath(e){let t=e.replace(/^package\//,""),r=t.indexOf("/");return r>0?t.substring(r+1):t}extractDtsFiles(e){let t=new Map;try{let r=jn(e),s=new TextDecoder("utf-8"),o=0;for(;o<r.length-512;){let i=r.slice(o,o+512);if(i[0]===0)break;let a=i.slice(0,100),c=a.indexOf(0),l=s.decode(a.slice(0,c>0?c:100)).trim(),d=i.slice(124,136),u=s.decode(d).trim().replace(/\0/g,""),h=parseInt(u,8)||0,b=String.fromCharCode(i[156]);if(o+=512,(b==="0"||b==="\0")&&(l.endsWith(".d.ts")||l.endsWith(".d.mts"))){let m=r.slice(o,o+h);t.set(this.normalizeTarPath(l),s.decode(m))}o+=Math.ceil(h/512)*512}}catch{}return t}},Ln=new oe;var Re=class extends se{constructor(e,t,r,s=new oe){super(e),this.cdnClient=t,this.cache=r,this.tarballFetcher=s}typesNameCandidates(e){let t=e.startsWith("@")?e.slice(1).replace("/","__"):e;return t.includes(".")?[t,t.split(".").join("-"),t.split(".").join("")]:[t]}selectTypesVersion(e,t,r){try{if(r){let o=z.majorOf(r),i=e.filter(a=>z.majorOf(a)===o);if(i.length)return i.sort((a,c)=>z.cmp(c,a))[0]}let s=t?.latest;return s&&e.includes(s)?s:e[0]}catch{return e[0]}}async fetchFromVersionedRoot(e,t){let r=new y(e),s=r.version;if(!s)return;let o;try{o=await this.tarballFetcher.fetchAndExtract(r.name,s)}catch{return}if(!o||o.size===0)return;for(let[a,c]of o.entries()){let l=this.cdnClient.file(e,a);try{await this.cache.setCachedFile(l,c)}catch{}}let i=t.subpath?[t.subpath+".d.ts",t.subpath+"/index.d.ts"]:["index.d.ts"];for(let a of i){let c=o.get(a);if(c)return{dts:c,url:this.cdnClient.file(e,a),resolvedPkg:t.subpath?new y(t).format():t.name}}}async resolve(e){let t=y.parse(e);if(t.name)for(let r of this.typesNameCandidates(t.name)){let s=`@types/${r}`,o;try{o=await this.cdnClient.fetchVersionsIndex(s)}catch{continue}if(!o?.versions?.length)continue;let i=this.selectTypesVersion(o.versions,o.distTags,t.version),a=await this.fetchFromVersionedRoot(`${s}@${i}`,t);if(a)return a}}};var Ee=class{collectRelativeTypeRefs(e){return this.collectRefs(e).filter(t=>t.startsWith("./")||t.startsWith("../"))}collectBareModuleRefs(e){return this.collectRefs(e).filter(t=>this.isBare(t))}collectRefs(e){let t=new Set,r=(s,o)=>(t.add(s[o]),null);return this.matchAll(e,/(import|export)\s+[^'"\n]*from\s*['"]([^'"\n]+)['"]/,s=>r(s,2)),this.matchAll(e,/export\s*\*\s*from\s*['"]([^'"\n]+)['"]/,s=>r(s,1)),Array.from(t)}matchAll(e,t,r){let s=[];try{let o=new RegExp(t.source,"g"),i;for(;i=o.exec(e);){let a=r(i);a!==null&&s.push(a)}}catch{}return s}isBare(e){return!(e.startsWith("./")||e.startsWith("../")||e.startsWith("file:")||e.startsWith("http://")||e.startsWith("https://"))}};var yr="file:///node_modules",ke=class{constructor(){this.epoch=0,this.listeners=new Set}getEpoch(){return this.epoch}bumpEpoch(){this.epoch+=1;for(let e of this.listeners)try{e(this.epoch)}catch{}return this.epoch}onEpochChange(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}epochDir(){return`__tsepoch_${this.epoch}`}pathForMain(e){return`${yr}/${this.epochDir()}/${e}/index.d.ts`}pathFor(e,t){let r=Bn(t);return`${yr}/${this.epochDir()}/${e}/${r}`}};function Bn(n){let e=n||"";return e.startsWith("./")?e.slice(2):e.replace(/^\/+/,"")}import{LRUCache as Un}from"lru-cache";function bt(n){let e=new Un({ttl:1e4,max:500}),t=new Map;return async function(s){try{if(await n.isNegative(s))return;let o=e.get(s);if(o&&Date.now()-o<1e4)return;let i=await n.getCachedFile(s);if(i)return{dts:i,url:s};let a=t.get(s);if(a)return a;let c=(async()=>{let l=await fetch(s,{cache:"no-store"});if(!l.ok){l.status===404&&(e.set(s,Date.now()),await n.recordNegative(s));return}let d=await l.text(),u=l.url||s;return await n.clearNegative(s),await n.setCachedFile(u,d),{dts:d,url:u}})();return t.set(s,c),await c.finally(()=>t.delete(s))}catch{return}}}var Be=class{constructor(e){this.inFlight=new Map,this.scanner=new Ee,this.cache=e.cache,this.cdnClient=e.cdnClient,this.versionResolver=e.versionResolver,this.packageService=e.packageService,this.fetchDts=bt(e.cache),this.typescriptProvider=new Pe(this.fetchDts,e.cdnClient),this.definitelyTypedProvider=new Re(this.fetchDts,e.cdnClient,e.cache),this.virtualFs=new ke}withInFlight(e,t){let r=this.inFlight.get(e);if(r)return r;let s=t().finally(()=>this.inFlight.delete(e));return this.inFlight.set(e,s),s}invalidate(){this.virtualFs.bumpEpoch(),this.inFlight.clear()}capArray(e,t){return e.length<=t?e:e.slice(0,t)}pushFileIfNew(e,t,r){e.some(s=>s.path===t)||e.push({path:t,content:r})}createStubDef(e){let t=this.virtualFs.pathForMain(e);return{pkg:e,mainPath:t,files:[{path:t,content:"export const _shim: any; export default _shim;"}],shims:[{module:e,path:t}]}}async trySubpathWithRootFallback(e,t){let r=new y(e);return r.subpath?this.fetchRootDts(r.name,t):void 0}async fetchViaProviders(e){for(let t of[this.typescriptProvider,this.definitelyTypedProvider])try{let r=await t.resolve(e);if(r?.dts)return r}catch{}}subpathsMatch(e,t){return new y(e).subpath===new y(t).subpath}async fetchRootDts(e,t){let{effectivePackage:r,root:s,pinned:o}=await this.versionResolver.effectivePackage(e,t),i=await this.cache.getCachedDts(r);if(i?.content){let c=i.url??this.cdnClient.file(o?`${s}@${o}`:s,"index.d.ts");return{dts:i.content,url:c,resolvedPkg:r}}let a;try{a=await this.fetchViaProviders(r)}catch{return}if(!(!a?.dts||!a.url)){try{await this.cache.setCachedFile(a.url,a.dts)}catch{}if(this.subpathsMatch(r,a.resolvedPkg||r)){try{await this.cache.setCachedDts(r,a.dts,a.url)}catch{}return a}}}extractPackageRootUrl(e){let t=e.pathname.match(/^(.+@[^/]+\/)/);return t?new URL(t[1],e.origin):new URL("./",e)}toVirtualPath(e,t,r){let s=t.pathname.startsWith(e.pathname)?t.pathname.slice(e.pathname.length):`__deps__/${encodeURIComponent(t.toString()).replace(/%/g,"_")}.d.ts`;return this.virtualFs.pathFor(r,s)}computeEntryPath(e,t){if(!e)return{mainPath:this.virtualFs.pathForMain(t),packageRootUrl:void 0};let r=new URL(e),s=this.extractPackageRootUrl(r);return{mainPath:this.toVirtualPath(s,r,t),packageRootUrl:s}}async expandRelativeRefs(e,t,r,s,o=new Set,i){if(!o.has(t)&&(o.add(t),!(o.size>H.maxRelativeTypeRefs)))try{let a=new URL(t),c=new URL("./",a);i??(i=this.extractPackageRootUrl(a));let l=this.capArray(this.scanner.collectRelativeTypeRefs(e),H.maxRelativeTypeRefs);for(let d of l)await this.tryRelativeRef(d,c,i,r,s,o)}catch{}}async tryRelativeRef(e,t,r,s,o,i){try{let a=new URL(e,t),c=a.pathname+a.search,l=yt(c)?[c]:this.typescriptProvider.declarationCandidatesFor(c);for(let d of l){let h=new URL(d,a).toString();if(i.has(h))return;let b=await this.fetchDts(h);if(b?.dts){let m=this.toVirtualPath(r,new URL(b.url),s);this.pushFileIfNew(o,m,b.dts),await this.expandRelativeRefs(b.dts,b.url,s,o,i,r);return}}}catch{}}isDifferentPackage(e,t){return e===t?!1:new y(e).name!==new y(t).name}ambientlyDeclares(e,t){for(let r of e.matchAll(/declare\s+module\s+['"]([^'"]+)['"]/g)){let s=r[1];if(s===t||s.endsWith("/*")&&t.startsWith(s.slice(0,-1)))return!0}return!1}markFileAmbient(e,t){let r=e.find(s=>s.path===t);r&&(r.ambient=!0)}async prefetchBareDeps(e,t,r,s,o){try{let i=this.capArray(this.scanner.collectBareModuleRefs(e),H.maxBareDeps).filter(l=>this.isDifferentPackage(l,t));if(!i.length)return;let a=new Set([t]),c=Wn(H.prefetchConcurrency);await Promise.all(i.map(l=>c(()=>this.prefetchBareDepsRecursive(l,r,s,H.maxBareDepth,a,o).catch(()=>{}))))}catch{}}async prefetchBareDepsRecursive(e,t,r,s,o,i){if(s<=0||o.has(e))return;o.add(e);let a=await this.fetchRootDts(e,i);if(!a?.dts)return;let c=a.resolvedPkg||e,l=this.virtualFs.pathForMain(c);this.pushFileIfNew(t,l,a.dts),this.ambientlyDeclares(a.dts,e)?this.markFileAmbient(t,l):r.push({module:e,path:l}),a.url&&await this.expandRelativeRefs(a.dts,a.url,c,t);let d=this.capArray(this.scanner.collectBareModuleRefs(a.dts),H.maxBareDeps).filter(u=>!o.has(u));for(let u of d)await this.prefetchBareDepsRecursive(u,t,r,s-1,o,i)}async resolve(e,t,r){let s=await this.packageService.extractImports(e),o=r?[...s,...r]:s;return(await Promise.all(o.map(a=>this.resolveOne(a,t)))).filter(a=>!!a)}async resolveOne(e,t){let{effectivePackage:r}=await this.versionResolver.effectivePackage(e,t);return this.withInFlight(r,async()=>{let s=await this.fetchRootDts(e,t)??await this.trySubpathWithRootFallback(e,t);return s?this.buildDefFromContent(e,s,s.resolvedPkg||e,t):this.createStubDef(e)})}async buildDefFromContent(e,t,r,s){let{dts:o,url:i,resolvedPkg:a}=t,c=new y(a||r),l=c.version?`${c.name}@${c.version}`:c.name,{mainPath:d,packageRootUrl:u}=this.computeEntryPath(i,l),h=[{path:d,content:o}],b=[];i&&await this.expandRelativeRefs(o,i,l,h,void 0,u);let m=h.map($=>$.content).join(`
251
+ `);await this.prefetchBareDeps(m,l,h,b,s);let S=c.format(),O=e===S?[e]:[e,S],_=O.some($=>this.ambientlyDeclares(o,$));return _?this.markFileAmbient(h,d):b.push(...O.map($=>({module:$,path:d}))),{pkg:e,mainPath:d,files:h,shims:b,ambient:_}}};function wt(n){return new Be(n)}import*as B from"fs/promises";import*as U from"path";import*as vr from"os";import*as vt from"fs/promises";import*as br from"crypto";function F(n){return br.createHash("sha1").update(n).digest("hex")}async function Y(n){try{return JSON.parse(await vt.readFile(n,"utf8"))}catch{return}}async function Ue(n){try{return await vt.readFile(n,"utf8")}catch{return}}var wr=1,V=U.join(vr.homedir(),".typebulb","cache"),Te=U.join(V,"packages"),_e=U.join(V,"proxy"),We=U.join(V,"dts"),Jn=U.join(V,"emit"),xt;function x(){return xt||(xt=Hn()),xt}function Je(n,e){return U.join(Jn,F(n),e)}async function Hn(){await B.mkdir(V,{recursive:!0});let n=U.join(V,"version.json");if((await Vn(n))?.version===wr)return;let t=await B.readdir(V).catch(()=>[]);await Promise.all(t.map(r=>B.rm(U.join(V,r),{recursive:!0,force:!0}))),await B.writeFile(n,JSON.stringify({version:wr})+`
252
+ `,"utf8")}async function Vn(n){try{let e=await B.readFile(n,"utf8");return JSON.parse(e)}catch{return}}import*as q from"fs/promises";import*as xr from"path";async function I(n,e){await q.mkdir(xr.dirname(n),{recursive:!0});let t=`${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;await q.writeFile(t,e,"utf8"),await q.rename(t,n).catch(async r=>{throw await q.rm(t,{force:!0}).catch(()=>{}),r})}var ie=class{constructor(e){this.filePath=e}mem;loadPromise;load(){return this.mem?Promise.resolve(this.mem):(this.loadPromise||(this.loadPromise=Y(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 I(this.filePath,JSON.stringify(Object.fromEntries(e)))}};var St=M.join(Te,"indexes"),Sr=M.join(Te,"pinned"),qn=M.join(Te,"meta"),Gn=M.join(Te,"negative.json"),ae=Symbol("missing"),Ve=class{pinnedMem=new Map;indexMem=new Map;metaMem=new Map;negativeCache=new K(new ie(Gn));async getPinnedExact(e,t){let r=`${e}@${t}`,s=this.pinnedMem.get(r);if(s!==void 0)return s===ae?void 0:s;await x();let o=await Ue(M.join(Sr,F(r)+".txt"));return this.pinnedMem.set(r,o??ae),o}async setPinnedExact(e,t,r){let s=`${e}@${t}`;this.pinnedMem.set(s,r),await x(),await I(M.join(Sr,F(s)+".txt"),r)}async getIndex(e){let t=this.indexMem.get(e);if(t!==void 0)return t===ae?void 0:t;await x();let r=await Y(M.join(St,He(e)+".json"));return this.indexMem.set(e,r??ae),r}async setIndex(e,t,r){let s={versions:t,distTags:r,updatedAt:Date.now()};this.indexMem.set(e,s),await x(),await I(M.join(St,He(e)+".json"),JSON.stringify(s))}async invalidateVersionsCache(e){this.indexMem.delete(e),await Rr.rm(M.join(St,He(e)+".json"),{force:!0})}async isNegative(e){return await x(),this.negativeCache.isNegative(e)}async recordNegative(e){await x(),await this.negativeCache.recordNegative(e)}async clearNegative(e){await this.negativeCache.clearNegative(e)}async getMeta(e,t){let r=`${e}@${t}`,s=this.metaMem.get(r);if(s!==void 0)return s===ae?void 0:s;await x();let o=await Y(Pr(e,t));return this.metaMem.set(r,o??ae),o}async setMeta(e,t,r,s,o){let i={dependencies:r,peerDependencies:s,peerDependenciesMeta:o,updatedAt:Date.now()};this.metaMem.set(`${e}@${t}`,i),await x(),await I(Pr(e,t),JSON.stringify(i))}};function Pr(n,e){return M.join(qn,He(n),encodeURIComponent(e)+".json")}function He(n){return n.replace(/\//g,"__")}var Er={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}}};var zn=new Ve,{packageService:qe,versionResolver:kr,cdnClient:Tr,peerResolver:ea}=lr(zn,Er);var _r=`
180
253
  (() => {
181
254
  // Embedded (bulb-in-a-bulb): runs inside a sandboxed iframe with no parent
182
255
  // bridge, so privileged tb.* (AI, fs, server RPC) can't reach a host and would
@@ -210,6 +283,9 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
210
283
  // The server returns raw bytes (no JSON envelope); read() decodes as UTF-8.
211
284
  const failIfNotOk = async (resp, action, path) => {
212
285
  if (resp.ok) return;
286
+ // The trust gate denies privileged routes with a plain-text 403 naming --trust;
287
+ // surface that as-is rather than a JSON-parse miss on a non-JSON body.
288
+ if (resp.status === 403) throw new Error((await resp.text().catch(() => '')) || 'tb.fs is blocked \u2014 re-run with --trust');
213
289
  const err = await resp.json().catch(() => ({}));
214
290
  throw new Error(err.error || 'Failed to ' + action + ' file: ' + path);
215
291
  };
@@ -254,6 +330,23 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
254
330
  }
255
331
  };
256
332
 
333
+ // Diagnostic logging (tb.server.log). Routes to the UNGATED /__log endpoint, which only ever
334
+ // runs the server's built-in console.log \u2014 never a user server.ts export \u2014 so it crosses no
335
+ // capability boundary and works even on a Restricted (untrusted) bulb (the FAQ's recommended
336
+ // debugging path). Embedded bulbs have no host, and any transport failure degrades to the page's
337
+ // own console: a diagnostic log must never throw or block.
338
+ const serverLog = async (...args) => {
339
+ if (isEmbedded) { console.log(...args); return; }
340
+ try {
341
+ const resp = await fetch('/__log', {
342
+ method: 'POST',
343
+ headers: { 'Content-Type': 'application/json' },
344
+ body: JSON.stringify({ args })
345
+ });
346
+ if (!resp.ok) console.log(...args);
347
+ } catch { console.log(...args); }
348
+ };
349
+
257
350
  // tb namespace
258
351
  globalThis.tb = Object.freeze({
259
352
  data: (index) => getData()[index],
@@ -278,6 +371,7 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
278
371
  headers: { 'Content-Type': 'application/json' },
279
372
  body: JSON.stringify({ messages, system, reasoning, provider, model, webSearch })
280
373
  });
374
+ if (resp.status === 403) throw new Error((await resp.text().catch(() => '')) || 'tb.ai() is blocked \u2014 re-run with --trust');
281
375
  const data = await resp.json();
282
376
  if (!resp.ok) {
283
377
  const err = new Error(data.message || 'tb.ai() call failed');
@@ -324,14 +418,19 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
324
418
  headers: { 'Content-Type': 'application/json' },
325
419
  body: JSON.stringify({ args })
326
420
  });
421
+ if (resp.status === 403) throw new Error((await resp.text().catch(() => '')) || ('tb.server.' + name + '() is blocked \u2014 re-run with --trust'));
327
422
  const data = await resp.json();
328
423
  if (!resp.ok) throw new Error(data.error || 'API call failed');
329
424
  return data.result;
330
425
  },
331
426
 
332
- // Server proxy - tb.server.fn(...) delegates to tb.api('fn', ...)
427
+ // Server proxy - tb.server.fn(...) delegates to tb.api('fn', ...). 'log' is special: it's the
428
+ // ungated diagnostic (serverLog -> /__log, built-in only), so it prints untrusted; everything
429
+ // else is a gated /__api call into the bulb's own server.ts.
333
430
  server: new Proxy({}, {
334
- get: (_, name) => (...args) => globalThis.tb.api(name, ...args)
431
+ get: (_, name) => name === 'log'
432
+ ? (...args) => serverLog(...args)
433
+ : (...args) => globalThis.tb.api(name, ...args)
335
434
  }),
336
435
 
337
436
  // Filesystem - local CLI extension
@@ -360,12 +459,12 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
360
459
  };
361
460
  }
362
461
  })();
363
- `;function tr(s){let{name:e,code:t,css:r,html:n,data:i,insight:o,importMap:a,watch:c,theme:l,trustHint:d}=s,p=n.trim()||'<div id="app"></div>',h=f=>f.replace(/<\/script/gi,"<\\/script"),w={imports:sn(a.imports)};return`<!DOCTYPE html>
462
+ `;function Cr(n){let{name:e,code:t,css:r,html:s,data:o,insight:i,importMap:a,watch:c,theme:l}=n,d=s.trim()||'<div id="app"></div>',u=b=>b.replace(/<\/script/gi,"<\\/script"),h={imports:Xn(a.imports)};return`<!DOCTYPE html>
364
463
  <html>
365
464
  <head>
366
465
  <meta charset="utf-8">
367
466
  <meta name="viewport" content="width=device-width, initial-scale=1">
368
- <title>${dt(e)} - typebulb</title>
467
+ <title>${Yn(e)} - typebulb</title>
369
468
  <script>
370
469
  // Theme engine. Sets html[data-theme] before stylesheets paint (no flash) and
371
470
  // exposes the tb.theme accessor via window.__tbTheme. The override is persisted
@@ -373,13 +472,13 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
373
472
  // toggles the effective theme. See Specs/Theme.md.
374
473
  (function() {
375
474
  try {
376
- var KEY = ${h(JSON.stringify("tb-theme:"+e))};
475
+ var KEY = ${u(JSON.stringify("tb-theme:"+e))};
377
476
  var doc = document.documentElement;
378
477
  var mq = window.matchMedia('(prefers-color-scheme: dark)');
379
478
  var os = function() { return mq.matches ? 'dark' : 'light'; };
380
479
  // A host-forced theme (bulb-in-a-bulb) outranks the OS but not an explicit
381
480
  // in-iframe override, so the user can still toggle the embed independently.
382
- var FORCED = ${h(JSON.stringify(l??null))};
481
+ var FORCED = ${u(JSON.stringify(l??null))};
383
482
  var stored = function() {
384
483
  try { var v = localStorage.getItem(KEY); return (v === 'dark' || v === 'light') ? v : undefined; }
385
484
  catch (e) { return undefined; }
@@ -410,7 +509,7 @@ declare const tb: {${Ft}${jt}${Nt}${Ut}${Ur}${Lt}${Bt}
410
509
  })();
411
510
  </script>
412
511
  <script type="importmap">
413
- ${JSON.stringify(w,null,2)}
512
+ ${JSON.stringify(h,null,2)}
414
513
  </script>
415
514
  <style>
416
515
  /* Reset and base styles */
@@ -424,180 +523,102 @@ ${r}
424
523
  </style>
425
524
  </head>
426
525
  <body>
427
- ${p}
526
+ ${d}
428
527
 
429
- ${i.length>0?`<script>window.__TB_DATA__ = ${h(JSON.stringify(i))};</script>`:""}
430
- ${o?`<script>window.__TB_INSIGHT__ = ${h(JSON.stringify(o))};</script>`:""}
528
+ ${o.length>0?`<script>window.__TB_DATA__ = ${u(JSON.stringify(o))};</script>`:""}
529
+ ${i?`<script>window.__TB_INSIGHT__ = ${u(JSON.stringify(i))};</script>`:""}
431
530
  ${c?"<script>window.__TYPEBULB_WATCH__ = true;</script>":""}
432
- ${d?`<script>window.__TB_EMBED_ERR__ = function (name) { return name + ' is blocked in sandboxed mode. Re-run with --trust to allow it:\\n ' + ${h(JSON.stringify(d))}; };</script>`:""}
433
531
 
434
532
  <script>
435
- ${er}
533
+ ${_r}
436
534
  </script>
437
535
 
438
- ${nn}
536
+ ${Kn}
439
537
 
440
538
  <script type="module">
441
- ${h(t)}
539
+ ${u(t)}
442
540
  </script>
443
541
  </body>
444
- </html>`}var nn=`<script>
542
+ </html>`}var Kn=`<script>
445
543
  (function () {
446
544
  if (window.parent === window) return;
447
- // Embedded: the host iframe owns sizing (auto-height below), so the document
448
- // must not scroll itself \u2014 otherwise sub-pixel rounding (the frame landing a
449
- // fraction shorter than content) leaves a phantom scrollbar. scrollHeight still
450
- // reports true content, so this is invisible to auto-height. A +1px report buffer
451
- // would seem simpler but runs away on full-bleed (height:100%) bulbs.
452
- document.documentElement.style.overflow = 'hidden';
545
+ var de = document.documentElement;
453
546
  var post = function (m) { try { parent.postMessage(m, '*'); } catch (e) {} };
454
- var sendHeight = function () {
455
- post({ __typebulbEmbed: true, kind: 'height', height: Math.ceil(document.documentElement.scrollHeight) });
547
+ // Overflow tracks fit, per axis. While content fits the frame, HIDE overflow: the
548
+ // sub-pixel gap (frame a fraction shorter than content) would otherwise flash a
549
+ // phantom scrollbar, and a full-bleed (height:100%) bulb \u2014 whose content equals the
550
+ // frame \u2014 must not scroll itself. When the host CAPS the frame (claude.bulb's inline
551
+ // mode caps height to a fraction of the viewport; a prose-column frame caps width),
552
+ // the content genuinely overflows, so ALLOW scroll on that axis to keep it reachable.
553
+ // Reported height is body.scrollHeight \u2014 the content's intrinsic extent: below the
554
+ // viewport for a short bulb (so the frame shrinks to it), tracking the frame for a
555
+ // full-bleed one (so it self-stabilises at the host's initial height).
556
+ //
557
+ // Coalesce to one rAF and only write an overflow value that actually changed: setting
558
+ // overflow adds/removes a scrollbar, which resizes the element and re-fires the
559
+ // observer \u2014 writing unconditionally ping-pongs (the "ResizeObserver loop" warning).
560
+ // The rAF + equality guard let it settle within a frame instead.
561
+ var raf = 0;
562
+ var apply = function () {
563
+ raf = 0;
564
+ var oy = de.scrollHeight > de.clientHeight + 1 ? 'auto' : 'hidden';
565
+ var ox = de.scrollWidth > de.clientWidth + 1 ? 'auto' : 'hidden';
566
+ if (de.style.overflowY !== oy) de.style.overflowY = oy;
567
+ if (de.style.overflowX !== ox) de.style.overflowX = ox;
568
+ post({ __typebulbEmbed: true, kind: 'height', height: Math.ceil(document.body.scrollHeight) });
456
569
  };
570
+ var update = function () { if (!raf) raf = requestAnimationFrame(apply); };
571
+ de.style.overflow = 'hidden';
457
572
  window.addEventListener('error', function (e) {
458
- post({ __typebulbEmbed: true, kind: 'error', message: String((e && e.message) || (e && e.error) || 'Error') });
573
+ var m = String((e && e.message) || (e && e.error) || 'Error');
574
+ // The benign "ResizeObserver loop completed\u2026" notice surfaces as a window error in
575
+ // some browsers; it's not a bulb fault, so don't forward it to the host as one.
576
+ if (m.indexOf('ResizeObserver') !== -1) return;
577
+ post({ __typebulbEmbed: true, kind: 'error', message: m });
459
578
  });
460
579
  window.addEventListener('unhandledrejection', function (e) {
461
580
  var r = e && e.reason;
462
581
  var msg = r && r.message ? r.message : (r == null ? 'Unhandled rejection' : r);
463
582
  post({ __typebulbEmbed: true, kind: 'error', message: String(msg) });
464
583
  });
465
- window.addEventListener('load', sendHeight);
466
- if (window.ResizeObserver) { try { new ResizeObserver(sendHeight).observe(document.documentElement); } catch (e) {} }
467
- })();
468
- </script>`;function rr(s){let{bulbHtml:e,name:t,watch:r}=s;return`<!DOCTYPE html>
469
- <html>
470
- <head>
471
- <meta charset="utf-8">
472
- <meta name="viewport" content="width=device-width, initial-scale=1">
473
- <title>${dt(t)} - typebulb</title>
474
- <style>
475
- *, *::before, *::after { box-sizing: border-box; }
476
- body { margin: 0; }
477
- /* The frame paints its own themed background and fills the viewport, so the
478
- host backdrop shows only at sub-pixel edges / behind the denial bar.
479
- color-scheme: light dark lets that backdrop and the scrollbar follow the OS
480
- with no script \u2014 the bulb's own theme engine (template head) is unaffected. */
481
- html { color-scheme: light dark; }
482
- /* The frame auto-grows to content (height messages below); min-height keeps a
483
- short bulb filling the viewport so it reads as a page, not a widget. */
484
- #tb-frame { display: block; width: 100%; min-height: 100dvh; border: 0; }
485
- #tb-deny {
486
- position: fixed; left: 0; right: 0; bottom: 0; z-index: 2147483647;
487
- margin: 0; padding: 10px 14px; font: 13px/1.5 system-ui, -apple-system, sans-serif;
488
- white-space: pre-wrap; background: #7f1d1d; color: #fff;
489
- border-top: 1px solid #b91c1c; display: none;
584
+ // Run at load (module mounted \u2192 real content, not the empty pre-mount body that would
585
+ // collapse the frame and snap back). Observe BOTH body (content growth) and the root
586
+ // element (the viewport \u2014 so a host resize/cap re-syncs overflow on the next frame).
587
+ window.addEventListener('load', function () {
588
+ update();
589
+ if (window.ResizeObserver) {
590
+ try { var ro = new ResizeObserver(update); ro.observe(document.body); ro.observe(de); } catch (e) {}
490
591
  }
491
- </style>
492
- </head>
493
- <body>
494
- <iframe id="tb-frame" sandbox="allow-scripts" srcdoc="${dt(e)}"></iframe>
495
- <pre id="tb-deny"></pre>
496
- <script>
497
- (function () {
498
- var frame = document.getElementById('tb-frame');
499
- var deny = document.getElementById('tb-deny');
500
- // Authenticate by window identity, not origin (opaque-origin frames post
501
- // from 'null'). Treat the payload as untrusted: clamp height, render error
502
- // text only (never HTML).
503
- window.addEventListener('message', function (e) {
504
- if (e.source !== frame.contentWindow) return;
505
- var d = e.data;
506
- if (!d || d.__typebulbEmbed !== true) return;
507
- if (d.kind === 'height' && typeof d.height === 'number' && Number.isFinite(d.height)) {
508
- frame.style.height = Math.max(0, Math.min(100000, Math.ceil(d.height))) + 'px';
509
- } else if (d.kind === 'error') {
510
- deny.textContent = '\u26A0 ' + String(d.message == null ? 'error' : d.message);
511
- deny.style.display = 'block';
512
- }
513
- });
514
- ${r?`var es = new EventSource('/__reload');
515
- es.addEventListener('reload', function () { location.reload(); });
516
- es.onerror = function () { es.close(); };`:""}
517
- })();
518
- </script>
519
- </body>
520
- </html>`}function dt(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function sn(s){let e={};for(let[t,r]of Object.entries(s))e[t]=r.startsWith("https://")?"/proxy/"+r:r;return e}import{Hono as an}from"hono";import{serve as cn}from"@hono/node-server";import{streamSSE as ln}from"hono/streaming";import*as X from"fs/promises";import*as L from"path";var D=class extends Error{constructor(e,t="unknown",r=!1){super(e),this.code=t,this.retryable=r}},N=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=`
592
+ });
593
+ })();
594
+ </script>`;function Yn(n){return n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Xn(n){let e={};for(let[t,r]of Object.entries(n))e[t]=r.startsWith("https://")?"/proxy/"+r:r;return e}import*as Ge from"fs/promises";import*as Pt from"path";import{existsSync as Or}from"fs";import{execFile as Qn}from"child_process";import{promisify as Zn}from"util";var es=Zn(Qn);async function ze(n,e){let t=n.filter(s=>!ts(s,e));if(t.length===0)return;await Ge.mkdir(e,{recursive:!0});let r=Pt.join(e,"package.json");Or(r)||await Ge.writeFile(r,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${t.join(", ")}`),await es("npm",["install","--no-audit","--no-fund",...t],{cwd:e,shell:!0})}function ts(n,e){return Or(Pt.join(e,"node_modules",rs(n)))}function Ke(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.includes(":"))continue;let o=s.startsWith("@")?s.split("/").slice(0,2).join("/"):s.split("/")[0];e.add(o)}return[...e]}function rs(n){if(n.startsWith("@")){let t=n.indexOf("/");if(t<0)return n;let r=n.indexOf("@",t+1);return r<0?n:n.slice(0,r)}let e=n.indexOf("@");return e<0?n:n.slice(0,e)}async function Ir(n){let t=(await G.readdir(n)).find(r=>r.endsWith(".bulb.md"));return t?ce.join(n,t):null}async function Ce(n){let e=await G.readFile(n,"utf-8"),t=tr(e);if(!t)throw new Error("Invalid .bulb.md file format");let r=rr(t);return{bulb:r,config:sr(r.config)}}async function Rt(n,e,t){let r=lt(n,{serverOnly:!0});if(r.error)throw new Error(`Server compilation error: ${r.error}`);let s=r.code;t&&(s=await Xt(s,t));let o=ce.join(e,".typebulb");await G.mkdir(o,{recursive:!0});let i=Ke(s);i.length>0&&await ze(i,o);let a=ce.join(o,"server.mjs");return await G.writeFile(a,s,"utf-8"),await import(`${ns(a).href}?t=${Date.now()}`)}async function Et(n,e,t,r){let{bulb:s,config:o}=await Ce(n),i=nr(s.data),a=lt(s.code,{jsxImportSource:o.jsxImportSource});a.error&&console.error("Compilation error:",a.error);let{importMap:c}=await qe.buildImportMap(a.code,o.dependencies??{},r?new Set([r.name]):void 0);r&&(c.imports[r.name]=r.entryUrl);let l=Cr({name:s.name,code:a.code,css:s.css,html:s.html,data:i,insight:s.insight,importMap:c,watch:e}),d=ce.dirname(n);o.env?.length&&fe(o.env,d);let u=null;return s.server&&t&&(u=await Rt(s.server,d,r)),{html:l,bulb:s,serverExports:u}}import{Hono as ps}from"hono";import{serve as fs}from"@hono/node-server";import{streamSSE as hs}from"hono/streaming";import*as Z from"fs/promises";import*as j from"path";var A=class extends Error{constructor(e,t="unknown",r=!1){super(e),this.code=t,this.retryable=r}},N=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=`
521
595
 
522
- `){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 D(t,r,n)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new D(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 Se=class extends N{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:this.withLastMessageCached(o),stream:n};if(r?.webSearch!==!1&&(a.tools=[{type:"web_search_20250305",name:"web_search"}]),i&&(a.system=[{type:"text",text:i,cache_control:{type:"ephemeral"}}]),this.isReasoningEnabled(r)){let c=r.reasoning;if(this.isModernModel(t)){let l={0:"low",1:"low",2:"medium",3:"high"};a.thinking={type:"adaptive"},a.output_config={effort:l[c]}}else{let l={0:0,1:2048,2:4096,3:8192};a.thinking={type:"enabled",budget_tokens:l[c]}}}return a}parseError(e,t){return this.parseJsonError(e,t)}parseNonStreamingResponse(e){if(!this.isAnthropicResponse(e))return{text:""};let t=e.content.filter(n=>n.type==="text").map(n=>n.text).join(""),r=e.content.filter(n=>n.type==="thinking").map(n=>n.thinking).join(`
596
+ `){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 A(t,r,s)}if("error"in e&&e.error){let t=this.extractErrorMessage(e.error);throw new A(t)}}extractErrorMessage(e){if(typeof e=="string")try{let t=JSON.parse(e);return t.error?.message||t.message||e}catch{return e}return typeof e=="object"&&e!==null?e.message||JSON.stringify(e):`${this.providerName} returned an error`}};var Oe=class extends N{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),a={model:t,max_tokens:this.getMaxTokens(t),messages:this.withLastMessageCached(i),stream:s};if(r?.webSearch!==!1&&(a.tools=[{type:"web_search_20250305",name:"web_search"}]),o&&(a.system=[{type:"text",text:o,cache_control:{type:"ephemeral"}}]),this.isReasoningEnabled(r)){let c=r.reasoning;if(this.isModernModel(t)){let l={0:"low",1:"low",2:"medium",3:"high"};a.thinking={type:"adaptive"},a.output_config={effort:l[c]}}else{let l={0:0,1:2048,2:4096,3:8192};a.thinking={type:"enabled",budget_tokens:l[c]}}}return a}parseError(e,t){return this.parseJsonError(e,t)}parseNonStreamingResponse(e){if(!this.isAnthropicResponse(e))return{text:""};let t=e.content.filter(s=>s.type==="text").map(s=>s.text).join(""),r=e.content.filter(s=>s.type==="thinking").map(s=>s.thinking).join(`
523
597
 
524
- `);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}}withLastMessageCached(e){let t=e.length-1;return e.map((r,n)=>n===t?{role:r.role,content:[{type:"text",text:r.content,cache_control:{type:"ephemeral"}}]}:r)}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 Re=class extends N{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(`
525
- `)),!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 D(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(`
598
+ `);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}}withLastMessageCached(e){let t=e.length-1;return e.map((r,s)=>s===t?{role:r.role,content:[{type:"text",text:r.content,cache_control:{type:"ephemeral"}}]}:r)}isAnthropicResponse(e){return"content"in e&&Array.isArray(e.content)&&"type"in e&&e.type==="message"}isModernModel(e){let t=e.match(/^claude-\w+-(\d+)-(\d+)/);return!!t&&(+t[1]>4||+t[1]==4&&+t[2]>=6)}getMaxTokens(e){return this.isModernModel(e)?64e3:32e3}};var Ie=class extends N{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(`
599
+ `)),!t&&s.type==="message"&&s.content&&(t=s.content.filter(o=>o.type==="output_text").map(o=>o.text).join(""));return{text:t,reasoning: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 A(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(`
526
600
 
527
- `)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var Ee=class extends N{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,`
528
- `),c={contents:o.map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.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(`
529
- `)[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 D(r)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new D(`Prompt blocked: ${t}`)}}};var ke=class extends N{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 on=new Map([["openai",new Re],["openrouter",new ke],["anthropic",new Se],["gemini",new Ee]]);function Y(s){let e=on.get(s);if(!e)throw new Error(`Unsupported protocol: ${s}`);return e}async function pt(s,e){let t=Y(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 ut(s,e){let t=Y(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 nr(s){let e=s.indexOf(`\r
601
+ `)}isResponsesApiEvent(e){return"type"in e&&typeof e.type=="string"}isResponsesApiResponse(e){return"object"in e&&e.object==="response"}};var Ae=class extends N{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,`
602
+ `),c={contents:i.map(l=>({role:l.role==="assistant"?"model":"user",parts:[{text:l.content}]}))};return r?.webSearch!==!1&&(c.tools=[{google_search:{}}]),o&&(c.systemInstruction={role:"system",parts:[{text:o}]}),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),s=Array.isArray(r)?r[0]?.error:r?.error;return s&&typeof s=="object"?{message:(s.message||`HTTP ${t}`).split(`
603
+ `)[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 A(r)}if(this.isGeminiResponse(e)&&e.promptFeedback?.blockReason){let t=e.promptFeedback.blockReason;throw new A(`Prompt blocked: ${t}`)}}};var De=class extends N{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 ss=new Map([["openai",new Ie],["openrouter",new De],["anthropic",new Oe],["gemini",new Ae]]);function X(n){let e=ss.get(n);if(!e)throw new Error(`Unsupported protocol: ${n}`);return e}async function kt(n,e){let t=X(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 Tt(n,e){let t=X(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 Ar(n){let e=n.indexOf(`\r
530
604
  \r
531
- `),t=s.indexOf(`
532
-
533
- `);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function ht(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(`
534
- `).trim();if(!r)return null;if(r==="[DONE]")return"done";try{return JSON.parse(r)}catch{return null}}async function sr(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:l}=a;if(c){if(n.trim()){let h=ht(n);h!==null&&h!=="done"&&e(h)}break}i=!0,n+=r.decode(l,{stream:!0});let{pos:d,len:p}=nr(n);for(;d!==-1;){let h=n.slice(0,d);n=n.slice(d+p);let w=ht(h);if(w==="done"){n="";break}w!==null&&e(w),{pos:d,len:p}=nr(n)}}return{receivedAnyData:i}}async function mt(s,e){let t=e??(s.headers.get("X-Provider-Protocol")||"openai"),r=Y(t);if(!s.body)throw new Error("Response body is missing");let n=s.body.getReader(),i="";return await sr(n,o=>{let a=r.parseStreamChunk(o);a?.text&&(i+=a.text)}),i}import*as ft from"fs/promises";import*as Te from"path";var Ue=class{async get(e){let t=F(e),r=Te.join(Pe,t+".bin"),n=Te.join(Pe,t+".json");try{let[i,o]=await Promise.all([ft.readFile(r),ft.readFile(n,"utf8")]),a=JSON.parse(o);return{body:i,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await P();let r=F(e),n=Te.join(Pe,r+".bin"),i=Te.join(Pe,r+".json"),o={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([O(n,t.body),O(i,JSON.stringify(o))])}};var ar="127.0.0.1",dn=new Set(["localhost","127.0.0.1","::1"]);function pn(s){if(s)try{return new URL(s.includes("://")?s:`http://${s}`).hostname}catch{return}}function ir(s){let e=pn(s);return!!e&&dn.has(e)}function We(s){return s instanceof Error?s.message:"Unknown error"}async function cr(s){let{getHtml:e,basePath:t,port:r,reloadEmitter:n,getServerExports:i,localOverride:o,trusted:a=!1,trustHint:c}=s,l=new an;l.use("*",async(u,m)=>{if(!ir(u.req.header("host")))return u.text("Forbidden: untrusted Host",403);await m()}),l.use("*",async(u,m)=>{await m(),u.res.headers.set("Cross-Origin-Opener-Policy","same-origin"),u.res.headers.set("Cross-Origin-Embedder-Policy","credentialless")});let d=["/__fs/*","/__api/*","/__ai"],p=async(u,m)=>{if(!a){let y=c?`
535
- ${c}`:"";return u.text(`Forbidden: this capability requires --trust.${y}`,403)}await m()},h=async(u,m)=>{let y=u.req.header("sec-fetch-site");if(y){if(y==="cross-site")return u.text("Forbidden: cross-site request",403)}else{let x=u.req.header("origin");if(x&&!ir(x))return u.text("Forbidden: cross-origin request",403)}await m()};for(let u of d)l.use(u,p),l.use(u,h);l.get("/",u=>u.html(e())),l.post("/__fs/read",async u=>{try{let{path:m}=await u.req.json(),y=yt(m,t),x=await X.readFile(y);return new Response(new Uint8Array(x),{headers:{"Content-Type":"application/octet-stream"}})}catch(m){let y=We(m);return u.json({error:y},400)}}),l.post("/__fs/write",async u=>{try{let m=u.req.query("path");if(!m)return u.json({error:"Missing path"},400);let y=yt(m,t);return await X.mkdir(L.dirname(y),{recursive:!0}),await X.writeFile(y,Buffer.from(await u.req.arrayBuffer())),u.json({success:!0})}catch(m){let y=We(m);return u.json({error:y},400)}});let w={log:console.log};l.post("/__api/:name",async u=>{try{let m=i?.(),y=u.req.param("name"),x=m?.[y]??w[y];if(!x||typeof x!="function")return u.json({error:`API function '${y}' not found`},404);let{args:b}=await u.req.json(),I=await x(...b||[]);return u.json({result:I})}catch(m){let y=We(m);return u.json({error:y},500)}}),l.post("/__ai",async u=>{try{let{messages:m,system:y,reasoning:x,provider:b,model:I,webSearch:H}=await u.req.json();if(!m||!Array.isArray(m)||m.length===0)return u.json({message:"messages array is required",code:"unknown",retryable:!1},400);let B=un(b,I);if(typeof B=="string")return u.json({message:B,code:"unknown",retryable:!1},400);let Ke=[...y?[{role:"system",content:y}]:[],...m.map(Ie=>({role:Ie.role,content:Ie.content}))],Z=await pt(B,{model:B.model,messages:Ke,stream:!0,reasoning:x??0,webSearch:H??!0});if(!Z.ok){let Ie=await ut(Z,B.protocol);return u.json(Ie,Z.status)}let kt=await mt(Z,B.protocol);return kt||console.warn("[tb.ai] Empty response from provider"),u.json({text:kt})}catch(m){if(m instanceof D)return u.json({message:m.message,code:m.code,retryable:m.retryable},500);let y=We(m);return u.json({message:y,code:"unknown",retryable:!1},500)}}),l.get("/__models",async u=>{try{let m=await fn();return u.json(m)}catch{return u.json([],200)}});let f=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"],R=new Ue;if(l.get("/proxy/*",async u=>{let m=new URL(u.req.url),x=(m.pathname+m.search).slice(7),b=x.lastIndexOf("https://");return b===-1?u.text("Invalid proxy URL",400):v(u,x.slice(b))}),o){let u=`/local/${o.name}/`;l.get("/local/*",async m=>{let{pathname:y}=new URL(m.req.url);if(!y.startsWith(u))return m.text("Not Found",404);let x=decodeURIComponent(y.slice(u.length));try{let b=yt(x,o.serveDir),I=await X.readFile(b);return new Response(I,{headers:{"Content-Type":gn(b)}})}catch{return m.text("Not Found",404)}})}async function v(u,m){let y;try{y=new URL(m)}catch{return u.text("Invalid URL",400)}if(y.protocol!=="https:")return u.text("HTTPS only",400);if(!f.includes(y.hostname))return u.text("Host not allowed",403);let x=await R.get(m);if(x)return new Response(x.body,{status:200,headers:gt(x.contentType,x.cacheControl)});try{let b=await fetch(m,{headers:{Accept:u.req.header("Accept")||"*/*"},redirect:"follow"});if(!b.ok)return u.text(`Upstream ${b.status}`,b.status);let I=b.headers.get("Content-Type")||void 0,H=b.headers.get("Cache-Control")||void 0;if(b.body){let[B,Ke]=b.body.tee();return(async()=>{try{let Z=await new Response(Ke).arrayBuffer();await R.set(m,{body:Buffer.from(Z),contentType:I,cacheControl:H})}catch{}})(),new Response(B,{status:b.status,headers:gt(I,H)})}return new Response(null,{status:b.status,headers:gt(I,H)})}catch(b){return u.text(`Proxy fetch failed: ${b instanceof Error?b.message:b}`,502)}}n&&l.get("/__reload",u=>ln(u,async m=>{let y=()=>{m.writeSSE({event:"reload",data:""})};for(n.on("reload",y),m.onAbort(()=>{n.removeListener("reload",y)});;)await m.sleep(3e4)}));let k=/^\/(v\d+\/|stable\/|node\/|gh\/|@[^/]+\/[^@/]+@|[^@/]+@)/;l.notFound(async u=>{if(u.req.method!=="GET")return u.text("Not Found",404);let m=new URL(u.req.url);return k.test(m.pathname)?v(u,"https://esm.sh"+m.pathname+m.search):u.text("Not Found",404)});let $=cn({fetch:l.fetch,port:r,hostname:ar});return{port:r,close:()=>$.close()}}var lr={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function un(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=Y(t)}catch{return`Unknown provider '${t}'.`}let i=lr[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 hn="https://api.typebulb.com/api/models",mn=1440*60*1e3,oe=null;async function fn(){if(!oe||Date.now()-oe.fetchedAt>mn){let s=await fetch(hn);if(!s.ok)return oe?or(oe.models):[];oe={models:await s.json(),fetchedAt:Date.now()}}return or(oe.models)}function or(s){let e=new Set(Object.entries(lr).filter(([,t])=>!!process.env[t]).map(([t])=>t));return s.filter(t=>e.has(t.provider))}function gt(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 gn(s){switch(L.extname(s).toLowerCase()){case".js":case".mjs":return"text/javascript";case".wasm":return"application/wasm";case".json":case".map":return"application/json";default:return"application/octet-stream"}}function yt(s,e){let t=L.resolve(e,s),r=L.normalize(e),n=L.normalize(t);if(n!==r&&!n.startsWith(r+L.sep))throw new Error("Path traversal detected - access denied");return t}async function wt(s){let e=await import("net");return new Promise(t=>{let r=e.createServer();r.listen(s,ar,()=>{let n=r.address(),i=typeof n=="object"&&n?n.port:s;r.close(()=>t(i))}),r.on("error",()=>{t(wt(s+1))})})}import yn from"open";async function dr(s){await yn(s)}import pr from"chokidar";var ur={persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}};function bt(s){let{bulbPath:e,emitter:t}=s,r=pr.watch(e,ur);return r.on("change",()=>{t.emit("reload")}),()=>r.close()}function hr(s){let{dir:e,onChange:t,debounceMs:r=150}=s,n,i=pr.watch(e,ur);return i.on("all",()=>{n&&clearTimeout(n),n=setTimeout(t,r)}),()=>{n&&clearTimeout(n),i.close()}}import*as _ from"fs/promises";import*as T from"path";import*as ae from"path";var wn=ae.join(Fe,"pkg"),bn=ae.join(Fe,"files"),vn=ae.join(Fe,"negative.json"),Je=class{pkgMem=new Map;fileMem=new Map;negativeCache=new z(new se(vn));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await P();let t=await K(mr(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 He(async()=>{await P(),await O(mr(e),JSON.stringify(n))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await P();let t=await $e(fr(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await He(async()=>{await P(),await O(fr(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await He(async()=>{await P(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return He(()=>this.negativeCache.clearNegative(e))}};async function He(s){try{await s()}catch{}}function mr(s){return ae.join(wn,F(s)+".json")}function fr(s){return ae.join(bn,F(s)+".txt")}var vt;function xn(){return vt||(vt=ot({cache:new Je,cdnClient:Zt,packageService:Be,versionResolver:Qt})),vt}var gr="file:///node_modules/";async function yr(s){let e=je(s.emitKey,"typecheck");await P(),await _.rm(e,{recursive:!0,force:!0}),await _.mkdir(e,{recursive:!0});let t=En(s.jsxImportSource,s.dependencies),r=await xn().resolve(s.code,s.dependencies,t),n=s.local?.name,i=n?r.filter(d=>d.pkg!==n):r,o=new Set;for(let d of i)for(let p of d.files){let h=Ve(p.path);if(!h||o.has(h))continue;o.add(h);let w=T.join(e,"node_modules",h);await _.mkdir(T.dirname(w),{recursive:!0}),await _.writeFile(w,p.content,"utf8")}let a={};for(let d of i)for(let p of d.shims){let h=Ve(p.path);h&&(a[p.module]=[`./node_modules/${h}`])}for(let d of i){if(d.ambient)continue;let p=Ve(d.mainPath);p&&(a[d.pkg]=[`./node_modules/${p}`])}let c=new Set;for(let d of i)for(let p of d.files){if(!p.ambient)continue;let h=Ve(p.path);h&&c.add(`node_modules/${h}`)}if(s.local){delete a[s.local.name];let d=await kn(s.local,e);d?a[s.local.name]=[`./node_modules/${s.local.name}/${d}`]:console.warn(` local: '${s.local.name}' ships no type defs; check cannot type against it.`)}let l=Pn(s.jsxImportSource,a,[...c]);return await _.writeFile(T.join(e,"tsconfig.json"),JSON.stringify(l,null,2)+`
536
- `,"utf8"),await _.writeFile(T.join(e,"code.tsx"),s.code,"utf8"),await _.writeFile(T.join(e,"tb.d.ts"),rt,"utf8"),{dir:e}}function Pn(s,e,t=[]){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"bundler",lib:Sn([...et,...tt]),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",...t]}}function Sn(s){return s.filter(e=>!e.since).map(e=>Rn(e.name))}function Rn(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 Ve(s){if(!s.startsWith(gr))return;let e=s.slice(gr.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}async function kn(s,e){if(!s.typesAbs)return;let t=T.dirname(s.typesAbs),r=T.join(e,"node_modules",s.name);for(let n of await Tn(t)){let i=T.join(r,T.relative(t,n));await _.mkdir(T.dirname(i),{recursive:!0}),await _.copyFile(n,i)}return T.basename(s.typesAbs)}async function Tn(s){let e=[];async function t(r){let n=await _.readdir(r,{withFileTypes:!0});for(let i of n){let o=T.join(r,i.name);i.isDirectory()?await t(o):/\.d\.ts(\.map)?$/.test(i.name)&&e.push(o)}}return await t(s),e}import*as A from"fs/promises";import*as Q from"path";import{existsSync as An}from"fs";import*as qe from"fs/promises";import*as xt from"path";import{existsSync as wr}from"fs";import{execFile as _n}from"child_process";import{promisify as Cn}from"util";var In=Cn(_n);async function Ge(s,e){let t=s.filter(n=>!On(n,e));if(t.length===0)return;await qe.mkdir(e,{recursive:!0});let r=xt.join(e,"package.json");wr(r)||await qe.writeFile(r,JSON.stringify({name:"typebulb-server",private:!0})),console.log(` Installing: ${t.join(", ")}`),await In("npm",["install","--no-audit","--no-fund",...t],{cwd:e,shell:!0})}function On(s,e){return wr(xt.join(e,"node_modules",Dn(s)))}function ze(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]}function Dn(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 Mn="^22";async function br(s){let e=je(s.emitKey,"typecheck-server");await P(),await A.rm(e,{recursive:!0,force:!0}),await A.mkdir(e,{recursive:!0});let t=Q.join(s.bulbDir,".typebulb"),r=ze(s.server);await Ge([`@types/node@${Mn}`,...r],t);let n=Q.join(t,"node_modules"),i=Q.join(e,"node_modules");return await Fn(n,i),await A.writeFile(Q.join(e,"server.ts"),s.server,"utf8"),await A.writeFile(Q.join(e,"tb.d.ts"),nt,"utf8"),await A.writeFile(Q.join(e,"tsconfig.json"),JSON.stringify($n(),null,2)+`
537
- `,"utf8"),{dir:e}}function $n(){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 Fn(s,e){if(!An(s)){await A.mkdir(e,{recursive:!0});return}await A.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await A.symlink(s,e,t)}import*as St from"fs/promises";import{existsSync as _e}from"fs";import*as E from"path";import{resolve as vr}from"resolve.exports";import{init as jn,parse as Nn}from"es-module-lexer";var Pt=["browser","import","default"];function xr(s){let e=s.indexOf("=");if(e===-1)throw new Error(`--replace must be <name>=<path> (got '${s}')`);let t=s.slice(0,e).trim(),r=s.slice(e+1).trim();if(!t)throw new Error(`--replace missing package name (got '${s}')`);if(!r)throw new Error(`--replace missing path for '${t}'`);if(t.startsWith("@"))throw new Error(`--replace does not support scoped names yet; '${t}' is scoped`);return{name:t,dir:E.resolve(r)}}async function Pr(s){let{name:e,dir:t}=s;if(!_e(t))throw new Error(`--replace path for '${e}' does not exist: ${t}`);let r=E.join(t,"package.json"),n;try{n=JSON.parse(await St.readFile(r,"utf8"))}catch{throw new Error(`--replace package '${e}' has no readable package.json at ${r}`)}let i=Ln(n,e),o=E.resolve(t,i);if(!_e(o))throw new Error(`--replace package '${e}' entry not found on disk: ${o} \u2014 did you build it (e.g. \`pnpm run build\`)?`);let a=E.dirname(o),c=`/local/${e}/${E.basename(o)}`,l=Bn(n,t);return await Un(e,o,a),{name:e,dir:t,entryAbs:o,serveDir:a,entryUrl:c,typesAbs:l}}function Ln(s,e){if(s.exports!==void 0){let r;try{r=vr(s,".",{browser:!0,conditions:Pt})}catch(i){throw new Error(`--replace package '${e}' "exports" does not resolve a browser entry (conditions: ${Pt.join(", ")}): ${i instanceof Error?i.message:i}`)}let n=Sr(r);if(!n)throw new Error(`--replace package '${e}' "exports" did not resolve "." to a single file (conditions: ${Pt.join(", ")}); too complex to override.`);return n}let t=s.module??s.main;if(!t)throw new Error(`--replace package '${e}' has no "exports", "module", or "main" entry to resolve.`);return t}function Bn(s,e){if(s.exports!==void 0)try{let r=vr(s,".",{conditions:["types"]}),n=Sr(r);if(n){let i=E.resolve(e,n);if(_e(i))return i}}catch{}let t=s.types??s.typings;if(t){let r=E.resolve(e,t);if(_e(r))return r}}function Sr(s){if(typeof s=="string")return s;if(Array.isArray(s))return s.find(e=>typeof e=="string")}async function Un(s,e,t){await jn;let r=E.normalize(t),n=new Set,i=[e];for(;i.length;){let o=i.shift();if(n.has(o))continue;n.add(o);let a;try{a=await St.readFile(o,"utf8")}catch{continue}let c,l;try{[c,,,l]=Nn(a,o)}catch{continue}if(o===e&&!l)throw new Error(`override package '${s}' entry is not an ES module (no import/export syntax); CommonJS or non-module entries aren't supported (esm.sh would have to transform it).`);for(let d of c){if(d.d===-2)continue;let p=d.n;if(p&&!p.startsWith("node:")){if(p.startsWith("./")||p.startsWith("../")||p.startsWith("/")){let h=Wn(o,p,r);h&&!n.has(h)&&i.push(h);continue}throw new Error(`override package must ship self-contained (bundle its dependencies); ${s} externalizes '${p}'`)}}}}function Wn(s,e,t){let r=e.replace(/[?#].*$/,""),n=E.resolve(E.dirname(s),r),i=[n,n+".js",n+".mjs",E.join(n,"index.js"),E.join(n,"index.mjs")];for(let o of i)if(E.normalize(o).startsWith(t)&&_e(o))return o}var ha=Gn(Vn),zn="0.9.1";function Kn(s){let e={subcommand:"run",file:"",port:3e3,watch:!0,open:!0,server:!1,trust:!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==="--trust")e.trust=!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 if(r==="--replace"||r.startsWith("--replace=")){let n=r.startsWith("--replace=")?r.slice(10):s[++t]??"";try{let i=xr(n);if(e.local)throw new Error(`--replace can only be used once (got '${e.local.name}' and '${i.name}')`);e.local=i}catch(i){console.error(i instanceof Error?i.message:String(i)),process.exit(1)}}else r.startsWith("-")||(e.file=r)}return e}function Yn(){console.log(`
538
- typebulb - Local bulb runner for Typebulb
539
-
540
- Usage:
541
- typebulb [file.bulb.md] Run a bulb (defaults to .bulb.md in cwd)
542
- typebulb check [file.bulb.md] Type-check a bulb without running it
543
-
544
- Options:
545
- --no-watch Disable hot reload (watch is on by default)
546
- -p, --port <port> Use a specific port (default: 3000)
547
- --no-open Don't auto-open browser
548
- --trust Grant privileged capabilities (filesystem, AI,
549
- and server.ts). Without it a bulb runs sandboxed:
550
- tb.fs / tb.ai / tb.server are blocked and the page
551
- shows the exact --trust command to unlock them.
552
- --server Run server.ts only, no web server (needs --trust)
553
- --replace <name>=<path> Replace a declared dependency with a local built
554
- package folder instead of a CDN (dev only).
555
- Applies to both run and check. Watched for
556
- rebuilds under --watch; --no-watch freezes it.
557
- e.g. --replace tensorgrad=../tensorgrad
558
- -V, --version Show version number
559
- -h, --help Show this help message
560
-
561
- Filesystem API:
562
- Bulbs can read and write local files via tb.fs:
563
- await tb.fs.read('file.txt') // UTF-8 text (throws on non-UTF-8)
564
- await tb.fs.readBytes('image.png') // raw bytes (Uint8Array)
565
- await tb.fs.write('output.html', content) // text or bytes
566
-
567
- Server API:
568
- Add a **server.ts** section to run Node.js code server-side.
569
- Exported functions become callable from the browser:
570
- // in **server.ts**: export async function query(sql) { ... }
571
- // in **code.tsx**: const rows = await tb.server.query(sql)
572
- .env and .env.local are auto-loaded from the working directory.
573
-
574
- Built-in server functions (available without a **server.ts** section):
575
- tb.server.log(...) Print to the CLI's stdout
576
-
577
- AI API:
578
- Bulbs can call AI providers via tb.ai(). Set API keys in .env:
579
- ANTHROPIC_API_KEY=sk-ant-...
580
- OPENAI_API_KEY=sk-...
581
- GOOGLE_API_KEY=AIza...
582
- OPENROUTER_API_KEY=sk-or-...
583
- Set provider and model (required):
584
- TB_AI_PROVIDER=anthropic
585
- TB_AI_MODEL=claude-haiku-4-5-20251001
586
- Both can be overridden per-call: tb.ai({ provider: "openai", model: "gpt-4o", ... })
587
- Optional reasoning depth (0=min, 1=low, 2=med, 3=max):
588
- tb.ai({ ..., reasoning: 2 })
589
-
590
- Examples:
591
- typebulb my-editor.bulb.md
592
- typebulb --no-watch --port 8080 my-editor.bulb.md
593
- typebulb .
594
- `)}async function Xn(s){let t=(await M.readdir(s)).find(r=>r.endsWith(".bulb.md"));return t?S.join(s,t):null}function Er(){Et([".env",".env.local"],process.cwd(),!0)}function Et(s,e,t=!1){for(let r of s){let n=S.resolve(e,r);try{let i=Hn(n,"utf-8");for(let o of i.split(`
595
- `)){let a=o.trim();if(!a||a.startsWith("#"))continue;let c=a.indexOf("=");if(c===-1)continue;let l=a.slice(0,c).trim(),d=a.slice(c+1).trim();(d.startsWith('"')&&d.endsWith('"')||d.startsWith("'")&&d.endsWith("'"))&&(d=d.slice(1,-1)),process.env[l]??=d}}catch{t||console.warn(` Warning: env file not found: ${r}`)}}}async function kr(s,e){let t=Ye(s,{serverOnly:!0});if(t.error)throw new Error(`Server compilation error: ${t.error}`);let r=S.join(e,".typebulb");await M.mkdir(r,{recursive:!0});let n=ze(t.code);n.length>0&&await Ge(n,r);let i=S.join(r,"server.mjs");return await M.writeFile(i,t.code,"utf-8"),await import(`${Jn(i).href}?t=${Date.now()}`)}async function Ce(s){let e=await M.readFile(s,"utf-8"),t=Tt(e);if(!t)throw new Error("Invalid .bulb.md file format");let r=_t(t);return{bulb:r,config:It(r.config)}}async function Rr(s,e,t,r,n){let{bulb:i,config:o}=await Ce(s),a=Ct(i.data),c=Ye(i.code,{jsxImportSource:o.jsxImportSource});c.error&&console.error("Compilation error:",c.error);let{importMap:l}=await Be.buildImportMap(c.code,o.dependencies??{},n?new Set([n.name]):void 0);n&&(l.imports[n.name]=n.entryUrl);let d=tr({name:i.name,code:c.code,css:i.css,html:i.html,data:a,insight:i.insight,importMap:l,watch:t?e:!1,trustHint:t?void 0:r}),p=t?d:rr({bulbHtml:d,name:i.name,watch:e}),h=S.dirname(s);o.env?.length&&Et(o.env,h);let w=null;return i.server&&t&&(w=await kr(i.server,h)),{html:p,bulb:i,serverExports:w}}async function Qn(s,e){let{bulb:t,config:r}=await Ce(s);!t.code&&!t.server&&(console.error("Bulb has neither **code.tsx** nor **server.ts**; nothing to check."),process.exit(1));let n=[];if(t.code){let{dir:o}=await yr({code:t.code,dependencies:r.dependencies??{},jsxImportSource:r.jsxImportSource,emitKey:s,local:e});n.push({role:"client",dir:o})}if(t.server){let{dir:o}=await br({server:t.server,bulbDir:S.dirname(s),emitKey:s});n.push({role:"server",dir:o})}let i=!1;for(let{role:o,dir:a}of n){let{stdout:c,exitCode:l}=await Zn(a);for(let d of c.split(/\r?\n/))d.trim()&&console.log(`${o} ${d}`);l!==0&&(i=!0)}i&&process.exit(1)}function Zn(s){return new Promise(e=>{let t=qn("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 es(s,e){Er();let t=async()=>{let{bulb:r,config:n}=await Ce(s),i=S.dirname(s);n.env?.length&&Et(n.env,i),await kr(r.server,i)};if(console.log(`Running ${S.basename(s)}...`),await t(),e){console.log(`Watching for changes...
596
- `);let r=new Rt;r.on("reload",async()=>{try{console.log("Re-running..."),await t()}catch(n){console.error("Error:",n)}}),bt({bulbPath:s,emitter:r})}}async function ts(){let s=Kn(process.argv.slice(2));s.version&&(console.log(`typebulb ${zn}`),process.exit(0)),s.help&&(Yn(),process.exit(0));let e;if(!s.file||s.file==="."){let v=await Xn(process.cwd());v||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=v}else e=S.resolve(s.file);try{await M.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=s.file&&s.file!=="."?s.file:S.relative(process.cwd(),e)||S.basename(e),r=`npx typebulb --trust ${t.includes(" ")?`"${t}"`:t}`,n;if(s.local){let v;try{v=await Ce(e)}catch{}v&&!(s.local.name in(v.config.dependencies??{}))&&(console.error(`--replace: '${s.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),v&&(!v.bulb.code||s.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{n=await Pr(s.local)}catch(k){console.error(k instanceof Error?k.message:String(k)),process.exit(1)}console.log(`replace: ${n.name} \u2192 ${S.relative(process.cwd(),n.dir)||"."}`)}if(s.subcommand==="check"){await Qn(e,n);return}try{let{bulb:v}=await Ce(e);if(v.server&&(!v.code||s.server)){s.trust||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
597
- ${r}`),process.exit(1)),await es(e,s.watch);return}}catch{}let i=process.cwd(),o=s.watch?new Rt:void 0;Er(),console.log(`Loading ${S.basename(e)}...`);let{html:a,bulb:c,serverExports:l}=await Rr(e,s.watch,s.trust,r,n),d=await wt(s.port),p=await cr({getHtml:()=>a,basePath:i,port:d,reloadEmitter:o,getServerExports:()=>l,localOverride:n?{name:n.name,serveDir:n.serveDir}:void 0,trusted:s.trust,trustHint:r}),h=`http://localhost:${d}`;console.log(`
598
- ${c.name}`),console.log(` ${h}`),console.log(s.trust?" trust: granted (filesystem, AI, server.ts enabled)":` trust: sandboxed \u2014 re-run with --trust to enable filesystem / AI / server.ts
599
- `),s.watch&&console.log(` Watching for changes...
600
- `);let w,f;if(s.watch&&o){let v=new Rt;if(v.on("reload",async()=>{try{console.log("Recompiling...");let k=await Rr(e,!0,s.trust,r,n);a=k.html,l=k.serverExports,o.emit("reload"),console.log(`Done. Browser reloading...
601
- `)}catch(k){console.error("Compile error:",k)}}),w=bt({bulbPath:e,emitter:v}),n){let{name:k,serveDir:$}=n;f=hr({dir:$,onChange:()=>{console.log(`Local package '${k}' changed. Browser reloading...
602
- `),o.emit("reload")}})}}s.open&&await dr(h);let R=async()=>{console.log(`
603
- Shutting down...`),p.close(),w?.(),f?.();let v=S.join(S.dirname(e),".typebulb","server.mjs");await M.rm(v,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",R),process.on("SIGTERM",R)}ts().catch(s=>{console.error("Error:",s.message),process.exit(1)});
605
+ `),t=n.indexOf(`
606
+
607
+ `);return e!==-1&&(t===-1||e<t)?{pos:e,len:4}:t!==-1?{pos:t,len:2}:{pos:-1,len:0}}function _t(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(`
608
+ `).trim();if(!r)return null;if(r==="[DONE]")return"done";try{return JSON.parse(r)}catch{return null}}async function Dr(n,e,t){let r=new TextDecoder,s="",o=!1,i=t?new Promise((a,c)=>{t.aborted&&c(new Error("Aborted")),t.addEventListener("abort",()=>c(new Error("Aborted")),{once:!0})}):null;for(;;){let a=i?await Promise.race([n.read(),i]):await n.read(),{done:c,value:l}=a;if(c){if(s.trim()){let h=_t(s);h!==null&&h!=="done"&&e(h)}break}o=!0,s+=r.decode(l,{stream:!0});let{pos:d,len:u}=Ar(s);for(;d!==-1;){let h=s.slice(0,d);s=s.slice(d+u);let b=_t(h);if(b==="done"){s="";break}b!==null&&e(b),{pos:d,len:u}=Ar(s)}}return{receivedAnyData:o}}async function Ct(n,e){let t=e??(n.headers.get("X-Provider-Protocol")||"openai"),r=X(t);if(!n.body)throw new Error("Response body is missing");let s=n.body.getReader(),o="";return await Dr(s,i=>{let a=r.parseStreamChunk(i);a?.text&&(o+=a.text)}),o}import*as Ot from"fs/promises";import*as $e from"path";var Ye=class{async get(e){let t=F(e),r=$e.join(_e,t+".bin"),s=$e.join(_e,t+".json");try{let[o,i]=await Promise.all([Ot.readFile(r),Ot.readFile(s,"utf8")]),a=JSON.parse(i);return{body:o,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await x();let r=F(e),s=$e.join(_e,r+".bin"),o=$e.join(_e,r+".json"),i={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([I(s,t.body),I(o,JSON.stringify(i))])}};import{readdir as as,readFile as Mr,writeFile as Nr,unlink as Fe,mkdir as cs}from"fs/promises";import{mkdirSync as ls,writeFileSync as $r,appendFileSync as ds,readFileSync as jr}from"fs";import*as de from"path";import{join as It,resolve as os}from"path";import{homedir as is}from"os";function Xe(){let n=process.env.TYPEBULB_SERVERS_DIR;return n?It(n,".."):It(is(),".typebulb")}function Q(){return process.env.TYPEBULB_SERVERS_DIR||It(Xe(),"servers")}function le(n){let e=os(n);return(process.platform==="win32"?e.toLowerCase():e).replace(/\\/g,"/")}var Fr=1e6;function At(n){return de.join(Q(),`${n}.json`)}function Qe(n){return de.join(Q(),`${n}.log`)}function Lr(n){let e=Qe(n);try{ls(Q(),{recursive:!0}),$r(e,"")}catch{return()=>{}}let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr),s=0,o=!1,i=a=>{if(!o)try{let c=typeof a=="string"?Buffer.from(a,"utf8"):Buffer.from(a);if(ds(e,c),s+=c.length,s>2*Fr){let l=jr(e),d=l.subarray(Math.max(0,l.length-Fr));$r(e,d),s=d.length}}catch{o=!0}};return process.stdout.write=((a,...c)=>(i(a),t(a,...c))),process.stderr.write=((a,...c)=>(i(a),r(a,...c))),()=>{process.stdout.write=t,process.stderr.write=r}}function Dt(n,e=0){try{let t=jr(Qe(n)),r=e>=0&&e<=t.length?e:0;return{text:t.subarray(r).toString("utf8"),offset:t.length}}catch{return{text:"",offset:0}}}function us(n){try{return process.kill(n,0),!0}catch(e){return e.code==="EPERM"}}async function Br(n){await cs(Q(),{recursive:!0}),await Nr(At(n.pid),JSON.stringify(n))}async function Ur(n,e){let t=At(n);try{let r=JSON.parse(await Mr(t,"utf8"));if(r.denied===e)return;r.denied=e,await Nr(t,JSON.stringify(r))}catch{}}async function $t(n){await Fe(At(n)).catch(()=>{}),await Fe(Qe(n)).catch(()=>{})}async function Ft(){let n;try{n=await as(Q())}catch{return[]}let e=[];return await Promise.all(n.map(async t=>{if(!t.endsWith(".json"))return;let r=de.join(Q(),t),s;try{s=JSON.parse(await Mr(r,"utf8"))}catch{await Fe(r).catch(()=>{});return}s&&typeof s.pid=="number"&&us(s.pid)?e.push(s):(await Fe(r).catch(()=>{}),s?.pid&&await Fe(Qe(s.pid)).catch(()=>{}))})),e.sort((t,r)=>t.startedAt-r.startedAt)}async function Wr(n){try{process.kill(n,"SIGTERM")}catch{}await $t(n)}var Vr="127.0.0.1",ms=new Set(["localhost","127.0.0.1","::1"]);function gs(n){if(n)try{return new URL(n.includes("://")?n:`http://${n}`).hostname}catch{return}}function Jr(n){let e=gs(n);return!!e&&ms.has(e)}function Ze(n){return n instanceof Error?n.message:"Unknown error"}async function qr(n){let{getHtml:e,basePath:t,port:r,reloadEmitter:s,getServerExports:o,localOverride:i,trusted:a=!1,trustHint:c}=n,l=new ps;l.use("*",async(p,f)=>{if(!Jr(p.req.header("host")))return p.text("Forbidden: untrusted Host",403);await f()}),l.use("*",async(p,f)=>{await f(),p.res.headers.set("Cross-Origin-Opener-Policy","same-origin"),p.res.headers.set("Cross-Origin-Embedder-Policy","credentialless")});let d=["/__fs/*","/__api/*","/__ai"],u=async(p,f)=>{if(!a){let g=new URL(p.req.url).pathname,v=g.startsWith("/__fs")?"the filesystem":g==="/__ai"?"AI (your API keys)":"server-side code (server.ts)";Ur(process.pid,v);let w=c?`
609
+ ${c}`:"";return p.text(`Forbidden: this capability requires --trust.${w}`,403)}await f()},h=async(p,f)=>{let g=p.req.header("sec-fetch-site");if(g){if(g==="cross-site")return p.text("Forbidden: cross-site request",403)}else{let v=p.req.header("origin");if(v&&!Jr(v))return p.text("Forbidden: cross-origin request",403)}await f()};for(let p of d)l.use(p,u),l.use(p,h);l.use("/__log",h),l.post("/__log",async p=>{try{let{args:f}=await p.req.json();console.log(...f||[])}catch{}return p.json({ok:!0})}),l.get("/",p=>p.html(e())),l.post("/__fs/read",async p=>{try{let{path:f}=await p.req.json(),g=Nt(f,t),v=await Z.readFile(g);return new Response(new Uint8Array(v),{headers:{"Content-Type":"application/octet-stream"}})}catch(f){let g=Ze(f);return p.json({error:g},400)}}),l.post("/__fs/write",async p=>{try{let f=p.req.query("path");if(!f)return p.json({error:"Missing path"},400);let g=Nt(f,t);return await Z.mkdir(j.dirname(g),{recursive:!0}),await Z.writeFile(g,Buffer.from(await p.req.arrayBuffer())),p.json({success:!0})}catch(f){let g=Ze(f);return p.json({error:g},400)}});let b={log:console.log};l.post("/__api/:name",async p=>{try{let f=o?.(),g=p.req.param("name"),v=f?.[g]??b[g];if(!v||typeof v!="function")return p.json({error:`API function '${g}' not found`},404);let{args:w}=await p.req.json(),C=await v(...w||[]);return p.json({result:C})}catch(f){let g=Ze(f);return p.json({error:g},500)}}),l.post("/__ai",async p=>{try{let{messages:f,system:g,reasoning:v,provider:w,model:C,webSearch:J}=await p.req.json();if(!f||!Array.isArray(f)||f.length===0)return p.json({message:"messages array is required",code:"unknown",retryable:!1},400);let L=ys(w,C);if(typeof L=="string")return p.json({message:L,code:"unknown",retryable:!1},400);let st=[...g?[{role:"system",content:g}]:[],...f.map(Me=>({role:Me.role,content:Me.content}))],ee=await kt(L,{model:L.model,messages:st,stream:!0,reasoning:v??0,webSearch:J??!0});if(!ee.ok){let Me=await Tt(ee,L.protocol);return p.json(Me,ee.status)}let Jt=await Ct(ee,L.protocol);return Jt||console.warn("[tb.ai] Empty response from provider"),p.json({text:Jt})}catch(f){if(f instanceof A)return p.json({message:f.message,code:f.code,retryable:f.retryable},500);let g=Ze(f);return p.json({message:g,code:"unknown",retryable:!1},500)}}),l.get("/__models",async p=>{try{let f=await vs();return p.json(f)}catch{return p.json([],200)}});let m=["esm.sh","unpkg.com","cdn.jsdelivr.net","cdnjs.cloudflare.com"],S=new Ye;if(l.get("/proxy/*",async p=>{let f=new URL(p.req.url),v=(f.pathname+f.search).slice(7),w=v.lastIndexOf("https://");return w===-1?p.text("Invalid proxy URL",400):O(p,v.slice(w))}),i){let p=`/local/${i.name}/`;l.get("/local/*",async f=>{let{pathname:g}=new URL(f.req.url);if(!g.startsWith(p))return f.text("Not Found",404);let v=decodeURIComponent(g.slice(p.length));try{let w=Nt(v,i.serveDir),C=await Z.readFile(w);return new Response(C,{headers:{"Content-Type":xs(w)}})}catch{return f.text("Not Found",404)}})}async function O(p,f){let g;try{g=new URL(f)}catch{return p.text("Invalid URL",400)}if(g.protocol!=="https:")return p.text("HTTPS only",400);if(!m.includes(g.hostname))return p.text("Host not allowed",403);let v=await S.get(f);if(v)return new Response(v.body,{status:200,headers:Mt(v.contentType,v.cacheControl)});try{let w=await fetch(f,{headers:{Accept:p.req.header("Accept")||"*/*"},redirect:"follow"});if(!w.ok)return p.text(`Upstream ${w.status}`,w.status);let C=w.headers.get("Content-Type")||void 0,J=w.headers.get("Cache-Control")||void 0;if(w.body){let[L,st]=w.body.tee();return(async()=>{try{let ee=await new Response(st).arrayBuffer();await S.set(f,{body:Buffer.from(ee),contentType:C,cacheControl:J})}catch{}})(),new Response(L,{status:w.status,headers:Mt(C,J)})}return new Response(null,{status:w.status,headers:Mt(C,J)})}catch(w){return p.text(`Proxy fetch failed: ${w instanceof Error?w.message:w}`,502)}}s&&l.get("/__reload",p=>hs(p,async f=>{let g=()=>{f.writeSSE({event:"reload",data:""})};for(s.on("reload",g),f.onAbort(()=>{s.removeListener("reload",g)});;)await f.sleep(3e4)}));let _=/^\/(v\d+\/|stable\/|node\/|gh\/|@[^/]+\/[^@/]+@|[^@/]+@)/;l.notFound(async p=>{if(p.req.method!=="GET")return p.text("Not Found",404);let f=new URL(p.req.url);return _.test(f.pathname)?O(p,"https://esm.sh"+f.pathname+f.search):p.text("Not Found",404)});let $=fs({fetch:l.fetch,port:r,hostname:Vr});return{port:r,close:()=>$.close()}}var Gr={anthropic:"ANTHROPIC_API_KEY",openai:"OPENAI_API_KEY",gemini:"GOOGLE_API_KEY",openrouter:"OPENROUTER_API_KEY"};function ys(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=X(t)}catch{return`Unknown provider '${t}'.`}let o=Gr[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 bs="https://api.typebulb.com/api/models",ws=1440*60*1e3,ue=null;async function vs(){if(!ue||Date.now()-ue.fetchedAt>ws){let n=await fetch(bs);if(!n.ok)return ue?Hr(ue.models):[];ue={models:await n.json(),fetchedAt:Date.now()}}return Hr(ue.models)}function Hr(n){let e=new Set(Object.entries(Gr).filter(([,t])=>!!process.env[t]).map(([t])=>t));return n.filter(t=>e.has(t.provider))}function Mt(n,e){let t=new Headers;return n&&t.set("Content-Type",n),e&&t.set("Cache-Control",e),t.set("Access-Control-Allow-Origin","*"),t.set("Cross-Origin-Resource-Policy","cross-origin"),t}function xs(n){switch(j.extname(n).toLowerCase()){case".js":case".mjs":return"text/javascript";case".wasm":return"application/wasm";case".json":case".map":return"application/json";default:return"application/octet-stream"}}function Nt(n,e){let t=j.resolve(e,n),r=j.normalize(e),s=j.normalize(t);if(s!==r&&!s.startsWith(r+j.sep))throw new Error("Path traversal detected - access denied");return t}async function jt(n){let e=await import("net");return new Promise(t=>{let r=e.createServer();r.listen(n,Vr,()=>{let s=r.address(),o=typeof s=="object"&&s?s.port:n;r.close(()=>t(o))}),r.on("error",()=>{t(jt(n+1))})})}import Ss from"open";async function zr(n){await Ss(n)}import Kr from"chokidar";var Yr={persistent:!0,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50}};function Lt(n){let{bulbPath:e,emitter:t}=n,r=Kr.watch(e,Yr);return r.on("change",()=>{t.emit("reload")}),()=>r.close()}function Xr(n){let{dir:e,onChange:t,debounceMs:r=150}=n,s,o=Kr.watch(e,Yr);return o.on("all",()=>{s&&clearTimeout(s),s=setTimeout(t,r)}),()=>{s&&clearTimeout(s),o.close()}}import*as k from"fs/promises";import*as E from"path";import*as pe from"path";var Ps=pe.join(We,"pkg"),Rs=pe.join(We,"files"),Es=pe.join(We,"negative.json"),tt=class{pkgMem=new Map;fileMem=new Map;negativeCache=new K(new ie(Es));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await x();let t=await Y(Qr(e));return this.pkgMem.set(e,t),t}async setCachedDts(e,t,r){let s={content:t,url:r};this.pkgMem.set(e,s),await et(async()=>{await x(),await I(Qr(e),JSON.stringify(s))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await x();let t=await Ue(Zr(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await et(async()=>{await x(),await I(Zr(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await et(async()=>{await x(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return et(()=>this.negativeCache.clearNegative(e))}};async function et(n){try{await n()}catch{}}function Qr(n){return pe.join(Ps,F(n)+".json")}function Zr(n){return pe.join(Rs,F(n)+".txt")}var Bt;function ks(){return Bt||(Bt=wt({cache:new tt,cdnClient:Tr,packageService:qe,versionResolver:kr})),Bt}var en="file:///node_modules/";async function tn(n){let e=Je(n.emitKey,"typecheck");await x(),await k.rm(e,{recursive:!0,force:!0}),await k.mkdir(e,{recursive:!0});let t=Os(n.jsxImportSource,n.dependencies),r=await ks().resolve(n.code,n.dependencies,t),s=n.local?.name,o=s?r.filter(d=>d.pkg!==s):r,i=new Set;for(let d of o)for(let u of d.files){let h=rt(u.path);if(!h||i.has(h))continue;i.add(h);let b=E.join(e,"node_modules",h);await k.mkdir(E.dirname(b),{recursive:!0}),await k.writeFile(b,u.content,"utf8")}let a={};for(let d of o)for(let u of d.shims){let h=rt(u.path);h&&(a[u.module]=[`./node_modules/${h}`])}for(let d of o){if(d.ambient)continue;let u=rt(d.mainPath);u&&(a[d.pkg]=[`./node_modules/${u}`])}let c=new Set;for(let d of o)for(let u of d.files){if(!u.ambient)continue;let h=rt(u.path);h&&c.add(`node_modules/${h}`)}if(n.local){delete a[n.local.name];let d=await Is(n.local,e);d?a[n.local.name]=[`./node_modules/${n.local.name}/${d}`]:console.warn(` local: '${n.local.name}' ships no type defs; check cannot type against it.`)}let l=Ts(n.jsxImportSource,a,[...c]);return await k.writeFile(E.join(e,"tsconfig.json"),JSON.stringify(l,null,2)+`
610
+ `,"utf8"),await k.writeFile(E.join(e,"code.tsx"),n.code,"utf8"),await k.writeFile(E.join(e,"tb.d.ts"),mt,"utf8"),{dir:e}}function Ts(n,e,t=[]){return{compilerOptions:{target:"es2023",module:"esnext",moduleResolution:"bundler",lib:_s([...ft,...ht]),jsx:"react-jsx",jsxImportSource:n??"react",strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0,baseUrl:".",paths:e},include:["code.tsx","tb.d.ts",...t]}}function _s(n){return n.filter(e=>!e.since).map(e=>Cs(e.name))}function Cs(n){return n.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 Os(n,e){let t=n??("react"in e?"react":void 0);return t?[`${t}/jsx-runtime`,`${t}/jsx-dev-runtime`]:[]}function rt(n){if(!n.startsWith(en))return;let e=n.slice(en.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}async function Is(n,e){if(!n.typesAbs)return;let t=E.dirname(n.typesAbs),r=E.join(e,"node_modules",n.name);for(let s of await As(t)){let o=E.join(r,E.relative(t,s));await k.mkdir(E.dirname(o),{recursive:!0}),await k.copyFile(s,o)}return E.basename(n.typesAbs)}async function As(n){let e=[];async function t(r){let s=await k.readdir(r,{withFileTypes:!0});for(let o of s){let i=E.join(r,o.name);o.isDirectory()?await t(i):/\.d\.ts(\.map)?$/.test(o.name)&&e.push(i)}}return await t(n),e}import*as D from"fs/promises";import*as W from"path";import{existsSync as Ds}from"fs";var $s="^22";async function rn(n){let e=Je(n.emitKey,"typecheck-server");await x(),await D.rm(e,{recursive:!0,force:!0}),await D.mkdir(e,{recursive:!0});let t=W.join(n.bulbDir,".typebulb"),r=Ke(n.server).filter(i=>i!==n.local?.name);await ze([`@types/node@${$s}`,...r],t);let s=W.join(t,"node_modules"),o=W.join(e,"node_modules");return await Ms(s,o),await D.writeFile(W.join(e,"server.ts"),n.server,"utf8"),await D.writeFile(W.join(e,"tb.d.ts"),gt,"utf8"),await D.writeFile(W.join(e,"tsconfig.json"),JSON.stringify(Fs(n.local),null,2)+`
611
+ `,"utf8"),{dir:e}}function Fs(n){let e={target:"es2023",module:"esnext",moduleResolution:"node",lib:["ES2023"],types:["node"],strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0};if(n?.typesAbs){let t=o=>o.replace(/\\/g,"/"),r=t(W.dirname(n.typesAbs)),s=t(n.typesAbs).replace(/\.d\.ts$/,"");e.baseUrl=".",e.paths={[n.name]:[s],[`${n.name}/*`]:[`${r}/*`]}}return{compilerOptions:e,include:["server.ts","tb.d.ts"]}}async function Ms(n,e){if(!Ds(n)){await D.mkdir(e,{recursive:!0});return}await D.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await D.symlink(n,e,t)}import{readFileSync as Ns,writeFileSync as js,mkdirSync as Ls}from"fs";import{join as Bs}from"path";function nn(){return Bs(Xe(),"trust.json")}function Ut(){try{let n=JSON.parse(Ns(nn(),"utf8"));return new Set(Array.isArray(n)?n:[])}catch{return new Set}}function Us(n){Ls(Xe(),{recursive:!0}),js(nn(),JSON.stringify([...n]))}function sn(n){return Ut().has(le(n))}function on(n,e){let t=Ut(),r=le(n);(e?t.has(r):!t.has(r))||(e?t.add(r):t.delete(r),Us(t))}function an(){return[...Ut()]}var Js="0.9.3";async function Hs(n,e){let{bulb:t,config:r}=await Ce(n);!t.code&&!t.server&&(console.error("Bulb has neither **code.tsx** nor **server.ts**; nothing to check."),process.exit(1));let s=[];if(t.code){let{dir:i}=await tn({code:t.code,dependencies:r.dependencies??{},jsxImportSource:r.jsxImportSource,emitKey:n,local:e});s.push({role:"client",dir:i})}if(t.server){let{dir:i}=await rn({server:t.server,bulbDir:R.dirname(n),emitKey:n,local:e?{name:e.name,typesAbs:e.typesAbs}:void 0});s.push({role:"server",dir:i})}let o=!1;for(let{role:i,dir:a}of s){let{stdout:c,exitCode:l}=await Vs(a);for(let d of c.split(/\r?\n/))d.trim()&&console.log(`${i} ${d}`);l!==0&&(o=!0)}o&&process.exit(1)}function Vs(n){return new Promise(e=>{let t=Ws("npx",["tsc","--noEmit"],{cwd:n,shell:!0}),r="";t.stdout?.on("data",s=>{r+=s.toString()}),t.stderr?.on("data",s=>{r+=s.toString()}),t.on("close",s=>e({stdout:r,exitCode:s??1}))})}async function qs(n,e,t){ct();let r=async()=>{let{bulb:s,config:o}=await Ce(n),i=R.dirname(n);o.env?.length&&fe(o.env,i),await Rt(s.server,i,t)};if(console.log(`Running ${R.basename(n)}...`),await r(),e){console.log(`Watching for changes...
612
+ `);let s=new Wt;s.on("reload",async()=>{try{console.log("Re-running..."),await r()}catch(o){console.error("Error:",o)}}),Lt({bulbPath:n,emitter:s})}}async function Gs(n,e,t,r){let s=process.cwd(),o=Lr(process.pid),i=e.watch?new Wt:void 0;ct(),console.log(`Loading ${R.basename(n)}...`);let{html:a,bulb:c,serverExports:l}=await Et(n,e.watch,e.trust,r),d=await jt(e.port),u=await qr({getHtml:()=>a,basePath:s,port:d,reloadEmitter:i,getServerExports:()=>l,localOverride:r?{name:r.name,serveDir:r.serveDir}:void 0,trusted:e.trust,trustHint:t}),h=`http://localhost:${d}`;await Br({pid:process.pid,port:d,url:h,file:n,startedAt:Date.now(),trust:e.trust}),console.log(`
613
+ ${c.name}`),console.log(` ${h}`),console.log(e.trust?" trust: granted (filesystem, AI, server.ts enabled)":` trust: sandboxed \u2014 re-run with --trust to enable filesystem / AI / server.ts
614
+ `),e.watch&&console.log(` Watching for changes...
615
+ `);let b,m;if(e.watch&&i){let O=new Wt;if(O.on("reload",async()=>{try{console.log("Recompiling...");let _=await Et(n,!0,e.trust,r);a=_.html,l=_.serverExports,i.emit("reload"),console.log(`Done. Browser reloading...
616
+ `)}catch(_){console.error("Compile error:",_)}}),b=Lt({bulbPath:n,emitter:O}),r){let{name:_,serveDir:$}=r;m=Xr({dir:$,onChange:()=>{console.log(`Local package '${_}' changed. Browser reloading...
617
+ `),i.emit("reload")}})}}e.open&&await zr(h);let S=async()=>{console.log(`
618
+ Shutting down...`),u.close(),b?.(),m?.(),o(),await $t(process.pid);let O=R.join(R.dirname(n),".typebulb","server.mjs");await nt.rm(O,{force:!0}).catch(()=>{}),process.exit(0)};process.on("SIGINT",S),process.on("SIGTERM",S)}function zs(n,e){return/^\d+$/.test(e)?n.find(t=>t.pid===parseInt(e,10)):n.find(t=>le(t.file)===le(e))}function cn(n,e){for(let t of n)e(` ${t.url} pid ${t.pid} ${t.trust?"trusted":"restricted"} ${t.file}`)}function ln(n,e){if(!n.length){console.log("No running bulb servers.");return}console.log("Running bulb servers:"),cn(n,t=>console.log(t)),console.log(`
619
+ `+e)}function dn(n,e,t){let r=zs(n,e);if(r)return r;console.error(`No running server for '${e}'.`),n.length?(console.error(`Running servers (try \`typebulb ${t} <file|pid>\`):`),cn(n,s=>console.error(s))):console.error("No bulb servers are running."),process.exit(1)}async function Ks(n,e){let t=await Ft();if(!n){ln(t,"Run `typebulb logs <file|pid>` to print one server's console.");return}let r=dn(t,n,"logs"),s=Dt(r.pid),o=s.text;if(e.lines&&e.lines>0){let i=o.split(`
620
+ `);i.length&&i[i.length-1]===""&&i.pop(),o=i.slice(-e.lines).join(`
621
+ `)}if(process.stdout.write(o),o&&!o.endsWith(`
622
+ `)&&process.stdout.write(`
623
+ `),e.follow){let i=s.offset,a=setInterval(()=>{let l=Dt(r.pid,i);i=l.offset,l.text&&process.stdout.write(l.text)},500),c=()=>{clearInterval(a),process.exit(0)};process.on("SIGINT",c),process.on("SIGTERM",c),await new Promise(()=>{})}}async function Ys(n){let e=await Ft();if(!n){ln(e,"Run `typebulb stop <file|pid>` to stop one.");return}let t=dn(e,n,"stop");await Wr(t.pid),console.log(`Stopped ${R.basename(t.file)} (pid ${t.pid}, ${t.url}).`)}async function Xs(n,e){if(!n){e||(console.error("Usage: typebulb untrust <file.bulb.md>"),process.exit(1));let r=an();if(!r.length){console.log("No bulbs are remembered as trusted.");return}console.log("Trusted bulbs (run with fs/AI/server.ts without --trust):");for(let s of r)console.log(` ${s}`);return}let t=R.resolve(n);t.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1)),on(t,e),console.log(e?`Trusted ${R.basename(t)} \u2014 runs with fs / AI / server.ts (no --trust needed).`:`Untrusted ${R.basename(t)} \u2014 runs Restricted.`),console.log(` ${t}`)}async function Qs(){let n=Qt(process.argv.slice(2));if(n.version&&(console.log(`typebulb ${Js}`),process.exit(0)),n.help&&(Zt(),process.exit(0)),n.subcommand==="logs"){await Ks(n.file||void 0,{follow:n.follow,lines:n.lines});return}if(n.subcommand==="stop"){await Ys(n.file||void 0);return}if(n.subcommand==="trust"||n.subcommand==="untrust"){await Xs(n.file||void 0,n.subcommand==="trust");return}let e;if(!n.file||n.file==="."){let a=await Ir(process.cwd());a||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=a}else e=R.resolve(n.file);try{await nt.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=!n.noTrust&&sn(e);t&&!n.trust&&console.log("trust: granted from memory (run `typebulb untrust` to revoke)"),n.trust=n.noTrust?!1:n.trust||t;let r=n.file&&n.file!=="."?n.file:R.relative(process.cwd(),e)||R.basename(e),s=`npx typebulb --trust ${r.includes(" ")?`"${r}"`:r}`,o;try{o=await Ce(e)}catch{}let i;if(n.local){o&&!(n.local.name in(o.config.dependencies??{}))&&(console.error(`--replace: '${n.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),o&&(!o.bulb.code||n.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{i=await Yt(n.local)}catch(a){console.error(a instanceof Error?a.message:String(a)),process.exit(1)}console.log(`replace: ${i.name} \u2192 ${R.relative(process.cwd(),i.dir)||"."}`)}if(n.subcommand==="check"){await Hs(e,i);return}if(o&&o.bulb.server&&(!o.bulb.code||n.server)){n.trust||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
624
+ ${s}`),process.exit(1)),await qs(e,n.watch,i);return}await Gs(e,n,s,i)}Qs().catch(n=>{console.error("Error:",n.message),process.exit(1)});