@burtson-labs/bandit-stealth-cli 1.7.337 → 1.7.338
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/cli.js +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1354,7 +1354,7 @@ When *describing* tool calls in prose (in synopsis or explanations), use words:
|
|
|
1354
1354
|
|
|
1355
1355
|
When the goal is complete, return a 2-6 line synopsis. No preamble. If the goal is ambiguous, make ONE reasonable interpretation and state it.`;function bLn(r){let i=new J2t.ToolRegistry;for(let m of r.parentRegistry.getAll())m.name!=="task"&&i.register(m);let s=r.maxIterations??6,u=r.onEvent??(()=>{}),l=t(async(m,A,w,P)=>{let F=0,$=0,H,Q=yLn(r.subagentLoopOptions),ce=new J2t.ToolUseLoop(i,r.ctx,{...Q,maxIterations:s,beforeToolExecute:r.beforeToolExecute,isSubagent:!0,emitEvent:t((lt,Et)=>{if(lt==="tool_loop:llm_start"){let Rt=Et?.iteration;typeof Rt=="number"&&Number.isFinite(Rt)&&(F=Math.max(F,Rt+1))}if(lt==="tool_loop:tool_execute"){$+=1;let Rt=Et?.name;typeof Rt=="string"&&(H=Rt)}w?.({iterations:F,toolCalls:$,lastTool:H});let St=P!==void 0&&Et&&typeof Et=="object"?{...Et,taskId:P}:Et;u(`subagent:${lt}`,St)},"emitEvent")}),oe=typeof r.parentSystemPrompt=="function"?r.parentSystemPrompt():r.parentSystemPrompt,ge=oe&&oe.trim().length>0?oe:ALn,$e=["","","## Subagent Scope","You are operating as a SUBAGENT \u2014 a focused sub-process spawned by the parent agent to accomplish a single bounded goal.","",`Your goal: ${m}`,A?`
|
|
1356
1356
|
Context: ${A}`:"","","Subagent rules:",`- Stay strictly on the goal. No adjacent work, refactors, or "while I'm here" cleanups.`,"- When the goal is complete, return a 2-6 line synopsis. No preamble.","- You CANNOT spawn further subagents (the `task` tool is not in your registry).","- If the goal is ambiguous, make ONE reasonable interpretation and state it in your synopsis.","- If you cannot reach the goal (tool errors, missing files, etc.), return what you learned and why you stopped."].filter((lt,Et,St)=>!(lt===""&&St[Et-1]==="")).join(`
|
|
1357
|
-
`),Xe=`${ge}${$e}`;return u("subagent:task:spawn",{taskId:P,goal:m,systemPromptChars:Xe.length,inheritedFromParent:!!(oe&&oe.trim().length>0),nativeTools:!!Q.nativeTools,registryToolCount:i.getAll().length}),ce.run(m,r.chat,Xe)},"runSubagent");return{name:"task",description:`Spawn a focused subagent to investigate a specific question or complete a bounded task. Do NOT use this for first-pass repo overviews like "what is this project" or "tell me about this repo" \u2014 answer those with direct list/read/search calls first. Use task for explicit exhaustive audits or a narrow branch of work whose intermediate details are not worth surfacing in the main conversation. The subagent returns a concise synopsis; its intermediate tool calls are hidden from you. Does NOT support nested task spawning. Pass run_in_background="true" for long-running or parallel investigations \u2014 the tool returns a task id immediately and the subagent's synopsis is delivered to you on a later turn so you can keep working with the user in the meantime.`,parameters:[{name:"goal",description:'The specific question or task for the subagent. Be concrete \u2014 "find all call sites of foo() and list their files" beats "look at foo usage".',required:!0},{name:"context",description:"Optional: one or two sentences of background the subagent needs that is not obvious from the goal alone.",required:!1},{name:"run_in_background",description:`Optional. When "true", spawn the subagent in the background and return immediately with a task id. The subagent's synopsis is auto-injected into a later turn when it completes, so you can keep responding to the user while it runs. Use this for investigations that would otherwise take 30+ seconds and don't block the user's next question. Default: false (synchronous, parent waits).`,required:!1}],async execute(m,A){let w=m.goal?.trim();if(!w)return{output:"Error: goal parameter is required.",isError:!0};let P=m.context?.trim(),F=String(m.run_in_background??"").toLowerCase()==="true";if(F&&r.backgroundStore){let $=r.backgroundStore,H=r.maxConcurrentBackground??vLn;if(H>0){let ce=$.listByStatus("running");if(ce.length>=H){u("task:cap-hit",{goal:w,cap:H,runningCount:ce.length,runningIds:ce.map(ge=>ge.id)});let oe=ce.map(ge=>ge.id).join(", ");return{output:`Background subagent limit reached (${ce.length} / ${H} already running). Pick one: (a) wait for a running task to complete and call task(run_in_background="true") again, (b) call check_task on one of [${oe}] to block on a specific task, or (c) re-issue this task without run_in_background to run it inline now.`,isError:!1}}}let Q=$.start(w);return u("task:start",{goal:w,maxIterations:s,background:!0,taskId:Q}),(async()=>{try{let ce=await l(w,P,Xe=>{$.progress(Q,Xe)},Q),oe=q2t(ce.finalResponse);if(!oe){let Xe=ce.iterations===0?"Subagent stalled in reasoning without emitting a tool call or final answer (0 iterations). The model thought through the goal but never committed to an action.":`Subagent finished in ${ce.iterations} iteration(s) but returned no synopsis.${ce.hitLimit?" (Hit iteration limit.)":""}`;$.fail(Q,Xe),u("task:error",{goal:w,taskId:Q,error:Xe});return}let ge=ce.hitLimit?`
|
|
1357
|
+
`),Xe=`${ge}${$e}`;return u("subagent:task:spawn",{taskId:P,goal:m,systemPromptChars:Xe.length,inheritedFromParent:!!(oe&&oe.trim().length>0),nativeTools:!!Q.nativeTools,registryToolCount:i.getAll().length}),ce.run(m,r.chat,Xe,{signal:r.getParentSignal?.()})},"runSubagent");return{name:"task",description:`Spawn a focused subagent to investigate a specific question or complete a bounded task. Do NOT use this for first-pass repo overviews like "what is this project" or "tell me about this repo" \u2014 answer those with direct list/read/search calls first. Use task for explicit exhaustive audits or a narrow branch of work whose intermediate details are not worth surfacing in the main conversation. The subagent returns a concise synopsis; its intermediate tool calls are hidden from you. Does NOT support nested task spawning. Pass run_in_background="true" for long-running or parallel investigations \u2014 the tool returns a task id immediately and the subagent's synopsis is delivered to you on a later turn so you can keep working with the user in the meantime.`,parameters:[{name:"goal",description:'The specific question or task for the subagent. Be concrete \u2014 "find all call sites of foo() and list their files" beats "look at foo usage".',required:!0},{name:"context",description:"Optional: one or two sentences of background the subagent needs that is not obvious from the goal alone.",required:!1},{name:"run_in_background",description:`Optional. When "true", spawn the subagent in the background and return immediately with a task id. The subagent's synopsis is auto-injected into a later turn when it completes, so you can keep responding to the user while it runs. Use this for investigations that would otherwise take 30+ seconds and don't block the user's next question. Default: false (synchronous, parent waits).`,required:!1}],async execute(m,A){let w=m.goal?.trim();if(!w)return{output:"Error: goal parameter is required.",isError:!0};let P=m.context?.trim(),F=String(m.run_in_background??"").toLowerCase()==="true";if(F&&r.backgroundStore){let $=r.backgroundStore,H=r.maxConcurrentBackground??vLn;if(H>0){let ce=$.listByStatus("running");if(ce.length>=H){u("task:cap-hit",{goal:w,cap:H,runningCount:ce.length,runningIds:ce.map(ge=>ge.id)});let oe=ce.map(ge=>ge.id).join(", ");return{output:`Background subagent limit reached (${ce.length} / ${H} already running). Pick one: (a) wait for a running task to complete and call task(run_in_background="true") again, (b) call check_task on one of [${oe}] to block on a specific task, or (c) re-issue this task without run_in_background to run it inline now.`,isError:!1}}}let Q=$.start(w);return u("task:start",{goal:w,maxIterations:s,background:!0,taskId:Q}),(async()=>{try{let ce=await l(w,P,Xe=>{$.progress(Q,Xe)},Q);if(ce.cancelled){$.cancel(Q),u("task:cancel",{goal:w,taskId:Q,iterations:ce.iterations});return}let oe=q2t(ce.finalResponse);if(!oe){let Xe=ce.iterations===0?"Subagent stalled in reasoning without emitting a tool call or final answer (0 iterations). The model thought through the goal but never committed to an action.":`Subagent finished in ${ce.iterations} iteration(s) but returned no synopsis.${ce.hitLimit?" (Hit iteration limit.)":""}`;$.fail(Q,Xe),u("task:error",{goal:w,taskId:Q,error:Xe});return}let ge=ce.hitLimit?`
|
|
1358
1358
|
|
|
1359
1359
|
[Note: subagent hit ${s}-iteration limit, synopsis may be incomplete.]`:"";$.complete(Q,`=== SUBAGENT REPORT \u2014 this is the answer to your delegation ===
|
|
1360
1360
|
|
|
@@ -1777,7 +1777,7 @@ ${(()=>{let H=`Bandit insights \u2014 ${new Date(i).toISOString().slice(0,10)}`,
|
|
|
1777
1777
|
<h1>You're signed in.</h1>
|
|
1778
1778
|
<p>Bandit picked up your session. You can close this tab and return to your terminal.</p>
|
|
1779
1779
|
</div>
|
|
1780
|
-
</body></html>`;t(e9n,"startLoopbackListener");t(t9n,"openBrowser");t(n9n,"buildDefaultDeviceLabel");t(r9n,"runOAuthSignIn")});var rbe=jt((Ulr,i9n)=>{i9n.exports={name:"@burtson-labs/bandit-stealth-cli",version:"1.7.
|
|
1780
|
+
</body></html>`;t(e9n,"startLoopbackListener");t(t9n,"openBrowser");t(n9n,"buildDefaultDeviceLabel");t(r9n,"runOAuthSignIn")});var rbe=jt((Ulr,i9n)=>{i9n.exports={name:"@burtson-labs/bandit-stealth-cli",version:"1.7.338",description:"Bandit \u2014 a local-first AI coding agent for your terminal. Same runtime as the Bandit Stealth VS Code / Cursor extension.",keywords:["ai","agent","cli","coding-agent","llm","ollama","local-first","bandit","burtson-labs","terminal","repl","developer-tools"],homepage:"https://burtson.ai",bugs:{url:"https://github.com/Burtson-Labs/bandit-agent-framework/issues",email:"team@burtson.ai"},license:"Apache-2.0",author:{name:"Burtson Labs",email:"team@burtson.ai",url:"https://burtson.ai"},repository:{type:"git",url:"git+https://github.com/Burtson-Labs/bandit-agent-framework.git",directory:"apps/bandit-cli"},type:"module",bin:{bandit:"./dist/cli.js"},main:"dist/cli.js",files:["dist/cli.js","README.md","LICENSE"],engines:{node:">=20"},publishConfig:{access:"public"},scripts:{test:"vitest run",typecheck:"tsc -p tsconfig.json --noEmit",build:"node build.mjs","build:publish":"node build.mjs --publish",dev:"node build.mjs --watch",start:"node dist/cli.js",smoke:"node build.mjs && node dist/__smoke__/smoke.js",integration:"node build.mjs && node dist/__integration__/ollama.js",eval:"node build.mjs && node dist/__eval__/eval.js",benchmark:"node build.mjs && node dist/__eval__/benchmark.js","gen-logo":"node scripts/gen-logo.mjs","preview-banner":"node scripts/preview-banner.mjs",clean:"rm -rf dist",prepack:"node scripts/prepack.mjs",postpack:"node scripts/postpack.mjs",prepublishOnly:"pnpm run clean && pnpm run typecheck && pnpm run build:publish"},dependencies:{"pdf-parse":"^2.4.5"},devDependencies:{"@burtson-labs/agent-core":"workspace:*","@burtson-labs/host-kit":"workspace:*","@burtson-labs/stealth-core-runtime":"workspace:*","@types/node":"^20.11.0","@types/pdf-parse":"^1.1.5","@types/pngjs":"^6.0.5","@types/react":"^19.2.2",esbuild:"^0.28.0",ink:"^7.0.4","ink-text-input":"^6.0.0",pngjs:"^7.0.0",react:"^19.2.0",typescript:"^5.4.0",vitest:"^4.0.10"}}});var z$e={};Rre(z$e,{resolveEditor:()=>Q$e,spawnEditorOnFile:()=>g9n});import{spawnSync as _9n,spawn as m9n}from"child_process";import*as Hxt from"path";function Q$e(r=process.env){let i=(r.VISUAL??"").trim();if(i.length>0){let{cmd:u,args:l}=Jxt(i);return{label:`$VISUAL (${u})`,cmd:u,args:l}}let s=(r.EDITOR??"").trim();if(s.length>0){let{cmd:u,args:l}=Jxt(s);return{label:`$EDITOR (${u})`,cmd:u,args:l}}return r.TERM_PROGRAM==="vscode"&&qxt("code",r)?{label:"code --wait (VS Code tab)",cmd:"code",args:["--wait"]}:process.platform==="win32"?{label:"notepad",cmd:"notepad.exe",args:[]}:qxt("nano",r)?{label:"nano",cmd:"nano",args:[]}:null}async function g9n(r,i){let s=Hxt.resolve(i);return new Promise(u=>{let l=m9n(r.cmd,[...r.args,s],{stdio:"inherit",shell:!1});l.on("exit",(m,A)=>{u({exitCode:typeof m=="number"?m:A?130:1})}),l.on("error",()=>u({exitCode:1}))})}function Jxt(r){let i=r.split(/\s+/).filter(Boolean);return{cmd:i[0]??"",args:i.slice(1)}}function qxt(r,i){let s=process.platform==="win32"?"where":"which";return _9n(s,[r],{stdio:"ignore",env:i}).status===0}var abe=E8(()=>{"use strict";t(Q$e,"resolveEditor");t(g9n,"spawnEditorOnFile");t(Jxt,"splitEditorEnv");t(qxt,"commandExists")});var Wxt={};Rre(Wxt,{PLAN_FILE:()=>Gxt,STAGING_DIR:()=>AK,loadPlan:()=>Vxt,runWizard:()=>h9n});import*as $J from"fs";import*as GR from"path";async function Vxt(r){let i=GR.join(r,AK,Gxt),s;try{s=await $J.promises.readFile(i,"utf-8")}catch{return null}try{let u=JSON.parse(s);return u.version!==1||!Array.isArray(u.entries)||u.entries.length===0?null:u}catch{return null}}async function h9n(r){let i=await Vxt(r.cwd);if(!i)return process.stdout.write(X.red("No migration plan found. ")+X.dim(`Run ${X.cyan("/memory migrate")} first to generate one, then ${X.cyan("/memory migrate apply")} to launch this wizard.
|
|
1781
1781
|
`)),{applied:0,skipped:0,edited:0,quit:!0,originalBackup:""};let s=Q$e();if(!s)return process.stdout.write(X.red("No editor available. ")+X.dim("Set $EDITOR (e.g. ")+X.cyan("EDITOR=code")+X.dim(") or ")+X.cyan("EDITOR=nano")+X.dim(" and rerun ")+X.cyan("/memory migrate apply")+X.dim(". ")+X.dim("You can also edit the files under ")+X.cyan(AK)+X.dim(` directly with any editor before running apply \u2014 the wizard reads them as-is.
|
|
1782
1782
|
`)),{applied:0,skipped:0,edited:0,quit:!0,originalBackup:""};let u="\u2550".repeat(60);process.stdout.write(`
|
|
1783
1783
|
`+X.accent(u)+`
|
|
@@ -2199,7 +2199,7 @@ Is Ollama running? Try: ${X.cyan("ollama serve")}`}}let m=l.map(P=>P.name);if(m.
|
|
|
2199
2199
|
`));else if(ud.choice==="always")$.grant(wa,xr),await(0,Va.persistAllowEntry)(u,xr?`${wa}:${xr}`:wa).catch(()=>{}),await oe?.append({type:"permission-decision",name:wa,primary:(0,Va.previewText)(xr),displayPrimary:(0,Va.previewText)(Xo),choice:"always"}),process.stdout.write(X.green(` ${Nc.check} saved allow rule for ${wa}${xr?`:${xr}`:""}
|
|
2200
2200
|
`));else if(ud.choice==="deny"){let di=f2t(ud,wa,xr);return await oe?.append({type:"permission-denied",name:wa,primary:(0,Va.previewText)(xr),displayPrimary:(0,Va.previewText)(Xo),source:"user",reason:(0,Va.previewText)(di),notes:ud.notes?(0,Va.previewText)(ud.notes):void 0}),process.stdout.write(X.yellow(` ${Nc.warn} denied ${wa}; Bandit will revise the plan
|
|
2201
2201
|
`)),{allow:!1,reason:di}}else await oe?.append({type:"permission-decision",name:wa,primary:(0,Va.previewText)(xr),displayPrimary:(0,Va.previewText)(Xo),choice:"once"}),process.stdout.write(X.green(` ${Nc.check} allowed once
|
|
2202
|
-
`))}finally{el()}}return{allow:!0}},"beforeToolExecute");r.backgroundStore&&(Rt.register((0,Va.buildCheckTaskTool)(r.backgroundStore)),Rt.register((0,Va.buildListTasksTool)(r.backgroundStore)));let Vc={current:void 0};Rt.register((0,Va.buildTaskTool)({chat:mo,parentRegistry:Rt,ctx:zt,backgroundStore:r.backgroundStore,beforeToolExecute:Ca,parentSystemPrompt:t(()=>Vc.current,"parentSystemPrompt"),subagentLoopOptions:t(()=>({nativeTools:rr,nativeToolFailureFallback:Sn,messageTokenBudget:Wr,maxParallelTools:Ai,outputBudgetTokens:yr}),"subagentLoopOptions"),onEvent:t((wa,Ur)=>{if(wa==="task:start"){let xr=Ur;g1.stop(),process.stdout.write(X.magenta(` ${Nc.spark} subagent: `)+X.dim(xr.goal)+`
|
|
2202
|
+
`))}finally{el()}}return{allow:!0}},"beforeToolExecute");r.backgroundStore&&(Rt.register((0,Va.buildCheckTaskTool)(r.backgroundStore)),Rt.register((0,Va.buildListTasksTool)(r.backgroundStore)));let Vc={current:void 0};Rt.register((0,Va.buildTaskTool)({chat:mo,parentRegistry:Rt,ctx:zt,backgroundStore:r.backgroundStore,beforeToolExecute:Ca,parentSystemPrompt:t(()=>Vc.current,"parentSystemPrompt"),getParentSignal:t(()=>r.signal,"getParentSignal"),subagentLoopOptions:t(()=>({nativeTools:rr,nativeToolFailureFallback:Sn,messageTokenBudget:Wr,maxParallelTools:Ai,outputBudgetTokens:yr}),"subagentLoopOptions"),onEvent:t((wa,Ur)=>{if(wa==="task:start"){let xr=Ur;g1.stop(),process.stdout.write(X.magenta(` ${Nc.spark} subagent: `)+X.dim(xr.goal)+`
|
|
2203
2203
|
`)}else if(wa==="subagent:task:spawn"){let xr=Ur;process.stdout.write(X.dim(` \u21B3 spawn: prompt=${xr?.systemPromptChars??"?"}c inherited=${xr?.inheritedFromParent??"?"} nativeTools=${xr?.nativeTools??"?"} tools=${xr?.registryToolCount??"?"}
|
|
2204
2204
|
`)),oe?.append({type:"subagent-spawn",taskId:xr?.taskId,systemPromptChars:xr?.systemPromptChars,inheritedFromParent:xr?.inheritedFromParent,nativeTools:xr?.nativeTools,registryToolCount:xr?.registryToolCount})}else if(wa==="task:done"){let xr=Ur;process.stdout.write(X.dim(` ${Nc.check} subagent done (${xr.iterations} iter${xr.hitLimit?", hit limit":""})
|
|
2205
2205
|
`))}else if(wa==="subagent:tool_loop:tool_execute"){let xr=Ur,Xo=xr?.name??"",Hu=xr?.params?.path??xr?.params?.pattern??xr?.params?.cmd??xr?.params?.url??xr?.params?.query??"";process.stdout.write(X.dim(` \u21B3 ${Xo}${Hu?" "+Hu:""}
|
package/package.json
CHANGED