typebulb 0.21.3 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/claude/client.js +100 -100
- package/dist/agents/claude/styles.css +28 -0
- package/dist/agents/claude/typebulb-inv.png +0 -0
- package/dist/agents/claude/typebulb.png +0 -0
- package/dist/agents/pi/client.js +99 -99
- package/dist/agents/pi/matchu-patchu.ts +41 -25
- package/dist/agents/pi/styles.css +28 -0
- package/dist/agents/pi/typebulb-inv.png +0 -0
- package/dist/agents/pi/typebulb.png +0 -0
- package/dist/index.js +2 -2
- package/package.json +1 -1
|
@@ -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
|
|
2220
|
+
var BUILD_TAG = true ? "matchu-patchu-pi 0.2.0, built 2026-07-08 17:41:19" : "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("
|
|
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
|
};
|
|
@@ -856,6 +856,34 @@ a.server-port:hover { text-decoration: underline; }
|
|
|
856
856
|
width: 100%;
|
|
857
857
|
margin: 0 auto;
|
|
858
858
|
}
|
|
859
|
+
/* Top-of-transcript wordmark + tagline (messageList.ts #masthead). Centred on the prose column,
|
|
860
|
+
scrolls with the conversation. Both logos render; theme picks which shows. */
|
|
861
|
+
.masthead {
|
|
862
|
+
max-width: var(--content-max);
|
|
863
|
+
width: 100%;
|
|
864
|
+
margin: 0 auto 1rem auto;
|
|
865
|
+
padding: .35rem 0 .35rem;
|
|
866
|
+
display: flex;
|
|
867
|
+
flex-direction: column;
|
|
868
|
+
align-items: flex-start;
|
|
869
|
+
gap: .5rem;
|
|
870
|
+
text-align: left;
|
|
871
|
+
user-select: none;
|
|
872
|
+
}
|
|
873
|
+
.masthead-logo {
|
|
874
|
+
width: 170px;
|
|
875
|
+
max-width: 55%;
|
|
876
|
+
height: auto;
|
|
877
|
+
opacity: .92;
|
|
878
|
+
}
|
|
879
|
+
.masthead-tagline {
|
|
880
|
+
color: var(--muted);
|
|
881
|
+
font-size: .85rem;
|
|
882
|
+
}
|
|
883
|
+
/* Black wordmark on light, outline on dark. */
|
|
884
|
+
.masthead-logo.dark { display: none; }
|
|
885
|
+
html[data-theme="dark"] .masthead-logo.light { display: none; }
|
|
886
|
+
html[data-theme="dark"] .masthead-logo.dark { display: block; }
|
|
859
887
|
.bubble {
|
|
860
888
|
position: relative;
|
|
861
889
|
max-width: var(--content-max);
|
|
Binary file
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -1415,11 +1415,11 @@ ${w0}
|
|
|
1415
1415
|
</html>`}var GE={claude:()=>Promise.resolve().then(()=>(kh(),Sh)),pi:()=>Promise.resolve().then(()=>(Ah(),Eh))};async function Oh(r){let e=process.cwd(),t=r.agentTarget;vp(t)||(console.error(`Unknown agent '${t}'. Known: ${ir().join(", ")}.`),process.exit(1));let n=await vc(e,t);if(n){console.log(`Mirror '${t}' is already running for this project:
|
|
1416
1416
|
${n.url}`),r.open&&await Ph(n.url);return}let s=gi(process.pid),i=r.watch?new YE:void 0,o=xe(r.mode),a=await GE[t](),c=a.displayName||`${t} mirror`;st(o,Z.join(e,"mirror"));let l=Z.dirname(VE(import.meta.url)),d=Z.join(l,"agents",t),u=Z.join(l,"..","cli","agents"),f=Z.join(d,"styles.css"),p=Z.join(d,"index.html"),g=()=>Fm({name:c,agent:t,styles:Th(f,"utf8"),mountHtml:Th(p,"utf8"),watch:r.watch}),m=await Sn(r.port),y=await Ii({getHtml:g,basePath:e,port:m,reloadEmitter:i,getServerExports:()=>a,trusted:!0,staticAssets:{mount:`${Z.posix.dirname(Wc(t))}/`,dir:d}}),x=`http://localhost:${m}`;await yi({pid:process.pid,port:m,url:x,file:`agent:${t}`,cwd:e,startedAt:Date.now(),trust:!0,agent:t}),console.log(`
|
|
1417
1417
|
${c}`),console.log(` ${x}`),m!==r.port&&console.log(` (port ${r.port} was busy)`),r.watch&&console.log(` Watching for changes...
|
|
1418
|
-
`);let A=Z.join(u,t,"client"),h=Z.join(u,"core","client");async function w(){await(await import("esbuild")).build({entryPoints:[Z.join(A,"index.ts")],bundle:!0,platform:"browser",format:"esm",outfile:Z.join(d,"client.js")});for(let T of["styles.css","index.html"])WE(Z.join(h,T),Z.join(d,T))}let v;if(r.watch&&i){let O=HE(A),T=!1;v=Ot({target:O?u:d,events:"all",onChange:async()=>{if(!T){T=!0;try{O&&await w(),console.log(`Mirror rebuilt. Browser reloading...
|
|
1418
|
+
`);let A=Z.join(u,t,"client"),h=Z.join(u,"core","client");async function w(){await(await import("esbuild")).build({entryPoints:[Z.join(A,"index.ts")],bundle:!0,platform:"browser",format:"esm",outfile:Z.join(d,"client.js")});for(let T of["styles.css","index.html","typebulb.png","typebulb-inv.png"])WE(Z.join(h,T),Z.join(d,T))}let v;if(r.watch&&i){let O=HE(A),T=!1;v=Ot({target:O?u:d,events:"all",onChange:async()=>{if(!T){T=!0;try{O&&await w(),console.log(`Mirror rebuilt. Browser reloading...
|
|
1419
1419
|
`),i.emit("reload")}catch(I){console.error("Mirror rebuild failed:",I instanceof Error?I.message:I)}finally{T=!1}}}})}r.open&&await Ph(x);let k=async()=>{console.log(`
|
|
1420
1420
|
Shutting down...`);try{a.shutdownSwitcher?.()}catch{}try{a.shutdownComposer?.()}catch{}y.close(),v?.(),s(),await kt(process.pid),process.exit(0)};process.on("SIGINT",k),process.on("SIGTERM",k)}import*as Rh from"path";async function _h(r,e,t,n,s){let i=xe(t),o=!1,a=async()=>{let{bulb:c,config:l}=await he(r);o||(st(i,r,c.server),o=!0),await un(c.server,s,n,l.dependencies)};console.log(`Running ${Rh.basename(r)}...`),await a(),e&&(console.log(`Watching for changes...
|
|
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.
|
|
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.22.0";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