@burtson-labs/bandit-stealth-cli 1.7.438 → 1.7.439

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.
Files changed (2) hide show
  1. package/dist/cli.js +3 -3
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -339,7 +339,7 @@ ${I.join(`
339
339
  `)}${N}`}}},Odn={name:"mail_read",description:"Read a single Mail.app message by its .emlx file path (from mail_search). Returns the RFC822 message \u2014 headers + body. Strips Apple's envelope (byte-count prefix + trailing plist). macOS only.",parameters:[{name:"path",description:"Absolute path to a .emlx file (use the path field from a mail_search row).",required:!0}],async execute(r){let i=Cht()??Eht();if(i)return i;let o=r.path?.trim();if(!o)return{output:"mail_read requires `path` (the .emlx file from a mail_search row).",isError:!0};let l=lBe.resolve(o),u=fBe();if(!l.startsWith(u+lBe.sep))return{output:`mail_read can only open files under ${u}. Got: ${l}`,isError:!0};if(!/\.(emlx|partial\.emlx|emlxpart)$/.test(l))return{output:`mail_read expects a .emlx file. Got: ${l}`,isError:!0};let _;try{_=await Sht.promises.readFile(l,"utf-8")}catch(N){return{output:`Failed to read ${l}: ${N instanceof Error?N.message:String(N)}`,isError:!0}}let h=_.indexOf(`
340
340
  `),C=parseInt(_.slice(0,h).trim(),10),I=Number.isFinite(C)&&C>0?_.slice(h+1,h+1+C):_;return I.length>cBe&&(I=I.slice(0,cBe)+`
341
341
 
