@burtson-labs/bandit-stealth-cli 1.7.86 → 1.7.87
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 +2 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -74,7 +74,7 @@ ${m}
|
|
|
74
74
|
`).filter(oe=>oe.length>0).length;return`<tool_result name="${S}">[earlier run, ${ee} lines elided \u2014 summary: ${V}]</tool_result>`}t(wxt,"summarizeToolResult");function Ext(p,m={}){let S=m.tokenBudget??xxt,T=m.keepRecentToolResults??Txt,k=m.charsPerToken??kxt,j=p.reduce((ye,Y)=>ye+x1e(Y.content,k),0);if(j<=S)return{compacted:p,beforeTokens:j,afterTokens:j,messagesCompacted:0};let V=[];for(let ye=0;ye<p.length;ye++)nJe(p[ye])&&V.push(ye);let ee=new Set(V.slice(-T)),oe=[],de=0;for(let ye=0;ye<p.length;ye++){let Y=p[ye];nJe(Y)&&!ee.has(ye)?(oe.push({role:Y.role,content:wxt(Y.content)}),de++):oe.push(Y)}let _e=oe.reduce((ye,Y)=>ye+x1e(Y.content,k),0);if(_e>S){let ye=new Set,Y=oe.findIndex(Je=>Je.role==="user");oe.forEach((Je,qe)=>{Je.role==="system"&&ye.add(qe)});let rt=Y+1;for(;_e>S&&rt<oe.length-2;){if(ye.has(rt)){rt++;continue}let Je=x1e(oe[rt].content,k);oe.splice(rt,1),_e-=Je,de++}}return{compacted:oe,beforeTokens:j,afterTokens:_e,messagesCompacted:de}}t(Ext,"compactToolMessages")});var rJe=hi(YB=>{"use strict";Object.defineProperty(YB,"__esModule",{value:!0});YB.ToolUseLoop=void 0;YB.createToolUseLoop=Dxt;var ex=S1e(),Pxt=k1e(),XY=class{static{t(this,"ToolUseLoop")}constructor(m,S,T={}){this.registry=m,this.ctx=S,this.maxIterations=T.maxIterations??10,this.defaultEmit=T.emitEvent??(()=>{}),this.defaultBeforeToolExecute=T.beforeToolExecute??(()=>({allow:!0}))}async run(m,S,T,k){return this.runWithMessages([{role:"user",content:m}],S,T,k)}async runWithMessages(m,S,T,k){let j=k?.emitEvent??this.defaultEmit,V=k?.maxIterations??this.maxIterations,ee=k?.beforeToolExecute??this.defaultBeforeToolExecute,oe=k?.signal,de=Math.max(1,k?.maxParallelTools??8),_e=Math.max(1,k?.maxTotalTools??60),ye=0,Y=t((No,Lo,Oo="")=>({finalResponse:Oo||"[cancelled]",iterations:Lo,messages:No,hitLimit:!1,cancelled:!0}),"buildCancelledResult"),rt=k?.nativeTools??!1,Je=rt?"":this.registry.buildSystemPromptBlock(),qe=T?Je?`${T}
|
|
75
75
|
|
|
76
76
|
${Je}`:T:Je,un=rt?this.registry.buildNativeToolsSchema():void 0,Wt=[];qe&&Wt.push({role:"system",content:qe});let Ut="";for(let No of m)No.role==="user"&&typeof No.content=="string"&&No.content.trim()&&(Ut=No.content);let Rn=!1;for(let No of m)No.role!=="system"&&Wt.push(No);let Jt=0,_n=!1,At=0,Xt=0,Cr=0,Ln=2,ci=2,Hn=[],hs=2,ms=!1,Jn=[],oa=3,ca=0,hn=3,Ao=!1,Ms=-1,Qs=0,Nr=!1,Ro=3,Ks=2,Hs=!1;{let No=m.filter(Lo=>Lo.role==="user").map(Lo=>Lo.content).join(`
|
|
77
|
-
`).toLowerCase();Hs=/\b(update|edit|change|fix|modify|refactor|rewrite|replace|add)\b/.test(No)||/[\w\-./]+\.(?:ts|tsx|js|jsx|py|rb|go|rs|java|kt|cs|swift|php|cpp|c|h|md|json|ya?ml|html|css)\b/.test(No)}let Ji=0,ei=!1,Cc=!1,Uu=!1,sl=[/in (?:my|a|the) previous response/i,/already provided (?:the|an?) (?:implementation|refactored|improved|updated)/i,/you can find (?:the |this )?(?:refactored|improved|updated) (?:code|implementation)/i,/here (?:is|'s) the (?:refactored|improved|updated|revised) (?:code|implementation|file)/i,/(?:i have|i've) (?:refactored|rewritten|updated|improved)/i,/(?:refactored|updated) (?:the )?(?:code|implementation) above/i,/i'll finalize the task here/i,/i've also marked (?:the tasks|these steps) as complet/i,/i apologi[sz]e for the (?:malformed|invalid)/i,/(?:ensure|escape) (?:all )?(?:quotes|newlines|characters).*(?:properly )?escap/i,/in my next tool call/i,/let me know (?:which|what) (?:task|action) (?:i should |to )?resume/i,/please (?:let me know|tell me).*(?:specific action|which task|what.*like me to)/i,/here (?:is|'s) the (?:final|resulting|updated|modified) (?:state|version|content|output) of/i,/(?:comments?|changes?|edits?|annotations?|updates?) (?:have )?been (?:added|made|applied|written|included)/i,/you can verify (?:these|the|your) (?:changes?|edits?|updates?)/i,/check(?:ing)? the files? (?:directly )?in your editor/i,/running (?:a )?build to (?:see|verify|check)/i];for(;;){if(oe?.aborted)return j("tool_loop:cancelled",{iteration:Jt,stage:"pre_iteration"}),Y(Wt,Jt);Jt>=V&&(_n=!0,Wt.push({role:"user",content:"You have reached the tool use limit. Please give your best final answer based on what you have gathered so far."})),ye>=_e&&!_n&&(_n=!0,j("tool_loop:total_tool_cap",{iteration:Jt,totalToolsExecuted:ye}),Wt.push({role:"user",content:`You have executed ${ye} tool calls this turn \u2014 the per-turn cap (${_e}) has been reached. Please give your best final answer based on what you have gathered so far.`}));let No=k?.messageTokenBudget;if(No!==void 0&&No>0&&Number.isFinite(No)){let $s=(0,Pxt.compactToolMessages)(Wt,{tokenBudget:No});$s.messagesCompacted>0&&(j("tool_loop:compacted",{iteration:Jt,messagesCompacted:$s.messagesCompacted,beforeTokens:$s.beforeTokens,afterTokens:$s.afterTokens}),Wt.length=0,Wt.push(...$s.compacted))}Ut&&!Rn&&Jt>=3&&!_n&&Wt.reduce((Dn,Jc)=>Dn+(Jc.content?.length??0),0)>8e3&&(Rn=!0,j("tool_loop:goal_anchor",{iteration:Jt,goalPreview:Ut.slice(0,120)}),Wt.push({role:"user",content:`Reminder of the original request: "${Ut.trim()}". Answer THAT question directly using what you have gathered. Do not pivot to a related-but-different topic that happens to be salient in the recent tool results.`})),j("tool_loop:llm_start",{iteration:Jt,messageCount:Wt.length});let Lo=await this.streamAndAggregate(S,Wt,j,Jt,un,oe);if(j("tool_loop:llm_response",{iteration:Jt,response:Lo.slice(0,200)}),oe?.aborted)return j("tool_loop:cancelled",{iteration:Jt,stage:"post_stream"}),Y(Wt,Jt,Lo);if(!_n&&/<tool_result\b[\s\S]*?<\/tool_result\s*>|<tool_result\b[^<]*$/i.test(Lo)&&Cr<ci){Cr++,j("tool_loop:fake_tool_result_detected",{iteration:Jt,preview:Lo.slice(0,200)});let $s=Lo.replace(/<tool_result\b[\s\S]*?<\/tool_result\s*>/gi,"").replace(/<tool_result\b[^<]*$/i,"").trim();Wt.push({role:"assistant",content:$s}),Wt.push({role:"user",content:'You emitted a `<tool_result>` envelope in your response. Those envelopes are SYSTEM output \u2014 they appear BETWEEN your turns, never inside your own message. If you meant to invoke a tool, emit a single `<tool_call>{"name":"...","params":{...}}</tool_call>` and wait for the real result. If the task is complete, give a plain-prose final answer with no XML envelopes. Retry now.'});continue}Wt.push({role:"assistant",content:Lo});let mt=Lo.replace(/<think\b[\s\S]*?<\/think\s*>/gi,"").replace(/<think\b[\s\S]*$/i,"").replace(/```bandit-reasoning\b[\s\S]*?```/gi,"").replace(/```bandit-reasoning\b[\s\S]*$/i,"").trim(),wn=!mt&&Lo.trim().length>0,zn=/\b(use|call|invoke|execute|run|search|look|read|check|find|list)\b[^.\n]*\.?\s*$/i,Ya=/\b(we (?:will|need to|should)|i'?ll|i will|let me|let'?s|going to|i'?m going to|i need to)\b/i,fs=/```[a-zA-Z0-9_-]*\s*\n/.test(mt),lo=!(0,ex.hasToolCalls)(Lo)&&!fs&&mt.length>0&&mt.length<240&&Ya.test(mt)&&zn.test(mt);if((!Lo.trim()&&Jt>0||wn||lo)&&!_n&&At<2){At++,j("tool_loop:empty_retry",{iteration:Jt,attempt:At,reasoningOnly:wn,narratedButNoAction:lo});let $s=lo?'You announced your next step in prose ("we will search\u2026" / "let me check\u2026" / "use X to find Y") but did NOT emit a `<tool_call>` envelope. Announcing intent is not enough \u2014 you must actually invoke the tool. Emit the call now in this exact format: `<tool_call>{"name":"<tool>","params":{...}}</tool_call>` \u2014 no commentary, no markdown fence around it. Or, if the task is already answerable from what you know, give a final answer instead.':wn?"You completed reasoning but emitted no tool_call and no final answer. Pick the next concrete action: invoke a tool to make progress, OR write a final answer using what you have. Do not stop after only thinking.":"Your previous response was empty. Please either invoke another tool to continue the task OR produce a final answer using what you've gathered so far. Do not respond with an empty message.";Wt.push({role:"user",content:$s});continue}if(At=0,!_n&&(0,ex.looksLikeAttemptedToolCall)(Lo)&&!(0,ex.hasToolCalls)(Lo)&&Xt<Ln){Xt++,j("tool_loop:parse_retry",{iteration:Jt,attempt:Xt});let $s=Xt===1;Wt.push({role:"user",content:$s?'Your previous tool_call was not valid JSON \u2014 I could not parse it. Common cause: unescaped `"` characters inside a string value (for example `["", "", ""]` inside a `content` string). Retry the tool call with properly escaped JSON: every `"` inside a string value must be written as `\\"`, and every newline as `\\n`. If the content is very long, consider shortening it or breaking the change into smaller edits.':"Your tool_call still did not parse. Do NOT retry with the same shape. Switch tactics: (a) call `write_file` instead \u2014 one `path` + one `content` string, much simpler to escape \u2014 OR (b) split the change into multiple small `apply_edit` calls that each target just one method or block (e.g. 3-5 lines of `find`, 5-10 lines of `replace`) instead of rewriting the whole class. Pick the smallest scope that accomplishes the next step. If you cannot produce a valid tool call, respond with a plain-prose final answer acknowledging you could not complete the edit."});continue}if(!_n&&!(0,ex.hasToolCalls)(Lo)){let $s=Lo.toLowerCase().replace(/\s+/g," ").trim(),Dn=Hn[Hn.length-1],Jc=!!Dn&&(()=>{let g0=Dn.length<$s.length?Dn:$s,Nu=Dn.length<$s.length?$s:Dn,Vv=0;for(;Vv<g0.length&&g0[Vv]===Nu[Vv];)Vv++;return Vv/g0.length>.6})(),qc=($s.match(/wait,? i see/g)??[]).length,Mr=($s.match(/actually,? i'?ll/g)??[]).length,Hc=qc>=3&&Mr>=3,ol=Lo.includes("[stream aborted: self-contradicting prose loop detected]");if(!ms&&(Jc||Hc||ol)){ms=!0,j("tool_loop:prose_loop_nudge",{iteration:Jt,responsePreview:Lo.slice(0,200),reason:ol?"stream_abort":Hc?"self_contradict":"cross_iteration_similarity"}),Wt.push({role:"user",content:'STOP deliberating. Your last response either repeated itself, contradicted itself (e.g. "Wait, I see X / Actually I\'ll try X"), or was aborted mid-stream as a loop. Do NOT continue speculating about what files might exist. Take exactly one of these actions now: (a) invoke a tool (`list_files`, `read_file`, `search_code`, etc.) to answer the question with real data, OR (b) give up and tell the user plainly that you could not complete the task and why. Do not write more than two sentences of prose before either calling a tool or terminating.'}),Hn.length=0;continue}Hn.push($s),Hn.length>hs&&Hn.shift()}else Hn.length=0;if(!_n&&!(0,ex.hasToolCalls)(Lo)&&!Cc){let $s=/```json\s*\n([\s\S]*?)```/i,Dn=Lo.match($s);if(Dn)try{let Jc=JSON.parse(Dn[1].trim());if(Array.isArray(Jc)&&Jc.length>0&&Jc.every(qc=>qc&&typeof qc=="object"&&typeof qc.content=="string")){Cc=!0,j("tool_loop:json_todo_auto_promoted",{iteration:Jt,itemCount:Jc.length});let qc=this.registry.get("todo_write");if(qc){let Mr={name:"todo_write",params:{items:JSON.stringify(Jc)},raw:`<tool_call>{"name":"todo_write","params":{"items":${JSON.stringify(JSON.stringify(Jc))}}}</tool_call>`};j("tool_loop:tool_execute",{name:"todo_write",params:Mr.params,rawSnippet:Mr.raw.slice(0,400)});try{let Hc=await qc.execute(Mr.params,this.ctx);j("tool_loop:tool_result",{name:"todo_write",isError:Hc.isError,outputLength:Hc.output.length,outputSnippet:Hc.output.slice(0,280),outputFull:Hc.output.slice(0,65536)}),Wt.push({role:"user",content:(0,ex.buildToolResultsMessage)([{name:"todo_write",output:Hc.output,isError:Hc.isError}])})}catch(Hc){let ol=Hc instanceof Error?Hc.message:String(Hc);j("tool_loop:tool_error",{name:"todo_write",error:ol}),Wt.push({role:"user",content:(0,ex.buildToolResultsMessage)([{name:"todo_write",output:`Error: ${ol}`,isError:!0}])})}Wt.push({role:"user",content:'Note: I detected a JSON todo list in your response and auto-promoted it to a todo_write call. Next time, emit `<tool_call>{"name":"todo_write","params":{"items":"..."}}</tool_call>` directly instead of pasting JSON as a code block \u2014 pasted JSON does not update your plan, only the tool call does.'}),Jt++;continue}}}catch{}}if(_n||!(0,ex.hasToolCalls)(Lo)){let $s=(0,ex.stripToolCallMarkup)(Lo).trim();if(!_n&&!Uu&&Ji===0&&sl.some(Jc=>Jc.test($s))){Uu=!0,j("tool_loop:false_completion_nudge",{iteration:Jt,responsePreview:$s.slice(0,200)}),Wt.push({role:"user",content:'Your response either claims work is done OR apologizes and asks what to do next \u2014 but I see NO successful `write_file` or `apply_edit` tool call in this turn, so nothing on disk has changed. Do NOT ask the user which task to resume, do NOT promise to escape JSON "in your next tool call", and do NOT defer. Either (a) emit the `write_file` or `apply_edit` tool call NOW with the actual change \u2014 if the content is long, keep the payload as a single properly-escaped string (use `\\n` for every newline, `\\"` for every internal quote), or (b) respond honestly that you could not complete the task and briefly explain why. Retry the tool call yourself; the user cannot help you escape JSON.'});continue}if(!_n&&!Uu&&Ji>0){let Dn=/[`"']?([\w./\\-]+\.(?:cs|ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|java|kt|swift|cpp|cc|c|h|hpp|md|json|ya?ml|html|css|scss|sql|toml|sh|bash))[`"']?/gi,Jc=new Set,qc;for(;(qc=Dn.exec($s))!==null;){let Mr=qc[1].split(/[/\\]/),Hc=Mr[Mr.length-1].toLowerCase();Jc.add(Hc)}if(Jc.size>Ji){Uu=!0,j("tool_loop:partial_completion_nudge",{iteration:Jt,editToolsInvoked:Ji,claimedFiles:Jc.size,responsePreview:$s.slice(0,200)}),Wt.push({role:"user",content:`Your response describes edits to ${Jc.size} files (${[...Jc].slice(0,8).join(", ")}${Jc.size>8?", \u2026":""}), but only ${Ji} successful edit${Ji===1?"":"s"} actually fired this turn. The remaining ${Jc.size-Ji} file(s) were NOT modified \u2014 nothing landed on disk for them. Either (a) emit the missing \`apply_edit\` / \`write_file\` tool calls now to actually do the work, OR (b) revise your response to honestly describe ONLY the edits that successfully applied. Do not summarize work that did not happen.`});continue}}if(!_n&&!ei&&Ji===0&&Hs){let Dn=/```[a-zA-Z0-9_-]*\n([\s\S]*?)```/g,qc=0,Mr;for(;(Mr=Dn.exec($s))!==null;){let Hc=Mr[1].split(`
|
|
77
|
+
`).toLowerCase();Hs=/\b(update|edit|change|fix|modify|refactor|rewrite|replace|add)\b/.test(No)||/[\w\-./]+\.(?:ts|tsx|js|jsx|py|rb|go|rs|java|kt|cs|swift|php|cpp|c|h|md|json|ya?ml|html|css)\b/.test(No)}let Ji=0,ei=!1,Cc=!1,Uu=!1,sl=[/in (?:my|a|the) previous response/i,/already provided (?:the|an?) (?:implementation|refactored|improved|updated)/i,/you can find (?:the |this )?(?:refactored|improved|updated) (?:code|implementation)/i,/here (?:is|'s) the (?:refactored|improved|updated|revised) (?:code|implementation|file)/i,/(?:i have|i've) (?:refactored|rewritten|updated|improved)/i,/(?:refactored|updated) (?:the )?(?:code|implementation) above/i,/i'll finalize the task here/i,/i've also marked (?:the tasks|these steps) as complet/i,/i apologi[sz]e for the (?:malformed|invalid)/i,/(?:ensure|escape) (?:all )?(?:quotes|newlines|characters).*(?:properly )?escap/i,/in my next tool call/i,/let me know (?:which|what) (?:task|action) (?:i should |to )?resume/i,/please (?:let me know|tell me).*(?:specific action|which task|what.*like me to)/i,/here (?:is|'s) the (?:final|resulting|updated|modified) (?:state|version|content|output) of/i,/(?:comments?|changes?|edits?|annotations?|updates?) (?:have )?been (?:added|made|applied|written|included)/i,/you can verify (?:these|the|your) (?:changes?|edits?|updates?)/i,/check(?:ing)? the files? (?:directly )?in your editor/i,/running (?:a )?build to (?:see|verify|check)/i];for(;;){if(oe?.aborted)return j("tool_loop:cancelled",{iteration:Jt,stage:"pre_iteration"}),Y(Wt,Jt);Jt>=V&&(_n=!0,Wt.push({role:"user",content:"You have reached the tool use limit. Please give your best final answer based on what you have gathered so far."})),ye>=_e&&!_n&&(_n=!0,j("tool_loop:total_tool_cap",{iteration:Jt,totalToolsExecuted:ye}),Wt.push({role:"user",content:`You have executed ${ye} tool calls this turn \u2014 the per-turn cap (${_e}) has been reached. Please give your best final answer based on what you have gathered so far.`}));let No=k?.messageTokenBudget;if(No!==void 0&&No>0&&Number.isFinite(No)){let $s=(0,Pxt.compactToolMessages)(Wt,{tokenBudget:No});$s.messagesCompacted>0&&(j("tool_loop:compacted",{iteration:Jt,messagesCompacted:$s.messagesCompacted,beforeTokens:$s.beforeTokens,afterTokens:$s.afterTokens}),Wt.length=0,Wt.push(...$s.compacted))}Ut&&!Rn&&Jt>=3&&!_n&&Wt.reduce((Dn,Jc)=>Dn+(Jc.content?.length??0),0)>8e3&&(Rn=!0,j("tool_loop:goal_anchor",{iteration:Jt,goalPreview:Ut.slice(0,120)}),Wt.push({role:"user",content:`Reminder of the original request: "${Ut.trim()}". Answer THAT question directly using what you have gathered. Do not pivot to a related-but-different topic that happens to be salient in the recent tool results.`})),j("tool_loop:llm_start",{iteration:Jt,messageCount:Wt.length});let Lo=await this.streamAndAggregate(S,Wt,j,Jt,un,oe);if(j("tool_loop:llm_response",{iteration:Jt,response:Lo.slice(0,200)}),oe?.aborted)return j("tool_loop:cancelled",{iteration:Jt,stage:"post_stream"}),Y(Wt,Jt,Lo);if(!_n&&/<tool_result\b[\s\S]*?<\/tool_result\s*>|<tool_result\b[^<]*$/i.test(Lo)&&Cr<ci){Cr++,j("tool_loop:fake_tool_result_detected",{iteration:Jt,preview:Lo.slice(0,200)});let $s=Lo.replace(/<tool_result\b[\s\S]*?<\/tool_result\s*>/gi,"").replace(/<tool_result\b[^<]*$/i,"").trim();Wt.push({role:"assistant",content:$s}),Wt.push({role:"user",content:'You emitted a `<tool_result>` envelope in your response. Those envelopes are SYSTEM output \u2014 they appear BETWEEN your turns, never inside your own message. If you meant to invoke a tool, emit a single `<tool_call>{"name":"...","params":{...}}</tool_call>` and wait for the real result. If the task is complete, give a plain-prose final answer with no XML envelopes. Retry now.'});continue}Wt.push({role:"assistant",content:Lo});let mt=Lo.replace(/<think\b[\s\S]*?<\/think\s*>/gi,"").replace(/<think\b[\s\S]*$/i,"").replace(/```bandit-reasoning\b[\s\S]*?```/gi,"").replace(/```bandit-reasoning\b[\s\S]*$/i,"").trim(),wn=!mt&&Lo.trim().length>0,zn=/\b(use|call|invoke|execute|run|search|look|read|check|find|list)\b[^.\n]*\.?\s*$/i,Ya=/\b(we (?:will|need to|should)|we'?ll|we'?re going to|i'?ll|i will|let me|let'?s|going to|i'?m going to|i need to)\b/i,fs=/```[a-zA-Z0-9_-]*\s*\n/.test(mt),lo=!(0,ex.hasToolCalls)(Lo)&&!fs&&mt.length>0&&mt.length<240&&Ya.test(mt)&&zn.test(mt);if((!Lo.trim()&&Jt>0||wn||lo)&&!_n&&At<2){At++,j("tool_loop:empty_retry",{iteration:Jt,attempt:At,reasoningOnly:wn,narratedButNoAction:lo});let $s=lo?'You announced your next step in prose ("we will search\u2026" / "let me check\u2026" / "use X to find Y") but did NOT emit a `<tool_call>` envelope. Announcing intent is not enough \u2014 you must actually invoke the tool. Emit the call now in this exact format: `<tool_call>{"name":"<tool>","params":{...}}</tool_call>` \u2014 no commentary, no markdown fence around it. Or, if the task is already answerable from what you know, give a final answer instead.':wn?"You completed reasoning but emitted no tool_call and no final answer. Pick the next concrete action: invoke a tool to make progress, OR write a final answer using what you have. Do not stop after only thinking.":"Your previous response was empty. Please either invoke another tool to continue the task OR produce a final answer using what you've gathered so far. Do not respond with an empty message.";Wt.push({role:"user",content:$s});continue}if(At=0,!_n&&(0,ex.looksLikeAttemptedToolCall)(Lo)&&!(0,ex.hasToolCalls)(Lo)&&Xt<Ln){Xt++,j("tool_loop:parse_retry",{iteration:Jt,attempt:Xt});let $s=Xt===1;Wt.push({role:"user",content:$s?'Your previous tool_call was not valid JSON \u2014 I could not parse it. Common cause: unescaped `"` characters inside a string value (for example `["", "", ""]` inside a `content` string). Retry the tool call with properly escaped JSON: every `"` inside a string value must be written as `\\"`, and every newline as `\\n`. If the content is very long, consider shortening it or breaking the change into smaller edits.':"Your tool_call still did not parse. Do NOT retry with the same shape. Switch tactics: (a) call `write_file` instead \u2014 one `path` + one `content` string, much simpler to escape \u2014 OR (b) split the change into multiple small `apply_edit` calls that each target just one method or block (e.g. 3-5 lines of `find`, 5-10 lines of `replace`) instead of rewriting the whole class. Pick the smallest scope that accomplishes the next step. If you cannot produce a valid tool call, respond with a plain-prose final answer acknowledging you could not complete the edit."});continue}if(!_n&&!(0,ex.hasToolCalls)(Lo)){let $s=Lo.toLowerCase().replace(/\s+/g," ").trim(),Dn=Hn[Hn.length-1],Jc=!!Dn&&(()=>{let g0=Dn.length<$s.length?Dn:$s,Nu=Dn.length<$s.length?$s:Dn,Vv=0;for(;Vv<g0.length&&g0[Vv]===Nu[Vv];)Vv++;return Vv/g0.length>.6})(),qc=($s.match(/wait,? i see/g)??[]).length,Mr=($s.match(/actually,? i'?ll/g)??[]).length,Hc=qc>=3&&Mr>=3,ol=Lo.includes("[stream aborted: self-contradicting prose loop detected]");if(!ms&&(Jc||Hc||ol)){ms=!0,j("tool_loop:prose_loop_nudge",{iteration:Jt,responsePreview:Lo.slice(0,200),reason:ol?"stream_abort":Hc?"self_contradict":"cross_iteration_similarity"}),Wt.push({role:"user",content:'STOP deliberating. Your last response either repeated itself, contradicted itself (e.g. "Wait, I see X / Actually I\'ll try X"), or was aborted mid-stream as a loop. Do NOT continue speculating about what files might exist. Take exactly one of these actions now: (a) invoke a tool (`list_files`, `read_file`, `search_code`, etc.) to answer the question with real data, OR (b) give up and tell the user plainly that you could not complete the task and why. Do not write more than two sentences of prose before either calling a tool or terminating.'}),Hn.length=0;continue}Hn.push($s),Hn.length>hs&&Hn.shift()}else Hn.length=0;if(!_n&&!(0,ex.hasToolCalls)(Lo)&&!Cc){let $s=/```json\s*\n([\s\S]*?)```/i,Dn=Lo.match($s);if(Dn)try{let Jc=JSON.parse(Dn[1].trim());if(Array.isArray(Jc)&&Jc.length>0&&Jc.every(qc=>qc&&typeof qc=="object"&&typeof qc.content=="string")){Cc=!0,j("tool_loop:json_todo_auto_promoted",{iteration:Jt,itemCount:Jc.length});let qc=this.registry.get("todo_write");if(qc){let Mr={name:"todo_write",params:{items:JSON.stringify(Jc)},raw:`<tool_call>{"name":"todo_write","params":{"items":${JSON.stringify(JSON.stringify(Jc))}}}</tool_call>`};j("tool_loop:tool_execute",{name:"todo_write",params:Mr.params,rawSnippet:Mr.raw.slice(0,400)});try{let Hc=await qc.execute(Mr.params,this.ctx);j("tool_loop:tool_result",{name:"todo_write",isError:Hc.isError,outputLength:Hc.output.length,outputSnippet:Hc.output.slice(0,280),outputFull:Hc.output.slice(0,65536)}),Wt.push({role:"user",content:(0,ex.buildToolResultsMessage)([{name:"todo_write",output:Hc.output,isError:Hc.isError}])})}catch(Hc){let ol=Hc instanceof Error?Hc.message:String(Hc);j("tool_loop:tool_error",{name:"todo_write",error:ol}),Wt.push({role:"user",content:(0,ex.buildToolResultsMessage)([{name:"todo_write",output:`Error: ${ol}`,isError:!0}])})}Wt.push({role:"user",content:'Note: I detected a JSON todo list in your response and auto-promoted it to a todo_write call. Next time, emit `<tool_call>{"name":"todo_write","params":{"items":"..."}}</tool_call>` directly instead of pasting JSON as a code block \u2014 pasted JSON does not update your plan, only the tool call does.'}),Jt++;continue}}}catch{}}if(_n||!(0,ex.hasToolCalls)(Lo)){let $s=(0,ex.stripToolCallMarkup)(Lo).trim();if(!_n&&!Uu&&Ji===0&&sl.some(Jc=>Jc.test($s))){Uu=!0,j("tool_loop:false_completion_nudge",{iteration:Jt,responsePreview:$s.slice(0,200)}),Wt.push({role:"user",content:'Your response either claims work is done OR apologizes and asks what to do next \u2014 but I see NO successful `write_file` or `apply_edit` tool call in this turn, so nothing on disk has changed. Do NOT ask the user which task to resume, do NOT promise to escape JSON "in your next tool call", and do NOT defer. Either (a) emit the `write_file` or `apply_edit` tool call NOW with the actual change \u2014 if the content is long, keep the payload as a single properly-escaped string (use `\\n` for every newline, `\\"` for every internal quote), or (b) respond honestly that you could not complete the task and briefly explain why. Retry the tool call yourself; the user cannot help you escape JSON.'});continue}if(!_n&&!Uu&&Ji>0){let Dn=/[`"']?([\w./\\-]+\.(?:cs|ts|tsx|js|jsx|mjs|cjs|py|rb|go|rs|java|kt|swift|cpp|cc|c|h|hpp|md|json|ya?ml|html|css|scss|sql|toml|sh|bash))[`"']?/gi,Jc=new Set,qc;for(;(qc=Dn.exec($s))!==null;){let Mr=qc[1].split(/[/\\]/),Hc=Mr[Mr.length-1].toLowerCase();Jc.add(Hc)}if(Jc.size>Ji){Uu=!0,j("tool_loop:partial_completion_nudge",{iteration:Jt,editToolsInvoked:Ji,claimedFiles:Jc.size,responsePreview:$s.slice(0,200)}),Wt.push({role:"user",content:`Your response describes edits to ${Jc.size} files (${[...Jc].slice(0,8).join(", ")}${Jc.size>8?", \u2026":""}), but only ${Ji} successful edit${Ji===1?"":"s"} actually fired this turn. The remaining ${Jc.size-Ji} file(s) were NOT modified \u2014 nothing landed on disk for them. Either (a) emit the missing \`apply_edit\` / \`write_file\` tool calls now to actually do the work, OR (b) revise your response to honestly describe ONLY the edits that successfully applied. Do not summarize work that did not happen.`});continue}}if(!_n&&!ei&&Ji===0&&Hs){let Dn=/```[a-zA-Z0-9_-]*\n([\s\S]*?)```/g,qc=0,Mr;for(;(Mr=Dn.exec($s))!==null;){let Hc=Mr[1].split(`
|
|
78
78
|
`).filter(ol=>ol.trim().length>0).length;Hc>qc&&(qc=Hc)}if(qc>=8){ei=!0,j("tool_loop:code_fence_nudge",{iteration:Jt,fenceLines:qc,responsePreview:$s.slice(0,200)}),Wt.push({role:"user",content:"You produced a substantial code block in your reply but never emitted a `write_file` or `apply_edit` tool call \u2014 so the change is NOT on disk. Do not ask the user to paste your code into a file themselves. Take exactly one of these actions now: (a) call `apply_edit` or `write_file` with the real change to the correct file, OR (b) say plainly that you could not locate the target file and explain what you searched for. Do not wrap up with another prose + code-fence response."});continue}}return{finalResponse:$s,iterations:Jt,messages:Wt,hitLimit:_n}}let ds=(0,ex.parseToolCalls)(Lo);j("tool_loop:tool_calls",{iteration:Jt,tools:ds.map($s=>$s.name)});let al=ds.length>0&&ds.every($s=>$s.name==="todo_write"),kl=ds.length>0&&!al;if(al?ca++:kl&&(ca=0,Ao=!1),al&&ca>=hn&&!Ao){Ao=!0,j("tool_loop:todo_churn_nudge",{iteration:Jt,consecutive:ca}),ds=[],Wt.push({role:"user",content:`You have revised the plan in ${ca+1} consecutive iterations without executing any step. Execute the first pending task now using a concrete tool \u2014 \`search_code\`, \`read_file\`, \`apply_edit\`, \`write_file\`, or \`run_command\`. Once a task is actually DONE (tool call succeeded), you may call \`todo_write\` again to mark it completed \u2014 but not to re-plan. If you cannot identify a next step, respond to the user with a short honest explanation and stop.`}),Jt++;continue}if(ds.length>1){let $s=new Set,Dn=[],Jc=0;for(let qc of ds){let Mr=`${qc.name}::${JSON.stringify(qc.params)}`;if($s.has(Mr)){Jc++;continue}$s.add(Mr),Dn.push(qc)}Jc>0&&j("tool_loop:tool_call_deduped",{iteration:Jt,removed:Jc,kept:Dn.length}),ds=Dn}let Fc=0;ds.length>de&&(Fc=ds.length-de,j("tool_loop:tool_call_capped",{iteration:Jt,requested:ds.length+0,kept:de,dropped:Fc}),ds=ds.slice(0,de));let Df=Math.max(0,_e-ye);ds.length>Df&&(j("tool_loop:tool_call_total_capped",{iteration:Jt,requested:ds.length,kept:Df,totalSoFar:ye,maxTotalTools:_e}),ds=ds.slice(0,Df)),ye+=ds.length;let Il=await Promise.all(ds.map(async $s=>{let Dn=$s.params.path??$s.params.file??$s.params.filepath,Jc=$s.name==="apply_edit"||$s.name==="write_file",qc;if(Dn&&Jc){let ol=`${$s.params.find??""}::${$s.params.replace??""}::${$s.params.content??""}`,g0=0;for(let Nu=0;Nu<ol.length;Nu++)g0=g0*31+ol.charCodeAt(Nu)|0;qc=`${$s.name}::${Dn}::${g0.toString(36)}`}else Dn?qc=`${$s.name}::${Dn}`:qc=`${$s.name}::${JSON.stringify($s.params).slice(0,160)}`;if(Jn.push(qc),Jn.length>oa&&Jn.shift(),Jn.length===oa&&Jn.every(ol=>ol===qc))return j("tool_loop:repeat_breaker",{name:$s.name,key:qc}),{name:$s.name,output:`Loop detected: ${$s.name} has been invoked ${oa} times in a row against the same target (${Dn??"identical params"}) without progress. This usually means the last write landed malformed \u2014 most often an unescaped \`"\` inside the JSON content string truncated the file. STOP retrying. Either (a) produce a final answer that explains the issue to the user, or (b) break the content into smaller edits. Do not call ${$s.name} with these params again.`,isError:!0};let Mr=this.registry.get($s.name);if(!Mr)return j("tool_loop:tool_not_found",{name:$s.name}),{name:$s.name,output:`Error: tool "${$s.name}" is not registered.`,isError:!0};($s.name==="write_file"||$s.name==="apply_edit")&&Ji++,j("tool_loop:tool_execute",{name:$s.name,params:$s.params,rawSnippet:$s.raw.slice(0,400)});let Hc=await ee({name:$s.name,params:$s.params});if(!Hc.allow){let ol=Hc.reason??"blocked by pre-execute guard";return j("tool_loop:tool_blocked",{name:$s.name,reason:ol}),{name:$s.name,output:`Blocked: ${ol}`,isError:!0}}try{let ol=await Mr.execute($s.params,this.ctx);return j("tool_loop:tool_result",{name:$s.name,isError:ol.isError,outputLength:ol.output.length,outputSnippet:ol.output.slice(0,280)}),{name:$s.name,output:ol.output,isError:ol.isError}}catch(ol){let g0=ol instanceof Error?ol.message:String(ol);return j("tool_loop:tool_error",{name:$s.name,error:g0}),{name:$s.name,output:`Error executing tool "${$s.name}": ${g0}`,isError:!0}}})),Fd=(0,ex.buildToolResultsMessage)(Il);if(Fc>0&&(Fd+=`
|
|
79
79
|
|
|
80
80
|
[Note: you emitted ${Fc+ds.length} tool calls in one iteration; only the first ${ds.length} were executed. Do not re-issue duplicates \u2014 instead, read the results above and pick a single most-promising next action.]`),Wt.push({role:"user",content:Fd}),!rt){for(let $s=0;$s<ds.length;$s++){let Dn=ds[$s],Jc=Il[$s];Dn.name==="todo_write"?(Ms=Jt,Qs=0):(Dn.name==="apply_edit"||Dn.name==="write_file")&&Jc&&!Jc.isError&&Qs++}!Nr&&Ms>=0&&Jt-Ms>=Ro&&Qs>=Ks&&(Nr=!0,j("tool_loop:todo_progress_nudge",{iteration:Jt,editsSinceLastTodo:Qs,iterationsSinceLastTodo:Jt-Ms}),Wt.push({role:"user",content:`You set up a plan with \`todo_write\` earlier but have since completed ${Qs} edit${Qs===1?"":"s"} without updating it. Call \`todo_write\` now with the current status \u2014 mark finished items as \`completed\` and leave remaining items as \`pending\`. The Plan block in the user's UI mirrors your last \`todo_write\`, so skipping this leaves them looking at a stale checklist while real work has landed.`}))}Jt++}}async streamAndAggregate(m,S,T,k,j,V){let ee="",Y=[],rt=800,Je=!1;for await(let qe of m(S,j)){if(V?.aborted){Je=!0,T("tool_loop:stream_abort",{iteration:k,reason:"cancelled",length:ee.length});break}if(ee+=qe,T("tool_loop:llm_chunk",{iteration:k,chunk:qe}),ee.length>=24e3){Je=!0,T("tool_loop:stream_abort",{iteration:k,reason:"hard_max",length:ee.length});break}if(ee.length>=rt){rt=ee.length+800;let Wt=ee.slice(Math.max(0,ee.length-400)).toLowerCase().replace(/\s+/g," ").replace(/\d+/g,"#").trim();if(Y.push(Wt),Y.length>3&&Y.shift(),Y.length===3&&Y.every(Ut=>Ut===Wt)){Je=!0,T("tool_loop:stream_abort",{iteration:k,reason:"intra_response_loop",length:ee.length,fingerprintPreview:Wt.slice(0,120)});break}}}return Je&&(ee=ee.replace(/\s+$/,"")+`
|
|
@@ -1044,7 +1044,7 @@ ${p.accomplishments.topFiles.length>0?`
|
|
|
1044
1044
|
`),T=m.split(`
|
|
1045
1045
|
`),k=S.length,j=T.length;if(k*j>4e4)return{plus:T.length,minus:S.length};let V=Array.from({length:k+1},()=>new Array(j+1).fill(0));for(let ye=1;ye<=k;ye++)for(let Y=1;Y<=j;Y++)V[ye][Y]=S[ye-1]===T[Y-1]?V[ye-1][Y-1]+1:Math.max(V[ye-1][Y],V[ye][Y-1]);let ee=k,oe=j,de=0,_e=0;for(;ee>0&&oe>0;)S[ee-1]===T[oe-1]?(ee--,oe--):V[ee][oe-1]>=V[ee-1][oe]?(de++,oe--):(_e++,ee--);return de+=oe,_e+=ee,{plus:de,minus:_e}}t(lIt,"lineCountDiff");function uIt(p){if(p.isNewFile)return"(new file)";let m=p.after.split(`
|
|
1046
1046
|
`),S=p.before.split(`
|
|
1047
|
-
`);for(let T=0;T<m.length;T++)if(m[T]!==S[T]){let k=(m[T]??"").trim();if(k)return k.length>80?k.slice(0,77)+"\u2026":k}return"(whitespace-only edit)"}t(uIt,"describeEdit");var i2e=class{static{t(this,"CheckpointStore")}constructor(m){this.counter=0,this.workspaceRoot=m.workspaceRoot,this.dir=n6.join(m.workspaceRoot,".bandit","checkpoints"),this.maxIndexEntries=m.maxIndexEntries??cIt}async create(m){await oE.promises.mkdir(n6.join(this.dir,m.turnId),{recursive:!0}),this.counter++;let S=`chk-${m.turnId.split("-").pop()??"x"}-${String(this.counter).padStart(3,"0")}`,T=n6.relative(this.workspaceRoot,m.absolutePath)||m.absolutePath,k=m.before.length===0,j={id:S,turnId:m.turnId,timestamp:Date.now(),tool:m.tool,path:m.absolutePath,relPath:T,before:m.before,after:m.after,isNewFile:k,iteration:m.iteration,description:uIt({before:m.before,after:m.after,isNewFile:k})},V=n6.join(this.dir,m.turnId,`${S}.json`);return await oE.promises.writeFile(V,JSON.stringify(j,null,2)),await this.appendToIndex(j),j}async list(m=20){return(await this.readIndex()).slice(0,m)}async get(m){let T=(await this.readIndex()).find(j=>j.id===m);if(!T)return null;let k=n6.join(this.dir,T.turnId,`${m}.json`);try{let j=await oE.promises.readFile(k,"utf-8");return JSON.parse(j)}catch{return null}}async rewind(m){let S=await this.get(m);if(!S)return null;try{return S.isNewFile?await oE.promises.unlink(S.path).catch(()=>{}):(await oE.promises.mkdir(n6.dirname(S.path),{recursive:!0}),await oE.promises.writeFile(S.path,S.before)),S}catch{return null}}async readIndex(){let m=n6.join(this.dir,y$e);try{let S=await oE.promises.readFile(m,"utf-8"),T=JSON.parse(S);return Array.isArray(T)?T:[]}catch{return[]}}async writeIndex(m){await oE.promises.mkdir(this.dir,{recursive:!0});let S=n6.join(this.dir,y$e);await oE.promises.writeFile(S,JSON.stringify(m,null,2))}async appendToIndex(m){let{plus:S,minus:T}=lIt(m.before,m.after),k={id:m.id,turnId:m.turnId,timestamp:m.timestamp,tool:m.tool,relPath:m.relPath,iteration:m.iteration,description:m.description,plus:S,minus:T},j=await this.readIndex();j.unshift(k);let V=j.slice(0,this.maxIndexEntries);await this.writeIndex(V)}};pk.CheckpointStore=i2e});var vJ=hi(uc=>{"use strict";Object.defineProperty(uc,"__esModule",{value:!0});uc.CheckpointStore=uc.isChatCapable=uc.suggestOllamaMatch=uc.listInstalledOllamaModels=uc.previewText=uc.openTurnLog=uc.SessionPermissionStore=uc.mergePolicies=uc.emptyPolicy=uc.evaluatePermission=uc.InMemoryBackgroundTaskStore=uc.writeInsightsReport=uc.renderInsightsHtml=uc.computeInsights=uc.buildListTasksTool=uc.buildCheckTaskTool=uc.buildTaskTool=uc.buildWebFetchTool=uc.buildTodoWriteTool=uc.TodoStore=uc.expandMentions=uc.runHooks=uc.persistAllowEntry=uc.loadHookSettings=uc.loadMemory=void 0;var fIt=HWe();Object.defineProperty(uc,"loadMemory",{enumerable:!0,get:t(function(){return fIt.loadMemory},"get")});var s2e=XWe();Object.defineProperty(uc,"loadHookSettings",{enumerable:!0,get:t(function(){return s2e.loadHookSettings},"get")});Object.defineProperty(uc,"persistAllowEntry",{enumerable:!0,get:t(function(){return s2e.persistAllowEntry},"get")});Object.defineProperty(uc,"runHooks",{enumerable:!0,get:t(function(){return s2e.runHooks},"get")});var _It=ZWe();Object.defineProperty(uc,"expandMentions",{enumerable:!0,get:t(function(){return _It.expandMentions},"get")});var a2e=t$e();Object.defineProperty(uc,"TodoStore",{enumerable:!0,get:t(function(){return a2e.TodoStore},"get")});Object.defineProperty(uc,"buildTodoWriteTool",{enumerable:!0,get:t(function(){return a2e.buildTodoWriteTool},"get")});Object.defineProperty(uc,"buildWebFetchTool",{enumerable:!0,get:t(function(){return a2e.buildWebFetchTool},"get")});var o2e=i$e();Object.defineProperty(uc,"buildTaskTool",{enumerable:!0,get:t(function(){return o2e.buildTaskTool},"get")});Object.defineProperty(uc,"buildCheckTaskTool",{enumerable:!0,get:t(function(){return o2e.buildCheckTaskTool},"get")});Object.defineProperty(uc,"buildListTasksTool",{enumerable:!0,get:t(function(){return o2e.buildListTasksTool},"get")});var c2e=l$e();Object.defineProperty(uc,"computeInsights",{enumerable:!0,get:t(function(){return c2e.computeInsights},"get")});Object.defineProperty(uc,"renderInsightsHtml",{enumerable:!0,get:t(function(){return c2e.renderInsightsHtml},"get")});Object.defineProperty(uc,"writeInsightsReport",{enumerable:!0,get:t(function(){return c2e.writeInsightsReport},"get")});var pIt=u$e();Object.defineProperty(uc,"InMemoryBackgroundTaskStore",{enumerable:!0,get:t(function(){return pIt.InMemoryBackgroundTaskStore},"get")});var eee=f$e();Object.defineProperty(uc,"evaluatePermission",{enumerable:!0,get:t(function(){return eee.evaluatePermission},"get")});Object.defineProperty(uc,"emptyPolicy",{enumerable:!0,get:t(function(){return eee.emptyPolicy},"get")});Object.defineProperty(uc,"mergePolicies",{enumerable:!0,get:t(function(){return eee.mergePolicies},"get")});Object.defineProperty(uc,"SessionPermissionStore",{enumerable:!0,get:t(function(){return eee.SessionPermissionStore},"get")});var S$e=g$e();Object.defineProperty(uc,"openTurnLog",{enumerable:!0,get:t(function(){return S$e.openTurnLog},"get")});Object.defineProperty(uc,"previewText",{enumerable:!0,get:t(function(){return S$e.previewText},"get")});var l2e=h$e();Object.defineProperty(uc,"listInstalledOllamaModels",{enumerable:!0,get:t(function(){return l2e.listInstalledOllamaModels},"get")});Object.defineProperty(uc,"suggestOllamaMatch",{enumerable:!0,get:t(function(){return l2e.suggestOllamaMatch},"get")});Object.defineProperty(uc,"isChatCapable",{enumerable:!0,get:t(function(){return l2e.isChatCapable},"get")});var dIt=b$e();Object.defineProperty(uc,"CheckpointStore",{enumerable:!0,get:t(function(){return dIt.CheckpointStore},"get")})});var tee=hi((P5t,mIt)=>{mIt.exports={name:"@burtson-labs/bandit-stealth-cli",version:"1.7.
|
|
1047
|
+
`);for(let T=0;T<m.length;T++)if(m[T]!==S[T]){let k=(m[T]??"").trim();if(k)return k.length>80?k.slice(0,77)+"\u2026":k}return"(whitespace-only edit)"}t(uIt,"describeEdit");var i2e=class{static{t(this,"CheckpointStore")}constructor(m){this.counter=0,this.workspaceRoot=m.workspaceRoot,this.dir=n6.join(m.workspaceRoot,".bandit","checkpoints"),this.maxIndexEntries=m.maxIndexEntries??cIt}async create(m){await oE.promises.mkdir(n6.join(this.dir,m.turnId),{recursive:!0}),this.counter++;let S=`chk-${m.turnId.split("-").pop()??"x"}-${String(this.counter).padStart(3,"0")}`,T=n6.relative(this.workspaceRoot,m.absolutePath)||m.absolutePath,k=m.before.length===0,j={id:S,turnId:m.turnId,timestamp:Date.now(),tool:m.tool,path:m.absolutePath,relPath:T,before:m.before,after:m.after,isNewFile:k,iteration:m.iteration,description:uIt({before:m.before,after:m.after,isNewFile:k})},V=n6.join(this.dir,m.turnId,`${S}.json`);return await oE.promises.writeFile(V,JSON.stringify(j,null,2)),await this.appendToIndex(j),j}async list(m=20){return(await this.readIndex()).slice(0,m)}async get(m){let T=(await this.readIndex()).find(j=>j.id===m);if(!T)return null;let k=n6.join(this.dir,T.turnId,`${m}.json`);try{let j=await oE.promises.readFile(k,"utf-8");return JSON.parse(j)}catch{return null}}async rewind(m){let S=await this.get(m);if(!S)return null;try{return S.isNewFile?await oE.promises.unlink(S.path).catch(()=>{}):(await oE.promises.mkdir(n6.dirname(S.path),{recursive:!0}),await oE.promises.writeFile(S.path,S.before)),S}catch{return null}}async readIndex(){let m=n6.join(this.dir,y$e);try{let S=await oE.promises.readFile(m,"utf-8"),T=JSON.parse(S);return Array.isArray(T)?T:[]}catch{return[]}}async writeIndex(m){await oE.promises.mkdir(this.dir,{recursive:!0});let S=n6.join(this.dir,y$e);await oE.promises.writeFile(S,JSON.stringify(m,null,2))}async appendToIndex(m){let{plus:S,minus:T}=lIt(m.before,m.after),k={id:m.id,turnId:m.turnId,timestamp:m.timestamp,tool:m.tool,relPath:m.relPath,iteration:m.iteration,description:m.description,plus:S,minus:T},j=await this.readIndex();j.unshift(k);let V=j.slice(0,this.maxIndexEntries);await this.writeIndex(V)}};pk.CheckpointStore=i2e});var vJ=hi(uc=>{"use strict";Object.defineProperty(uc,"__esModule",{value:!0});uc.CheckpointStore=uc.isChatCapable=uc.suggestOllamaMatch=uc.listInstalledOllamaModels=uc.previewText=uc.openTurnLog=uc.SessionPermissionStore=uc.mergePolicies=uc.emptyPolicy=uc.evaluatePermission=uc.InMemoryBackgroundTaskStore=uc.writeInsightsReport=uc.renderInsightsHtml=uc.computeInsights=uc.buildListTasksTool=uc.buildCheckTaskTool=uc.buildTaskTool=uc.buildWebFetchTool=uc.buildTodoWriteTool=uc.TodoStore=uc.expandMentions=uc.runHooks=uc.persistAllowEntry=uc.loadHookSettings=uc.loadMemory=void 0;var fIt=HWe();Object.defineProperty(uc,"loadMemory",{enumerable:!0,get:t(function(){return fIt.loadMemory},"get")});var s2e=XWe();Object.defineProperty(uc,"loadHookSettings",{enumerable:!0,get:t(function(){return s2e.loadHookSettings},"get")});Object.defineProperty(uc,"persistAllowEntry",{enumerable:!0,get:t(function(){return s2e.persistAllowEntry},"get")});Object.defineProperty(uc,"runHooks",{enumerable:!0,get:t(function(){return s2e.runHooks},"get")});var _It=ZWe();Object.defineProperty(uc,"expandMentions",{enumerable:!0,get:t(function(){return _It.expandMentions},"get")});var a2e=t$e();Object.defineProperty(uc,"TodoStore",{enumerable:!0,get:t(function(){return a2e.TodoStore},"get")});Object.defineProperty(uc,"buildTodoWriteTool",{enumerable:!0,get:t(function(){return a2e.buildTodoWriteTool},"get")});Object.defineProperty(uc,"buildWebFetchTool",{enumerable:!0,get:t(function(){return a2e.buildWebFetchTool},"get")});var o2e=i$e();Object.defineProperty(uc,"buildTaskTool",{enumerable:!0,get:t(function(){return o2e.buildTaskTool},"get")});Object.defineProperty(uc,"buildCheckTaskTool",{enumerable:!0,get:t(function(){return o2e.buildCheckTaskTool},"get")});Object.defineProperty(uc,"buildListTasksTool",{enumerable:!0,get:t(function(){return o2e.buildListTasksTool},"get")});var c2e=l$e();Object.defineProperty(uc,"computeInsights",{enumerable:!0,get:t(function(){return c2e.computeInsights},"get")});Object.defineProperty(uc,"renderInsightsHtml",{enumerable:!0,get:t(function(){return c2e.renderInsightsHtml},"get")});Object.defineProperty(uc,"writeInsightsReport",{enumerable:!0,get:t(function(){return c2e.writeInsightsReport},"get")});var pIt=u$e();Object.defineProperty(uc,"InMemoryBackgroundTaskStore",{enumerable:!0,get:t(function(){return pIt.InMemoryBackgroundTaskStore},"get")});var eee=f$e();Object.defineProperty(uc,"evaluatePermission",{enumerable:!0,get:t(function(){return eee.evaluatePermission},"get")});Object.defineProperty(uc,"emptyPolicy",{enumerable:!0,get:t(function(){return eee.emptyPolicy},"get")});Object.defineProperty(uc,"mergePolicies",{enumerable:!0,get:t(function(){return eee.mergePolicies},"get")});Object.defineProperty(uc,"SessionPermissionStore",{enumerable:!0,get:t(function(){return eee.SessionPermissionStore},"get")});var S$e=g$e();Object.defineProperty(uc,"openTurnLog",{enumerable:!0,get:t(function(){return S$e.openTurnLog},"get")});Object.defineProperty(uc,"previewText",{enumerable:!0,get:t(function(){return S$e.previewText},"get")});var l2e=h$e();Object.defineProperty(uc,"listInstalledOllamaModels",{enumerable:!0,get:t(function(){return l2e.listInstalledOllamaModels},"get")});Object.defineProperty(uc,"suggestOllamaMatch",{enumerable:!0,get:t(function(){return l2e.suggestOllamaMatch},"get")});Object.defineProperty(uc,"isChatCapable",{enumerable:!0,get:t(function(){return l2e.isChatCapable},"get")});var dIt=b$e();Object.defineProperty(uc,"CheckpointStore",{enumerable:!0,get:t(function(){return dIt.CheckpointStore},"get")})});var tee=hi((P5t,mIt)=>{mIt.exports={name:"@burtson-labs/bandit-stealth-cli",version:"1.7.87",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:{email:"team@burtson.ai"},license:"MIT",author:{name:"Burtson Labs",email:"team@burtson.ai",url:"https://burtson.ai"},bin:{bandit:"./dist/cli.js"},main:"dist/cli.js",files:["dist/cli.js","README.md","LICENSE"],engines:{node:">=20"},publishConfig:{access:"public"},scripts:{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",esbuild:"^0.28.0",pngjs:"^7.0.0",typescript:"^5.4.0"}}});var FIt={};module.exports=B2t(FIt);var Od=Au(require("fs")),u2e=Au(require("os")),rd=Au(require("path")),CF=Au(require("readline")),iee=Au(require("child_process")),CS=Au(aZ()),qN=Au(RSe());var WN=Au(require("fs")),LSe=Au(require("os")),QD=Au(require("path")),dJ=Au(require("child_process"));function _J(p){return p==="~"?LSe.homedir():p.startsWith("~/")?QD.join(LSe.homedir(),p.slice(2)):p}t(_J,"expandHome");var hF=16*1024,pJ=32*1024,gWe=1e4,B4t=3e4,jSe=200,BSe=new Set(["node_modules",".git","dist","build","out",".next",".turbo","coverage","target","__pycache__",".venv","venv"]);function J4t(p){let m=t(T=>{let k=T.match(/^(.*?)\{([^}]+)\}(.*)$/);if(!k)return[T];let[,j,V,ee]=k;return V.split(",").map(oe=>`${j}${oe.trim()}${ee}`)},"braceExpand"),S=p.match(/^([^*{}]+?)\/\*\*\/(.+)$/);if(S){let[,T,k]=S;return{includes:m(k),subDir:T}}return{includes:m(p),subDir:""}}t(J4t,"expandGlobForGrep");var yF=class{constructor(m,S,T={}){this.workspaceRoot=m;this.languageAdapters=S;this.options=T}static{t(this,"CliToolExecutionContext")}async readFile(m){return WN.promises.readFile(_J(m),"utf-8")}async writeFile(m,S){let T=_J(m);if(this.options.approveWrite&&!await this.options.approveWrite(T,S))throw new Error(`Write to ${T} rejected by user`);await WN.promises.mkdir(QD.dirname(T),{recursive:!0}),await WN.promises.writeFile(T,S,"utf-8")}async listFiles(m,S){let T=_J(S??this.workspaceRoot),k=z4t(m),j=[];return await hWe(T,T,k,j),j.slice(0,jSe).sort()}async listDirectoryEntries(m){let S=_J(m),T=await WN.promises.readdir(S,{withFileTypes:!0}),k=[];for(let j of T){if(j.name.startsWith("."))continue;let V=j.isDirectory();if(j.isSymbolicLink())try{V=(await WN.promises.stat(QD.join(S,j.name))).isDirectory()}catch{V=!1}k.push(V?`${j.name}/`:j.name)}return k.sort()}async searchCode(m,S,T){let k=_J(S??this.workspaceRoot);return this.runRipgrep(m,k,T).catch(()=>this.runGrep(m,k,T))}async runCommand(m,S,T){return new Promise(k=>{let j="",V="",ee=dJ.spawn(m,S,{cwd:T??this.workspaceRoot,shell:process.platform==="win32",env:{...process.env}}),oe=setTimeout(()=>{ee.kill("SIGTERM"),k({stdout:j.slice(0,pJ),stderr:V+`
|
|
1048
1048
|
[process timed out]`,exitCode:124})},B4t);ee.stdout?.on("data",de=>{j+=de.toString(),j.length>pJ&&ee.kill("SIGTERM")}),ee.stderr?.on("data",de=>{V+=de.toString()}),ee.on("close",de=>{clearTimeout(oe),k({stdout:j.slice(0,pJ),stderr:V.slice(0,4*1024),exitCode:de??0})}),ee.on("error",de=>{clearTimeout(oe),k({stdout:"",stderr:de.message,exitCode:1})})})}async watchCommand(m,S,T,k){return new Promise(j=>{let V="",ee="",oe=!1,de=!1,_e=dJ.spawn(m,S,{cwd:T??this.workspaceRoot,shell:process.platform==="win32",env:{...process.env}}),ye=t(rt=>{de||(de=!0,j({stdout:V.slice(0,pJ),stderr:ee.slice(0,4*1024),exitCode:rt,endedEarly:oe}))},"finish"),Y=setTimeout(()=>{try{_e.kill("SIGTERM")}catch{}let rt=setTimeout(()=>{try{_e.kill("SIGKILL")}catch{}ye(null)},1e3);_e.once("close",Je=>{clearTimeout(rt),ye(typeof Je=="number"?Je:null)})},k);_e.stdout?.on("data",rt=>{if(V+=rt.toString(),V.length>pJ)try{_e.kill("SIGTERM")}catch{}}),_e.stderr?.on("data",rt=>{ee+=rt.toString()}),_e.on("close",rt=>{de||(clearTimeout(Y),oe=!0,ye(typeof rt=="number"?rt:null))}),_e.on("error",rt=>{de||(clearTimeout(Y),oe=!0,ee+=rt.message,ye(1))})})}runRipgrep(m,S,T){return new Promise((k,j)=>{let V=["--color=never","--line-number","--max-count=25","--max-filesize=1M",...[...BSe].map(_e=>["--glob",`!${_e}`]).flat()];T&&V.push("--glob",T),V.push(m,S);let ee="",oe=dJ.spawn("rg",V,{shell:!1}),de=setTimeout(()=>{oe.kill("SIGTERM"),k(ee.slice(0,hF))},gWe);oe.stdout?.on("data",_e=>{ee+=_e.toString(),ee.length>hF&&oe.kill("SIGTERM")}),oe.on("close",_e=>{clearTimeout(de),_e!=null&&_e>=2&&ee.length===0?j(new Error(`rg exited with code ${_e}`)):k(ee.slice(0,hF))}),oe.on("error",j)})}runGrep(m,S,T){return new Promise((k,j)=>{let V=[...BSe].map(Je=>["--exclude-dir",Je]).flat(),ee=T?J4t(T):{includes:[],subDir:""},oe=ee.includes.flatMap(Je=>["--include",Je]),de=ee.subDir?`${S}/${ee.subDir}`:S,_e=["-rn","-E","--color=never",...V,...oe,m,de],ye="",Y=dJ.spawn("grep",_e,{shell:!1}),rt=setTimeout(()=>{Y.kill("SIGTERM"),k(ye.slice(0,hF))},gWe);Y.stdout?.on("data",Je=>{ye+=Je.toString(),ye.length>hF&&Y.kill("SIGTERM")}),Y.on("close",Je=>{clearTimeout(rt),Je!=null&&Je>=2&&ye.length===0?j(new Error(`grep exited with code ${Je}`)):k(ye.slice(0,hF))}),Y.on("error",j)})}};function z4t(p){let m=W4t(p);return S=>m.test(S.replace(/\\/g,"/"))}t(z4t,"compileGlob");function W4t(p){let m="^";for(let S=0;S<p.length;S++){let T=p[S];if(T==="*")p[S+1]==="*"?(m+=".*",S++,p[S+1]==="/"&&S++):m+="[^/]*";else if(T==="?")m+="[^/]";else if(T==="{"){let k=p.indexOf("}",S);if(k===-1){m+="\\{";continue}let j=p.slice(S+1,k).split(",").map($4t).join("|");m+=`(?:${j})`,S=k}else/[.+^$()|\\]/.test(T)?m+="\\"+T:m+=T}return m+="$",new RegExp(m)}t(W4t,"globToRegex");function $4t(p){return p.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}t($4t,"escapeRegex");async function hWe(p,m,S,T){if(T.length>=jSe)return;let k;try{k=await WN.promises.readdir(p,{withFileTypes:!0})}catch{return}for(let j of k){if(T.length>=jSe)return;if(BSe.has(j.name))continue;let V=QD.join(p,j.name),ee=QD.relative(m,V);j.isDirectory()?await hWe(V,m,S,T):j.isFile()&&S(ee)&&T.push(V)}}t(hWe,"walk");var vWe=Au(require("child_process")),uk=Au(require("fs")),bWe=Au(require("os")),JSe=Au(require("path")),SWe=Au(require("crypto"));function zSe(){let p=SWe.randomBytes(4).toString("hex");return JSe.join(bWe.tmpdir(),`bandit-paste-${Date.now()}-${p}.png`)}t(zSe,"freshTempPath");function zZ(p,m,S={}){try{let T=vWe.spawnSync(p,m,{...S,encoding:void 0});return{stdout:Buffer.isBuffer(T.stdout)?T.stdout:Buffer.from(T.stdout??""),code:T.status}}catch{return{stdout:Buffer.alloc(0),code:null}}}t(zZ,"tryExec");async function WZ(){return process.platform==="darwin"?U4t():process.platform==="linux"?V4t():process.platform==="win32"?q4t():null}t(WZ,"readClipboardImage");function U4t(){let p=zSe(),m=`set pngData to (the clipboard as \xABclass PNGf\xBB)
|
|
1049
1049
|
set outFile to (open for access (POSIX file "${p}") with write permission)
|
|
1050
1050
|
write pngData to outFile
|
package/package.json
CHANGED