typebulb 0.55.3 → 0.55.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -229,7 +229,7 @@ One exception: if `TYPEBULB_MIRROR=1` is set in your environment, the user is pr
229
229
 
230
230
  - **First, can it even run inline?** A bulb needing `tb.ai`, `tb.infer`, `tb.fs`, or `server.ts` must be **local** — inline bulbs are client-only, so those calls fail there. The choice below is only for client-only bulbs.
231
231
  - **Is anyone watching?** An inline bulb only renders live when the agent mirror is open; with none it shows as raw text. `npx typebulb agent` starts the mirror if needed and prints its link — share it with the user; don't make the user start anything.
232
- - **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **inline**: emit it in a `bulb` block so it renders live in the conversation.
232
+ - **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **inline**: emit it in a `bulb` block, straight into the reply. Don't draft it as a `.bulb.md` and test it first: a broken one reports its own error back to you (below), and the user expects a snappy response with an inline bulb.
233
233
  - **A tool worth keeping** — something to reuse, run on its own, or refine over several turns. → **local**: write a `.bulb.md` file run with `npx typebulb`. An inline block is throwaway and can't be edited in place, so it's the wrong fit for anything iterative.
234
234
 
235
235
  ### Emitting an inline bulb
@@ -279,7 +279,7 @@ That one launch *is* the loop: the server watches the file, so every save recomp
279
279
  - **Slow work settles in the handler** — a handler may be async, and the reply waits for its promise: keep a done-promise, `await` it, and return the finished state, with `--wait=<ms>` sized to the work (instead of polling flags in a sleep loop, or snapshot-polling from outside). The sharp edge: settle the promise on *every* exit of the run — success, failure, supersession, in a `finally` — and start idle with an already-resolved one, or the handler hangs and reads as a broken bulb. One case stays two-step: a `tb:*` gesture that kicks off slow work replies with the immediate frame (runtime-answered), so follow it with this settle probe.
280
280
  - **Rendered truth** — `typebulb send <file> tb:snapshot` prints the page's accessibility outline (roles, names, visible text) without disturbing its state. Use it when logs say ok but the screen might not, and as the first probe on a live page in a state you can't reproduce — a save would hot-reload and destroy it. (`tb:` messages are answered by the runtime, never your handlers, and imply `--wait`.) Its first line is the page's geometry — viewport, content size, and a fits-or-overflows verdict — so an unwanted scrollbar shows up in the first read.
281
281
  - **Measuring layout** — `typebulb send <file> 'tb:rect button "Pass"'` prints that control's viewport-relative rect as JSON (`{x, y, width, height, viewport}`, integers): how big something ended up, whether two things align, whether one is offscreen — arithmetic on rects, no probe handler. Only what the outline names is measurable; give a structural container a `role` **and** an `aria-label` (`<div role="group" aria-label="board">`) to measure it — a label alone leaves it invisible.
282
- - **Acting on the page** — `typebulb send <file> 'tb:click button "Pass"'` clicks the one control matching that role and name (exact, else a unique case-insensitive substring) and replies with a fresh snapshot; `tb:set combobox "strength" = hard` is the same for form controls (checkboxes and radios take `tb:click`). A disabled, readonly, or covered target is an error naming it — that silence is the bug class these verbs catch. Needs exactly one page open, and the reply is the immediate frame (slow work: follow up with `tb:snapshot`). Only what the outline names is targetable: real `<button>`s and labeled controls, not an `onClick` `<div>`.
282
+ - **Acting on the page** — `typebulb send <file> 'tb:click button "Pass"'` clicks the one control matching that role and name (exact, else a unique case-insensitive substring) and replies with a fresh snapshot; `tb:set combobox "strength" = hard` is the same for form controls (checkboxes and radios take `tb:click`). A disabled, readonly, or covered target is an error naming it — that silence is the bug class these verbs catch. The click is synthetic, so a handler needing user activation (a clipboard write, fullscreen) does nothing and reports nothing. Needs exactly one page open, and the reply is the immediate frame (slow work: follow up with `tb:snapshot`). Only what the outline names is targetable: real `<button>`s and labeled controls, not an `onClick` `<div>`.
283
283
  - **Poking state** — for state beyond what a form control expresses (`tb:set` covers those), author a set-handler up front: a `tb.onMessage` branch that takes a data payload (JSON arrives parsed), applies it to your state — committing the change if your framework needs an explicit step — and returns the new state: `typebulb send <file> '{"set":"speed","value":2}' --wait` prints it. In React, register it in an effect so it closes over the setters (the returned unsubscribe is the cleanup).