342
- [\u2026truncated, ${I.length-cBe} more bytes; use a more specific search to narrow the thread]`),{output:I}}};o8.mailSearchSkill={id:"mac/mail-search",name:"Mail Search (macOS)",version:"1.0.0",description:"Search and read Apple Mail.app messages via Spotlight + .emlx \u2014 no AppleScript timeouts.",instructions:"When the user asks about an email thread, who emailed them, or to summarise a conversation: \n1. Call `mail_search` with `query`/`from`/`subject`/`since` filters. Do NOT use `osascript ... whose ...` on Mail.app \u2014 it scans linearly and times out at 30s on large inboxes.\n2. Pick the relevant `path` from the result list.\n3. Call `mail_read(path=...)` to get the message body.\nFor a thread you may need to mail_read 2-3 messages. Prefer `from` over generic `query` when you know the sender \u2014 it returns much fewer false positives.",activation:"auto",triggerPatterns:[/\bemail\b/i,/\binbox\b/i,/\bmail\.?app\b/i,/\bapple mail\b/i,/\bmessage(s)? from\b/i],tools:[Ndn,Odn]}});var pBe=Dt(Nq=>{"use strict";Object.defineProperty(Nq,"__esModule",{value:!0});Nq.webArtifactSkill=Nq.HTML_ARTIFACT_GUIDANCE=void 0;Nq.HTML_ARTIFACT_GUIDANCE=["When you build a self-contained HTML artifact (a page, report, dashboard, briefing, or any HTML you will publish), treat it as real product design, not a raw document. Deliver these by DEFAULT:","- Self-contained + CSP-safe: ALL CSS in a <style> tag and ALL JS in a <script> tag \u2014 no external stylesheets, fonts, scripts, or CDNs (they are blocked). Embed images as data: URIs. Use a system font stack, no web fonts.","- Mobile-first & responsive: design for a phone first, then scale up. Relative units, flexbox/grid, max-width on content, images max-width:100%. The page body must NEVER scroll horizontally \u2014 wide tables/code/diagrams scroll inside their own overflow-x:auto container. Comfortable tap targets and spacing.","- Light AND dark theme: style BOTH. Default to the viewer\u2019s system preference with @media (prefers-color-scheme: dark), drive every color from CSS variables, and add a small theme toggle that flips them. Never hard-code one background/text color that breaks in the other mode.",'- Lucide icons, inlined as SVG: use Lucide-style icons inlined directly as <svg> (never a CDN or icon font). Lucide convention: viewBox="0 0 24 24", fill="none", stroke="currentColor", stroke-width="2", stroke-linecap="round", stroke-linejoin="round" \u2014 currentColor makes them follow the theme automatically. Size with width/height or CSS.',"- Polished by default: clear visual hierarchy, generous whitespace, one coherent accent color, subtle borders/shadows, and a readable line length (~60-75ch) for prose.","If the task leaves room and you can ask the user (ask_user), briefly offer to tailor the polish BEFORE you build: how refined they want it, brand colors or a logo, imagery, and tone. Ask ONCE, keep it short, and never block a quick request \u2014 if they do not care or it is a fast turn, just ship the great default above."].join(`
342
+ [\u2026truncated, ${I.length-cBe} more bytes; use a more specific search to narrow the thread]`),{output:I}}};o8.mailSearchSkill={id:"mac/mail-search",name:"Mail Search (macOS)",version:"1.0.0",description:"Search and read Apple Mail.app messages via Spotlight + .emlx \u2014 no AppleScript timeouts.",instructions:"When the user asks about an email thread, who emailed them, or to summarise a conversation: \n1. Call `mail_search` with `query`/`from`/`subject`/`since` filters. Do NOT use `osascript ... whose ...` on Mail.app \u2014 it scans linearly and times out at 30s on large inboxes.\n2. Pick the relevant `path` from the result list.\n3. Call `mail_read(path=...)` to get the message body.\nFor a thread you may need to mail_read 2-3 messages. Prefer `from` over generic `query` when you know the sender \u2014 it returns much fewer false positives.",activation:"auto",triggerPatterns:[/\bemail\b/i,/\binbox\b/i,/\bmail\.?app\b/i,/\bapple mail\b/i,/\bmessage(s)? from\b/i],tools:[Ndn,Odn]}});var pBe=Dt(Nq=>{"use strict";Object.defineProperty(Nq,"__esModule",{value:!0});Nq.webArtifactSkill=Nq.HTML_ARTIFACT_GUIDANCE=void 0;Nq.HTML_ARTIFACT_GUIDANCE=["When you build a self-contained HTML artifact (a page, report, dashboard, briefing, or any HTML you will publish), treat it as real product design, not a raw document. Deliver these by DEFAULT:","- Self-contained + CSP-safe: ALL CSS in a <style> tag and ALL JS in a <script> tag \u2014 no external stylesheets, fonts, scripts, or CDNs (they are blocked). Embed images as data: URIs. Use a system font stack, no web fonts.","- Mobile-first & responsive: design for a phone first, then scale up. Relative units, flexbox/grid, max-width on content, images max-width:100%. The page body must NEVER scroll horizontally \u2014 wide tables/code/diagrams scroll inside their own overflow-x:auto container. Comfortable tap targets and spacing.","- Light AND dark theme: style BOTH. Default to the viewer\u2019s system preference with @media (prefers-color-scheme: dark), drive every color from CSS variables, and add a small theme toggle that flips them. Never hard-code one background/text color that breaks in the other mode.",'- Lucide icons, inlined as SVG: use Lucide-style icons inlined directly as <svg> (never a CDN or icon font). Lucide convention: viewBox="0 0 24 24", fill="none", stroke="currentColor", stroke-width="2", stroke-linecap="round", stroke-linejoin="round" \u2014 currentColor makes them follow the theme automatically. Size with width/height or CSS.',"- Polished by default: clear visual hierarchy, generous whitespace, one coherent accent color, subtle borders/shadows, and a readable line length (~60-75ch) for prose.",'These rules ARE Bandit\u2019s house UX standard. When the user says "make it nice", "polish it", or "follow our UX guidelines", just APPLY them \u2014 do NOT ask what the guidelines are; you already have them. Reserve a brief ask_user only for something you genuinely cannot infer and that would materially change the result \u2014 a brand logo, specific brand colors, or particular imagery \u2014 and only when building something substantial from scratch. Even then, prefer to ship a strong default and offer to refine afterward. On a revision or a quick turn, do not ask \u2014 apply the guidelines and show the result.'].join(`
343
343
  `);Nq.webArtifactSkill={id:"web/artifact",name:"Web Artifact",version:"1.0.0",description:"Build self-contained HTML artifacts with excellent, mobile-friendly, theme-aware UX.",instructions:Nq.HTML_ARTIFACT_GUIDANCE,activation:"auto",triggerPatterns:[/\bhtml\b/i,/\bartifact\b/i,/\bweb\s?page\b/i,/\blanding page\b/i,/\bstatic site\b/i,/\bmicrosite\b/i,/\bone[-\s]?pager\b/i,/\bself[-\s]?contained\b/i,/\b(build|make|create|generate|design)\b[\s\S]{0,30}\b(page|site|report|briefing|dashboard|deck|flyer|poster|resume|cv|portfolio|invoice|newsletter)\b/i,/\b(publish|share)\b[\s\S]{0,40}\b(page|site|report|briefing|dashboard|deck|artifact)\b/i],tools:[]}});var Tht=Dt(e0e=>{"use strict";Object.defineProperty(e0e,"__esModule",{value:!0});e0e.interactionSkill=void 0;var Rdn=BMe();e0e.interactionSkill={id:"core/interaction",name:"Ask the User",version:"1.0.0",description:"Ask the user clarifying questions with selectable options when blocked on a decision.",activation:"always",tools:[Rdn.askUserTool]}});var kht=Dt(Zh=>{"use strict";Object.defineProperty(Zh,"__esModule",{value:!0});Zh.interactionSkill=Zh.HTML_ARTIFACT_GUIDANCE=Zh.webArtifactSkill=Zh.mailSearchSkill=Zh.resetSemanticIndex=Zh.configureSemanticSearchOllamaUrl=Zh.semanticSearchSkill=Zh.planSkill=Zh.testGenSkill=Zh.codeReviewSkill=Zh.gitSkill=Zh.coreSkill=void 0;Zh.createDefaultSkillRegistry=Kdn;var Mdn=tBe();Object.defineProperty(Zh,"coreSkill",{enumerable:!0,get:t(function(){return Mdn.coreSkill},"get")});var Bdn=nBe();Object.defineProperty(Zh,"gitSkill",{enumerable:!0,get:t(function(){return Bdn.gitSkill},"get")});var Fdn=rBe();Object.defineProperty(Zh,"codeReviewSkill",{enumerable:!0,get:t(function(){return Fdn.codeReviewSkill},"get")});var Ldn=iBe();Object.defineProperty(Zh,"testGenSkill",{enumerable:!0,get:t(function(){return Ldn.testGenSkill},"get")});var jdn=aBe();Object.defineProperty(Zh,"planSkill",{enumerable:!0,get:t(function(){return jdn.planSkill},"get")});var _Be=sBe();Object.defineProperty(Zh,"semanticSearchSkill",{enumerable:!0,get:t(function(){return _Be.semanticSearchSkill},"get")});Object.defineProperty(Zh,"configureSemanticSearchOllamaUrl",{enumerable:!0,get:t(function(){return _Be.configureSemanticSearchOllamaUrl},"get")});Object.defineProperty(Zh,"resetSemanticIndex",{enumerable:!0,get:t(function(){return _Be.resetSemanticIndex},"get")});var $dn=dBe();Object.defineProperty(Zh,"mailSearchSkill",{enumerable:!0,get:t(function(){return $dn.mailSearchSkill},"get")});var wht=pBe();Object.defineProperty(Zh,"webArtifactSkill",{enumerable:!0,get:t(function(){return wht.webArtifactSkill},"get")});Object.defineProperty(Zh,"HTML_ARTIFACT_GUIDANCE",{enumerable:!0,get:t(function(){return wht.HTML_ARTIFACT_GUIDANCE},"get")});var Udn=Tht();Object.defineProperty(Zh,"interactionSkill",{enumerable:!0,get:t(function(){return Udn.interactionSkill},"get")});var zdn=XMe(),Qdn=tBe(),qdn=nBe(),Jdn=rBe(),Hdn=iBe(),Gdn=aBe(),Vdn=sBe(),Wdn=dBe(),Zdn=pBe();function Kdn(){return new zdn.SkillRegistry().registerAll([Qdn.coreSkill,qdn.gitSkill,Jdn.codeReviewSkill,Hdn.testGenSkill,Gdn.planSkill,Vdn.semanticSearchSkill,Wdn.mailSearchSkill,Zdn.webArtifactSkill])}t(Kdn,"createDefaultSkillRegistry")});var xht=Dt(Db=>{"use strict";var Ydn=Db&&Db.__createBinding||(Object.create?(function(r,i,o,l){l===void 0&&(l=o);var u=Object.getOwnPropertyDescriptor(i,o);(!u||("get"in u?!i.__esModule:u.writable||u.configurable))&&(u={enumerable:!0,get:t(function(){return i[o]},"get")}),Object.defineProperty(r,l,u)}):(function(r,i,o,l){l===void 0&&(l=o),r[l]=i[o]})),yx=Db&&Db.__exportStar||function(r,i){for(var o in r)o!=="default"&&!Object.prototype.hasOwnProperty.call(i,o)&&Ydn(i,r,o)};Object.defineProperty(Db,"__esModule",{value:!0});yx($mt(),Db);yx(sae(),Db);yx(MMe(),Db);yx(BMe(),Db);yx(FMe(),Db);yx(Igt(),Db);yx(bZ(),Db);yx(WMe(),Db);yx(HMe(),Db);yx(uht(),Db);yx(dht(),Db);yx(XMe(),Db);yx(yht(),Db);yx(kht(),Db)});var n0e=Dt(t0e=>{"use strict";Object.defineProperty(t0e,"__esModule",{value:!0});t0e.graphFingerprint=Xdn;t0e.validateGraph=epn;function Xdn(r){let i=[...r.nodes].map(o=>[o.id,[...o.dependsOn??[]].sort()]).sort((o,l)=>o[0].localeCompare(l[0]));return JSON.stringify(i)}t(Xdn,"graphFingerprint");function epn(r){let i=[],o=new Set;for(let l of r.nodes)!l.id||l.id.trim().length===0?i.push("node with empty id"):o.has(l.id)?i.push(`duplicate node id: ${l.id}`):o.add(l.id);for(let l of r.nodes)for(let u of l.dependsOn??[])u===l.id?i.push(`node ${l.id} depends on itself`):o.has(u)||i.push(`node ${l.id} depends on unknown node: ${u}`);if(i.length===0){let l=new Map,u=new Map;for(let C of r.nodes){l.set(C.id,(C.dependsOn??[]).length);for(let I of C.dependsOn??[]){let N=u.get(I)??[];N.push(C.id),u.set(I,N)}}let _=r.nodes.filter(C=>(l.get(C.id)??0)===0).map(C=>C.id),h=0;for(;_.length>0;){let C=_.shift();h+=1;for(let I of u.get(C)??[]){let N=(l.get(I)??1)-1;l.set(I,N),N===0&&_.push(I)}}if(h!==r.nodes.length){let C=r.nodes.filter(I=>(l.get(I.id)??0)>0).map(I=>I.id);i.push(`cycle detected involving: ${C.join(", ")}`)}}return{ok:i.length===0,errors:i}}t(epn,"validateGraph")});var mBe=Dt(r0e=>{"use strict";Object.defineProperty(r0e,"__esModule",{value:!0});r0e.checkContract=tpn;r0e.verificationNode=npn;function tpn(r,i){if(!r)return[];let o=[],l=typeof i.output=="string"?i.output:i.output===void 0?"":JSON.stringify(i.output);if(r.outputNonEmpty&&l.trim().length===0&&o.push("contract: output is empty"),r.outputMatches)try{new RegExp(r.outputMatches,"s").test(l)||o.push(`contract: output does not match /${r.outputMatches}/`)}catch{o.push(`contract: invalid outputMatches regex /${r.outputMatches}/`)}for(let u of r.requireEvidence??[]){let _=Math.max(1,u.min??1),h=(i.evidence??[]).filter(C=>C.kind===u.kind).length;h<_&&o.push(`contract: needs ${_} evidence of kind "${u.kind}", got ${h}`)}return o}t(tpn,"checkContract");function npn(r,i,o,l){return{node:{id:r,label:l?.label??`verify ${i}`,dependsOn:[...new Set([i,...l?.dependsOn??[]])]},executor:t(async h=>{let C=await o(h);if(!C.pass){let I=C.reasons?.length?C.reasons.join("; "):"no reasons given";throw new Error(`verification failed for ${i}: ${I}`)}return{output:C,summary:`verified ${i}`,evidence:[{kind:"verification",detail:i,data:C}]}},"executor")}}t(npn,"verificationNode")});var Dht=Dt(gBe=>{"use strict";Object.defineProperty(gBe,"__esModule",{value:!0});gBe.runGraph=ipn;var Iht=n0e(),rpn=mBe();async function ipn(r,i,o={}){let l=Date.now(),u=(0,Iht.validateGraph)(r);if(!u.ok)throw new Error(`invalid graph: ${u.errors.join("; ")}`);let _=Math.max(1,o.maxConcurrency??2),h=o.emitEvent??(()=>{}),C=o.signal,I=t(Nt=>{if(typeof i=="function")return i;let nn=i[Nt];if(!nn)throw new Error(`no executor for node: ${Nt}`);return nn},"executorFor");for(let Nt of r.nodes)I(Nt.id);let N=(0,Iht.graphFingerprint)(r);if(o.resumeFrom&&o.resumeFrom.specFingerprint!==N)throw new Error("resume checkpoint does not match this graph (node ids/dependencies differ)");let M={};for(let Nt of r.nodes){let nn=o.resumeFrom?.nodes[Nt.id];nn&&nn.state==="done"?M[Nt.id]={...nn}:M[Nt.id]={id:Nt.id,state:"pending"}}let J=t(()=>({version:1,specFingerprint:N,nodes:Object.fromEntries(Object.entries(M).map(([Nt,nn])=>[Nt,{...nn}]))}),"checkpoint"),j=t(()=>{try{o.onCheckpoint?.(J())}catch{}},"fireCheckpoint"),ne=new Map;for(let Nt of r.nodes)for(let nn of Nt.dependsOn??[]){let En=ne.get(nn)??[];En.push(Nt.id),ne.set(nn,En)}let re=new Map(r.nodes.map(Nt=>[Nt.id,Nt.dependsOn??[]])),se=new Map(r.nodes.map(Nt=>[Nt.id,Nt.label??Nt.id])),Pe=new Map(r.nodes.map(Nt=>[Nt.id,Nt])),Qe=new Map,qe=!1,dt=t(Nt=>M[Nt].state==="pending"&&(re.get(Nt)??[]).every(nn=>M[nn].state==="done"),"readyToRun"),pt=t(Nt=>M[Nt].state==="pending"&&(re.get(Nt)??[]).some(nn=>{let En=M[nn].state;return En==="failed"||En==="skipped"||En==="cancelled"}),"blocked"),vt=t(()=>{let Nt=!0;for(;Nt;){Nt=!1;for(let nn of r.nodes)pt(nn.id)&&(M[nn.id]={...M[nn.id],state:"skipped"},h("graph:node_skipped",{id:nn.id,label:se.get(nn.id)}),Nt=!0)}},"markSkippedCascade"),st=t(Nt=>{let nn=M[Nt];nn.state="running",nn.startedAt=Date.now(),h("graph:node_start",{id:Nt,label:se.get(Nt)});let En={};for(let sr of re.get(Nt)??[])En[sr]=M[sr];let Tr=(async()=>{try{let sr=await I(Nt)({nodeId:Nt,signal:C??new AbortController().signal,upstream:En,envelope:Pe.get(Nt)?.envelope}),Wt=(0,rpn.checkContract)(Pe.get(Nt)?.contract,sr??{});nn.output=sr?.output,nn.summary=sr?.summary,nn.evidence=sr?.evidence,Wt.length>0?(nn.state="failed",nn.error=Wt.join("; "),nn.contractViolations=Wt,qe=!0,h("graph:node_contract_violation",{id:Nt,label:se.get(Nt),violations:Wt}),h("graph:node_failed",{id:Nt,label:se.get(Nt),error:nn.error})):(nn.state="done",h("graph:node_done",{id:Nt,label:se.get(Nt),summary:nn.summary}))}catch(sr){nn.state="failed",nn.error=sr instanceof Error?sr.message:String(sr),qe=!0,h("graph:node_failed",{id:Nt,label:se.get(Nt),error:nn.error})}finally{nn.endedAt=Date.now(),nn.durationMs=nn.endedAt-(nn.startedAt??nn.endedAt),Qe.delete(Nt),j()}})();Qe.set(Nt,Tr)},"launch");h("graph:start",{nodes:r.nodes.length,maxConcurrency:_,resumed:!!o.resumeFrom});for(let Nt of r.nodes)M[Nt.id].state==="done"&&o.resumeFrom&&h("graph:node_restored",{id:Nt.id,label:se.get(Nt.id),summary:M[Nt.id].summary});for(;;){if(vt(),!C?.aborted)for(let Nt of r.nodes){if(Qe.size>=_)break;dt(Nt.id)&&st(Nt.id)}if(Qe.size===0)break;await Promise.race(Qe.values())}for(let Nt of r.nodes)M[Nt.id].state==="pending"&&(M[Nt.id]={...M[Nt.id],state:"cancelled"},h("graph:node_cancelled",{id:Nt.id,label:se.get(Nt.id)}));j();let xt=C?.aborted?"cancelled":qe?"failed":"completed",Nn={status:xt,nodes:M,durationMs:Date.now()-l};return h("graph:done",{status:xt,durationMs:Nn.durationMs,done:Object.values(M).filter(Nt=>Nt.state==="done").length,failed:Object.values(M).filter(Nt=>Nt.state==="failed").length,skipped:Object.values(M).filter(Nt=>Nt.state==="skipped").length}),Nn}t(ipn,"runGraph")});var hBe=Dt(i0e=>{"use strict";Object.defineProperty(i0e,"__esModule",{value:!0});i0e.envelopeGate=apn;i0e.composeGates=spn;function apn(r){let i=new Set(r?.denyTools??[]),o=r?.allowTools?new Set(r.allowTools):null;return l=>i.has(l.name)?{allow:!1,reason:`node envelope denies "${l.name}" \u2014 this node may not use that tool; work within its declared capabilities or report what you would have done.`}:o&&!o.has(l.name)?{allow:!1,reason:`node envelope allows only [${[...o].join(", ")}] \u2014 "${l.name}" is outside this node's capabilities; use the allowed tools or report what you would have done.`}:{allow:!0}}t(apn,"envelopeGate");function spn(...r){let i=r.filter(o=>typeof o=="function");return async o=>{for(let l of i){let u=await l(o);if(!u.allow)return u}return{allow:!0}}}t(spn,"composeGates")});var Nht=Dt(a0e=>{"use strict";Object.defineProperty(a0e,"__esModule",{value:!0});a0e.defaultNodePrompt=cpn;a0e.wrapLoopAsNode=lpn;var opn=WMe(),Pht=hBe();function cpn(r){return i=>{let o=Object.keys(i.upstream);if(o.length===0)return r;let l=o.map(u=>{let _=i.upstream[u],h=_.summary??(typeof _.output=="string"?_.output:JSON.stringify(_.output??""));return`### Result of "${u}"
