typebulb 0.21.3 → 0.21.4

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.
@@ -2217,7 +2217,7 @@ var Patcher = class _Patcher {
2217
2217
 
2218
2218
  // cli/agents/pi/server/piPatcherExtension.ts
2219
2219
  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.";
2220
- var BUILD_TAG = true ? "matchu-patchu-pi 0.2.0, built 2026-07-08 10:08:31" : "matchu-patchu-pi dev";
2220
+ var BUILD_TAG = true ? "matchu-patchu-pi 0.2.0, built 2026-07-08 16:28:04" : "matchu-patchu-pi dev";
2221
2221
  var errorBlocks = (errors) => {
2222
2222
  const parts = [`Patch failed with ${errors.length} error(s):`];
2223
2223
  for (const e of errors) parts.push("", e.toString());
@@ -2289,36 +2289,51 @@ function logErr(...a) {
2289
2289
  } catch {
2290
2290
  }
2291
2291
  }
2292
+ function patchOwnership(tools, registeredByUs) {
2293
+ const patch = tools.find((t) => t.name === "patch");
2294
+ if (!patch) return "absent";
2295
+ return registeredByUs || /matchu-patchu/i.test(patch.sourceInfo?.path ?? "") ? "ours" : "foreign";
2296
+ }
2297
+ var PATCH_TOOL = {
2298
+ name: "patch",
2299
+ label: "Patch",
2300
+ description: DESCRIPTION,
2301
+ promptSnippet: "Modify one or more existing files by applying a unified diff",
2302
+ promptGuidelines: [
2303
+ "Use patch for every edit to an existing file; write is only for creating new files or full rewrites.",
2304
+ "patch accepts lenient unified diffs: line numbers are optional and hunks anchor by context lines. One diff may target several files via ---/+++ headers; pass filePath instead for a headerless single-file diff."
2305
+ ],
2306
+ parameters: Type.Object({
2307
+ diff: Type.String({ description: "Unified diff content to apply" }),
2308
+ filePath: Type.Optional(Type.String({
2309
+ description: "Path of the single file to patch (absolute or relative to the project root); the diff's headers are then ignored. Omit to target the file(s) named by the diff's ---/+++ headers."
2310
+ })),
2311
+ dryRun: Type.Optional(Type.Boolean({ description: "If true, return the patched content without writing to disk" }))
2312
+ }),
2313
+ async execute(_id, params, _signal, _onUpdate, ctx) {
2314
+ const { ok, message } = applyPatch(ctx.cwd, params);
2315
+ if (!ok) throw new Error(message);
2316
+ return { content: [{ type: "text", text: message }], details: {} };
2317
+ }
2318
+ };
2292
2319
  function piPatcherExtension_default(pi) {
2320
+ let registeredPatch = false;
2293
2321
  try {
2294
- pi.registerTool({
2295
- name: "patch",
2296
- label: "Patch",
2297
- description: DESCRIPTION,
2298
- promptSnippet: "Modify one or more existing files by applying a unified diff",
2299
- promptGuidelines: [
2300
- "Use patch for every edit to an existing file; write is only for creating new files or full rewrites.",
2301
- "patch accepts lenient unified diffs: line numbers are optional and hunks anchor by context lines. One diff may target several files via ---/+++ headers; pass filePath instead for a headerless single-file diff."
2302
- ],
2303
- parameters: Type.Object({
2304
- diff: Type.String({ description: "Unified diff content to apply" }),
2305
- filePath: Type.Optional(Type.String({
2306
- description: "Path of the single file to patch (absolute or relative to the project root); the diff's headers are then ignored. Omit to target the file(s) named by the diff's ---/+++ headers."
2307
- })),
2308
- dryRun: Type.Optional(Type.Boolean({ description: "If true, return the patched content without writing to disk" }))
2309
- }),
2310
- async execute(_id, params, _signal, _onUpdate, ctx) {
2311
- const { ok, message } = applyPatch(ctx.cwd, params);
2312
- if (!ok) throw new Error(message);
2313
- return { content: [{ type: "text", text: message }], details: {} };
2314
- }
2315
- });
2316
2322
  pi.on("session_start", () => {
2317
2323
  try {
2324
+ const owner = patchOwnership(pi.getAllTools(), registeredPatch);
2325
+ if (owner === "foreign") {
2326
+ logErr('another extension already provides "patch" \u2014 typebulb patcher standing down (built-in edit kept)');
2327
+ return;
2328
+ }
2329
+ if (owner === "absent") {
2330
+ pi.registerTool(PATCH_TOOL);
2331
+ registeredPatch = true;
2332
+ }
2318
2333
  const active = pi.getActiveTools();
2319
2334
  if (active.includes("edit")) pi.setActiveTools(active.filter((n) => n !== "edit"));
2320
2335
  } catch (e) {
2321
- logErr("remove edit", e);
2336
+ logErr("session_start", e);
2322
2337
  }
2323
2338
  });
2324
2339
  } catch (e) {
@@ -2328,5 +2343,6 @@ function piPatcherExtension_default(pi) {
2328
2343
  export {
2329
2344
  applyPatch,
2330
2345
  piPatcherExtension_default as default,
2331
- discoverDiffKeys
2346
+ discoverDiffKeys,
2347
+ patchOwnership
2332
2348
  };
package/dist/index.js CHANGED
@@ -1421,5 +1421,5 @@ Shutting down...`);try{a.shutdownSwitcher?.()}catch{}try{a.shutdownComposer?.()}
1421
1421
  `),Ot({target:r,onChange:async()=>{try{console.log("Re-running..."),await a()}catch(c){console.error("Error:",c)}}}))}import{Console as zE}from"node:console";Me();async function Ih(r,e,t,n,s){tA();try{let p=cr(await K(),r)[0];p&&(hi(p.pid,ve(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=xe(t),{bulb:o,config:a}=await he(r);o.server||Tn("This bulb has no **server.ts** block; nothing to call."),st(i,r,o.server);let c;try{c=await un(o.server,s,n,a.dependencies)}catch(p){Tn(p instanceof Error?p.message:String(p))}let l=Ci(c,e.fn);if(!l){let p=[...Object.keys(c).filter(g=>typeof c[g]=="function"),...Object.keys(qc)];Tn(`Function '${e.fn}' not found. Available: ${p.length?p.join(", "):"(none)"}.`)}let d=await QE(e);if(Ni(l)){try{for await(let p of l(...d))await Nh(JSON.stringify(p,Lh)+`
1422
1422
  `)}catch(p){Tn(p instanceof Error?p.stack??p.message:String(p))}return Ch(0)}let u;try{u=await l(...d)}catch(p){Tn(p instanceof Error?p.stack??p.message:String(p))}let f=eA(u);f!==void 0&&await Nh(f+`
1423
1423
  `),Ch(0)}function Ch(r){process.exitCode=r,setTimeout(()=>process.exit(r),2e3).unref?.()}async function QE(r){if(r.hasArgsFlag){let e=r.argsJson??"";return e==="-"&&(e=await rA()),ZE(e)}return XE(r.positional)}function XE(r){return r.map(e=>{try{return JSON.parse(e)}catch{return e}})}function ZE(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 eA(r){if(r!==void 0)return JSON.stringify(r,Lh,2)}function Lh(r,e){return typeof e=="bigint"?e.toString():e}function Tn(r){process.stderr.write(r+`
1424
- `),process.exit(1)}function tA(){let r=new zE(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 Nh(r){return new Promise((e,t)=>{process.stdout.write(r,n=>n?t(n):e())})}async function rA(){let r=[];for await(let e of process.stdin)r.push(e);return Buffer.concat(r).toString("utf-8")}var nl="0.21.3";function $h(r,e){r||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
1424
+ `),process.exit(1)}function tA(){let r=new zE(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 Nh(r){return new Promise((e,t)=>{process.stdout.write(r,n=>n?t(n):e())})}async function rA(){let r=[];for await(let e of process.stdin)r.push(e);return Buffer.concat(r).toString("utf-8")}var nl="0.21.4";function $h(r,e){r||(console.error(`This bulb runs server-side Node code (server.ts), which --trust must authorize:
1425
1425
  ${e}`),process.exit(1))}async function nA(){let r=gl(process.argv.slice(2));if(r.version&&(console.log(`typebulb ${nl}`),process.exit(0)),r.help&&(yl(),process.exit(0)),bm(),r.subcommand==="logs"){await Om(r.file||void 0,{follow:r.follow,clear:r.clear,run:r.run,lines:r.lines});return}if(r.subcommand==="wait"){await Rm(r.file||void 0,{match:r.match,timeoutSec:r.timeoutSec});return}if(r.subcommand==="stop"){r.stopScope?await Cm(r.stopScope):await _m(r.file||void 0);return}if(r.subcommand==="send"){await Im(r.file,r.sendMessage,r.sendWaitMs??0);return}if(r.subcommand==="skill"){await Am(nl);return}if(r.subcommand==="models"){await xm(r.mode);return}if(r.subcommand==="agent"){await(r.agentTarget?Oh(r):km(nl));return}if(r.subcommand==="trust"||r.subcommand==="untrust"){await Rp(r.file||void 0,r.subcommand==="trust");return}let e;if(!r.file||r.file==="."){let l=await gp(process.cwd());l||(console.error("No .bulb.md file found in current directory"),process.exit(1)),e=l}else e=je.resolve(r.file);await Mh.access(e).then(()=>!0,()=>!1)||(ir().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));let n=r.file&&r.file!=="."?r.file:je.relative(process.cwd(),e)||je.basename(e),s=`npx typebulb --trust ${n.includes(" ")?`"${n}"`:n}`;if(r.subcommand==="predict"){await Op(e,s);return}let i=!r.noTrust&&St(e);i&&!r.trust&&console.log("trust: granted from memory (run `typebulb untrust` to revoke)"),r.trust=r.noTrust?!1:r.trust||i;let o;try{o=await he(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 ml(r.local)}catch(l){console.error(l instanceof Error?l.message:String(l)),process.exit(1)}console.log(`replace: ${a.name} \u2192 ${je.relative(process.cwd(),a.dir)||"."}`)}if(r.subcommand==="check"){await Pp(e,a);return}let c=je.dirname(e);if(r.subcommand==="call"){$h(r.trust,s),await Ih(e,{fn:r.fn,positional:r.callArgs,argsJson:r.argsJson,hasArgsFlag:r.hasArgsFlag},r.mode,a,c);return}if(o&&o.bulb.server&&(Ps(o.bulb)||r.server)){$h(r.trust,s),await _h(e,r.watch,r.mode,a,c);return}await jm(e,r,s,a,c)}nA().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.21.3",
3
+ "version": "0.21.4",
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": {