284
284
  - **A page must be open** — the CLI runs no browser of its own, so every client-side check waits on a real window (and `--no-open` means there isn't one). `send` says which case it is: nobody has ever connected (share the link), or a page dropped and hasn't returned (it's stale — reload it). Never open a window at the user: the server logs `[page] connected` when a page attaches, so end your turn with the link, arming `typebulb wait <file> --match "[page] connected"` in the background first — the user opening the page is your wake-up.
285
285
  - **Reading a canvas** — `typebulb send <file> tb:png` writes the page's canvas to a PNG (a stable per-bulb path under `~/.typebulb/`, overwritten each read) and prints the path — rendered truth for a bulb whose output is drawn, with no probe handler and nothing disturbed. One canvas needs no name; several take `tb:png "<name>"` — an `aria-label` on the canvas, or `role="img" aria-label="…"` on the container when a chart library owns the canvas. A WebGL/WebGPU canvas without `preserveDrawingBuffer` reads back blank outside its own frame — capture during the draw instead.
@@ -486,7 +486,7 @@ The user can proxy claude with the agent mirror's model switcher, to any model o
486
486
 
487
487
  ## Push & Pull (typebulb.com)
488
488
 
489
- One bulb per command, between typebulb.com and its conventional local file — the path IS the remote identity: `typebulbs/u/ben/birds.bulb.md` ↔ `typebulb.com/u/ben/birds`.
489
+ One bulb per command, between typebulb.com and its conventional local file — the path IS the remote identity: `typebulbs/u/ben/birds.bulb.md` ↔ `typebulb.com/u/ben/birds`. That bare URL opens the bulb in IDE mode; `typebulb.com/u/ben/birds/full` opens it in published mode — the canonical page, and the link to share.
490
490
 
491
491
  - **Pull**: `typebulb pull <bulb-url>` (or an existing local file, to refresh in place) — brings the bulb's `assets/` folder along. Unlisted and public bulbs need no login. A local file or asset with real changes is refused; `--force` overwrites it.
492
492
  - **Push**: `typebulb push <file>` uploads as you — set `TYPEBULB_TOKEN` in `.env` (minted on your typebulb.com settings page). A slug that doesn't exist yet is created, unlisted. If the site copy changed since your last pull/push, the push is refused; `--force` overwrites it. A `**server.ts**` block is stripped from the site copy (CLI-only); your local file is never modified.
package/SKILL.md CHANGED
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: typebulb
3
3
  description: "Author and run Typebulb bulbs — single-file markdown apps (TypeScript/TSX) that run locally via `npx typebulb` (full power: filesystem, database, `server.ts`, `tb.ai`) or render live inline in your coding agent's session through Typebulb's agent mirror (sandboxed, client-only). A bulb can be a visual widget (chart, simulation, diagram, calculator, UI), a full-stack tool with a Node backend, or an AI app that calls models at runtime. Covers the bulb format, the `tb.*` API, trust, and the local run/inline workflow. Use when the user wants a bulb, a quick local tool (visual, backend-backed, or AI-powered), or something visual rendered inline in the conversation."
4
- version: 0.55.3
4
+ version: 0.55.5
5
5
  ---
6
6
 
7
- > Generated from typebulb v0.55.3. `npx typebulb agent` prints the running version alongside the path to its packaged SKILL.md: if that version is newer than this one, replace this file with that one.
7
+ > Generated from typebulb v0.55.5. `npx typebulb agent` prints the running version alongside the path to its packaged SKILL.md: if that version is newer than this one, replace this file with that one.
8
8
 
9
9
  # typebulb
10
10
 
@@ -237,7 +237,7 @@ One exception: if `TYPEBULB_MIRROR=1` is set in your environment, the user is pr
237
237
 
238
238
  - **First, can it even run inline?** A bulb needing `tb.ai`, `tb.infer`, `tb.fs`, or `server.ts` must be **local** — inline bulbs are client-only, so those calls fail there. The choice below is only for client-only bulbs.
239
239
  - **Is anyone watching?** An inline bulb only renders live when the agent mirror is open; with none it shows as raw text. `npx typebulb agent` starts the mirror if needed and prints its link — share it with the user; don't make the user start anything.
240
- - **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **inline**: emit it in a `bulb` block so it renders live in the conversation.
240
+ - **Something to see right now, in the flow of the conversation** — a chart of some numbers, a quick simulation, an illustrative widget. → **inline**: emit it in a `bulb` block, straight into the reply. Don't draft it as a `.bulb.md` and test it first: a broken one reports its own error back to you (below), and the user expects a snappy response with an inline bulb.
241
241
  - **A tool worth keeping** — something to reuse, run on its own, or refine over several turns. → **local**: write a `.bulb.md` file run with `npx typebulb`. An inline block is throwaway and can't be edited in place, so it's the wrong fit for anything iterative.
242
242
 
243
243
  ### Emitting an inline bulb
@@ -287,7 +287,7 @@ That one launch *is* the loop: the server watches the file, so every save recomp
287
287
  - **Slow work settles in the handler** — a handler may be async, and the reply waits for its promise: keep a done-promise, `await` it, and return the finished state, with `--wait=<ms>` sized to the work (instead of polling flags in a sleep loop, or snapshot-polling from outside). The sharp edge: settle the promise on *every* exit of the run — success, failure, supersession, in a `finally` — and start idle with an already-resolved one, or the handler hangs and reads as a broken bulb. One case stays two-step: a `tb:*` gesture that kicks off slow work replies with the immediate frame (runtime-answered), so follow it with this settle probe.
288
288
  - **Rendered truth** — `typebulb send <file> tb:snapshot` prints the page's accessibility outline (roles, names, visible text) without disturbing its state. Use it when logs say ok but the screen might not, and as the first probe on a live page in a state you can't reproduce — a save would hot-reload and destroy it. (`tb:` messages are answered by the runtime, never your handlers, and imply `--wait`.) Its first line is the page's geometry — viewport, content size, and a fits-or-overflows verdict — so an unwanted scrollbar shows up in the first read.
289
289
  - **Measuring layout** — `typebulb send <file> 'tb:rect button "Pass"'` prints that control's viewport-relative rect as JSON (`{x, y, width, height, viewport}`, integers): how big something ended up, whether two things align, whether one is offscreen — arithmetic on rects, no probe handler. Only what the outline names is measurable; give a structural container a `role` **and** an `aria-label` (`<div role="group" aria-label="board">`) to measure it — a label alone leaves it invisible.
290
- - **Acting on the page** — `typebulb send <file> 'tb:click button "Pass"'` clicks the one control matching that role and name (exact, else a unique case-insensitive substring) and replies with a fresh snapshot; `tb:set combobox "strength" = hard` is the same for form controls (checkboxes and radios take `tb:click`). A disabled, readonly, or covered target is an error naming it — that silence is the bug class these verbs catch. Needs exactly one page open, and the reply is the immediate frame (slow work: follow up with `tb:snapshot`). Only what the outline names is targetable: real `<button>`s and labeled controls, not an `onClick` `<div>`.
290
+ - **Acting on the page** — `typebulb send <file> 'tb:click button "Pass"'` clicks the one control matching that role and name (exact, else a unique case-insensitive substring) and replies with a fresh snapshot; `tb:set combobox "strength" = hard` is the same for form controls (checkboxes and radios take `tb:click`). A disabled, readonly, or covered target is an error naming it — that silence is the bug class these verbs catch. The click is synthetic, so a handler needing user activation (a clipboard write, fullscreen) does nothing and reports nothing. Needs exactly one page open, and the reply is the immediate frame (slow work: follow up with `tb:snapshot`). Only what the outline names is targetable: real `<button>`s and labeled controls, not an `onClick` `<div>`.
291
291
  - **Poking state** — for state beyond what a form control expresses (`tb:set` covers those), author a set-handler up front: a `tb.onMessage` branch that takes a data payload (JSON arrives parsed), applies it to your state — committing the change if your framework needs an explicit step — and returns the new state: `typebulb send <file> '{"set":"speed","value":2}' --wait` prints it. In React, register it in an effect so it closes over the setters (the returned unsubscribe is the cleanup).
292
292
  - **A page must be open** — the CLI runs no browser of its own, so every client-side check waits on a real window (and `--no-open` means there isn't one). `send` says which case it is: nobody has ever connected (share the link), or a page dropped and hasn't returned (it's stale — reload it). Never open a window at the user: the server logs `[page] connected` when a page attaches, so end your turn with the link, arming `typebulb wait <file> --match "[page] connected"` in the background first — the user opening the page is your wake-up.
293
293
  - **Reading a canvas** — `typebulb send <file> tb:png` writes the page's canvas to a PNG (a stable per-bulb path under `~/.typebulb/`, overwritten each read) and prints the path — rendered truth for a bulb whose output is drawn, with no probe handler and nothing disturbed. One canvas needs no name; several take `tb:png "<name>"` — an `aria-label` on the canvas, or `role="img" aria-label="…"` on the container when a chart library owns the canvas. A WebGL/WebGPU canvas without `preserveDrawingBuffer` reads back blank outside its own frame — capture during the draw instead.
@@ -494,7 +494,7 @@ The user can proxy claude with the agent mirror's model switcher, to any model o
494
494
 
495
495
  ## Push & Pull (typebulb.com)
496
496
 
497
- One bulb per command, between typebulb.com and its conventional local file — the path IS the remote identity: `typebulbs/u/ben/birds.bulb.md` ↔ `typebulb.com/u/ben/birds`.
497
+ One bulb per command, between typebulb.com and its conventional local file — the path IS the remote identity: `typebulbs/u/ben/birds.bulb.md` ↔ `typebulb.com/u/ben/birds`. That bare URL opens the bulb in IDE mode; `typebulb.com/u/ben/birds/full` opens it in published mode — the canonical page, and the link to share.
498
498
 
499
499
  - **Pull**: `typebulb pull <bulb-url>` (or an existing local file, to refresh in place) — brings the bulb's `assets/` folder along. Unlisted and public bulbs need no login. A local file or asset with real changes is refused; `--force` overwrites it.
500
500
  - **Push**: `typebulb push <file>` uploads as you — set `TYPEBULB_TOKEN` in `.env` (minted on your typebulb.com settings page). A slug that doesn't exist yet is created, unlisted. If the site copy changed since your last pull/push, the push is refused; `--force` overwrites it. A `**server.ts**` block is stripped from the site copy (CLI-only); your local file is never modified.
package/dist/index.js CHANGED
@@ -248,7 +248,7 @@ ${t.comment}`:t.comment}this.doc.range[2]=t.offset;break}default:this.errors.pus
248
248
  `),c=i.filter(u=>u.type==="tool_use").map(u=>({id:u.id??"",name:u.name??"",input:u.input??{}}));if(o||a||c.length){let u=Date.parse(e.timestamp??""),d=!isNaN(u)&&u>=t;r.push({type:"assistant",text:o,thinking:a,tools:c,live:d})}let l=e.message?.usage??e.usage,f=l&&{in:l.input_tokens??0,out:l.output_tokens??0,cached:l.cache_read_input_tokens??0,cacheCreate:l.cache_creation_input_tokens??0};return{events:r,usage:f,model:e.message?.model}}return{events:r}}chainWorking(e){let t;for(let o of e)(o.type==="user"||o.type==="assistant")&&(t=o);if(!t)return!1;if(t.type==="user"){try{let o=t.message?.content,a=typeof o=="string"?o:Array.isArray(o)?o.filter(l=>l&&l.type==="text").map(l=>l.text??"").join(""):"";if(!(Array.isArray(o)&&o.some(l=>l&&l.type==="tool_result"))&&a.trim()&&xt(a)==="")return!1}catch{}return!0}let s=(Array.isArray(t.message?.content)?t.message.content:[]).filter(o=>o.type==="tool_use").map(o=>o.id);if(s.length===0)return!1;let i=new Set;for(let o of e){let a=o.message?.content;if(Array.isArray(a))for(let c of a)c.type==="tool_result"&&c.tool_use_id&&i.add(c.tool_use_id)}return s.some(o=>o&&!i.has(o))}sessionAlive(e){return zE(e)}readPreview(e){return VE(e)}searchText(e){if(!e||Hr(e)||e.type!=="user"&&e.type!=="assistant")return"";let t=e.message?.content,r="";if(typeof t=="string")r=xt(t);else if(Array.isArray(t)){let s=t;r=e.type==="user"?s.map(Ll).filter(Boolean).join(" "):s.filter(i=>i.type==="text"&&typeof i.text=="string").map(i=>i.text).join(" ")}return r.replace(/\s+/g," ").trim()}}});import{statSync as GE,readdirSync as XE,openSync as QE,readSync as ZE,closeSync as eA,existsSync as tA}from"fs";import{basename as nA,join as Dl,resolve as rA}from"path";import{homedir as qm}from"os";function iA(n){let e=n.trimStart();return sA.some(t=>e.startsWith(t))}function Vr(n,e){return Array.isArray(n)?n.map(t=>typeof t?.text=="string"?e&&iA(t.text)?"":be(t.text):t?.type==="input_image"&&typeof t.image_url=="string"&&t.image_url.startsWith("data:")?`![image](${t.image_url})`:"").filter(Boolean).join(`
249
249
  `):""}function oA(n){return typeof n=="string"?be(n):Vr(n,!1)}function aA(n){let e=n??"";for(let t of[/tools\.shell_command\((\{[\s\S]*?\})\)/,/tools\.shell_command\((\{[\s\S]*\})\)/]){let r=t.exec(e);if(r)try{return JSON.parse(r[1])}catch{}}return{script:e}}function cA(n){if(typeof n=="string"&&n)try{let e=JSON.parse(n);if(e&&typeof e=="object"&&!Array.isArray(e))return e}catch{}return{arguments:n??""}}function Km(n,e){let t;try{t=QE(n,"r")}catch{return}try{let r=Buffer.alloc(e),s=ZE(t,r,0,e,0);return{text:r.subarray(0,s).toString("utf8"),bytes:s}}finally{eA(t)}}function lA(n){let t=Km(n,65536);if(t===void 0)return;let r=t.text.indexOf(`
250
250
  `);if(r<0)return t.bytes>=65536?"":void 0;try{let s=JSON.parse(t.text.slice(0,r));return s?.type==="session_meta"&&typeof s.payload?.cwd=="string"?s.payload.cwd:""}catch{return""}}var sA,Jm,_n,jl=v(()=>{"use strict";Wr();Wi();sA=["<permissions instructions>","<apps_instructions>","<plugins_instructions>","<skills_instructions>","<recommended_plugins>","<environment_context>","<user_instructions>"];Jm=n=>{let e=rA(n);return process.platform==="win32"?e.toLowerCase():e},_n=class extends kt{constructor(t=Dl(qm(),".codex","sessions")){super();this.root=t}displayName="Codex Mirror";#e=0;#s;#t=new Map;detectsSelf(){return!!process.env.CODEX_THREAD_ID}detectsInstalled(){return tA(Dl(qm(),".codex"))}sessionsDir(t){return this.root}listSessionFiles(t){let r=Jm(t),s=[];for(let i of this.#r()){let o;try{let c=GE(i);if(!c.isFile())continue;o=c.mtimeMs}catch{continue}let a=this.#t.get(i);if(a===void 0){if(a=lA(i),a===void 0)continue;this.#t.set(i,a)}Jm(a)===r&&s.push({sessionId:nA(i,".jsonl"),file:i,mtime:o})}return s}#r(){let t=[],r=s=>{try{return XE(s).map(i=>Dl(s,i))}catch{return[]}};for(let s of r(this.root))for(let i of r(s))for(let o of r(i))for(let a of r(o))a.endsWith(".jsonl")&&t.push(a);return t}parseEntry(t){let r;try{r=JSON.parse(t)}catch{return null}return!r||typeof r.type!="string"?null:r}idOf(t){return t.ord===void 0&&(t.ord=String(this.#e++),t.parent=this.#s,this.#s=t.ord),t.ord}parentOf(t){return t.parent}timestampOf(t){return t.timestamp}isSidechain(t){return!1}isLeafType(t){return!0}isRecoveryNoise(t){return!1}apply(t,r){let s=[],i=t.payload;if(!i)return{events:s};let o=()=>{let a=Date.parse(t.timestamp??"");return!isNaN(a)&&a>=r};if(t.type==="response_item"){if(i.type==="message"){if(i.role==="user"){let a=Vr(i.content,!0).trim();a&&s.push({type:"user",text:a})}else if(i.role==="assistant"){let a=Vr(i.content,!1);a&&s.push({type:"assistant",text:a,thinking:"",tools:[],live:o()})}return{events:s}}if(i.type==="reasoning"){let a=Vr(i.summary,!1);return a&&s.push({type:"assistant",text:"",thinking:a,tools:[],live:o()}),{events:s}}if(i.type==="custom_tool_call"||i.type==="function_call"){let a=i.type==="custom_tool_call"?aA(i.input):cA(i.arguments);return s.push({type:"assistant",text:"",thinking:"",tools:[{id:i.call_id??"",name:i.name??"",input:a}],live:o()}),{events:s}}if(i.type==="custom_tool_call_output"||i.type==="function_call_output"){let a=oA(i.output);return s.push({type:"tool_result",id:i.call_id??"",content:a,isError:!1,digest:Le(a)}),{events:s}}return{events:s}}if(t.type==="event_msg"){if(i.type==="token_count"){let a=i.info?.last_token_usage;if(!a)return{events:s};let c={in:Math.max(0,(a.input_tokens??0)-(a.cached_input_tokens??0)),out:a.output_tokens??0,cached:a.cached_input_tokens??0,cacheCreate:a.cache_write_input_tokens??0};return{events:s,usage:c}}return{events:s}}return t.type==="turn_context"?{events:s,model:i.model}:{events:s}}chainWorking(t){let r=!1;for(let s of t){if(s.type!=="event_msg")continue;let i=s.payload?.type;i==="task_started"?r=!0:(i==="task_complete"||i==="turn_aborted")&&(r=!1)}return r}sessionAlive(){}readPreview(t){for(let r of(Km(t,256*1024)?.text??"").split(`
251
- `))if(r.includes('"user_message"'))try{let s=JSON.parse(r);if(s?.type==="event_msg"&&s.payload?.type==="user_message"&&typeof s.payload.message=="string"){let i=s.payload.message.replace(/\s+/g," ").trim();if(i)return i.slice(0,200)}}catch{}return""}searchText(t){if(t?.type!=="response_item"||t.payload?.type!=="message")return"";let r=t.payload.role;return r!=="user"&&r!=="assistant"?"":Vr(t.payload.content,r==="user").replace(/\s+/g," ").trim()}}});import{realpathSync as uA}from"fs";import{createHash as dA}from"crypto";import{join as Vi,resolve as fA}from"path";import{homedir as pA}from"os";function Et(){let n=process.env.TYPEBULB_SERVERS_DIR;return n?Vi(n,".."):Vi(pA(),".typebulb")}function et(){Wm||(Wm=!0,console.error(`${Et()} not writable \u2014 continuing stateless: ports won't stick, caches stay cold, and typebulb logs/wait/send/stop may not see this run`))}function tt(){return process.env.TYPEBULB_SERVERS_DIR||Vi(Et(),"servers")}function Hm(n){let e=X(n),t=dA("sha1").update(e).digest("hex").slice(0,8),r=e.slice(e.lastIndexOf("/")+1).replace(/\.bulb\.md$/,"");return Vi(Et(),"canvas",`${r}-${t}.png`)}function X(n){let e=fA(n),t=e;try{t=uA.native(e)}catch{}return(process.platform==="win32"?t.toLowerCase():t).replace(/\\/g,"/")}function Ym(n,e){let t=X(n),r=X(e);return t.startsWith(r.endsWith("/")?r:r+"/")?!t.includes("/node_modules/"):!1}var Wm,At=v(()=>{"use strict";Wm=!1});var Be,zi=v(()=>{"use strict";Be="0.55.3"});import{spawn as Vm}from"child_process";import{readdir as hA,readFile as Gm,writeFile as Xm,unlink as Fl,mkdir as mA}from"fs/promises";import{mkdirSync as Qm,writeFileSync as Gi,appendFileSync as gA,readFileSync as Ul}from"fs";import*as xe from"path";import{fileURLToPath as yA}from"url";function ql(n){return xe.join(tt(),`${n}.json`)}function Gr(n){return xe.join(tt(),`${n}.log`)}function Jl(n){return xe.join(tt(),`${n}.wait.json`)}function Zm(n){try{let e=JSON.parse(Ul(Jl(n),"utf8"));return e.cursors&&typeof e.cursors=="object"?e.cursors:{}}catch{return{}}}function Kl(n,e=""){let t=Zm(n)[e];return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:void 0}function Xi(n,e,t=""){try{Qm(tt(),{recursive:!0});let r=Zm(n);r[t]=e,Gi(Jl(n),JSON.stringify({cursors:r}))}catch{}}function Qi(n){let e=Gr(n);try{Qm(tt(),{recursive:!0}),Gi(e,"")}catch{return()=>{}}let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr),s=0,i=!1,o=a=>{if(!i)try{let c=typeof a=="string"?Buffer.from(a,"utf8"):Buffer.from(a);if(gA(e,c),s+=c.length,s>2*zm){let l=Ul(e),f=l.subarray(Math.max(0,l.length-zm));Gi(e,f),s=f.length}}catch{i=!0}};return process.stdout.write=((a,...c)=>(o(a),t(a,...c))),process.stderr.write=((a,...c)=>(o(a),r(a,...c))),()=>{process.stdout.write=t,process.stderr.write=r}}function eg(n){try{Gi(Gr(n),"")}catch{}}function He(n,e=0){try{let t=Ul(Gr(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 Wl(n){return`\u2500\u2500 run ${n} \u2500\u2500 ${new Date().toTimeString().slice(0,8)}`}function wA(n){let e=bA.exec(n);return e?Number(e[1]):void 0}function tg(n,e){let t=n.split(`
251
+ `))if(r.includes('"user_message"'))try{let s=JSON.parse(r);if(s?.type==="event_msg"&&s.payload?.type==="user_message"&&typeof s.payload.message=="string"){let i=s.payload.message.replace(/\s+/g," ").trim();if(i)return i.slice(0,200)}}catch{}return""}searchText(t){if(t?.type!=="response_item"||t.payload?.type!=="message")return"";let r=t.payload.role;return r!=="user"&&r!=="assistant"?"":Vr(t.payload.content,r==="user").replace(/\s+/g," ").trim()}}});import{realpathSync as uA}from"fs";import{createHash as dA}from"crypto";import{join as Vi,resolve as fA}from"path";import{homedir as pA}from"os";function Et(){let n=process.env.TYPEBULB_SERVERS_DIR;return n?Vi(n,".."):Vi(pA(),".typebulb")}function et(){Wm||(Wm=!0,console.error(`${Et()} not writable \u2014 continuing stateless: ports won't stick, caches stay cold, and typebulb logs/wait/send/stop may not see this run`))}function tt(){return process.env.TYPEBULB_SERVERS_DIR||Vi(Et(),"servers")}function Hm(n){let e=X(n),t=dA("sha1").update(e).digest("hex").slice(0,8),r=e.slice(e.lastIndexOf("/")+1).replace(/\.bulb\.md$/,"");return Vi(Et(),"canvas",`${r}-${t}.png`)}function X(n){let e=fA(n),t=e;try{t=uA.native(e)}catch{}return(process.platform==="win32"?t.toLowerCase():t).replace(/\\/g,"/")}function Ym(n,e){let t=X(n),r=X(e);return t.startsWith(r.endsWith("/")?r:r+"/")?!t.includes("/node_modules/"):!1}var Wm,At=v(()=>{"use strict";Wm=!1});var Be,zi=v(()=>{"use strict";Be="0.55.5"});import{spawn as Vm}from"child_process";import{readdir as hA,readFile as Gm,writeFile as Xm,unlink as Fl,mkdir as mA}from"fs/promises";import{mkdirSync as Qm,writeFileSync as Gi,appendFileSync as gA,readFileSync as Ul}from"fs";import*as xe from"path";import{fileURLToPath as yA}from"url";function ql(n){return xe.join(tt(),`${n}.json`)}function Gr(n){return xe.join(tt(),`${n}.log`)}function Jl(n){return xe.join(tt(),`${n}.wait.json`)}function Zm(n){try{let e=JSON.parse(Ul(Jl(n),"utf8"));return e.cursors&&typeof e.cursors=="object"?e.cursors:{}}catch{return{}}}function Kl(n,e=""){let t=Zm(n)[e];return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:void 0}function Xi(n,e,t=""){try{Qm(tt(),{recursive:!0});let r=Zm(n);r[t]=e,Gi(Jl(n),JSON.stringify({cursors:r}))}catch{}}function Qi(n){let e=Gr(n);try{Qm(tt(),{recursive:!0}),Gi(e,"")}catch{return()=>{}}let t=process.stdout.write.bind(process.stdout),r=process.stderr.write.bind(process.stderr),s=0,i=!1,o=a=>{if(!i)try{let c=typeof a=="string"?Buffer.from(a,"utf8"):Buffer.from(a);if(gA(e,c),s+=c.length,s>2*zm){let l=Ul(e),f=l.subarray(Math.max(0,l.length-zm));Gi(e,f),s=f.length}}catch{i=!0}};return process.stdout.write=((a,...c)=>(o(a),t(a,...c))),process.stderr.write=((a,...c)=>(o(a),r(a,...c))),()=>{process.stdout.write=t,process.stderr.write=r}}function eg(n){try{Gi(Gr(n),"")}catch{}}function He(n,e=0){try{let t=Ul(Gr(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 Wl(n){return`\u2500\u2500 run ${n} \u2500\u2500 ${new Date().toTimeString().slice(0,8)}`}function wA(n){let e=bA.exec(n);return e?Number(e[1]):void 0}function tg(n,e){let t=n.split(`
252
252
  `),r=[];if(t.forEach((o,a)=>{let c=wA(o);c!==void 0&&r.push({id:c,idx:a})}),!r.length)return e==="latest"?n:"";let s=e==="latest"?r[r.length-1]:r.find(o=>o.id===e);if(!s)return"";let i=r.find(o=>o.idx>s.idx);return t.slice(s.idx,i?i.idx:t.length).join(`
253
253
  `)}function Hl(n){try{return process.kill(n,0),!0}catch(e){return e.code==="EPERM"}}async function ng(n){try{await mA(tt(),{recursive:!0}),await Xm(ql(n.pid),JSON.stringify({version:Be,...n}))}catch{et()}}async function rg(n,e){let t=ql(n);try{let r=JSON.parse(await Gm(t,"utf8"));if(r.denied===e)return;r.denied=e,await Xm(t,JSON.stringify(r))}catch{}}async function zr(n){await Fl(ql(n)).catch(()=>{}),await Fl(Gr(n)).catch(()=>{}),await Fl(Jl(n)).catch(()=>{})}async function Q(n){let e;try{e=await hA(tt())}catch{return[]}let t=[];return await Promise.all(e.map(async s=>{if(!/^\d+\.json$/.test(s))return;let i=parseInt(s,10),o;try{o=JSON.parse(await Gm(xe.join(tt(),s),"utf8"))}catch{await zr(i);return}o&&typeof o.pid=="number"&&Hl(o.pid)?t.push(o):await zr(i)})),(n?t.filter(s=>s.agent==null&&Ym(s.file,n)):t).sort((s,i)=>s.startedAt-i.startedAt)}async function Yl(n,e){let t=X(n);return(await Q()).find(r=>r.cwd!=null&&X(r.cwd)===t&&(e?r.agent===e:r.agent!=null))}async function Yt(n){try{process.kill(n,"SIGTERM")}catch{}await zr(n)}function Rn(n,e){let t=X(e);return n.filter(r=>r.agent==null&&r.pid!==process.pid&&X(r.file)===t)}async function Vl(n){let e=Rn(await Q(),n);for(let t of e)await Yt(t.pid);return e}function SA(n,e,t){(process.platform==="win32"?Vm("cmd",["/c","start","","/b",n,...e],{cwd:t,stdio:"ignore",windowsHide:!0}):Vm(n,e,{cwd:t,detached:!0,stdio:"ignore"})).unref()}function Xr(){return xe.join(xe.dirname(yA(import.meta.url)),"index.js")}function kA(n,e={}){return{command:process.execPath,args:[Xr(),...e.trust?["--trust"]:[],...e.batch?["--batch",e.batch]:[],...e.mode?["--mode",e.mode]:[],n,...e.open===!1?["--no-open"]:[]]}}function xA(n){return{command:process.execPath,args:[Xr(),`agent:${n}`,"--no-open"]}}async function sg(n,e,t,r){let s=await n();if(s)return s;SA(e.command,e.args,t);let i=Date.now()+2e4;for(;Date.now()<i;){await vA(150);let o=await n();if(o)return o}throw new Error(`Launched ${r} but it did not register within 20s.`)}async function Zi(n,e={}){let t=e.cwd??process.cwd(),r=xe.resolve(t,n),[s]=await Vl(r),i={...e,batch:e.batch??s?.batch,mode:e.mode??s?.mode};return sg(async()=>Rn(await Q(),r)[0],kA(n,i),t,xe.basename(n))}async function ig(n,e=process.cwd()){return sg(()=>Yl(e,n),xA(n),e,`the ${n} mirror`)}var zm,bA,vA,Ee=v(()=>{"use strict";At();zi();zm=1e6;bA=/^── run (\d+) ── /;vA=n=>new Promise(e=>setTimeout(e,n))});function In(n){return{...pf(n),server:n.files.get("server.ts")??""}}function eo(n){return!!n.server&&!n.code}var Qr=v(()=>{"use strict";Z();Z()});function to(n){let e=/^---[^\n]*\n([\s\S]*?)\n---/.exec(n),t=e?/^\s*name:\s*(.+?)\s*$/m.exec(e[1]):null;return t?t[1].replace(/^["']|["']$/g,""):void 0}function zl(n){return On(to(n)??"bulb")||"bulb"}var Gl=v(()=>{"use strict";Z()});import{transform as EA}from"sucrase";function Xl(n,e={}){let t=e.serverOnly?["typescript"]:["typescript","jsx"];try{let{code:r}=EA(n,{transforms:t,jsxRuntime:"automatic",jsxImportSource:e.jsxImportSource||"react",production:!0});return{code:r}}catch(r){return{code:"",error:String(r)}}}var og=v(()=>{});function Ql(n){let e=n.split(""),t=(i,o)=>{for(let a=i;a<o&&a<e.length;a++)e[a]!==`
254
254
  `&&(e[a]=" ")},r=0,s="";for(;r<n.length;){let i=n[r],o=n[r+1];if(i==="/"&&o==="/"){let a=r;for(;a<n.length&&n[a]!==`
@@ -1534,7 +1534,7 @@ Re-run with --force to overwrite the local file.`),process.exitCode=1;return;cas
1534
1534
  `+s.paths.map(o=>` assets/${o}`).join(`
1535
1535
  `)+`
1536
1536
  Re-run with --force to overwrite them.`),process.exitCode=1;return;case"http-error":s.status===404?console.error(`Bulb not found: ${r}`):s.status===401||s.status===403?console.error(`This bulb is private (${s.status}) \u2014 pulling it needs a TYPEBULB_TOKEN for its owner.`):console.error(`Pull failed: ${t.origin} responded ${s.status}`),process.exitCode=1;return;case"not-markdown":console.error(`${r}.md did not return bulb markdown (got ${s.contentType??"no content-type"}) \u2014 is ${t.origin} a typebulb host?`),process.exitCode=1}}function Sy(n){if(!(!n||!n.downloaded&&!n.errors.length)){console.log(`assets: ${n.downloaded} downloaded${n.unchanged?`, ${n.unchanged} unchanged`:""}`);for(let e of n.errors)console.error(` asset failed \u2014 ${e} (a re-pull retries just the missing ones)`);n.errors.length&&(process.exitCode=1)}}var aO,Uo,Uu,qo,ws,Ju,Wo=v(()=>{"use strict";it();Z();ze();aO="https://typebulb.com",Uo=(n,e)=>Oe.join("typebulbs","u",n,`${e}.bulb.md`),Uu=n=>`${n.origin}/u/${encodeURIComponent(n.userSlug)}/${encodeURIComponent(n.slug)}.md`,qo=n=>n.split("/").map(encodeURIComponent).join("/"),ws=n=>`${n.origin}/u/${encodeURIComponent(n.userSlug)}/${encodeURIComponent(n.slug)}/assets`;Ju=n=>oO("md5").update(n).digest("hex")});import*as Ge from"fs/promises";import*as vs from"path";async function xy(n,e=""){let t=await Ge.readdir(n,{withFileTypes:!0}).catch(()=>[]),r=[];for(let s of t)s.isDirectory()?r.push(...await xy(vs.join(n,s.name),`${e}${s.name}/`)):s.isFile()&&r.push(e+s.name);return r}async function dO(n,e){let t=e.timeoutMs??3e4,r=ws(n),s={Authorization:`Bearer ${e.token}`},i=$t(n.dest);if(!await Ge.stat(i).then(m=>m.isDirectory()).catch(()=>!1))return{kind:"skipped"};let o=await xy(i),a=await Ku(n,{token:e.token,timeoutMs:t});if("error"in a)return{kind:"sync-error",message:a.error};let c=a.entries;if(!o.length&&!c.length)return{kind:"skipped"};let l=new Map(c.map(m=>[m.path,m.md5])),f=new Set(o),u=c.map(m=>m.path).filter(m=>!f.has(m)),d=0,p=0;try{await qu(o,4,async m=>{let h=await Ge.readFile(vs.join(i,...m.split("/")));if(l.get(m)===Ju(h)){p++;return}let y=await fetch(`${r}/${qo(m)}`,{method:"PUT",body:new Uint8Array(h),headers:s,signal:AbortSignal.timeout(t)});if(!y.ok)throw new Error(`upload of '${m}' refused (${y.status}): ${Xn(await y.text())}`);d++})}catch(m){return{kind:"sync-error",message:m instanceof Error?m.message:String(m)}}return{kind:"synced",uploaded:d,unchanged:p,toDelete:u,base:qs(n.userSlug,n.slug)}}async function fO(n,e,t){let r=t.timeoutMs??3e4,s=ws(n),i=[];for(let o of e)try{let a=await fetch(`${s}/${qo(o)}`,{method:"DELETE",headers:{Authorization:`Bearer ${t.token}`},signal:AbortSignal.timeout(r)});if(!a.ok)return{deleted:i,error:`delete of '${o}' refused (${a.status}): ${Xn(await a.text())}`};i.push(o)}catch(a){return{deleted:i,error:a instanceof Error?a.message:String(a)}}return{deleted:i}}async function Ho(n,e){let t=await Ge.readFile(n.dest,"utf-8"),{mtime:r}=await Ge.stat(n.dest),s=await dO(n,{token:e.token,timeoutMs:e.timeoutMs});if(s.kind==="sync-error")return{kind:"asset-error",message:s.message};let i=s.kind==="synced"?{uploaded:s.uploaded,unchanged:s.unchanged,deleted:[],base:s.base}:void 0,o={Authorization:`Bearer ${e.token}`,"Content-Type":"text/markdown; charset=utf-8"};e.force||(o["If-Unmodified-Since"]=r.toUTCString());let a=await fetch(Uu(n),{method:"PUT",body:t,headers:o,signal:e.timeoutMs?AbortSignal.timeout(e.timeoutMs):void 0}),c=await a.text();if(a.status===409)return{kind:"conflict",message:Xn(c),assets:i};if(!a.ok)return{kind:"http-error",status:a.status,message:Xn(c),assets:i};let l=JSON.parse(c);if(await Ge.utimes(n.dest,new Date,new Date(l.updatedAt)),i&&s.kind==="synced"&&s.toDelete.length){let f=await fO(n,s.toDelete,{token:e.token,timeoutMs:e.timeoutMs});i.deleted=f.deleted,f.error&&(i.pruneError=f.error)}return{kind:"pushed",created:l.created,serverStripped:l.serverStripped,updatedAt:l.updatedAt,assets:i}}async function Ey(n,e){n||(console.error("Usage: typebulb push <typebulbs/u/<user>/<slug>.bulb.md>"),process.exit(1)),/^https?:\/\//i.test(n)&&(console.error("push takes a local .bulb.md file, not a URL (the path is its remote identity)"),process.exit(1));let t=Wu(n,e.mode),r=process.env.TYPEBULB_TOKEN;r||(console.error("push needs TYPEBULB_TOKEN in your .env \u2014 create one on your typebulb.com settings page."),process.exit(1));let s=`${t.origin}/u/${t.userSlug}/${t.slug}`,i=vs.relative(process.cwd(),t.dest)||t.dest,o;try{o=await Ho(t,{token:r,force:e.force})}catch(a){let c=a instanceof Error?a.message:String(a);console.error(a?.code==="ENOENT"?`File not found: ${i}`:`Could not push to ${t.origin}: ${c}`),process.exitCode=1;return}switch(o.kind!=="asset-error"&&o.assets&&console.log(`assets: ${o.assets.uploaded} uploaded, ${o.assets.unchanged} unchanged \u2192 ${o.assets.base}`),o.kind){case"asset-error":console.error(`assets sync failed: ${o.message}
1537
- push refused: the bulb text was not pushed.`),process.exitCode=1;return;case"pushed":{console.log(`pushed ${i} \u2192 ${s}`),o.created&&(console.log(" created a new bulb, unlisted \u2014 nothing existed at this URL before"),console.log(" if you renamed this file, its previous bulb is still live at the old URL")),o.serverStripped&&console.log("note: the server.ts block was stripped on the server copy (CLI-only); your local file is untouched.");for(let a of o.assets?.deleted??[])console.log(` deleted ${a} (no longer in assets/)`);o.assets?.pruneError&&console.log(`note: asset cleanup incomplete \u2014 ${o.assets.pruneError}; the next push will retry.`);return}case"conflict":console.error(`${o.message}
1537
+ push refused: the bulb text was not pushed.`),process.exitCode=1;return;case"pushed":{console.log(`pushed ${i} \u2192 ${s}/full`),o.created&&(console.log(" created a new bulb, unlisted \u2014 nothing existed at this URL before"),console.log(" if you renamed this file, its previous bulb is still live at the old URL")),o.serverStripped&&console.log("note: the server.ts block was stripped on the server copy (CLI-only); your local file is untouched.");for(let a of o.assets?.deleted??[])console.log(` deleted ${a} (no longer in assets/)`);o.assets?.pruneError&&console.log(`note: asset cleanup incomplete \u2014 ${o.assets.pruneError}; the next push will retry.`);return}case"conflict":console.error(`${o.message}
1538
1538
  pull to see the remote: typebulb pull ${i}
1539
1539
  or overwrite it: typebulb push ${i} --force`),process.exitCode=1;return;case"http-error":o.status===401?console.error("The server rejected TYPEBULB_TOKEN (401) \u2014 it may be revoked; mint a new one on the settings page."):console.error(`Push failed: ${t.origin} responded ${o.status}${o.message?` \u2014 ${o.message}`:""}`),process.exitCode=1}}var Hu=v(()=>{"use strict";Z();Wo();ze()});var Qn=v(()=>{"use strict";Ee();cy();Yn();yy();Gl();by();vy();ys();rn();rn();_o();Fu();Ee();Wo();Hu();it()});import{existsSync as pO,mkdirSync as hO,readFileSync as mO,rmSync as gO,writeFileSync as yO}from"fs";import{homedir as bO}from"os";import*as Zn from"path";function kO(){return SO.replace('"__TB_SKILL_PATH__"',JSON.stringify(bs())).replace('"__TB_BIN_PATH__"',JSON.stringify(Xr()))}function Ay(){try{if(!pO(Yu()))return}catch{return}try{let n=wO(),e=kO(),t;try{t=mO(n,"utf8")}catch{}t!==e&&(hO(Zn.dirname(n),{recursive:!0}),yO(n,e))}catch{}for(let n of vO())try{gO(n,{force:!0})}catch{}}var Yu,wO,vO,SO,Ty=v(()=>{"use strict";Qn();Yu=()=>Zn.join(bO(),".pi","agent"),wO=()=>Zn.join(Yu(),"extensions","typebulb.ts"),vO=()=>["typebulb-wait.ts","matchu-patchu.ts"].map(n=>Zn.join(Yu(),"extensions",n)),SO=String.raw`// Generated by typebulb — do not edit; overwritten on each run.
1540
1540
  import { spawn } from "node:child_process";
@@ -1624,6 +1624,7 @@ var TB_MIRROR_BLOCK = [
1624
1624
  " • no need to end your reply with a mirror link",
1625
1625
  " Reusable app/tool → write a .bulb.md",
1626
1626
  " Show something inline → emit an inline bulb",
1627
+ " emit it with no .bulb.md draft first",
1627
1628
  " Read the authoring skill before writing a bulb:",
1628
1629
  " • " + TB_SKILL_PATH,
1629
1630
  ].join("\n");
@@ -1862,7 +1863,7 @@ data: ${JSON.stringify(a)}
1862
1863
  `)?`
1863
1864
  `:"";yb(r,i+`OPENROUTER_API_KEY=${e}
1864
1865
  `)}}catch(i){return{ok:!1,error:Y(i)}}return process.env.OPENROUTER_API_KEY=e,wb(t,[".env"],"# secrets"),{ok:!0}}function nC(){if(!(!rr&&!Xe)){try{xb(z)}catch{}YP()}}function rC(n,e){return Ab.test(e)?"blocked by your OpenRouter data policy":n===401||n===403||/unauthor|invalid api key|no auth|forbidden/i.test(e)?"auth rejected \u2014 check your OpenRouter key":n===404||/not a valid model|no such model|unknown model|model not found/i.test(e)?"model not found on this route":n===429||/rate limit/i.test(e)?"rate limited":n===402||/insufficient|credit|quota|balance/i.test(e)?"out of credits / quota":e.slice(0,160)}function sC(n){if(Ab.test(n))return"This model's only provider(s) require prompt logging/training, which your OpenRouter account disallows by default. Allow it (or that provider) at openrouter.ai/settings/privacy, then probe again."}function iC(n,e,t){if(!n)return{works:null,read:0,note:t?`couldn't re-test on ${t} \u2014 caching unconfirmed`:"caching unconfirmed"};let r=Ed(e?.cache_read_input_tokens)||Ed(e?.prompt_tokens_details?.cached_tokens),s=e?.cache_read_input_tokens!==void 0||e?.cache_creation_input_tokens!==void 0||e?.prompt_tokens_details!==void 0;return r>0?{works:!0,read:r,note:`${r} tokens read from cache on the 2nd call`}:s?{works:!1,read:r,note:"no cache reads after a warm call \u2014 every turn re-bills the full context"}:{works:null,read:r,note:"route doesn't report cache usage \u2014 caching almost certainly not honored"}}async function oC({model:n}){let e=process.env.OPENROUTER_API_KEY;if(!e)return{ok:!1,error:"OPENROUTER_API_KEY not set \u2014 add a key first"};if(!n)return{ok:!1,error:"no model given"};if(Od(n))return{ok:!1,error:"Anthropic model \u2014 not offered or probed via OpenRouter"};let t=Date.now(),r=Array(350).fill("Caching probe filler sentence; its only purpose is to exceed the prompt-cache minimum token threshold.").join(" "),s={"content-type":"application/json",authorization:`Bearer ${e}`,"anthropic-version":"2023-06-01"},i={model:n,max_tokens:64,system:[{type:"text",text:r,cache_control:{type:"ephemeral"}}],messages:[{role:"user",content:"Reply with exactly: ok"}]},o=async a=>{let c=new AbortController,l=setTimeout(()=>c.abort(),2e4);try{let f=JSON.stringify(a?{...i,provider:vb(a)}:i),u=await fetch(Td,{method:"POST",signal:c.signal,headers:s,body:f}),d=await u.json().catch(()=>({}));return{r:u,j:d}}finally{clearTimeout(l)}};try{let{r:a,j:c}=await o();if(!a.ok){let A=c?.error?.message||c?.message||JSON.stringify(c).slice(0,300);return{ok:!0,callable:!1,status:a.status,ms:Date.now()-t,error:rC(a.status,A),restriction:sC(A)}}let l=typeof c?.provider=="string"?c.provider:void 0,f=c?.content?.find?.(A=>A.type==="text")?.text??c?.content?.[0]?.text??"ok",u=Ed(c?.usage?.cache_creation_input_tokens),{r:d,j:p}=await o(l),{works:m,read:h,note:y}=iC(d.ok,p?.usage,l);return m===!0&&l&&(Pd[n]=l,Xe===n&&(fn=l)),{ok:!0,callable:!0,status:a.status,ms:Date.now()-t,provider:l,sample:String(f).trim().slice(0,60),cache:{works:m,created:u,read:h,note:y}}}catch(a){let c=Y(a);return{ok:!0,callable:!1,ms:Date.now()-t,error:/abort/i.test(c)?"timed out (20s)":c}}}var LP,Td,MP,BP,bb,DP,xd,ua,da,aa,Od,rr,dn,Xe,fn,Es,As,Ts,Pd,Ed,vb,Ab,Tb=v(()=>{"use strict";Qn();Lt();LP="https://openrouter.ai/api",Td=`${LP}/v1/messages`,MP="typebulb-proxy-managed",BP="The typebulb model override was reverted to Anthropic, but this Claude Code session still points at the now-idle proxy. Reload the window (VS Code/Cursor: \u201CDeveloper: Reload Window\u201D) or relaunch `claude` in a terminal to return to your Anthropic subscription.",bb=["ANTHROPIC_BASE_URL","ANTHROPIC_AUTH_TOKEN"],DP=5e3,xd=["low","medium","high"],ua=n=>la(n,".claude","settings.local.json"),da=n=>la(n,".claude",".cc-switcher.json"),aa=n=>`http://127.0.0.1:${n}`;Od=n=>/^anthropic\//i.test(n)||/claude/i.test(n),rr=null,dn=null,Xe=null,fn=null,Es=null,As="unknown",Ts=1,Pd={},Ed=n=>typeof n=="number"?n:0,vb=n=>({order:[n],allow_fallbacks:!1});Ab=/data policy|no endpoints|no allowed providers|privacy|requires.*(training|logging|data)/i;(async function(){try{let e=Bt(da(z)),t=e?.active?.model;if(!t)return;let s=(Bt(ua(z))?.env||{}).ANTHROPIC_BASE_URL||"";if(!/127\.0\.0\.1|localhost/.test(s))return;let i=await Eb(t,e.active.provider??Pd[t]??null);console.log(`[switcher] re-adopted override after restart: ${t} via ${aa(i)}`)}catch(e){console.error("[switcher] boot reconcile failed",Y(e))}})()});var Pb={};Na(Pb,{attach:()=>hC,blockToMarkdown:()=>Hi,breakout:()=>cd,capText:()=>be,cleanUserText:()=>xt,clearSwitchModel:()=>eC,composerPasteRead:()=>mC,displayName:()=>aC,downloadSample:()=>bd,firstLineDigest:()=>Le,git:()=>Je,gitChangedFiles:()=>Qu,gitDiff:()=>Zu,info:()=>cC,isHiddenTurn:()=>Hr,launchBulb:()=>pd,listBreakouts:()=>ld,listBulbFiles:()=>dd,listMyBulbs:()=>vd,listSamples:()=>yd,listSessions:()=>dC,listSwitchModels:()=>GP,logInlineStatus:()=>uC,openFile:()=>ad,poll:()=>lC,predictTrustOf:()=>hd,probeModel:()=>oC,pullRemoteBulb:()=>Sd,pushLocalBulb:()=>kd,readBulbLog:()=>gd,repoRoot:()=>cn,saveOpenRouterKey:()=>tC,searchBulbs:()=>fd,searchSessions:()=>fC,sessionPeek:()=>pC,setBulbTrust:()=>md,setReasoning:()=>ZP,setSwitchModel:()=>QP,shutdownSwitcher:()=>nC,stopBreakout:()=>ud,summarizeTurn:()=>gC,switchState:()=>XP,toolResultDigest:()=>Bl});var Ob,aC,cC,lC,uC,dC,fC,pC,hC,mC,gC,Cb=v(()=>{"use strict";sa();Yi();oa();Ss();Tb();Yi();Wr();Ob=new Cn,aC=Ob.displayName,{info:cC,poll:lC,logInlineStatus:uC,listSessions:dC,searchSessions:fC,sessionPeek:pC,attach:hC,composerPasteRead:mC,summarizeTurn:gC}=nr(Ob)});var Rb={};Na(Rb,{attach:()=>EC,breakout:()=>cd,composerPasteRead:()=>AC,displayName:()=>yC,downloadSample:()=>bd,git:()=>Je,gitChangedFiles:()=>Qu,gitDiff:()=>Zu,info:()=>bC,launchBulb:()=>pd,listBreakouts:()=>ld,listBulbFiles:()=>dd,listMyBulbs:()=>vd,listSamples:()=>yd,listSessions:()=>SC,logInlineStatus:()=>vC,openFile:()=>ad,poll:()=>wC,predictTrustOf:()=>hd,pullRemoteBulb:()=>Sd,pushLocalBulb:()=>kd,readBulbLog:()=>gd,repoRoot:()=>cn,searchBulbs:()=>fd,searchSessions:()=>kC,sessionPeek:()=>xC,setBulbTrust:()=>md,stopBreakout:()=>ud,summarizeTurn:()=>TC});var _b,yC,bC,wC,vC,SC,kC,xC,EC,AC,TC,Ib=v(()=>{"use strict";sa();jl();oa();Ss();_b=new _n,yC=_b.displayName,{info:bC,poll:wC,logInlineStatus:vC,listSessions:SC,searchSessions:kC,sessionPeek:xC,attach:EC,composerPasteRead:AC,summarizeTurn:TC}=nr(_b)});import{readFileSync as OC,writeFileSync as PC,mkdirSync as CC}from"fs";import{homedir as _C}from"os";import*as fa from"path";async function Lb(){try{let n=await fetch(new URL("/api/tags",$b()).toString(),{signal:AbortSignal.timeout(RC)});return n.ok?((await n.json()).models??[]).map(t=>t.name).filter(t=>!!t):[]}catch{return[]}}function Mb(n){let e;try{e=OC(n,"utf-8")}catch{return{json:void 0,unreadable:!1}}try{let t=JSON.parse(e);if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;return{json:r,unreadable:"providers"in r&&!Cd(r)}}}catch{}return{json:void 0,unreadable:!0}}function Cd(n){let e=n?.providers;return e&&typeof e=="object"&&!Array.isArray(e)?e:void 0}function IC(n){let e=Cd(n);if(!e||!("ollama"in e))return null;let t=e.ollama?.models;return Array.isArray(t)?t.map(r=>r?.id).filter(r=>typeof r=="string"):[]}async function Bb(){let{json:n,unreadable:e}=Mb(Nb());return e?{installed:[],configured:null}:{installed:await Lb(),configured:IC(n)}}async function Db(){let n=await Lb();return n.length?NC(Nb(),n,$b()):{ok:!1,error:"Ollama is not running (or has no models installed)"}}function NC(n,e,t){let{json:r,unreadable:s}=Mb(n);if(s)return{ok:!1,error:`could not parse ${n} \u2014 edit the ollama provider there yourself`};let i={...r??{},providers:{...Cd(r)??{},ollama:{baseUrl:`${t}/v1`,api:"openai-completions",apiKey:"ollama",models:e.map(o=>({id:o}))}}};try{CC(fa.dirname(n),{recursive:!0}),PC(n,JSON.stringify(i,null,2)+`
1865
- `)}catch(o){return{ok:!1,error:`could not write ${n}: ${Y(o)}`}}return{ok:!0,count:e.length}}var RC,Nb,$b,jb=v(()=>{"use strict";Lt();Qn();RC=1500,Nb=()=>fa.join(_C(),".pi","agent","models.json"),$b=()=>Jn(process.env.OLLAMA_HOST??"http://localhost:11434")});var Ub={};Na(Ub,{attach:()=>UC,breakout:()=>cd,composerFiles:()=>WC,composerNew:()=>KC,composerPaste:()=>VC,composerPasteRead:()=>zC,composerRpc:()=>YC,composerSend:()=>qC,composerStop:()=>JC,composerUiRespond:()=>HC,displayName:()=>$C,downloadSample:()=>bd,git:()=>Je,gitChangedFiles:()=>Qu,gitDiff:()=>Zu,info:()=>LC,launchBulb:()=>pd,listBreakouts:()=>ld,listBulbFiles:()=>dd,listMyBulbs:()=>vd,listSamples:()=>yd,listSessions:()=>DC,logInlineStatus:()=>BC,ollamaOffer:()=>Bb,ollamaSync:()=>Db,openFile:()=>ad,poll:()=>MC,predictTrustOf:()=>hd,pullRemoteBulb:()=>Sd,pushLocalBulb:()=>kd,readBulbLog:()=>gd,repoRoot:()=>cn,searchBulbs:()=>fd,searchSessions:()=>jC,sessionPeek:()=>FC,setBulbTrust:()=>md,shutdownComposer:()=>XC,stopBreakout:()=>ud,summarizeTurn:()=>GC});var Fb,$C,LC,MC,BC,DC,jC,FC,UC,qC,JC,KC,WC,HC,YC,VC,zC,GC,XC,qb=v(()=>{"use strict";sa();Gu();oa();Ss();jb();Fb=new er,$C=Fb.displayName,{info:LC,poll:MC,logInlineStatus:BC,listSessions:DC,searchSessions:jC,sessionPeek:FC,attach:UC,composerSend:qC,composerStop:JC,composerNew:KC,composerFiles:WC,composerUiRespond:HC,composerRpc:YC,composerPaste:VC,composerPasteRead:zC,summarizeTurn:GC,shutdownComposer:XC}=nr(Fb)});import*as tv from"fs/promises";import*as dt from"path";Ds();Z();function Il(n){if(!Re.includes(n))throw new Error(`Unknown block kind '${n}' (one of: ${Re.join(", ")})`);return n}function Bm(n){let e=[];for(let t of n){let r=t.indexOf("=");if(r<=0||r===t.length-1)throw new Error(`Expected <kind>=<source>, got '${t}' (e.g. data=results.json, or data=- for stdin)`);let s=Il(t.slice(0,r));if(e.some(i=>i.kind===s))throw new Error(`Duplicate block kind '${s}' \u2014 each block can be written once per invocation`);e.push({kind:s,source:t.slice(r+1)})}if(e.filter(t=>t.source==="-").length>1)throw new Error("Only one <kind>=- can read stdin");return e}Yi();jl();Gu();var pa={claude:{adapter:()=>new Cn,server:()=>Promise.resolve().then(()=>(Cb(),Pb))},codex:{adapter:()=>new _n,server:()=>Promise.resolve().then(()=>(Ib(),Rb))},pi:{adapter:()=>new er,server:()=>Promise.resolve().then(()=>(qb(),Ub))}};function Jb(n){return n in pa}function sr(){return Object.keys(pa)}function Kb(){return Object.fromEntries(Object.entries(pa).map(([n,e])=>[n,e.adapter]))}function Wb(n){return pa[n].server()}var Os=Kb();function Hb(){for(let n of Object.values(Os))try{n().ensureHarnessSupport()}catch{}}function pn(){for(let n of Object.keys(Os))try{if(Os[n]().detectsSelf())return n}catch{}}function Yb(n){let e=sr(),t=new Map(e.filter(i=>Os[i]).map(i=>[i,Os[i]()]));for(let[i,o]of t)if(o.detectsSelf())return{name:i};let r=[...t].filter(([,i])=>i.detectsInstalled()).map(([i])=>i);if(r.length===0)return{name:e[0]};if(r.length===1)return{name:r[0]};let s=i=>t.get(i).listSessionFiles(n).length>0;return{ambiguous:[...r].sort((i,o)=>Number(s(o))-Number(s(i)))}}var Rd=5e3;function _d(n){try{return n()}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}}function Vb(n){let t={subcommand:"run",file:"",watch:!0,open:!(process.env.TERM_PROGRAM==="vscode"||pn()!==void 0),server:!1,trust:!1,noTrust:!1,force:!1,follow:!1,clear:!1,help:!1,version:!1,callArgs:[],hasArgsFlag:!1},r=["call","check","predict","logs","wait","stop","trust","untrust","models","slug","send","pull","push","get","put"],s=n[0];if(s==="agent"||s?.startsWith("agent:")){t.subcommand="agent";let o=s.indexOf(":");if(o!==-1){let a=s.slice(o+1);a&&(t.agentTarget=a)}n=n.slice(1)}else s&&r.includes(s)&&(t.subcommand=s,n=n.slice(1));let i=[];for(let o=0;o<n.length;o++){let a=n[o];if(a==="--help"||a==="-h")t.help=!0;else if(a==="--version"||a==="-V")t.version=!0;else if(a==="--no-watch")t.watch=!1;else if(a==="--open")t.open=!0;else if(a==="--no-open")t.open=!1;else if(a==="--server")t.server=!0;else if(a==="--trust")t.trust=!0;else if(a==="--no-trust")t.noTrust=!0;else if(a==="--force")t.force=!0;else if(a==="--mode"){let c=n[++o];(!c||c.startsWith("-"))&&(console.error("Missing value for --mode (e.g. --mode staging)"),process.exit(1)),t.mode=c}else if(a==="--batch"){let c=n[++o];(!c||c.startsWith("-"))&&(console.error("Missing value for --batch (a batch name, e.g. --batch pilot)"),process.exit(1));let l=c.replace(/[\\/]+$/,"");(!l||/[\\/]/.test(l)||l==="."||l==="..")&&(console.error(`Invalid --batch value: ${c} (a single folder name \u2014 no path separators or dot segments)`),process.exit(1)),t.batch=l}else if(a==="--follow"||a==="-f")t.follow=!0;else if(a==="--clear")t.clear=!0;else if(a==="--run"){let c=n[++o];if(c==="latest")t.run="latest";else{let l=parseInt(c,10);(isNaN(l)||l<1)&&(console.error(`Invalid --run value: ${c} (a run number, or 'latest')`),process.exit(1)),t.run=l}}else if(a==="--bulbs")t.stopScope="bulbs";else if(a==="--agent")t.stopScope="agent";else if(a==="--global")t.stopScope="global";else if(a==="--match"){let c=n[++o];c===void 0&&(console.error("Missing value for --match (a literal substring new log lines must contain)"),process.exit(1)),t.match=c}else if(a==="--timeout"){let c=parseInt(n[++o],10);(isNaN(c)||c<=0)&&(console.error(`Invalid --timeout value: ${n[o]} (seconds)`),process.exit(1)),t.timeoutSec=c}else if(a==="--wait"||a.startsWith("--wait="))if(a.startsWith("--wait=")){let c=parseInt(a.slice(7),10);(isNaN(c)||c<=0)&&(console.error(`Invalid --wait value: ${a.slice(7)} (milliseconds)`),process.exit(1)),t.sendWaitMs=c}else t.sendWaitMs=Rd;else if(a==="--lines"||a==="-n"){let c=parseInt(n[++o],10);(isNaN(c)||c<0)&&(console.error(`Invalid --lines value: ${n[o]}`),process.exit(1)),t.lines=c}else if(a==="--port"||a==="-p"){let c=n[++o],l=parseInt(c,10);isNaN(l)&&(console.error(`Invalid port: ${c}`),process.exit(1)),t.port=l}else if(a==="--replace"||a.startsWith("--replace=")){let c=a.startsWith("--replace=")?a.slice(10):n[++o]??"",l=_d(()=>rf(c));t.local&&(console.error(`--replace can only be used once (got '${t.local.name}' and '${l.name}')`),process.exit(1)),t.local=l}else if(a==="--args"||a.startsWith("--args=")){t.hasArgsFlag=!0;let c=a.startsWith("--args=")?a.slice(7):n[++o];c===void 0&&(console.error("Missing value for --args (a JSON array, or - to read it from stdin)"),process.exit(1)),t.argsJson=c}else if(!a.startsWith("-"))["call","send","get","put","slug"].includes(t.subcommand)?i.push(a):t.file=a;else{let c=t.subcommand==="call"?" (for a negative or dash-leading argument, use --args '<json-array>')":"";console.error(`Unknown option: ${a}${c}`),process.exit(1)}}return t.subcommand==="call"&&(i.length<2&&(console.error("Usage: typebulb call <file> <fn> [arg\u2026]"),process.exit(1)),t.file=i[0],t.fn=i[1],t.callArgs=i.slice(2)),t.subcommand==="send"&&(i.length<1&&(console.error("Usage: typebulb send <file> [message]"),process.exit(1)),t.file=i[0],t.sendMessage=i[1]),t.subcommand==="slug"&&(i.length||(console.error("Usage: typebulb slug <bulb name>"),process.exit(1)),t.slugName=i.join(" ")),t.subcommand==="get"&&(i.length!==2&&(console.error("Usage: typebulb get <file> <kind>"),process.exit(1)),t.file=i[0],t.blockKind=_d(()=>Il(i[1]))),t.subcommand==="put"&&(i.length<2&&(console.error("Usage: typebulb put <file> <kind>=<source> [<kind>=<source> \u2026]"),process.exit(1)),t.file=i[0],t.blockPairs=_d(()=>Bm(i.slice(1)))),t}function zb(){console.log(`
1866
+ `)}catch(o){return{ok:!1,error:`could not write ${n}: ${Y(o)}`}}return{ok:!0,count:e.length}}var RC,Nb,$b,jb=v(()=>{"use strict";Lt();Qn();RC=1500,Nb=()=>fa.join(_C(),".pi","agent","models.json"),$b=()=>Jn(process.env.OLLAMA_HOST??"http://localhost:11434")});var Ub={};Na(Ub,{attach:()=>UC,breakout:()=>cd,composerFiles:()=>WC,composerNew:()=>KC,composerPaste:()=>VC,composerPasteRead:()=>zC,composerRpc:()=>YC,composerSend:()=>qC,composerStop:()=>JC,composerUiRespond:()=>HC,displayName:()=>$C,downloadSample:()=>bd,git:()=>Je,gitChangedFiles:()=>Qu,gitDiff:()=>Zu,info:()=>LC,launchBulb:()=>pd,listBreakouts:()=>ld,listBulbFiles:()=>dd,listMyBulbs:()=>vd,listSamples:()=>yd,listSessions:()=>DC,logInlineStatus:()=>BC,ollamaOffer:()=>Bb,ollamaSync:()=>Db,openFile:()=>ad,poll:()=>MC,predictTrustOf:()=>hd,pullRemoteBulb:()=>Sd,pushLocalBulb:()=>kd,readBulbLog:()=>gd,repoRoot:()=>cn,searchBulbs:()=>fd,searchSessions:()=>jC,sessionPeek:()=>FC,setBulbTrust:()=>md,shutdownComposer:()=>XC,stopBreakout:()=>ud,summarizeTurn:()=>GC});var Fb,$C,LC,MC,BC,DC,jC,FC,UC,qC,JC,KC,WC,HC,YC,VC,zC,GC,XC,qb=v(()=>{"use strict";sa();Gu();oa();Ss();jb();Fb=new er,$C=Fb.displayName,{info:LC,poll:MC,logInlineStatus:BC,listSessions:DC,searchSessions:jC,sessionPeek:FC,attach:UC,composerSend:qC,composerStop:JC,composerNew:KC,composerFiles:WC,composerUiRespond:HC,composerRpc:YC,composerPaste:VC,composerPasteRead:zC,summarizeTurn:GC,shutdownComposer:XC}=nr(Fb)});import*as tv from"fs/promises";import*as dt from"path";Ds();Z();function Il(n){if(!Re.includes(n))throw new Error(`Unknown block kind '${n}' (one of: ${Re.join(", ")})`);return n}function Bm(n){let e=[];for(let t of n){let r=t.indexOf("=");if(r<=0||r===t.length-1)throw new Error(`Expected <kind>=<source>, got '${t}' (e.g. data=results.json, or data=- for stdin)`);let s=Il(t.slice(0,r));if(e.some(i=>i.kind===s))throw new Error(`Duplicate block kind '${s}' \u2014 each block can be written once per invocation`);e.push({kind:s,source:t.slice(r+1)})}if(e.filter(t=>t.source==="-").length>1)throw new Error("Only one <kind>=- can read stdin");return e}Yi();jl();Gu();var pa={claude:{adapter:()=>new Cn,server:()=>Promise.resolve().then(()=>(Cb(),Pb))},codex:{adapter:()=>new _n,server:()=>Promise.resolve().then(()=>(Ib(),Rb))},pi:{adapter:()=>new er,server:()=>Promise.resolve().then(()=>(qb(),Ub))}};function Jb(n){return n in pa}function sr(){return Object.keys(pa)}function Kb(){return Object.fromEntries(Object.entries(pa).map(([n,e])=>[n,e.adapter]))}function Wb(n){return pa[n].server()}var Os=Kb();function Hb(){for(let n of Object.values(Os))try{n().ensureHarnessSupport()}catch{}}function pn(){for(let n of Object.keys(Os))try{if(Os[n]().detectsSelf())return n}catch{}}function Yb(n){let e=sr(),t=new Map(e.filter(i=>Os[i]).map(i=>[i,Os[i]()]));for(let[i,o]of t)if(o.detectsSelf())return{name:i};let r=[...t].filter(([,i])=>i.detectsInstalled()).map(([i])=>i);if(r.length===0)return{name:e[0]};if(r.length===1)return{name:r[0]};let s=i=>t.get(i).listSessionFiles(n).length>0;return{ambiguous:[...r].sort((i,o)=>Number(s(o))-Number(s(i)))}}var Rd=5e3;function _d(n){try{return n()}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}}function Vb(n){let t={subcommand:"run",file:"",watch:!0,open:!(process.env.TERM_PROGRAM==="vscode"||pn()!==void 0),server:!1,trust:!1,noTrust:!1,force:!1,follow:!1,clear:!1,help:!1,version:!1,callArgs:[],hasArgsFlag:!1},r=["call","check","predict","logs","wait","stop","trust","untrust","models","slug","send","pull","push","get","put"],s=n[0];if(s==="agent"||s?.startsWith("agent:")){t.subcommand="agent";let o=s.indexOf(":");if(o!==-1){let a=s.slice(o+1);a&&(t.agentTarget=a)}n=n.slice(1)}else s&&r.includes(s)&&(t.subcommand=s,n=n.slice(1));let i=[];for(let o=0;o<n.length;o++){let a=n[o];if(a==="--help"||a==="-h")t.help=!0;else if(a==="--version"||a==="-V")t.version=!0;else if(a==="--no-watch")t.watch=!1;else if(a==="--open")t.open=!0;else if(a==="--no-open")t.open=!1;else if(a==="--server")t.server=!0;else if(a==="--trust")t.trust=!0;else if(a==="--no-trust")t.noTrust=!0;else if(a==="--force")t.force=!0;else if(a==="--mode"){let c=n[++o];(!c||c.startsWith("-"))&&(console.error("Missing value for --mode (e.g. --mode staging)"),process.exit(1)),t.mode=c}else if(a==="--batch"){let c=n[++o];(!c||c.startsWith("-"))&&(console.error("Missing value for --batch (a batch name, e.g. --batch pilot)"),process.exit(1));let l=c.replace(/[\\/]+$/,"");(!l||/[\\/]/.test(l)||l==="."||l==="..")&&(console.error(`Invalid --batch value: ${c} (a single folder name \u2014 no path separators or dot segments)`),process.exit(1)),t.batch=l}else if(a==="--follow"||a==="-f")t.follow=!0;else if(a==="--clear")t.clear=!0;else if(a==="--run"){let c=n[++o];if(c==="latest")t.run="latest";else{let l=parseInt(c,10);(isNaN(l)||l<1)&&(console.error(`Invalid --run value: ${c} (a run number, or 'latest')`),process.exit(1)),t.run=l}}else if(a==="--bulbs")t.stopScope="bulbs";else if(a==="--agent")t.stopScope="agent";else if(a==="--global")t.stopScope="global";else if(a==="--match"){let c=n[++o];c===void 0&&(console.error("Missing value for --match (a literal substring new log lines must contain)"),process.exit(1)),t.match=c}else if(a==="--timeout"){let c=parseInt(n[++o],10);(isNaN(c)||c<=0)&&(console.error(`Invalid --timeout value: ${n[o]} (seconds)`),process.exit(1)),t.timeoutSec=c}else if(a==="--wait"||a.startsWith("--wait="))if(a.startsWith("--wait=")){let c=parseInt(a.slice(7),10);(isNaN(c)||c<=0)&&(console.error(`Invalid --wait value: ${a.slice(7)} (milliseconds)`),process.exit(1)),t.sendWaitMs=c}else t.sendWaitMs=Rd;else if(a==="--lines"||a==="-n"){let c=parseInt(n[++o],10);(isNaN(c)||c<0)&&(console.error(`Invalid --lines value: ${n[o]}`),process.exit(1)),t.lines=c}else if(a==="--port"||a==="-p"){let c=n[++o],l=parseInt(c,10);isNaN(l)&&(console.error(`Invalid port: ${c}`),process.exit(1)),t.port=l}else if(a==="--replace"||a.startsWith("--replace=")){let c=a.startsWith("--replace=")?a.slice(10):n[++o]??"",l=_d(()=>rf(c));t.local&&(console.error(`--replace can only be used once (got '${t.local.name}' and '${l.name}')`),process.exit(1)),t.local=l}else if(a==="--args"||a.startsWith("--args=")){t.hasArgsFlag=!0;let c=a.startsWith("--args=")?a.slice(7):n[++o];c===void 0&&(console.error("Missing value for --args (a JSON array, or - to read it from stdin)"),process.exit(1)),t.argsJson=c}else if(!a.startsWith("-")||a==="-"&&t.subcommand==="send")["call","send","get","put","slug"].includes(t.subcommand)?i.push(a):t.file=a;else{let c=t.subcommand==="call"?" (for a negative or dash-leading argument, use --args '<json-array>')":"";console.error(`Unknown option: ${a}${c}`),process.exit(1)}}return t.subcommand==="call"&&(i.length<2&&(console.error("Usage: typebulb call <file> <fn> [arg\u2026]"),process.exit(1)),t.file=i[0],t.fn=i[1],t.callArgs=i.slice(2)),t.subcommand==="send"&&(i.length<1&&(console.error("Usage: typebulb send <file> [message]"),process.exit(1)),t.file=i[0],t.sendMessage=i[1]),t.subcommand==="slug"&&(i.length||(console.error("Usage: typebulb slug <bulb name>"),process.exit(1)),t.slugName=i.join(" ")),t.subcommand==="get"&&(i.length!==2&&(console.error("Usage: typebulb get <file> <kind>"),process.exit(1)),t.file=i[0],t.blockKind=_d(()=>Il(i[1]))),t.subcommand==="put"&&(i.length<2&&(console.error("Usage: typebulb put <file> <kind>=<source> [<kind>=<source> \u2026]"),process.exit(1)),t.file=i[0],t.blockPairs=_d(()=>Bm(i.slice(1)))),t}function zb(){console.log(`
1866
1867
  typebulb - Local bulb runner for Typebulb
1867
1868
 
1868
1869
  Usage:
@@ -2243,7 +2244,7 @@ declare const tb: {${i_}${Zb}${nw}${rw}${ew}${tw}
2243
2244
  `);await this.prefetchBareDeps(m,l,d,p,s);let h=c.format(),y=e===h?[e]:[e,h],A=y.some(S=>this.ambientlyDeclares(i,S));return A?this.markFileAmbient(d,f):p.push(...y.map(S=>({module:S,path:f}))),{pkg:e,mainPath:f,files:d,shims:p,ambient:A}}};uu();nt();Mn();ls();cu();Ln();import*as or from"path";var u_=or.join(ao,"pkg"),d_=or.join(ao,"files"),f_=or.join(ao,"negative.json"),Sa=class{pkgMem=new Map;fileMem=new Map;negativeCache=new Qt(new Bn(f_));async getCachedDts(e){if(this.pkgMem.has(e))return this.pkgMem.get(e);await ee();let t=await rt(cw(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 va(async()=>{await ee(),await Ae(cw(e),JSON.stringify(s))})}async getCachedFile(e){if(this.fileMem.has(e))return this.fileMem.get(e);await ee();let t=await oo(lw(e));return this.fileMem.set(e,t),t}async setCachedFile(e,t){this.fileMem.set(e,t),await va(async()=>{await ee(),await Ae(lw(e),t)})}isNegative(e){return this.negativeCache.isNegative(e)}async recordNegative(e){await va(async()=>{await ee(),await this.negativeCache.recordNegative(e)})}clearNegative(e){return va(()=>this.negativeCache.clearNegative(e))}};async function va(n){try{await n()}catch{}}function cw(n){return or.join(u_,De(n)+".json")}function lw(n){return or.join(d_,De(n)+".txt")}Mn();var Dd;function p_(){return Dd||(Dd=new Cs({cache:new Sa,cdnClient:Rg,packageService:fo,versionResolver:_g})),Dd}var uw="file:///node_modules/";async function dw(n){let e=co(n.emitKey,"typecheck");await ee(),await fe.rm(e,{recursive:!0,force:!0}),await fe.mkdir(e,{recursive:!0});let t=y_(n.jsxImportSource,n.dependencies),r=await p_().resolve(n.code,n.dependencies,t),s=n.local?.name,i=s?r.filter(f=>f.pkg!==s):r,o=new Set;for(let f of i)for(let u of f.files){let d=ka(u.path);if(!d||o.has(d))continue;o.add(d);let p=ue.join(e,"node_modules",d);await fe.mkdir(ue.dirname(p),{recursive:!0}),await fe.writeFile(p,u.content,"utf8")}let a={};for(let f of i)for(let u of f.shims){let d=ka(u.path);d&&(a[u.module]=[`./node_modules/${d}`])}for(let f of i){if(f.ambient)continue;let u=ka(f.mainPath);u&&(a[f.pkg]=[`./node_modules/${u}`])}let c=new Set;for(let f of i)for(let u of f.files){if(!u.ambient)continue;let d=ka(u.path);d&&c.add(`node_modules/${d}`)}if(n.local){delete a[n.local.name];let f=await b_(n.local,e);f?a[n.local.name]=[`./node_modules/${n.local.name}/${f}`]:console.warn(` local: '${n.local.name}' ships no type defs; check cannot type against it.`)}let l=h_(n.jsxImportSource,a,[...c]);return await fe.writeFile(ue.join(e,"tsconfig.json"),JSON.stringify(l,null,2)+`
2244
2245
  `,"utf8"),await fe.writeFile(ue.join(e,"code.tsx"),n.code,"utf8"),await fe.writeFile(ue.join(e,"tb.d.ts"),Ld,"utf8"),{dir:e}}var jd={target:"es2023",module:"esnext",moduleResolution:"bundler",strict:!0,noEmit:!0,skipLibCheck:!0,esModuleInterop:!0,allowSyntheticDefaultImports:!0,forceConsistentCasingInFileNames:!0};function h_(n,e,t=[]){return{compilerOptions:{...jd,lib:m_([...Id,...Nd]),jsx:"react-jsx",jsxImportSource:n??"react",paths:e},include:["code.tsx","tb.d.ts",...t]}}function m_(n){return $d(n).map(e=>g_(e.name))}function g_(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 y_(n,e){let t=n??("react"in e?"react":void 0);return t?[`${t}/jsx-runtime`,`${t}/jsx-dev-runtime`]:[]}function ka(n){if(!n.startsWith(uw))return;let e=n.slice(uw.length),t=e.indexOf("/");if(!(t<0))return e.slice(t+1)}async function b_(n,e){if(!n.typesAbs)return;let t=ue.dirname(n.typesAbs),r=ue.join(e,"node_modules",n.name);for(let s of await w_(t)){let i=ue.join(r,ue.relative(t,s));await fe.mkdir(ue.dirname(i),{recursive:!0}),await fe.copyFile(s,i)}return ue.basename(n.typesAbs)}async function w_(n){let e=[];async function t(r){let s=await fe.readdir(r,{withFileTypes:!0});for(let i of s){let o=ue.join(r,i.name);i.isDirectory()?await t(o):/\.d\.ts(\.map)?$/.test(i.name)&&e.push(o)}}return await t(n),e}import*as Pe from"fs/promises";import*as ut from"path";import{existsSync as v_}from"fs";Mn();du();var S_="^22";async function fw(n){let e=co(n.emitKey,"typecheck-server");await ee(),await Pe.rm(e,{recursive:!0,force:!0}),await Pe.mkdir(e,{recursive:!0});let t=ut.join(n.bulbDir,".typebulb"),r=vo(n.server).filter(o=>o!==n.local?.name);await wo([`@types/node@${S_}`,...r],t,n.dependencies,{ignoreScripts:!0});let s=ut.join(t,"node_modules"),i=ut.join(e,"node_modules");return await x_(s,i),await Pe.writeFile(ut.join(e,"server.ts"),n.server,"utf8"),await Pe.writeFile(ut.join(e,"tb.d.ts"),Md,"utf8"),await Pe.writeFile(ut.join(e,"tsconfig.json"),JSON.stringify(k_(n.local),null,2)+`
2245
2246
  `,"utf8"),{dir:e}}function k_(n){let e={...jd,lib:["ES2023"],types:["node"]};if(n?.typesAbs){let t=i=>i.replace(/\\/g,"/"),r=t(ut.dirname(n.typesAbs)),s=t(n.typesAbs).replace(/\.d\.ts$/,"");e.paths={[n.name]:[s],[`${n.name}/*`]:[`${r}/*`]}}return{compilerOptions:e,include:["server.ts","tb.d.ts"]}}async function x_(n,e){if(!v_(n)){await Pe.mkdir(e,{recursive:!0});return}await Pe.rm(e,{recursive:!0,force:!0});let t=process.platform==="win32"?"junction":"dir";await Pe.symlink(n,e,t)}no();Z();async function hw(n,e){let{bulb:t,config:r,warnings:s,starts:i}=await qe(n),o=Ce.basename(n),a=h=>i.get(h)??1;!t.code&&!t.server&&(console.error("Bulb has neither **code.tsx** nor **server.ts**; nothing to check."),process.exit(1));let c=!1,l=!1;for(let h of s)console.log(`structure ${h}`);s.length&&(c=!0);let f=Hn(Ce.resolve(n)),u=f?On(t.name):"";f&&u&&u!==f.slug&&(console.log(`naming filename '${f.slug}.bulb.md' doesn't match the title '${t.name}' \u2014 its slug derives to '${u}'. Rename the file to '${u}.bulb.md', or change name: to suit the filename.`),l=!0),t.code&&(c=pw(Zr(t.code,{target:"client",dependencies:r.dependencies??{},lineOffset:a("code.tsx")}),"client")||c),t.server&&(c=pw(Zr(t.server,{target:"server",lineOffset:a("server.ts")}),"server")||c);let d=R_([process.cwd(),Ce.dirname(n)]);if(!d){let h=Ce.relative(process.cwd(),n)||n;console.error("check: TypeScript not found \u2014 install it once, then re-run:"),console.error(" npm i -g typescript"),console.error(` typebulb check ${h}`),process.exit(2)}let p=[];if(t.code){let{dir:h}=await dw({code:t.code,dependencies:r.dependencies??{},jsxImportSource:r.ts?.jsxImportSource,emitKey:n,local:e});p.push({role:"client",dir:h})}if(t.server){let{dir:h}=await fw({server:t.server,bulbDir:Ce.dirname(n),emitKey:n,local:e?{name:e.name,typesAbs:e.typesAbs}:void 0,dependencies:r.dependencies});p.push({role:"server",dir:h})}for(let{role:h,dir:y}of p){let{stdout:A,exitCode:S}=await C_(d,y);for(let P of A.split(/\r?\n/))P.trim()&&console.log(`${h} ${P_(P,o,a)}`);S!==0&&(c=!0)}c&&process.exit(1);let m=[t.code&&"code.tsx",t.server&&"server.ts"].filter(Boolean).join(", ");console.error(l?`\u2713 type-checks (${m}) \u2014 see the naming warning above`:`\u2713 no issues (${m})`)}function pw(n,e){for(let t of n)for(let r of t.message.split(`
2246
- `))console.log(`${e} ${r}`);return n.length>0}function P_(n,e,t){return n.replace(/\b(code\.tsx|server\.ts)\((\d+),(\d+)\)/g,(r,s,i,o)=>`${e}(${Number(i)+t(s)-1},${o})`)}function C_(n,e){return new Promise(t=>{let r=E_(process.execPath,[n,"--noEmit"],{cwd:e}),s="";r.stdout?.on("data",i=>{s+=i.toString()}),r.stderr?.on("data",i=>{s+=i.toString()}),r.on("close",i=>t({stdout:s,exitCode:i??1}))})}var __=T_(import.meta.url);function R_(n){let e=r=>{try{let s=__.resolve("typescript/package.json",{paths:r}),i=Ce.join(Ce.dirname(s),"lib","tsc.js");return O_(i)?i:void 0}catch{return}},t=e(n);if(t)return t;try{let r=A_("npm root -g",{encoding:"utf8"}).trim();return e([r])}catch{return}}ze();Fo();ys();async function mw(n,e){let{bulb:t}=await qe(n),r=Vn(t);if(on(n)){console.log("remembered-trusted \u2014 runs with filesystem / AI / server.ts automatically (`typebulb untrust` to revoke)."),r&&console.log(` (it uses ${r})`);return}r?(console.log(`This bulb appears to use ${r}; it runs Restricted unless you grant trust:`),console.log(` ${e}`)):console.log("No privileged capability detected \u2014 runs Restricted by default. (A clean scan is a hint, not a guarantee.)")}ys();import*as _s from"path";async function gw(n,e){if(!n){e||(console.error("Usage: typebulb untrust <file.bulb.md>"),process.exit(1));let r=ju();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=_s.resolve(n);t.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1));try{zn(t,e)}catch(r){console.error(r.message),process.exit(1)}console.log(e?`Trusted ${_s.basename(t)} \u2014 runs with fs / AI / server.ts (no --trust needed).`:`Untrusted ${_s.basename(t)} \u2014 runs Restricted.`),console.log(` ${t}`)}Ee();import*as ww from"readline";Fu();function Fd(n){let e=t=>r=>n?`\x1B[${t}m${r}\x1B[0m`:r;return{lit:e("38;5;70"),litLink:e("4;38;5;70"),brand:e("38;5;135")}}var I_=5e3,xa=()=>Math.round(performance.now()),yw=n=>n>=1e3?`${(n/1e3).toFixed(1)}s`:`${n}ms`;async function vw(n){let e=Yb(process.cwd()),t=xa();if("ambiguous"in e){let r=await N_(n,e.ambiguous);return r?bw(n,r,{boot:t,from:xa()}):$_(n,e.ambiguous)}return bw(n,e.name,{boot:t,from:xa()})}async function bw(n,e,t){let r,s;try{r=await ig(e)}catch(p){s=p instanceof Error?p.message:String(p)}let i=xa()-t.from,{lit:o,litLink:a,brand:c}=Fd(process.stdout.isTTY===!0),l=[" Read the authoring skill before writing a bulb:",` \u2022 ${o(bs())}`],f=r?[` Agent mirror (${e}) is live\u{1F4A1}`,` ${o("\u25CF")} ${a(r.url)}`," Inline bulbs render live here."," Agents:",` Reusable app/tool \u2192 write a ${o(".bulb.md")}`," Show something inline \u2192 emit an inline bulb",...e==="codex"?[" verify it this turn \u2014 foreground-wait, bounded:",` \u2022 ${o('typebulb wait agent --match "[inline <name>" --timeout 120')}`," raise the shell tool's timeout_ms to 130000"," (its 10s default kills even a clean ok)"]:[e==="pi"?" arm a wait for its render verdict \u2014 run it plainly:":" background a wait for its render verdict:",` \u2022 ${o('typebulb wait agent --match "[inline <name>"')}`],...l," End this reply with the mirror link above"," \u2022 easy to miss the link mid-message"]:[` The mirror did not start (${s})`,` \u25CF Start it manually: ${o(`npx typebulb agent:${e}`)}`," Agents:",...l],u=t.boot+i>I_?[` slow launch: boot ${yw(t.boot)} \xB7 mirror ${yw(i)}`]:[],d=[` ${c(`typebulb v${n}`)}`,...u,...f,""];process.stdout.write(d.join(`
2247
+ `))console.log(`${e} ${r}`);return n.length>0}function P_(n,e,t){return n.replace(/\b(code\.tsx|server\.ts)\((\d+),(\d+)\)/g,(r,s,i,o)=>`${e}(${Number(i)+t(s)-1},${o})`)}function C_(n,e){return new Promise(t=>{let r=E_(process.execPath,[n,"--noEmit"],{cwd:e}),s="";r.stdout?.on("data",i=>{s+=i.toString()}),r.stderr?.on("data",i=>{s+=i.toString()}),r.on("close",i=>t({stdout:s,exitCode:i??1}))})}var __=T_(import.meta.url);function R_(n){let e=r=>{try{let s=__.resolve("typescript/package.json",{paths:r}),i=Ce.join(Ce.dirname(s),"lib","tsc.js");return O_(i)?i:void 0}catch{return}},t=e(n);if(t)return t;try{let r=A_("npm root -g",{encoding:"utf8"}).trim();return e([r])}catch{return}}ze();Fo();ys();async function mw(n,e){let{bulb:t}=await qe(n),r=Vn(t);if(on(n)){console.log("remembered-trusted \u2014 runs with filesystem / AI / server.ts automatically (`typebulb untrust` to revoke)."),r&&console.log(` (it uses ${r})`);return}r?(console.log(`This bulb appears to use ${r}; it runs Restricted unless you grant trust:`),console.log(` ${e}`)):console.log("No privileged capability detected \u2014 runs Restricted by default. (A clean scan is a hint, not a guarantee.)")}ys();import*as _s from"path";async function gw(n,e){if(!n){e||(console.error("Usage: typebulb untrust <file.bulb.md>"),process.exit(1));let r=ju();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=_s.resolve(n);t.endsWith(".bulb.md")||(console.error("File must have .bulb.md extension"),process.exit(1));try{zn(t,e)}catch(r){console.error(r.message),process.exit(1)}console.log(e?`Trusted ${_s.basename(t)} \u2014 runs with fs / AI / server.ts (no --trust needed).`:`Untrusted ${_s.basename(t)} \u2014 runs Restricted.`),console.log(` ${t}`)}Ee();import*as ww from"readline";Fu();function Fd(n){let e=t=>r=>n?`\x1B[${t}m${r}\x1B[0m`:r;return{lit:e("38;5;70"),litLink:e("4;38;5;70"),brand:e("38;5;135")}}var I_=5e3,xa=()=>Math.round(performance.now()),yw=n=>n>=1e3?`${(n/1e3).toFixed(1)}s`:`${n}ms`;async function vw(n){let e=Yb(process.cwd()),t=xa();if("ambiguous"in e){let r=await N_(n,e.ambiguous);return r?bw(n,r,{boot:t,from:xa()}):$_(n,e.ambiguous)}return bw(n,e.name,{boot:t,from:xa()})}async function bw(n,e,t){let r,s;try{r=await ig(e)}catch(p){s=p instanceof Error?p.message:String(p)}let i=xa()-t.from,{lit:o,litLink:a,brand:c}=Fd(process.stdout.isTTY===!0),l=[" Read the authoring skill before writing a bulb:",` \u2022 ${o(bs())}`],f=r?[` Agent mirror (${e}) is live\u{1F4A1}`,` ${o("\u25CF")} ${a(r.url)}`," Inline bulbs render live here."," Agents:",` Reusable app/tool \u2192 write a ${o(".bulb.md")}`," Show something inline \u2192 emit an inline bulb"," emit it with no .bulb.md draft first",...e==="codex"?[" verify it this turn \u2014 foreground-wait, bounded:",` \u2022 ${o('typebulb wait agent --match "[inline <name>" --timeout 120')}`," raise the shell tool's timeout_ms to 130000"," (its 10s default kills even a clean ok)"]:[e==="pi"?" arm a wait for its render verdict \u2014 run it plainly:":" background a wait for its render verdict:",` \u2022 ${o('typebulb wait agent --match "[inline <name>"')}`],...l," End this reply with the mirror link above"," \u2022 easy to miss the link mid-message"]:[` The mirror did not start (${s})`,` \u25CF Start it manually: ${o(`npx typebulb agent:${e}`)}`," Agents:",...l],u=t.boot+i>I_?[` slow launch: boot ${yw(t.boot)} \xB7 mirror ${yw(i)}`]:[],d=[` ${c(`typebulb v${n}`)}`,...u,...f,""];process.stdout.write(d.join(`
2247
2248
  `)+`
2248
2249
  `)}async function N_(n,e){if(!process.stdin.isTTY||!process.stdout.isTTY)return;let{lit:t,brand:r}=Fd(!0),s=[` ${r(`typebulb v${n}`)}`," More than one agent harness is available here.",...e.map((o,a)=>` ${t(String(a+1))}) ${o}`),""];process.stdout.write(s.join(`
2249
2250
  `)+`
@@ -2256,7 +2257,7 @@ declare const tb: {${i_}${Zb}${nw}${rw}${ew}${tw}
2256
2257
  `)&&process.stdout.write(`
2257
2258
  `),e.follow&&e.run===void 0){let i=r.offset,o=setInterval(()=>{let c=He(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 D_=n=>new Promise(e=>setTimeout(e,n));async function Ow(n,e){if(!n){Ud(await Q(process.cwd()),"Run `typebulb wait <file|pid>` to block until one logs a new line.");return}let t=qd(await Q(),n,"wait",process.cwd(),pn()),r=t.agent!=null,s=process.env.TYPEBULB_WAIT_SHIM==="1",i=process.env.TYPEBULB_WAIT_FOLLOW==="1",o=s||i,a=e.timeoutSec??1800,c=e.match??"",l=He(t.pid).offset,f=i?void 0:Kl(t.pid,c)??(c?Kl(t.pid):void 0),u=i?l:f!==void 0&&f<=l?f:c?0:l,d=Date.now()+a*1e3,p=r?1e4:1e3,m=2e3,h,y="",A=0;for(;;){let S=He(t.pid,u);if(u=S.offset,S.text){y+=S.text;let P=y.split(`
2258
2259
  `);y=P.pop()??"";for(let C of P)C.trim()&&(e.match&&!C.includes(e.match)||(console.log(C),!i&&(h??=Date.now()+p,r&&(C.includes("] compile error")||C.includes("] runtime error"))&&(h=Math.min(h,Date.now()+m)))))}if(h&&Date.now()>=h)break;if(!o&&!h&&Date.now()>=d){console.error(`timeout: no ${e.match?`line matching '${e.match}'`:"new output"} from ${Rs(t)} within ${a}s`),A=2;break}if(!Hl(t.pid)){h||(console.error(`server ${Rs(t)} (pid ${t.pid}) exited while waiting`),process.exit(3));break}await D_(400)}i||Xi(t.pid,u,c),process.exit(A)}async function Pw(n){if(!n){Ud(await Q(process.cwd()),"Run `typebulb stop <file|pid>` to stop one.");return}let e=qd(await Q(),n,"stop",process.cwd(),pn());await Yt(e.pid),console.log(`Stopped ${Rs(e)} (pid ${e.pid}, ${e.url}).`)}async function Cw(n){let e=process.cwd(),t=n==="agent"?pn():void 0,r=n==="global"?await Q():n==="bulbs"?await Q(e):(await Q()).filter(i=>i.agent!=null&&i.cwd!=null&&X(i.cwd)===X(e)&&(!t||i.agent===t)),s=n==="global"?"server":n==="agent"?"mirror":"bulb";if(!r.length){console.log(n==="global"?"No running bulb servers.":`No running ${s}s for this project.`);return}await Promise.all(r.map(i=>Yt(i.pid))),console.log(`Stopped ${r.length} ${s}${r.length===1?"":"s"}:`);for(let i of r)console.log(` ${i.url} pid ${i.pid} ${Rs(i)}`)}Ee();At();Yn();import*as Ea from"path";import*as _w from"http";import{mkdir as j_,writeFile as F_}from"fs/promises";async function ar(){let n=[];for await(let e of process.stdin)n.push(e);return Buffer.concat(n).toString("utf-8")}function Is(n){return(n.charCodeAt(0)===65279?n.slice(1):n).replace(/\r\n/g,`
2259
- `).trimEnd()}function U_(n,e){return new Promise((t,r)=>{let s=new URL(n),i=_w.request({hostname:s.hostname,port:s.port,path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"text/plain","Content-Length":Buffer.byteLength(e)}},o=>{let a="";o.setEncoding("utf8"),o.on("data",c=>{a+=c}),o.on("end",()=>t({status:o.statusCode??0,text:a}))});i.setTimeout(0),i.on("error",r),i.end(e)})}var q_=n=>{let e=Math.round((Date.now()-n)/6e4);return e<1?"moments ago":e<60?`${e}m ago`:`${Math.round(e/60)}h ago`};async function Rw(n,e,t=0){e==="-"&&(e=Is(await ar()));let r=e!==void 0&&e.startsWith("tb:");r&&t<=0&&(t=Rd);let s=e!==void 0&&/^tb:(click|set)( |$)/.test(e),i=Ea.resolve(n),o=Rn(await Q(),i)[0];if(!o){let p=(await ms(process.cwd()))(i);console.error(p?`No running server for '${n}' \u2014 it last ran ${q_(p)}. Relaunching reuses the same URL (a stale tab is one reload from live): npx typebulb ${n}`:`No running server for '${n}'. Start it first: npx typebulb ${n}`),process.exit(1)}let a=async p=>{let m=[p>0?`reply=${p}`:"",s?"solo=1":""].filter(Boolean).join("&"),h=await U_(`${o.url}/__send${m?`?${m}`:""}`,e??"");(h.status<200||h.status>=300)&&(console.error(`send failed: HTTP ${h.status} from ${o.url}/__send`),process.exit(1));try{return JSON.parse(h.text)}catch{return{}}},c={};try{let p=Date.now()+t;do{if(c=await a(t>0?Math.max(p-Date.now(),1e3):0),(c.clients??0)>0||Date.now()>=p)break;await new Promise(m=>setTimeout(m,150))}while(!0)}catch(p){console.error(`send failed: ${p instanceof Error?p.message:String(p)}`),process.exit(1)}let l=c.clients??0,f=`${l} page${l===1?"":"s"}`;if(c.refused&&(console.error(`Actuation needs exactly one connected page; ${f} are open on ${o.url} \u2014 close the extras and retry.`),process.exit(1)),l===0){let p=c.droppedMsAgo,m=p!==void 0?` \u2014 a page disconnected ${Math.round(p/1e3)}s ago and hasn't reconnected; reload it, or open ${o.url}`:` \u2014 no page has ever connected; share ${o.url} and arm: typebulb wait ${n} --match "[page] connected"`;t>0?console.error(`No page connected after ${t/1e3}s${m}`):console.error(`Sent, but no page is connected${m}`),r&&process.exit(1);return}console.error(`Sent to ${f}.`);let u=c.results??[],d=c.errors??[];for(let p of d)console.error(`handler error: ${p}`);if(d.length&&process.exit(1),u.length>1&&(console.error(`${u.length} replies from ${f} \u2014 one reply owns stdout: at most one tb.onMessage handler, in one page, may return a value.`),process.exit(1)),u.length===1){if(e!==void 0&&/^tb:png( |$)/.test(e)){let m={};try{m=JSON.parse(u[0])}catch{}typeof m.png!="string"&&(console.error("tb:png replied with an unexpected shape \u2014 an older runtime? (`typebulb logs` lists server versions)"),process.exit(1));let h=Hm(i);await j_(Ea.dirname(h),{recursive:!0}),await F_(h,Buffer.from(m.png,"base64"));let y=[m.via?`inside "${m.via}"`:"",m.backdrop?`backdrop ${m.backdrop}`:""].filter(Boolean);console.error(`canvas ${m.width}\xD7${m.height} \u2192 PNG${y.length?` (${y.join("; ")})`:""}`),console.log(h);return}let p;try{p=JSON.parse(u[0])}catch{p=void 0}console.log(typeof p=="string"?p:u[0])}else c.timedOut&&(r&&(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 slow work needs a larger --wait=ms; a reply that NEVER comes is a done-promise that missed an exit)`))}Wo();Hu();Z();import*as Iw from"fs/promises";async function Nw(n,e){let t=await Iw.readFile(n,"utf-8"),r=mn(t),s=ce[e].path,i=r.files.get(s);i||(console.error(i===void 0?`No **${s}** block in ${n}`:`The **${s}** block in ${n} is empty`),process.exit(2)),process.stdout.write(i.endsWith(`
2260
+ `).trimEnd()}function U_(n,e){return new Promise((t,r)=>{let s=new URL(n),i=_w.request({hostname:s.hostname,port:s.port,path:s.pathname+s.search,method:"POST",headers:{"Content-Type":"text/plain","Content-Length":Buffer.byteLength(e)}},o=>{let a="";o.setEncoding("utf8"),o.on("data",c=>{a+=c}),o.on("end",()=>t({status:o.statusCode??0,text:a}))});i.setTimeout(0),i.on("error",r),i.end(e)})}var q_=n=>{let e=Math.round((Date.now()-n)/6e4);return e<1?"moments ago":e<60?`${e}m ago`:`${Math.round(e/60)}h ago`};async function Rw(n,e,t=0){e==="-"&&(e=Is(await ar()));let r=e!==void 0&&e.startsWith("tb:");r&&t<=0&&(t=Rd);let s=e!==void 0&&/^tb:(click|set)( |$)/.test(e),i=Ea.resolve(n),o=Rn(await Q(),i)[0];if(!o){let p=(await ms(process.cwd()))(i);console.error(p?`No running server for '${n}' \u2014 it last ran ${q_(p)}. Relaunching reuses the same URL (a stale tab is one reload from live): npx typebulb ${n}`:`No running server for '${n}'. Start it first: npx typebulb ${n}`),process.exit(1)}let a=async p=>{let m=[p>0?`reply=${p}`:"",s?"solo=1":""].filter(Boolean).join("&"),h=await U_(`${o.url}/__send${m?`?${m}`:""}`,e??"");(h.status<200||h.status>=300)&&(console.error(`send failed: HTTP ${h.status} from ${o.url}/__send`),process.exit(1));try{return JSON.parse(h.text)}catch{return{}}},c={};try{let p=Date.now()+t;do{if(c=await a(t>0?Math.max(p-Date.now(),1e3):0),(c.clients??0)>0||Date.now()>=p)break;await new Promise(m=>setTimeout(m,150))}while(!0)}catch(p){console.error(`send failed: ${p instanceof Error?p.message:String(p)}`),process.exit(1)}let l=c.clients??0,f=`${l} page${l===1?"":"s"}`;if(c.refused&&(console.error(`Actuation needs exactly one connected page; ${f} are open on ${o.url} \u2014 close the extras and retry.`),process.exit(1)),l===0){let p=c.droppedMsAgo,m=p!==void 0?` \u2014 a page disconnected ${Math.round(p/1e3)}s ago and hasn't reconnected; reload it, or open ${o.url}`:` \u2014 no page has ever connected; share ${o.url} and arm: typebulb wait ${n} --match "[page] connected"`;t>0?console.error(`No page connected after ${t/1e3}s${m}`):console.error(`Sent, but no page is connected${m}`),r&&process.exit(1);return}console.error(`Sent to ${f}.`);let u=c.results??[],d=c.errors??[];for(let p of d)console.error(`handler error: ${p}`);if(d.length&&process.exit(1),u.length>1&&(console.error(`${u.length} replies from ${f} \u2014 one reply owns stdout: at most one tb.onMessage handler, in one page, may return a value.`),process.exit(1)),u.length===1){if(e!==void 0&&/^tb:png( |$)/.test(e)){let m={};try{m=JSON.parse(u[0])}catch{}typeof m.png!="string"&&(console.error("tb:png replied with an unexpected shape \u2014 an older runtime? (`typebulb logs` lists server versions)"),process.exit(1));let h=Hm(i);await j_(Ea.dirname(h),{recursive:!0}),await F_(h,Buffer.from(m.png,"base64"));let y=[m.via?`inside "${m.via}"`:"",m.backdrop?`backdrop ${m.backdrop}`:""].filter(Boolean);console.error(`canvas ${m.width}\xD7${m.height} \u2192 PNG${y.length?` (${y.join("; ")})`:""}`),console.log(h);return}let p;try{p=JSON.parse(u[0])}catch{p=void 0}console.log(typeof p=="string"?p:u[0])}else c.timedOut&&(r&&(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 slow work needs a larger --wait=ms; a reply that NEVER comes is a done-promise that missed an exit, or a blocked main thread: tb:snapshot runs no page code, so its silence too means blocked)`))}Wo();Hu();Z();import*as Iw from"fs/promises";async function Nw(n,e){let t=await Iw.readFile(n,"utf-8"),r=mn(t),s=ce[e].path,i=r.files.get(s);i||(console.error(i===void 0?`No **${s}** block in ${n}`:`The **${s}** block in ${n} is empty`),process.exit(2)),process.stdout.write(i.endsWith(`
2260
2261
  `)?i:i+`
2261
2262
  `)}Z();import*as Ns from"fs/promises";async function Mw(n,e){let t=await Ns.readFile(n,"utf-8"),r=[];for(let{kind:i,source:o}of e){let a;try{a=o==="-"?await ar():await Ns.readFile(o,"utf-8")}catch(c){Lw(`Cannot read ${i}'s source: ${c instanceof Error?c.message:String(c)}`)}r.push({kind:i,content:Is(a),label:o==="-"?"stdin":o})}let s;try{s=J_(t,r)}catch(i){Lw(`${n}: ${i instanceof Error?i.message:String(i)}`)}for(let i of s.upToDate)console.log(`${ce[i].path}: already up to date`);if(s.written.length){await Ns.writeFile(n,s.text);for(let i of s.written)console.log(i.action==="removed"?`${ce[i.kind].path}: removed (${i.label} is empty)`:`${ce[i.kind].path}: ${i.action} from ${i.label} (${i.chars.toLocaleString()} chars)`)}}function J_(n,e){let t=mn(n),r=n,s=[],i=[];for(let{kind:o,content:a,label:c}of e){let l=ce[o].path,f=t.files.get(l);if(!a){if(f===void 0){i.push(o);continue}r=$w(bf(r,o),r,l),s.push({kind:o,action:"removed",chars:0,label:c});continue}if(f!==void 0&&Is(f)===a){i.push(o);continue}r=$w(lr(r,o,a),r,l),s.push({kind:o,action:f===void 0?"created":"replaced",chars:a.length,label:c})}return{text:r,written:s,upToDate:i}}function $w(n,e,t){if(n===e)throw new Error(`the **${t}** block's fence is unterminated; refusing to rewrite inside it`);return n}function Lw(n){console.error(n),process.exit(1)}it();ze();Z();Fo();import*as Ft from"fs/promises";import*as Ra from"path";import{EventEmitter as qw}from"events";import oR from"open";nn();Z();import{Hono as z_}from"hono";import{serve as G_}from"@hono/node-server";import{streamSSE as X_}from"hono/streaming";import*as Hd from"fs/promises";Mn();ls();Ln();import*as Jd from"fs/promises";import*as $s from"path";var Aa=class{async get(e){let t=De(e),r=$s.join(cs,t+".bin"),s=$s.join(cs,t+".json");try{let[i,o]=await Promise.all([Jd.readFile(r),Jd.readFile(s,"utf8")]),a=JSON.parse(o);return{body:i,contentType:a.contentType,cacheControl:a.cacheControl}}catch{return}}async set(e,t){await ee();let r=De(e),s=$s.join(cs,r+".bin"),i=$s.join(cs,r+".json"),o={url:e,contentType:t.contentType,cacheControl:t.cacheControl};await Promise.all([Ae(s,t.body),Ae(i,JSON.stringify(o))])}};var Bw=`
2262
2263
  const CSS = '\\n' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typebulb",
3
- "version": "0.55.3",
3
+ "version": "0.55.5",
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
  "keywords": [
6
6
  "bulb",