344
344
  ${(h??"").toString().slice(0,4e3)}`});return`${r}
345
345
 
@@ -1540,7 +1540,7 @@ Content-Type: ${o}\r
1540
1540
  `}<style data-${T4t}>body{word-wrap:break-word;-webkit-text-size-adjust:100%}img,video,canvas,svg{max-width:100%;height:auto}table{display:block;max-width:100%;overflow-x:auto}pre{max-width:100%;overflow-x:auto}</style>`,l=/<head[^>]*>/i.exec(r);if(l){let _=l.index+l[0].length;return`${r.slice(0,_)}
1541
1541
  ${o}${r.slice(_)}`}let u=/<html[^>]*>/i.exec(r);if(u){let _=u.index+u[0].length;return`${r.slice(0,_)}
1542
1542
  <head>${o}</head>${r.slice(_)}`}return`${o}
1543
- ${r}`}t(Eqe,"ensureMobileFriendlyHtml");async function gVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=r.contentType??Cqe(r.filename),u=typeof r.content=="string"&&/html/.test(l)?Eqe(r.content):r.content,_=typeof u=="string"?new TextEncoder().encode(u):u,h=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),{body:C,contentType:I}=k4t("File",r.filename,l,_),N=r.scope==="team"?"?scope=team":"",M=Math.max(1,r.maxAttempts??3),J=r.retryDelayMs??300,j=new Error("artifact upload failed");for(let ne=1;ne<=M;ne++){let re;try{re=await i(`${o}/api/artifact${N}`,{method:"POST",headers:{authorization:`Bearer ${h}`,"content-type":I},body:C})}catch(Pe){if(j=new Error(`artifact upload failed: ${Pe instanceof Error?Pe.message:String(Pe)}`),ne<M){await w4t(J*ne);continue}throw j}if(re.ok){let Pe=await re.json();if(!Pe.url)throw new Error("artifact upload succeeded but no URL was returned");return{url:Pe.url,key:Pe.key??"",size:Pe.size??_.byteLength}}let se="";try{se=(await re.json())?.message??""}catch{}if(j=new Error(`artifact upload failed: HTTP ${re.status}${se?` \u2014 ${se}`:""}`),re.status>=500&&ne<M){await w4t(J*ne);continue}throw j}throw j}t(gVn,"publishArtifact");function w4t(r){return r>0?new Promise(i=>setTimeout(i,r)):Promise.resolve()}t(w4t,"sleep");function wM(r){let i="/api/artifact/",o=r.indexOf(i);return(o>=0?r.slice(o+i.length):r).split("/").map(u=>{try{return decodeURIComponent(u)}catch{return u}}).join("/")}t(wM,"artifactKeyFromUrl");async function hVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),u=await i(`${o}/api/artifact/mine`,{headers:{authorization:`Bearer ${l}`}});if(!u.ok)throw new Error(`could not list artifacts: HTTP ${u.status}`);return(await u.json()).artifacts??[]}t(hVn,"listArtifacts");async function yVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),u=wM(r.keyOrUrl).split("/").map(encodeURIComponent).join("/"),_=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),h=await i(`${o}/api/artifact/${u}`,{method:"DELETE",headers:{authorization:`Bearer ${_}`}});if(!h.ok)throw h.status===404?new Error(`no artifact found for "${r.keyOrUrl}" (or it isn't yours)`):new Error(`could not delete artifact: HTTP ${h.status}`)}t(yVn,"deleteArtifact");async function vVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/share`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l,expiryMinutes:r.expiryMinutes})});if(!_.ok){let C="";try{C=(await _.json())?.message??""}catch{}throw new Error(`could not create share link: HTTP ${_.status}${C?` \u2014 ${C}`:""}`)}let h=await _.json();if(!h.url)throw new Error("share link created but no URL was returned");return{url:h.url,token:h.token??"",expiresAt:h.expiresAt??""}}t(vVn,"createShareLink");async function AVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/scope`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l,scope:r.scope})});if(!_.ok){let C="";try{C=(await _.json())?.message??""}catch{}throw new Error(`could not change scope: HTTP ${_.status}${C?` \u2014 ${C}`:""}`)}let h=await _.json();return{key:h.key??l,url:h.url??"",scope:h.scope??r.scope}}t(AVn,"setArtifactScope");async function bVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/restore`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l})});if(!_.ok){let h="";try{h=(await _.json())?.message??""}catch{}throw new Error(`could not restore artifact: HTTP ${_.status}${h?` \u2014 ${h}`:""}`)}}t(bVn,"restoreArtifact");async function SVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/archive`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l})});if(!_.ok){let h="";try{h=(await _.json())?.message??""}catch{}throw new Error(`could not archive artifact: HTTP ${_.status}${h?` \u2014 ${h}`:""}`)}}t(SVn,"archiveArtifact");async function CVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=l.split("/").map(encodeURIComponent).join("/"),_=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),h=await i(`${o}/api/artifact/${u}`,{headers:{authorization:`Bearer ${_}`}});if(!h.ok){let N="";try{N=(await h.json())?.message??""}catch{}throw new Error(`could not fetch artifact: HTTP ${h.status}${N?` \u2014 ${N}`:""}`)}let C=h.headers.get("content-type")??"application/octet-stream",I=await h.text();return{key:l,contentType:C,content:I}}t(CVn,"getArtifact");async function EVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=l.split("/").map(encodeURIComponent).join("/"),_=r.filename??(l.split("/").pop()||"artifact"),h=r.contentType??Cqe(_),C=typeof r.content=="string"&&/html/.test(h)?Eqe(r.content):r.content,I=typeof C=="string"?new TextEncoder().encode(C):C,N=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),{body:M,contentType:J}=k4t("File",_,h,I),j=await i(`${o}/api/artifact/${u}`,{method:"PUT",headers:{authorization:`Bearer ${N}`,"content-type":J},body:M});if(!j.ok){let re="";try{re=(await j.json())?.message??""}catch{}throw new Error(`could not update artifact: HTTP ${j.status}${re?` \u2014 ${re}`:""}`)}let ne=await j.json();return{url:ne.url??r.keyOrUrl,key:ne.key??l,size:ne.size??I.byteLength}}t(EVn,"updateArtifact");async function TVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/share/email`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l,to:r.to,expiryMinutes:r.expiryMinutes,message:r.message})});if(!_.ok){let C="";try{C=(await _.json())?.message??""}catch{}throw new Error(`could not email share link: HTTP ${_.status}${C?` \u2014 ${C}`:""}`)}let h=await _.json();if(!h.url)throw new Error("share link created but no URL was returned");return{url:h.url,token:h.token??"",expiresAt:h.expiresAt??"",emailed:h.emailed??!1}}t(TVn,"emailShareLink");async function wVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),u=await i(`${o}/api/artifact/share/${encodeURIComponent(r.shareToken)}`,{method:"DELETE",headers:{authorization:`Bearer ${l}`}});if(!u.ok)throw u.status===404?new Error("no matching share link (or it isn't yours)"):new Error(`could not revoke share link: HTTP ${u.status}`)}t(wVn,"revokeShareLink");async function kVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/shares?key=${encodeURIComponent(l)}`,{headers:{authorization:`Bearer ${u}`}});if(!_.ok)throw new Error(`could not list share links: HTTP ${_.status}`);return(await _.json()).shares??[]}t(kVn,"listShareLinks");async function xVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=r.scope==="team"?"?scope=team":"",u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/mine${l}`,{method:"DELETE",headers:{authorization:`Bearer ${u}`}});if(!_.ok)throw new Error(`could not clear artifacts: HTTP ${_.status}`);return(await _.json()).deleted??0}t(xVn,"clearArtifacts")});var ACe=Dt(RL=>{"use strict";var IVn=RL&&RL.__createBinding||(Object.create?(function(r,i,o,l){l===void 0&&(l=o);var u=Object.getOwnPropertyDescriptor(i,o);(!u||("get"in u?!i.__esModule:u.writable||u.configurable))&&(u={enumerable:!0,get:t(function(){return i[o]},"get")}),Object.defineProperty(r,l,u)}):(function(r,i,o,l){l===void 0&&(l=o),r[l]=i[o]})),DVn=RL&&RL.__setModuleDefault||(Object.create?(function(r,i){Object.defineProperty(r,"default",{enumerable:!0,value:i})}):function(r,i){r.default=i}),x4t=RL&&RL.__importStar||(function(){var r=t(function(i){return r=Object.getOwnPropertyNames||function(o){var l=[];for(var u in o)Object.prototype.hasOwnProperty.call(o,u)&&(l[l.length]=u);return l},r(i)},"ownKeys");return function(i){if(i&&i.__esModule)return i;var o={};if(i!=null)for(var l=r(i),u=0;u<l.length;u++)l[u]!=="default"&&IVn(o,i,l[u]);return DVn(o,i),o}})();Object.defineProperty(RL,"__esModule",{value:!0});RL.inlineHtmlImages=MVn;var PVn=x4t(Fa("fs")),Tqe=x4t(Fa("path")),NVn={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".avif":"image/avif"};function OVn(r){return NVn[Tqe.extname(r).toLowerCase()]??"application/octet-stream"}t(OVn,"mimeFromPath");async function RVn(r,i,o){if(!r||r.startsWith("data:"))return null;try{let l,u;if(/^https?:\/\//i.test(r)){let _=new AbortController,h=setTimeout(()=>_.abort(),i.timeoutMs),C;try{C=await i.fetchImpl(r,{signal:_.signal,redirect:"follow"})}finally{clearTimeout(h)}if(!C.ok||(u=(C.headers.get("content-type")??"").split(";")[0].trim(),!/^image\//i.test(u)))return null;l=Buffer.from(await C.arrayBuffer())}else{let _=Tqe.isAbsolute(r)?r:Tqe.join(i.baseDir,r);if(l=await PVn.promises.readFile(_),u=OVn(_),!u.startsWith("image/"))return null}return l.byteLength>i.maxImageBytes||l.byteLength>o?null:`data:${u};base64,${l.toString("base64")}`}catch{return null}}t(RVn,"resolveOne");async function MVn(r,i={}){let o={baseDir:i.baseDir??process.cwd(),fetchImpl:i.fetchImpl??fetch,maxImageBytes:i.maxImageBytes??4194304,timeoutMs:i.timeoutMs??15e3},l=i.maxTotalBytes??20*1024*1024,u=/<img\b[^>]*?\bsrc\s*=\s*(["'])(.*?)\1/gi,_=[...r.matchAll(u)];if(_.length===0)return{html:r,inlined:0,skipped:0};let h=0,C=0,I=0,N=[];for(let j of _){let ne=j[0],re=j[1],se=j[2],Pe=await RVn(se,o,l-h);if(Pe==null){se&&!se.startsWith("data:")&&I++;continue}h+=Math.ceil((Pe.length-13)*.75);let Qe=ne.replace(`=${re}${se}${re}`,`=${re}${Pe}${re}`);N.push({index:j.index??0,length:ne.length,text:Qe}),C++}if(N.length===0)return{html:r,inlined:0,skipped:I};let M="",J=0;for(let j of N)M+=r.slice(J,j.index)+j.text,J=j.index+j.length;return M+=r.slice(J),{html:M,inlined:C,skipped:I}}t(MVn,"inlineHtmlImages")});var D4t=Dt(ML=>{"use strict";var BVn=ML&&ML.__createBinding||(Object.create?(function(r,i,o,l){l===void 0&&(l=o);var u=Object.getOwnPropertyDescriptor(i,o);(!u||("get"in u?!i.__esModule:u.writable||u.configurable))&&(u={enumerable:!0,get:t(function(){return i[o]},"get")}),Object.defineProperty(r,l,u)}):(function(r,i,o,l){l===void 0&&(l=o),r[l]=i[o]})),FVn=ML&&ML.__setModuleDefault||(Object.create?(function(r,i){Object.defineProperty(r,"default",{enumerable:!0,value:i})}):function(r,i){r.default=i}),I4t=ML&&ML.__importStar||(function(){var r=t(function(i){return r=Object.getOwnPropertyNames||function(o){var l=[];for(var u in o)Object.prototype.hasOwnProperty.call(o,u)&&(l[l.length]=u);return l},r(i)},"ownKeys");return function(i){if(i&&i.__esModule)return i;var o={};if(i!=null)for(var l=r(i),u=0;u<l.length;u++)l[u]!=="default"&&BVn(o,i,l[u]);return FVn(o,i),o}})();Object.defineProperty(ML,"__esModule",{value:!0});ML.buildPublishArtifactTool=$Vn;var LVn=I4t(Fa("fs")),LY=I4t(Fa("path")),wqe=OL(),jVn=ACe();function $Vn(r){return{name:"publish_artifact",description:'Publish a file from the workspace as a shareable Bandit Artifact and return a public URL anyone can open. Use this when the user asks to "publish", "share", or "make an artifact" of a file \u2014 write the file first, then call this with its path. Cloud feature.',parameters:[{name:"path",description:'Workspace-relative (or absolute) path to the file to publish, e.g. "README.md".',required:!0},{name:"scope",description:'Visibility: "private" (default, only the user) or "team" (shared with their team). The link works for anyone either way.',required:!1}],async execute(i,o){let l=(i.path??"").trim();if(!l)return{output:"Error: the `path` parameter is required.",isError:!0};let u=o.workspaceRoot??process.cwd(),_=LY.isAbsolute(l)?l:LY.join(u,l),h;try{h=await LVn.promises.readFile(_)}catch{return{output:`Error: can't read "${l}". Write the file first, then publish it.`,isError:!0}}try{let C=(i.scope??"").trim().toLowerCase()==="team"?"team":void 0,I=(0,wqe.guessContentType)(LY.basename(_)),N=new Uint8Array(h),M="";if(I==="text/html"){let Pe=await(0,jVn.inlineHtmlImages)(h.toString("utf8"),{baseDir:LY.dirname(_)});N=new Uint8Array(Buffer.from(Pe.html,"utf8")),Pe.inlined&&(M=` Inlined ${Pe.inlined} image(s).`),Pe.skipped&&(M+=` (${Pe.skipped} image(s) couldn't be inlined \u2014 unreachable, not an image, or too large.)`)}let J=await(0,wqe.publishArtifact)({s3ApiBaseUrl:r.s3ApiBaseUrl,authBaseUrl:r.authBaseUrl,token:r.token,scope:C,content:N,filename:LY.basename(_),contentType:I}),j=LY.basename(_),ne=(0,wqe.artifactKeyFromUrl)(J.url),re=r.webBaseUrl?`${r.webBaseUrl.replace(/\/$/,"")}/artifacts?a=${encodeURIComponent(ne)}`:null,se=re?` The user can open and manage it here (signs them in if needed): ${re}`:"";return{output:`Published "${j}"${C==="team"?" to the team":" (private)"}.`+M+se+` To create an external link anyone can open without signing in, call share_artifact with url "${J.url}".`}}catch(C){return{output:`Error publishing artifact: ${C instanceof Error?C.message:String(C)}`,isError:!0}}}}}t($Vn,"buildPublishArtifactTool")});var P4t=Dt(kqe=>{"use strict";Object.defineProperty(kqe,"__esModule",{value:!0});kqe.buildShareArtifactTool=QVn;var UVn=OL();function zVn(r){if(!r)return;let i=/^(\d+)\s*(d|h|m)?$/i.exec(r.trim());if(!i)return;let o=parseInt(i[1],10),l=(i[2]??"m").toLowerCase();return l==="d"?o*24*60:l==="h"?o*60:o}t(zVn,"parseExpiryMinutes");function QVn(r){return{name:"share_artifact",description:'Create an EXTERNAL share link for an artifact you already published \u2014 a URL anyone can open without a Bandit account. Use when the user asks to "share externally", "send this to someone outside", or "make a link for a client". Pass the artifact URL returned by publish_artifact (or its key). The link auto-expires and can be revoked later. Cloud feature.',parameters:[{name:"url",description:"The artifact URL from publish_artifact (or its object key). This must be an artifact you own.",required:!0},{name:"expires",description:'Optional lifetime like "1d", "7d" (default), or "30d" (max). Prefer the shortest window that fits.',required:!1}],async execute(i){let o=(i.url??"").trim();if(!o)return{output:"Error: the `url` parameter is required (the artifact URL or key).",isError:!0};try{let l=await(0,UVn.createShareLink)({s3ApiBaseUrl:r.s3ApiBaseUrl,authBaseUrl:r.authBaseUrl,token:r.token,keyOrUrl:o,expiryMinutes:zVn(i.expires),fetchImpl:r.fetchImpl}),u=(l.expiresAt||"").replace("T"," ").slice(0,16);return{output:`External share link${u?` (expires ${u} UTC)`:""} \u2014 anyone with it can view:
1543
+ ${r}`}t(Eqe,"ensureMobileFriendlyHtml");async function gVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=r.contentType??Cqe(r.filename),u=typeof r.content=="string"&&/html/.test(l)?Eqe(r.content):r.content,_=typeof u=="string"?new TextEncoder().encode(u):u,h=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),{body:C,contentType:I}=k4t("File",r.filename,l,_),N=r.scope==="team"?"?scope=team":"",M=Math.max(1,r.maxAttempts??3),J=r.retryDelayMs??300,j=new Error("artifact upload failed");for(let ne=1;ne<=M;ne++){let re;try{re=await i(`${o}/api/artifact${N}`,{method:"POST",headers:{authorization:`Bearer ${h}`,"content-type":I},body:C})}catch(Pe){if(j=new Error(`artifact upload failed: ${Pe instanceof Error?Pe.message:String(Pe)}`),ne<M){await w4t(J*ne);continue}throw j}if(re.ok){let Pe=await re.json();if(!Pe.url)throw new Error("artifact upload succeeded but no URL was returned");return{url:Pe.url,key:Pe.key??"",size:Pe.size??_.byteLength}}let se="";try{se=(await re.json())?.message??""}catch{}if(j=new Error(`artifact upload failed: HTTP ${re.status}${se?` \u2014 ${se}`:""}`),re.status>=500&&ne<M){await w4t(J*ne);continue}throw j}throw j}t(gVn,"publishArtifact");function w4t(r){return r>0?new Promise(i=>setTimeout(i,r)):Promise.resolve()}t(w4t,"sleep");function wM(r){let i=/[?&]a=([^&#]+)/.exec(r);if(i)try{return decodeURIComponent(i[1])}catch{return i[1]}let o="/api/artifact/",l=r.indexOf(o);return(l>=0?r.slice(l+o.length):r).split("/").map(_=>{try{return decodeURIComponent(_)}catch{return _}}).join("/")}t(wM,"artifactKeyFromUrl");async function hVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),u=await i(`${o}/api/artifact/mine`,{headers:{authorization:`Bearer ${l}`}});if(!u.ok)throw new Error(`could not list artifacts: HTTP ${u.status}`);return(await u.json()).artifacts??[]}t(hVn,"listArtifacts");async function yVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),u=wM(r.keyOrUrl).split("/").map(encodeURIComponent).join("/"),_=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),h=await i(`${o}/api/artifact/${u}`,{method:"DELETE",headers:{authorization:`Bearer ${_}`}});if(!h.ok)throw h.status===404?new Error(`no artifact found for "${r.keyOrUrl}" (or it isn't yours)`):new Error(`could not delete artifact: HTTP ${h.status}`)}t(yVn,"deleteArtifact");async function vVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/share`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l,expiryMinutes:r.expiryMinutes})});if(!_.ok){let C="";try{C=(await _.json())?.message??""}catch{}throw new Error(`could not create share link: HTTP ${_.status}${C?` \u2014 ${C}`:""}`)}let h=await _.json();if(!h.url)throw new Error("share link created but no URL was returned");return{url:h.url,token:h.token??"",expiresAt:h.expiresAt??""}}t(vVn,"createShareLink");async function AVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/scope`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l,scope:r.scope})});if(!_.ok){let C="";try{C=(await _.json())?.message??""}catch{}throw new Error(`could not change scope: HTTP ${_.status}${C?` \u2014 ${C}`:""}`)}let h=await _.json();return{key:h.key??l,url:h.url??"",scope:h.scope??r.scope}}t(AVn,"setArtifactScope");async function bVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/restore`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l})});if(!_.ok){let h="";try{h=(await _.json())?.message??""}catch{}throw new Error(`could not restore artifact: HTTP ${_.status}${h?` \u2014 ${h}`:""}`)}}t(bVn,"restoreArtifact");async function SVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/archive`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l})});if(!_.ok){let h="";try{h=(await _.json())?.message??""}catch{}throw new Error(`could not archive artifact: HTTP ${_.status}${h?` \u2014 ${h}`:""}`)}}t(SVn,"archiveArtifact");async function CVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=l.split("/").map(encodeURIComponent).join("/"),_=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),h=await i(`${o}/api/artifact/${u}`,{headers:{authorization:`Bearer ${_}`}});if(!h.ok){let N="";try{N=(await h.json())?.message??""}catch{}throw new Error(`could not fetch artifact: HTTP ${h.status}${N?` \u2014 ${N}`:""}`)}let C=h.headers.get("content-type")??"application/octet-stream",I=await h.text();return{key:l,contentType:C,content:I}}t(CVn,"getArtifact");async function EVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=l.split("/").map(encodeURIComponent).join("/"),_=r.filename??(l.split("/").pop()||"artifact"),h=r.contentType??Cqe(_),C=typeof r.content=="string"&&/html/.test(h)?Eqe(r.content):r.content,I=typeof C=="string"?new TextEncoder().encode(C):C,N=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),{body:M,contentType:J}=k4t("File",_,h,I),j=await i(`${o}/api/artifact/${u}`,{method:"PUT",headers:{authorization:`Bearer ${N}`,"content-type":J},body:M});if(!j.ok){let re="";try{re=(await j.json())?.message??""}catch{}throw new Error(`could not update artifact: HTTP ${j.status}${re?` \u2014 ${re}`:""}`)}let ne=await j.json();return{url:ne.url??r.keyOrUrl,key:ne.key??l,size:ne.size??I.byteLength}}t(EVn,"updateArtifact");async function TVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/share/email`,{method:"POST",headers:{authorization:`Bearer ${u}`,"content-type":"application/json"},body:JSON.stringify({key:l,to:r.to,expiryMinutes:r.expiryMinutes,message:r.message})});if(!_.ok){let C="";try{C=(await _.json())?.message??""}catch{}throw new Error(`could not email share link: HTTP ${_.status}${C?` \u2014 ${C}`:""}`)}let h=await _.json();if(!h.url)throw new Error("share link created but no URL was returned");return{url:h.url,token:h.token??"",expiresAt:h.expiresAt??"",emailed:h.emailed??!1}}t(TVn,"emailShareLink");async function wVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),u=await i(`${o}/api/artifact/share/${encodeURIComponent(r.shareToken)}`,{method:"DELETE",headers:{authorization:`Bearer ${l}`}});if(!u.ok)throw u.status===404?new Error("no matching share link (or it isn't yours)"):new Error(`could not revoke share link: HTTP ${u.status}`)}t(wVn,"revokeShareLink");async function kVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=wM(r.keyOrUrl),u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/shares?key=${encodeURIComponent(l)}`,{headers:{authorization:`Bearer ${u}`}});if(!_.ok)throw new Error(`could not list share links: HTTP ${_.status}`);return(await _.json()).shares??[]}t(kVn,"listShareLinks");async function xVn(r){let i=r.fetchImpl??fetch,o=r.s3ApiBaseUrl.replace(/\/$/,""),l=r.scope==="team"?"?scope=team":"",u=await xx(r.token,{authBaseUrl:r.authBaseUrl,fetchImpl:i}),_=await i(`${o}/api/artifact/mine${l}`,{method:"DELETE",headers:{authorization:`Bearer ${u}`}});if(!_.ok)throw new Error(`could not clear artifacts: HTTP ${_.status}`);return(await _.json()).deleted??0}t(xVn,"clearArtifacts")});var ACe=Dt(RL=>{"use strict";var IVn=RL&&RL.__createBinding||(Object.create?(function(r,i,o,l){l===void 0&&(l=o);var u=Object.getOwnPropertyDescriptor(i,o);(!u||("get"in u?!i.__esModule:u.writable||u.configurable))&&(u={enumerable:!0,get:t(function(){return i[o]},"get")}),Object.defineProperty(r,l,u)}):(function(r,i,o,l){l===void 0&&(l=o),r[l]=i[o]})),DVn=RL&&RL.__setModuleDefault||(Object.create?(function(r,i){Object.defineProperty(r,"default",{enumerable:!0,value:i})}):function(r,i){r.default=i}),x4t=RL&&RL.__importStar||(function(){var r=t(function(i){return r=Object.getOwnPropertyNames||function(o){var l=[];for(var u in o)Object.prototype.hasOwnProperty.call(o,u)&&(l[l.length]=u);return l},r(i)},"ownKeys");return function(i){if(i&&i.__esModule)return i;var o={};if(i!=null)for(var l=r(i),u=0;u<l.length;u++)l[u]!=="default"&&IVn(o,i,l[u]);return DVn(o,i),o}})();Object.defineProperty(RL,"__esModule",{value:!0});RL.inlineHtmlImages=MVn;var PVn=x4t(Fa("fs")),Tqe=x4t(Fa("path")),NVn={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml",".bmp":"image/bmp",".ico":"image/x-icon",".avif":"image/avif"};function OVn(r){return NVn[Tqe.extname(r).toLowerCase()]??"application/octet-stream"}t(OVn,"mimeFromPath");async function RVn(r,i,o){if(!r||r.startsWith("data:"))return null;try{let l,u;if(/^https?:\/\//i.test(r)){let _=new AbortController,h=setTimeout(()=>_.abort(),i.timeoutMs),C;try{C=await i.fetchImpl(r,{signal:_.signal,redirect:"follow"})}finally{clearTimeout(h)}if(!C.ok||(u=(C.headers.get("content-type")??"").split(";")[0].trim(),!/^image\//i.test(u)))return null;l=Buffer.from(await C.arrayBuffer())}else{let _=Tqe.isAbsolute(r)?r:Tqe.join(i.baseDir,r);if(l=await PVn.promises.readFile(_),u=OVn(_),!u.startsWith("image/"))return null}return l.byteLength>i.maxImageBytes||l.byteLength>o?null:`data:${u};base64,${l.toString("base64")}`}catch{return null}}t(RVn,"resolveOne");async function MVn(r,i={}){let o={baseDir:i.baseDir??process.cwd(),fetchImpl:i.fetchImpl??fetch,maxImageBytes:i.maxImageBytes??4194304,timeoutMs:i.timeoutMs??15e3},l=i.maxTotalBytes??20*1024*1024,u=/<img\b[^>]*?\bsrc\s*=\s*(["'])(.*?)\1/gi,_=[...r.matchAll(u)];if(_.length===0)return{html:r,inlined:0,skipped:0};let h=0,C=0,I=0,N=[];for(let j of _){let ne=j[0],re=j[1],se=j[2],Pe=await RVn(se,o,l-h);if(Pe==null){se&&!se.startsWith("data:")&&I++;continue}h+=Math.ceil((Pe.length-13)*.75);let Qe=ne.replace(`=${re}${se}${re}`,`=${re}${Pe}${re}`);N.push({index:j.index??0,length:ne.length,text:Qe}),C++}if(N.length===0)return{html:r,inlined:0,skipped:I};let M="",J=0;for(let j of N)M+=r.slice(J,j.index)+j.text,J=j.index+j.length;return M+=r.slice(J),{html:M,inlined:C,skipped:I}}t(MVn,"inlineHtmlImages")});var D4t=Dt(ML=>{"use strict";var BVn=ML&&ML.__createBinding||(Object.create?(function(r,i,o,l){l===void 0&&(l=o);var u=Object.getOwnPropertyDescriptor(i,o);(!u||("get"in u?!i.__esModule:u.writable||u.configurable))&&(u={enumerable:!0,get:t(function(){return i[o]},"get")}),Object.defineProperty(r,l,u)}):(function(r,i,o,l){l===void 0&&(l=o),r[l]=i[o]})),FVn=ML&&ML.__setModuleDefault||(Object.create?(function(r,i){Object.defineProperty(r,"default",{enumerable:!0,value:i})}):function(r,i){r.default=i}),I4t=ML&&ML.__importStar||(function(){var r=t(function(i){return r=Object.getOwnPropertyNames||function(o){var l=[];for(var u in o)Object.prototype.hasOwnProperty.call(o,u)&&(l[l.length]=u);return l},r(i)},"ownKeys");return function(i){if(i&&i.__esModule)return i;var o={};if(i!=null)for(var l=r(i),u=0;u<l.length;u++)l[u]!=="default"&&BVn(o,i,l[u]);return FVn(o,i),o}})();Object.defineProperty(ML,"__esModule",{value:!0});ML.buildPublishArtifactTool=$Vn;var LVn=I4t(Fa("fs")),LY=I4t(Fa("path")),wqe=OL(),jVn=ACe();function $Vn(r){return{name:"publish_artifact",description:'Publish a file from the workspace as a shareable Bandit Artifact and return a public URL anyone can open. Use this when the user asks to "publish", "share", or "make an artifact" of a file \u2014 write the file first, then call this with its path. Cloud feature.',parameters:[{name:"path",description:'Workspace-relative (or absolute) path to the file to publish, e.g. "README.md".',required:!0},{name:"scope",description:'Visibility: "private" (default, only the user) or "team" (shared with their team). The link works for anyone either way.',required:!1}],async execute(i,o){let l=(i.path??"").trim();if(!l)return{output:"Error: the `path` parameter is required.",isError:!0};let u=o.workspaceRoot??process.cwd(),_=LY.isAbsolute(l)?l:LY.join(u,l),h;try{h=await LVn.promises.readFile(_)}catch{return{output:`Error: can't read "${l}". Write the file first, then publish it.`,isError:!0}}try{let C=(i.scope??"").trim().toLowerCase()==="team"?"team":void 0,I=(0,wqe.guessContentType)(LY.basename(_)),N=new Uint8Array(h),M="";if(I==="text/html"){let Pe=await(0,jVn.inlineHtmlImages)(h.toString("utf8"),{baseDir:LY.dirname(_)});N=new Uint8Array(Buffer.from(Pe.html,"utf8")),Pe.inlined&&(M=` Inlined ${Pe.inlined} image(s).`),Pe.skipped&&(M+=` (${Pe.skipped} image(s) couldn't be inlined \u2014 unreachable, not an image, or too large.)`)}let J=await(0,wqe.publishArtifact)({s3ApiBaseUrl:r.s3ApiBaseUrl,authBaseUrl:r.authBaseUrl,token:r.token,scope:C,content:N,filename:LY.basename(_),contentType:I}),j=LY.basename(_),ne=(0,wqe.artifactKeyFromUrl)(J.url),re=r.webBaseUrl?`${r.webBaseUrl.replace(/\/$/,"")}/artifacts?a=${encodeURIComponent(ne)}`:null,se=re?` The user can open and manage it here (signs them in if needed): ${re}`:"";return{output:`Published "${j}"${C==="team"?" to the team":" (private)"}.`+M+se+` To create an external link anyone can open without signing in, call share_artifact with url "${J.url}".`}}catch(C){return{output:`Error publishing artifact: ${C instanceof Error?C.message:String(C)}`,isError:!0}}}}}t($Vn,"buildPublishArtifactTool")});var P4t=Dt(kqe=>{"use strict";Object.defineProperty(kqe,"__esModule",{value:!0});kqe.buildShareArtifactTool=QVn;var UVn=OL();function zVn(r){if(!r)return;let i=/^(\d+)\s*(d|h|m)?$/i.exec(r.trim());if(!i)return;let o=parseInt(i[1],10),l=(i[2]??"m").toLowerCase();return l==="d"?o*24*60:l==="h"?o*60:o}t(zVn,"parseExpiryMinutes");function QVn(r){return{name:"share_artifact",description:'Create an EXTERNAL share link for an artifact you already published \u2014 a URL anyone can open without a Bandit account. Use when the user asks to "share externally", "send this to someone outside", or "make a link for a client". Pass the artifact URL returned by publish_artifact (or its key). The link auto-expires and can be revoked later. Cloud feature.',parameters:[{name:"url",description:"The artifact URL from publish_artifact (or its object key). This must be an artifact you own.",required:!0},{name:"expires",description:'Optional lifetime like "1d", "7d" (default), or "30d" (max). Prefer the shortest window that fits.',required:!1}],async execute(i){let o=(i.url??"").trim();if(!o)return{output:"Error: the `url` parameter is required (the artifact URL or key).",isError:!0};try{let l=await(0,UVn.createShareLink)({s3ApiBaseUrl:r.s3ApiBaseUrl,authBaseUrl:r.authBaseUrl,token:r.token,keyOrUrl:o,expiryMinutes:zVn(i.expires),fetchImpl:r.fetchImpl}),u=(l.expiresAt||"").replace("T"," ").slice(0,16);return{output:`External share link${u?` (expires ${u} UTC)`:""} \u2014 anyone with it can view:
1544
1544
  ${l.url}
1545
1545
  Revoke it later with this token: ${l.token}`}}catch(l){return{output:`Error creating share link: ${l instanceof Error?l.message:String(l)}`,isError:!0}}}}}t(QVn,"buildShareArtifactTool")});var N4t=Dt(xqe=>{"use strict";Object.defineProperty(xqe,"__esModule",{value:!0});xqe.buildListArtifactsTool=HVn;var qVn=OL();function JVn(r){return r<1024?`${r} B`:r<1024*1024?`${(r/1024).toFixed(1)} KB`:`${(r/1024/1024).toFixed(1)} MB`}t(JVn,"humanSize");function HVn(r){return{name:"list_artifacts",description:`List the user's published Bandit Artifacts (their private ones and their team's shared ones), newest first, with each artifact's name, scope, size, and URL. Use this to answer "what have I published?" or to find an artifact's URL before sharing or deleting it. Cloud feature.`,parameters:[{name:"scope",description:`Optional filter: "private" (only yours), "team" (your team's shared), or omit for both.`,required:!1}],async execute(i){try{let o=await(0,qVn.listArtifacts)({s3ApiBaseUrl:r.s3ApiBaseUrl,authBaseUrl:r.authBaseUrl,token:r.token,fetchImpl:r.fetchImpl}),l=(i.scope??"").trim().toLowerCase(),u=l==="private"?o.filter(h=>h.scope!=="team"):l==="team"?o.filter(h=>h.scope==="team"):o;if(u.length===0)return{output:"No artifacts found. Publish one with publish_artifact."};let _=u.map(h=>{let C=h.key.split("/").pop()??h.key,I=(h.lastModified||"").replace("T"," ").slice(0,16);return`- ${C} [${h.scope==="team"?"team":"private"}] ${JVn(h.size)} ${I} \u2014 ${h.url}`});return{output:`${u.length} artifact(s):
1546
1546
  ${_.join(`
@@ -2096,7 +2096,7 @@ Upgrade it with:
2096
2096
  `)),l}async function oce(r,i){let o=MRt(r);if(o===null)return process.stdout.write(z.dim("No graph run to resume. Start one with: ")+z.cyan("BANDIT_GRAPH=1 bandit graph demo")+z.dim(" or ")+z.cyan('bandit graph plan "\u2026" --run')+`
2097
2097
  `),null;if(!o.ok)return process.stdout.write(z.red(`Can't resume: ${o.error}
2098
2098
  `)),null;let{spec:l,checkpoint:u,nodePrompts:_}=o.file,h=l.nodes.filter(I=>!_[I.id]).map(I=>I.id);if(h.length>0)return process.stdout.write(z.red(`Can't resume: run file has no prompts for: ${h.join(", ")}
2099
- `)),null;let C=JCe(_,i);return J$({cwd:r,spec:l,executors:C,nodePrompts:_,resumeFrom:u})}var q$,h6,qY=Gi(()=>{"use strict";q$=Eo(JC(),1);sv();h6=["read_file","list_files","ls","search_code","find_directory","glob","web_fetch","web_search","read_pdf","read_memory","list_artifacts","fetch_image"];t(QCe,"graphRunPath");t(RRt,"saveRunFile");t(MRt,"loadRunFile");t(JCe,"executorsFromPrompts");t(J$,"runSpecLive");t(oce,"resumeSpecLive")});var cce=Dt((XEr,yXn)=>{yXn.exports={name:"@burtson-labs/bandit-stealth-cli",version:"1.7.438",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"}}});import*as GJ from"child_process";import*as N1 from"fs";import*as Ow from"path";function vXn(r){let i=process.env.HOME||"";return i&&r.startsWith(i)?`~${r.slice(i.length)}`:r}function AXn(){return new Promise(r=>{let i=GJ.spawn("npm",["view",HCe,"version"],{shell:!1,stdio:["ignore","pipe","pipe"]}),o="";i.stdout?.on("data",u=>{o+=u.toString()});let l=setTimeout(()=>{i.kill("SIGTERM"),r(null)},8e3);i.on("close",u=>{clearTimeout(l),r(u===0?o.trim():null)}),i.on("error",()=>{clearTimeout(l),r(null)})})}function SXn(r){return(r??"").trim().split(/\s+/).filter(Boolean).some(i=>bXn.has(i.toLowerCase()))}function CXn(r,i){let o=[...r].map(h=>h.role).lastIndexOf("user");if(o===-1)return null;let l=r[o],u=typeof l.content=="string"?l.content:"",_=i&&i.trim()?i.trim():u;return _?{prompt:_,trimmedConversation:r.slice(0,o)}:null}function EXn(r,i){let o=t(N=>N.replace(/[^0-9.]/g,"").split(".").map(M=>parseInt(M,10)||0),"parse"),[l,u,_]=o(r),[h,C,I]=o(i);return l!==h?l<h?-1:1:u!==C?u<C?-1:1:_!==I?_<I?-1:1:0}function wXn(r){return JY.find(i=>i.name===r)}function kXn(){let r=JY.map(i=>` ${z.cyan("/"+i.name.padEnd(14))} ${z.dim(i.description)}`);return[z.bold("All slash commands:"),...r,"",z.dim("Tip: prefix any file with @ to pin it, or run /help permissions for the permission model.")].join(`
2099
+ `)),null;let C=JCe(_,i);return J$({cwd:r,spec:l,executors:C,nodePrompts:_,resumeFrom:u})}var q$,h6,qY=Gi(()=>{"use strict";q$=Eo(JC(),1);sv();h6=["read_file","list_files","ls","search_code","find_directory","glob","web_fetch","web_search","read_pdf","read_memory","list_artifacts","fetch_image"];t(QCe,"graphRunPath");t(RRt,"saveRunFile");t(MRt,"loadRunFile");t(JCe,"executorsFromPrompts");t(J$,"runSpecLive");t(oce,"resumeSpecLive")});var cce=Dt((XEr,yXn)=>{yXn.exports={name:"@burtson-labs/bandit-stealth-cli",version:"1.7.439",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"}}});import*as GJ from"child_process";import*as N1 from"fs";import*as Ow from"path";function vXn(r){let i=process.env.HOME||"";return i&&r.startsWith(i)?`~${r.slice(i.length)}`:r}function AXn(){return new Promise(r=>{let i=GJ.spawn("npm",["view",HCe,"version"],{shell:!1,stdio:["ignore","pipe","pipe"]}),o="";i.stdout?.on("data",u=>{o+=u.toString()});let l=setTimeout(()=>{i.kill("SIGTERM"),r(null)},8e3);i.on("close",u=>{clearTimeout(l),r(u===0?o.trim():null)}),i.on("error",()=>{clearTimeout(l),r(null)})})}function SXn(r){return(r??"").trim().split(/\s+/).filter(Boolean).some(i=>bXn.has(i.toLowerCase()))}function CXn(r,i){let o=[...r].map(h=>h.role).lastIndexOf("user");if(o===-1)return null;let l=r[o],u=typeof l.content=="string"?l.content:"",_=i&&i.trim()?i.trim():u;return _?{prompt:_,trimmedConversation:r.slice(0,o)}:null}function EXn(r,i){let o=t(N=>N.replace(/[^0-9.]/g,"").split(".").map(M=>parseInt(M,10)||0),"parse"),[l,u,_]=o(r),[h,C,I]=o(i);return l!==h?l<h?-1:1:u!==C?u<C?-1:1:_!==I?_<I?-1:1:0}function wXn(r){return JY.find(i=>i.name===r)}function kXn(){let r=JY.map(i=>` ${z.cyan("/"+i.name.padEnd(14))} ${z.dim(i.description)}`);return[z.bold("All slash commands:"),...r,"",z.dim("Tip: prefix any file with @ to pin it, or run /help permissions for the permission model.")].join(`
2100
2100
  `)}function xXn(){return[z.bold("Permission choices"),"",` ${z.accent("allow once")} ${z.dim("Run only this call.")}`,` ${z.accent("allow turn")} ${z.dim("Allow calls like this until the agent finishes the current turn.")}`,` ${z.dim(" ")}${z.dim("Best pick when the model is making a batch of similar edits.")}`,` ${z.accent("allow session")} ${z.dim("Allow them until you exit Bandit.")}`,` ${z.accent("always allow")} ${z.dim("Save the rule to .bandit/settings.json so it survives restarts.")}`,` ${z.accent("deny")} ${z.dim("Block the call. Bandit should not retry it.")}`,` ${z.accent("deny + note")} ${z.dim("Block it and tell Bandit what to do instead.")}`,"",z.dim(" The card shows the exact rule each choice stores, under the highlighted"),z.dim(" option. For shell commands the rule covers a command shape \u2014 approving"),z.dim(" `git status` grants `git status \u2026`, not every command."),"",z.bold("Permission modes")+z.dim(" \u2014 /auto to change"),` ${z.accent("ask")} ${z.dim("Every non-allowlisted call prompts. Default.")}`,` ${z.accent("auto")} ${z.dim("Routine work runs unprompted: reading, editing files in this")}`,` ${z.dim(" ")}${z.dim("project, running builds and tests. Everything else still asks.")}`,` ${z.accent("dangerous")} ${z.dim("Nothing prompts. CI and sandboxes only; not settable from /auto.")}`,"",z.bold("What auto mode never does without asking"),z.dim(" Deleting files \xB7 writing outside the project \xB7 force-push and history"),z.dim(" rewrites \xB7 global installs and publishes \xB7 touching credential files \xB7"),z.dim(" sending data off the machine \xB7 mutating a connected service."),z.dim(" That floor holds even if a saved allow rule would cover the call."),"",z.dim(" /permissions review what ran unattended and which grants are active"),z.dim(" /doctor explain the current setup and next best actions")].join(`
2101
2101
  `)}function IXn(){let r=[z.bold("Bandit commands"),z.dim("Use /help all for the full list, /help permissions for approval choices."),""],i=new Set;for(let l of TXn){let u=l.names.map(_=>wXn(_)).filter(_=>!!_);if(u.length!==0){r.push(z.bold(l.title));for(let _ of u)i.add(_.name),r.push(` ${z.cyan("/"+_.name.padEnd(14))} ${z.dim(_.description)}`);r.push("")}}let o=JY.filter(l=>!i.has(l.name)&&l.name!=="quit");return o.length>0&&(r.push(z.dim(`Also available: ${o.map(l=>"/"+l.name).join(", ")}`)),r.push("")),r.push(z.dim("Fast path: /doctor \u2192 /connect or /init \u2192 ask for the change \u2192 /review \u2192 /test \u2192 /commit")),r.join(`
2102
2102
  `)}function DXn(r){let i=[],o=r.accomplishments,l=Math.max(1,Math.round((Date.now()-(r.firstSeenAt??Date.now()))/864e5)),u=r.ai?.storyline&&r.ai.storyline.length>0?r.ai.storyline:r.localStory;if(u.length>0){let N=Math.min(process.stdout.columns||80,100),M=Math.max(40,N-4);i.push(z.bold("Your story")+z.dim(` \xB7 ${r.ai?.storyline?.length?r.ai.modelLabel:"local synthesis"}`)),i.push("");for(let J of u){let j=J.replace(/\s+/g," ").trim().split(" "),ne="";for(let re of j)ne.length===0?ne=re:ne.length+1+re.length<=M?ne+=" "+re:(i.push(" "+ne),ne=re);ne&&i.push(" "+ne),i.push("")}}if(i.push(z.bold("How you use Bandit")),i.push(""),i.push(` ${z.dim("sessions ")} ${z.accent(String(r.sessions.length))} ${z.dim("over "+l+" day"+(l===1?"":"s"))}`),i.push(` ${z.dim("prompts ")} ${z.accent(String(r.totalPrompts))} ${z.dim("~"+(r.totalApproxTokens>=1e3?(r.totalApproxTokens/1e3).toFixed(1)+"K":r.totalApproxTokens)+" tokens")}`),(r.streak.current>0||r.streak.longest>0)&&i.push(` ${z.dim("streak ")} ${z.accent(r.streak.current+" day"+(r.streak.current===1?"":"s"))} ${z.dim("(longest "+r.streak.longest+")")}`),r.peakDay&&i.push(` ${z.dim("peak day ")} ${z.accent(r.peakDay.date)} ${z.dim(r.peakDay.prompts+" prompts")}`),i.push(""),i.push(z.bold("What got done")),i.push(` ${z.dim("files touched ")} ${z.accent(String(o.filesTouched))} ${z.dim("("+o.filesWritten+" written, "+o.editsApplied+" edited)")}`),o.gitOperations>0&&i.push(` ${z.dim("git ops ")} ${z.accent(String(o.gitOperations))} ${z.dim("("+o.commitsMade+" commits)")}`),o.testsRun>0&&i.push(` ${z.dim("tests run ")} ${z.accent(String(o.testsRun))}`),o.subagentsSpawned>0&&i.push(` ${z.dim("subagents ")} ${z.accent(String(o.subagentsSpawned))}`),o.languages.length>0){let N=o.languages.slice(0,5).map(M=>`${M.label} ${z.dim("("+M.count+")")}`).join(z.dim(", "));i.push(` ${z.dim("languages ")} ${N}`)}if(r.work.themes.length>0){i.push(""),i.push(z.bold("Bigger arcs"));for(let N of r.work.themes.slice(0,4)){let M=[`${N.turns} turn${N.turns===1?"":"s"}`,N.filesTouched>0?`${N.filesTouched} files`:"",N.testsRun>0?`${N.testsRun} tests`:"",N.externalActions>0?`${N.externalActions} external`:"",N.subagentsSpawned>0?`${N.subagentsSpawned} subagents`:""].filter(Boolean).join(", ");i.push(` ${z.cyan(N.title)} ${z.dim(M?"\u2014 "+M:"")}`),N.outcomes.length>0&&i.push(z.dim(` ${N.outcomes[0]}`)),N.sampleTitles.length>0&&i.push(z.dim(` ${N.sampleTitles[0]}`))}}if(r.work.highlights.length>0){i.push(""),i.push(z.bold("Largest work highlights"));for(let N of r.work.highlights.slice(0,5))i.push(` ${z.cyan(N.date)} ${z.accent(N.area)} ${z.dim("\xB7 "+N.category)}`),i.push(z.dim(` ${N.title}`)),i.push(z.dim(` ${N.summary}`)),N.outcome&&i.push(z.dim(` ${N.outcome}`))}if(o.topFiles.length>0){i.push(""),i.push(z.bold("Most-touched files"));for(let N of o.topFiles.slice(0,5))i.push(` ${z.cyan(N.path)} ${z.dim("\xD7"+N.touches)}`)}let _=[...r.toolStats.entries()].map(([N,M])=>({name:N,calls:M.calls,errors:M.errors,rate:M.calls>0?M.errors/M.calls:0})).sort((N,M)=>M.calls-N.calls).slice(0,6);if(_.length>0){i.push(""),i.push(z.bold("Top tools"));for(let N of _){let M=Math.round(N.rate*100),J=N.calls>=5&&M>=25?" "+z.yellow("\u26A0 "+M+"% error rate"):"";i.push(` ${z.cyan(N.name.padEnd(16))} ${z.accent(String(N.calls).padStart(4))} ${z.dim("calls")}${J}`)}}let h=[...r.errorClusters.entries()].flatMap(([N,M])=>M.map(J=>({tool:N,error:J.error,count:J.count}))).sort((N,M)=>M.count-N.count);if(h.length>0){let N=h[0],M=N.error.replace(/\s+/g," ").slice(0,70);i.push(""),i.push(z.bold("Top friction")),i.push(` ${z.cyan(N.tool)} ${z.dim("\xD7"+N.count)} ${z.dim(M+(N.error.length>70?"\u2026":""))}`)}let C=r.sentiment;if(C.satisfied+C.happy+C.excited+C.frustrated+C.unsatisfied>0){let N=[];C.excited>0&&N.push(z.green("excited ")+z.bold(String(C.excited))),C.happy>0&&N.push(z.green("happy ")+z.bold(String(C.happy))),C.satisfied>0&&N.push(z.green("satisfied ")+z.bold(String(C.satisfied)));let M=[];if(C.unsatisfied>0&&M.push(z.yellow("unsatisfied ")+z.bold(String(C.unsatisfied))),C.frustrated>0&&M.push(z.red("frustrated ")+z.bold(String(C.frustrated))),i.push(""),i.push(z.bold("How you felt")),N.length>0&&i.push(` ${N.join(z.dim(" \xB7 "))}`),M.length>0&&i.push(` ${M.join(z.dim(" \xB7 "))}`),C.notable.length>0){i.push(z.dim(" Frustration moments:"));for(let J of C.notable.slice(0,3))i.push(z.dim(' "')+z.dim(J)+z.dim('"'))}}return i.push(""),i.push(z.dim(" Full report (HTML + AI summary): ")+z.cyan("/insights")),i.join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burtson-labs/bandit-stealth-cli",
3
- "version": "1.7.438",
3
+ "version": "1.7.439",
4
4
  "description": "Bandit — a local-first AI coding agent for your terminal. Same runtime as the Bandit Stealth VS Code / Cursor extension.",
5
5
  "keywords": [
6
6
  "ai",