typebulb 0.39.0 → 0.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,7 +44,7 @@ typebulb call <file> <fn> […] Invoke one server.ts export headlessly: prints
44
44
  typebulb send <file> [msg] Push a message into a running bulb's page (its tb.onMessage handlers); the client-side twin of call, no --trust.
45
45
  With --wait, a handler's non-undefined return prints on stdout (JSON; a bare string raw)
46
46
  typebulb send <file> tb:snapshot Print the live page's rendered outline (roles, names, visible text)
47
- typebulb get <file> <kind> Print one block's content (data, insight, code, …) to stdout; absent block exits 1
47
+ typebulb get <file> <kind> Print one block's content (data, insight, code, …) to stdout; absent block exits 2, real errors 1
48
48
  typebulb put <file> <k>=<src> Write a file's (or stdin's: <kind>=-) content into a block, surgically — replace, or append if absent; several pairs are one atomic write; identical content writes nothing. No --trust
49
49
  typebulb pull <url|file> Fetch a bulb from typebulb.com into typebulbs/u/<user>/<slug>.bulb.md
50
50
  typebulb push <file> Upload a local bulb to typebulb.com as you (needs TYPEBULB_TOKEN in .env)
@@ -2280,7 +2280,7 @@ var Patcher = class {
2280
2280
 
2281
2281
  // cli/agents/pi/server/piPatcherExtension.ts
2282
2282
  var DESCRIPTION = true ? "Apply unified diffs to files \u2014 tolerant of form, strict about intent. Repairs sloppy AI-generated diffs (mangled headers, whitespace drift, missing prefixes; line numbers can be wrong or absent \u2014 hunks anchor by fuzzy-matched context lines) and applies all hunks atomically when the intent is unambiguous; fails with a precise, typed error when it isn't. Use for multi-hunk edits in one step, or when exact string-replacement editing fails on whitespace or invisible characters." : "Apply unified diffs to files.";
2283
- var BUILD_TAG = true ? "matchu-patchu-pi 0.3.1, built 2026-07-24 19:59:08" : "matchu-patchu-pi dev";
2283
+ var BUILD_TAG = true ? "matchu-patchu-pi 0.3.1, built 2026-07-24 20:09:43" : "matchu-patchu-pi dev";
2284
2284
  var errorBlocks = (errors) => {
2285
2285
  const parts = [`Patch failed with ${errors.length} error(s):`];
2286
2286
  for (const e of errors) parts.push("", e.toString());
package/dist/index.js CHANGED
@@ -1286,7 +1286,8 @@ Usage:
1286
1286
  rendered outline (roles, names, visible text).
1287
1287
  typebulb get <file> <kind> Print one block's content to stdout (kind: code,
1288
1288
  css, html, data, infer, insight, config, notes).
1289
- Absent block: exit 1. Pipe-safe (\u2026 | jq).
1289
+ Absent block: exit 2 (real errors: 1).
1290
+ Pipe-safe (\u2026 | jq).
1290
1291
  typebulb put <file> <k>=<src> Write a file's content into a block, surgically \u2014
1291
1292
  the rest of the bulb is preserved verbatim.
1292
1293
  <src> may be - for stdin. Several <kind>=<src>
@@ -1617,7 +1618,7 @@ declare const tb: {${hy}${by}${wy}${gy}${yy}
1617
1618
  `)}if(process.stdout.write(s),s&&!s.endsWith(`
1618
1619
  `)&&process.stdout.write(`
1619
1620
  `),e.follow&&e.run===void 0){let i=n.offset,o=setInterval(()=>{let c=Be(t.pid,i);i=c.offset,c.text&&process.stdout.write(c.text)},500),a=()=>{clearInterval(o),process.exit(0)};process.on("SIGINT",a),process.on("SIGTERM",a),await new Promise(()=>{})}}var ZP=r=>new Promise(e=>setTimeout(e,r));async function Ky(r,e){if(!r){Nu(await Q(process.cwd()),"Run `typebulb wait <file|pid>` to block until one logs a new line.");return}let t=Iu(await Q(),r,"wait",process.cwd(),is()),n=t.agent!=null,i=process.env.TYPEBULB_WAIT_SHIM==="1",o=e.timeoutSec??1800,a=e.match??"",c=Be(t.pid).offset,l=ql(t.pid,a)??(a?ql(t.pid):void 0),f=l!==void 0&&l<=c?l:a?0:c,u=Date.now()+o*1e3,d=n?1e4:1e3,p=2e3,y,m="",h=0;for(;;){let x=Be(t.pid,f);if(f=x.offset,x.text){m+=x.text;let A=m.split(`
1620
- `);m=A.pop()??"";for(let P of A)P.trim()&&(e.match&&!P.includes(e.match)||(console.log(P),y??=Date.now()+d,n&&(P.includes("] compile error")||P.includes("] runtime error"))&&(y=Math.min(y,Date.now()+p))))}if(y&&Date.now()>=y)break;if(!i&&!y&&Date.now()>=u){console.error(`timeout: no ${e.match?`line matching '${e.match}'`:"new output"} from ${os(t)} within ${o}s`),h=2;break}if(!Jl(t.pid)){y||(console.error(`server ${os(t)} (pid ${t.pid}) exited while waiting`),process.exit(3));break}await ZP(400)}Zi(t.pid,f,a),process.exit(h)}async function Hy(r){if(!r){Nu(await Q(process.cwd()),"Run `typebulb stop <file|pid>` to stop one.");return}let e=Iu(await Q(),r,"stop",process.cwd(),is());await Vt(e.pid),console.log(`Stopped ${os(e)} (pid ${e.pid}, ${e.url}).`)}async function Wy(r){let e=process.cwd(),t=r==="agent"?is():void 0,n=r==="global"?await Q():r==="bulbs"?await Q(e):(await Q()).filter(i=>i.agent!=null&&i.cwd!=null&&se(i.cwd)===se(e)&&(!t||i.agent===t)),s=r==="global"?"server":r==="agent"?"mirror":"bulb";if(!n.length){console.log(r==="global"?"No running bulb servers.":`No running ${s}s for this project.`);return}await Promise.all(n.map(i=>Vt(i.pid))),console.log(`Stopped ${n.length} ${s}${n.length===1?"":"s"}:`);for(let i of n)console.log(` ${i.url} pid ${i.pid} ${os(i)}`)}je();import*as Yy from"path";async function Vy(r,e,t=0){let n=e!==void 0&&e.startsWith("tb:");n&&t<=0&&(t=Vc);let s=Yy.resolve(r),i=Nr(await Q(),s)[0];i||(console.error(`No running server for '${r}'. Start it first: npx typebulb ${r}`),process.exit(1));let o=async d=>{let p=await fetch(`${i.url}/__send${d>0?`?reply=${d}`:""}`,{method:"POST",headers:{"Content-Type":"text/plain"},body:e??""});return p.ok||(console.error(`send failed: HTTP ${p.status} from ${i.url}/__send`),process.exit(1)),await p.json().catch(()=>({}))},a={};try{let d=Date.now()+t;do{if(a=await o(t>0?Math.max(d-Date.now(),1e3):0),(a.clients??0)>0||Date.now()>=d)break;await new Promise(p=>setTimeout(p,150))}while(!0)}catch(d){console.error(`send failed: ${d instanceof Error?d.message:String(d)}`),process.exit(1)}let c=a.clients??0,l=`${c} page${c===1?"":"s"}`;if(c===0){t>0?console.error(`No page connected after ${t/1e3}s \u2014 is the bulb open?`):console.error("Sent, but no page is connected yet \u2014 open the bulb and retry."),n&&process.exit(1);return}console.error(`Sent to ${l}.`);let f=a.results??[],u=a.errors??[];for(let d of u)console.error(`handler error: ${d}`);if(u.length&&process.exit(1),f.length>1&&(console.error(`${f.length} replies from ${l} \u2014 one reply owns stdout: at most one tb.onMessage handler, in one page, may return a value.`),process.exit(1)),f.length===1){let d;try{d=JSON.parse(f[0])}catch{d=void 0}console.log(typeof d=="string"?d:f[0])}else a.timedOut&&(n&&(console.error(`No reply to '${e}' within ${t/1e3}s \u2014 reload the page and retry.`),process.exit(1)),console.error(`(no reply within ${t/1e3}s \u2014 a slow handler's return needs a larger --wait=ms)`))}po();nu();me();import*as Gy from"fs/promises";async function zy(r,e){let t=await Gy.readFile(r,"utf-8"),n=oe(t);n||(console.error(`Not a valid bulb: ${r}`),process.exit(1));let s=ie[e].path,i=n.files.get(s);i===void 0&&(console.error(`No **${s}** block in ${r}`),process.exit(1)),i.length&&process.stdout.write(i.endsWith(`
1621
+ `);m=A.pop()??"";for(let P of A)P.trim()&&(e.match&&!P.includes(e.match)||(console.log(P),y??=Date.now()+d,n&&(P.includes("] compile error")||P.includes("] runtime error"))&&(y=Math.min(y,Date.now()+p))))}if(y&&Date.now()>=y)break;if(!i&&!y&&Date.now()>=u){console.error(`timeout: no ${e.match?`line matching '${e.match}'`:"new output"} from ${os(t)} within ${o}s`),h=2;break}if(!Jl(t.pid)){y||(console.error(`server ${os(t)} (pid ${t.pid}) exited while waiting`),process.exit(3));break}await ZP(400)}Zi(t.pid,f,a),process.exit(h)}async function Hy(r){if(!r){Nu(await Q(process.cwd()),"Run `typebulb stop <file|pid>` to stop one.");return}let e=Iu(await Q(),r,"stop",process.cwd(),is());await Vt(e.pid),console.log(`Stopped ${os(e)} (pid ${e.pid}, ${e.url}).`)}async function Wy(r){let e=process.cwd(),t=r==="agent"?is():void 0,n=r==="global"?await Q():r==="bulbs"?await Q(e):(await Q()).filter(i=>i.agent!=null&&i.cwd!=null&&se(i.cwd)===se(e)&&(!t||i.agent===t)),s=r==="global"?"server":r==="agent"?"mirror":"bulb";if(!n.length){console.log(r==="global"?"No running bulb servers.":`No running ${s}s for this project.`);return}await Promise.all(n.map(i=>Vt(i.pid))),console.log(`Stopped ${n.length} ${s}${n.length===1?"":"s"}:`);for(let i of n)console.log(` ${i.url} pid ${i.pid} ${os(i)}`)}je();import*as Yy from"path";async function Vy(r,e,t=0){let n=e!==void 0&&e.startsWith("tb:");n&&t<=0&&(t=Vc);let s=Yy.resolve(r),i=Nr(await Q(),s)[0];i||(console.error(`No running server for '${r}'. Start it first: npx typebulb ${r}`),process.exit(1));let o=async d=>{let p=await fetch(`${i.url}/__send${d>0?`?reply=${d}`:""}`,{method:"POST",headers:{"Content-Type":"text/plain"},body:e??""});return p.ok||(console.error(`send failed: HTTP ${p.status} from ${i.url}/__send`),process.exit(1)),await p.json().catch(()=>({}))},a={};try{let d=Date.now()+t;do{if(a=await o(t>0?Math.max(d-Date.now(),1e3):0),(a.clients??0)>0||Date.now()>=d)break;await new Promise(p=>setTimeout(p,150))}while(!0)}catch(d){console.error(`send failed: ${d instanceof Error?d.message:String(d)}`),process.exit(1)}let c=a.clients??0,l=`${c} page${c===1?"":"s"}`;if(c===0){t>0?console.error(`No page connected after ${t/1e3}s \u2014 is the bulb open?`):console.error("Sent, but no page is connected yet \u2014 open the bulb and retry."),n&&process.exit(1);return}console.error(`Sent to ${l}.`);let f=a.results??[],u=a.errors??[];for(let d of u)console.error(`handler error: ${d}`);if(u.length&&process.exit(1),f.length>1&&(console.error(`${f.length} replies from ${l} \u2014 one reply owns stdout: at most one tb.onMessage handler, in one page, may return a value.`),process.exit(1)),f.length===1){let d;try{d=JSON.parse(f[0])}catch{d=void 0}console.log(typeof d=="string"?d:f[0])}else a.timedOut&&(n&&(console.error(`No reply to '${e}' within ${t/1e3}s \u2014 reload the page and retry.`),process.exit(1)),console.error(`(no reply within ${t/1e3}s \u2014 a slow handler's return needs a larger --wait=ms)`))}po();nu();me();import*as Gy from"fs/promises";async function zy(r,e){let t=await Gy.readFile(r,"utf-8"),n=oe(t);n||(console.error(`Not a valid bulb: ${r}`),process.exit(1));let s=ie[e].path,i=n.files.get(s);i===void 0&&(console.error(`No **${s}** block in ${r}`),process.exit(2)),i.length&&process.stdout.write(i.endsWith(`
1621
1622
  `)?i:i+`
1622
1623
  `)}me();import*as as from"fs/promises";async function Qy(r,e){let t=await as.readFile(r,"utf-8"),n=[];for(let{kind:i,source:o}of e){let a;try{a=o==="-"?await tO():await as.readFile(o,"utf-8")}catch(c){Xy(`Cannot read ${i}'s source: ${c instanceof Error?c.message:String(c)}`)}n.push({kind:i,content:Zy(a),label:o==="-"?"stdin":o})}let s;try{s=eO(t,n)}catch(i){Xy(`${r}: ${i instanceof Error?i.message:String(i)}`)}for(let i of s.upToDate)console.log(`${ie[i].path}: already up to date`);if(s.written.length){await as.writeFile(r,s.text);for(let i of s.written)console.log(`${ie[i.kind].path}: ${i.created?"created":"replaced"} from ${i.label} (${i.chars.toLocaleString()} chars)`)}}function eO(r,e){let t=oe(r);if(!t)throw new Error("not a valid bulb");let n=r,s=[],i=[];for(let{kind:o,content:a,label:c}of e){let l=ie[o].path,f=t.files.get(l);if(f!==void 0&&Zy(f)===a){i.push(o);continue}let u=Kr(n,o,a);if(u===n)throw new Error(`the **${l}** block's fence is unterminated; refusing to rewrite inside it`);n=u,s.push({kind:o,created:f===void 0,chars:a.length,label:c})}return{text:n,written:s,upToDate:i}}function Zy(r){return(r.charCodeAt(0)===65279?r.slice(1):r).replace(/\r\n/g,`
1623
1624
  `).trimEnd()}function Xy(r){console.error(r),process.exit(1)}async function tO(){let r=[];for await(let e of process.stdin)r.push(e);return Buffer.concat(r).toString("utf-8")}xt();Me();me();io();import*as _t from"fs/promises";import*as Xo from"path";import{EventEmitter as ab}from"events";import gO from"open";Er();me();import{Hono as aO}from"hono";import{serve as cO}from"@hono/node-server";import{streamSSE as lO}from"hono/streaming";import*as nb from"fs/promises";wr();Dn();br();import*as $u from"fs/promises";import*as cs from"path";var Ho=class{async get(e){let t=Oe(e),n=cs.join(Mn,t+".bin"),s=cs.join(Mn,t+".json");try{let[i,o]=await Promise.all([$u.readFile(n),$u.readFile(s,"utf8")]),a=JSON.parse(o);return{body:i,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await G();let n=Oe(e),s=cs.join(Mn,n+".bin"),i=cs.join(Mn,n+".json"),o={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([we(s,t.body),we(i,JSON.stringify(o))])}};var eb=`
@@ -2002,5 +2003,5 @@ ${yO}
2002
2003
  `);let c=0,l=Promise.resolve();Ct({target:r,onChange:()=>{let f=++c;l=l.then(async()=>{if(f===c)try{console.log("Re-running..."),await a()}catch(u){console.error("Error:",u)}})}})}}xt();Me();import{Console as kO}from"node:console";je();async function yb(r,e,t,n,s){PO();try{let p=Nr(await Q(),r)[0];p&&(Zi(p.pid,Be(p.pid).offset),console.error(`note: 'call' boots a fresh server.ts instance; the running server (${p.url}) is not contacted \u2014 state shared with it must live on disk.`))}catch{}let i=Se(t),{bulb:o,config:a}=await Ne(r);o.server||us("This bulb has no **server.ts** block; nothing to call."),kt(i,r,o.server),s&&await Or(r,s);let c;try{c=await Un(o.server,r,n,a.dependencies,s)}catch(p){us(p instanceof Error?p.message:String(p))}let l=Vo(c,e.fn);if(!l){let p=[...Object.keys(c).filter(y=>typeof c[y]=="function"),...Object.keys(Yo)];us(`Function '${e.fn}' not found. Available: ${p.length?p.join(", "):"(none)"}.`)}let f=await xO(e);if(Go(l)){try{for await(let p of l(...f))await gb(JSON.stringify(p,bb)+`
2003
2004
  `)}catch(p){us(p instanceof Error?p.stack??p.message:String(p))}return hb(0)}let u;try{u=await l(...f)}catch(p){us(p instanceof Error?p.stack??p.message:String(p))}let d=TO(u);d!==void 0&&await gb(d+`
2004
2005
  `),hb(0)}function hb(r){process.exitCode=r,setTimeout(()=>process.exit(r),2e3).unref?.()}async function xO(r){if(r.hasArgsFlag){let e=r.argsJson??"";return e==="-"&&(e=await OO()),AO(e)}return EO(r.positional)}function EO(r){return r.map(e=>{try{return JSON.parse(e)}catch{return e}})}function AO(r){let e;try{e=JSON.parse(r)}catch(t){throw new Error(`--args must be a JSON array: ${t instanceof Error?t.message:String(t)}`)}if(!Array.isArray(e))throw new Error(`--args must be a JSON array, got ${e===null?"null":typeof e}`);return e}function TO(r){if(r!==void 0)return JSON.stringify(r,bb,2)}function bb(r,e){return typeof e=="bigint"?e.toString():e}function us(r){process.stderr.write(r+`
2005
- `),process.exit(1)}function PO(){let r=new kO(process.stderr,process.stderr);console.log=r.log.bind(r),console.info=r.info.bind(r),console.debug=r.debug.bind(r),console.dir=r.dir.bind(r)}function gb(r){return new Promise((e,t)=>{process.stdout.write(r,n=>n?t(n):e())})}async function OO(){let r=[];for await(let e of process.stdin)r.push(e);return Buffer.concat(r).toString("utf-8")}var ju="0.39.0";function wb(r,e){r||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
2006
+ `),process.exit(1)}function PO(){let r=new kO(process.stderr,process.stderr);console.log=r.log.bind(r),console.info=r.info.bind(r),console.debug=r.debug.bind(r),console.dir=r.dir.bind(r)}function gb(r){return new Promise((e,t)=>{process.stdout.write(r,n=>n?t(n):e())})}async function OO(){let r=[];for await(let e of process.stdin)r.push(e);return Buffer.concat(r).toString("utf-8")}var ju="0.39.1";function wb(r,e){r||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
2006
2007
  ${e}`),process.exit(1))}async function CO(){let r=mm(process.argv.slice(2));if(r.version&&(console.log(`typebulb ${ju}`),process.exit(0)),r.help&&(hm(),process.exit(0)),Iy(),r.subcommand==="logs"){await Jy(r.file||void 0,{follow:r.follow,clear:r.clear,run:r.run,lines:r.lines});return}if(r.subcommand==="wait"){await Ky(r.file||void 0,{match:r.match,timeoutSec:r.timeoutSec});return}if(r.subcommand==="stop"){r.stopScope?await Wy(r.stopScope):await Hy(r.file||void 0);return}if(r.subcommand==="send"){await Vy(r.file,r.sendMessage,r.sendWaitMs??0);return}if(r.subcommand==="skill"){await Fy(ju);return}if(r.subcommand==="models"){await By(r.mode);return}if(r.subcommand==="pull"){await Bh(r.file||void 0,{force:r.force,mode:r.mode});return}if(r.subcommand==="push"){await Fh(r.file||void 0,{force:r.force,mode:r.mode});return}if(r.subcommand==="agent"){await(r.agentTarget?fb(r):Dy(ju));return}if(r.subcommand==="trust"||r.subcommand==="untrust"){await Ny(r.file||void 0,r.subcommand==="trust");return}let e;if(!r.file||r.file==="."){let c=await sh(process.cwd());c||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=c}else e=rr.resolve(r.file);if(await vb.access(e).then(()=>!0,()=>!1)||(qr().includes(r.file)&&(console.error(`To open the ${r.file} agent mirror, run: npx typebulb agent:${r.file}`),process.exit(1)),console.error(`File not found: ${e}`),process.exit(1)),e.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1)),r.subcommand==="get"){await zy(e,r.blockKind);return}if(r.subcommand==="put"){await Qy(e,r.blockPairs);return}let n=r.file&&r.file!=="."?r.file:rr.relative(process.cwd(),e)||rr.basename(e),s=`npx typebulb --trust ${n.includes(" ")?`"${n}"`:n}`;if(r.subcommand==="predict"){await Ry(e,s);return}let i=!r.noTrust&&Yt(e);i&&!r.trust&&console.error("trust: granted from memory (run `typebulb untrust` to revoke)"),r.trust=r.noTrust?!1:r.trust||i;let o;try{o=await Ne(e)}catch{}let a;if(r.local){o&&!(r.local.name in(o.config.dependencies??{}))&&(console.error(`--replace: '${r.local.name}' is not a dependency in this bulb's config.json; nothing to replace.`),process.exit(1)),o&&r.subcommand!=="call"&&(!o.bulb.code||r.server)&&console.warn("warning: --replace has no effect in server mode (the override is client-only).");try{a=await Xu(r.local)}catch(c){console.error(c instanceof Error?c.message:String(c)),process.exit(1)}console.error(`replace: ${a.name} \u2192 ${rr.relative(process.cwd(),a.dir)||"."}`)}if(r.subcommand==="check"){await _y(e,a);return}if(r.subcommand==="call"){wb(r.trust,s),await yb(e,{fn:r.fn,positional:r.callArgs,argsJson:r.argsJson,hasArgsFlag:r.hasArgsFlag},r.mode,a,r.batch);return}if(o&&o.bulb.server&&(hi(o.bulb)||r.server)){wb(r.trust,s),await mb(e,r.watch,r.mode,a,r.batch);return}await cb(e,r,s,a)}CO().catch(r=>{console.error("Error:",r.message),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebulb",
3
- "version": "0.39.0",
3
+ "version": "0.39.1",
4
4
  "description": "Typebulb CLI to run single-file markdown apps called bulbs, either as standalone web apps or embedded in agent responses.",
5
5
  "license": "MIT",
6
6
  "repository": {