kpilot 0.10.10 → 0.10.45
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/README.md +1 -1
- package/dist/cli.mjs +203 -145
- package/package.json +3 -2
package/dist/cli.mjs
CHANGED
|
@@ -1,26 +1,48 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{access as
|
|
3
|
-
`)
|
|
4
|
-
`),
|
|
5
|
-
`)
|
|
6
|
-
`);
|
|
7
|
-
|
|
8
|
-
`)
|
|
9
|
-
|
|
10
|
-
${s
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`)
|
|
14
|
-
`)
|
|
15
|
-
`),this.
|
|
16
|
-
`)
|
|
17
|
-
|
|
18
|
-
`)
|
|
2
|
+
import{access as Od,appendFile as Id,chmod as $n,mkdir as et,readFile as eo,stat as Bi,writeFile as ke}from"node:fs/promises";import{createHash as Ji,randomUUID as Dd}from"node:crypto";import{homedir as Ki}from"node:os";import L from"node:path";import{spawn as Wi}from"node:child_process";import{createInterface as Gi}from"node:readline/promises";import{emitKeypressEvents as so}from"node:readline";var q={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m"};function B(t,e){return process.stdout.isTTY?`${t}${e}${q.reset}`:e}var io="\x1B[?25l",ao="\x1B[?25h",Ut=class{drawn=0;out;constructor(e){this.out=e}paint(e){this.clear();for(let n of e)this.out.write(`\x1B[2K\r${n}
|
|
3
|
+
`);this.drawn=e.length}clear(){if(this.drawn===0)return;let e=this.drawn;this.drawn=0,this.out.write(`\x1B[${e}A`);for(let n=0;n<e;n+=1)this.out.write("\x1B[2K\r"),n<e-1&&this.out.write("\x1B[1B");e>1&&this.out.write(`\x1B[${e-1}A`)}};function ca(t){let e=t.findIndex(n=>n.default);return e>=0?e:0}function la(t,e){let n=e.trim().toLowerCase();return n?t.filter(r=>r.value.toLowerCase().includes(n)||r.label.toLowerCase().includes(n)||r.description?.toLowerCase().includes(n)||r.aliases?.some(o=>o.toLowerCase().includes(n))):t}function ua(t,e){let n=e.trim();if(!n){let s=t.find(i=>i.default)??null;return s?s.value:null}if(/^\d+$/.test(n)){let s=t[Number(n)-1];return s?s.value:null}let r=n.toLowerCase(),o=t.find(s=>s.value.toLowerCase()===r||s.label.toLowerCase()===r||s.description?.toLowerCase()===r||s.aliases?.some(i=>i.toLowerCase()===r));return o?o.value:null}async function da(t){let e=t.choices;if(e.length===0)return null;console.log(`${B(q.cyan,"\u25C6")} ${t.title}`);for(let[i,a]of e.entries()){let c=`${String(i+1).padStart(2)}.`,l=a.default?B(q.green,"*"):" ",u=a.description?B(q.dim,a.description):"";console.log(` ${B(q.cyan,c)}${l} ${B(q.bold,a.label.padEnd(16))} ${u}`)}let n=e.find(i=>i.default),r=n?`Select \u203A (Enter = ${n.label}) `:"Select \u203A ",o=await t.question(r),s=ua(e,o);return o.trim()&&s===null&&console.log(`${B(q.yellow,"!")} Unknown selection: ${o.trim()}`),s}function co(t,e,n){let r=n?B(q.green,"\u203A"):" ",o=B(q.cyan,`${String(e+1).padStart(2)}.`),s=n?B(q.bold,t.label.padEnd(16)):t.label.padEnd(16),i=t.description?B(q.dim,t.description):"";return` ${r} ${o} ${s} ${i}`}async function ma(t){let e=t.choices;if(e.length===0)return null;let n=ca(e),r=new Ut(process.stdout),o=()=>[`${B(q.cyan,"\u25C6")} ${t.title}`,B(q.dim,"\u2191/\u2193 move \xB7 Enter select \xB7 Esc cancel \xB7 1-9 jump"),...e.map((i,a)=>co(i,a,a===n))];r.paint(o()),t.pauseResume?.pause(),so(process.stdin);let s=process.stdin.isRaw;return process.stdin.setRawMode?.(!0),process.stdin.isPaused()&&process.stdin.resume(),process.stdout.write(io),await new Promise(i=>{let a=!1,c=u=>{if(!a){a=!0,process.stdin.off("keypress",l);try{process.stdin.setRawMode?.(s??!1)}catch{}if(t.pauseResume?.resume(),r.clear(),process.stdout.write(ao),u!==null){let m=e.find(d=>d.value===u);process.stdout.write(`${B(q.green,"\u2713")} ${m?.label??u}
|
|
4
|
+
`)}i(u)}},l=(u,m)=>{if(!(!m||a)){if(m.ctrl&&m.name==="c"){c(null);return}if(m.name==="escape"){c(null);return}if(m.name==="return"||m.name==="enter"){c(e[n]?.value??null);return}if(m.name==="up"||m.name==="k"||m.name==="p"&&m.ctrl){n=(n-1+e.length)%e.length,r.paint(o());return}if(m.name==="down"||m.name==="j"||m.name==="n"&&m.ctrl){n=(n+1)%e.length,r.paint(o());return}if(m.name&&/^[1-9]$/.test(m.name)){let d=Number(m.name)-1;d<e.length&&(n=d,r.paint(o()))}}};process.stdin.on("keypress",l)})}async function pa(t){let e=t.pageSize??5,n=t.initialQuery??"",r=0,o=0,s=()=>la(t.choices,n),i=m=>Math.max(1,Math.ceil(m.length/e)),a=m=>{o=Math.min(o,i(m)-1)},c=new Ut(process.stdout),l=()=>{let m=s();a(m);let d=o*e,p=m.slice(d,d+e),y=m.length?B(q.dim,`\u2191/\u2193 move \xB7 Tab complete \xB7 Enter select \xB7 Esc cancel \xB7 ${m.length} match${m.length===1?"":"es"}`):B(q.dim,"No matches \u2014 keep typing or Esc to cancel");return[`${B(q.cyan,"\u25C6")} ${t.title}`,`${B(q.dim,"Filter")} ${B(q.bold,"/"+n)}`,y,...p.map((S,x)=>co(S,d+x,x===r))]};t.pauseResume?.pause(),so(process.stdin);let u=process.stdin.isRaw;return process.stdin.setRawMode?.(!0),process.stdin.isPaused()&&process.stdin.resume(),c.paint(l()),process.stdout.write(io),await new Promise(m=>{let d=!1,p=x=>{if(!d){d=!0,process.stdin.off("keypress",S);try{process.stdin.setRawMode?.(u??!1)}catch{}if(t.pauseResume?.resume(),c.clear(),process.stdout.write(ao),x!==null){let k=t.choices.find(R=>R.value===x);process.stdout.write(`${B(q.green,"\u2713")} /${x}${k&&k.description?B(q.dim,` \u2014 ${k.description}`):""}
|
|
5
|
+
`)}else process.stdout.write(`${B(q.dim,"\xB7")} cancelled
|
|
6
|
+
`);m(x)}},y=()=>{let k=s()[o*e+r];return k?k.value:null},S=(x,k)=>{if(!k||d)return;if(k.ctrl&&k.name==="c"||k.name==="escape")return p(null);if(k.name==="return"||k.name==="enter")return p(y());if(k.name==="tab"){let P=y();P&&(n=P,r=0,o=0,c.paint(l()));return}if(k.name==="backspace"){n=n.slice(0,-1),r=0,o=0,c.paint(l());return}if(k.name==="up"||k.name==="k"||k.name==="p"&&k.ctrl){let P=s();if(P.length===0)return;r>0?r-=1:o>0&&(o-=1,r=Math.min(e-1,Math.max(0,P.length-1-o*e))),c.paint(l());return}if(k.name==="down"||k.name==="j"||k.name==="n"&&k.ctrl){let P=s();if(P.length===0)return;r<e-1&&o*e+r+1<P.length?r+=1:o+1<i(P)&&(o+=1,r=0),c.paint(l());return}if(k.name&&/^[1-9]$/.test(k.name)){let P=Number(k.name)-1;P<s().length&&(o=Math.floor(P/e),r=P%e,c.paint(l()));return}let R=k.sequence??x;R&&R.length===1&&R.charCodeAt(0)>=32&&(n+=R,r=0,o=0,c.paint(l()))};process.stdin.on("keypress",S)})}async function Q(t){let e=!!(process.stdin.isTTY&&process.stdout.isTTY&&typeof process.stdin.setRawMode=="function");return e&&t.typeahead===!0?pa(t):e?ma(t):da(t)}var Nt="__fresh__";function fa(t,e={}){let n=e.prefer??(e.currentId?"current":"recent"),r=[];e.includeFresh&&r.push({value:Nt,label:"Start fresh",description:"Create a new empty session",aliases:["fresh","new"],default:n==="fresh"});for(let[o,s]of t.entries()){let i=s.id.slice(0,8),a=e.currentId===s.id?" \xB7 current":"",c=!1;n==="current"?c=s.id===e.currentId:n==="recent"&&(c=o===0),r.push({value:s.id,label:s.title,description:`${s.updatedAt} ${s.mode.padEnd(5)} ${String(s.runCount).padStart(3)} run(s)${a}`,aliases:[i],default:c})}if(!r.some(o=>o.default)&&r.length>0){let o=n==="fresh"?r.find(s=>s.value===Nt)??r[0]:r.find(s=>s.value!==Nt)??r[0];o&&(o.default=!0)}return r}async function Dn(t){let e=await t.store.list();if(e.length===0)return t.includeFresh?{kind:"fresh"}:(console.log("[no sessions]"),{kind:"cancel"});let n=await Q({title:t.title,question:t.question,pauseResume:t.pauseResume,typeahead:!0,pageSize:8,choices:fa(e,{includeFresh:t.includeFresh,currentId:t.currentId,prefer:t.prefer})});return n?n===Nt?{kind:"fresh"}:{kind:"session",session:await t.store.load(n)}:{kind:"cancel"}}var ga=new Set(["exit","quit","q","bye",":q",":quit",":exit","/exit","/quit","/q"]);function jn(t){return ga.has(t.trim().toLowerCase())}import{emitKeypressEvents as jd}from"node:readline";var C={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m"};function M(t,e){return process.stdout.isTTY?`${t}${e}${C.reset}`:e}function uo(t){return t.replace(/\u001b\[[0-9;]*m/g,"")}function mo(t){let e=0;for(let n of uo(t)){let r=n.codePointAt(0)??0;e+=r>11904?2:1}return e}function po(t,e){let n=mo(t);return n>=e?t:t+" ".repeat(e-n)}var fo={read_file:{label:"READ",key:"path"},list_files:{label:"LIST",key:"path"},search_text:{label:"SEARCH",key:"query"},workspace_summary:{label:"SCAN"},git_status:{label:"STATUS"},git_diff:{label:"DIFF"},write_file:{label:"WRITE",key:"path"},replace_in_file:{label:"EDIT",key:"path"},make_directory:{label:"MKDIR",key:"path"},delete_path:{label:"DELETE",key:"path"},shell:{label:"SHELL",key:"command"},web_search:{label:"WEB",key:"query"},web_fetch:{label:"FETCH",key:"url"},browser_open:{label:"BROWSER",key:"url"},delegate_subagents:{label:"AGENTS"}};function ha(t){return fo[t]?.label??t.replace(/^mcp_/,"MCP").replace(/_/g," ").toUpperCase()}function go(t){if(!t||Object.keys(t).length===0)return"";let n=t.total_lines??t.totalLines,r=t.start_line??t.startLine,o=t.end_line??t.endLine,s=t.matches??t.match_count??t.count,i=t.entries??t.entry_count,a=t.top_level??t.topLevel,c=t.manifests,l=t.files??t.file_count,u=t.dirs??t.directories??t.dir_count,m=t.resultCount??t.result_count;if(typeof n=="number")return typeof r=="number"&&typeof o=="number"?`lines ${r}-${o} of ${n}`:`${n} lines`;if(typeof s=="number")return`${s} match${s===1?"":"es"}`;if(typeof m=="number")return`${m} result${m===1?"":"s"}`;if(typeof i=="number")return`${i} entr${i===1?"y":"ies"}`;if(typeof a=="number"){let S=[`${a} top-level`];return typeof c=="number"&&S.push(`${c} manifest${c===1?"":"s"}`),S.join(" \xB7 ")}if(typeof l=="number"){let S=[`${l} file${l===1?"":"s"}`];return typeof u=="number"&&S.push(`${u} dir${u===1?"":"s"}`),S.join(" \xB7 ")}let d=[],p=!1;for(let[S,x]of Object.entries(t)){let k=typeof x=="object"&&x!==null?JSON.stringify(x):String(x);if(k.length>24){p=!0;continue}d.push(`${S}: ${k}`)}let y=d.join(", ");return y.length>60&&(y=y.slice(0,57).trimEnd(),p=!0),p?`${y}${y?" ":""}\u2026`:y}function Nn(t,e){let n=fo[e]?.key??["file_path","path","cwd","command","query","url","message"].find(i=>typeof t[i]=="string"&&t[i].trim().length>0);if(n&&typeof t[n]=="string"){let i=t[n].trim();if(!i)return"";let a=n==="path"||n==="file_path"?i.split("/").pop()??i:i;return a.length>60?`${a.slice(0,57)}\u2026`:a}let r=t&&typeof t=="object"?t:{};if(Object.keys(r).length===0)return"";let s=JSON.stringify(r);return s.length>60?`${s.slice(0,57)}\u2026`:s}function ho(t){if(!t)return[];let e=t.split(/\r?\n/).filter(Boolean),n=new Map,r,o=(s,i,a)=>{let c=n.get(s)??{file:s,added:0,deleted:0};c.added+=i,c.deleted+=a,n.set(s,c)};for(let s of e){if(/^\+\+\+\s/.test(s)&&!s.includes("|")){r=s.slice(4).trim().replace(/^b\//,"");continue}let i=/^(.+?)\s+\|\s+[\d ]+(.*)$/.exec(s);if(i){let a=i[1].trim(),c=i[2]??"",l=0,u=0;for(let m of c)m==="+"&&(l+=1),m==="-"&&(u+=1);if(l===0&&u===0)continue;r=a,o(a,l,u);continue}r&&s.startsWith("+")&&!s.startsWith("+++")&&o(r,1,0),r&&s.startsWith("-")&&!s.startsWith("---")&&o(r,0,1)}return[...n.values()].sort((s,i)=>s.file.localeCompare(i.file))}function lo(t){return Number.isFinite(t)?String(t):"0"}function wo(t){let e=Math.max(0,Math.floor(t/1e3)),n=Math.floor(e/60),r=e%60;return n>0?`${n}m${r.toString().padStart(2,"0")}s`:`${r}s`}function Ue(t){if(!Number.isFinite(t)||t<1e3)return String(Math.round(t));let e=["K","M","B","T"],n=Math.min(Math.floor(Math.log10(t)/3),e.length),r=t/10**(n*3),o=r>=100?0:r>=10?1:2;return`${r.toFixed(o)}${e[n-1]}`}function wa(t){return t===void 0||!Number.isFinite(t)||t<=0?"":t>=.01?`\xB7 est $${t.toFixed(4)}`:`\xB7 est $${t.toFixed(6)}`}function qt(t,e,n,r={}){let s=[e?M(C.dim,e):"",n?M(C.dim,n):""].filter(Boolean).join(M(C.dim," \xB7 "));if(r.bypass&&t!=="plan"){let a=M(C.red,"BYPASS MODE"),c=M(C.dim,"\xB7 approvals auto-granted \xB7 Shift+Tab to turn off");return`\u2500\u2500 ${a} ${c}${s?` ${s}`:""} \u2500\u2500`}if(t==="plan"){let a=M(C.yellow,"PLAN MODE"),c=M(C.dim,"\xB7 read-only \xB7 edits & mutating commands are blocked");return`\u2500\u2500 ${a} ${c}${s?` ${s}`:""} \u2500\u2500`}return`\u2500\u2500 ${M(C.green,"WRITE MODE")}${s?` ${s}`:""} \u2500\u2500`}function yo(t){return t?" \u26A0 Bypass ON \xB7 approvals auto-granted \xB7 Shift+Tab to turn off":" \u2713 Bypass OFF \xB7 approvals required \xB7 Shift+Tab to turn on"}function bo(t,e){return t.lineOpen||t.speakerShown?"":`${e} \u203A `}function ya(t){let e=/ /.test(t),n=e?t.replace(/\s+/g," ").trim():t.replace(/\s+/g,""),r=e?n.split(" "):[n],o=e&&r.length>1&&r.filter(R=>R.length===1).length>=r.length*.5,s=o?n.replace(/ /g,""):n;if(!s)return`\u250C\u2500 ${M(C.dim,"thinking")} \u2500\u2510
|
|
7
|
+
\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518`;let i=Math.min(72,Math.max(24,s.length)),a=Array.from(s),c=[],l=Math.max(1,i-2);if(e&&!o){let R="";for(let P of r){let _=R?`${R} ${P}`:P;mo(_)>i-2&&R?(c.push(R),R=P):R=_}R&&c.push(R)}else for(let R=0;R<a.length;R+=l)c.push(a.slice(R,R+l).join(""));let u=process.stdout.isTTY,m=u?"\x1B[100m":"",d=u?C.reset:"",p=12,y=c.length>p?[...c.slice(0,p),M(C.dim,`\u2026 ${c.length-p} more lines`)]:c,S=`${m}\u250C\u2500 ${M(C.dim,"thinking")} ${M(C.dim,"\u2500".repeat(Math.max(0,i-10)))}\u2510${d}`,x=`${m}\u2514${M(C.dim,"\u2500".repeat(i))}\u2518${d}`,k=y.map(R=>`${m}\u2502 ${M(C.dim,po(R,i-2))} \u2502${d}`).join(`
|
|
8
|
+
`);return`${S}
|
|
9
|
+
${k}
|
|
10
|
+
${x}`}function ba(t){let e=[];return t.elapsedMs!==void 0&&e.push(wo(t.elapsedMs)),e.push(`${Ue(t.inputTokens)}\u25B2 \xB7 ${Ue(t.outputTokens)}\u25BC`),t.cacheReadTokens&&t.cacheReadTokens>0&&e.push(M(C.green,`${Ue(t.cacheReadTokens)} cached`)),t.costUsd&&e.push(wa(t.costUsd)),t.mode==="plan"&&e.push(M(C.yellow,"plan \xB7 edits blocked")),e.join(M(C.dim," \xB7 "))}function va(t,e=28){if(!t)return"";let n=t.split(/\r?\n/).filter(Boolean),r=n.length,s=n.slice(0,e).map(i=>i.startsWith("+")?M(C.green,i):i.startsWith("-")?M(C.red,i):i.startsWith("@@")?M(C.cyan,i):(i.startsWith("diff --git")||i.startsWith("index ")||i.startsWith("---")||i.startsWith("+++"),M(C.dim,i))).join(`
|
|
11
|
+
`);return r>e&&(s+=`
|
|
12
|
+
${M(C.dim,`\u2026 ${r-e} more diff lines`)}`),s}var Ln=["\u2722","\u2740","\u273F","\u2744","\u2748","\u2734","\u2736","\u2605","\u272E","\u272A","\u263C","\u25C6"],Un=["parsing","framing","ingesting","detecting","decoding","scanning","probing","mapping","brainstorming","clustering","structuring","pivoting","planning","blueprinting","architecting","scoping","routing","filtering","reasoning","coding","calculating","compiling","building","synthesizing","processing"];function ka(t,e){let n=Math.max(3,Math.round(t.length/2)),r="";for(let o=0;o<t.length;o+=1){let s=e-o,i=C.dim;s>=0&&s<n&&(s===0?i=C.green:s<Math.ceil(n/2)?i=C.cyan:i=C.yellow),r+=M(i,t[o])}return r}var Ft=class{mode;output;tty;timer;frame=0;startedAt=Date.now();inputTokens=0;cacheReadTokens=0;outputTokens=0;costUsd;reasoning=[];reasoningOpen=!1;lastLineOpen=!1;nonTtyAnnounced=!1;finished=!1;sawOutput=!1;constructor(e){this.mode=e.mode,this.output=e.output??process.stdout,this.tty=e.tty??!!process.stdout.isTTY}clearLine(){this.tty&&this.output.write("\r\x1B[2K")}writeLine(e){if(this.tty)this.output.write(`\r\x1B[2K${e}
|
|
13
|
+
`);else{let n=uo(e);this.output.write(`${n}
|
|
14
|
+
`)}this.lastLineOpen=!1}noteOutput(){this.sawOutput=!0}activity(e,n,r,o){if(this.finished)return;this.sawOutput=!0,this.clearReasoningIfOpen();let s=ha(n),i=this.tty?`\x1B[7m ${s} \x1B[0m`:`[${s}]`,a=r?M(C.dim,` ${r}`):"";if(e==="start")this.writeLine(`${M(C.magenta,"\u2192")} ${i}${a}`);else if(e==="result"){let c=o===!1?M(C.red,"\u2717"):M(C.green,"\u2713");this.writeLine(`${c} ${i}${a}`)}else this.writeLine(` ${i}${a}`)}reasoningDelta(e,n=!0){this.finished||(this.sawOutput=!0,this.reasoning.push(e),this.reasoningOpen=!0,n&&this.redrawFooter())}clearReasoning(){this.clearReasoningIfOpen()}clearReasoningIfOpen(){this.reasoningOpen&&(this.reasoningOpen=!1,this.reasoning.length>0&&!this.finished&&this.writeLine(ya(this.reasoning.join("").trim())),this.reasoning=[])}addUsage(e,n,r=0){this.inputTokens+=e,this.outputTokens+=n,this.cacheReadTokens+=r}setCost(e){this.costUsd=e}finish(e){if(this.finished)return;this.finished=!0,this.stopTimer(),this.clearReasoningIfOpen(),this.tty?(this.lastLineOpen&&process.stdout.write(`
|
|
15
|
+
`),this.writeLine("")):console.log("");let n=e?.files??[];if(e?.changed&&n.length>0){this.writeLine(M(C.bold,`Files changed (${n.length}):`));for(let o of n)this.writeLine(` ${M(C.dim,o.file.padEnd(40))} ${M(C.green,`+${lo(o.added)}`)} ${M(C.red,`\u2212${lo(o.deleted)}`)}`);if(e.diff){this.writeLine(""),this.writeLine(M(C.dim,"Diff:"));for(let o of va(e.diff).split(`
|
|
16
|
+
`))this.writeLine(o)}}else e&&!e.changed&&this.mode==="plan"&&this.writeLine(M(C.dim,"No files changed \xB7 plan-only run."));if(e?.planSummary){this.writeLine(M(C.bold,"Plan summary"));for(let o of e.planSummary.split(`
|
|
17
|
+
`))this.writeLine(M(C.dim,` ${o}`))}let r=ba({elapsedMs:Date.now()-this.startedAt,inputTokens:this.inputTokens,outputTokens:this.outputTokens,costUsd:this.costUsd,cacheReadTokens:this.cacheReadTokens,mode:this.mode});this.writeLine(M(C.dim,r))}renderFrame(){if(this.finished||!this.tty)return;let e=this.frame,n=Ln[Math.floor(e/2)%Ln.length]??Ln[0],r=this.reasoningOpen?this.reasoning.join("").replace(/\s+/g," ").trim().slice(-60):"",o;if(!this.sawOutput)o=M(C.dim,"connecting\u2026");else if(r)o=M(C.dim,`thinking: ${r}`);else{let u=Un[Math.floor(e/8)%Un.length]??Un[0],m=Math.floor(e/2)%Math.max(1,u.length+6);o=ka(u,m)}let s=wo(Date.now()-this.startedAt),i=` \xB7 ${Ue(this.inputTokens)}\u25B2 ${Ue(this.outputTokens)}\u25BC${this.cacheReadTokens>0?M(C.green,` ${Ue(this.cacheReadTokens)} cached`):""}`,a=`${o}${M(C.dim,`${i} \xB7 ${s}`)}`,c=Math.max(30,(this.output.columns??80)-4);this.output.write(`\r\x1B[2K${M(C.cyan,n)} ${po(a,c)}`),this.lastLineOpen=!0}redrawFooter(){!this.tty||this.finished||(this.clearLine(),this.renderFrame())}start(){this.timer||this.finished||(this.startedAt=Date.now(),this.tty?(process.stdout.write(`
|
|
18
|
+
`),this.renderFrame(),this.timer=setInterval(()=>{this.frame+=1,this.renderFrame()},140)):this.nonTtyAnnounced||(this.nonTtyAnnounced=!0,this.output.write(`${M(C.dim,"\u25C6 working\u2026")}
|
|
19
|
+
`)))}stop(){this.stopTimer(),this.tty&&(this.clearLine(),this.lastLineOpen=!1)}dispose(){this.finished=!0,this.stop(),this.reasoningOpen=!1,this.reasoning=[]}stopTimer(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}};function vo(t){let e=new Set(["read_file","git_diff","git_status"]),n=new Set(["search_text","list_files","workspace_summary"]),r=new Set,o=0,s=0;for(let a of t)a.type==="tool_start"&&(e.has(a.call.function.name)?r.add(Nn(a.args,a.call.function.name)):n.has(a.call.function.name)&&(o+=1)),a.type==="tool_result"&&!a.result.ok&&(s+=1);let i=[];return i.push(`inspected ${r.size} file(s)${r.size?`: ${[...r].slice(0,6).join(", ")}${r.size>6?"\u2026":""}`:""}`),o>0&&i.push(`${o} search/list call(s)`),s>0&&i.push(`${s} tool call(s) failed`),i.push("No files were modified (plan mode)."),i.join(`
|
|
20
|
+
`)}var ko={"anthropic/claude-opus-5":{name:"Claude Opus 5",description:"Anthropic flagship for demanding reasoning, coding, and long-horizon agentic work"},"anthropic/claude-opus-4.8":{name:"Claude Opus 4.8",description:"Anthropic flagship for complex reasoning and high-stakes coding"},"anthropic/claude-sonnet-5":{name:"Claude Sonnet 5",description:"Frontier Sonnet-class model for coding, agents, and knowledge work"},"anthropic/claude-fable-5.1":{name:"Claude Fable 5.1",description:"Agentic coding and long-range tool use with broad gains over Fable 5"},"anthropic/claude-fable-5":{name:"Claude Fable 5",description:"Lightweight Claude model tuned for agentic coding and tool calling"},"openai/gpt-6-astra":{name:"GPT-6 Astra",description:"OpenAI flagship for advanced analysis, software engineering, and agentic work"},"openai/gpt-5.6-sol":{name:"GPT-5.6 Sol",description:"OpenAI flagship for complex reasoning and coding"},"openai/gpt-5.6-terra":{name:"GPT-5.6 Terra",description:"Balanced GPT-5.6 model between flagship and everyday tiers"},"openai/gpt-5.6-luna":{name:"GPT-5.6 Luna",description:"GPT-5.6 series model for general reasoning and coding"},"openai/gpt-5.5":{name:"GPT-5.5",description:"OpenAI frontier model for complex professional workloads"},"google/gemini-3.8-flash":{name:"Gemini 3.8 Flash",description:"Google\u2019s most intelligent Flash model for software and reasoning"},"google/gemini-3.7-flash":{name:"Gemini 3.7 Flash",description:"Google Flash model balancing speed, reasoning, and coding"},"google/gemini-3.5-flash-lite":{name:"Gemini 3.5 Flash Lite",description:"Fast, low-latency Google model for everyday tasks"},"google/gemini-3.1-flash-lite":{name:"Gemini 3.1 Flash Lite",description:"Lightweight Google model for quick, cost-effective work"},"x-ai/grok-4.6":{name:"Grok 4.6",description:"xAI\u2019s smartest model for coding, knowledge work, and STEM"},"x-ai/grok-4.5":{name:"Grok 4.5",description:"xAI model for coding and knowledge-heavy tasks"},"qwen/qwen3.8-max-0902":{name:"Qwen3.8 Max",description:"2.4T-parameter Qwen model for complex coding and reasoning"},"qwen/qwen3.8-27b":{name:"Qwen3.8 27B",description:"Qwen model for general coding and agentic work"},"qwen/qwen3.8-flash":{name:"Qwen3.8 Flash",description:"Fast Qwen model for everyday agentic coding"},"qwen/qwen3.7-plus":{name:"Qwen3.7 Plus",description:"Cost-effective Qwen model with text + image input"},"qwen/qwen3.7-flash":{name:"Qwen3.7 Flash",description:"Fast Qwen model for agentic coding tasks"},"moonshotai/kimi-k3":{name:"Kimi K3",description:"2.8T-parameter multimodal reasoning model from Moonshot AI"},"z-ai/glm-5.3":{name:"GLM-5.3",description:"Large-scale Z.ai reasoning model for complex software engineering"},"z-ai/glm-5.3-flash":{name:"GLM-5.3 Flash",description:"Fast Z.ai GLM model for everyday coding"},"deepseek/deepseek-v4-pro-0813":{name:"DeepSeek V4 Pro",description:"Large mixture-of-experts model for reasoning and coding"},"deepseek/deepseek-v4-flash":{name:"DeepSeek V4 Flash",description:"Sparse MoE model balancing speed and capability"},"deepseek/deepseek-v4-flash-0731":{name:"DeepSeek V4 Flash (fast)",description:"Fast-flash DeepSeek model for quick coding turns"},"deepseek/deepseek-v4-flash-vision-exp":{name:"DeepSeek V4 Flash Vision",description:"Vision-capable DeepSeek model for image and UI work"},"stepfun/step-3.5-flash":{name:"Step 3.5 Flash",description:"StepFun fast model for everyday tasks"},"stepfun/step-3.7-flash":{name:"Step 3.7 Flash",description:"StepFun fast model for agentic coding"},"tencent/hy3":{name:"Tencent Hy3",description:"Tencent hybrid reasoning model for general work"},"minimax/minimax-m3":{name:"MiniMax M3",description:"MiniMax high-capability model for coding and long context"},"xiaomi/mimo-v2.5-pro":{name:"MiMo V2.5 Pro",description:"High-capability long-context agentic coding"},"xiaomi/mimo-v2.5":{name:"MiMo V2.5",description:"Xiaomi general-purpose model for coding and agents"},"meta/muse-spark-1.3":{name:"Muse Spark 1.3",description:"Meta reasoning model for complex agentic work"},"meta/muse-spark-1.2":{name:"Muse Spark 1.2",description:"Meta reasoning model for coding and analysis"},"meta/muse-spark-1.3-contributor":{name:"Muse Spark 1.3 (Contributor)",description:"Meta open-contributor Muse Spark model"}};function Bt(t){let e=ko[t]?.name;return e||(t.includes("/")?t.slice(t.lastIndexOf("/")+1):t).replace(/[-_]/g," ").replace(/\b\w/g,r=>r.toUpperCase())}function xo(t){return ko[t]?.description??"Hosted model available through kpilot"}import{emitKeypressEvents as xa}from"node:readline";var Se={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m"},Fn="\x1B[2K";function Pe(t,e){return`${t}${e}${Se.reset}`}function Ee(t){if(!t.startsWith("/"))return null;let e=t.slice(1);return e.includes(" ")||e.includes(" ")?null:e}function Sa(t){return[t.name,...t.aliases??[]].map(e=>e.toLowerCase())}function So(t,e){let n=e.trim().toLowerCase();if(!n)return[...t];let r=[];for(let o of t){let s=o.name.toLowerCase(),i=-1;Sa(o).includes(n)?i=0:s.startsWith(n)?i=1:s.includes(n)?i=2:o.description.toLowerCase().includes(n)&&(i=3),i>=0&&r.push({entry:o,score:i})}return r.sort((o,s)=>o.score-s.score||o.entry.name.localeCompare(s.entry.name)),r.map(o=>o.entry)}var Jt=class{entries=[];attached=!1;suspended=!1;drawn=0;pending=!1;skipRender=!1;hover=0;current=[];lastQuery=null;pendingSelection=null;savedHistory=null;maxRows;tty;rl;streams;constructor(e,n,r={}){this.rl=e,this.streams=n,this.maxRows=r.maxRows??8,this.tty=!!(n.input.isTTY&&n.output.isTTY)}setEntries(e){this.entries=e,this.current=this.computeMatches(),this.schedule()}attach(){this.attached||!this.tty||(this.attached=!0,xa(this.streams.input),this.streams.input.on("keypress",this.onKeypress),this.rl.on("pause",this.onPause),this.rl.on("resume",this.onResume))}detach(){this.attached&&(this.attached=!1,this.erase(),this.restoreHistory(),this.streams.input.off("keypress",this.onKeypress),this.rl.off("pause",this.onPause),this.rl.off("resume",this.onResume))}takeSelection(){let e=this.pendingSelection;return this.pendingSelection=null,e}onPause=()=>{this.suspended=!0,this.erase()};onResume=()=>{this.suspended=!1,this.schedule()};computeMatches(){let e=Ee(this.rl.line);return e===null?[]:So(this.entries,e)}onKeypress=(e,n)=>{if(!this.suspended){if(n?.name==="return"||n?.name==="enter"||n?.ctrl&&n.name==="c"){if(n.name!=="c"){let r=this.current;r.length>0&&this.hover<r.length&&(this.pendingSelection=r[this.hover]?.name??null)}this.clearAtCursor(),this.skipRender=!0;return}if(n?.ctrl&&n.name==="l"){this.drawn=0,this.schedule();return}if(n?.name==="escape"){this.rl.write?.(null,{ctrl:!0,name:"u"}),this.erase(),this.skipRender=!0;return}if(this.current=this.computeMatches(),(n?.name==="down"||n?.ctrl&&n.name==="n")&&this.current.length>0){this.move(1);return}if((n?.name==="up"||n?.ctrl&&n.name==="p")&&this.current.length>0){this.move(-1);return}this.pendingSelection!==null&&(this.pendingSelection=null),this.schedule()}};move(e){let n=this.current.length;n!==0&&(this.hover=(this.hover+e+n)%n,this.render())}syncHistory(e){try{e&&this.savedHistory===null?(this.savedHistory=[...this.rl.history],this.rl.history.splice(0,this.rl.history.length)):e||this.restoreHistory()}catch{}}restoreHistory(){if(this.savedHistory!==null){try{this.rl.history.splice(0,0,...this.savedHistory)}catch{}this.savedHistory=null}}schedule(){!this.attached||this.suspended||!this.tty||this.pending||(this.pending=!0,setTimeout(()=>{if(this.pending=!1,this.skipRender){this.skipRender=!1,this.lastQuery=Ee(this.rl.line);return}this.render()},0))}render(){if(!this.attached||this.suspended||!this.tty)return;let e=Ee(this.rl.line);if(this.syncHistory(e!==null),e===null){this.erase();return}let n=So(this.entries,e);if(this.current=n,n.length===0){this.hover=0,this.lastQuery=e,this.draw([` ${Pe(Se.dim,"No matching commands")}`]);return}e!==this.lastQuery&&(this.hover=0,this.lastQuery=e),this.hover>=n.length&&(this.hover=n.length-1);let r=Math.max(0,Math.min(this.hover,n.length-this.maxRows)),o=n.slice(r,r+this.maxRows),s=o.map((a,c)=>this.renderRow(a,r+c===this.hover));n.length-o.length>0&&s.push(` ${Pe(Se.dim,`\u2026 ${r+1}-${r+o.length} of ${n.length} \u2014 \u2191/\u2193 to move`)}`),this.draw(s)}renderRow(e,n){let r=`/${e.name}`.padEnd(14),o=n?Pe(Se.green,"\u203A"):" ",s=n?Pe(Se.bold,Pe(Se.cyan,r)):Pe(Se.cyan,r);return` ${o} ${s} ${Pe(Se.dim,e.description)}`}draw(e){if(this.erase(),e.length===0)return;let{output:n}=this.streams;n.write(`\r
|
|
21
|
+
`);for(let r=0;r<e.length;r+=1)n.write(`${Fn}${e[r]}`),r<e.length-1&&n.write(`\r
|
|
22
|
+
`);n.write(`\x1B[${e.length}A\r`),this.drawn=e.length}erase(){let e=this.drawn;if(this.drawn=0,e===0)return;let{output:n}=this.streams;n.write(`\r
|
|
23
|
+
`);for(let r=0;r<e;r+=1)n.write(Fn),r<e-1&&n.write(`\r
|
|
24
|
+
`);n.write(`\x1B[${e}A\r`)}clearAtCursor(){let e=this.drawn;if(this.drawn=0,e===0)return;let{output:n}=this.streams;for(let r=0;r<e;r+=1)n.write(Fn),r<e-1&&n.write(`\r
|
|
25
|
+
`);e>1&&n.write(`\x1B[${e-1}A\r`)}};import{readFile as Ta,stat as Pa}from"node:fs/promises";import To from"node:path";var Po="\x1B[?2004h",Eo="\x1B[?2004l",Ea=200,Ra=5e3,Ca=5*1024*1024,Ma={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"};function $a(t){if(t.length===0)return null;let n=t.replace(/\r\n|\r/g,`
|
|
26
|
+
`).replace(/\n+$/,"").split(`
|
|
27
|
+
`).length;if(n>1)return`[pasted ${n} lines]`;let r=[...t].length;return r>Ea?`[pasted ${r} chars]`:null}var Kt=class{entries=[];pasted=!1;record(e,n){let r=n??$a(e);return r?(this.entries.push({token:r,text:e}),r):e}markPasted(){this.pasted=!0}get isEmpty(){return!this.pasted&&this.entries.length===0}expand(e){let n=e,r=!1;for(let s of this.entries)n.includes(s.token)&&(n=n.replace(s.token,()=>s.text),r=!0);let o=this.pasted||r;return this.reset(),{text:n,pasted:o}}reset(){this.entries=[],this.pasted=!1}};async function Ro(t){let e=t.trim();if(!e||/[\r\n]/.test(e))return{text:t};if(/^data:image\//i.test(e))return{text:e,label:"[pasted image]"};let n=To.extname(e).toLowerCase(),r=Ma[n];if(!r)return{text:t};try{let o=await Pa(e);if(!o.isFile()||o.size>Ca)return{text:t};let s=await Ta(e);return{text:`data:${r};base64,${s.toString("base64")}`,label:`[pasted image ${To.basename(e)}]`}}catch{return{text:t}}}var Wt=class{rl;input;store;options;attached=!1;pasting=!1;buffer="";suspended=[];restoreTimer;constructor(e,n,r,o={}){this.rl=e,this.input=n,this.store=r,this.options=o}attach(){this.attached||(this.attached=!0,this.input.on("keypress",this.onKeypress))}detach(){this.attached&&(this.attached=!1,this.restore(),this.input.off("keypress",this.onKeypress))}onKeypress=(e,n)=>{if(n){if(n.name==="paste-start"){this.beginPaste();return}if(n.name==="paste-end"){this.endPaste();return}this.pasting&&(this.buffer+=n.sequence??e??"")}};beginPaste(){if(!this.pasting){this.pasting=!0,this.buffer="",this.suspended=this.input.listeners("keypress").filter(e=>e!==this.onKeypress);for(let e of this.suspended)this.input.off("keypress",e);this.restoreTimer=setTimeout(()=>this.restore(),Ra)}}restore(){this.restoreTimer&&(clearTimeout(this.restoreTimer),this.restoreTimer=void 0);for(let e of this.suspended)this.input.on("keypress",e);this.suspended=[]}async endPaste(){if(!this.pasting)return;let e=this.buffer;this.pasting=!1,this.buffer="",this.restore();let n=this.options.prepare?await this.options.prepare(e):{text:e};this.store.markPasted();let r=this.store.record(n.text,n.label);this.options.placeholder&&this.rl.line===this.options.placeholder&&this.rl.write(null,{ctrl:!0,name:"u"}),this.rl.write(r),this.options.onInsert?.(r)}};var _a=["--yolo","--bypass-permissions","--yes-always","--dangerously-skip-permissions","--auto-accept","--force"];function $o(t){return _a.includes(t)}var Co=new Set(["bypass","bypass-permissions","yolo","auto-accept","autoaccept","accept","accept-edits","auto","skip","all"]),Mo=new Set(["ask","default","manual","normal","prompt","confirm"]);function _o(t){let e=t.trim().toLowerCase();if(Co.has(e))return!0;if(Mo.has(e))return!1;let n=[...Co,...Mo].join(", ");throw new Error(`--permission-mode must be one of: ${n}.`)}var me={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",yellow:"\x1B[33m",cyan:"\x1B[36m"},Aa=`${me.bold}${me.cyan}`;function Re(t,e,n){return n?`${t}${e}${me.reset}`:e}function qn(){return process.stdout.isTTY===!0}var Ht=`${Re(me.cyan,"\u276F",!0)} `,Bn="Ask your question...",Ao=2;function Jn(t=process.stdout.columns,e=qn()){return Re(me.dim,"\u2500".repeat(Math.max(20,zt(t)-1)),e)}function zt(t=process.stdout.columns){return typeof t=="number"&&Number.isFinite(t)&&t>0?t:80}function Kn(t){return t.replace(/\u001b\[[0-9;]*m/g,"").length}function Oo(t,e=process.stdout.columns){return t?1+Math.max(1,Math.ceil(Kn(t)/zt(e))):1}function Io(t){return`\x1B[${t+1}A\r\x1B[0J`}function Do(t,e={}){let n=zt(e.columns),r=e.color??qn(),o=Math.max(1,Math.ceil((Ao+Kn(t))/n));return`\x1B[${(e.rowsAbove??0)+o}A\r\x1B[0J${Ht}${Re(Aa,t,r)}
|
|
28
|
+
`}function jo(t,e=qn()){let n=t.bypass?"type / for commands \xB7 Shift+Tab bypass is ON":"type / for commands \xB7 Shift+Tab bypass",r=t.exitArmed?"Press Ctrl+C again to exit":"Ctrl+C twice to exit",o=" ";return[Re(me.dim,o+n,e),Re(t.exitArmed?me.yellow:me.dim,o+r,e)]}var Gt=class{output;rl;active=!1;footer=[];noteText=null;noteTimer;placeholder=null;placeholderPending=!1;constructor(e,n){this.output=e,this.rl=n}get tty(){return this.output.isTTY===!0}columns(){return zt(this.output.columns)}column(){return(Ao+this.rl.cursor)%this.columns()+1}suppressed(){return Ee(this.rl.line)!==null}belowLines(){let e=[Jn(this.columns(),this.tty),...this.footer];return this.noteText&&e.push(this.noteText),e}paint(){if(!this.active||!this.tty||this.suppressed())return;let e=this.belowLines();e.length!==0&&this.output.write(`
|
|
29
|
+
\x1B[0J${e.join(`
|
|
30
|
+
`)}\x1B[${e.length}A\x1B[${this.column()}G`)}setFooter(e){this.footer=e.filter(n=>n.length>0),this.paint()}note(e){!this.active||!this.tty||this.suppressed()||(this.noteText=Re(me.dim,` ${e}`,this.tty),this.paint(),this.noteTimer&&clearTimeout(this.noteTimer),this.noteTimer=setTimeout(()=>{this.noteText=null,this.paint()},2500),this.noteTimer.unref?.())}showPlaceholder(e){this.placeholder=e,this.placeholderPending=!0,!(!this.active||!this.tty||this.suppressed())&&this.drawPlaceholder()}drawPlaceholder(){this.placeholder!==null&&this.output.write(`${Re(me.dim,this.placeholder,!0)}\x1B[${Kn(this.placeholder)}D`)}syncPlaceholder(){if(!(!this.placeholderPending||this.placeholder===null||!this.tty)){if(this.rl.line.length>0){this.placeholderPending=!1,this.output.write(`\r\x1B[2K${Ht}${this.rl.line}\x1B[${this.column()}G`);return}this.drawPlaceholder()}}clearPlaceholder(){this.placeholder=null,this.placeholderPending=!1}rewind(){!this.active||!this.tty||this.suppressed()||this.output.write("\x1B[1A\x1B[2K\r")}clear(){try{this.rl.write(null,{ctrl:!0,name:"u"})}catch{}}begin(){this.active=!0,this.paint()}end(){this.active=!1,this.noteText=null,this.noteTimer&&(clearTimeout(this.noteTimer),this.noteTimer=void 0)}};import{emitKeypressEvents as Oa}from"node:readline";var Ia=1e4;function Gn(){let t=new Error("Stopped by user");return t.name="AbortError",t}var Wn=class{active=null;stopped=null;stream;constructor(e=process.stdin){this.stream=e}install(){if(!this.stream.isTTY)return;Oa(this.stream),(this.stream.listeners?.("keypress")??[]).includes(this.onKeypress)||this.stream.on("keypress",this.onKeypress)}onKeypress=(e,n)=>{this.handleKey(n)};handleKey(e){if(!e)return!1;let n=e.name==="escape"||e.sequence==="\x1B",r=e.ctrl===!0&&(e.name==="c"||e.sequence==="");return!n&&!r?!1:this.stop(n?"Esc":"Ctrl+C")}noteStop(e){this.stopped={reason:e,at:Date.now()}}get stopReason(){return!this.stopped||Date.now()-this.stopped.at>Ia?null:this.stopped.reason}stop(e){let n=this.active;return!n||n.signal.aborted?!1:(this.stopped={reason:e,at:Date.now()},n.abort(Gn()),!0)}get running(){return this.active!==null&&!this.active.signal.aborted}begin(e){this.install(),this.active=e,this.stopped=null;let n=this.stream.isRaw;try{this.stream.setRawMode?.(!0),this.stream.resume?.()}catch{}let r=!1;return()=>{if(!r){r=!0,this.active===e&&(this.active=null);try{this.stream.setRawMode?.(n??!1)}catch{}}}}},ct=new Wn;function Hn(t){let e=new Set;for(let n of t.split(/\r?\n/))if(n.startsWith("+++ b/"))e.add(n.slice(6));else if(n.startsWith("diff --git ")){let r=/diff --git a\/(.+) b\/(.+)/.exec(n.trim());r?.[1]&&e.add(r[1])}return[...e]}function Lo(t){return`'${t.replace(/'/g,"'\\''")}'`}import Na from"node:path";import{mkdir as No,readdir as Yn,rename as Da,rm as zn,stat as Fo}from"node:fs/promises";import Ce from"node:path";var E=".kpilot",qo=".konsolepilot";async function Uo(t){try{return await Fo(t),!0}catch{return!1}}async function Bo(t){try{return(await Fo(t)).isDirectory()}catch{return!1}}async function Vn(t){return await Bo(t)?(await Yn(t)).length===0:!1}async function ja(t,e){if(await Uo(t)&&!await Uo(e)){await No(Ce.dirname(e),{recursive:!0});try{await Da(t,e)}catch(n){throw(n&&typeof n=="object"&&"code"in n?String(n.code):"")==="EXDEV"?new Error(`Cannot migrate ${t} to ${e} across filesystems. Move .konsolepilot into .kpilot manually.`):n}}}async function Vt(t){let e=Ce.resolve(t),n=Ce.join(e,qo),r=Ce.join(e,E);if(await No(r,{recursive:!0}),!await Bo(n))return{migrated:!1};let o=await Yn(n);for(let s of o)await ja(Ce.join(n,s),Ce.join(r,s));if(await Vn(n))await zn(n,{recursive:!0,force:!0});else{let s=await Yn(n);for(let i of s){let a=Ce.join(n,i);await Vn(a)&&await zn(a,{recursive:!0,force:!0})}await Vn(n)&&await zn(n,{recursive:!0,force:!0})}return{migrated:!0}}function La(t,e="value"){if(typeof t!="object"||t===null||Array.isArray(t))throw new Error(`${e} must be a JSON object.`);return t}function F(t,e,n={}){let r=t[e];if(typeof r!="string")throw new Error(`"${e}" must be a string.`);if(!n.allowEmpty&&r.trim().length===0)throw new Error(`"${e}" cannot be empty.`);if(n.maximumLength&&r.length>n.maximumLength)throw new Error(`"${e}" exceeds ${n.maximumLength} characters.`);return r}function X(t,e){let n=t[e];if(n!==void 0){if(typeof n!="string")throw new Error(`"${e}" must be a string.`);return n}}function Me(t,e,n){let r=t[e];if(r===void 0)return n;if(typeof r!="boolean")throw new Error(`"${e}" must be a boolean.`);return r}function ne(t,e,n,r,o){let s=t[e];if(s===void 0)return n;if(typeof s!="number"||!Number.isInteger(s))throw new Error(`"${e}" must be an integer.`);if(s<r||s>o)throw new Error(`"${e}" must be between ${r} and ${o}.`);return s}function Jo(t,e="JSON"){let n;try{n=JSON.parse(t)}catch(r){let o=r instanceof Error?r.message:String(r);throw new Error(`${e} is invalid: ${o}`)}return La(n,e)}function Ua(t){try{return JSON.parse(t&&t.trim()?t:"{}"),!0}catch{return!1}}function pe(t){let e=new Set,n=[];for(let o of t){if(o.role==="assistant"&&o.tool_calls?.length){let s=[],i=[];for(let a of o.tool_calls){if(Ua(a.function.arguments)){s.push(a);continue}e.add(a.id),i.push(a.function.name||"unknown_tool")}if(s.length===0){let a=i.length?`[Dropped invalid tool call(s): ${i.join(", ")}. Prefer replace_in_file or write_file with content_b64.]`:"[Dropped invalid tool call.]";n.push({role:"assistant",content:[o.content?.trim(),a].filter(Boolean).join(`
|
|
31
|
+
|
|
32
|
+
`)||a});continue}n.push({role:"assistant",content:o.content,tool_calls:s});continue}o.role==="tool"&&e.has(o.tool_call_id)||n.push(o)}let r=new Set;for(let o of n)if(o.role==="assistant"&&o.tool_calls)for(let s of o.tool_calls)r.add(s.id);return n.filter(o=>o.role!=="tool"||r.has(o.tool_call_id))}function Fa(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,48)||"plan"}function qa(t=new Date){return t.toISOString().slice(0,16).replace(/[:T]/g,"").replace(/-/g,"")}function Ko(t,e,n=new Date){return Na.join(t,E,"plans",`${Fa(e)}-${qa(n)}.md`)}function Wo(t){let n=(t.split(/\r?\n/).find(r=>r.trim())??"").replace(/^\s*(?:title|name|session)\s*[:\-–—]\s*/i,"").replace(/[`"“”'‘’*_#]+/g,"").replace(/\s+/g," ").trim().replace(/[.,;:!?\-–—]+$/,"").trim();return Ba(n)}function Ba(t){if(!t)return"";let e=t.split(" ").slice(0,8).join(" ");if(e.length<=60)return e;let n=e.slice(0,60),r=n.lastIndexOf(" ");return`${(r>60/2?n.slice(0,r):n).trim()}\u2026`}function Ja(t){let n=(t.split(/\r?\n/).find(r=>r.trim())??"").replace(/`{1,3}[^`]*`{1,3}/g," ").replace(/\[([^\]]+)\]\([^)]*\)/g,"$1").replace(/\s+/g," ").trim();return Wo(n)||"New session"}async function Go(t,e,n={}){let r=Ja(e);try{let o=await t.complete({messages:[{role:"system",content:"You name coding sessions. Reply with a title of at most 6 words describing what the request is for. No quotes, no trailing punctuation, no explanation."},{role:"user",content:`Request:
|
|
33
|
+
|
|
34
|
+
${e.slice(0,1500)}`}],tools:[]},{signal:n.signal});return Wo(o.message.content??"")||r}catch{return r}}import{readFile as Ka,stat as Wa}from"node:fs/promises";import Ga from"node:path";var Ha=[".kpilot/logbook/project.md",".kpilot/logbook/learnings.md",".kpilot/instructions.md","KPILOT.md","AGENTS.md","KONSOLEPILOT.md",".kpilot/understanding.md",".kpilot/learnings.md"],za=8e3,Va=50,Ya={"AGENTS.md":1500,"KPILOT.md":2e3,"KONSOLEPILOT.md":2e3};async function Qa(t){try{return await Wa(t),!0}catch{return!1}}async function Xa(t){let e=[],n=0;for(let r of Ha){let o=Ga.join(t,r);if(!await Qa(o))continue;let s=await Ka(o,"utf8"),i=za-n;if(i<=0)break;let a=Ya[r]??i,c=s.slice(0,Math.min(i,a));e.push(`## ${r}
|
|
19
35
|
${c}`),n+=c.length}return e.join(`
|
|
20
36
|
|
|
21
|
-
`)}function
|
|
37
|
+
`)}function Za(t){return`You are kpilot, a precise local coding agent operating inside one repository.
|
|
22
38
|
|
|
23
|
-
${t.mode==="plan"
|
|
39
|
+
${t.mode==="plan"?`You are in PLAN mode \u2014 read-only. Inspect and reason; do not change files or run mutating commands.
|
|
40
|
+
Produce a concrete, actionable implementation plan for the request:
|
|
41
|
+
1. What you inspected (key files and findings).
|
|
42
|
+
2. The exact changes proposed, file by file (paths and what changes).
|
|
43
|
+
3. The verification steps (tests/build commands to run).
|
|
44
|
+
4. Risks or open questions.
|
|
45
|
+
Keep it concise and specific. End with a short numbered list of steps that can be executed in write mode.`:'You are in WRITE mode \u2014 a terminal coding agent that gets the job done.\n- When the user asks you to run, start, install, build, test, fix, create, or change something: use tools immediately. Do not tell them which commands to paste into their own terminal.\n- When the user asks an open question (how/why/what/\u201Ccan you \u2026\u201D, design or review requests): answer or outline the approach FIRST in plain language, then use read-only inspection to ground the answer. Do not start mutating anything before explaining what you are doing.\n- Prefer shell for package scripts (`pnpm dev`, `pnpm test`, `pnpm setup`, etc.).\n- For long-lived processes (dev servers, watchers), call shell with background=true so the process keeps running after the tool returns.\n- Only claim a dev server is running when the shell tool result has ok:true and ready: yes. If ok:false or the log shows ERR_PNPM_/install failure, say it failed and quote the error \u2014 never invent localhost success.\n- Only explain "how to" when the user explicitly asks for instructions, or a required tool/permission is denied.'}
|
|
24
46
|
|
|
25
47
|
Repository root: ${t.rootDir}
|
|
26
48
|
|
|
@@ -43,123 +65,147 @@ Operating rules:
|
|
|
43
65
|
- When Logbook learnings are present (see \`.kpilot/logbook/learnings.md\`), treat them as durable project facts and apply them to save steps\u2014do not re-discover the same conventions each turn.
|
|
44
66
|
- When finished, summarize what you did (commands run, URLs, files changed), not a tutorial for the user to repeat.
|
|
45
67
|
|
|
68
|
+
Tool guide (use the right tool, keep it economical):
|
|
69
|
+
- Find code with \`search_text\` (ripgrep) and \`list_files\` before reading; do not scan the whole tree.
|
|
70
|
+
- Read with \`read_file\` in focused windows (about 120 lines around what you need) \u2014 not whole large files.
|
|
71
|
+
- Use \`git_status\` and \`git_diff\` tools rather than shelling out to \`git status\`/\`git diff\`.
|
|
72
|
+
- Use \`replace_in_file\` for surgical edits; \`write_file\` for new files or full rewrites.
|
|
73
|
+
- Use \`shell\` for project scripts (\`pnpm test\`, \`pnpm build\`, \`pnpm lint\`) and other commands; long-lived servers must use \`background=true\`.
|
|
74
|
+
- The sandbox may strip environment variables, disable network, and enforce a timeout \u2014 if a command needs them, expect failure and report it.
|
|
75
|
+
- Delegate broad read-only investigation to \`delegate_subagents\` instead of reading many files yourself.
|
|
76
|
+
|
|
77
|
+
Verification and git hygiene:
|
|
78
|
+
- After changing code, run the most relevant test/build/lint command and confirm it passes before finishing.
|
|
79
|
+
- Before finishing a change, review \`git_diff\` to confirm the edit is correct and limited to the intended files.
|
|
80
|
+
- Do not modify unrelated files; keep the change scoped to the request.
|
|
81
|
+
- If the same step fails three times, stop and report the blocker instead of looping.
|
|
82
|
+
|
|
83
|
+
Stopping:
|
|
84
|
+
- Stop as soon as the request is satisfied; do not gold-plate or add unrequested features.
|
|
85
|
+
- If a write task is ambiguous, ask for clarification instead of guessing.
|
|
86
|
+
|
|
46
87
|
${t.projectInstructions?`Project instructions:
|
|
47
88
|
${t.projectInstructions}
|
|
48
89
|
`:""}
|
|
49
|
-
${t.memoryContext?`Persistent project memory:
|
|
50
|
-
${t.memoryContext}
|
|
51
|
-
`:""}
|
|
52
90
|
${t.preferenceContext?`Learned coding preferences:
|
|
53
91
|
${t.preferenceContext}
|
|
54
|
-
`:""}
|
|
55
|
-
${t.skillContext?`Active reusable skill:
|
|
56
|
-
${t.skillContext}
|
|
57
|
-
`:""}
|
|
58
|
-
${t.workspaceSummary?`Initial workspace summary:
|
|
59
|
-
${t.workspaceSummary}
|
|
60
|
-
`:""}`}var Be=class extends Error{constructor(e){super(typeof e=="string"&&e.trim()?`Agent run cancelled: ${e}`:"Agent run cancelled."),this.name="AgentCancelledError"}};function Pt(t){if(t?.aborted)throw new Be(t.reason)}function ii(t){let e=t instanceof Error?t.message:String(t);return/parse tool call arguments as JSON|json\.exception\.parse_error|tool call arguments/i.test(e)}var ai=`Your previous tool call failed because the tool-argument JSON was invalid (usually unescaped quotes/newlines in a raw "content" string).
|
|
92
|
+
`:""}`}var lt=class extends Error{constructor(e){super(typeof e=="string"&&e.trim()?`Agent run cancelled: ${e}`:"Agent run cancelled."),this.name="AgentCancelledError"}};function Yt(t){if(t?.aborted)throw new lt(t.reason)}function ec(t){let e=t instanceof Error?t.message:String(t);return/parse tool call arguments as JSON|json\.exception\.parse_error|tool call arguments/i.test(e)}var tc=`Your previous tool call failed because the tool-argument JSON was invalid (usually unescaped quotes/newlines in a raw "content" string).
|
|
61
93
|
|
|
62
94
|
Retry with ONE of these safer approaches:
|
|
63
95
|
1. For .env / markdown / plain config: write_file with content set to the raw text (escape newlines as \\n in JSON), OR
|
|
64
96
|
2. replace_in_file with a short exact old_string and new_string, OR
|
|
65
97
|
3. For TypeScript/JS with nested quotes only: write_file using content_b64 (real base64 of the UTF-8 file) \u2014 never invent placeholder base64.
|
|
66
98
|
|
|
67
|
-
Do not keep retrying the same broken content_b64.`,
|
|
99
|
+
Do not keep retrying the same broken content_b64.`,nc=`Stop. write_file for that path already succeeded earlier in this turn (or was refused as a repeat).
|
|
68
100
|
Do NOT call write_file again for the same path. Do NOT invent base64.
|
|
69
|
-
If needed, call read_file once to verify, then finish with a short confirmation and no more tools.`;function
|
|
101
|
+
If needed, call read_file once to verify, then finish with a short confirmation and no more tools.`;function Ho(t){return typeof t.path=="string"?t.path:""}function rc(t){let e=t instanceof Error?t.message:String(t);return/exceeds the available context size|context.?length|context.?window|too many tokens|maximum context/i.test(e)}function oc(t){let e=t instanceof Error?t.message:String(t),n=/request \((\d+) tokens\) exceeds the available context size \((\d+) tokens\)/i.exec(e);return n?{requestTokens:Number(n[1]),availableTokens:Number(n[2])}:null}function Qn(t){return t?Math.max(1,Math.ceil(t.length/3.5)):0}function Xn(t){return t.role==="assistant"?{role:"assistant",content:t.content,...t.tool_calls?{tool_calls:t.tool_calls.map(e=>({id:e.id,type:e.type,function:{name:e.function.name,arguments:e.function.arguments}}))}:{}}:t.role==="tool"?{role:"tool",tool_call_id:t.tool_call_id,content:t.content}:{role:t.role,content:t.content}}function Qo(t){if(t.role==="assistant"){let e=t.tool_calls?.map(n=>n.function.arguments).join(`
|
|
70
102
|
`)??"";return`${t.content??""}
|
|
71
|
-
${e}`}return t.content??""}function
|
|
72
|
-
\u2026[${n}]`}function
|
|
73
|
-
`)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
\u2026
|
|
78
|
-
|
|
103
|
+
${e}`}return t.content??""}function Qt(t){let e=0;for(let n of t)e+=Qn(Qo(n))+8;return e}function Ne(t,e,n){return t.length<=e?t:`${t.slice(0,Math.max(0,e))}
|
|
104
|
+
\u2026[${n}]`}function Xo(t,e){return t.map(n=>n.role==="system"?{role:"system",content:Ne(n.content,e.systemChars,"system truncated for hub context")}:n.role==="tool"?{role:"tool",tool_call_id:n.tool_call_id,content:Ne(n.content,e.toolChars,"tool output truncated for hub context")}:n.role==="assistant"&&n.tool_calls?.length?{role:"assistant",content:n.content,tool_calls:n.tool_calls.map(r=>({...r,function:{...r.function,arguments:Ne(r.function.arguments,e.argumentChars,"args truncated")}}))}:n.role==="user"&&n.content.length>e.systemChars?{role:"user",content:Ne(n.content,e.systemChars,"user truncated for hub context")}:Xn(n))}function sc(t){if(t.length<=2)return t;let e=t[0]?.role==="system"?1:0,n=-1;for(let s=t.length-1;s>=e;s-=1)if(t[s]?.role==="user"){n=s;break}if(n<=e)return t;let r=t[e];if(!r)return t;let o=e+1;if(r.role==="assistant"&&r.tool_calls?.length){let s=new Set(r.tool_calls.map(a=>a.id)),i=e+1;for(;i<n&&t[i]?.role==="tool"&&s.has(t[i].tool_call_id);)i+=1;o=i}return o>n?t:[...t.slice(0,e),...t.slice(o)]}function zo(t,e){let n=t.map(Xn),r=800,o=2e3;for(let s=0;s<8&&Qt(n)>e;s+=1)r=Math.max(240,Math.floor(r*.6)),o=Math.max(600,Math.floor(o*.7)),n=Xo(n,{toolChars:r,systemChars:o,argumentChars:Math.max(200,r)});return n}var Zo="Continue from where you stopped. Check the current state first and do not redo work that is already finished.";function Zn(t){return/^(Context reset:|Hub context full|Your previous tool call failed|Stop\. write_file|Tool JSON parse failed|Continue from where you stopped|Write the project's Logbook entry|The verification command)/i.test(t.trim())}function Vo(t){for(let e=t.length-1;e>=0;e-=1){let n=t[e];if(n?.role==="user"&&!Zn(n.content))return n.content}}function ic(t){let e=[];for(let n=t.length-1;n>=0;n-=1){let r=t[n];if(r?.role!=="user")break;Zn(r.content)||e.unshift(r.content)}return e}function ac(t,e){if(t.length===0)return"";let n=t.map((r,o)=>`${o+1}. ${Ne(r.replace(/\s+/g," ").trim(),300,"\u2026")}`).join(`
|
|
105
|
+
`);return e?[`Unfinished request(s) from this session that were never answered (oldest first):
|
|
106
|
+
${n}`,'The user asked you to resume. Complete the oldest unfinished request first, then any that follow, opening with a short line such as "Now let me complete the previous answer\u2026".'].join(`
|
|
107
|
+
|
|
108
|
+
`):[`Earlier request(s) in this session that were interrupted before you answered them (oldest first):
|
|
109
|
+
${n}`,'Answer the current request below first. Then complete the unfinished request(s) above, opening that part with a short line such as "Now let me complete the previous answer\u2026". If the current request is a follow-up to or part of an earlier one, treat them as a single task instead.'].join(`
|
|
110
|
+
|
|
111
|
+
`)}function cc(t,e=6){let n=t.filter(r=>r.role==="tool").slice(-e);return n.length===0?"":n.map((r,o)=>{let s=Ne(r.content,240,"truncated");return`${o+1}. ${s}`}).join(`
|
|
112
|
+
`)}function Yo(t,e){let n=Math.max(1,e.aggressiveness??1),r=(e.reserveOutputTokens??384)*n,o=Qn(e.toolsJson??""),i=e.contextWindowTokens-r-o-96;i<400&&(i=400);let a=n>=2?600:e.contextWindowTokens<=8192?1200:2500,c=n>=2?2200:e.contextWindowTokens<=8192?4e3:8e3,l=Xo(t.map(Xn),{toolChars:a,systemChars:c,argumentChars:Math.min(2e3,a*2)}),u=0;for(;Qt(l)>i&&u<40;){u+=1;let m=sc(l);if(m.length===l.length){l=zo(l,i);break}l=m}return Qt(l)>i&&(l=zo(l,i)),pe(l)}var Fe=class{gateway;runtime;permissions;conversation;constructor(e){this.gateway=e.gateway,this.runtime=e.runtime,this.permissions=e.permissions,this.conversation=e.initialMessages?pe(e.initialMessages):[]}reset(){this.conversation=[]}restore(e){this.conversation=pe(e)}get messages(){return this.conversation}async refreshSystemMessage(e){let n=await Xa(e.rootDir),r=(e.contextWindowTokens??Number.POSITIVE_INFINITY)<=8192,o=e.preferenceContext,s=n;r&&(s&&s.length>3500&&(s=`${s.slice(0,3500)}
|
|
113
|
+
\u2026[project instructions truncated for hub context]`),o&&o.length>600&&(o=`${o.slice(0,600)}
|
|
114
|
+
\u2026[preferences truncated for hub context]`));let i={role:"system",content:Za({rootDir:e.rootDir,mode:e.mode,projectInstructions:s,preferenceContext:o})};this.conversation[0]?.role==="system"?this.conversation[0]=i:this.conversation.unshift(i)}toolResultCharCap(e){return e===void 0?4e3:e<=8192?1200:e<=16384?2e3:4e3}async run(e){if(!e.prompt.trim())throw new Error("Prompt cannot be empty.");if(e.maxSteps!==void 0&&e.maxSteps<1)throw new Error("maxSteps must be at least 1.");let n=e.maxSteps??Va;Yt(e.signal),this.conversation=pe(this.conversation);let r=ic(this.conversation);await this.refreshSystemMessage(e),Yt(e.signal),this.conversation.push({role:"user",content:[e.volatileContext?.trim(),ac(r,Zn(e.prompt)),e.prompt].filter(Boolean).join(`
|
|
115
|
+
|
|
116
|
+
`)});let o={inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0},s=new Set(["read_file","list_files","search_text","git_status","git_diff","workspace_summary"]),i=new Map,a=new Set(["write_file","replace_in_file","make_directory","delete_path","shell"]),c=0,l=0,u=e.contextWindowTokens,m=new Map,d=new Map,p=0,y=0,S=!1,x=this.runtime.definitions(),k=JSON.stringify(x),R=async _=>{l+=1;let I=Vo(this.conversation)??e.prompt,j=cc(this.conversation);this.conversation=[],await this.refreshSystemMessage({...e,contextWindowTokens:u}),this.conversation.push({role:"user",content:I}),j&&this.conversation.push({role:"user",content:`Context reset: hub window was full. Continue without redoing finished work.
|
|
79
117
|
Recent tool results:
|
|
80
|
-
${
|
|
81
|
-
`})};for(let
|
|
82
|
-
`}),this.conversation.push({role:"user",content:
|
|
83
|
-
\u2026[truncated ${
|
|
84
|
-
|
|
85
|
-
`)
|
|
86
|
-
`
|
|
118
|
+
${j}`}),u&&(this.conversation=Yo(this.conversation,{contextWindowTokens:u,toolsJson:k,aggressiveness:2})),await e.onEvent?.({type:"assistant_text",text:`${_} Context reset (${l}/2)\u2026
|
|
119
|
+
`})};for(let _=1;_<=n;_+=1){Yt(e.signal),await e.onEvent?.({type:"step",current:_,maximum:n});let I=!1,j;if(e.maxTotalTokens){let O=o.inputTokens+o.outputTokens+Qt(this.conversation)+Qn(k);if(O>e.maxTotalTokens)throw new Error(`Per-run token budget exceeded (projected ${O}/${e.maxTotalTokens}).`)}try{this.conversation=pe(this.conversation);let v=u?Yo(this.conversation,{contextWindowTokens:u,toolsJson:k,aggressiveness:1}):this.conversation;j=await this.gateway.complete({messages:v,tools:x},{signal:e.signal,onTextDelta:async O=>{I=!0,await e.onEvent?.({type:"assistant_delta",delta:O})},onReasoningDelta:async O=>{I=!0,await e.onEvent?.({type:"reasoning_delta",delta:O})}})}catch(v){if(ec(v)&&c<2){c+=1,this.conversation=pe(this.conversation),await e.onEvent?.({type:"assistant_text",text:`Tool JSON parse failed; cleaned history and guiding a safer retry (${c}/2).
|
|
120
|
+
`}),this.conversation.push({role:"user",content:tc});continue}if(rc(v)&&l<2){let O=oc(v);O&&(u=O.availableTokens),await R("Hub context full."),_-=1;continue}throw v}let N=j.message,h=j.usage?.inputTokens??0,f=j.usage?.outputTokens??0,w=j.usage?.cacheReadTokens??0,g=j.usage?.cacheWriteTokens??0;if(o.inputTokens+=h,o.outputTokens+=f,o.cacheReadTokens+=w,o.cacheWriteTokens+=g,await e.onEvent?.({type:"usage",model:j.model,inputTokens:h,outputTokens:f,...w?{cacheReadTokens:w}:{},...g?{cacheWriteTokens:g}:{}}),this.conversation.push(N),e.maxTotalTokens&&o.inputTokens+o.outputTokens>e.maxTotalTokens)throw new Error(`Per-run token budget exceeded (${o.inputTokens+o.outputTokens}/${e.maxTotalTokens}).`);!I&&N.content?.trim()&&await e.onEvent?.({type:"assistant_text",text:N.content});let b=N.tool_calls??[];if(b.length===0)return{answer:N.content?.trim()||"[The model returned no text.]",messages:[...this.conversation],steps:_,usage:o};for(let v of b){Yt(e.signal);let O;try{O=Jo(v.function.arguments||"{}",`Arguments for ${v.function.name}`)}catch(Y){let at=Y instanceof Error?Y.message:String(Y),xe={role:"tool",tool_call_id:v.id,content:JSON.stringify({ok:!1,output:`${at}. For .env/plain text use write_file with content; for TS/JS with nested quotes use content_b64 or prefer replace_in_file.`})};this.conversation.push(xe);continue}if(v.function.name==="write_file"){let Y=Ho(O),at=(d.get(Y)??0)+1;if(d.set(Y,at),(m.get(Y)??0)>=1&&at>=2){let oo={ok:!0,output:`Refusing repeated write_file to ${Y||"(missing path)"}: already succeeded earlier this turn. Stop retrying. Use read_file once only if needed, then finish.`};await e.onEvent?.({type:"tool_start",call:v,args:O}),await e.onEvent?.({type:"tool_result",call:v,result:oo}),this.conversation.push({role:"tool",tool_call_id:v.id,content:JSON.stringify(oo)}),p<2&&(p+=1,this.conversation.push({role:"user",content:nc}));continue}}await e.onEvent?.({type:"tool_start",call:v,args:O});let H=await this.permissions.authorize(v.function.name,O,e.mode,e.approvalHandler,{bypassPermissions:e.bypassPermissions});if(await e.onEvent?.({type:"permission",request:H,approved:H.approved}),!H.approved){this.conversation.push({role:"tool",tool_call_id:v.id,content:JSON.stringify({ok:!1,output:`Permission denied: ${H.reason}`,permission:H.category})});continue}let ce=`${v.function.name}:${v.function.arguments}`;if(s.has(v.function.name)&&i.has(ce)){let Y=i.get(ce);if(this.conversation.some(xe=>xe.role==="tool"&&xe.tool_call_id===Y)){let xe={ok:!0,output:"Unchanged: this is an identical repeat of an earlier call whose result is already above. Use it directly."};await e.onEvent?.({type:"tool_result",call:v,result:xe}),this.conversation.push({role:"tool",tool_call_id:v.id,content:JSON.stringify(xe)});continue}}let te=await this.runtime.execute(v.function.name,O,{rootDir:e.rootDir,mode:e.mode,signal:e.signal,...e.onEvent?{onOutput:Y=>{e.onEvent?.({type:"tool_output",call:v,chunk:Y})}}:{}});if(s.has(v.function.name)&&te.ok&&i.set(ce,v.id),te.ok&&a.has(v.function.name)&&i.clear(),await e.onEvent?.({type:"tool_result",call:v,result:te}),te.ok){if(y=0,v.function.name==="write_file"){let Y=Ho(O);m.set(Y,(m.get(Y)??0)+1)}}else y+=1;if(y>=12)throw new Error(`Agent stopped after ${y} consecutive tool failures.`);y>=6&&!S&&(S=!0,this.conversation.push({role:"user",content:"Six consecutive tool calls have failed. Stop retrying, explain what is blocking you, and report what you have so far."}));let ye=JSON.stringify(te),In=this.toolResultCharCap(u),aa=ye.length<=In?ye:`${ye.slice(0,In)}
|
|
121
|
+
\u2026[truncated ${ye.length-In} chars to fit local hub context]`;this.conversation.push({role:"tool",tool_call_id:v.id,content:aa})}}let P=e.maxSteps===void 0?"internal step backstop":`${e.maxSteps}-step`;throw new Error(`Agent stopped after reaching the ${P} safety limit.`)}async compact(e){let n=this.conversation.length,r=this.conversation.find(l=>l.role==="system"),o=Vo(this.conversation)??"Continue the current task.",s=this.conversation.filter(l=>l.role!=="system").map(l=>Qo(l)).join(`
|
|
122
|
+
|
|
123
|
+
`).slice(-24e3);if(!s.trim())return{before:n,after:n};let a=((await this.gateway.complete({messages:[{role:"system",content:"You compress coding-agent transcripts. Produce a dense brief that preserves the task, key decisions, files changed, exact commands with their outcomes, and remaining work. Plain prose, no preamble, at most 400 words."},{role:"user",content:s}],tools:[]},{signal:e})).message.content??"").trim().slice(0,4e3);if(!a)return{before:n,after:n};let c=[];return r&&c.push({role:"system",content:r.content}),c.push({role:"user",content:`Conversation summary so far (context was compacted):
|
|
124
|
+
${a}`}),c.push({role:"user",content:o}),this.conversation=pe(c),{before:n,after:this.conversation.length}}};import{mkdir as lc,readFile as uc,rename as dc,stat as mc,writeFile as pc}from"node:fs/promises";import{randomUUID as es}from"node:crypto";import tr from"node:path";async function fc(t){try{return await mc(t),!0}catch{return!1}}async function er(t,e){await lc(tr.dirname(t),{recursive:!0});let n=`${t}.${es()}.tmp`;await pc(n,`${JSON.stringify(e,null,2)}
|
|
125
|
+
`,"utf8"),await dc(n,t)}function gc(t,e){let n;try{n=JSON.parse(t)}catch(o){throw new Error(`Invalid memory JSON in ${e}: ${o instanceof Error?o.message:String(o)}`)}if(typeof n!="object"||n===null||Array.isArray(n))throw new Error("Memory document must be an object.");let r=n;if(r.schemaVersion!==1||!Array.isArray(r.entries))throw new Error("Unsupported memory document schema.");return r}var Xt=class{rootDir;filePath;constructor(e){this.rootDir=tr.resolve(e),this.filePath=tr.join(this.rootDir,E,"memory.json")}async readDocument(){return await fc(this.filePath)?gc(await uc(this.filePath,"utf8"),this.filePath):{schemaVersion:1,entries:[]}}async list(){return[...(await this.readDocument()).entries].sort((n,r)=>r.updatedAt.localeCompare(n.updatedAt))}async add(e,n="user"){let r=e.trim();if(!r)throw new Error("Memory text cannot be empty.");if(r.length>4e3)throw new Error("A memory entry cannot exceed 4,000 characters.");let o=await this.readDocument(),s=o.entries.find(c=>c.text.toLowerCase()===r.toLowerCase());if(s)return s;let i=new Date().toISOString(),a={id:es(),text:r,createdAt:i,updatedAt:i,source:n};return o.entries.push(a),await er(this.filePath,o),a}async remove(e){let n=await this.readDocument(),r=n.entries.filter(s=>s.id.startsWith(e));if(r.length===0)throw new Error(`Memory entry not found: ${e}`);if(r.length>1)throw new Error(`Memory entry prefix is ambiguous: ${e}`);let o=r[0];return n.entries=n.entries.filter(s=>s.id!==o.id),await er(this.filePath,n),o}async clear(){let n=(await this.readDocument()).entries.length;return await er(this.filePath,{schemaVersion:1,entries:[]}),n}async renderForPrompt(e=12e3){let n=await this.list(),r=[],o=0;for(let s of n){let i=`- ${s.text}`;if(o+i.length+1>e)break;r.push(i),o+=i.length+1}return r.join(`
|
|
126
|
+
`)}};import{mkdir as hc,readFile as wc,rename as yc,stat as bc,writeFile as vc}from"node:fs/promises";import{randomUUID as ts}from"node:crypto";import ns from"node:path";async function kc(t){try{return await bc(t),!0}catch{return!1}}async function xc(t){try{return JSON.parse(await wc(t,"utf8"))}catch{return{schemaVersion:1,todos:[]}}}async function Zt(t,e){await hc(ns.dirname(t),{recursive:!0});let n=`${t}.${ts()}.tmp`;await vc(n,`${JSON.stringify(e,null,2)}
|
|
127
|
+
`,"utf8"),await yc(n,t)}var en=class{rootDir;filePath;constructor(e){this.rootDir=e,this.filePath=ns.join(e,E,"todos.json")}async list(){return await kc(this.filePath)?(await xc(this.filePath)).todos??[]:[]}async open(){return(await this.list()).filter(e=>!e.completed)}async add(e){let n=e.trim();if(!n)throw new Error("Todo text is required.");let r=await this.list(),o={id:ts(),text:n,completed:!1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return r.push(o),await Zt(this.filePath,{schemaVersion:1,todos:r}),o}async complete(e){let n=await this.list(),r=s=>s.id.startsWith(e),o=n.find(r);if(!o)throw new Error(`No todo matches "${e}".`);return o.completed=!0,o.updatedAt=new Date().toISOString(),await Zt(this.filePath,{schemaVersion:1,todos:n}),o}async remove(e){let n=await this.list(),r=i=>i.id.startsWith(e),o=n.findIndex(r);if(o===-1)throw new Error(`No todo matches "${e}".`);let[s]=n.splice(o,1);return await Zt(this.filePath,{schemaVersion:1,todos:n}),s}async clear(){let n=(await this.list()).length;return await Zt(this.filePath,{schemaVersion:1,todos:[]}),n}async renderForPrompt(){let e=await this.open();return e.length===0?"":`Open project todos (track with /todo, mark done with /todo done <id>):
|
|
128
|
+
`+e.map(n=>`- [ ] ${n.text} (${n.id.slice(0,8)})`).join(`
|
|
129
|
+
`)}};import{mkdir as Sc,readFile as rs,readdir as Tc,rename as Pc,rm as Ec,stat as Rc,writeFile as Cc}from"node:fs/promises";import{randomUUID as os}from"node:crypto";import tn from"node:path";async function Mc(t){try{return await Rc(t),!0}catch{return!1}}async function $c(t,e){await Sc(tn.dirname(t),{recursive:!0});let n=`${t}.${os()}.tmp`;await Cc(n,`${JSON.stringify(e,null,2)}
|
|
130
|
+
`,"utf8"),await Pc(n,t)}var nn=class{rootDir;constructor(e){this.rootDir=e}dir(e){return tn.join(this.rootDir,E,"checkpoints",e)}file(e,n){return tn.join(this.dir(e),`${n}.json`)}async save(e,n,r){let o=os(),s={id:o,label:(r??"").trim()||`checkpoint ${new Date().toISOString()}`,createdAt:new Date().toISOString(),sessionId:e,messages:n};return await $c(this.file(e,o),s),s}async list(e){let n=this.dir(e);if(!await Mc(n))return[];let r=(await Tc(n)).filter(s=>s.endsWith(".json")),o=[];for(let s of r)try{let i=JSON.parse(await rs(tn.join(n,s),"utf8"));o.push({id:i.id,label:i.label,createdAt:i.createdAt,sessionId:i.sessionId})}catch{}return o.sort((s,i)=>s.createdAt.localeCompare(i.createdAt))}async load(e,n){let o=(await this.list(e)).find(s=>s.id.startsWith(n));if(!o)throw new Error(`No checkpoint matches "${n}".`);return JSON.parse(await rs(this.file(e,o.id),"utf8"))}async remove(e,n){let o=(await this.list(e)).find(s=>s.id.startsWith(n));if(!o)throw new Error(`No checkpoint matches "${n}".`);await Ec(this.file(e,o.id),{force:!0})}};function Te(t){return t.replace(/\/+$/,"")}function nr(t){let e=typeof t=="string"&&t.trim()?`: ${t}`:"",n=new Error(`Model request cancelled${e}`);return n.name="AbortError",n}function _c(t,e){let n=new AbortController,r=setTimeout(()=>n.abort("request timeout"),t),o=()=>n.abort(e?.reason);return e?.aborted?n.abort(e.reason):e?.addEventListener("abort",o,{once:!0}),{signal:n.signal,cleanup:()=>{clearTimeout(r),e?.removeEventListener("abort",o)}}}async function fe(t,e,n,r){let o=_c(r,n.signal);try{let s=await fetch(t,{...e,signal:o.signal}),i=await s.text(),a={};if(i)try{a=JSON.parse(i)}catch{throw new Error(`Model endpoint returned non-JSON data (HTTP ${s.status}): ${i.slice(0,500)}`)}if(!s.ok){let c=a?.error?.message??a?.message??a?.detail??`HTTP ${s.status}`;throw new Error(`Model request failed: ${c}`)}return a}catch(s){throw n.signal?.aborted?nr(n.signal.reason):s}finally{o.cleanup()}}async function ge(t,e){t.content&&await e.onTextDelta?.(t.content)}function qe(t){let e=[],n=o=>{typeof o=="string"&&o.trim()&&e.push(o)};for(let o of t?.content??[])(o?.type==="thinking"||o?.type==="redacted_thinking")&&n(o.thinking);for(let o of t?.message?.content??[])if(typeof o=="string")n(o);else if(o?.type==="text"){let s=typeof o.text=="string"?o.text:JSON.stringify(o.text??"");n(s.replace(/\s*\(reasoning:\s*([\s\S]*?)\)\s*$/,"$1"))}else if(o?.type==="reasoning"){let s=typeof o.summary=="string"?o.summary:Array.isArray(o.summary)?o.summary.map(i=>typeof i?.text=="string"?i.text:"").join(""):"";n(s)}for(let o of t?.candidates?.[0]?.content?.parts??[])typeof o?.thought=="string"&&n(o.thought);let r=t?.usage;if(r){let o=typeof r.reasoning_tokens=="number"?`${r.reasoning_tokens} reasoning tokens`:"";o&&e.push(o)}return e.join(`
|
|
131
|
+
`)}async function he(t,e){if(!e.onReasoningDelta)return;let n=qe(t);n&&await e.onReasoningDelta(n)}function ss(t){return t.map(e=>({type:"function",name:e.function.name,description:e.function.description,parameters:e.function.parameters,strict:e.function.strict}))}function is(t){let e=[];for(let n of t){if(n.role==="system"||n.role==="user"){e.push({role:n.role,content:n.content});continue}if(n.role==="assistant"){n.content&&e.push({role:"assistant",content:n.content});for(let r of n.tool_calls??[])e.push({type:"function_call",call_id:r.id,name:r.function.name,arguments:r.function.arguments});continue}e.push({type:"function_call_output",call_id:n.tool_call_id,output:n.content})}return e}function as(t){let e=[],n=[];for(let o of t?.output??[])if(o?.type==="message")for(let s of o.content??[])s?.type==="output_text"&&typeof s.text=="string"&&e.push(s.text);else o?.type==="function_call"&&typeof o.name=="string"&&n.push({id:o.call_id??o.id??`tool_call_${n.length+1}`,type:"function",function:{name:o.name,arguments:typeof o.arguments=="string"?o.arguments:JSON.stringify(o.arguments??{})}});return{message:{role:"assistant",content:e.length?e.join(""):null,...n.length?{tool_calls:n}:{}},model:t?.model,usage:{inputTokens:t?.usage?.input_tokens,outputTokens:t?.usage?.output_tokens}}}function Ac(t){return t.map(e=>e.role==="tool"?`tool(${e.tool_call_id}): ${e.content}`:e.role==="assistant"&&e.tool_calls?.length?`assistant: ${e.content??""}
|
|
87
132
|
tool calls: ${JSON.stringify(e.tool_calls)}`:`${e.role}: ${e.content??""}`).join(`
|
|
88
133
|
|
|
89
|
-
`)}function
|
|
90
|
-
`)}var
|
|
91
|
-
|
|
92
|
-
`),n=[],
|
|
93
|
-
|
|
94
|
-
`),n=[],
|
|
95
|
-
`).join(""),u=["POST",e.pathname,"",l,c.join(";"),
|
|
96
|
-
`),
|
|
97
|
-
`),
|
|
98
|
-
|
|
99
|
-
`),n=[];for(let
|
|
100
|
-
`)})}};import{spawn as Ii}from"node:child_process";var Vr=[{id:"openai-compatible",name:"OpenAI-compatible Chat Completions",protocol:"POST /v1/chat/completions",auth:["none","api-key","bearer-token"],nativeTools:!0,streaming:!0},{id:"openai-responses",name:"OpenAI Responses API",protocol:"POST /v1/responses",auth:["api-key","bearer-token"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.openai.com/v1"},{id:"anthropic",name:"Anthropic Claude API",protocol:"POST /v1/messages",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.anthropic.com"},{id:"gemini",name:"Google Gemini Developer API",protocol:"models.generateContent",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta"},{id:"xai",name:"xAI Inference API",protocol:"POST /v1/responses",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.x.ai/v1"},{id:"mistral",name:"Mistral AI API",protocol:"POST /v1/chat/completions",auth:["api-key"],nativeTools:!0,streaming:!0,defaultBaseUrl:"https://api.mistral.ai/v1"},{id:"cohere",name:"Cohere v2 Chat API",protocol:"POST /v2/chat",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.cohere.com"},{id:"aws-bedrock",name:"Amazon Bedrock Converse API",protocol:"Converse",auth:["aws-sigv4"],nativeTools:!0,streaming:"buffered-fallback"},{id:"google-vertex",name:"Google Vertex AI",protocol:"publishers/google/models:generateContent",auth:["bearer-token"],nativeTools:!0,streaming:"buffered-fallback"},{id:"azure-openai",name:"Azure OpenAI v1 Responses API",protocol:"POST /openai/v1/responses",auth:["api-key","bearer-token"],nativeTools:!0,streaming:"buffered-fallback"},{id:"github-copilot",name:"GitHub Copilot subscription bridge",protocol:"Official Copilot CLI",auth:["github-subscription"],nativeTools:"bridge-limited",streaming:!1,notes:"Uses copilot login or COPILOT_GITHUB_TOKEN/GH_TOKEN/GITHUB_TOKEN. Model calls are read-only text bridges so kpilot governance remains authoritative."},{id:"chatgpt-codex",name:"ChatGPT subscription through Codex CLI",protocol:"Official Codex CLI",auth:["chatgpt-subscription"],nativeTools:"bridge-limited",streaming:!1,notes:"Uses the official Codex CLI signed in with ChatGPT. It does not treat a ChatGPT subscription as an API key."},{id:"kpilot-hosted",name:"kpilot hosted models",protocol:"POST /v1/ai/responses",auth:["kpilot-account"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.konsolepilot.ai",notes:"Automatically routes prompts to a preferred kpilot model unless a route or model is selected."},{id:"external-agent",name:"Bring-your-own agent",protocol:"kpilot Agent Protocol v1 over HTTP or stdio",auth:["none","bearer-token","external"],nativeTools:!0,streaming:"buffered-fallback",notes:"Runs an operator-provided agent executable or HTTP service."}];function Ee(t){let e=Vr.find(n=>n.id===t);if(!e)throw new Error(`Unknown model provider: ${t}`);return e}async function Di(t,e){return t.length?await new Promise((n,o)=>{let r=Ii(t[0],t.slice(1),{cwd:e,env:process.env,stdio:["ignore","pipe","pipe"]}),s="",i="";r.stdout?.on("data",a=>{s+=String(a)}),r.stderr?.on("data",a=>{i+=String(a)}),r.on("error",o),r.on("close",a=>{a===0?n(s.trim()):o(new Error(`${t.join(" ")} exited with code ${a}: ${i.trim()}`))})}):""}async function ji(t){if(t.accessToken)return t.accessToken;if(t.credentialCommand?.length)return await Di(t.credentialCommand,t.rootDir)}function V(t,e){if(!t)throw new Error(e);return t}async function Ct(t){let e=t.provider??"openai-compatible",n=Ee(e),o=t.model||(e==="github-copilot"||e==="chatgpt-codex"||e==="kpilot-hosted"||e==="external-agent"?"auto":"");if(!o)throw new Error(`A model is required for provider ${e}.`);let r=await ji(t),s;switch(e){case"openai-compatible":s=new ze({baseUrl:t.baseUrl??"https://api.openai.com/v1",model:o,apiKey:t.apiKey??r,headers:t.headers,providerBody:t.providerBody,streaming:t.streaming,timeoutMs:t.timeoutMs,retries:t.retries,maxOutputTokens:t.maxOutputTokens});break;case"openai-responses":s=new ge({baseUrl:t.baseUrl??n.defaultBaseUrl,model:o,apiKey:t.apiKey,accessToken:r,headers:t.headers,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"anthropic":s=new qe({baseUrl:t.baseUrl,model:o,apiKey:V(t.apiKey,"ANTHROPIC_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"gemini":s=new Te({baseUrl:t.baseUrl,model:o,apiKey:t.apiKey,accessToken:r,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"xai":s=new ge({baseUrl:t.baseUrl??n.defaultBaseUrl,model:o,apiKey:V(t.apiKey,"XAI_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"mistral":s=new ze({baseUrl:t.baseUrl??n.defaultBaseUrl,model:o,apiKey:V(t.apiKey,"MISTRAL_API_KEY is required."),headers:t.headers,streaming:t.streaming,timeoutMs:t.timeoutMs,retries:t.retries,maxOutputTokens:t.maxOutputTokens});break;case"cohere":s=new Fe({baseUrl:t.baseUrl,model:o,apiKey:V(t.apiKey,"COHERE_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"aws-bedrock":s=new Je({baseUrl:t.baseUrl,model:o,region:V(t.region,"AWS region is required."),accessKeyId:V(t.awsAccessKeyId,"AWS_ACCESS_KEY_ID is required."),secretAccessKey:V(t.awsSecretAccessKey,"AWS_SECRET_ACCESS_KEY is required."),sessionToken:t.awsSessionToken,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"google-vertex":s=new Te({baseUrl:t.baseUrl,model:o,accessToken:V(r,"Google OAuth access token is required."),project:V(t.project,"Google Cloud project is required."),location:V(t.location,"Vertex AI location is required."),vertex:!0,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"azure-openai":{let i=V(t.baseUrl,"Azure OpenAI base URL ending in /openai/v1 is required."),a=t.apiKey?{"api-key":t.apiKey,...t.headers}:t.headers;s=new ge({baseUrl:i,model:o,accessToken:r,headers:a,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break}case"kpilot-hosted":s=new He({baseUrl:t.baseUrl??n.defaultBaseUrl,accessToken:V(r??t.accessToken,"kpilot account access token is required."),route:t.route??(o==="auto"?"auto":void 0),model:o==="auto"?void 0:o,timeoutMs:t.timeoutMs,headers:t.headers,getAccessToken:t.getAccessToken});break;case"external-agent":s=new We({command:t.command,args:t.commandArgs,endpoint:t.endpoint??t.baseUrl,accessToken:r??t.accessToken??t.apiKey,rootDir:t.rootDir,timeoutMs:t.timeoutMs});break;case"github-copilot":s=new Ke({command:t.command??"copilot",model:o==="default"?void 0:o,rootDir:t.rootDir??process.cwd(),timeoutMs:t.timeoutMs});break;case"chatgpt-codex":s=new Ge({command:t.command??"codex",model:o==="default"?void 0:o,rootDir:t.rootDir??process.cwd(),timeoutMs:t.timeoutMs});break}return{gateway:s,provider:n,resolvedConfig:{...t,provider:e,model:o}}}function gn(t){let e=t?.prompt_tokens_details?.cached_tokens;return typeof e=="number"&&Number.isFinite(e)&&e>=0?e:void 0}function Ui(t){return t.replace(/\/+$/,"")}function Yr(t,e){return e?.aborted?Promise.reject(Ve(e.reason)):new Promise((n,o)=>{let s=setTimeout(()=>{e?.removeEventListener("abort",i),n()},t),i=()=>{clearTimeout(s),e?.removeEventListener("abort",i),o(Ve(e?.reason))};e?.addEventListener("abort",i,{once:!0})})}function Ve(t){let e=typeof t=="string"&&t.trim()?`: ${t}`:"",n=new Error(`Model request cancelled${e}`);return n.name="AbortError",n}function Li(t){return ie(t).map(e=>e.role==="assistant"?{role:"assistant",content:e.content,...e.tool_calls?{tool_calls:e.tool_calls}:{}}:e.role==="tool"?{role:"tool",tool_call_id:e.tool_call_id,content:e.content}:{role:e.role,content:e.content})}function Ni(t){let e=t.choices?.[0]?.message;if(!e)throw new Error(t.error?.message??"The model response did not contain an assistant message.");let n=e.tool_calls?.map((o,r)=>{if(!o.function?.name)throw new Error(`Tool call ${r+1} is missing a function name.`);return{id:o.id??`tool_call_${r+1}`,type:"function",function:{name:o.function.name,arguments:o.function.arguments??"{}"}}});return{role:"assistant",content:typeof e.content=="string"?e.content:null,...n?.length?{tool_calls:n}:{}}}function Qr(t,e){let n=new AbortController,o=setTimeout(()=>n.abort("request timeout"),t),r=()=>n.abort(e?.reason);return e?.aborted?n.abort(e.reason):e?.addEventListener("abort",r,{once:!0}),{controller:n,cleanup:()=>{clearTimeout(o),e?.removeEventListener("abort",r)}}}function Xr(t,e){if(t instanceof Error&&t.name==="AbortError")return t;let n=t instanceof Error?t.message:String(t);return/fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|network/i.test(n)?new Error(`Model hub unreachable at ${e} (${n}). Check that llama-server/Cockpit is still running.`):t instanceof Error?t:new Error(n)}function Bi(t){return!/unreachable|fetch failed|ECONNREFUSED|ECONNRESET|ENOTFOUND/i.test(t.message)}var ze=class{options;constructor(e){if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Ui(e.baseUrl),model:e.model,timeoutMs:e.timeoutMs??12e4,retries:e.retries??2,streaming:e.streaming??!0}}async complete(e,n={}){return this.options.streaming&&n.onTextDelta?await this.completeStreaming(e,n):await this.completeBuffered(e,n)}requestBody(e,n){return{model:this.options.model,messages:Li(e.messages),tools:e.tools,tool_choice:"auto",...this.options.maxOutputTokens===void 0?{}:{max_tokens:this.options.maxOutputTokens},...n?{stream:!0,stream_options:{include_usage:!0}}:{},...this.options.providerBody&&Object.keys(this.options.providerBody).length>0?{provider:this.options.providerBody}:{}}}requestHeaders(){return{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{},...this.options.headers}}async completeBuffered(e,n){let o;for(let r=0;r<=this.options.retries;r+=1){let s=Qr(this.options.timeoutMs,n.signal);try{let i=await fetch(`${this.options.baseUrl}/chat/completions`,{method:"POST",signal:s.controller.signal,headers:this.requestHeaders(),body:JSON.stringify(this.requestBody(e,!1))}),a=await i.text(),c;try{c=JSON.parse(a)}catch{throw new Error(`Model endpoint returned non-JSON data (HTTP ${i.status}): ${a.slice(0,500)}`)}if(!i.ok){let u=c.error?.message??`HTTP ${i.status}`;if((i.status===408||i.status===409||i.status===429||i.status>=500)&&r<this.options.retries){await Yr(500*2**r,n.signal);continue}throw new Error(`Model request failed: ${u}`)}let l=c.choices?.[0]?.message?.reasoning_content;return l&&n.onReasoningDelta&&await n.onReasoningDelta(l),{message:Ni(c),model:c.model,usage:{inputTokens:c.usage?.prompt_tokens,outputTokens:c.usage?.completion_tokens,...gn(c.usage)===void 0?{}:{cacheReadTokens:gn(c.usage)}}}}catch(i){if(o=n.signal?.aborted?Ve(n.signal.reason):Xr(i,this.options.baseUrl),o.name==="AbortError")break;if(r<this.options.retries&&Bi(o)){await Yr(500*2**r,n.signal);continue}break}finally{s.cleanup()}}throw o??new Error("Model request failed for an unknown reason.")}async completeStreaming(e,n){let o=Qr(this.options.timeoutMs,n.signal);try{let r=await fetch(`${this.options.baseUrl}/chat/completions`,{method:"POST",signal:o.controller.signal,headers:this.requestHeaders(),body:JSON.stringify(this.requestBody(e,!0))});if(!r.ok){let h=await r.text(),w=`HTTP ${r.status}`;try{w=JSON.parse(h).error?.message??w}catch{h&&(w=h.slice(0,500))}throw new Error(`Model request failed: ${w}`)}if(!r.body)throw new Error("Model endpoint returned no streaming response body.");let s=r.body.getReader(),i=new TextDecoder,a="",c="",l="",u,d,p,b,f=new Map,y=async h=>{let w=h.trim();if(!w||w.startsWith(":")||!w.startsWith("data:"))return!1;let k=w.slice(5).trim();if(k==="[DONE]")return!0;let C;try{C=JSON.parse(k)}catch{throw new Error(`Invalid streaming JSON chunk: ${k.slice(0,300)}`)}if(C.error?.message)throw new Error(`Model request failed: ${C.error.message}`);u=C.model??u,d=C.usage?.prompt_tokens??d,p=C.usage?.completion_tokens??p,b=gn(C.usage)??b;let S=C.choices?.[0]?.delta;typeof S?.content=="string"&&S.content&&(c+=S.content,await n.onTextDelta?.(S.content)),typeof S?.reasoning_content=="string"&&S.reasoning_content&&(l+=S.reasoning_content,await n.onReasoningDelta?.(S.reasoning_content));for(let A of S?.tool_calls??[]){let se=A.index??f.size,le=f.get(se)??{id:A.id??`tool_call_${se+1}`,type:"function",function:{name:"",arguments:""}};A.id&&(le.id=A.id),A.function?.name&&(le.function.name+=A.function.name),A.function?.arguments&&(le.function.arguments+=A.function.arguments),f.set(se,le)}return!1},m=!1;for(;!m;){if(n.signal?.aborted)throw Ve(n.signal.reason);let h=await s.read();a+=i.decode(h.value??new Uint8Array,{stream:!h.done});let w=a.split(/\r?\n/);a=w.pop()??"";for(let k of w)if(await y(k)){m=!0;break}if(h.done){a.trim()&&await y(a);break}}let g=[...f.entries()].sort(([h],[w])=>h-w).map(([,h],w)=>{if(!h.function.name)throw new Error(`Streaming tool call ${w+1} is missing a function name.`);return h});return{message:{role:"assistant",content:c||null,...g.length?{tool_calls:g}:{}},model:u,usage:{inputTokens:d,outputTokens:p,...b===void 0?{}:{cacheReadTokens:b}}}}catch(r){throw n.signal?.aborted?Ve(n.signal.reason):Xr(r,this.options.baseUrl)}finally{o.cleanup()}}};var he=["fast","balanced","complex","reasoning","large-context","vision","security"];function Ye(t){return he.includes(t)}var qi=[{route:"vision",score:8,words:["image","screenshot","diagram","visual","ui mockup","photo","video","multimodal"]},{route:"security",score:7,words:["security","security audit","vulnerability","vulnerabilities","threat model","penetration test","xss","csrf","sql injection","authentication bypass","authorization bypass","cryptography","secret leak","owasp"]},{route:"reasoning",score:6,words:["prove","root cause","deep analysis","formal","algorithm","optimize","concurrency","race condition","distributed","debug complex"]},{route:"complex",score:5,words:["architecture","migration","repository-wide","large refactor","multi-service","implement feature","production-ready","redesign","framework upgrade"]},{route:"balanced",score:3,words:["fix","refactor","test","review","implement","bug","api","database","typescript"]},{route:"fast",score:2,words:["rename","explain","summarize","format","typo","comment","small change","documentation"]}];function hn(t,e={}){return e.hasImages?{route:"vision",confidence:.99,reason:"The request includes image input."}:(e.estimatedContextTokens??0)>=18e4||t.length>=8e4?{route:"large-context",confidence:.96,reason:"The request requires an unusually large context window."}:null}function Rt(t,e={}){let n=hn(t,e);if(n)return n;let o=t.toLowerCase(),r=new Map;for(let l of qi)for(let u of l.words)o.includes(u)&&r.set(l.route,(r.get(l.route)??0)+l.score);t.length>12e3&&r.set("large-context",(r.get("large-context")??0)+5),t.length>3e3&&r.set("complex",(r.get("complex")??0)+2),/\b(one[- ]?liner|quick|simple|minor)\b/.test(o)&&r.set("fast",(r.get("fast")??0)+3);let s=[...r.entries()].sort((l,u)=>u[1]-l[1]),i=s[0];if(!i)return{route:"balanced",confidence:.55,reason:"No specialist signal was strong enough; using the balanced coding model."};let a=s[1]?.[1]??0,c=Math.min(.98,.58+Math.max(0,i[1]-a)*.05);return{route:i[0],confidence:c,reason:`Prompt signals matched the ${i[0]} route.`}}import{spawn as Gi}from"node:child_process";var Zr="2025-11-25",eo=new Set([Zr,"2025-06-18","2025-03-26"]);function W(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be an object.`);return t}function Mt(t){return t.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/^_+|_+$/g,"")||"unnamed"}function to(t){if(!t)return"[MCP tool returned no result]";let e=W(t,"MCP tool result"),n=e.content;if(!Array.isArray(n))return JSON.stringify(t,null,2);let o=[];for(let r of n){if(!r||typeof r!="object"||Array.isArray(r))continue;let s=r;s.type==="text"&&typeof s.text=="string"?o.push(s.text):o.push(JSON.stringify(s))}return e.structuredContent!==void 0&&o.push(JSON.stringify(e.structuredContent,null,2)),o.join(`
|
|
101
|
-
`)||JSON.stringify(t,null,2)}var
|
|
102
|
-
`)}notify(e,n){this.write({jsonrpc:"2.0",method:e,params:n})}async request(e,n,
|
|
103
|
-
`);for(;a!==-1;){let c=
|
|
104
|
-
`)}}}async consumeJson(e){let n=await e.text();n.trim()&&this.routeMessage(this.safelyParse(n))}safelyParse(e){try{return JSON.parse(e)}catch{return null}}routeMessage(e){if(!e||e.id===void 0||typeof e.id!="number"||!("result"in e)&&!e.error)return;let n=this.pending.get(e.id);n&&(clearTimeout(n.timer),this.pending.delete(e.id),e.error?n.reject(new Error(`MCP ${this.name}: ${e.error.message??`error ${e.error.code??"unknown"}`}`)):n.resolve(e.result??null))}async listTools(e){await this.connect(e);let n=[],
|
|
105
|
-
`);for(;a!==-1;){let c=
|
|
106
|
-
`)}if(i&&
|
|
107
|
-
`)}var
|
|
108
|
-
`,"utf8"),await
|
|
109
|
-
`)}};import{mkdir as
|
|
110
|
-
`,"utf8"),await
|
|
134
|
+
`)}function rr(t,e){let n=e.map(r=>({name:r.function.name,description:r.function.description,parameters:r.function.parameters}));return["You are acting as a read-only model backend for kpilot.","Answer the latest user request directly. Do not modify files or run commands.","The following tool definitions are informational only; this bridge does not permit tool execution.",JSON.stringify(n),"",Ac(t)].join(`
|
|
135
|
+
`)}var $e=class{options;constructor(e){if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Te(e.baseUrl),model:e.model,timeoutMs:e.timeoutMs??12e4}}async complete(e,n={}){let r=this.options.accessToken??this.options.apiKey,o=await fe(`${this.options.baseUrl}/responses`,{method:"POST",headers:{"content-type":"application/json",...r?{authorization:`Bearer ${r}`}:{},...this.options.headers},body:JSON.stringify({model:this.options.model,input:is(e.messages),tools:ss(e.tools),tool_choice:"auto",...this.options.maxOutputTokens===void 0?{}:{max_output_tokens:this.options.maxOutputTokens}})},n,this.options.timeoutMs),s=as(o);return await he(o,n),await ge(s.message,n),s}};function Oc(t){let e=t.filter(s=>s.role==="system").map(s=>s.content).join(`
|
|
136
|
+
|
|
137
|
+
`),n=[],r=new Map;for(let s of t)if(s.role!=="system")if(s.role==="user")n.push({role:"user",content:s.content});else if(s.role==="assistant"){let i=[];s.content&&i.push({type:"text",text:s.content});for(let a of s.tool_calls??[]){r.set(a.id,a.function.name);let c={};try{c=JSON.parse(a.function.arguments)}catch{c={raw:a.function.arguments}}i.push({type:"tool_use",id:a.id,name:a.function.name,input:c})}n.push({role:"assistant",content:i})}else{let i=n[n.length-1],a={type:"tool_result",tool_use_id:s.tool_call_id,content:s.content};i?.role==="user"&&Array.isArray(i.content)?i.content.push(a):n.push({role:"user",content:[a]})}let o=e?[{type:"text",text:e,cache_control:{type:"ephemeral"}}]:void 0;return{...o?{system:o}:{},messages:n}}var ut=class{options;constructor(e){if(!e.apiKey)throw new Error("Anthropic API key is required.");if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Te(e.baseUrl??"https://api.anthropic.com"),model:e.model,maxTokens:e.maxOutputTokens??e.maxTokens??16384,anthropicVersion:e.anthropicVersion??"2023-06-01",timeoutMs:e.timeoutMs??12e4}}async complete(e,n={}){let r=Oc(e.messages),o=await fe(`${this.options.baseUrl}/v1/messages`,{method:"POST",headers:{"content-type":"application/json","x-api-key":this.options.apiKey,"anthropic-version":this.options.anthropicVersion},body:JSON.stringify({model:this.options.model,max_tokens:this.options.maxTokens,...r,tools:e.tools.map((c,l,u)=>({name:c.function.name,description:c.function.description,input_schema:c.function.parameters,...l===u.length-1?{cache_control:{type:"ephemeral"}}:{}}))})},n,this.options.timeoutMs),s=[],i=[];for(let c of o?.content??[])c?.type==="text"&&typeof c.text=="string"&&s.push(c.text),c?.type==="tool_use"&&typeof c.name=="string"&&i.push({id:c.id??`tool_call_${i.length+1}`,type:"function",function:{name:c.name,arguments:JSON.stringify(c.input??{})}});let a={role:"assistant",content:s.length?s.join(""):null,...i.length?{tool_calls:i}:{}};return await he(o,n),await ge(a,n),{message:a,model:o?.model,usage:{inputTokens:o?.usage?.input_tokens,outputTokens:o?.usage?.output_tokens,...o?.usage?.cache_read_input_tokens===void 0&&o?.usage?.cache_creation_input_tokens===void 0?{}:{...o.usage.cache_read_input_tokens===void 0?{}:{cacheReadTokens:o.usage.cache_read_input_tokens},...o.usage.cache_creation_input_tokens===void 0?{}:{cacheWriteTokens:o.usage.cache_creation_input_tokens}}}}}};function Ic(t){let e=t.filter(o=>o.role==="system").map(o=>o.content).join(`
|
|
138
|
+
|
|
139
|
+
`),n=[],r=new Map;for(let o of t)if(o.role!=="system")if(o.role==="user")n.push({role:"user",parts:[{text:o.content}]});else if(o.role==="assistant"){let s=[];o.content&&s.push({text:o.content});for(let i of o.tool_calls??[]){r.set(i.id,i.function.name);let a={};try{a=JSON.parse(i.function.arguments)}catch{a={raw:i.function.arguments}}s.push({functionCall:{name:i.function.name,args:a}})}n.push({role:"model",parts:s})}else{let s=r.get(o.tool_call_id)??o.tool_call_id,i={output:o.content};try{i=JSON.parse(o.content)}catch{}n.push({role:"user",parts:[{functionResponse:{name:s,response:i}}]})}return{...e?{systemInstruction:{parts:[{text:e}]}}:{},contents:n}}var Be=class{options;constructor(e){if(!e.model.trim())throw new Error("A model name is required.");if(!e.apiKey&&!e.accessToken)throw new Error("Gemini API key or Google access token is required.");if(e.vertex&&(!e.project||!e.location))throw new Error("Vertex AI requires project and location.");this.options={...e,baseUrl:Te(e.baseUrl??(e.vertex?`https://${e.location}-aiplatform.googleapis.com/v1`:"https://generativelanguage.googleapis.com/v1beta")),model:e.model,vertex:e.vertex??!1,timeoutMs:e.timeoutMs??12e4}}endpoint(){if(this.options.vertex)return`${this.options.baseUrl}/projects/${encodeURIComponent(this.options.project)}/locations/${encodeURIComponent(this.options.location)}/publishers/google/models/${encodeURIComponent(this.options.model)}:generateContent`;let e=this.options.apiKey?`?key=${encodeURIComponent(this.options.apiKey)}`:"";return`${this.options.baseUrl}/models/${encodeURIComponent(this.options.model)}:generateContent${e}`}async complete(e,n={}){let r=Ic(e.messages),o=await fe(this.endpoint(),{method:"POST",headers:{"content-type":"application/json",...this.options.accessToken?{authorization:`Bearer ${this.options.accessToken}`}:{}},body:JSON.stringify({...r,tools:e.tools.length?[{functionDeclarations:e.tools.map(l=>({name:l.function.name,description:l.function.description,parameters:l.function.parameters}))}]:void 0,toolConfig:e.tools.length?{functionCallingConfig:{mode:"AUTO"}}:void 0,...this.options.maxOutputTokens===void 0?{}:{generationConfig:{maxOutputTokens:this.options.maxOutputTokens}}})},n,this.options.timeoutMs),s=o?.candidates?.[0]?.content?.parts??[],i=[],a=[];for(let l of s)typeof l?.text=="string"&&i.push(l.text),l?.functionCall?.name&&a.push({id:l.functionCall.id??`tool_call_${a.length+1}`,type:"function",function:{name:l.functionCall.name,arguments:JSON.stringify(l.functionCall.args??{})}});let c={role:"assistant",content:i.length?i.join(""):null,...a.length?{tool_calls:a}:{}};return await he(o,n),await ge(c,n),{message:c,model:this.options.model,usage:{inputTokens:o?.usageMetadata?.promptTokenCount,outputTokens:o?.usageMetadata?.candidatesTokenCount}}}};var dt=class{options;constructor(e){if(!e.apiKey)throw new Error("Cohere API key is required.");if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Te(e.baseUrl??"https://api.cohere.com"),model:e.model,timeoutMs:e.timeoutMs??12e4}}async complete(e,n={}){let r=await fe(`${this.options.baseUrl}/v2/chat`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${this.options.apiKey}`,"x-client-name":"kpilot"},body:JSON.stringify({model:this.options.model,messages:e.messages.map(c=>c.role==="tool"?{role:"tool",tool_call_id:c.tool_call_id,content:c.content}:c.role==="assistant"?{role:"assistant",content:c.content??"",tool_calls:c.tool_calls}:{role:c.role,content:c.content}),tools:e.tools.map(c=>({type:"function",function:{name:c.function.name,description:c.function.description,parameters:c.function.parameters}})),...this.options.maxOutputTokens===void 0?{}:{max_tokens:this.options.maxOutputTokens}})},n,this.options.timeoutMs),o=[];for(let c of r?.message?.content??[])typeof c?.text=="string"?o.push(c.text):typeof c=="string"&&o.push(c);let i=(r?.message?.tool_calls??r?.tool_calls??[]).map((c,l)=>({id:c.id??`tool_call_${l+1}`,type:"function",function:{name:c.function?.name??c.name,arguments:typeof c.function?.arguments=="string"?c.function.arguments:JSON.stringify(c.function?.arguments??c.parameters??{})}})).filter(c=>!!c.function.name),a={role:"assistant",content:o.length?o.join(""):null,...i.length?{tool_calls:i}:{}};return await he(r,n),await ge(a,n),{message:a,model:this.options.model,usage:{inputTokens:r?.usage?.tokens?.input_tokens??r?.usage?.billed_units?.input_tokens,outputTokens:r?.usage?.tokens?.output_tokens??r?.usage?.billed_units?.output_tokens}}}};import{createHash as Dc,createHmac as ls}from"node:crypto";function cs(t){return Dc("sha256").update(t).digest("hex")}function rn(t,e){return ls("sha256",t).update(e).digest()}function jc(t){let e=t.toISOString().replace(/[:-]|\.\d{3}/g,"");return{timestamp:e,day:e.slice(0,8)}}function Lc(t,e,n,r=new Date){let{timestamp:o,day:s}=jc(r),a={"content-type":"application/json",host:e.host,"x-amz-date":o,...t.sessionToken?{"x-amz-security-token":t.sessionToken}:{}},c=Object.keys(a).sort(),l=c.map(R=>`${R}:${a[R].trim()}
|
|
140
|
+
`).join(""),u=["POST",e.pathname,"",l,c.join(";"),cs(n)].join(`
|
|
141
|
+
`),m=`${s}/${t.region}/bedrock/aws4_request`,d=["AWS4-HMAC-SHA256",o,m,cs(u)].join(`
|
|
142
|
+
`),p=rn(`AWS4${t.secretAccessKey}`,s),y=rn(p,t.region),S=rn(y,"bedrock"),x=rn(S,"aws4_request"),k=ls("sha256",x).update(d).digest("hex");return{"content-type":a["content-type"],"x-amz-date":o,...t.sessionToken?{"x-amz-security-token":t.sessionToken}:{},authorization:`AWS4-HMAC-SHA256 Credential=${t.accessKeyId}/${m}, SignedHeaders=${c.join(";")}, Signature=${k}`}}function Uc(t){let e=t.filter(r=>r.role==="system").map(r=>r.content).join(`
|
|
143
|
+
|
|
144
|
+
`),n=[];for(let r of t)if(r.role!=="system")if(r.role==="user")n.push({role:"user",content:[{text:r.content}]});else if(r.role==="assistant"){let o=[];r.content&&o.push({text:r.content});for(let s of r.tool_calls??[]){let i={};try{i=JSON.parse(s.function.arguments)}catch{i={raw:s.function.arguments}}o.push({toolUse:{toolUseId:s.id,name:s.function.name,input:i}})}n.push({role:"assistant",content:o})}else{let o;try{o={json:JSON.parse(r.content)}}catch{o={text:r.content}}n.push({role:"user",content:[{toolResult:{toolUseId:r.tool_call_id,content:[o]}}]})}return{...e?{system:[{text:e}]}:{},messages:n}}var mt=class{options;constructor(e){if(!e.model.trim())throw new Error("A Bedrock model ID is required.");if(!e.region)throw new Error("AWS region is required.");if(!e.accessKeyId||!e.secretAccessKey)throw new Error("AWS credentials are required.");this.options={...e,model:e.model,region:e.region,accessKeyId:e.accessKeyId,secretAccessKey:e.secretAccessKey,baseUrl:e.baseUrl??`https://bedrock-runtime.${e.region}.amazonaws.com`,timeoutMs:e.timeoutMs??12e4}}async complete(e,n={}){let r=Uc(e.messages),o=JSON.stringify({...r,toolConfig:e.tools.length?{tools:e.tools.map(m=>({toolSpec:{name:m.function.name,description:m.function.description,inputSchema:{json:m.function.parameters}}})),toolChoice:{auto:{}}}:void 0,...this.options.maxOutputTokens===void 0?{}:{inferenceConfig:{maxTokens:this.options.maxOutputTokens}}}),s=new URL(`${this.options.baseUrl.replace(/\/+$/,"")}/model/${encodeURIComponent(this.options.model)}/converse`),i=await fe(s.toString(),{method:"POST",headers:Lc(this.options,s,o),body:o},n,this.options.timeoutMs),a=i?.output?.message?.content??[],c=[],l=[];for(let m of a)typeof m?.text=="string"&&c.push(m.text),m?.toolUse?.name&&l.push({id:m.toolUse.toolUseId??`tool_call_${l.length+1}`,type:"function",function:{name:m.toolUse.name,arguments:JSON.stringify(m.toolUse.input??{})}});let u={role:"assistant",content:c.length?c.join(""):null,...l.length?{tool_calls:l}:{}};return await he(i,n),await ge(u,n),{message:u,model:this.options.model,usage:{inputTokens:i?.usage?.inputTokens,outputTokens:i?.usage?.outputTokens}}}};import{spawn as Nc}from"node:child_process";async function us(t,e,n,r){return await new Promise((o,s)=>{let i=Nc(t,e,{cwd:n.rootDir,env:{...process.env,...n.environment},stdio:["ignore","pipe","pipe"]}),a="",c="",l=setTimeout(()=>i.kill("SIGTERM"),n.timeoutMs??3e5),u=()=>{i.kill("SIGTERM")};r.signal?.addEventListener("abort",u,{once:!0}),i.stdout?.on("data",m=>{a+=String(m)}),i.stderr?.on("data",m=>{c+=String(m)}),i.on("error",m=>{clearTimeout(l),r.signal?.removeEventListener("abort",u),s(m)}),i.on("close",m=>{clearTimeout(l),r.signal?.removeEventListener("abort",u),r.signal?.aborted?s(nr(r.signal.reason)):m!==0?s(new Error(`${t} exited with code ${m}: ${c.trim()||a.trim()}`)):o({stdout:a,stderr:c})})})}function Fc(t){let e=t.split(/\r?\n/).filter(Boolean),n=[];for(let r of e)try{let o=JSON.parse(r),s=[o?.item?.text,o?.item?.content,o?.message?.content,o?.message,o?.text,o?.output_text,o?.content];for(let i of s)typeof i=="string"&&i.trim()&&n.push(i.trim())}catch{}return n.at(-1)??t.trim()}var pt=class{options;constructor(e){this.options=e}async complete(e,n={}){let r=rr(e.messages,e.tools),o=["bash","powershell","list_bash","list_powershell","read_bash","read_powershell","stop_bash","stop_powershell","write_bash","write_powershell","apply_patch","create","edit","list_agents","read_agent","task","write_agent","ask_user","skill","web_fetch"].join(","),s=["-p",r,"-s","--no-ask-user","--allow-tool=read",`--excluded-tools=${o}`,"--disable-builtin-mcps","--no-custom-instructions","--no-experimental","--no-remote","--no-remote-export","--no-auto-update"];this.options.model&&s.push("--model",this.options.model);let{stdout:i}=await us(this.options.command||"copilot",s,this.options,n),a=i.trim();if(!a)throw new Error("GitHub Copilot CLI returned no response. Run `copilot login` and verify the subscription.");return await n.onTextDelta?.(a),{message:{role:"assistant",content:a},model:this.options.model}}},ft=class{options;constructor(e){this.options=e}async complete(e,n={}){let r=rr(e.messages,e.tools),o=["exec","--json","--sandbox","read-only","--skip-git-repo-check"];this.options.model&&o.push("--model",this.options.model),o.push(r);let{stdout:s}=await us(this.options.command||"codex",o,this.options,n),i=Fc(s);if(!i)throw new Error("Codex CLI returned no response. Run `codex login` and sign in with ChatGPT.");return await n.onTextDelta?.(i),{message:{role:"assistant",content:i},model:this.options.model}}};var gt=class{baseUrl;options;constructor(e){if(this.options=e,!e.accessToken)throw new Error("kpilot needs an account to continue. Run `kpilot login`.");this.baseUrl=e.baseUrl.replace(/\/+$/,"")}async complete(e,n={}){let r=new AbortController,o=setTimeout(()=>r.abort("request timeout"),this.options.timeoutMs??18e4),s=()=>r.abort(n.signal?.reason);n.signal?.aborted?r.abort(n.signal.reason):n.signal?.addEventListener("abort",s,{once:!0});let i=await this.options.getAccessToken?.()??this.options.accessToken;try{let a=await fetch(`${this.baseUrl}/v1/ai/responses`,{method:"POST",signal:r.signal,headers:{authorization:`Bearer ${i}`,"content-type":"application/json",...this.options.headers},body:JSON.stringify({route:this.options.route??"auto",...this.options.model?{model:this.options.model}:{},messages:e.messages,tools:e.tools})}),c=await a.text(),l;try{l=c?JSON.parse(c):{}}catch{throw new Error(`kpilot endpoint returned a non-JSON response (HTTP ${a.status}). If this persists, re-run \`kpilot login\`.`)}if(!a.ok){let u=typeof l.message=="string"?l.message:typeof l.error?.message=="string"?l.error.message:`kpilot endpoint returned HTTP ${a.status}.`,m=typeof l.detail=="string"?l.detail:void 0,d=l.attempts??l.error?.attempts,p=Array.isArray(d)&&d.length>0?d.map(y=>`${y.model??"?"}: ${y.error??"unknown error"}`).join(" | "):void 0;throw new Error([u,m&&m!==u?m:void 0,p].filter(y=>!!(y&&y.trim())).join(" "))}if(l.message?.content&&n.onTextDelta&&await n.onTextDelta(l.message.content),n.onReasoningDelta){let u=qe(l);u&&await n.onReasoningDelta(u)}return l}finally{clearTimeout(o),n.signal?.removeEventListener("abort",s)}}};import{spawn as qc}from"node:child_process";function ds(t){if(!t||t.message?.role!=="assistant")throw new Error("External agent response must contain an assistant message.");return t}var ht=class{options;constructor(e){if(this.options=e,!e.command&&!e.endpoint)throw new Error("Bring-your-own-agent requires either command or endpoint.")}async complete(e,n={}){return this.options.endpoint?await this.completeHttp(e,n):await this.completeCommand(e,n)}async completeHttp(e,n){let r=await fetch(this.options.endpoint,{method:"POST",signal:n.signal,headers:{"content-type":"application/json",...this.options.accessToken?{authorization:`Bearer ${this.options.accessToken}`}:{}},body:JSON.stringify({protocol:"kpilot-agent-v1",request:e})}),o=await r.text(),s;try{s=JSON.parse(o)}catch{throw new Error(`External agent returned non-JSON data (HTTP ${r.status}).`)}if(!r.ok)throw new Error(s.message??`External agent returned HTTP ${r.status}.`);let i=ds(s);if(n.onReasoningDelta){let a=qe(s);a&&await n.onReasoningDelta(a)}return i.message.content&&n.onTextDelta&&await n.onTextDelta(i.message.content),i}async completeCommand(e,n){return await new Promise((r,o)=>{let s=qc(this.options.command,this.options.args??[],{cwd:this.options.rootDir??process.cwd(),env:process.env,stdio:["pipe","pipe","pipe"]}),i=setTimeout(()=>s.kill("SIGTERM"),this.options.timeoutMs??18e4),a="",c="",l=()=>{s.kill("SIGTERM")};n.signal?.addEventListener("abort",l,{once:!0}),s.stdout?.on("data",u=>{a+=String(u)}),s.stderr?.on("data",u=>{c+=String(u)}),s.once("error",o),s.once("close",async u=>{if(clearTimeout(i),n.signal?.removeEventListener("abort",l),n.signal?.aborted)return o(n.signal.reason??new Error("External agent cancelled."));if(u!==0)return o(new Error(`External agent exited with code ${u}: ${c.trim().slice(0,1e3)}`));try{let m=ds(JSON.parse(a.trim()));if(n.onReasoningDelta){let d=qe(m);d&&await n.onReasoningDelta(d)}m.message.content&&n.onTextDelta&&await n.onTextDelta(m.message.content),r(m)}catch(m){o(m)}}),s.stdin?.end(`${JSON.stringify({protocol:"kpilot-agent-v1",request:e})}
|
|
145
|
+
`)})}};import{spawn as Bc}from"node:child_process";var ms=[{id:"openai-compatible",name:"OpenAI-compatible Chat Completions",protocol:"POST /v1/chat/completions",auth:["none","api-key","bearer-token"],nativeTools:!0,streaming:!0},{id:"openai-responses",name:"OpenAI Responses API",protocol:"POST /v1/responses",auth:["api-key","bearer-token"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.openai.com/v1"},{id:"anthropic",name:"Anthropic Claude API",protocol:"POST /v1/messages",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.anthropic.com"},{id:"gemini",name:"Google Gemini Developer API",protocol:"models.generateContent",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://generativelanguage.googleapis.com/v1beta"},{id:"xai",name:"xAI Inference API",protocol:"POST /v1/responses",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.x.ai/v1"},{id:"mistral",name:"Mistral AI API",protocol:"POST /v1/chat/completions",auth:["api-key"],nativeTools:!0,streaming:!0,defaultBaseUrl:"https://api.mistral.ai/v1"},{id:"cohere",name:"Cohere v2 Chat API",protocol:"POST /v2/chat",auth:["api-key"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.cohere.com"},{id:"aws-bedrock",name:"Amazon Bedrock Converse API",protocol:"Converse",auth:["aws-sigv4"],nativeTools:!0,streaming:"buffered-fallback"},{id:"google-vertex",name:"Google Vertex AI",protocol:"publishers/google/models:generateContent",auth:["bearer-token"],nativeTools:!0,streaming:"buffered-fallback"},{id:"azure-openai",name:"Azure OpenAI v1 Responses API",protocol:"POST /openai/v1/responses",auth:["api-key","bearer-token"],nativeTools:!0,streaming:"buffered-fallback"},{id:"github-copilot",name:"GitHub Copilot subscription bridge",protocol:"Official Copilot CLI",auth:["github-subscription"],nativeTools:"bridge-limited",streaming:!1,notes:"Uses copilot login or COPILOT_GITHUB_TOKEN/GH_TOKEN/GITHUB_TOKEN. Model calls are read-only text bridges so kpilot governance remains authoritative."},{id:"chatgpt-codex",name:"ChatGPT subscription through Codex CLI",protocol:"Official Codex CLI",auth:["chatgpt-subscription"],nativeTools:"bridge-limited",streaming:!1,notes:"Uses the official Codex CLI signed in with ChatGPT. It does not treat a ChatGPT subscription as an API key."},{id:"kpilot-hosted",name:"kpilot",protocol:"POST /v1/ai/responses",auth:["kpilot-account"],nativeTools:!0,streaming:"buffered-fallback",defaultBaseUrl:"https://api.konsolepilot.ai",notes:"Automatically routes prompts to a preferred kpilot capability unless a route or model is selected."},{id:"external-agent",name:"Bring-your-own agent",protocol:"kpilot Agent Protocol v1 over HTTP or stdio",auth:["none","bearer-token","external"],nativeTools:!0,streaming:"buffered-fallback",notes:"Runs an operator-provided agent executable or HTTP service."}];function Je(t){let e=ms.find(n=>n.id===t);if(!e)throw new Error(`Unknown model provider: ${t}`);return e}async function Jc(t,e){return t.length?await new Promise((n,r)=>{let o=Bc(t[0],t.slice(1),{cwd:e,env:process.env,stdio:["ignore","pipe","pipe"]}),s="",i="";o.stdout?.on("data",a=>{s+=String(a)}),o.stderr?.on("data",a=>{i+=String(a)}),o.on("error",r),o.on("close",a=>{a===0?n(s.trim()):r(new Error(`${t.join(" ")} exited with code ${a}: ${i.trim()}`))})}):""}async function Kc(t){if(t.accessToken)return t.accessToken;if(t.credentialCommand?.length)return await Jc(t.credentialCommand,t.rootDir)}function se(t,e){if(!t)throw new Error(e);return t}async function on(t){let e=t.provider??"openai-compatible",n=Je(e),r=t.model||(e==="github-copilot"||e==="chatgpt-codex"||e==="kpilot-hosted"||e==="external-agent"?"auto":"");if(!r)throw new Error(`A model is required for provider ${e}.`);let o=await Kc(t),s;switch(e){case"openai-compatible":s=new wt({baseUrl:t.baseUrl??"https://api.openai.com/v1",model:r,apiKey:t.apiKey??o,headers:t.headers,providerBody:t.providerBody,streaming:t.streaming,timeoutMs:t.timeoutMs,retries:t.retries,maxOutputTokens:t.maxOutputTokens,...t.sessionId?{sessionId:t.sessionId}:{}});break;case"openai-responses":s=new $e({baseUrl:t.baseUrl??n.defaultBaseUrl,model:r,apiKey:t.apiKey,accessToken:o,headers:t.headers,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"anthropic":s=new ut({baseUrl:t.baseUrl,model:r,apiKey:se(t.apiKey,"ANTHROPIC_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"gemini":s=new Be({baseUrl:t.baseUrl,model:r,apiKey:t.apiKey,accessToken:o,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"xai":s=new $e({baseUrl:t.baseUrl??n.defaultBaseUrl,model:r,apiKey:se(t.apiKey,"XAI_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"mistral":s=new wt({baseUrl:t.baseUrl??n.defaultBaseUrl,model:r,apiKey:se(t.apiKey,"MISTRAL_API_KEY is required."),headers:t.headers,streaming:t.streaming,timeoutMs:t.timeoutMs,retries:t.retries,maxOutputTokens:t.maxOutputTokens});break;case"cohere":s=new dt({baseUrl:t.baseUrl,model:r,apiKey:se(t.apiKey,"COHERE_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"aws-bedrock":s=new mt({baseUrl:t.baseUrl,model:r,region:se(t.region,"AWS region is required."),accessKeyId:se(t.awsAccessKeyId,"AWS_ACCESS_KEY_ID is required."),secretAccessKey:se(t.awsSecretAccessKey,"AWS_SECRET_ACCESS_KEY is required."),sessionToken:t.awsSessionToken,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"google-vertex":s=new Be({baseUrl:t.baseUrl,model:r,accessToken:se(o,"Google OAuth access token is required."),project:se(t.project,"Google Cloud project is required."),location:se(t.location,"Vertex AI location is required."),vertex:!0,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"azure-openai":{let i=se(t.baseUrl,"Azure OpenAI base URL ending in /openai/v1 is required."),a=t.apiKey?{"api-key":t.apiKey,...t.headers}:t.headers;s=new $e({baseUrl:i,model:r,accessToken:o,headers:a,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break}case"kpilot-hosted":s=new gt({baseUrl:t.baseUrl??n.defaultBaseUrl,accessToken:se(o??t.accessToken,"kpilot account access token is required."),route:t.route??(r==="auto"?"auto":void 0),model:r==="auto"?void 0:r,timeoutMs:t.timeoutMs,headers:t.headers,getAccessToken:t.getAccessToken});break;case"external-agent":s=new ht({command:t.command,args:t.commandArgs,endpoint:t.endpoint??t.baseUrl,accessToken:o??t.accessToken??t.apiKey,rootDir:t.rootDir,timeoutMs:t.timeoutMs});break;case"github-copilot":s=new pt({command:t.command??"copilot",model:r==="default"?void 0:r,rootDir:t.rootDir??process.cwd(),timeoutMs:t.timeoutMs});break;case"chatgpt-codex":s=new ft({command:t.command??"codex",model:r==="default"?void 0:r,rootDir:t.rootDir??process.cwd(),timeoutMs:t.timeoutMs});break}return{gateway:s,provider:n,resolvedConfig:{...t,provider:e,model:r}}}function ps(t){let e=t?.prompt_tokens_details?.cached_tokens,n=t?.prompt_tokens_details?.cache_write_tokens;return{...typeof e=="number"&&e>=0?{read:e}:{},...typeof n=="number"&&n>=0?{write:n}:{}}}function Wc(t){return t.replace(/\/+$/,"")}function fs(t,e){return e?.aborted?Promise.reject(yt(e.reason)):new Promise((n,r)=>{let s=setTimeout(()=>{e?.removeEventListener("abort",i),n()},t),i=()=>{clearTimeout(s),e?.removeEventListener("abort",i),r(yt(e?.reason))};e?.addEventListener("abort",i,{once:!0})})}function yt(t){let e=typeof t=="string"&&t.trim()?`: ${t}`:"",n=new Error(`Model request cancelled${e}`);return n.name="AbortError",n}function Gc(t){return pe(t).map(e=>e.role==="assistant"?{role:"assistant",content:e.content,...e.tool_calls?{tool_calls:e.tool_calls}:{}}:e.role==="tool"?{role:"tool",tool_call_id:e.tool_call_id,content:e.content}:{role:e.role,content:e.content})}function Hc(t){let e=t.toLowerCase();return!!(e.includes("claude")||e.startsWith("anthropic/")||/(^|\/)gemini/.test(e)||/qwen[^/]*(?:max|plus)/.test(e)||/qwen3-coder-(?:plus|flash)/.test(e))}function gs(t){return[{type:"text",text:t,cache_control:{type:"ephemeral"}}]}function zc(t){if(t.length===0)return t;let e=t.map(o=>({...o})),n=e[0];n.role==="system"&&typeof n.content=="string"&&(n.content=gs(n.content));let r=e[e.length-1];return r.role==="user"&&typeof r.content=="string"&&(r.content=gs(r.content)),e}function Vc(t){let e=t.choices?.[0]?.message;if(!e)throw new Error(t.error?.message??"The model response did not contain an assistant message.");let n=e.tool_calls?.map((r,o)=>{if(!r.function?.name)throw new Error(`Tool call ${o+1} is missing a function name.`);return{id:r.id??`tool_call_${o+1}`,type:"function",function:{name:r.function.name,arguments:r.function.arguments??"{}"}}});return{role:"assistant",content:typeof e.content=="string"?e.content:null,...n?.length?{tool_calls:n}:{}}}function hs(t,e){let n=new AbortController,r=setTimeout(()=>n.abort("request timeout"),t),o=()=>n.abort(e?.reason);return e?.aborted?n.abort(e.reason):e?.addEventListener("abort",o,{once:!0}),{controller:n,cleanup:()=>{clearTimeout(r),e?.removeEventListener("abort",o)}}}function ws(t,e){if(t instanceof Error&&t.name==="AbortError")return t;let n=t instanceof Error?t.message:String(t);return/fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|network/i.test(n)?new Error(`Model hub unreachable at ${e} (${n}). Check that llama-server/Cockpit is still running.`):t instanceof Error?t:new Error(n)}function Yc(t){return!/unreachable|fetch failed|ECONNREFUSED|ECONNRESET|ENOTFOUND/i.test(t.message)}var wt=class{options;isOpenRouter;constructor(e){if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Wc(e.baseUrl),model:e.model,timeoutMs:e.timeoutMs??12e4,retries:e.retries??2,streaming:e.streaming??!0},this.isOpenRouter=e.openrouter??/openrouter\.ai/i.test(this.options.baseUrl)}async complete(e,n={}){return this.options.streaming&&n.onTextDelta?await this.completeStreaming(e,n):await this.completeBuffered(e,n)}requestBody(e,n){let r=Gc(e.messages);return this.isOpenRouter&&Hc(this.options.model)&&(r=zc(r)),{model:this.options.model,messages:r,tools:e.tools,tool_choice:"auto",...this.options.sessionId?{session_id:this.options.sessionId,prompt_cache_key:this.options.sessionId}:{},...this.options.maxOutputTokens===void 0?{}:{max_tokens:this.options.maxOutputTokens},...n?{stream:!0,stream_options:{include_usage:!0}}:{},...this.options.providerBody&&Object.keys(this.options.providerBody).length>0?{provider:this.options.providerBody}:{}}}requestHeaders(){return{"content-type":"application/json",...this.options.apiKey?{authorization:`Bearer ${this.options.apiKey}`}:{},...this.options.headers}}async completeBuffered(e,n){let r,o=Math.ceil(JSON.stringify(e.messages).length/4),s=this.options.maxRetryPromptTokens??32e3,i=o>s?0:this.options.retries;for(let a=0;a<=i;a+=1){let c=hs(this.options.timeoutMs,n.signal);try{let l=await fetch(`${this.options.baseUrl}/chat/completions`,{method:"POST",signal:c.controller.signal,headers:this.requestHeaders(),body:JSON.stringify(this.requestBody(e,!1))}),u=await l.text(),m;try{m=JSON.parse(u)}catch{throw new Error(`Model endpoint returned non-JSON data (HTTP ${l.status}): ${u.slice(0,500)}`)}if(!l.ok){let y=m.error?.message??`HTTP ${l.status}`;if((l.status===408||l.status===409||l.status===429||l.status>=500)&&a<i){await fs(500*2**a,n.signal);continue}throw new Error(`Model request failed: ${y}`)}let d=m.choices?.[0]?.message?.reasoning_content;d&&n.onReasoningDelta&&await n.onReasoningDelta(d);let p=ps(m.usage);return{message:Vc(m),model:m.model,usage:{inputTokens:m.usage?.prompt_tokens,outputTokens:m.usage?.completion_tokens,...p.read===void 0?{}:{cacheReadTokens:p.read},...p.write===void 0?{}:{cacheWriteTokens:p.write}}}}catch(l){if(r=n.signal?.aborted?yt(n.signal.reason):ws(l,this.options.baseUrl),r.name==="AbortError")break;if(a<i&&Yc(r)){await fs(500*2**a,n.signal);continue}break}finally{c.cleanup()}}throw r??new Error("Model request failed for an unknown reason.")}async completeStreaming(e,n){let r=hs(this.options.timeoutMs,n.signal);try{let o=await fetch(`${this.options.baseUrl}/chat/completions`,{method:"POST",signal:r.controller.signal,headers:this.requestHeaders(),body:JSON.stringify(this.requestBody(e,!0))});if(!o.ok){let P=await o.text(),_=`HTTP ${o.status}`;try{_=JSON.parse(P).error?.message??_}catch{P&&(_=P.slice(0,500))}throw new Error(`Model request failed: ${_}`)}if(!o.body)throw new Error("Model endpoint returned no streaming response body.");let s=o.body.getReader(),i=new TextDecoder,a="",c="",l="",u,m,d,p,y,S=new Map,x=async P=>{let _=P.trim();if(!_||_.startsWith(":")||!_.startsWith("data:"))return!1;let I=_.slice(5).trim();if(I==="[DONE]")return!0;let j;try{j=JSON.parse(I)}catch{throw new Error(`Invalid streaming JSON chunk: ${I.slice(0,300)}`)}if(j.error?.message)throw new Error(`Model request failed: ${j.error.message}`);u=j.model??u,m=j.usage?.prompt_tokens??m,d=j.usage?.completion_tokens??d;let N=ps(j.usage);p=N.read??p,y=N.write??y;let h=j.choices?.[0]?.delta;typeof h?.content=="string"&&h.content&&(c+=h.content,await n.onTextDelta?.(h.content)),typeof h?.reasoning_content=="string"&&h.reasoning_content&&(l+=h.reasoning_content,await n.onReasoningDelta?.(h.reasoning_content));for(let f of h?.tool_calls??[]){let w=f.index??S.size,g=S.get(w)??{id:f.id??`tool_call_${w+1}`,type:"function",function:{name:"",arguments:""}};f.id&&(g.id=f.id),f.function?.name&&(g.function.name+=f.function.name),f.function?.arguments&&(g.function.arguments+=f.function.arguments),S.set(w,g)}return!1},k=!1;for(;!k;){if(n.signal?.aborted)throw yt(n.signal.reason);let P=await s.read();a+=i.decode(P.value??new Uint8Array,{stream:!P.done});let _=a.split(/\r?\n/);a=_.pop()??"";for(let I of _)if(await x(I)){k=!0;break}if(P.done){a.trim()&&await x(a);break}}let R=[...S.entries()].sort(([P],[_])=>P-_).map(([,P],_)=>{if(!P.function.name)throw new Error(`Streaming tool call ${_+1} is missing a function name.`);return P});return{message:{role:"assistant",content:c||null,...R.length?{tool_calls:R}:{}},model:u,usage:{inputTokens:m,outputTokens:d,...p===void 0?{}:{cacheReadTokens:p},...y===void 0?{}:{cacheWriteTokens:y}}}}catch(o){throw n.signal?.aborted?yt(n.signal.reason):ws(o,this.options.baseUrl)}finally{r.cleanup()}}};var _e=["fast","balanced","complex","reasoning","large-context","vision","security"];function bt(t){return _e.includes(t)}var Qc=[{route:"vision",score:8,words:["image","screenshot","diagram","visual","ui mockup","photo","video","multimodal"]},{route:"security",score:7,words:["security","security audit","vulnerability","vulnerabilities","threat model","penetration test","xss","csrf","sql injection","authentication bypass","authorization bypass","cryptography","secret leak","owasp"]},{route:"reasoning",score:6,words:["prove","root cause","deep analysis","formal","algorithm","optimize","concurrency","race condition","distributed","debug complex"]},{route:"complex",score:5,words:["architecture","migration","repository-wide","large refactor","multi-service","implement feature","production-ready","redesign","framework upgrade"]},{route:"balanced",score:3,words:["fix","refactor","test","review","implement","bug","api","database","typescript"]},{route:"fast",score:2,words:["rename","explain","summarize","format","typo","comment","small change","documentation"]}];function or(t,e={}){return e.hasImages?{route:"vision",confidence:.99,reason:"The request includes image input."}:(e.estimatedContextTokens??0)>=18e4||t.length>=8e4?{route:"large-context",confidence:.96,reason:"The request requires an unusually large context window."}:null}function sn(t,e={}){let n=or(t,e);if(n)return n;let r=t.toLowerCase(),o=new Map;for(let l of Qc)for(let u of l.words)r.includes(u)&&o.set(l.route,(o.get(l.route)??0)+l.score);t.length>12e3&&o.set("large-context",(o.get("large-context")??0)+5),t.length>3e3&&o.set("complex",(o.get("complex")??0)+2),/\b(one[- ]?liner|quick|simple|minor)\b/.test(r)&&o.set("fast",(o.get("fast")??0)+3);let s=[...o.entries()].sort((l,u)=>u[1]-l[1]),i=s[0];if(!i)return{route:"balanced",confidence:.55,reason:"No specialist signal was strong enough; using the balanced coding model."};let a=s[1]?.[1]??0,c=Math.min(.98,.58+Math.max(0,i[1]-a)*.05);return{route:i[0],confidence:c,reason:`Prompt signals matched the ${i[0]} route.`}}import{spawn as tl}from"node:child_process";var ys="2025-11-25",bs=new Set([ys,"2025-06-18","2025-03-26"]);function re(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be an object.`);return t}function an(t){return t.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/^_+|_+$/g,"")||"unnamed"}function nl(t,e=200){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function vs(t){if(!t)return"[MCP tool returned no result]";let e=re(t,"MCP tool result"),n=e.content;if(!Array.isArray(n))return JSON.stringify(t,null,2);let r=[];for(let o of n){if(!o||typeof o!="object"||Array.isArray(o))continue;let s=o;s.type==="text"&&typeof s.text=="string"?r.push(s.text):r.push(JSON.stringify(s))}return e.structuredContent!==void 0&&r.push(JSON.stringify(e.structuredContent,null,2)),r.join(`
|
|
146
|
+
`)||JSON.stringify(t,null,2)}var sr=class{name;config;child;nextId=1;buffer="";pending=new Map;initialized=!1;serverInfo={};constructor(e,n){if(!n.command.trim())throw new Error(`MCP server ${e} requires a command.`);this.name=an(e),this.config={...n,args:n.args??[],timeoutMs:n.timeoutMs??3e4,enabled:n.enabled??!0}}async connect(e){if(this.initialized)return;if(!this.config.enabled)throw new Error(`MCP server ${this.name} is disabled.`);this.child=tl(this.config.command,this.config.args,{cwd:this.config.cwd,env:{...process.env,...this.config.env},stdio:["pipe","pipe","pipe"]}),this.child.stdout.setEncoding("utf8"),this.child.stderr.setEncoding("utf8"),this.child.stdout.on("data",o=>this.consume(o)),this.child.stderr.on("data",o=>{}),this.child.once("error",o=>this.failAll(o)),this.child.once("close",o=>{this.initialized=!1,this.failAll(new Error(`MCP server ${this.name} exited with code ${o??1}.`))});let n=re(await this.request("initialize",{protocolVersion:ys,capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.45",description:"Local-first AI coding agent"}},e),"MCP initialize result"),r=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!bs.has(r))throw await this.close(),new Error(`MCP server ${this.name} negotiated unsupported protocol version ${r||"[missing]"}.`);this.serverInfo=re(n.serverInfo,"MCP serverInfo"),this.notify("notifications/initialized",{}),this.initialized=!0}consume(e){this.buffer+=e;let n=this.buffer.split(/\r?\n/);this.buffer=n.pop()??"";for(let r of n){if(!r.trim())continue;let o;try{o=JSON.parse(r)}catch{this.failAll(new Error(`MCP server ${this.name} emitted invalid JSON on stdout.`));continue}if(o.id!==void 0&&(o.result!==void 0||o.error)){let s=this.pending.get(o.id);if(!s)continue;clearTimeout(s.timeout),this.pending.delete(o.id),o.error?s.reject(new Error(`MCP ${this.name}: ${o.error.message??`error ${o.error.code??"unknown"}`}`)):s.resolve(o.result??null)}else o.id!==void 0&&o.method&&this.write({jsonrpc:"2.0",id:o.id,error:{code:-32601,message:`Client method not supported: ${o.method}`}})}}write(e){if(!this.child?.stdin?.writable)throw new Error(`MCP server ${this.name} is not connected.`);this.child.stdin.write(`${JSON.stringify(e)}
|
|
147
|
+
`)}notify(e,n){this.write({jsonrpc:"2.0",method:e,params:n})}async request(e,n,r){if(r?.aborted)throw new Error(`MCP request cancelled: ${String(r.reason??"")}`);let o=this.nextId++;return await new Promise((s,i)=>{let a=setTimeout(()=>{this.pending.delete(o),this.notify("notifications/cancelled",{requestId:o,reason:"timeout"}),i(new Error(`MCP ${this.name} request timed out: ${e}`))},this.config.timeoutMs),c=()=>{clearTimeout(a),this.pending.delete(o);try{this.notify("notifications/cancelled",{requestId:o,reason:"user cancellation"})}catch{}i(new Error(`MCP request cancelled: ${e}`))};r?.addEventListener("abort",c,{once:!0}),this.pending.set(o,{resolve:l=>{r?.removeEventListener("abort",c),s(l)},reject:l=>{r?.removeEventListener("abort",c),i(l)},timeout:a});try{this.write({jsonrpc:"2.0",id:o,method:e,params:n})}catch(l){clearTimeout(a),this.pending.delete(o),i(l instanceof Error?l:new Error(String(l)))}})}async listTools(e){await this.connect(e);let n=[],r;do{let o=re(await this.request("tools/list",r?{cursor:r}:{},e),"MCP tools/list result"),s=o.tools;if(!Array.isArray(s))throw new Error(`MCP server ${this.name} returned an invalid tool list.`);for(let i of s){let a=re(i,"MCP tool");if(typeof a.name!="string")throw new Error(`MCP server ${this.name} returned a tool without a name.`);n.push({name:a.name,title:typeof a.title=="string"?a.title:void 0,description:typeof a.description=="string"?a.description:void 0,inputSchema:re(a.inputSchema,`MCP inputSchema for ${a.name}`)})}r=typeof o.nextCursor=="string"?o.nextCursor:void 0}while(r);return n}async callTool(e,n,r){await this.connect(r);let o=await this.request("tools/call",{name:e,arguments:n},r);return{ok:re(o,"MCP tools/call result").isError!==!0,output:vs(o),metadata:{server:this.name,tool:e}}}info(){return{name:this.name,serverInfo:this.serverInfo,connected:this.initialized}}failAll(e){for(let n of this.pending.values())clearTimeout(n.timeout),n.reject(e);this.pending.clear()}async close(){if(!this.child)return;let e=this.child;this.child=void 0,this.initialized=!1,await new Promise(n=>{let r=!1,o=()=>{r||(r=!0,clearTimeout(s),clearTimeout(i),clearTimeout(a),n())};e.once("close",o),e.stdin?.end();let s=setTimeout(()=>e.kill("SIGTERM"),300),i=setTimeout(()=>e.kill("SIGKILL"),900),a=setTimeout(o,1200)})}},ir=class{name;config;url;nextId=1;pending=new Map;initialized=!1;serverInfo={};constructor(e,n){if(!n.url?.trim())throw new Error(`MCP server ${e} requires url for ${n.transport??"http"} transport.`);let r=new URL(n.url);if(r.protocol!=="http:"&&r.protocol!=="https:")throw new Error(`MCP server ${e} http transport requires an http(s) url; got ${r.protocol}`);this.name=an(e),this.config={...n,timeoutMs:n.timeoutMs??3e4},this.url=r.href}headers(){return{"Content-Type":"application/json",Accept:"application/json, text/event-stream","MCP-Protocol-Version":"2025-06-18",...this.config.token?{Authorization:`Bearer ${this.config.token}`}:{},...this.config.headers}}async connect(e){if(this.initialized)return;if(this.config.enabled===!1)throw new Error(`MCP server ${this.name} is disabled.`);let n=re(await this.request("initialize",{protocolVersion:"2025-06-18",capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.45",description:"Local-first AI coding agent"}},e),"MCP initialize result"),r=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!bs.has(r))throw new Error(`MCP server ${this.name} negotiated unsupported protocol version ${r||"[missing]"}.`);this.serverInfo=re(n.serverInfo,"MCP serverInfo"),this.notify("notifications/initialized",{}),this.initialized=!0}async request(e,n,r){if(r?.aborted)throw new Error(`MCP request cancelled: ${String(r.reason??"")}`);let o=this.nextId++;return await new Promise((s,i)=>{let a=setTimeout(()=>{this.pending.delete(o),this.notify("notifications/cancelled",{requestId:o,reason:"timeout"}),i(new Error(`MCP ${this.name} request timed out: ${e}`))},this.config.timeoutMs),c=()=>{clearTimeout(a),this.pending.delete(o);try{this.notify("notifications/cancelled",{requestId:o,reason:"user cancellation"})}catch{}i(new Error(`MCP request cancelled: ${e}`))};r?.addEventListener("abort",c,{once:!0});let l=u=>{r?.removeEventListener("abort",c),u()};this.pending.set(o,{resolve:u=>l(()=>s(u)),reject:u=>l(()=>i(u)),timer:a}),this.postBody({jsonrpc:"2.0",id:o,method:e,params:n}).then(u=>this.consumeResponse(u)).catch(u=>{let m=this.pending.get(o);m&&(clearTimeout(m.timer),this.pending.delete(o),l(()=>i(u instanceof Error?u:new Error(String(u)))))})})}notify(e,n){return this.postBody({jsonrpc:"2.0",method:e,params:n}).then(r=>{r?.body?.cancel().catch(()=>{})}).catch(()=>{})}async postBody(e){return await fetch(this.url,{method:"POST",headers:this.headers(),body:JSON.stringify(e),signal:AbortSignal.timeout(this.config.timeoutMs)})}async consumeResponse(e){let n=e.headers.get("content-type")??"";n.includes("text/event-stream")?await this.consumeSse(e):n.includes("application/json")?await this.consumeJson(e):await e.body?.cancel().catch(()=>{})}async consumeSse(e){if(!e.body)return;let n=e.body.getReader(),r=new TextDecoder,o="";for(;;){let{done:s,value:i}=await n.read();if(s)break;o+=r.decode(i,{stream:!0});let a=o.indexOf(`
|
|
148
|
+
`);for(;a!==-1;){let c=o.slice(0,a).trim();if(o=o.slice(a+1),c.startsWith("data:")){let l=c.slice(5).trim();l&&this.routeMessage(this.safelyParse(l))}a=o.indexOf(`
|
|
149
|
+
`)}}}async consumeJson(e){let n=await e.text();n.trim()&&this.routeMessage(this.safelyParse(n))}safelyParse(e){try{return JSON.parse(e)}catch{return null}}routeMessage(e){if(!e||e.id===void 0||typeof e.id!="number"||!("result"in e)&&!e.error)return;let n=this.pending.get(e.id);n&&(clearTimeout(n.timer),this.pending.delete(e.id),e.error?n.reject(new Error(`MCP ${this.name}: ${e.error.message??`error ${e.error.code??"unknown"}`}`)):n.resolve(e.result??null))}async listTools(e){await this.connect(e);let n=[],r;do{let o=re(await this.request("tools/list",r?{cursor:r}:{},e),"MCP tools/list result"),s=o.tools;if(!Array.isArray(s))throw new Error(`MCP server ${this.name} returned an invalid tool list.`);for(let i of s){let a=re(i,"MCP tool");if(typeof a.name!="string")throw new Error(`MCP server ${this.name} returned a tool without a name.`);n.push({name:a.name,title:typeof a.title=="string"?a.title:void 0,description:typeof a.description=="string"?a.description:void 0,inputSchema:re(a.inputSchema,`MCP inputSchema for ${a.name}`)})}r=typeof o.nextCursor=="string"?o.nextCursor:void 0}while(r);return n}async callTool(e,n,r){await this.connect(r);let o=await this.request("tools/call",{name:e,arguments:n},r);return{ok:re(o,"MCP tools/call result").isError!==!0,output:vs(o),metadata:{server:this.name,tool:e}}}info(){return{name:this.name,serverInfo:this.serverInfo,connected:this.initialized}}async close(){this.initialized=!1;for(let e of this.pending.values())clearTimeout(e.timer),e.reject(new Error("MCP client closed."));this.pending.clear()}},Ae=class t{tools=new Map;clients;constructor(e){this.clients=e}static async connect(e,n){let r=Object.entries(e).filter(([,s])=>s.enabled!==!1).map(([s,i])=>(i.transport??"stdio")==="stdio"?new sr(s,i):new ir(s,i)),o=new t(r);for(let s of r){let i=await s.listTools(n);for(let a of i){let c=`mcp_${an(s.name)}_${an(a.name)}`;if(o.tools.has(c))throw new Error(`Duplicate MCP tool name: ${c}`);o.tools.set(c,{client:s,remoteName:a.name,definition:{type:"function",function:{name:c,description:`[MCP:${s.name}] ${nl(a.description??a.title??a.name)}`,parameters:a.inputSchema}}})}}return o}definitions(){return[...this.tools.values()].map(e=>e.definition)}async execute(e,n,r){let o=this.tools.get(e);return o?await o.client.callTool(o.remoteName,n,r.signal):{ok:!1,output:`Unknown MCP tool: ${e}`}}list(){return[...this.tools.entries()].map(([e,n])=>({exposedName:e,server:n.client.name,remoteName:n.remoteName,description:n.definition.function.description}))}async close(){await Promise.all(this.clients.map(e=>e.close()))}};var rl="2025-11-25",ol=["2025-11-25","2025-06-18","2025-03-26"];function sl(t){return t.map(e=>({name:e.function.name,description:e.function.description,inputSchema:e.function.parameters??{type:"object",properties:{}}}))}function ks(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be an object.`);return t}var cn=class{name;version;rootDir;mode;runtime;initialized=!1;constructor(e,n){this.runtime=e,this.name=n.name??"kpilot",this.version=n.version??"0.0.0",this.rootDir=n.rootDir,this.mode=n.mode??"write"}async dispatch(e){let n=e.id,r=e.method;if(!(typeof n=="number"||typeof n=="string"))return r==="notifications/initialized"&&(this.initialized=!0),null;let s=ks(e.params??{},`${r} params`);try{let i=await this.handleMethod(String(r??""),s);return r==="initialize"&&(this.initialized=!0),{jsonrpc:"2.0",id:n,result:i}}catch(i){let a=i instanceof Error?i.message:String(i);return{jsonrpc:"2.0",id:n,error:{code:r==="tools/call"?-32603:-32601,message:a}}}}async handleMethod(e,n){switch(e){case"initialize":{let r=typeof n.protocolVersion=="string"?n.protocolVersion:"";return{protocolVersion:ol.includes(r)?r:rl,capabilities:{tools:{listChanged:!1}},serverInfo:{name:this.name,version:this.version}}}case"ping":return{};case"tools/list":{let r=sl(this.runtime.definitions());return typeof n.cursor=="string"?{tools:[],nextCursor:void 0}:{tools:r}}case"tools/call":{let r=typeof n.name=="string"?n.name:"";if(!r)throw new Error("tools/call requires a name.");let o=ks(n.arguments??{},"tools/call arguments"),s={rootDir:this.rootDir,mode:this.mode},i=await this.runtime.execute(r,o,s);return{content:[{type:"text",text:i.output??""}],isError:i.ok!==!0}}default:throw new Error(`Method not found: ${e}`)}}};function xs(t){if(!t.trim())return null;try{let e=JSON.parse(t);return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}}async function Ts(t){await new Promise((e,n)=>{let r="";process.stdin.setEncoding("utf8");let o=(s,i=!1)=>{r+=s;let a=r.indexOf(`
|
|
150
|
+
`);for(;a!==-1;){let c=r.slice(0,a);r=r.slice(a+1);let l=xs(c);l&&Ss(t,l),a=r.indexOf(`
|
|
151
|
+
`)}if(i&&r.trim()){let c=xs(r.trim());c&&Ss(t,c),r=""}};process.stdin.on("data",s=>o(s)),process.stdin.on("end",()=>{o("",!0),e()}),process.stdin.on("error",n)})}async function Ss(t,e){let n=await t.dispatch(e);n&&process.stdout.write(`${JSON.stringify(n)}
|
|
152
|
+
`)}var le={filesystem:{read:"allow",write:"ask",delete:"ask"},shell:{readOnly:"allow",mutating:"ask",destructive:"deny"},git:{read:"allow",write:"ask"},network:{search:"ask",fetch:"ask"},mcp:{call:"ask"},subagents:{delegate:"allow"}},il=[/\brm\s+-[^\n]*r[^\n]*f\b/i,/\bmkfs(?:\.|\s)/i,/\bdd\s+[^\n]*\bof=/i,/\bshutdown\b/i,/\breboot\b/i,/\bpoweroff\b/i,/\bhalt\b/i,/\bgit\s+reset\s+--hard\b/i,/\bgit\s+clean\s+-[^\n]*f/i,/\bDROP\s+(?:DATABASE|SCHEMA|TABLE)\b/i,/\bTRUNCATE\s+TABLE\b/i,/\bcurl\b[^\n|]*\|\s*(?:sudo\s+)?(?:sh|bash|zsh)\b/i,/\bwget\b[^\n|]*\|\s*(?:sudo\s+)?(?:sh|bash|zsh)\b/i,/\|\s*(?:sudo\s+)?(?:sh|bash|zsh|pwsh|powershell)(?:\s|$)/i,/\bchmod\s+-R\b/i,/\bchown\s+-R\b/i],al=[/^pwd(?:\s|$)/i,/^ls(?:\s|$)/i,/^find(?:\s|$)/i,/^rg(?:\s|$)/i,/^grep(?:\s|$)/i,/^cat(?:\s|$)/i,/^head(?:\s|$)/i,/^tail(?:\s|$)/i,/^sed\s+-n(?:\s|$)/i,/^wc(?:\s|$)/i,/^file(?:\s|$)/i,/^stat(?:\s|$)/i,/^cd(?:\s|$)/i,/^git\s+(?:status|diff|log|show|branch|rev-parse|ls-files)(?:\s|$)/i,/^(?:node|npm|pnpm|yarn|bun)\s+--version(?:\s|$)/i,/^which(?:\s|$)/i,/^whereis(?:\s|$)/i,/^echo(?:\s|$)/i];function cl(t){let e=t.trim();if(il.some(r=>r.test(e)))return"destructive";if(/(?:^|[^<])>{1,2}|\btee(?:\s|$)|\bsed\s+-i(?:\s|$)/i.test(e))return"mutating";let n=e.split(/&&|\|\||\||;|\n/).map(r=>r.trim()).filter(Boolean);return n.length>0&&n.every(r=>al.some(o=>o.test(r)))?"readOnly":"mutating"}function Z(t,e,n,r,o){return{tool:t,category:e,decision:n,reason:r,summary:o}}function vt(t){let e=X(t,"path")??X(t,"cwd")??".";return e.length>100?`${e.slice(0,97)}...`:e}function Ps(t,e){let n=X(t,"query")??X(t,"url")??e;return n.length>100?`${n.slice(0,97)}...`:n}var Ke=class{policy;constructor(e=le){this.policy=e}inspect(e,n,r){switch(e){case"list_files":case"read_file":case"search_text":case"workspace_summary":return Z(e,"filesystem.read",this.policy.filesystem.read,"Reads project files only.",vt(n));case"write_file":case"replace_in_file":case"make_directory":return r==="plan"?Z(e,"filesystem.write","deny","Plan mode cannot change files.",vt(n)):Z(e,"filesystem.write",this.policy.filesystem.write,"Changes a project file.",vt(n));case"delete_path":return r==="plan"?Z(e,"filesystem.delete","deny","Plan mode cannot delete files.",vt(n)):Z(e,"filesystem.delete",this.policy.filesystem.delete,"Deletes a path inside the project.",vt(n));case"git_status":case"git_diff":return Z(e,"git.read",this.policy.git.read,"Reads repository state.",".git");case"web_search":return Z(e,"network.search",this.policy.network.search,"Queries the public web (DuckDuckGo first; Brave if keyed and free search fails).",Ps(n,"web search"));case"web_fetch":return Z(e,"network.fetch",this.policy.network.fetch,"Fetches a public http(s) URL and returns extracted text.",Ps(n,"web fetch"));case"delegate_subagents":return Z(e,"subagents.delegate",this.policy.subagents.delegate,"Runs read-only specialist agents in parallel.","read-only repository analysis");case(e.startsWith("mcp_")?e:""):return r==="plan"?Z(e,"mcp.call","deny","MCP tools are denied in plan mode because their side effects are not knowable locally.",e):Z(e,"mcp.call",this.policy.mcp.call,"Invokes an external MCP tool whose side effects depend on its server.",e);case"shell":{let o=F(n,"command",{maximumLength:2e4}),s=cl(o);return r==="plan"&&s!=="readOnly"?Z(e,`shell.${s}`,"deny","Plan mode permits only read-only shell commands.",o):Z(e,`shell.${s}`,this.policy.shell[s],`Command classified as ${s}.`,o)}default:return Z(e,"unknown","deny","Unknown tools are denied by default.",e)}}async authorize(e,n,r,o,s={}){let i=this.inspect(e,n,r);if(i.decision==="allow")return{...i,approved:!0};if(s.bypassPermissions&&r!=="plan"&&i.category!=="unknown")return{...i,decision:"allow",reason:`${i.reason} Auto-approved (bypass).`,approved:!0};if(i.decision==="deny")return{...i,approved:!1};let a=await o(i);return{...i,approved:a}}};import{mkdir as ll,readFile as ul,rename as dl,stat as ml,writeFile as pl}from"node:fs/promises";import{randomUUID as cr}from"node:crypto";import ar from"node:path";async function fl(t){try{return await ml(t),!0}catch{return!1}}async function Es(t,e){await ll(ar.dirname(t),{recursive:!0});let n=`${t}.${cr()}.tmp`;await pl(n,`${JSON.stringify(e,null,2)}
|
|
153
|
+
`,"utf8"),await dl(n,t)}function gl(){return{schemaVersion:1,rules:[],feedback:[]}}function hl(t){let e;try{e=JSON.parse(t)}catch(r){throw new Error(`Invalid preferences JSON: ${r instanceof Error?r.message:String(r)}`)}if(typeof e!="object"||e===null||Array.isArray(e))throw new Error("Preferences document must be an object.");let n=e;if(n.schemaVersion!==1||!Array.isArray(n.rules)||!Array.isArray(n.feedback))throw new Error("Unsupported preferences document schema.");return n}function wl(t){return t.split(/\r?\n/).filter(e=>e.startsWith("+")&&!e.startsWith("+++")).map(e=>e.slice(1))}function yl(t){return t.split(/\r?\n/).filter(e=>e.startsWith("+++ b/")).map(e=>e.slice(6))}function bl(t){let e=wl(t),n=yl(t),r=[];if(e.length===0)return r;let o=e.filter(d=>/(?:^|[=(,:\s])'[^']*'/.test(d)).length,s=e.filter(d=>/(?:^|[=(,:\s])"[^"]*"/.test(d)).length;o+s>=6&&(o>=s*2?r.push({text:"Use single quotes for string literals where the language permits.",confidence:.62,source:"heuristic:quotes"}):s>=o*2&&r.push({text:"Use double quotes for string literals where the language permits.",confidence:.62,source:"heuristic:quotes"}));let i=e.filter(d=>/;\s*$/.test(d.trim())).length,a=e.filter(d=>/^(?:\s*)(?:const|let|var|return|throw|import|export|[A-Za-z_$][\w$]*\s*=)/.test(d)).length;a>=8&&i>=a*.7&&r.push({text:"Terminate applicable statements with semicolons.",confidence:.58,source:"heuristic:semicolon"});let c=n.filter(d=>/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(d)),l=c.filter(d=>/\.test\./.test(d)).length,u=c.filter(d=>/\.spec\./.test(d)).length;return c.length>=2&&l>u?r.push({text:"Name test files with the .test.* convention.",confidence:.68,source:"heuristic:test-name"}):c.length>=2&&u>l&&r.push({text:"Name test files with the .spec.* convention.",confidence:.68,source:"heuristic:test-name"}),n.some(d=>d.endsWith("pnpm-lock.yaml"))?r.push({text:"Use pnpm as the package manager for this project.",confidence:.9,source:"heuristic:package-manager"}):n.some(d=>d.endsWith("yarn.lock"))?r.push({text:"Use Yarn as the package manager for this project.",confidence:.9,source:"heuristic:package-manager"}):n.some(d=>d.endsWith("package-lock.json"))&&r.push({text:"Use npm as the package manager for this project.",confidence:.9,source:"heuristic:package-manager"}),e.filter(d=>/^\s*import\s+type\b/.test(d)).length>=3&&r.push({text:"Use TypeScript type-only imports when imports are used only as types.",confidence:.65,source:"heuristic:type-imports"}),r}function vl(t){return t.trim().replace(/\s+/g," ")}function Rs(t,e){let n=vl(e.text),r=t.rules.find(i=>i.polarity===e.polarity&&i.text.toLowerCase()===n.toLowerCase()),o=new Date().toISOString();if(r)return r.evidenceCount+=1,r.confidence=Math.min(.99,Number((r.confidence+(1-r.confidence)*e.confidence*.35).toFixed(3))),r.updatedAt=o,r.sources.includes(e.source)||r.sources.push(e.source),r;let s={id:cr(),text:n,polarity:e.polarity,confidence:e.confidence,evidenceCount:1,createdAt:o,updatedAt:o,sources:[e.source]};return t.rules.push(s),s}var ln=class{rootDir;filePath;constructor(e){this.rootDir=ar.resolve(e),this.filePath=ar.join(this.rootDir,E,"preferences.json")}async readDocument(){return await fl(this.filePath)?hl(await ul(this.filePath,"utf8")):gl()}async listRules(){return[...(await this.readDocument()).rules].sort((n,r)=>r.confidence-n.confidence||r.updatedAt.localeCompare(n.updatedAt))}async listFeedback(){return[...(await this.readDocument()).feedback].sort((n,r)=>r.createdAt.localeCompare(n.createdAt))}async learn(e){if(!e.task.trim())throw new Error("Feedback must reference a non-empty task.");let n=await this.readDocument(),r=[],o=`feedback:${e.outcome}`;e.note?.trim()&&r.push(Rs(n,{text:e.note,polarity:e.outcome==="rejected"?"avoid":"prefer",confidence:e.outcome==="edited"?.92:.88,source:`${o}:note`}));let s=e.outcome==="edited"?e.finalDiff:e.outcome==="accepted"?e.proposedDiff:void 0;if(s?.trim())for(let a of bl(s))r.push(Rs(n,{text:a.text,polarity:"prefer",confidence:e.outcome==="edited"?Math.min(.95,a.confidence+.12):a.confidence,source:`${o}:${a.source}`}));let i={id:cr(),outcome:e.outcome,task:e.task.trim(),note:e.note?.trim()||void 0,sessionId:e.sessionId,proposedDiff:e.proposedDiff,finalDiff:e.finalDiff,createdAt:new Date().toISOString(),learnedRuleIds:[...new Set(r.map(a=>a.id))]};return n.feedback.push(i),n.feedback.length>500&&(n.feedback=n.feedback.slice(-500)),await Es(this.filePath,n),{feedback:i,learned:[...new Map(r.map(a=>[a.id,a])).values()]}}async removeRule(e){let n=await this.readDocument(),r=n.rules.filter(s=>s.id.startsWith(e));if(r.length===0)throw new Error(`Preference rule not found: ${e}`);if(r.length>1)throw new Error(`Preference rule prefix is ambiguous: ${e}`);let o=r[0];return n.rules=n.rules.filter(s=>s.id!==o.id),await Es(this.filePath,n),o}async renderForPrompt(e=.55,n=12e3){let r=(await this.listRules()).filter(i=>i.confidence>=e),o=[],s=0;for(let i of r){let c=`- ${i.polarity==="prefer"?"Prefer":"Avoid"}: ${i.text} (confidence ${Math.round(i.confidence*100)}%)`;if(s+c.length+1>n)break;o.push(c),s+=c.length+1}return o.join(`
|
|
154
|
+
`)}};import{mkdir as kl,readFile as Cs,readdir as xl,rename as Sl,rm as Tl,stat as Pl,writeFile as El}from"node:fs/promises";import{randomUUID as As}from"node:crypto";import We from"node:path";function Ms(t){let e=t.trim();if(!Os.test(e))throw new Error("Session ID may contain only letters, numbers, underscores, and hyphens.");return e}var Os=/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/;async function $s(t){try{return await Pl(t),!0}catch{return!1}}async function Rl(t,e){await kl(We.dirname(t),{recursive:!0});let n=`${t}.${process.pid??"tmp"}.${As()}.tmp`;await El(n,`${JSON.stringify(e,null,2)}
|
|
155
|
+
`,"utf8"),await Sl(n,t)}function _s(t,e){let n;try{n=JSON.parse(t)}catch(o){throw new Error(`Invalid session JSON in ${e}: ${o instanceof Error?o.message:String(o)}`)}if(typeof n!="object"||n===null||Array.isArray(n))throw new Error(`Session file ${e} does not contain an object.`);let r=n;if(r.schemaVersion!==1||typeof r.id!="string"||typeof r.title!="string")throw new Error(`Session file ${e} has an unsupported schema.`);if(!Array.isArray(r.messages)||!Array.isArray(r.runs))throw new Error(`Session file ${e} is missing messages or runs.`);return r}var un=class{rootDir;directory;constructor(e){this.rootDir=We.resolve(e),this.directory=We.join(this.rootDir,E,"sessions")}filePath(e){return We.join(this.directory,`${Ms(e)}.json`)}async create(e){let n=new Date().toISOString(),r=As(),o=e.title?.trim(),s={schemaVersion:1,id:r,title:o||`Session ${n.slice(0,16).replace("T"," ")}`,titleSource:o?"user":"auto",rootDir:this.rootDir,createdAt:n,updatedAt:n,mode:e.mode,model:e.model,messages:[],runs:[]};return await this.save(s),s}async save(e){if(Ms(e.id),We.resolve(e.rootDir)!==this.rootDir)throw new Error("Session belongs to a different project root.");e.updatedAt=new Date().toISOString(),await Rl(this.filePath(e.id),e)}async load(e){let n=await this.resolveId(e),r=this.filePath(n);return _s(await Cs(r,"utf8"),r)}async resolveId(e){let n=e.trim();if(!n)throw new Error("A session id or name is required.");if(Os.test(n)&&await $s(this.filePath(n)))return n;let r=await this.list(),o=r.filter(i=>i.id.startsWith(n)),s=o.length>0?o:r.filter(i=>i.title.toLowerCase()===n.toLowerCase());if(s.length===0)throw new Error(`Session not found: ${e}`);if(s.length>1)throw new Error(`Session reference is ambiguous: ${e}`);return s[0].id}async list(){if(!await $s(this.directory))return[];let e=await xl(this.directory,{withFileTypes:!0}),n=[];for(let r of e){if(!r.isFile()||!r.name.endsWith(".json"))continue;let o=We.join(this.directory,r.name);try{let s=_s(await Cs(o,"utf8"),o);n.push({id:s.id,title:s.title,updatedAt:s.updatedAt,mode:s.mode,model:s.model,messageCount:s.messages.length,runCount:s.runs.length})}catch{}}return n.sort((r,o)=>o.updatedAt.localeCompare(r.updatedAt))}async delete(e){let n=await this.resolveId(e);await Tl(this.filePath(n),{force:!1})}};import{readFile as Cl,readdir as Ml,stat as $l}from"node:fs/promises";import{homedir as _l}from"node:os";import kt from"node:path";async function Is(t){try{return await $l(t),!0}catch{return!1}}function Al(t){if(!t.startsWith(`---
|
|
111
156
|
`))return{metadata:{},body:t.trim()};let e=t.indexOf(`
|
|
112
157
|
---
|
|
113
|
-
`,4);if(e<0)return{metadata:{},body:t.trim()};let n={};for(let
|
|
158
|
+
`,4);if(e<0)return{metadata:{},body:t.trim()};let n={};for(let r of t.slice(4,e).split(/\r?\n/)){let o=r.indexOf(":");if(o<1)continue;let s=r.slice(0,o).trim().toLowerCase(),i=r.slice(o+1).trim().replace(/^['"]|['"]$/g,"");s&&(n[s]=i)}return{metadata:n,body:t.slice(e+5).trim()}}function js(t){let e=t.trim().toLowerCase();if(!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(e))throw new Error(`Invalid skill name: ${t}`);return e}async function Ds(t,e){if(!await Is(t))return[];let n=await Ml(t,{withFileTypes:!0}),r=[];for(let o of n){let s,i=o.name;if(o.isDirectory()?s=kt.join(t,o.name,"SKILL.md"):o.isFile()&&o.name.endsWith(".md")&&(s=kt.join(t,o.name),i=o.name.slice(0,-3)),!s||!await Is(s))continue;let a=Al(await Cl(s,"utf8")),c=js(a.metadata.name||i);a.body&&r.push({name:c,description:a.metadata.description||`Reusable ${c} workflow`,instructions:a.body,source:e,filePath:s})}return r}var dn=class{rootDir;projectDirectory;globalDirectory;constructor(e,n=kt.join(_l(),".config","kpilot","skills")){this.rootDir=kt.resolve(e),this.projectDirectory=kt.join(this.rootDir,E,"skills"),this.globalDirectory=n}async list(){let[e,n]=await Promise.all([Ds(this.globalDirectory,"global"),Ds(this.projectDirectory,"project")]),r=new Map;for(let o of e)r.set(o.name,o);for(let o of n)r.set(o.name,o);return[...r.values()].sort((o,s)=>o.name.localeCompare(s.name))}async get(e){let n=js(e),r=(await this.list()).find(o=>o.name===n);if(!r)throw new Error(`Skill not found: ${e}`);return r}async renderInvocation(e,n=""){let r=await this.get(e);return`Apply the reusable skill "${r.name}".
|
|
114
159
|
|
|
115
160
|
Skill instructions:
|
|
116
|
-
${
|
|
161
|
+
${r.instructions}
|
|
117
162
|
|
|
118
163
|
Invocation arguments:
|
|
119
|
-
${n.trim()||"[none]"}`}};var
|
|
164
|
+
${n.trim()||"[none]"}`}};var xt=class{runtimes;owners=new Map;tools;constructor(e){this.runtimes=e.filter(n=>!!n),this.tools=[];for(let n of this.runtimes)for(let r of n.definitions()){let o=r.function.name;if(this.owners.has(o))throw new Error(`Duplicate tool definition: ${o}`);this.owners.set(o,n),this.tools.push(r)}}definitions(){return[...this.tools]}async execute(e,n,r){let o=this.owners.get(e);return o?await o.execute(e,n,r):{ok:!1,output:`Unknown tool: ${e}`}}};import{mkdir as Pr,open as gu,readFile as gn,readdir as hu,realpath as Sr,rm as wu,stat as De,writeFile as Er}from"node:fs/promises";import W from"node:path";import{spawn as ri}from"node:child_process";import{spawn as Ol}from"node:child_process";import{realpath as Ls}from"node:fs/promises";import mn from"node:path";var Il=new Set(["PATH","HOME","USER","LOGNAME","SHELL","LANG","LC_ALL","LC_CTYPE","TERM","COLORTERM","TMPDIR","TMP","TEMP","XDG_CACHE_HOME","XDG_CONFIG_HOME","XDG_DATA_HOME","CI"]);function Dl(t){return process.platform==="win32"?Promise.resolve(!1):new Promise(e=>{let n=Ol("/bin/sh",["-lc",`command -v "${t}" >/dev/null 2>&1`],{stdio:"ignore"});n.once("error",()=>e(!1)),n.once("close",r=>e(r===0))})}function jl(t){let e=new Set([...Il,...t]),n={};for(let[r,o]of Object.entries(process.env))(e.has(r)||r.startsWith("npm_")||r.startsWith("PNPM_"))&&(n[r]=o);return n.KPILOT_SANDBOX="1",n}var pn=class{rootDir;config;constructor(e,n={}){if(this.rootDir=mn.resolve(e),this.config={mode:n.mode??"portable",allowNetwork:n.allowNetwork??!1,passEnvironment:n.passEnvironment??[],...n.maxTimeoutMs===void 0?{}:{maxTimeoutMs:n.maxTimeoutMs}},this.config.maxTimeoutMs!==void 0&&(this.config.maxTimeoutMs<100||this.config.maxTimeoutMs>6e5))throw new Error("sandbox.maxTimeoutMs must be between 100 and 600000.")}async backend(){if(this.config.mode==="none")return"none";if(this.config.mode==="portable")return"portable";let e=process.platform==="linux"&&await Dl("bwrap");if(this.config.mode==="bwrap"&&!e)throw new Error("sandbox.mode is bwrap, but bubblewrap is unavailable.");return e?"bwrap":"portable"}async prepareShell(e,n,r){let o=mn.resolve(n),[s,i]=await Promise.all([Ls(this.rootDir).catch(()=>this.rootDir),Ls(o).catch(()=>o)]),a=mn.relative(s,i);if(a.startsWith("..")||mn.isAbsolute(a))throw new Error("Sandbox cwd escapes the repository root.");let c=this.config.maxTimeoutMs===void 0?r:Math.min(r,this.config.maxTimeoutMs),l=await this.backend(),u=l==="none"?process.env:jl(this.config.passEnvironment);if(process.platform==="win32")return{command:"cmd.exe",args:["/d","/s","/c",e],cwd:o,env:u,timeoutMs:c,backend:l};if(l!=="bwrap")return{command:"/bin/sh",args:["-lc",e],cwd:o,env:u,timeoutMs:c,backend:l};let m=["--die-with-parent","--new-session","--unshare-pid","--ro-bind","/","/","--bind",this.rootDir,this.rootDir,"--tmpfs","/tmp","--proc","/proc","--dev","/dev","--chdir",o];return this.config.allowNetwork||m.push("--unshare-net"),m.push("/bin/sh","-lc",e),{command:"bwrap",args:m,cwd:o,env:u,timeoutMs:c,backend:l}}async describe(){let e=await this.backend(),n=e==="bwrap"?this.config.allowNetwork?"allowed":"isolated":e==="none"?"unrestricted":"not OS-isolated",r=this.config.maxTimeoutMs===void 0?"unlimited":`${this.config.maxTimeoutMs}ms`;return`${e} (network ${n}, timeout cap ${r})`}};import{lookup as Ll}from"node:dns/promises";import{isIP as dr}from"node:net";var Ul="https://api.search.brave.com/res/v1/web/search",Fs="https://html.duckduckgo.com/html/",Nl="https://api.tavily.com/search",Fl="https://api.exa.ai/search",ql="https://google.serper.dev/search",Bl=5,Jl=10,Oe=2e4,Kl=1e6,Wl=5e4,Gl=2e5,lr=5;function pr(t=process.env){return t.BRAVE_API_KEY?.trim()||t.BRAVE_SEARCH_API_KEY?.trim()||void 0}function Hl(t=process.env){let e=pr(t);if(!e)throw new Error("Brave Search requires BRAVE_API_KEY (or BRAVE_SEARCH_API_KEY). Get a key at https://brave.com/search/api/");return e}function fr(t=process.env){return t.TAVILY_API_KEY?.trim()||void 0}function zl(t=process.env){let e=fr(t);if(!e)throw new Error("Tavily search requires TAVILY_API_KEY. Get a key at https://tavily.com/");return e}function gr(t=process.env){return t.EXA_API_KEY?.trim()||void 0}function Vl(t=process.env){let e=gr(t);if(!e)throw new Error("Exa search requires EXA_API_KEY. Get a key at https://exa.ai/");return e}function hr(t=process.env){return t.SERPER_API_KEY?.trim()||void 0}function Yl(t=process.env){let e=hr(t);if(!e)throw new Error("Serper search requires SERPER_API_KEY. Get a key at https://serper.dev/");return e}function wr(t=process.env){let e=t.SEARXNG_BASE_URL?.trim();return e?e.replace(/\/+$/,""):void 0}function Ge(t){return Math.min(Math.max(t??Bl,1),Jl)}function qs(t){return t.replace(/ /gi," ").replace(/&/gi,"&").replace(/</gi,"<").replace(/>/gi,">").replace(/"/gi,'"').replace(/'/gi,"'").replace(/'/gi,"'").replace(/&#(\d+);/g,(e,n)=>String.fromCharCode(Number(n)))}function Us(t){return qs(t.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim())}function Ql(t){try{let e=new URL(t,Fs);if(e.hostname.endsWith("duckduckgo.com")&&e.pathname==="/l/"){let n=e.searchParams.get("uddg");if(n)return decodeURIComponent(n)}return e.href}catch{return t}}function Xl(t,e){let n=[],r=new Set,o=/<a[^>]*class="[^"]*result__a[^"]*"[^>]*href="([^"]+)"[^>]*>([\s\S]*?)<\/a>([\s\S]*?)(?=<a[^>]*class="[^"]*result__a|$)/gi,s;for(;(s=o.exec(t))!==null&&n.length<e;){let i=Ql(qs(s[1]??"")).trim();if(!i||!/^https?:\/\//i.test(i)||r.has(i))continue;let a=Us(s[2]??"")||i,l=(s[3]??"").match(/class="[^"]*result__snippet[^"]*"[^>]*>([\s\S]*?)<\/(?:a|td|div)/i),u=l?Us(l[1]??""):"";r.add(i),n.push({title:a,url:i,description:u})}return n}function Zl(t){let e=t.trim().toLowerCase().replace(/\.$/,"");return!!(!e||e==="localhost"||e.endsWith(".localhost")||e.endsWith(".local")||e==="metadata.google.internal"||e==="metadata")}function mr(t){let e=dr(t);if(e===4){let n=t.split(".").map(Number);if(n.length!==4||n.some(s=>!Number.isInteger(s)||s<0||s>255))return!0;let[r,o]=n;return r===0||r===10||r===127||r===255||r===169&&o===254||r===172&&o>=16&&o<=31||r===192&&o===168||r===100&&o>=64&&o<=127}if(e===6){let n=t.toLowerCase();if(n==="::"||n==="::1"||n.startsWith("fc")||n.startsWith("fd")||n.startsWith("fe80"))return!0;if(n.startsWith("::ffff:")){let r=n.slice(7);if(dr(r)===4)return mr(r)}return!1}return!0}async function yr(t){let e;try{e=new URL(t)}catch{throw new Error(`Invalid URL: ${t}`)}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Error(`Only http(s) URLs are allowed; got ${e.protocol}`);if(e.username||e.password)throw new Error("URLs with embedded credentials are not allowed.");let n=e.hostname;if(Zl(n))throw new Error(`Blocked hostname: ${n}`);if(dr(n)){if(mr(n))throw new Error(`Blocked IP address: ${n}`);return e}let o;try{o=await Ll(n,{all:!0,verbatim:!0})}catch(s){throw new Error(`DNS lookup failed for ${n}: ${s instanceof Error?s.message:String(s)}`)}if(o.length===0)throw new Error(`DNS lookup returned no addresses for ${n}`);for(let s of o)if(mr(s.address))throw new Error(`Hostname ${n} resolves to blocked address ${s.address}`);return e}function St(t){return t.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi," ").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi," ").replace(/<noscript\b[^>]*>[\s\S]*?<\/noscript>/gi," ").replace(/<(?:br|\/p|\/div|\/h[1-6]|\/li|\/tr)\b[^>]*>/gi,`
|
|
120
165
|
`).replace(/<[^>]+>/g," ").replace(/ /gi," ").replace(/&/gi,"&").replace(/</gi,"<").replace(/>/gi,">").replace(/"/gi,'"').replace(/'/gi,"'").replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
|
121
166
|
`).replace(/\n{3,}/g,`
|
|
122
167
|
|
|
123
|
-
`).replace(/[ \t]{2,}/g," ").trim()}async function Ja(t,e){if(!t.body){let s=await t.arrayBuffer(),i=Buffer.from(s);if(i.byteLength>e)throw new Error(`Response body exceeds ${e} byte limit.`);return i}let n=t.body.getReader(),o=[],r=0;for(;;){let{done:s,value:i}=await n.read();if(s)break;let a=Buffer.from(i??new Uint8Array);if(r+=a.byteLength,r>e)throw await n.cancel().catch(()=>{}),new Error(`Response body exceeds ${e} byte limit.`);o.push(a)}return Buffer.concat(o,r)}async function Ka(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Me(t.count),o=t.fetchImpl??fetch,r=new URLSearchParams({q:e}),s=await o(vo,{method:"POST",headers:{Accept:"text/html","Content-Type":"application/x-www-form-urlencoded","User-Agent":"kpilot/web_search"},body:r.toString(),signal:t.signal??AbortSignal.timeout(ye)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`DuckDuckGo search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let i=await s.text(),a=qa(i,n);return{query:e,count:a.length,results:a,provider:"duckduckgo"}}async function Ga(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Me(t.count),o=t.apiKey??ja(),r=new URL(Ca);r.searchParams.set("q",e),r.searchParams.set("count",String(n));let i=await(t.fetchImpl??fetch)(r,{method:"GET",headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":o},signal:t.signal??AbortSignal.timeout(ye)});if(!i.ok){let l=(await i.text().catch(()=>"")).slice(0,300);throw new Error(`Brave Search API returned HTTP ${i.status}${l?`: ${l}`:""}`)}let c=((await i.json()).web?.results??[]).filter(l=>typeof l?.url=="string"&&l.url.trim()).slice(0,n).map(l=>({title:String(l.title??"").trim()||l.url.trim(),url:l.url.trim(),description:String(l.description??"").trim()}));return{query:e,count:c.length,results:c,provider:"brave"}}async function Ha(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Me(t.count),o=t.apiKey??Ua(),s=await(t.fetchImpl??fetch)(Ra,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":"kpilot/web_search"},body:JSON.stringify({api_key:o,query:e,max_results:n,include_answer:!1,include_raw_content:!1}),signal:t.signal??AbortSignal.timeout(ye)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`Tavily search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let a=((await s.json()).results??[]).filter(c=>typeof c?.url=="string"&&/^https?:\/\//i.test(c.url)).slice(0,n).map(c=>({title:String(c.title??"").trim()||c.url.trim(),url:c.url.trim(),description:String(c.content??"").trim()}));return{query:e,count:a.length,results:a,provider:"tavily"}}async function Wa(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Me(t.count),o=t.apiKey??La(),s=await(t.fetchImpl??fetch)(Ma,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":o,"User-Agent":"kpilot/web_search"},body:JSON.stringify({query:e,numResults:n,contents:{text:!1}}),signal:t.signal??AbortSignal.timeout(ye)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`Exa search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let a=((await s.json()).results??[]).filter(c=>typeof c?.url=="string"&&/^https?:\/\//i.test(c.url)).slice(0,n).map(c=>({title:String(c.title??"").trim()||c.url.trim(),url:c.url.trim(),description:String(c.text??"").trim().slice(0,300)}));return{query:e,count:a.length,results:a,provider:"exa"}}async function za(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Me(t.count),o=t.apiKey??Na(),s=await(t.fetchImpl??fetch)($a,{method:"POST",headers:{"Content-Type":"application/json","X-API-KEY":o,"User-Agent":"kpilot/web_search"},body:JSON.stringify({q:e,num:n}),signal:t.signal??AbortSignal.timeout(ye)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`Serper search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let a=((await s.json()).organic??[]).filter(c=>typeof c?.link=="string"&&/^https?:\/\//i.test(c.link)).slice(0,n).map(c=>({title:String(c.title??"").trim()||c.link.trim(),url:c.link.trim(),description:String(c.snippet??"").trim()}));return{query:e,count:a.length,results:a,provider:"serper"}}async function Va(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Me(t.count),o=t.baseUrl??$n();if(!o)throw new Error("SearXNG search requires SEARXNG_BASE_URL.");let r=new URL(`${o}/search`);r.searchParams.set("q",e),r.searchParams.set("format","json"),r.searchParams.set("safesearch","0");let i=await(t.fetchImpl??fetch)(r,{method:"GET",headers:{Accept:"application/json","User-Agent":"kpilot/web_search"},signal:t.signal??AbortSignal.timeout(ye)});if(!i.ok){let l=(await i.text().catch(()=>"")).slice(0,300);throw new Error(`SearXNG search returned HTTP ${i.status}${l?`: ${l}`:""}`)}let c=((await i.json()).results??[]).filter(l=>typeof l?.url=="string"&&/^https?:\/\//i.test(l.url)).slice(0,n).map(l=>({title:String(l.title??"").trim()||l.url.trim(),url:l.url.trim(),description:String(l.content??"").trim()}));return{query:e,count:c.length,results:c,provider:"searxng"}}function Sn(t,e){let{query:n,count:o,signal:r,fetchImpl:s,env:i}=e;switch(t){case"duckduckgo":return Ka({query:n,count:o,signal:r,fetchImpl:s});case"tavily":return Ha({query:n,count:o,signal:r,fetchImpl:s,apiKey:Cn(i)});case"exa":return Wa({query:n,count:o,signal:r,fetchImpl:s,apiKey:Rn(i)});case"serper":return za({query:n,count:o,signal:r,fetchImpl:s,apiKey:Mn(i)});case"searxng":return Va({query:n,count:o,signal:r,fetchImpl:s,baseUrl:$n(i)});case"brave":return Ga({query:n,count:o,signal:r,fetchImpl:e.braveFetchImpl??s,apiKey:En(i)})}}function bo(t,e){switch(t){case"duckduckgo":return!0;case"tavily":return!!Cn(e);case"exa":return!!Rn(e);case"serper":return!!Mn(e);case"searxng":return!!$n(e);case"brave":return!!En(e)}}var Ya=["tavily","exa","serper","searxng","brave"];async function xo(t){let e=t.env??process.env,n=t.fetchImpl??fetch,o={query:t.query,count:t.count,signal:t.signal,fetchImpl:n,env:e,braveFetchImpl:t.braveFetchImpl};if(t.provider){if(!bo(t.provider,e))throw new Error(`Web search provider "${t.provider}" is not configured. Set the required key or enabling variable.`);return await Sn(t.provider,o)}let r;try{let s=await Sn("duckduckgo",o);if(s.results.length>0)return s;r=new Error("DuckDuckGo search returned no results.")}catch(s){r=s instanceof Error?s:new Error(String(s))}for(let s of Ya)if(bo(s,e))try{let i=await Sn(s,o);if(i.results.length>0)return{...i,fallbackReason:r?.message};r=new Error(`${s} search returned no results.`)}catch(i){r=i instanceof Error?i:new Error(String(i))}throw r??new Error("Web search failed.")}async function So(t){let e=Math.min(Math.max(t.maxChars??Ia,1),Da),n=t.fetchImpl??fetch,o=t.assertPublicUrlFn??_n,r=await o(t.url),s,i=0;for(;i<=xn;){if(s=await n(r,{method:"GET",redirect:"manual",headers:{Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,text/plain;q=0.8,*/*;q=0.5","User-Agent":"kpilot/web_fetch"},signal:t.signal??AbortSignal.timeout(ye)}),s.status>=300&&s.status<400){let p=s.headers.get("location");if(!p)throw new Error(`Redirect without Location header from ${r.href}`);r=await o(new URL(p,r).href),i+=1;continue}break}if(!s)throw new Error("Failed to fetch URL.");if(i>xn)throw new Error(`Too many redirects (max ${xn}).`);if(!s.ok)throw new Error(`HTTP ${s.status} fetching ${r.href}`);let a=s.headers.get("content-type")??void 0,c=await Ja(s,Oa),l=new TextDecoder().decode(c),u=a&&/html|xml|sgml/i.test(a)||/html/i.test(l.slice(0,512))?et(l):l.trim(),d=u.length>e;return{url:t.url,finalUrl:r.href,status:s.status,contentType:a,text:d?u.slice(0,e):u,truncated:d}}import{spawn as In,spawnSync as Qa}from"node:child_process";import{mkdir as To,writeFile as Xa}from"node:fs/promises";import{tmpdir as Za}from"node:os";import be from"node:path";var tt="Chromium is not installed. Install it (e.g. `brew install --cask chromium` on macOS, `sudo apt install chromium-browser` on Debian/Ubuntu, or point KPILOT_CHROME_PATH at a browser binary), or use web_fetch for static pages.",ec=["google-chrome-stable","google-chrome","chromium-browser","chromium","microsoft-edge","microsoft-edge-stable"],tc=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],$e;function An(t){try{let e=Qa(t,["--version"],{timeout:3e3,stdio:"ignore"});return e.error===void 0&&e.status===0}catch{return!1}}function nt(t=process.env){if($e!==void 0)return $e||void 0;let e=t.KPILOT_CHROME_PATH?.trim();if(e&&An(e))return $e=e,e;for(let n of ec)if(An(n))return $e=n,n;for(let n of tc)if(An(n))return $e=n,n;$e=null}function Po(t){return new Promise(e=>{setTimeout(()=>e(),t)})}var Eo=1280,Co=1200,On=class t{child;ws;sessionId="";nextId=1;pending=new Map;closed=!1;constructor(e,n){this.child=e,this.ws=n,this.ws.addEventListener("message",o=>this.handleMessage(String(o?.data??""))),this.ws.addEventListener("close",()=>this.failAll(new Error("Browser connection closed.")))}static async launch(e){let n=be.join(Za(),`kpilot-browser-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,7)}`),o=In(e,["--headless=new","--no-sandbox","--disable-gpu","--disable-dev-shm-usage","--disable-extensions",`--user-data-dir=${n}`,"--remote-debugging-port=0"],{stdio:["ignore","ignore","pipe"]}),r=await new Promise((a,c)=>{let l="",u=setTimeout(()=>{o.kill("SIGKILL"),c(new Error("Timed out waiting for the browser to expose a DevTools endpoint."))},15e3);o.stderr.setEncoding("utf8"),o.stderr.on("data",d=>{l+=d;let p=l.match(/DevTools listening on (ws:\/\/\S+)/i);p?.[1]&&(clearTimeout(u),a(p[1]))}),o.once("error",d=>{clearTimeout(u),c(d)}),o.once("exit",d=>{clearTimeout(u),c(new Error(`Browser exited before starting (code ${d??1}).`))})}),s=new WebSocket(r);await new Promise((a,c)=>{s.addEventListener("open",()=>a()),s.addEventListener("error",()=>c(new Error("Failed to open the DevTools WebSocket.")))});let i=new t(o,s);return await i.attachPageTarget(),i}async attachPageTarget(){let e=await this.send("Target.createTarget",{url:"about:blank"}),n=String(e.targetId??"");if(!n)throw new Error("Browser did not create a page target.");let o=await this.send("Target.attachToTarget",{targetId:n,flatten:!0});if(this.sessionId=String(o.sessionId??""),!this.sessionId)throw new Error("Browser did not attach a page session.")}send(e,n={},o=15e3){let r=this.nextId++,s={id:r,method:e,params:n};return this.sessionId&&(s.sessionId=this.sessionId),this.ws.send(JSON.stringify(s)),new Promise((i,a)=>{let c=setTimeout(()=>{this.pending.delete(r),a(new Error(`CDP ${e} timed out.`))},o);this.pending.set(r,{resolve:i,reject:a,timer:c})})}handleMessage(e){let n;try{n=JSON.parse(e)}catch{return}let o=n.id;if(o===void 0)return;let r=this.pending.get(o);if(r)if(clearTimeout(r.timer),this.pending.delete(o),n.error&&typeof n.error=="object"){let s=n.error;r.reject(new Error(String(s.message??"CDP error")))}else r.resolve(n.result??{})}async evaluate(e){return await this.send("Runtime.evaluate",{expression:e,returnByValue:!0,awaitPromise:!0})}failAll(e){for(let n of this.pending.values())clearTimeout(n.timer),n.reject(e);this.pending.clear()}async navigate(e,n,o){await this.send("Page.navigate",{url:e});let r=o==="domcontentloaded"?["interactive","complete"]:["complete"],s=Date.now()+Math.min(n,3e4);for(;Date.now()<s;){let i=await this.evaluate("document.readyState"),a=String(i.result?.value??"");if(r.includes(a))break;await Po(120)}o==="networkidle2"&&await Po(700)}async readPage(e){let n=await this.evaluate("JSON.stringify({title:document.title,url:location.href,text:(()=>{const c=document.body?document.body.cloneNode(true):null;if(!c)return '';c.querySelectorAll('script,style,noscript,svg,canvas,iframe,template').forEach(function(n){n.remove()});return (c.innerText||c.textContent||'').replace(/\\s+/g,' ').trim();})()})"),o={};try{o=JSON.parse(String(n.result?.value??"{}"))}catch{o={}}let r=String(o.text??""),s=r.length>e;return{url:String(o.url??""),title:String(o.title??""),text:s?r.slice(0,e):r,truncated:s}}async screenshot(e,n){let o=Eo,r=Co;if(e){let u=(await this.send("Page.getLayoutMetrics")).cssContentSize?.height;r=Math.max(r,Math.ceil(Number(u)||r)),await this.send("Emulation.setDeviceMetricsOverride",{width:o,height:r,deviceScaleFactor:1,mobile:!1})}let s=await this.send("Page.captureScreenshot",{format:"png"}),i=String(s.data??"");if(!i)throw new Error("Browser returned an empty screenshot.");let a=be.join(n,".kpilot","run");await To(a,{recursive:!0});let c=be.join(".kpilot","run",`browser-${Date.now().toString(36)}.png`);return await Xa(be.join(n,c),Buffer.from(i,"base64")),c}async click(e){let o=(await this.evaluate(`(()=>{const el=document.querySelector(${JSON.stringify(e)});if(!el)return {ok:false,why:'no matching element'};const r=el.getBoundingClientRect();try{el.click();}catch(e){}return {ok:true,tag:(el.tagName||'').toLowerCase(),x:Math.round(r.left+r.width/2),y:Math.round(r.top+r.height/2)};})()`)).result?.value??{};if(!o.ok)return`Click failed: ${String(o.why??"unknown")}`;let r=Number(o.x??0),s=Number(o.y??0);return await this.send("Input.dispatchMouseEvent",{type:"mousePressed",x:r,y:s,button:"left",clickCount:1}),await this.send("Input.dispatchMouseEvent",{type:"mouseReleased",x:r,y:s,button:"left",clickCount:1}),`Clicked <${String(o.tag)}>@${e} at (${r}, ${s}).`}async typeText(e,n){let r=(await this.evaluate(`(()=>{const el=document.querySelector(${JSON.stringify(e)});if(!el)return {ok:false,why:'no matching element'};el.focus();return {ok:true,tag:(el.tagName||'').toLowerCase()};})()`)).result?.value??{};return r.ok?(await this.send("Input.insertText",{text:n}),`Typed ${n.length} characters into <${String(r.tag)}>@${e}.`):`Type failed: ${String(r.why??"unknown")}`}async evaluateExpression(e){let n=await this.evaluate(e);if(n.exceptionDetails){let r=n.exceptionDetails,s=r?.exception?.description??r?.text??"evaluation error";return`Evaluation error: ${String(s)}`}let o=n.result?.value;if(o===void 0)return"undefined";if(typeof o=="string")return o;try{return JSON.stringify(o)}catch{return String(o)}}async close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}if(this.failAll(new Error("Browser closed.")),this.child)try{this.child.kill("SIGTERM")}catch{}}}},_e;async function rt(){if(_e)return _e;let t=nt();if(!t)throw new Error(tt);return _e=await On.launch(t),_e}async function Ro(){await _e?.close(),_e=void 0}async function Dn(t){let n=(await _n(t.url)).href,o=Math.min(Math.max(t.maxChars??5e4,1),2e5),r=t.waitUntil??"load",s=t.waitMs??15e3;try{let i=await rt();await i.navigate(n,s,r);let a=await i.readPage(o);return{mode:"cdp",...a,title:a.title||n}}catch{let a=await nc(n);return{mode:"static",url:n,title:String(a.title??""),text:a.text.slice(0,o),truncated:a.text.length>o}}}async function Mo(t){let e=t.fullPage===!0;t.url&&await Dn({url:t.url,waitUntil:"load",waitMs:15e3,maxChars:4e3});try{return{path:await(await rt()).screenshot(e,t.rootDir),mode:"cdp"}}catch{if(t.url){let n=await rc(t.url,e,t.rootDir);if(n)return{path:n,mode:"static"}}throw new Error("Unable to capture a screenshot without a browser. "+tt)}}async function $o(t){return await(await rt()).click(t)}async function _o(t,e){return await(await rt()).typeText(t,e)}async function Ao(t){return await(await rt()).evaluateExpression(t)}async function nc(t){let e=nt();if(!e)throw new Error(tt);let n=await new Promise((r,s)=>{let i=In(e,["--headless=new","--no-sandbox","--disable-gpu","--dump-dom",t],{stdio:["ignore","pipe","pipe"]}),a="",c="",l=setTimeout(()=>i.kill("SIGKILL"),2e4);i.stdout.setEncoding("utf8"),i.stdout.on("data",u=>{a.length<1e6&&(a+=u)}),i.stderr.setEncoding("utf8"),i.stderr.on("data",u=>{c+=u}),i.once("error",u=>{clearTimeout(l),s(u)}),i.once("exit",u=>{clearTimeout(l),u!==0&&!a?s(new Error(c.trim()||`Browser exited with code ${u??1}.`)):r(a)})}),o=n.match(/<title[^>]*>([\s\S]*?)<\/title>/i);return{title:et(o?.[1]??""),text:et(n)}}async function rc(t,e,n){let o=nt();if(!o)return null;let r=be.join(n,".kpilot","run");await To(r,{recursive:!0});let s=be.join(".kpilot","run",`browser-${Date.now().toString(36)}.png`),i=be.join(n,s),a=["--headless=new","--no-sandbox","--disable-gpu"];return e&&a.push(`--window-size=${Eo},${Co*3}`),a.push(`--screenshot=${i}`,t),await new Promise(l=>{let u=In(o,a,{stdio:["ignore","ignore","ignore"]}),d=setTimeout(()=>u.kill("SIGKILL"),2e4);u.once("error",()=>{clearTimeout(d),l(!1)}),u.once("exit",p=>{clearTimeout(d),l(p===0)})})?s:null}var ac=new Set([".git","node_modules","dist","build",".next",".turbo","coverage",".cache",".idea"]),Bn=1e6,qn=2e5,cc=/(?:✓\s*)?Ready in\b|Local:\s+https?:\/\/|Network:\s+https?:\/\/|listening on (?:port\s+)?\d+\b|started server on\b|VITE .+ ready in\b/i,Oo=/ERR_PNPM_|ELIFECYCLE|EADDRINUSE|ECONNREFUSED|Error:\s|Command failed|exit code [1-9]\d*|Failed to compile|Module not found|Cannot find module|ENOENT|pnpm approve-builds|IGNORED_BUILDS/i,lc=/\b(?:pnpm|npm|yarn|bun)(?:\s+run)?\s+dev\b|\bnext\s+dev\b|\bvite(?:\s|$)|(?:^|[;&|]\s*)(?:nodemon|tsx\s+watch|node\s+--watch)\b|\bdocker\s+compose\s+up\b(?![^\n]*\s-d\b)/i;function ot(t,e=qn){if(t.length<=e)return t;let n=t.length-e;return`${t.slice(0,e)}
|
|
168
|
+
`).replace(/[ \t]{2,}/g," ").trim()}async function eu(t,e){if(!t.body){let s=await t.arrayBuffer(),i=Buffer.from(s);if(i.byteLength>e)throw new Error(`Response body exceeds ${e} byte limit.`);return i}let n=t.body.getReader(),r=[],o=0;for(;;){let{done:s,value:i}=await n.read();if(s)break;let a=Buffer.from(i??new Uint8Array);if(o+=a.byteLength,o>e)throw await n.cancel().catch(()=>{}),new Error(`Response body exceeds ${e} byte limit.`);r.push(a)}return Buffer.concat(r,o)}async function tu(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.fetchImpl??fetch,o=new URLSearchParams({q:e}),s=await r(Fs,{method:"POST",headers:{Accept:"text/html","Content-Type":"application/x-www-form-urlencoded","User-Agent":"kpilot/web_search"},body:o.toString(),signal:t.signal??AbortSignal.timeout(Oe)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`DuckDuckGo search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let i=await s.text(),a=Xl(i,n);return{query:e,count:a.length,results:a,provider:"duckduckgo"}}async function nu(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??Hl(),o=new URL(Ul);o.searchParams.set("q",e),o.searchParams.set("count",String(n));let i=await(t.fetchImpl??fetch)(o,{method:"GET",headers:{Accept:"application/json","Accept-Encoding":"gzip","X-Subscription-Token":r},signal:t.signal??AbortSignal.timeout(Oe)});if(!i.ok){let l=(await i.text().catch(()=>"")).slice(0,300);throw new Error(`Brave Search API returned HTTP ${i.status}${l?`: ${l}`:""}`)}let c=((await i.json()).web?.results??[]).filter(l=>typeof l?.url=="string"&&l.url.trim()).slice(0,n).map(l=>({title:String(l.title??"").trim()||l.url.trim(),url:l.url.trim(),description:String(l.description??"").trim()}));return{query:e,count:c.length,results:c,provider:"brave"}}async function ru(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??zl(),s=await(t.fetchImpl??fetch)(Nl,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":"kpilot/web_search"},body:JSON.stringify({api_key:r,query:e,max_results:n,include_answer:!1,include_raw_content:!1}),signal:t.signal??AbortSignal.timeout(Oe)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`Tavily search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let a=((await s.json()).results??[]).filter(c=>typeof c?.url=="string"&&/^https?:\/\//i.test(c.url)).slice(0,n).map(c=>({title:String(c.title??"").trim()||c.url.trim(),url:c.url.trim(),description:String(c.content??"").trim()}));return{query:e,count:a.length,results:a,provider:"tavily"}}async function ou(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??Vl(),s=await(t.fetchImpl??fetch)(Fl,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":r,"User-Agent":"kpilot/web_search"},body:JSON.stringify({query:e,numResults:n,contents:{text:!1}}),signal:t.signal??AbortSignal.timeout(Oe)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`Exa search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let a=((await s.json()).results??[]).filter(c=>typeof c?.url=="string"&&/^https?:\/\//i.test(c.url)).slice(0,n).map(c=>({title:String(c.title??"").trim()||c.url.trim(),url:c.url.trim(),description:String(c.text??"").trim().slice(0,300)}));return{query:e,count:a.length,results:a,provider:"exa"}}async function su(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??Yl(),s=await(t.fetchImpl??fetch)(ql,{method:"POST",headers:{"Content-Type":"application/json","X-API-KEY":r,"User-Agent":"kpilot/web_search"},body:JSON.stringify({q:e,num:n}),signal:t.signal??AbortSignal.timeout(Oe)});if(!s.ok){let c=(await s.text().catch(()=>"")).slice(0,300);throw new Error(`Serper search returned HTTP ${s.status}${c?`: ${c}`:""}`)}let a=((await s.json()).organic??[]).filter(c=>typeof c?.link=="string"&&/^https?:\/\//i.test(c.link)).slice(0,n).map(c=>({title:String(c.title??"").trim()||c.link.trim(),url:c.link.trim(),description:String(c.snippet??"").trim()}));return{query:e,count:a.length,results:a,provider:"serper"}}async function iu(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.baseUrl??wr();if(!r)throw new Error("SearXNG search requires SEARXNG_BASE_URL.");let o=new URL(`${r}/search`);o.searchParams.set("q",e),o.searchParams.set("format","json"),o.searchParams.set("safesearch","0");let i=await(t.fetchImpl??fetch)(o,{method:"GET",headers:{Accept:"application/json","User-Agent":"kpilot/web_search"},signal:t.signal??AbortSignal.timeout(Oe)});if(!i.ok){let l=(await i.text().catch(()=>"")).slice(0,300);throw new Error(`SearXNG search returned HTTP ${i.status}${l?`: ${l}`:""}`)}let c=((await i.json()).results??[]).filter(l=>typeof l?.url=="string"&&/^https?:\/\//i.test(l.url)).slice(0,n).map(l=>({title:String(l.title??"").trim()||l.url.trim(),url:l.url.trim(),description:String(l.content??"").trim()}));return{query:e,count:c.length,results:c,provider:"searxng"}}function ur(t,e){let{query:n,count:r,signal:o,fetchImpl:s,env:i}=e;switch(t){case"duckduckgo":return tu({query:n,count:r,signal:o,fetchImpl:s});case"tavily":return ru({query:n,count:r,signal:o,fetchImpl:s,apiKey:fr(i)});case"exa":return ou({query:n,count:r,signal:o,fetchImpl:s,apiKey:gr(i)});case"serper":return su({query:n,count:r,signal:o,fetchImpl:s,apiKey:hr(i)});case"searxng":return iu({query:n,count:r,signal:o,fetchImpl:s,baseUrl:wr(i)});case"brave":return nu({query:n,count:r,signal:o,fetchImpl:e.braveFetchImpl??s,apiKey:pr(i)})}}function Ns(t,e){switch(t){case"duckduckgo":return!0;case"tavily":return!!fr(e);case"exa":return!!gr(e);case"serper":return!!hr(e);case"searxng":return!!wr(e);case"brave":return!!pr(e)}}var au=["tavily","exa","serper","searxng","brave"];async function Bs(t){let e=t.env??process.env,n=t.fetchImpl??fetch,r={query:t.query,count:t.count,signal:t.signal,fetchImpl:n,env:e,braveFetchImpl:t.braveFetchImpl};if(t.provider){if(!Ns(t.provider,e))throw new Error(`Web search provider "${t.provider}" is not configured. Set the required key or enabling variable.`);return await ur(t.provider,r)}let o;try{let s=await ur("duckduckgo",r);if(s.results.length>0)return s;o=new Error("DuckDuckGo search returned no results.")}catch(s){o=s instanceof Error?s:new Error(String(s))}for(let s of au)if(Ns(s,e))try{let i=await ur(s,r);if(i.results.length>0)return{...i,fallbackReason:o?.message};o=new Error(`${s} search returned no results.`)}catch(i){o=i instanceof Error?i:new Error(String(i))}throw o??new Error("Web search failed.")}async function Js(t){let e=Math.min(Math.max(t.maxChars??Wl,1),Gl),n=t.fetchImpl??fetch,r=t.assertPublicUrlFn??yr,o=await r(t.url),s,i=0;for(;i<=lr;){if(s=await n(o,{method:"GET",redirect:"manual",headers:{Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,text/plain;q=0.8,*/*;q=0.5","User-Agent":"kpilot/web_fetch"},signal:t.signal??AbortSignal.timeout(Oe)}),s.status>=300&&s.status<400){let d=s.headers.get("location");if(!d)throw new Error(`Redirect without Location header from ${o.href}`);o=await r(new URL(d,o).href),i+=1;continue}break}if(!s)throw new Error("Failed to fetch URL.");if(i>lr)throw new Error(`Too many redirects (max ${lr}).`);if(!s.ok)throw new Error(`HTTP ${s.status} fetching ${o.href}`);let a=s.headers.get("content-type")??void 0,c=await eu(s,Kl),l=new TextDecoder().decode(c),u=a&&/html|xml|sgml/i.test(a)||/html/i.test(l.slice(0,512))?St(l):l.trim(),m=u.length>e;return{url:t.url,finalUrl:o.href,status:s.status,contentType:a,text:m?u.slice(0,e):u,truncated:m}}import{spawn as kr,spawnSync as cu}from"node:child_process";import{mkdir as Ws,writeFile as lu}from"node:fs/promises";import{tmpdir as uu}from"node:os";import Ie from"node:path";var Tt="Chromium is not installed. Install it (e.g. `brew install --cask chromium` on macOS, `sudo apt install chromium-browser` on Debian/Ubuntu, or point KPILOT_CHROME_PATH at a browser binary), or use web_fetch for static pages.",du=["google-chrome-stable","google-chrome","chromium-browser","chromium","microsoft-edge","microsoft-edge-stable"],mu=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],He;function br(t){try{let e=cu(t,["--version"],{timeout:3e3,stdio:"ignore"});return e.error===void 0&&e.status===0}catch{return!1}}function Pt(t=process.env){if(He!==void 0)return He||void 0;let e=t.KPILOT_CHROME_PATH?.trim();if(e&&br(e))return He=e,e;for(let n of du)if(br(n))return He=n,n;for(let n of mu)if(br(n))return He=n,n;He=null}function Ks(t){return new Promise(e=>{setTimeout(()=>e(),t)})}var Gs=1280,Hs=1200,vr=class t{child;ws;sessionId="";nextId=1;pending=new Map;closed=!1;constructor(e,n){this.child=e,this.ws=n,this.ws.addEventListener("message",r=>this.handleMessage(String(r?.data??""))),this.ws.addEventListener("close",()=>this.failAll(new Error("Browser connection closed.")))}static async launch(e){let n=Ie.join(uu(),`kpilot-browser-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,7)}`),r=kr(e,["--headless=new","--no-sandbox","--disable-gpu","--disable-dev-shm-usage","--disable-extensions",`--user-data-dir=${n}`,"--remote-debugging-port=0"],{stdio:["ignore","ignore","pipe"]}),o=await new Promise((a,c)=>{let l="",u=setTimeout(()=>{r.kill("SIGKILL"),c(new Error("Timed out waiting for the browser to expose a DevTools endpoint."))},15e3);r.stderr.setEncoding("utf8"),r.stderr.on("data",m=>{l+=m;let d=l.match(/DevTools listening on (ws:\/\/\S+)/i);d?.[1]&&(clearTimeout(u),a(d[1]))}),r.once("error",m=>{clearTimeout(u),c(m)}),r.once("exit",m=>{clearTimeout(u),c(new Error(`Browser exited before starting (code ${m??1}).`))})}),s=new WebSocket(o);await new Promise((a,c)=>{s.addEventListener("open",()=>a()),s.addEventListener("error",()=>c(new Error("Failed to open the DevTools WebSocket.")))});let i=new t(r,s);return await i.attachPageTarget(),i}async attachPageTarget(){let e=await this.send("Target.createTarget",{url:"about:blank"}),n=String(e.targetId??"");if(!n)throw new Error("Browser did not create a page target.");let r=await this.send("Target.attachToTarget",{targetId:n,flatten:!0});if(this.sessionId=String(r.sessionId??""),!this.sessionId)throw new Error("Browser did not attach a page session.")}send(e,n={},r=15e3){let o=this.nextId++,s={id:o,method:e,params:n};return this.sessionId&&(s.sessionId=this.sessionId),this.ws.send(JSON.stringify(s)),new Promise((i,a)=>{let c=setTimeout(()=>{this.pending.delete(o),a(new Error(`CDP ${e} timed out.`))},r);this.pending.set(o,{resolve:i,reject:a,timer:c})})}handleMessage(e){let n;try{n=JSON.parse(e)}catch{return}let r=n.id;if(r===void 0)return;let o=this.pending.get(r);if(o)if(clearTimeout(o.timer),this.pending.delete(r),n.error&&typeof n.error=="object"){let s=n.error;o.reject(new Error(String(s.message??"CDP error")))}else o.resolve(n.result??{})}async evaluate(e){return await this.send("Runtime.evaluate",{expression:e,returnByValue:!0,awaitPromise:!0})}failAll(e){for(let n of this.pending.values())clearTimeout(n.timer),n.reject(e);this.pending.clear()}async navigate(e,n,r){await this.send("Page.navigate",{url:e});let o=r==="domcontentloaded"?["interactive","complete"]:["complete"],s=Date.now()+Math.min(n,3e4);for(;Date.now()<s;){let i=await this.evaluate("document.readyState"),a=String(i.result?.value??"");if(o.includes(a))break;await Ks(120)}r==="networkidle2"&&await Ks(700)}async readPage(e){let n=await this.evaluate("JSON.stringify({title:document.title,url:location.href,text:(()=>{const c=document.body?document.body.cloneNode(true):null;if(!c)return '';c.querySelectorAll('script,style,noscript,svg,canvas,iframe,template').forEach(function(n){n.remove()});return (c.innerText||c.textContent||'').replace(/\\s+/g,' ').trim();})()})"),r={};try{r=JSON.parse(String(n.result?.value??"{}"))}catch{r={}}let o=String(r.text??""),s=o.length>e;return{url:String(r.url??""),title:String(r.title??""),text:s?o.slice(0,e):o,truncated:s}}async screenshot(e,n){let r=Gs,o=Hs;if(e){let u=(await this.send("Page.getLayoutMetrics")).cssContentSize?.height;o=Math.max(o,Math.ceil(Number(u)||o)),await this.send("Emulation.setDeviceMetricsOverride",{width:r,height:o,deviceScaleFactor:1,mobile:!1})}let s=await this.send("Page.captureScreenshot",{format:"png"}),i=String(s.data??"");if(!i)throw new Error("Browser returned an empty screenshot.");let a=Ie.join(n,".kpilot","run");await Ws(a,{recursive:!0});let c=Ie.join(".kpilot","run",`browser-${Date.now().toString(36)}.png`);return await lu(Ie.join(n,c),Buffer.from(i,"base64")),c}async click(e){let r=(await this.evaluate(`(()=>{const el=document.querySelector(${JSON.stringify(e)});if(!el)return {ok:false,why:'no matching element'};const r=el.getBoundingClientRect();try{el.click();}catch(e){}return {ok:true,tag:(el.tagName||'').toLowerCase(),x:Math.round(r.left+r.width/2),y:Math.round(r.top+r.height/2)};})()`)).result?.value??{};if(!r.ok)return`Click failed: ${String(r.why??"unknown")}`;let o=Number(r.x??0),s=Number(r.y??0);return await this.send("Input.dispatchMouseEvent",{type:"mousePressed",x:o,y:s,button:"left",clickCount:1}),await this.send("Input.dispatchMouseEvent",{type:"mouseReleased",x:o,y:s,button:"left",clickCount:1}),`Clicked <${String(r.tag)}>@${e} at (${o}, ${s}).`}async typeText(e,n){let o=(await this.evaluate(`(()=>{const el=document.querySelector(${JSON.stringify(e)});if(!el)return {ok:false,why:'no matching element'};el.focus();return {ok:true,tag:(el.tagName||'').toLowerCase()};})()`)).result?.value??{};return o.ok?(await this.send("Input.insertText",{text:n}),`Typed ${n.length} characters into <${String(o.tag)}>@${e}.`):`Type failed: ${String(o.why??"unknown")}`}async evaluateExpression(e){let n=await this.evaluate(e);if(n.exceptionDetails){let o=n.exceptionDetails,s=o?.exception?.description??o?.text??"evaluation error";return`Evaluation error: ${String(s)}`}let r=n.result?.value;if(r===void 0)return"undefined";if(typeof r=="string")return r;try{return JSON.stringify(r)}catch{return String(r)}}async close(){if(!this.closed){this.closed=!0;try{this.ws.close()}catch{}if(this.failAll(new Error("Browser closed.")),this.child)try{this.child.kill("SIGTERM")}catch{}}}},ze;async function Et(){if(ze)return ze;let t=Pt();if(!t)throw new Error(Tt);return ze=await vr.launch(t),ze}async function zs(){await ze?.close(),ze=void 0}async function xr(t){let n=(await yr(t.url)).href,r=Math.min(Math.max(t.maxChars??5e4,1),2e5),o=t.waitUntil??"load",s=t.waitMs??15e3;try{let i=await Et();await i.navigate(n,s,o);let a=await i.readPage(r);return{mode:"cdp",...a,title:a.title||n}}catch{let a=await pu(n);return{mode:"static",url:n,title:String(a.title??""),text:a.text.slice(0,r),truncated:a.text.length>r}}}async function Vs(t){let e=t.fullPage===!0;t.url&&await xr({url:t.url,waitUntil:"load",waitMs:15e3,maxChars:4e3});try{return{path:await(await Et()).screenshot(e,t.rootDir),mode:"cdp"}}catch{if(t.url){let n=await fu(t.url,e,t.rootDir);if(n)return{path:n,mode:"static"}}throw new Error("Unable to capture a screenshot without a browser. "+Tt)}}async function Ys(t){return await(await Et()).click(t)}async function Qs(t,e){return await(await Et()).typeText(t,e)}async function Xs(t){return await(await Et()).evaluateExpression(t)}async function pu(t){let e=Pt();if(!e)throw new Error(Tt);let n=await new Promise((o,s)=>{let i=kr(e,["--headless=new","--no-sandbox","--disable-gpu","--dump-dom",t],{stdio:["ignore","pipe","pipe"]}),a="",c="",l=setTimeout(()=>i.kill("SIGKILL"),2e4);i.stdout.setEncoding("utf8"),i.stdout.on("data",u=>{a.length<1e6&&(a+=u)}),i.stderr.setEncoding("utf8"),i.stderr.on("data",u=>{c+=u}),i.once("error",u=>{clearTimeout(l),s(u)}),i.once("exit",u=>{clearTimeout(l),u!==0&&!a?s(new Error(c.trim()||`Browser exited with code ${u??1}.`)):o(a)})}),r=n.match(/<title[^>]*>([\s\S]*?)<\/title>/i);return{title:St(r?.[1]??""),text:St(n)}}async function fu(t,e,n){let r=Pt();if(!r)return null;let o=Ie.join(n,".kpilot","run");await Ws(o,{recursive:!0});let s=Ie.join(".kpilot","run",`browser-${Date.now().toString(36)}.png`),i=Ie.join(n,s),a=["--headless=new","--no-sandbox","--disable-gpu"];return e&&a.push(`--window-size=${Gs},${Hs*3}`),a.push(`--screenshot=${i}`,t),await new Promise(l=>{let u=kr(r,a,{stdio:["ignore","ignore","ignore"]}),m=setTimeout(()=>u.kill("SIGKILL"),2e4);u.once("error",()=>{clearTimeout(m),l(!1)}),u.once("exit",d=>{clearTimeout(m),l(d===0)})})?s:null}var yu=new Set([".git","node_modules","dist","build",".next",".turbo","coverage",".cache",".idea"]),Rr=1e6,Cr=2e5,bu=/(?:✓\s*)?Ready in\b|Local:\s+https?:\/\/|Network:\s+https?:\/\/|listening on (?:port\s+)?\d+\b|started server on\b|VITE .+ ready in\b/i,Zs=/ERR_PNPM_|ELIFECYCLE|EADDRINUSE|ECONNREFUSED|Error:\s|Command failed|exit code [1-9]\d*|Failed to compile|Module not found|Cannot find module|ENOENT|pnpm approve-builds|IGNORED_BUILDS/i,vu=/\b(?:pnpm|npm|yarn|bun)(?:\s+run)?\s+dev\b|\bnext\s+dev\b|\bvite(?:\s|$)|(?:^|[;&|]\s*)(?:nodemon|tsx\s+watch|node\s+--watch)\b|\bdocker\s+compose\s+up\b(?![^\n]*\s-d\b)/i;function Rt(t,e=Cr){if(t.length<=e)return t;let n=t.length-e;return`${t.slice(0,e)}
|
|
124
169
|
|
|
125
|
-
[output truncated: ${n} characters omitted]`}function
|
|
170
|
+
[output truncated: ${n} characters omitted]`}function Mr(t,e){let n=t;for(let[r,o]of Object.entries(e))!o||o.length<8||!/(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL)/i.test(r)||(n=n.split(o).join(`[REDACTED:${r}]`));return n}async function fn(t,e,n){let r=n.timeoutMs??3e4,o=n.env??process.env;return await new Promise((s,i)=>{let a=ri(t,e,{cwd:n.cwd,env:o,shell:n.shell??!1,stdio:["ignore","pipe","pipe"]}),c="",l="",u=!1,m=!1;a.stdout?.setEncoding("utf8"),a.stderr?.setEncoding("utf8");let d="",p=x=>{if(!n.onOutput)return;d+=x;let k=d.split(/\r?\n/);d=k.pop()??"";for(let R of k)n.onOutput(R)};a.stdout?.on("data",x=>{c.length<Cr*2&&(c+=x),p(x)}),a.stderr?.on("data",x=>{l.length<Cr*2&&(l+=x),p(x)});let y=()=>{m=!0,a.kill("SIGTERM"),setTimeout(()=>a.kill("SIGKILL"),1e3)};n.signal?.aborted?y():n.signal?.addEventListener("abort",y,{once:!0});let S=setTimeout(()=>{u=!0,a.kill("SIGTERM"),setTimeout(()=>a.kill("SIGKILL"),1e3)},r);a.once("error",x=>{clearTimeout(S),n.signal?.removeEventListener("abort",y),i(x)}),a.once("close",x=>{clearTimeout(S),n.signal?.removeEventListener("abort",y),s({code:x??1,stdout:Rt(Mr(c,o)),stderr:Rt(Mr(l,o)),timedOut:u,cancelled:m})})})}function Tr(t,e){let n=W.relative(t,e);return n===""||!n.startsWith("..")&&!W.isAbsolute(n)}async function ku(t){let e=t;for(;;)try{return await De(e),e}catch{let n=W.dirname(e);if(n===e)throw new Error(`No existing ancestor found for ${t}`);e=n}}var $r=class{rootDir;canonicalRoot;constructor(e){this.rootDir=W.resolve(e)}async root(){this.canonicalRoot??=await Sr(this.rootDir);let e=this.canonicalRoot;if(!e)throw new Error("Unable to resolve the project root.");return e}async resolve(e,n={}){if(e.includes("\0"))throw new Error("Paths cannot contain null bytes.");let r=await this.root(),o=W.resolve(r,e||".");if(!Tr(r,o))throw new Error(`Path escapes the project root: ${e}`);if(n.mustExist){let a=await Sr(o);if(!Tr(r,a))throw new Error(`Resolved path escapes the project root: ${e}`);return a}let s=await ku(o),i=await Sr(s);if(!Tr(r,i))throw new Error(`Path crosses a symlink outside the project root: ${e}`);return o}};function K(t,e,n,r=[]){return{type:"function",function:{name:t,description:e,parameters:{type:"object",properties:n,required:r,additionalProperties:!1}}}}var ei=[K("workspace_summary","Return a concise repository overview, top-level files, detected manifests, and Git status.",{}),K("list_files","List files and directories under a project-relative path. Common generated directories are ignored.",{path:{type:"string",description:"Project-relative directory. Defaults to the project root."},max_depth:{type:"integer",minimum:0,maximum:8,description:"Maximum recursive depth."},max_entries:{type:"integer",minimum:1,maximum:2e3,description:"Maximum returned entries."}}),K("read_file","Read a UTF-8 text file with optional 1-based line boundaries.",{path:{type:"string",description:"Project-relative file path."},start_line:{type:"integer",minimum:1},end_line:{type:"integer",minimum:1}},["path"]),K("search_text","Search text across project files using ripgrep when available, with a built-in fallback.",{query:{type:"string",description:"Literal or regex search query."},path:{type:"string",description:"Project-relative search path. Defaults to root."},regex:{type:"boolean",description:"Interpret query as a regular expression."},max_results:{type:"integer",minimum:1,maximum:500}},["query"]),K("write_file","Create or replace a UTF-8 file. Prefer content (raw text) for .env, markdown, JSON, and other plain config. Use content_b64 only for multi-line source code with nested quotes that break JSON. Prefer replace_in_file for small edits.",{path:{type:"string",description:"Project-relative file path."},content:{type:"string",description:"Raw UTF-8 content. Preferred for .env and plain text."},content_b64:{type:"string",description:"Standard base64 of UTF-8 bytes. Only for code with nested quotes; never invent placeholder base64."},overwrite:{type:"boolean",description:"Allow replacing an existing file. Defaults to true."}},["path"]),K("replace_in_file","Replace an exact string in a UTF-8 file. Prefer this over write_file for small edits \u2014 safer and easier for tool JSON.",{path:{type:"string"},old_string:{type:"string"},new_string:{type:"string"},expected_occurrences:{type:"integer",minimum:1,maximum:1e3}},["path","old_string","new_string"]),K("make_directory","Create a directory recursively inside the project.",{path:{type:"string"}},["path"]),K("delete_path","Delete a file, or a directory only when recursive is explicitly true.",{path:{type:"string"},recursive:{type:"boolean"}},["path"]),K("shell","Run a shell command from a project-relative working directory. For long-lived processes (pnpm/npm/yarn/bun dev, next dev, vite, watchers), set background=true (or rely on auto-detect) so the server keeps running; the tool returns pid + log path after a ready line or wait_ms.",{command:{type:"string"},cwd:{type:"string",description:"Project-relative working directory."},timeout_ms:{type:"integer",minimum:100,maximum:36e5,description:"Foreground only: kill the command after this many ms (default 30000). When the sandbox sets a timeout cap, the lower of the two applies."},background:{type:"boolean",description:"Detach and keep running. Use for dev servers and watchers. Auto-enabled for common `*dev` / vite / next dev commands."},ready_pattern:{type:"string",description:"Optional regex (case-insensitive) matched against the background log before returning."},wait_ms:{type:"integer",minimum:500,maximum:36e5,description:"Background only: how long to wait for ready_pattern (default 45000)."}},["command"]),K("git_status","Show concise Git working-tree status.",{}),K("git_diff","Show the current Git diff, optionally staged and optionally limited to a path.",{staged:{type:"boolean"},path:{type:"string"}}),K("web_search","Search the public web. Auto mode tries free DuckDuckGo first, then the first configured API provider (TAVILY_API_KEY -> EXA_API_KEY -> SERPER_API_KEY -> SEARXNG_BASE_URL -> BRAVE_API_KEY). Set `provider` to force one. Returns titles, URLs, and descriptions.",{query:{type:"string",description:"Search query."},count:{type:"integer",minimum:1,maximum:10,description:"Number of results to return (default 5)."},provider:{type:"string",enum:["duckduckgo","brave","tavily","exa","serper","searxng"],description:"Optional provider to use; omit for auto. Requires the matching API key."}},["query"]),K("web_fetch","Fetch a public http(s) URL and return extracted text. Blocks private/link-local hosts (SSRF protection). Prefer web_search first when the URL is unknown.",{url:{type:"string",description:"Absolute http(s) URL to fetch."},max_chars:{type:"integer",minimum:1,maximum:2e5,description:"Maximum characters of extracted text to return (default 50000)."}},["url"])],xu=[K("browser_open","Open a URL in a real (headless Chromium) browser and return the JavaScript-rendered page text. Use when web_fetch returns empty or a page requires JS. Requires a Chromium browser (KPILOT_CHROME_PATH or system Chrome/Chromium/Edge).",{url:{type:"string",description:"Absolute http(s) URL to open."},wait_until:{type:"string",enum:["load","domcontentloaded","networkidle2"],description:"When to consider the page loaded (default load). networkidle2 waits ~0.7s extra for async JS."},wait_ms:{type:"integer",minimum:1e3,maximum:6e4,description:"Maximum wait for page load (default 15000)."},max_chars:{type:"integer",minimum:1,maximum:2e5,description:"Maximum extracted text characters (default 50000)."}},["url"]),K("browser_screenshot","Capture a PNG screenshot of the current browser session page (or a given URL) into .kpilot/run/ and return its relative path.",{url:{type:"string",description:"Optional URL to open before screenshot; omit to capture the current page."},full_page:{type:"boolean",description:"Capture the full page height instead of the viewport."}}),K("browser_click","Click an element in the current browser session by CSS selector.",{selector:{type:"string",description:"CSS selector of the element to click."}},["selector"]),K("browser_type","Type text into a focused-able element in the current browser session (input/textarea) by CSS selector.",{selector:{type:"string",description:"CSS selector of the input element."},text:{type:"string",description:"Text to type."}},["selector","text"]),K("browser_evaluate","Evaluate a JavaScript expression in the current browser session page and return its JSON-serializable result.",{expression:{type:"string",description:"JavaScript expression that yields a JSON-serializable value."}},["expression"]),K("browser_close","Close the browser session and release the Chromium process.",{})];async function ti(t){try{return await De(t),!0}catch{return!1}}async function _r(t,e,n,r){let o=[];async function s(i,a){if(o.length>=r)return;let c=await hu(i,{withFileTypes:!0});c.sort((l,u)=>l.name.localeCompare(u.name));for(let l of c){if(o.length>=r)break;if(yu.has(l.name))continue;let u=W.join(i,l.name),m=W.relative(e,u)||".";o.push(`${l.isDirectory()?"d":l.isSymbolicLink()?"l":"f"} ${m}`),l.isDirectory()&&a<n&&await s(u,a+1)}}return await s(t,0),o.length>=r&&o.push(`[truncated at ${r} entries]`),o}async function Su(t,e,n,r,o){let s=r?new RegExp(n,"i"):void 0,i=await _r(t,e,8,5e3),a=[];for(let c of i){if(!c.startsWith("f "))continue;let l=c.slice(2),u=W.join(e,l);if((await De(u)).size>Rr)continue;let d;try{d=await gn(u,"utf8")}catch{continue}if(d.includes("\0"))continue;let p=d.split(/\r?\n/);for(let y=0;y<p.length;y+=1){let S=p[y]??"";if((s?s.test(S):S.toLowerCase().includes(n.toLowerCase()))&&a.push(`${l}:${y+1}:${S}`),a.length>=o)return a}}return a}function Tu(t){let e=[`exit_code: ${t.code}`,`timed_out: ${t.timedOut}`,`cancelled: ${t.cancelled}`];return t.stdout&&e.push(`stdout:
|
|
126
171
|
${t.stdout}`),t.stderr&&e.push(`stderr:
|
|
127
172
|
${t.stderr}`),e.join(`
|
|
128
|
-
`)}function
|
|
129
|
-
`,"utf8");let
|
|
130
|
-
${
|
|
131
|
-
`),metadata:{background:!0,pid:l,id:n,log:
|
|
132
|
-
${
|
|
133
|
-
`),metadata:{background:!0,pid:l,id:n,log:
|
|
134
|
-
${
|
|
135
|
-
`),metadata:{background:!0,pid:l,id:n,log:
|
|
173
|
+
`)}function Pu(t){return vu.test(t.trim())}function Eu(t){return new Promise(e=>{setTimeout(()=>e(),t)})}async function Ar(t,e=4e3){try{let n=await gn(t,"utf8");return n.length<=e?n:n.slice(-e)}catch{return""}}async function Ru(t){let e=Date.now()+t.waitMs;for(;Date.now()<e;){if(t.signal?.aborted)return{ready:!1,failed:!1,exitedEarly:!1};let n=await Ar(t.logPath,8e4);if(Zs.test(n)&&!t.pattern.test(n))return{ready:!1,failed:!0,exitedEarly:!1};if(t.pattern.test(n))return{ready:!0,failed:!1,exitedEarly:!1};try{process.kill(t.pid,0)}catch{return{ready:!1,failed:!1,exitedEarly:!0}}await Eu(250)}try{process.kill(t.pid,0);let n=await Ar(t.logPath,8e4);return Zs.test(n)?{ready:!1,failed:!0,exitedEarly:!1}:{ready:!1,failed:!1,exitedEarly:!1}}catch{return{ready:!1,failed:!1,exitedEarly:!0}}}function Cu(t){let e=t.match(/https?:\/\/(?:localhost|127\.0\.0\.1):\d+\b/gi)??[];return[...new Set(e.map(n=>n.replace(/\/$/,"")))]}async function ni(t){for(let e of t.slice(0,3))try{let n=new AbortController,r=setTimeout(()=>n.abort(),1500);try{return await fetch(e,{signal:n.signal,redirect:"manual"}),{url:e,ok:!0}}finally{clearTimeout(r)}}catch(n){let r=n instanceof Error?n.message:String(n);if(/abort|timeout/i.test(r)||/ECONNREFUSED|fetch failed|ENOTFOUND/i.test(r))continue}}async function Mu(t){let e=W.join(t.rootDir,E,"run");await Pr(e,{recursive:!0});let n=`bg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,r=W.join(E,"run",`${n}.log`),o=W.join(E,"run",`${n}.json`),s=W.join(t.rootDir,r),i=W.join(t.rootDir,o),a=await gu(s,"a"),c;try{c=ri(t.command,t.args,{cwd:t.cwd,env:t.env,detached:!0,stdio:["ignore",a.fd,a.fd]})}finally{await a.close()}if(c.pid==null)return{ok:!1,output:"Failed to start background process (no pid)."};let l=c.pid;c.unref();let u={id:n,pid:l,command:t.originalCommand,cwd:t.cwd,log:r,backend:t.backend,startedAt:new Date().toISOString()};await Er(i,`${JSON.stringify(u,null,2)}
|
|
174
|
+
`,"utf8");let m=null;c.once("exit",_=>{m=_});let d=t.readyPattern?new RegExp(t.readyPattern,"i"):bu,p=await Ru({logPath:s,pid:l,pattern:d,waitMs:t.waitMs,signal:t.signal}),y=Mr(await Ar(s),t.env),S=Cu(y),x=p.ready?await ni(S):void 0;!p.ready&&!p.failed&&!p.exitedEarly&&S.length>0&&(x=await ni(S));let k=(()=>{try{return process.kill(l,0),m===null}catch{return!1}})(),R=!!(k&&(p.ready||x?.ok)&&!p.failed&&m===null),P=()=>{try{process.kill(-l,"SIGTERM")}catch{try{process.kill(l,"SIGTERM")}catch{}}};return p.exitedEarly||m!==null||!k?{ok:!1,output:[`Background process is NOT running (pid=${l}, id=${n}). Do not tell the user the server is up.`,`command: ${t.originalCommand}`,`log: ${r}`,`meta: ${o}`,`sandbox: ${t.backend}`,y?`--- log ---
|
|
175
|
+
${Rt(y)}`:"[empty log]"].join(`
|
|
176
|
+
`),metadata:{background:!0,pid:l,id:n,log:r,ready:!1}}:p.failed||!R?(P(),{ok:!1,output:[`Background process started (pid=${l}) but is NOT ready. Do not tell the user the server is up.`,`command: ${t.originalCommand}`,p.failed?"ready: no (failure detected in log \u2014 install/build/runtime error)":`ready: no (no server startup line after ${t.waitMs}ms; http probe ${x?.ok?"ok":"failed/skipped"})`,`log: ${r}`,`meta: ${o}`,`sandbox: ${t.backend}`,"Process was stopped. Fix the error in the log (e.g. pnpm approve-builds / install), then retry.",y?`--- log (tail) ---
|
|
177
|
+
${Rt(y)}`:"[empty log so far]"].join(`
|
|
178
|
+
`),metadata:{background:!0,pid:l,id:n,log:r,ready:!1,failed:p.failed}}):{ok:!0,output:[`Started background process pid=${l} id=${n}`,`command: ${t.originalCommand}`,p.ready?"ready: yes (matched startup pattern in log)":`ready: yes (HTTP probe succeeded at ${x?.url})`,x?.url?`url: ${x.url}`:S[0]?`url: ${S[0]} (from log)`:void 0,`log: ${r}`,`meta: ${o}`,`sandbox: ${t.backend}`,"Process keeps running after this tool returns.",y?`--- log (tail) ---
|
|
179
|
+
${Rt(y)}`:"[empty log so far]"].filter(Boolean).join(`
|
|
180
|
+
`),metadata:{background:!0,pid:l,id:n,log:r,ready:!0,url:x?.url??S[0]}}}function $u(t){let e=t.replace(/\s+/g,"");if(!e)throw new Error("content_b64 is empty.");if(e==="QWxhZGRpbjpvcGVuIHNlc2FtZQ==")throw new Error("content_b64 is a placeholder example, not your file bytes. For .env and plain text, call write_file with content (raw string), not content_b64.");if(!/^[A-Za-z0-9+/]+={0,2}$/.test(e)||e.length%4!==0)throw new Error("content_b64 is not valid base64. For .env/config/markdown use write_file with content instead.");let n=Buffer.from(e,"base64"),r=n.toString("base64").replace(/=+$/,""),o=e.replace(/=+$/,"");if(r!==o)throw new Error("content_b64 failed base64 round-trip. For .env/config/markdown use write_file with content instead.");let s=n.toString("utf8");if(s.includes("\uFFFD"))throw new Error("content_b64 does not decode to valid UTF-8 text.");return s}var be=class{rootDir;guard;sandbox;browserEnabled;browserClosed=!1;constructor(e,n={}){this.rootDir=W.resolve(e),this.guard=new $r(this.rootDir),this.sandbox=new pn(this.rootDir,n.sandbox);let r=n.browser??"auto";this.browserEnabled=r==="on"?!0:r==="off"?!1:Pt()!==void 0}definitions(){return this.browserEnabled?[...ei,...xu]:ei}async execute(e,n,r){if(W.resolve(r.rootDir)!==this.rootDir)throw new Error("Tool runtime root does not match the agent root.");try{switch(e){case"workspace_summary":return await this.workspaceSummary();case"list_files":return await this.listFiles(n);case"read_file":return await this.readFile(n);case"search_text":return await this.searchText(n);case"write_file":return await this.writeFile(n);case"replace_in_file":return await this.replaceInFile(n);case"make_directory":return await this.makeDirectory(n);case"delete_path":return await this.deletePath(n);case"shell":return await this.shell(n,r.signal,r.onOutput);case"git_status":return await this.gitStatus(r.signal);case"git_diff":return await this.gitDiff(n,r.signal);case"web_search":return await this.webSearch(n,r.signal);case"web_fetch":return await this.webFetch(n,r.signal);case"browser_open":return await this.browserOpen(n);case"browser_screenshot":return await this.browserScreenshot(n);case"browser_click":return await this.browserClick(n);case"browser_type":return await this.browserType(n);case"browser_evaluate":return await this.browserEvaluate(n);case"browser_close":return await this.browserClose();default:return{ok:!1,output:`Unknown tool: ${e}`}}}catch(o){return{ok:!1,output:o instanceof Error?o.message:String(o)}}}async workspaceSummary(){let e=await _r(this.rootDir,this.rootDir,1,80),n=["package.json","pnpm-workspace.yaml","pyproject.toml","Cargo.toml","go.mod","composer.json","Gemfile","pom.xml","build.gradle"],r=[];for(let u of n)await ti(W.join(this.rootDir,u))&&r.push(u);let o=await this.gitStatus(),s=(o.output||"").split(/\r?\n/),i=40,a=s.length<=i?o.output:`${s.slice(0,i).join(`
|
|
136
181
|
`)}
|
|
137
|
-
\u2026[${s.length-i} more git status lines omitted]`,c=[`root: ${this.rootDir}`,`manifests: ${
|
|
182
|
+
\u2026[${s.length-i} more git status lines omitted]`,c=[`root: ${this.rootDir}`,`manifests: ${r.length?r.join(", "):"none detected"}`,"top_level:",...e,"git_status:",a].join(`
|
|
138
183
|
`),l=3e3;return{ok:!0,output:c.length<=l?c:`${c.slice(0,l)}
|
|
139
|
-
\u2026[workspace_summary truncated ${c.length-l} chars for hub context]
|
|
140
|
-
`)||"[empty directory]"}}async readFile(e){let n=
|
|
141
|
-
`),metadata:{total_lines:c.length,start_line:
|
|
142
|
-
`)||"[no matches]"}}catch{}
|
|
143
|
-
`)||"[no matches]"}}async writeFile(e){let n=
|
|
144
|
-
sandbox: ${d.backend}`,metadata:{sandbox:d.backend}}}async gitStatus(e){try{let n=await
|
|
184
|
+
\u2026[workspace_summary truncated ${c.length-l} chars for hub context]`,metadata:{top_level:e.length,manifests:r.length}}}async listFiles(e){let n=X(e,"path")??".",r=ne(e,"max_depth",3,0,8),o=ne(e,"max_entries",500,1,2e3),s=await this.guard.resolve(n,{mustExist:!0});if(!(await De(s)).isDirectory())throw new Error(`${n} is not a directory.`);let a=await _r(s,this.rootDir,r,o);return{ok:!0,output:a.join(`
|
|
185
|
+
`)||"[empty directory]",metadata:{entries:a.length}}}async readFile(e){let n=F(e,"path"),r=ne(e,"start_line",1,1,1e7),o=ne(e,"end_line",r+119,r,1e7),s=await this.guard.resolve(n,{mustExist:!0}),i=await De(s);if(!i.isFile())throw new Error(`${n} is not a file.`);if(i.size>Rr)throw new Error(`File exceeds ${Rr} bytes.`);let a=await gn(s,"utf8");if(a.includes("\0"))throw new Error("Binary files are not supported by read_file.");let c=a.split(/\r?\n/);return{ok:!0,output:c.slice(r-1,o).map((m,d)=>`${String(r+d).padStart(6," ")} | ${m}`).join(`
|
|
186
|
+
`),metadata:{total_lines:c.length,start_line:r,end_line:Math.min(o,c.length)}}}async searchText(e){let n=F(e,"query",{maximumLength:2e3}),r=X(e,"path")??".",o=Me(e,"regex",!1),s=ne(e,"max_results",100,1,500),i=await this.guard.resolve(r,{mustExist:!0}),a=["--line-number","--no-heading","--color","never","--hidden","--glob","!/.git/**","--glob","!/node_modules/**","--glob","!/dist/**"];o||a.push("--fixed-strings"),a.push("--max-count",String(s),"--",n,i);try{let l=await fn("rg",a,{cwd:this.rootDir,timeoutMs:15e3});if(l.code===0||l.code===1){let u=l.stdout.split(/\r?\n/).filter(Boolean).slice(0,s).map(m=>m.replace(`${this.rootDir}${W.sep}`,""));return{ok:!0,output:u.join(`
|
|
187
|
+
`)||"[no matches]",metadata:{matches:u.length}}}}catch{}let c=await Su(i,this.rootDir,n,o,s);return{ok:!0,output:c.join(`
|
|
188
|
+
`)||"[no matches]",metadata:{matches:c.length}}}async writeFile(e){let n=F(e,"path"),r=X(e,"content_b64"),o;if(r!==void 0){if(o=$u(r),o.length===0)throw new Error("content_b64 decoded to an empty file. For .env use write_file with content.")}else if(Object.prototype.hasOwnProperty.call(e,"content"))o=F(e,"content",{allowEmpty:!0});else throw new Error("write_file requires content or content_b64.");let s=Me(e,"overwrite",!0),i=await this.guard.resolve(n);if(!s&&await ti(i))throw new Error(`${n} already exists.`);await Pr(W.dirname(i),{recursive:!0}),await Er(i,o,"utf8");let a=/\.(env|md|txt|json|ya?ml|toml|ini)$/i.test(n)||n===".env"?" File written successfully \u2014 do not rewrite with content_b64; use read_file only if you need to verify.":" File written successfully \u2014 do not repeat write_file for this path unless the content must change.";return{ok:!0,output:`Wrote ${o.length} characters to ${n}.${a}`}}async replaceInFile(e){let n=F(e,"path"),r=F(e,"old_string",{allowEmpty:!1}),o=F(e,"new_string",{allowEmpty:!0}),s=ne(e,"expected_occurrences",1,1,1e3),i=await this.guard.resolve(n,{mustExist:!0}),a=await gn(i,"utf8"),c=a.split(r).length-1;if(c!==s)throw new Error(`Expected ${s} occurrence(s), found ${c}; file was not changed.`);let l=a.split(r).join(o);return await Er(i,l,"utf8"),{ok:!0,output:`Replaced ${c} occurrence(s) in ${n}.`}}async makeDirectory(e){let n=F(e,"path"),r=await this.guard.resolve(n);return await Pr(r,{recursive:!0}),{ok:!0,output:`Created directory ${n}.`}}async deletePath(e){let n=F(e,"path");if(n==="."||n==="")throw new Error("Deleting the project root is forbidden.");let r=Me(e,"recursive",!1),o=await this.guard.resolve(n,{mustExist:!0});if((await De(o)).isDirectory()&&!r)throw new Error("Directory deletion requires recursive=true.");return await wu(o,{recursive:r,force:!1}),{ok:!0,output:`Deleted ${n}.`}}async shell(e,n,r){let o=F(e,"command",{maximumLength:2e4}),s=X(e,"cwd")??".",i=ne(e,"timeout_ms",3e4,100,36e5),a=e.background===void 0?Pu(o):Me(e,"background",!1),c=ne(e,"wait_ms",45e3,500,36e5),l=X(e,"ready_pattern");if(l)try{new RegExp(l,"i")}catch{throw new Error(`Invalid ready_pattern regex: ${l}`)}let u=await this.guard.resolve(s,{mustExist:!0});if(!(await De(u)).isDirectory())throw new Error(`${s} is not a directory.`);let d=await this.sandbox.prepareShell(o,u,i);if(a)return await Mu({command:d.command,args:d.args,cwd:d.cwd,env:d.env,rootDir:this.rootDir,originalCommand:o,backend:d.backend,readyPattern:l,waitMs:c,signal:n});let p=await fn(d.command,d.args,{cwd:d.cwd,timeoutMs:d.timeoutMs,env:d.env,signal:n,...r?{onOutput:r}:{}});return{ok:p.code===0&&!p.timedOut&&!p.cancelled,output:`${Tu(p)}
|
|
189
|
+
sandbox: ${d.backend}`,metadata:{sandbox:d.backend}}}async gitStatus(e){try{let n=await fn("git",["status","--short","--branch"],{cwd:this.rootDir,timeoutMs:1e4,signal:e});return{ok:n.code===0,output:n.stdout||n.stderr||"[clean working tree]"}}catch(n){return{ok:!1,output:n instanceof Error?n.message:String(n)}}}async gitDiff(e,n){let r=Me(e,"staged",!1),o=X(e,"path"),s=["diff"];r&&s.push("--cached"),o&&(await this.guard.resolve(o),s.push("--",o));let i=await fn("git",s,{cwd:this.rootDir,timeoutMs:15e3,signal:n});return{ok:i.code===0,output:i.stdout||i.stderr||"[no diff]"}}async webSearch(e,n){let r=F(e,"query",{maximumLength:500}),o=ne(e,"count",5,1,10),s=X(e,"provider"),i=await Bs({query:r,count:o,provider:s,signal:n});return{ok:!0,output:JSON.stringify(i,null,2),metadata:{provider:i.provider,resultCount:i.count,...i.fallbackReason?{fallbackReason:i.fallbackReason}:{}}}}async webFetch(e,n){let r=F(e,"url",{maximumLength:2e3}),o=ne(e,"max_chars",5e4,1,2e5),s=await Js({url:r,maxChars:o,signal:n});return{ok:!0,output:`${[`url: ${s.url}`,`final_url: ${s.finalUrl}`,`status: ${s.status}`,s.contentType?`content_type: ${s.contentType}`:void 0,s.truncated?"truncated: true":void 0].filter(Boolean).join(`
|
|
145
190
|
`)}
|
|
146
191
|
|
|
147
|
-
${s.text}`,metadata:{status:s.status,finalUrl:s.finalUrl,truncated:s.truncated}}}browserToolsAvailable(){return this.browserEnabled}async browserOpen(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=
|
|
192
|
+
${s.text}`,metadata:{status:s.status,finalUrl:s.finalUrl,truncated:s.truncated}}}browserToolsAvailable(){return this.browserEnabled}async browserOpen(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=F(e,"url",{maximumLength:2e3}),r=X(e,"wait_until"),o=ne(e,"wait_ms",15e3,1e3,6e4),s=ne(e,"max_chars",5e4,1,2e5),i=await xr({url:n,waitUntil:r,waitMs:o,maxChars:s});return{ok:!0,output:`${[`mode: ${i.mode}`,`url: ${i.url}`,i.title?`title: ${i.title}`:void 0,i.truncated?"truncated: true":void 0].filter(Boolean).join(`
|
|
148
193
|
`)}
|
|
149
194
|
|
|
150
|
-
${i.text}`,metadata:{mode:i.mode,url:i.url,truncated:i.truncated}}}async browserScreenshot(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=
|
|
195
|
+
${i.text}`,metadata:{mode:i.mode,url:i.url,truncated:i.truncated}}}async browserScreenshot(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=X(e,"url"),r=Me(e,"full_page",!1),o=await Vs({url:n,fullPage:r,rootDir:this.rootDir});return{ok:!0,output:`Screenshot saved to ${o.path}`,metadata:{path:o.path,mode:o.mode}}}async browserClick(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=F(e,"selector",{maximumLength:2e3});return{ok:!0,output:await Ys(n)}}async browserType(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=F(e,"selector",{maximumLength:2e3}),r=F(e,"text",{maximumLength:2e4});return{ok:!0,output:await Qs(n,r)}}async browserEvaluate(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=F(e,"expression",{maximumLength:1e4});return{ok:!0,output:await Xs(n)}}async browserClose(){return await zs(),this.browserClosed=!0,{ok:!0,output:"Browser session closed."}}browserUnavailable(){return{ok:!1,output:"Browser tools are disabled (no Chromium detected, or tools.browser is off). "+Tt}}};var ii={explorer:"Map the relevant code paths, dependencies, and architecture. Do not edit files. Return exact file references and concise findings.",reviewer:"Review for correctness, regressions, maintainability, and missing validation. Do not edit files. Report findings by severity.",tester:"Identify the relevant tests, likely failure modes, and the smallest useful validation plan. You may run read-only discovery commands but must not edit files.",security:"Inspect trust boundaries, input validation, secret handling, command execution, and authorization. Do not edit files. Report exploitable risks first."};function oi(t,e){let n=t[e];if(!(n==null||n==="")){if(typeof n!="string"||!n.trim())throw new Error(`"${e}" must be a non-empty string when provided.`);return n.trim()}}function _u(){return{type:"function",function:{name:"delegate_subagents",description:["Run up to four read-only specialist coding subagents in parallel, then return their independent findings.","Optionally set route and/or model on each task so that specialist can use a different capability tier than the primary agent.",`Supported routes: ${_e.join(", ")}.`,"Omit route and model to reuse the primary model."].join(" "),parameters:{type:"object",properties:{tasks:{type:"array",minItems:1,maxItems:4,items:{type:"object",properties:{role:{type:"string",enum:["explorer","reviewer","tester","security"]},task:{type:"string"},route:{type:"string",enum:[..._e],description:"Optional capability tier for this subagent (fast, balanced, complex, \u2026)."},model:{type:"string",description:"Optional explicit preferred model id for this subagent."}},required:["role","task"],additionalProperties:!1}}},required:["tasks"],additionalProperties:!1}}}}function Au(t,e){let n=t.tasks;if(!Array.isArray(n)||n.length===0)throw new Error('"tasks" must be a non-empty array.');if(n.length>e)throw new Error(`At most ${e} subagents may run at once.`);return n.map((r,o)=>{if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`tasks[${o}] must be an object.`);let s=r,i=F(s,"role");if(!(i in ii))throw new Error(`Unsupported subagent role: ${i}`);let a=oi(s,"route");if(a&&!bt(a))throw new Error(`tasks[${o}].route must be one of ${_e.join(", ")}.`);let c=oi(s,"model");return{role:i,task:F(s,"task",{maximumLength:1e4}),...a?{route:a}:{},...c?{model:c}:{}}})}var Ou=12,si=4e3,hn=class{options;constructor(e){if(this.options={...e,maxParallel:e.maxParallel??4},this.options.maxParallel<1||this.options.maxParallel>4)throw new Error("maxParallel must be between 1 and 4.")}definitions(){return[_u()]}async gatewayFor(e){let n={...e.route?{route:e.route}:{},...e.model?{model:e.model}:{}};if(!n.route&&!n.model)return{gateway:this.options.gateway,selection:n};if(!this.options.resolveGateway)throw new Error("This session cannot resolve per-task subagent routes/models. Omit route and model, or use a provider that supports resolution.");return{gateway:await this.options.resolveGateway(n),selection:n}}async execute(e,n,r){if(e!=="delegate_subagents")return{ok:!1,output:`Unknown subagent tool: ${e}`};if(r.signal?.aborted)return{ok:!1,output:"Subagent delegation cancelled."};let o=Au(n,this.options.maxParallel),s=await Promise.all(o.map(async i=>{let a=new be(this.options.rootDir,this.options.localRuntimeOptions),c=new Ke({...le,filesystem:{read:"allow",write:"deny",delete:"deny"},shell:{readOnly:"allow",mutating:"deny",destructive:"deny"},git:{read:"allow",write:"deny"},network:{search:"deny",fetch:"deny"}});try{let{gateway:l,selection:u}=await this.gatewayFor(i),d=await new Fe({gateway:l,runtime:a,permissions:c}).run({prompt:`${ii[i.role]}
|
|
151
196
|
|
|
152
197
|
Assigned task:
|
|
153
|
-
${i.task}`,mode:"plan",rootDir:this.options.rootDir,maxSteps:this.options.maxSteps,approvalHandler:async()=>!1,signal:
|
|
198
|
+
${i.task}`,mode:"plan",rootDir:this.options.rootDir,maxSteps:this.options.maxSteps??Ou,approvalHandler:async()=>!1,signal:r.signal}),p=d.answer.length>si?`${d.answer.slice(0,si)}
|
|
199
|
+
\u2026[subagent answer truncated]`:d.answer;return{role:i.role,task:i.task,ok:!0,answer:p,steps:d.steps,route:u.route,model:u.model}}catch(l){return{role:i.role,task:i.task,ok:!1,answer:l instanceof Error?l.message:String(l),steps:0,route:i.route,model:i.model}}}));return{ok:s.every(i=>i.ok),output:s.map((i,a)=>{let c=[i.route?`route=${i.route}`:void 0,i.model?`model=${i.model}`:void 0].filter(Boolean).join(", ");return[`## Subagent ${a+1}: ${i.role}${c?` (${c})`:""}`,`Task: ${i.task}`,`Status: ${i.ok?"completed":"failed"}`,i.answer].join(`
|
|
154
200
|
`)}).join(`
|
|
155
201
|
|
|
156
|
-
`),metadata:{count:s.length,successful:s.filter(i=>i.ok).length,tasks:s.map(i=>({role:i.role,ok:i.ok,...i.route?{route:i.route}:{},...i.model?{model:i.model}:{}}))}}}};import{mkdir as
|
|
157
|
-
`,{encoding:"utf8",mode:384}),i}finally{await n()}}async list(e=50){if(!Number.isInteger(e)||e<1||e>1e3)throw new Error("Audit limit must be between 1 and 1000.");return(await this.parseAll()).slice(-e).reverse()}async verify(){let e;try{e=await this.parseAll()}catch(
|
|
158
|
-
`,{encoding:"utf8",mode:384}),
|
|
159
|
-
`,{encoding:"utf8",mode:384}),await
|
|
160
|
-
`,{encoding:"utf8",mode:384}),
|
|
161
|
-
`,"utf8"),
|
|
162
|
-
`,"utf8")}};function
|
|
202
|
+
`),metadata:{count:s.length,successful:s.filter(i=>i.ok).length,tasks:s.map(i=>({role:i.role,ok:i.ok,...i.route?{route:i.route}:{},...i.model?{model:i.model}:{}}))}}}};import{mkdir as Iu,realpath as Ct,rm as Du,stat as ju}from"node:fs/promises";import ve from"node:path";import{spawn as Lu}from"node:child_process";function Mt(t,e){return new Promise((n,r)=>{let o=Lu("git",e,{cwd:t,stdio:["ignore","pipe","pipe"]}),s="",i="";o.stdout.setEncoding("utf8"),o.stderr.setEncoding("utf8"),o.stdout.on("data",a=>{s+=a}),o.stderr.on("data",a=>{i+=a}),o.once("error",r),o.once("close",a=>n({code:a??1,stdout:s,stderr:i}))})}function ai(t){let e=t.trim();if(!/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$/.test(e))throw new Error("Worktree name must use 1\u201364 letters, numbers, dots, underscores, or hyphens.");return e}async function ci(t){try{return await ju(t),!0}catch{return!1}}var $t=class{rootDir;storageDir;constructor(e){this.rootDir=ve.resolve(e),this.storageDir=ve.join(ve.dirname(this.rootDir),`.${ve.basename(this.rootDir)}-kpilot-worktrees`)}async assertRepository(){let e=await Mt(this.rootDir,["rev-parse","--show-toplevel"]);if(e.code!==0)throw new Error(e.stderr.trim()||"Not a Git repository.");let n=ve.resolve(e.stdout.trim()),r=await Ct(this.rootDir);if(n!==r)throw new Error(`Use the repository root as --cwd: ${n}`)}pathFor(e){return ve.join(this.storageDir,ai(e))}async create(e,n={}){await this.assertRepository();let r=ai(e),o=this.pathFor(r);if(await ci(o))throw new Error(`Worktree path already exists: ${o}`);await Iu(this.storageDir,{recursive:!0});let s=n.branch?.trim()||`kpilot/${r}`,i=n.base?.trim()||"HEAD",a=await Mt(this.rootDir,["worktree","add","-b",s,o,i]);if(a.code!==0)throw new Error(a.stderr.trim()||a.stdout.trim()||"Unable to create worktree.");let c=await this.list(),l=await Ct(o).catch(()=>o),u=c.find(m=>m.path===l||m.path===o);if(!u)throw new Error("Git created the worktree, but it could not be discovered afterward.");return u}async list(){await this.assertRepository();let e=await Mt(this.rootDir,["worktree","list","--porcelain"]);if(e.code!==0)throw new Error(e.stderr.trim()||"Unable to list worktrees.");let n=await Ct(this.storageDir).catch(()=>this.storageDir),r=[],o;for(let s of e.stdout.split(/\r?\n/))if(s.startsWith("worktree ")){o&&r.push(o);let i=s.slice(9),a=await Ct(i).catch(()=>i),c=ve.relative(n,a),l=c!==""&&!c.startsWith("..")&&!ve.isAbsolute(c);o={path:a,bare:!1,detached:!1,managed:l,name:l?c.split(ve.sep)[0]:void 0}}else{if(!o||!s)continue;s.startsWith("HEAD ")?o.head=s.slice(5):s.startsWith("branch ")?o.branch=s.slice(7).replace(/^refs\/heads\//,""):s==="bare"?o.bare=!0:s==="detached"?o.detached=!0:s.startsWith("locked")?o.locked=s.slice(6).trim()||"locked":s.startsWith("prunable")&&(o.prunable=s.slice(8).trim()||"prunable")}return o&&r.push(o),r}async remove(e,n=!1){await this.assertRepository();let r=this.pathFor(e),o=await Ct(r).catch(()=>r);if(!(await this.list()).find(l=>l.managed&&l.path===o))throw new Error(`Managed worktree not found: ${e}`);let a=["worktree","remove"];n&&a.push("--force"),a.push(r);let c=await Mt(this.rootDir,a);if(c.code!==0)throw new Error(c.stderr.trim()||c.stdout.trim()||"Unable to remove worktree.");await ci(r)&&await Du(r,{recursive:!0,force:!0})}async prune(){await this.assertRepository();let e=await Mt(this.rootDir,["worktree","prune"]);if(e.code!==0)throw new Error(e.stderr.trim()||"Unable to prune worktrees.")}};import{appendFile as Uu,mkdir as li,readFile as Nu,rm as ui,stat as mi}from"node:fs/promises";import{createHash as Fu,randomUUID as qu}from"node:crypto";import{hostname as Bu,userInfo as Ju}from"node:os";import wn from"node:path";function Or(t){if(Array.isArray(t))return`[${t.map(Or).join(",")}]`;if(t&&typeof t=="object"){let e=t;return`{${Object.keys(e).sort().map(n=>`${JSON.stringify(n)}:${Or(e[n])}`).join(",")}}`}return JSON.stringify(t)}function di(t){return Fu("sha256").update(Or(t)).digest("hex")}async function Ku(t){try{return await mi(t),!0}catch{return!1}}function Wu(){try{return Ju().username||"unknown"}catch{return"unknown"}}var yn=class{rootDir;filePath;lockPath;constructor(e){this.rootDir=wn.resolve(e),this.filePath=wn.join(this.rootDir,E,"audit","audit.jsonl"),this.lockPath=wn.join(this.rootDir,E,"audit",".append-lock")}async parseAll(){if(!await Ku(this.filePath))return[];let e=await Nu(this.filePath,"utf8"),n=[];for(let[r,o]of e.split(/\r?\n/).entries()){if(!o.trim())continue;let s;try{s=JSON.parse(o)}catch(i){throw new Error(`Invalid audit JSON at line ${r+1}: ${i instanceof Error?i.message:String(i)}`)}if(!s||typeof s!="object"||Array.isArray(s))throw new Error(`Invalid audit record at line ${r+1}.`);n.push(s)}return n}async acquireLock(e=5e3){await li(wn.dirname(this.lockPath),{recursive:!0});let n=Date.now();for(;;)try{return await li(this.lockPath),async()=>{await ui(this.lockPath,{recursive:!0,force:!0})}}catch(r){if(r.code!=="EEXIST")throw r;try{let s=await mi(this.lockPath);if(Date.now()-s.mtimeMs>3e4){await ui(this.lockPath,{recursive:!0,force:!0});continue}}catch{continue}if(Date.now()-n>=e)throw new Error("Timed out waiting for the audit append lock.");await new Promise(s=>setTimeout(s,25))}}async append(e){if(!e.action.trim())throw new Error("Audit action cannot be empty.");let n=await this.acquireLock();try{let o=(await this.parseAll()).at(-1)?.hash??"GENESIS",s={schemaVersion:1,id:qu(),timestamp:new Date().toISOString(),actor:e.actor?.trim()||Wu(),host:Bu(),action:e.action.trim(),outcome:e.outcome,...e.category?{category:e.category}:{},...e.sessionId?{sessionId:e.sessionId}:{},...e.details?{details:e.details}:{},previousHash:o},i={...s,hash:di(s)};return await Uu(this.filePath,`${JSON.stringify(i)}
|
|
203
|
+
`,{encoding:"utf8",mode:384}),i}finally{await n()}}async list(e=50){if(!Number.isInteger(e)||e<1||e>1e3)throw new Error("Audit limit must be between 1 and 1000.");return(await this.parseAll()).slice(-e).reverse()}async verify(){let e;try{e=await this.parseAll()}catch(r){return{valid:!1,records:0,firstInvalidLine:1,reason:r instanceof Error?r.message:String(r),headHash:"GENESIS"}}let n="GENESIS";for(let[r,o]of e.entries()){if(o.schemaVersion!==1)return{valid:!1,records:e.length,firstInvalidLine:r+1,reason:"Unsupported audit schema.",headHash:n};if(o.previousHash!==n)return{valid:!1,records:e.length,firstInvalidLine:r+1,reason:"Previous hash mismatch.",headHash:n};let{hash:s,...i}=o,a=di(i);if(s!==a)return{valid:!1,records:e.length,firstInvalidLine:r+1,reason:"Record hash mismatch.",headHash:n};n=s}return{valid:!0,records:e.length,headHash:n}}};import{appendFile as Gu,mkdir as Hu,readFile as zu,stat as Vu}from"node:fs/promises";import{randomUUID as Yu}from"node:crypto";import Ir from"node:path";async function Qu(t){try{return await Vu(t),!0}catch{return!1}}function bn(t,e){if(t!==void 0){if(!Number.isInteger(t)||t<0)throw new Error(`${e} must be a non-negative integer.`);return t}}function Xu(t){let e={dailyInputTokens:bn(t.dailyInputTokens,"dailyInputTokens"),dailyOutputTokens:bn(t.dailyOutputTokens,"dailyOutputTokens"),dailyTotalTokens:bn(t.dailyTotalTokens,"dailyTotalTokens"),perRunTotalTokens:bn(t.perRunTotalTokens,"perRunTotalTokens"),dailyEstimatedCostUsd:t.dailyEstimatedCostUsd,warnAtPercent:t.warnAtPercent??80};if(e.dailyEstimatedCostUsd!==void 0&&(!Number.isFinite(e.dailyEstimatedCostUsd)||e.dailyEstimatedCostUsd<0))throw new Error("dailyEstimatedCostUsd must be a non-negative number.");if(!Number.isFinite(e.warnAtPercent)||e.warnAtPercent<1||e.warnAtPercent>100)throw new Error("warnAtPercent must be between 1 and 100.");return e}var vn=class{rootDir;filePath;constructor(e){this.rootDir=Ir.resolve(e),this.filePath=Ir.join(this.rootDir,E,"usage","usage.jsonl")}async records(){return await Qu(this.filePath)?(await zu(this.filePath,"utf8")).split(/\r?\n/).filter(Boolean).map((n,r)=>{try{return JSON.parse(n)}catch(o){throw new Error(`Invalid usage JSON at line ${r+1}: ${o instanceof Error?o.message:String(o)}`)}}):[]}async record(e){let n=Math.max(0,Math.trunc(e.inputTokens??0)),r=Math.max(0,Math.trunc(e.outputTokens??0)),o=Math.max(0,Math.trunc(e.cacheReadTokens??0)),s=Math.max(0,Math.trunc(e.cacheWriteTokens??0)),i=e.price?.cacheReadPerMillionUsd??e.price?.inputPerMillionUsd??0,a=e.price?.cacheWritePerMillionUsd??e.price?.inputPerMillionUsd??0,c=n/1e6*(e.price?.inputPerMillionUsd??0)+o/1e6*i+s/1e6*a+r/1e6*(e.price?.outputPerMillionUsd??0),l={schemaVersion:1,id:Yu(),timestamp:new Date().toISOString(),...e.sessionId?{sessionId:e.sessionId}:{},model:e.model,inputTokens:n,outputTokens:r,...o>0?{cacheReadTokens:o}:{},...s>0?{cacheWriteTokens:s}:{},totalTokens:n+r+o+s,estimatedCostUsd:Number(c.toFixed(8))};return await Hu(Ir.dirname(this.filePath),{recursive:!0}),await Gu(this.filePath,`${JSON.stringify(l)}
|
|
204
|
+
`,{encoding:"utf8",mode:384}),l}async summarize(e=new Date().toISOString().slice(0,10)){return(await this.records()).filter(r=>r.timestamp.slice(0,10)===e).reduce((r,o)=>({date:e,inputTokens:r.inputTokens+o.inputTokens,outputTokens:r.outputTokens+o.outputTokens,cacheReadTokens:r.cacheReadTokens+(o.cacheReadTokens??0),cacheWriteTokens:r.cacheWriteTokens+(o.cacheWriteTokens??0),totalTokens:r.totalTokens+o.totalTokens,estimatedCostUsd:Number((r.estimatedCostUsd+o.estimatedCostUsd).toFixed(8)),runs:r.runs+1}),{date:e,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,totalTokens:0,estimatedCostUsd:0,runs:0})}async list(e=50){if(!Number.isInteger(e)||e<1||e>1e3)throw new Error("Usage limit must be between 1 and 1000.");return(await this.records()).slice(-e).reverse()}async check(e,n=0){let r=Xu(e),o=await this.summarize(),s=[],i=[],a=[["daily input tokens",o.inputTokens,r.dailyInputTokens],["daily output tokens",o.outputTokens,r.dailyOutputTokens],["daily total tokens",o.totalTokens+n,r.dailyTotalTokens],["daily estimated cost",o.estimatedCostUsd,r.dailyEstimatedCostUsd]];for(let[c,l,u]of a)u===void 0||u===0||(l>=u?s.push(`${c} limit reached (${l}/${u}).`):l/u*100>=r.warnAtPercent&&i.push(`${c} is at ${Math.round(l/u*100)}% (${l}/${u}).`));return r.perRunTotalTokens&&n>r.perRunTotalTokens&&s.push(`per-run token limit exceeded (${n}/${r.perRunTotalTokens}).`),{allowed:s.length===0,warnings:i,violations:s,summary:o}}};import{chmod as Zu,mkdir as ed,readFile as td,rename as nd,rm as rd,writeFile as od}from"node:fs/promises";import{homedir as sd,hostname as id}from"node:os";import Dr from"node:path";var _t=class extends Error{status;code;constructor(e,n,r){super(e),this.name="ControlPlaneError",this.status=n,this.code=r}};function ad(t){let e=new URL(t);if(e.protocol!=="https:"&&e.hostname!=="localhost"&&e.hostname!=="127.0.0.1")throw new Error("Control-plane URL must use HTTPS outside localhost.");return t.replace(/\/+$/,"")}var ue=class{baseUrl;userAgent;constructor(e="https://api.konsolepilot.ai",n="kpilot CLI"){this.baseUrl=ad(e),this.userAgent=n}async request(e,n={}){let r=await fetch(`${this.baseUrl}${e}`,{method:n.method??(n.body===void 0?"GET":"POST"),headers:{accept:"application/json","content-type":"application/json","user-agent":this.userAgent,...n.accessToken?{authorization:`Bearer ${n.accessToken}`}:{}},...n.body===void 0?{}:{body:JSON.stringify(n.body)},...n.signal?{signal:n.signal}:{}}),o=await r.text(),s={};if(o)try{s=JSON.parse(o)}catch{s={message:o}}if(!r.ok)throw new _t(s.message??`Control plane returned HTTP ${r.status}.`,r.status,s.code);return s}createDeviceCode(e={}){return this.request("/v1/device/code",{body:{client_name:"kpilot CLI",device_name:e.deviceName??id(),platform:e.platform??process.platform},signal:e.signal})}async pollDeviceToken(e,n={}){let r=Date.now(),o=n.expiresInSeconds??600,s=Math.max(1,n.intervalSeconds??5),i=0;for(;(Date.now()-r)/1e3<o;){if(n.signal?.aborted)throw n.signal.reason??new Error("Login cancelled.");i+=1;try{return await this.request("/v1/device/token",{body:{device_code:e},signal:n.signal})}catch(a){if(!(a instanceof _t))throw a;if(a.code==="authorization_pending")n.onPending?.(i);else if(a.code==="slow_down")s+=2;else throw a}await new Promise((a,c)=>{let l=setTimeout(()=>a(),s*1e3);n.signal?.addEventListener("abort",()=>{clearTimeout(l),c(n.signal?.reason??new Error("Login cancelled."))},{once:!0})})}throw new Error("Device authorization expired. Run `kpilot login` again.")}profile(e){return this.request("/v1/me",{accessToken:e})}refresh(e){return this.request("/v1/auth/refresh",{body:{refresh_token:e}})}logout(e){return this.request("/v1/auth/logout",{body:{refresh_token:e}})}catalog(e){return this.request("/v1/ai/models",{accessToken:e})}ingestUsage(e,n){return this.request("/v1/usage/events",{body:{events:n},accessToken:e})}checkBudget(e,n=0){return this.request("/v1/usage/preflight",{body:{projectedTokens:n},accessToken:e})}},ie=class{filePath;constructor(e=Dr.join(sd(),".config","kpilot","cloud-auth.json")){this.filePath=Dr.resolve(e)}async load(){try{let e=JSON.parse(await td(this.filePath,"utf8"));if(!e.accessToken||!e.refreshToken||!e.controlPlaneUrl)throw new Error("Cloud credential file is incomplete.");return e}catch(e){if(e?.code==="ENOENT")return;throw e}}async save(e){await ed(Dr.dirname(this.filePath),{recursive:!0,mode:448});let n=`${this.filePath}.${process.pid??"tmp"}.tmp`;await od(n,`${JSON.stringify(e,null,2)}
|
|
205
|
+
`,{encoding:"utf8",mode:384}),await nd(n,this.filePath),await Zu(this.filePath,384)}async clear(){try{await rd(this.filePath,{force:!0})}catch(e){if(e?.code!=="ENOENT")throw e}}async validAccessToken(e){let n=await this.load();if(!n)return;let r=e??new ue(n.controlPlaneUrl);if(new Date(n.expiresAt).getTime()>Date.now()+3e4)return{tokens:n,client:r};try{let o=await r.refresh(n.refreshToken);return await this.save(o),{tokens:o,client:r}}catch(o){throw o instanceof _t&&o.status>=400&&o.status<500?(await this.clear(),new Error("Your kpilot session has expired or was revoked. Run `kpilot login` to sign in again.")):o}}};import{lstat as cd,mkdir as pi,readFile as jr,readdir as ld,stat as yi,writeFile as fi}from"node:fs/promises";import{createCipheriv as ud,createDecipheriv as dd,randomBytes as gi,scryptSync as md}from"node:crypto";import ee from"node:path";var pd=[`${E}/instructions.md`,`${E}/memory.json`,`${E}/preferences.json`,`${E}/team-policy.json`,`${E}/skills`];async function kn(t){try{return await yi(t),!0}catch{return!1}}async function Lr(t,e,n){let r=ee.join(t,e);if(!await kn(r))return;let o=await ld(r,{withFileTypes:!0});for(let s of o){let i=ee.posix.join(e.replaceAll("\\","/"),s.name);if(s.isDirectory())await Lr(t,i,n);else if(s.isFile()){let a=await jr(ee.join(t,i));n.push({path:i,contentBase64:a.toString("base64")})}}}function fd(t){let e=t.replaceAll("\\","/");if(e.startsWith(".konsolepilot/")&&(e=`${E}/${e.slice(14)}`),!e.startsWith(`${E}/`)||e.includes("../")||ee.isAbsolute(e))throw new Error(`Unsafe bundle path: ${t}`);return e}async function gd(t,e){let n=e.split("/").filter(Boolean),r=t;for(let o of n.slice(0,-1)){if(r=ee.join(r,o),!await kn(r))continue;if((await cd(r)).isSymbolicLink())throw new Error(`Refusing to import through symbolic link: ${ee.relative(t,r)}`)}}function hi(t){return Buffer.from(JSON.stringify({schemaVersion:t.schemaVersion,format:t.format,createdAt:t.createdAt,projectName:t.projectName,includeSessions:t.includeSessions,algorithm:t.encryption.algorithm,kdf:t.encryption.kdf,salt:t.encryption.salt,iv:t.encryption.iv}),"utf8")}function wi(t,e){if(t.length<12)throw new Error("Sync passphrase must contain at least 12 characters.");return md(t,e,32,{N:32768,r:8,p:1,maxmem:64*1024*1024})}var xn=class{rootDir;constructor(e){this.rootDir=ee.resolve(e)}async exportBundle(e,n,r=!1){let o=[];for(let y of pd){let S=ee.join(this.rootDir,y);if(!await kn(S))continue;(await yi(S)).isDirectory()?await Lr(this.rootDir,y,o):o.push({path:y,contentBase64:(await jr(S)).toString("base64")})}r&&await Lr(this.rootDir,`${E}/sessions`,o),o.sort((y,S)=>y.path.localeCompare(S.path));let s={schemaVersion:1,files:o},i=gi(16),a=gi(12),c=wi(n,i),l={schemaVersion:1,format:"kpilot-encrypted-sync",createdAt:new Date().toISOString(),projectName:ee.basename(this.rootDir),includeSessions:r,encryption:{algorithm:"aes-256-gcm",kdf:"scrypt",salt:i.toString("base64"),iv:a.toString("base64"),tag:""}},u=ud("aes-256-gcm",c,a);u.setAAD(hi(l));let m=Buffer.concat([u.update(JSON.stringify(s),"utf8"),u.final()]),d={...l,encryption:{...l.encryption,tag:u.getAuthTag().toString("base64")},ciphertext:m.toString("base64")},p=ee.resolve(e);return await pi(ee.dirname(p),{recursive:!0}),await fi(p,`${JSON.stringify(d,null,2)}
|
|
206
|
+
`,{encoding:"utf8",mode:384}),d}async inspectBundle(e){let n=await this.readEnvelope(e),{ciphertext:r,...o}=n;return o}async importBundle(e,n,r=!1){let o=await this.readEnvelope(e),s=Buffer.from(o.encryption.salt,"base64"),i=Buffer.from(o.encryption.iv,"base64"),a=Buffer.from(o.encryption.tag,"base64"),c=wi(n,s),l;try{let p=dd("aes-256-gcm",c,i);p.setAuthTag(a);let{ciphertext:y,...S}=o;p.setAAD(hi(S)),l=Buffer.concat([p.update(Buffer.from(o.ciphertext,"base64")),p.final()])}catch{throw new Error("Unable to decrypt sync bundle. The passphrase is incorrect or the bundle was modified.")}let u;try{u=JSON.parse(l.toString("utf8"))}catch{throw new Error("Decrypted sync bundle payload is invalid JSON.")}if(u.schemaVersion!==1||!Array.isArray(u.files))throw new Error("Unsupported sync payload schema.");let m=[],d=[];for(let p of u.files){let y=fd(p.path),S=ee.join(this.rootDir,y);if(await gd(this.rootDir,y),!r&&await kn(S)){d.push(y);continue}await pi(ee.dirname(S),{recursive:!0}),await fi(S,Buffer.from(p.contentBase64,"base64"),{mode:384}),m.push(y)}return{imported:m,skipped:d}}async readEnvelope(e){let n;try{n=JSON.parse(await jr(ee.resolve(e),"utf8"))}catch(o){throw new Error(`Invalid sync bundle: ${o instanceof Error?o.message:String(o)}`)}if(!n||typeof n!="object"||Array.isArray(n))throw new Error("Sync bundle must be a JSON object.");let r=n;if(r.schemaVersion!==1||r.format!=="kpilot-encrypted-sync")throw new Error("Unsupported sync bundle format.");if(r.encryption?.algorithm!=="aes-256-gcm"||r.encryption?.kdf!=="scrypt")throw new Error("Unsupported sync bundle encryption.");return r}};import{mkdir as bi,readFile as hd,stat as wd,writeFile as vi}from"node:fs/promises";import Sn from"node:path";async function ki(t){try{return await wd(t),!0}catch{return!1}}function xi(t){let e=[],n=[];t.schemaVersion!==1&&e.push("schemaVersion must be 1."),t.maximumSteps!==void 0&&(!Number.isInteger(t.maximumSteps)||t.maximumSteps<1||t.maximumSteps>50)&&e.push("maximumSteps must be an integer between 1 and 50."),t.allowedModels&&((!Array.isArray(t.allowedModels)||t.allowedModels.some(o=>typeof o!="string"||!o.trim()))&&e.push("allowedModels must contain non-empty strings."),t.allowedModels.length===0&&n.push("allowedModels is empty; no model can run.")),t.allowedMcpServers?.some(o=>typeof o!="string"||!o.trim())&&e.push("allowedMcpServers must contain non-empty strings.");let r=new Set(["allow","ask","deny"]);for(let[o,s]of Object.entries(t.permissions??{}))for(let[i,a]of Object.entries(s??{}))r.has(a)||e.push(`permissions.${o}.${i} must be allow, ask, or deny.`);return{valid:e.length===0,errors:e,warnings:n}}var je=class{rootDir;filePath;constructor(e){this.rootDir=Sn.resolve(e),this.filePath=Sn.join(this.rootDir,E,"team-policy.json")}async load(){if(!await ki(this.filePath))return;let e;try{e=JSON.parse(await hd(this.filePath,"utf8"))}catch(o){throw new Error(`Invalid team policy JSON: ${o instanceof Error?o.message:String(o)}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Error("Team policy must be a JSON object.");let n=e,r=xi(n);if(!r.valid)throw new Error(`Invalid team policy: ${r.errors.join(" ")}`);return n}async initialize(e,n=[]){if(await ki(this.filePath))throw new Error(`${E}/team-policy.json already exists.`);let r={schemaVersion:1,...e?.trim()?{organization:e.trim()}:{},allowedModels:[...new Set(n.map(o=>o.trim()).filter(Boolean))],allowWriteMode:!0,requireSandbox:!0,requireNetworkIsolation:!0,allowedMcpServers:[],permissions:{}};return await bi(Sn.dirname(this.filePath),{recursive:!0}),await vi(this.filePath,`${JSON.stringify(r,null,2)}
|
|
207
|
+
`,"utf8"),r}async save(e){let n=xi(e);if(!n.valid)throw new Error(`Invalid team policy: ${n.errors.join(" ")}`);await bi(Sn.dirname(this.filePath),{recursive:!0}),await vi(this.filePath,`${JSON.stringify(e,null,2)}
|
|
208
|
+
`,"utf8")}};function Ti(t){let e=t.policy;if(e){if(t.mode==="write"&&e.allowWriteMode===!1)throw new Error("Team policy denies WRITE mode.");if(e.allowedModels&&!e.allowedModels.includes(t.model))throw new Error(`Model "${t.model}" is not allowed by team policy.`);if(e.maximumSteps!==void 0&&t.maxSteps!==void 0&&t.maxSteps>e.maximumSteps)throw new Error(`Requested max steps (${t.maxSteps}) exceeds team policy (${e.maximumSteps}).`);if(e.requireSandbox&&t.sandboxMode==="none")throw new Error("Team policy requires a command sandbox.");if(e.requireNetworkIsolation&&t.allowNetwork)throw new Error("Team policy requires sandbox network isolation.")}}var Si={allow:0,ask:1,deny:2};function Tn(t,e){return e&&Si[e]>Si[t]?e:t}function Pi(t,e){return e?{...t,search:Tn(t.search,"deny"),fetch:Tn(t.fetch,"deny")}:t}import{mkdir as En,readFile as Ve,readdir as yd,rename as bd,writeFile as Nr,chmod as vd,unlink as Ci,stat as Mi}from"node:fs/promises";import z from"node:path";var Pn=".kpilot",kd="logbook",xd="project.md",Sd="learnings.md",Td="meta.json",Pd=220,Ed=12e3,Ei=3,Ur={project:z.join(Pn,"understanding.md"),learnings:z.join(Pn,"learnings.md"),meta:z.join(Pn,"meta.json")},Rn=`Write the project's Logbook entry (.kpilot/logbook/project.md). Keep the tool chain tiny for small-context models (~8k context).
|
|
163
209
|
|
|
164
210
|
Allowed steps only:
|
|
165
211
|
1. workspace_summary once
|
|
@@ -169,8 +215,8 @@ Allowed steps only:
|
|
|
169
215
|
5. write_file .kpilot/logbook/project.md using content_b64 (preferred) or a short content string
|
|
170
216
|
|
|
171
217
|
Do NOT list deep trees or read more files. Brief: purpose, stack, layout, run/test commands, gotchas. Max ~60 lines of markdown.
|
|
172
|
-
When done, one short confirmation sentence.`;async function
|
|
173
|
-
`).trim()}catch{}let a="";try{let l=JSON.parse(await
|
|
218
|
+
When done, one short confirmation sentence.`;async function Fr(t){let e=z.resolve(t),n=await yd(e).catch(()=>[]),r=[];for(let l of n.slice(0,60))if(!(l===".git"||l==="node_modules"||l==="dist"))try{let u=await Mi(z.join(e,l));r.push(`${u.isDirectory()?"dir":"file"} ${l}`)}catch{r.push(`file ${l}`)}let s=["package.json","pnpm-workspace.yaml","package-lock.json","yarn.lock","Cargo.toml","go.mod","pyproject.toml","composer.json"].filter(l=>n.includes(l)),i="";try{i=(await Ve(z.join(e,"README.md"),"utf8")).split(/\r?\n/).slice(0,50).join(`
|
|
219
|
+
`).trim()}catch{}let a="";try{let l=JSON.parse(await Ve(z.join(e,"package.json"),"utf8")),u=l.scripts?Object.keys(l.scripts).slice(0,12).map(m=>`- \`${m}\`: \`${l.scripts[m]}\``).join(`
|
|
174
220
|
`):"_none_";a=[l.name?`- name: \`${l.name}\``:"",l.description?`- description: ${l.description}`:"",l.packageManager?`- packageManager: \`${l.packageManager}\``:"","- scripts:",u].filter(Boolean).join(`
|
|
175
221
|
`)}catch{}let c=`# Project Logbook
|
|
176
222
|
|
|
@@ -190,7 +236,7 @@ ${a}
|
|
|
190
236
|
`:""}
|
|
191
237
|
## Top-level layout
|
|
192
238
|
\`\`\`
|
|
193
|
-
${
|
|
239
|
+
${r.join(`
|
|
194
240
|
`)||"[empty]"}
|
|
195
241
|
\`\`\`
|
|
196
242
|
|
|
@@ -201,18 +247,18 @@ See \`package.json\` scripts above (or README). Prefer the repo's documented pac
|
|
|
201
247
|
- Keep secrets out of git (\`.env\`).
|
|
202
248
|
- Prefer small, permission-gated edits.
|
|
203
249
|
- This lite entry may be incomplete on large monorepos \u2014 re-run \`/logbook\` with more context when possible.
|
|
204
|
-
`;return
|
|
205
|
-
`,{encoding:"utf8",mode:384}),await
|
|
250
|
+
`;return Md(e,c)}function qr(t){let e=t instanceof Error?t.message:String(t);return/exceeds the available context size|context.?length|context.?window|too many tokens|maximum context/i.test(e)}function Rd(t){return z.join(z.resolve(t),Pn)}function Le(t){return z.join(Rd(t),kd)}function Ye(t){return z.join(Le(t),xd)}async function $i(t,e=7){try{let n=await Mi(Ye(t));return Date.now()-n.mtimeMs>e*24*60*60*1e3}catch{return!1}}function Br(t){return z.join(Le(t),Sd)}function Cn(t){return z.join(Le(t),Td)}async function Ri(t){try{return await Ve(t),!0}catch{return!1}}async function Qe(t){let e=z.resolve(t),n=Le(e);await En(n,{recursive:!0,mode:493});let r=[[z.join(e,Ur.project),Ye(e)],[z.join(e,Ur.learnings),Br(e)],[z.join(e,Ur.meta),Cn(e)]];for(let[o,s]of r)if(await Ri(o)){if(await Ri(s)){try{await Ci(o)}catch{}continue}try{await bd(o,s)}catch{}}}async function Cd(t){try{return JSON.parse(await Ve(t,"utf8"))}catch{return{}}}async function At(t){await Qe(t);let e=await Cd(Cn(t)),n=typeof e.projectCapturedAt=="string"?e.projectCapturedAt:typeof e.understoodAt=="string"?e.understoodAt:void 0;return{schemaVersion:1,updatedAt:typeof e.updatedAt=="string"?e.updatedAt:new Date(0).toISOString(),declined:e.declined===!0,projectCapturedAt:n,learningEnabled:e.learningEnabled===!0,learningOffered:e.learningOffered===!0,lastLearnedAt:typeof e.lastLearnedAt=="string"?e.lastLearnedAt:void 0}}async function Ot(t,e){await Qe(t);let n=await At(t),r={schemaVersion:1,updatedAt:new Date().toISOString()};(e.declined!==void 0?e.declined:n.declined)&&(r.declined=!0);let s=e.projectCapturedAt!==void 0?e.projectCapturedAt:n.projectCapturedAt;s&&(r.projectCapturedAt=s),(e.learningEnabled!==void 0?e.learningEnabled:n.learningEnabled)&&(r.learningEnabled=!0),(e.learningOffered!==void 0?e.learningOffered:n.learningOffered)&&(r.learningOffered=!0);let c=e.lastLearnedAt!==void 0?e.lastLearnedAt:n.lastLearnedAt;c&&(r.lastLearnedAt=c);let l=Le(t);await En(l,{recursive:!0,mode:448});let u=Cn(t);await Nr(u,`${JSON.stringify(r,null,2)}
|
|
251
|
+
`,{encoding:"utf8",mode:384}),await vd(u,384)}async function Xe(t){await Qe(t);try{return(await Ve(Ye(t),"utf8")).trim().length>0}catch{return!1}}async function Md(t,e){await Qe(t);let n=Le(t);await En(n,{recursive:!0,mode:493});let r=Ye(t),o=e.trim().endsWith(`
|
|
206
252
|
`)?e.trimStart():`${e.trim()}
|
|
207
|
-
`;return await
|
|
208
|
-
`)}async function
|
|
253
|
+
`;return await Nr(r,o,{encoding:"utf8",mode:420}),await Ot(t,{projectCapturedAt:new Date().toISOString(),declined:!1}),r}async function Jr(t){await Ot(t,{declined:!0})}async function Kr(t){let e=await At(t);if(!e.declined&&!e.projectCapturedAt&&!e.learningEnabled&&!e.learningOffered&&!e.lastLearnedAt){try{await Ci(Cn(t))}catch{}return}await Ot(t,{declined:!1})}async function _i(t){return await Xe(t)?!1:!(await At(t)).declined}async function It(t){return(await At(t)).learningEnabled===!0}async function Ai(t){let e=await Xe(t),n=await It(t);return e&&!n?"":e?"Logbook: learning on \xB7 /learn off":"Logbook: no project entry \xB7 /logbook to capture"}async function Dt(t,e){await Ot(t,{learningEnabled:e,learningOffered:!0})}async function Oi(t){let e=await At(t);return!(e.learningEnabled||e.learningOffered)}function Wr(t){return t.replace(/\s+/g," ").trim().replace(/^[-*•]\s*/,"").slice(0,Pd)}function $d(t){let e=[];for(let n of t.split(/\r?\n/)){let r=/^\s*[-*]\s+(.+)$/.exec(n);if(!r?.[1])continue;let o=Wr(r[1]);o&&e.push(o)}return e}async function Ii(t){await Qe(t);try{let e=await Ve(Br(t),"utf8");return $d(e)}catch{return[]}}async function Gr(t,e=8e3){let n=await Ii(t);if(!n.length)return"";let r=[],o=0;for(let s of n){let i=`- ${s}`;if(o+i.length+1>e)break;r.push(i),o+=i.length+1}return r.join(`
|
|
254
|
+
`)}async function _d(t,e){await Qe(t);let n=e.map(Wr).filter(Boolean);if(!n.length)return[];let r=await Ii(t),o=new Set(r.map(l=>l.toLowerCase())),s=[];for(let l of n){let u=l.toLowerCase();o.has(u)||(o.add(u),r.push(l),s.push(l))}if(!s.length)return[];let i=r,a=`${i.map(l=>`- ${l}`).join(`
|
|
209
255
|
`)}
|
|
210
|
-
`;for(;a.length>
|
|
256
|
+
`;for(;a.length>Ed&&i.length>1;)i=i.slice(1),a=`${i.map(l=>`- ${l}`).join(`
|
|
211
257
|
`)}
|
|
212
|
-
`;let c=
|
|
258
|
+
`;let c=Le(t);return await En(c,{recursive:!0,mode:493}),await Nr(Br(t),`# Logbook learnings
|
|
213
259
|
|
|
214
|
-
${a}`,{encoding:"utf8",mode:420}),await
|
|
215
|
-
`,{mode:384})}catch{}}}function
|
|
260
|
+
${a}`,{encoding:"utf8",mode:420}),await Ot(t,{lastLearnedAt:new Date().toISOString()}),s}function Ad(t){let e=[],n=t.prompt.trim();if(!n||n===Rn)return[];let r=s=>{if(!s)return;let i=Wr(s);!i||i.length<8||e.some(a=>a.toLowerCase()===i.toLowerCase())||e.length>=Ei||e.push(i)},o=[/\b(?:please\s+)?remember(?:\s+that)?\s+(.+)$/im,/\b(?:from now on|going forward)[,:]?\s+(.+)$/im,/\balways\s+(.+)$/im,/\bnever\s+(.+)$/im,/\b(?:prefer|use)\s+(.+?)(?:\s+instead\b|\s+for\b|\.|$)/im,/\bdon'?t\s+(.+)$/im,/\bdo not\s+(.+)$/im,/\bnote that\s+(.+)$/im,/\bin this (?:repo|project|codebase)[,:]?\s+(.+)$/im];for(let s of o){let i=s.exec(n);i?.[1]&&r(i[1])}if(t.changed&&t.diffAfter){let s=t.diffAfter;/\bpnpm-lock\.yaml\b/.test(s)||/\bpnpm-workspace\.yaml\b/.test(s)?r("Use pnpm for installs and scripts in this repository."):/\bpackage-lock\.json\b/.test(s)?r("Use npm for installs and scripts in this repository."):/\byarn\.lock\b/.test(s)?r("Use yarn for installs and scripts in this repository."):/\bbun\.lockb?\b/.test(s)&&r("Use bun for installs and scripts in this repository."),/\.spec\.(ts|tsx|js|jsx)\b/.test(s)&&!/\.test\.(ts|tsx|js|jsx)\b/.test(s)?r("Tests in this repository often use *.spec.* filenames."):/\.test\.(ts|tsx|js|jsx)\b/.test(s)&&!/\.spec\.(ts|tsx|js|jsx)\b/.test(s)&&r("Tests in this repository often use *.test.* filenames.")}return e.slice(0,Ei)}async function Di(t){if(!await It(t.rootDir))return[];if(t.prompt.trim()===Rn)return[];let e=Ad(t);return e.length?_d(t.rootDir,e):[]}function ji(t){let e=t.replace(/\\/g,"/");return e===".kpilot"||e.startsWith(".kpilot/")||e.includes("/.kpilot/")}var V="0.10.45",Hr=[26,0,0];function Ld(){let t=process.version.replace(/^v/,"").split(".").slice(0,3).map(Number);if(!Hr.every((n,r)=>{for(let o=0;o<r;o+=1)if((t[o]??0)!==Hr[o])return!0;return(t[r]??0)>=n})&&process.env.KPILOT_ALLOW_UNSUPPORTED_NODE!=="1")throw new Error(`kpilot requires Node.js ${Hr.join(".")} or newer; detected ${process.version}.`)}var D={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m"},Lt=[{name:"help",usage:"/help",description:"Show slash commands"},{name:"mode",usage:"/mode plan|write",description:"Change mode without deleting history",choices:[{value:"plan",label:"plan",description:"Inspect and reason only"},{value:"write",label:"write",description:"Allow file and command changes"}]},{name:"status",usage:"/status",description:"Show Git status"},{name:"diff",usage:"/diff",description:"Show Git diff"},{name:"clear",usage:"/clear",description:"Clear current conversation history"},{name:"undo",usage:"/undo",description:"Revert file changes from the last run"},{name:"compact",usage:"/compact",description:"Summarize history to free context"},{name:"cost",usage:"/cost",description:"Show this session\u2019s token usage and estimated cost"},{name:"context",usage:"/context",description:"Show conversation size and context fill"},{name:"checkpoint",usage:"/checkpoint [save|restore|list] [id]",description:"Snapshot or restore conversation state"},{name:"save",usage:"/save",description:"Persist the current session"},{name:"sessions",usage:"/sessions",description:"Switch session (selectable list)"},{name:"resume",usage:"/resume [id]",description:"Switch session by id or picker"},{name:"new",usage:"/new [title]",description:"Start a new session"},{name:"logbook",usage:"/logbook [skip]",description:"Build or refresh .kpilot/logbook/project.md",aliases:["understand"],choices:[{value:"capture",label:"capture",description:"Inspect repo and write project.md",default:!0},{value:"skip",label:"skip",description:"Do not auto-offer Logbook again"}]},{name:"learn",usage:"/learn [on|off|status]",description:"Continuous Logbook learning",choices:[{value:"status",label:"status",description:"Show learning state and facts",default:!0},{value:"on",label:"on",description:"Enable continuous learning"},{value:"off",label:"off",description:"Disable continuous learning"}]},{name:"memory",usage:"/memory",description:"List project memory"},{name:"todo",usage:"/todo [add|done|remove|clear] [text|id]",description:"Track project todos"},{name:"remember",usage:"/remember <text>",description:"Add persistent project memory",needsArgs:!0,argPrompt:"Memory text \u203A "},{name:"forget",usage:"/forget <id>",description:"Remove a memory entry",needsArgs:!0,argPrompt:"Memory id \u203A "},{name:"skills",usage:"/skills",description:"List reusable skills"},{name:"skill",usage:"/skill <name> [args]",description:"Run a skill",needsArgs:!0,argPrompt:"Skill name [args] \u203A "},{name:"preferences",usage:"/preferences",description:"List learned preferences"},{name:"feedback",usage:"/feedback <outcome> [note]",description:"Record accepted, rejected, or edited feedback",choices:[{value:"accepted",label:"accepted",description:"Mark last run accepted"},{value:"rejected",label:"rejected",description:"Mark last run rejected"},{value:"edited",label:"edited",description:"Mark last run edited"}]},{name:"models",usage:"/models",description:"Show active models and select one",aliases:["model"]},{name:"agent",usage:"/agent",description:"Show external agent configuration"},{name:"mcp",usage:"/mcp",description:"List connected MCP tools"},{name:"worktrees",usage:"/worktrees",description:"List Git worktrees"},{name:"policy",usage:"/policy",description:"Show team policy"},{name:"usage",usage:"/usage",description:"Show usage summary"},{name:"audit",usage:"/audit",description:"Verify audit chain"},{name:"admin",usage:"/admin",description:"Show admin/control-plane status"},{name:"exit",usage:"/exit",description:"End session (also: exit, quit)",aliases:["quit"]}],Hi=new Set(Lt.flatMap(t=>[t.name,...t.aliases??[]]));function Ud(t){if(!t.startsWith("/")||t==="/")return!1;let[e="",...n]=t.slice(1).split(/\s+/);return!e||n.length>0?!1:!Hi.has(e)}function U(t,e){return process.stdout.isTTY?`${t}${e}${D.reset}`:e}function de(t){if(!Number.isFinite(t)||t<1e3)return String(Math.round(t));let e=["K","M","B","T"],n=Math.min(Math.floor(Math.log10(t)/3),e.length),r=t/10**(n*3),o=r>=100?0:r>=10?1:2;return`${r.toFixed(o)}${e[n-1]}`}function zi(t){if(t)return{pause:()=>{t.closed||t.pause()},resume:()=>{t.closed||t.resume()}}}function Nd(){console.log(U(D.bold,"Slash commands")),console.log(U(D.dim,"Type / to list commands as you type \u2014 \u2191/\u2193 to move, Enter to run."));for(let t of Lt)console.log(` ${U(D.cyan,t.usage.padEnd(28))} ${t.description}`);console.log(` ${U(D.cyan,"/<skill-name> [args]".padEnd(28))} Run a skill directly`)}function Li(t=[]){let e=t.map(n=>({name:n,usage:`/${n}`,description:`Run skill \u201C${n}\u201D`}));return[...Lt.map(n=>({name:n.name,usage:n.usage,description:n.description,aliases:n.aliases})),...e]}async function Fd(t){let e=(t.skillNames??[]).map(s=>({name:s,usage:`/${s}`,description:`Run skill \u201C${s}\u201D`})),n=[...Lt,...e],r=await Q({title:"Select a command:",question:t.question,pauseResume:t.pauseResume,typeahead:!0,initialQuery:t.initialQuery??"",choices:n.map(s=>({value:s.name,label:s.usage,description:s.description,aliases:s.aliases}))});if(!r)return null;let o=n.find(s=>s.name===r);if(!o)return null;if(o.choices&&o.choices.length>0){let s=await Q({title:`${o.usage} \u2014 choose an action:`,question:t.question,pauseResume:t.pauseResume,choices:o.choices});if(!s)return $("Cancelled."),null;if(o.name==="logbook"&&s==="capture")return"/logbook";if(o.name==="feedback"){let i=(await t.question("Optional note \u203A ")).trim();return i?`/feedback ${s} ${i}`:`/feedback ${s}`}return`/${o.name} ${s}`}if(o.needsArgs){let s=(await t.question(o.argPrompt??"Args \u203A ")).trim();return s?`/${o.name} ${s}`:($("Cancelled."),null)}return`/${o.name}`}function $(t){console.log(`${U(D.cyan,"\u25C6")} ${t}`)}function T(t){console.log(`${U(D.green,"\u2713")} ${t}`)}function A(t){console.log(`${U(D.yellow,"!")} ${t}`)}function J(t){console.error(`${U(D.red,"\u2717")} ${t}`)}function qd(){return L.join(Ki(),".config","kpilot","installed-version")}function Bd(t,e){let n=s=>s.split(".").map(i=>Number(i)||0),r=n(t),o=n(e);for(let s=0;s<3;s+=1)if((r[s]??0)!==(o[s]??0))return(r[s]??0)<(o[s]??0)?-1:1;return 0}async function Jd(){if(process.env.KPILOT_SILENT_VERSION_NOTICE==="1")return;let t=qd(),e;try{e=(await eo(t,"utf8")).trim()||void 0}catch{e=void 0}if(e!==V){if(e){let n=Bd(e,V)<0?"Updated":"Changed";$(`kpilot CLI ${n}: ${e} \u2192 ${V}`)}else $(`kpilot CLI installed: ${V}`);try{await et(L.dirname(t),{recursive:!0}),await ke(t,`${V}
|
|
261
|
+
`,{mode:384})}catch{}}}function Kd(){return`${U(D.bold,`kpilot ${V}`)} \u2014 governed engineering agent
|
|
216
262
|
|
|
217
263
|
All requests go through kpilot \u2014 sign in once, and kpilot handles the rest.
|
|
218
264
|
|
|
@@ -258,65 +304,77 @@ Options:
|
|
|
258
304
|
--no-browser Do not open a browser during \`kpilot login\`
|
|
259
305
|
--limit <number> Row limit for usage and audit lists
|
|
260
306
|
--yes Approve all policy decisions marked "ask"
|
|
307
|
+
--yolo Bypass tool approvals (--force, --yes-always,
|
|
308
|
+
--dangerously-skip-permissions, --auto-accept,
|
|
309
|
+
--permission-mode <mode>; Shift+Tab toggles live)
|
|
261
310
|
--debug Print complete tool results
|
|
262
|
-
--force
|
|
311
|
+
--force Bypass approvals AND force destructive management ops
|
|
263
312
|
-h, --help Show this help
|
|
264
313
|
-V, --version Print the CLI version
|
|
265
314
|
|
|
266
315
|
Interactive additions:
|
|
267
|
-
/sessions, /resume [id], /new [title], /save
|
|
316
|
+
/sessions, /resume [id], /new [title], /save, /clear, /undo
|
|
317
|
+
/compact, /cost, /context, /checkpoint [save|restore|list] [id]
|
|
268
318
|
/memory, /remember <text>, /forget <id>
|
|
319
|
+
/todo [add|done|remove|clear] [text|id]
|
|
269
320
|
/skills, /skill <name> [arguments], /<skill-name> [arguments]
|
|
270
321
|
/preferences, /feedback <accepted|rejected|edited> [note]
|
|
271
322
|
/models, /agent, /mcp, /worktrees, /policy, /usage, /audit, /admin
|
|
272
|
-
`}function
|
|
323
|
+
`}function ae(t,e,n){let r=t[e+1];if(!r||r.startsWith("--"))throw new Error(`${n} requires a value.`);return[r,e+1]}function Wd(t){let e={command:"run",prompt:"",args:[],cwd:process.cwd(),yes:!1,bypassPermissions:!1,debug:!1,force:!1,passphraseEnv:"KPILOT_SYNC_PASSPHRASE",includeSessions:!1,overwrite:!1,limit:50,noCloudSync:!1,noBrowser:!1},n=[],r=!1,o=["run","chat","init","doctor","login","logout","whoami","models","agents","sessions","memory","skills","preferences","feedback","mcp","worktrees","policy","usage","audit","sync","admin","help","version"];for(let s=0;s<t.length;s+=1){let i=t[s]??"";if(i==="--"){n.push(...t.slice(s+1));break}if(i==="-h"||i==="--help"){e.command="help",r=!0;continue}if(i==="-V"||i==="--version"){e.command="version",r=!0;continue}if(i.startsWith("--")&&!i.includes("=")){let a=i.slice(2);if(o.includes(a)){e.command=a,r=!0;continue}}if(i==="--yes"||i==="-y"){e.yes=!0;continue}if($o(i)){e.bypassPermissions=!0,i==="--force"&&(e.force=!0);continue}if(i==="--permission-mode"){let[a,c]=ae(t,s,i);e.bypassPermissions=_o(a),s=c;continue}if(i==="--debug"){e.debug=!0;continue}if(i==="--include-sessions"){e.includeSessions=!0;continue}if(i==="--overwrite"){e.overwrite=!0;continue}if(i==="--no-cloud-sync"){e.noCloudSync=!0;continue}if(i==="--no-browser"){e.noBrowser=!0;continue}if(i==="--cwd"){let[a,c]=ae(t,s,i);e.cwd=L.resolve(a),s=c;continue}if(i==="--mode"){let[a,c]=ae(t,s,i);if(a!=="plan"&&a!=="write")throw new Error("--mode must be plan or write.");e.mode=a,s=c;continue}if(i==="--session"){let[a,c]=ae(t,s,i);e.session=a,s=c;continue}if(i==="--title"){let[a,c]=ae(t,s,i);e.title=a,s=c;continue}if(i==="--note"){let[a,c]=ae(t,s,i);e.note=a,s=c;continue}if(i==="--model"){let[a,c]=ae(t,s,i);e.model=a,s=c;continue}if(i==="--passphrase-env"){let[a,c]=ae(t,s,i);e.passphraseEnv=a,s=c;continue}if(i==="--control-plane-url"){let[a,c]=ae(t,s,i);e.controlPlaneUrl=a,s=c;continue}if(i==="--organization"){let[a,c]=ae(t,s,i);e.organization=a,s=c;continue}if(i==="--limit"){let[a,c]=ae(t,s,i),l=Number(a);if(!Number.isInteger(l)||l<1||l>1e3)throw new Error("--limit must be between 1 and 1000.");e.limit=l,s=c;continue}if(i==="--max-steps"){let[a,c]=ae(t,s,i),l=Number(a);if(!Number.isInteger(l)||l<1||l>50)throw new Error("--max-steps must be an integer between 1 and 50.");e.maxSteps=l,s=c;continue}if(i.startsWith("-")){let a=i.replace(/^--?/,"");throw o.includes(a)?new Error(`Unknown option: ${i}. Use \`kpilot ${a}\` or \`kpilot --${a}\`.`):new Error(`Unknown option: ${i}`)}if(!r&&o.includes(i)){e.command=i,r=!0;continue}n.push(i)}return e.args=n,e.prompt=e.command==="run"?n.join(" ").trim():"",e.command==="run"&&!e.prompt&&(e.command="chat"),e}async function tt(t){try{return await Bi(t),!0}catch{return!1}}async function Vr(t){if(!await tt(t))return{};let e=await eo(t,"utf8");try{return JSON.parse(e)}catch(n){throw new Error(`Invalid JSON in ${t}: ${n instanceof Error?n.message:String(n)}`)}}function Gd(t,e){return{model:{...t.model,...e.model},agent:{...t.agent,...e.agent},sandbox:{...t.sandbox,...e.sandbox},subagents:{...t.subagents,...e.subagents},mcp:{...t.mcp,...e.mcp,servers:{...t.mcp?.servers,...e.mcp?.servers}},preferences:{...t.preferences,...e.preferences},usage:{...t.usage,...e.usage,budget:{...t.usage?.budget,...e.usage?.budget},pricing:{...t.usage?.pricing,...e.usage?.pricing}},permissions:{filesystem:{...t.permissions?.filesystem,...e.permissions?.filesystem},shell:{...t.permissions?.shell,...e.permissions?.shell},git:{...t.permissions?.git,...e.permissions?.git},network:{...t.permissions?.network,...e.permissions?.network},mcp:{...t.permissions?.mcp,...e.permissions?.mcp},subagents:{...t.permissions?.subagents,...e.permissions?.subagents}}}}async function we(t){await Vt(t);let e=L.join(Ki(),".config","kpilot","config.json"),n=L.join(t,E,"config.json");return Gd(await Vr(e),await Vr(n))}function Hd(t,e){let n={filesystem:{...le.filesystem,...t?.filesystem},shell:{...le.shell,...t?.shell},git:{...le.git,...t?.git},network:{...le.network,...t?.network},mcp:{...le.mcp,...t?.mcp},subagents:{...le.subagents,...t?.subagents}};for(let r of["filesystem","shell","git","network","mcp","subagents"]){let o=e?.permissions?.[r]??{},s=n[r];for(let[i,a]of Object.entries(o))i in s&&(s[i]=Tn(s[i],a))}return e?.requireNetworkIsolation&&(n.network=Pi(n.network,!0)),n}function An(t,e){let n=["dailyInputTokens","dailyOutputTokens","dailyTotalTokens","perRunTotalTokens","dailyEstimatedCostUsd"],r={};for(let o of n){let s=[t?.[o],e?.[o]].filter(i=>typeof i=="number"&&i>0);s.length&&(r[o]=Math.min(...s))}return r.warnAtPercent=Math.min(t?.warnAtPercent??80,e?.warnAtPercent??80),r}function nt(t,e,n){let r=e.model?.provider==="external-agent"?"external-agent":"kpilot-hosted";Je(r);let o=e.preferences?.minimumConfidence??.55;if(o<0||o>1)throw new Error("preferences.minimumConfidence must be between 0 and 1.");let s=t.mode??e.agent?.mode??"write",i=t.maxSteps??e.agent?.maxSteps,a=t.model??process.env.KPILOT_MODEL??e.model?.model??"auto";Ti({policy:n,mode:s,model:a,maxSteps:i,sandboxMode:e.sandbox?.mode??"portable",allowNetwork:e.sandbox?.allowNetwork??!1});let c={provider:r,model:a,baseUrl:e.model?.baseUrl,streaming:e.model?.streaming??!0,timeoutMs:e.model?.timeoutMs,retries:e.model?.retries,headers:e.model?.headers,region:e.model?.region,project:e.model?.project,location:e.model?.location,credentialCommand:e.model?.credentialCommand,command:e.model?.command,commandArgs:e.model?.commandArgs,endpoint:e.model?.endpoint,route:e.model?.route,rootDir:t.cwd};return{mode:s,maxSteps:i,provider:r,baseUrl:c.baseUrl??"",model:a,apiKeyEnv:"",apiKey:void 0,accessTokenEnv:"",accessToken:void 0,modelConfig:c,minimumPreferenceConfidence:o,streaming:c.streaming??!0,usageBudget:An(e.usage?.budget,n?.usage),modelPrice:void 0,policy:n,showModel:e.ui?.showModel===!0,verifyCommand:e.agent?.verifyCommand?.trim()||void 0,autoCompactTokens:e.agent?.autoCompactTokens}}function oe(t){return{sessions:new un(t),memory:new Xt(t),todos:new en(t),checkpoints:new nn(t),skills:new dn(t),preferences:new ln(t),audit:new yn(t),usage:new vn(t),policy:new je(t)}}async function G(t){if(!(await Bi(t)).isDirectory())throw new Error(`${t} is not a directory.`);await Od(t),await Vt(t)}async function zd(t,e){let n=L.join(t,".gitignore"),r=await tt(n)?await eo(n,"utf8"):"",o=new Set(r.split(/\r?\n/).filter(Boolean)),s=e.filter(a=>!o.has(a));if(s.length===0)return;let i=r&&!r.endsWith(`
|
|
273
324
|
`)?`
|
|
274
|
-
`:"";await
|
|
325
|
+
`:"";await tt(n)?await Id(n,`${i}${s.join(`
|
|
275
326
|
`)}
|
|
276
|
-
`,"utf8"):await
|
|
327
|
+
`,"utf8"):await ke(n,`${s.join(`
|
|
277
328
|
`)}
|
|
278
|
-
`,"utf8"),
|
|
279
|
-
`,{encoding:"utf8",mode:384}),await
|
|
329
|
+
`,"utf8"),T(`Updated .gitignore with ${s.length} kpilot runtime path(s).`)}async function Vd(t){await G(t);let e=L.join(t,E),n=L.join(e,"config.json"),r=L.join(e,"instructions.md"),o=L.join(e,"skills","review","SKILL.md");await et(L.dirname(o),{recursive:!0}),await tt(n)?A(`${L.relative(t,n)} already exists; left unchanged.`):(await ke(n,`${JSON.stringify({model:{provider:"kpilot-hosted",baseUrl:"https://api.konsolepilot.ai",model:"auto",route:"auto",streaming:!0},agent:{mode:"write"},sandbox:{mode:"portable",allowNetwork:!1,passEnvironment:[]},subagents:{enabled:!0,maxParallel:4},mcp:{servers:{}},preferences:{minimumConfidence:.55},usage:{pricing:{}},permissions:le},null,2)}
|
|
330
|
+
`,{encoding:"utf8",mode:384}),await $n(n,384),T(`Created ${L.relative(t,n)}.`)),await tt(r)?A(`${L.relative(t,r)} already exists; left unchanged.`):(await ke(r,`# Project instructions
|
|
280
331
|
|
|
281
332
|
- Follow the repository's existing architecture and naming conventions.
|
|
282
333
|
- Do not introduce placeholder implementations.
|
|
283
334
|
- Run relevant tests after code changes.
|
|
284
|
-
`,"utf8"),
|
|
335
|
+
`,"utf8"),T(`Created ${L.relative(t,r)}.`)),await tt(o)||(await ke(o,`---
|
|
285
336
|
name: review
|
|
286
337
|
description: Inspect a change for correctness, safety, and missing validation.
|
|
287
338
|
---
|
|
288
339
|
Inspect the relevant implementation and its diff. Prioritize correctness defects, security problems, regressions, missing tests, and inaccurate claims. Report findings by severity with exact file references. Do not modify files unless the invocation explicitly requests fixes.
|
|
289
|
-
`,"utf8"),
|
|
290
|
-
`,{encoding:"utf8",mode:384}),await
|
|
291
|
-
`,{encoding:"utf8",mode:384}),await
|
|
292
|
-
`,{encoding:"utf8",mode:384}),await
|
|
293
|
-
`),t.lineOpen=!1)}function
|
|
294
|
-
`),process.stdout.write(
|
|
340
|
+
`,"utf8"),T(`Created ${L.relative(t,o)}.`)),await zd(t,[`${E}/sessions/`,`${E}/memory.json`,`${E}/preferences.json`,`${E}/todos.json`,`${E}/checkpoints/`,`${E}/audit/`,`${E}/usage/`,`${E}/run/`,`${E}/cache/`,`${E}/logbook/meta.json`]),$(`kpilot ${V} initialized. Connect your account with \`kpilot login\`; bring your own agent via \`kpilot agents\`.`),$("Log in with `kpilot login` and kpilot handles the rest."),$("On first chat, kpilot can inspect the repo and save a Logbook entry under `.kpilot/logbook/project.md`.")}async function Yd(t){let e=t.args[0]??"routes";if(e==="routes"||e==="list"||e==="show"){let n=await Yr();if(!n.length){console.log("No kpilot capabilities are configured for this account yet.");return}console.log(U(D.bold,"kpilot capabilities"));for(let r of n){let o=r.isDefault?"default":r.routeKeys.length?`routes: ${r.routeKeys.join(", ")}`:"available";console.log(`${r.model.padEnd(52)} ${r.provider} ${U(D.dim,o)}`)}console.log("For help, contact your kpilot administrator.");return}if(e==="route"){let n=t.args.slice(1).join(" ").trim();if(!n)throw new Error("Usage: kpilot models route <prompt>");let r=sn(n),s=(await Yr()).find(i=>i.routeKeys.includes(r.route))?.model??null;console.log(JSON.stringify({...r,selected:s},null,2));return}throw new Error("Usage: kpilot models [routes|route] [prompt]")}async function Yr(){let e=await new ie().validAccessToken();if(!e)throw new Error("kpilot needs an account. Run `kpilot login`.");let n=await e.client.catalog(e.tokens.accessToken),r=new Map;for(let[o,s]of Object.entries(n.routeCandidates??{}))for(let i of s){let a=r.get(i.model)??{provider:i.provider,isDefault:i.isDefault,routeKeys:[]};a.routeKeys.includes(o)||a.routeKeys.push(o),i.isDefault&&(a.isDefault=!0),r.set(i.model,a)}return[...r.entries()].map(([o,s])=>({model:o,provider:s.provider,isDefault:s.isDefault,routeKeys:s.routeKeys}))}async function Vi(t){await G(t.cwd);let e=L.join(t.cwd,E,"config.json"),n=await Vr(e),r=t.args[0]??"show";if(r==="show"){if(n.model?.provider!=="external-agent"){console.log("[no project external agent configured]");return}console.log(JSON.stringify({provider:n.model.provider,command:n.model.command,commandArgs:n.model.commandArgs,endpoint:n.model.endpoint,timeoutMs:n.model.timeoutMs},null,2));return}if(r==="use-http"){let o=t.args[1];if(!o)throw new Error("Usage: kpilot agents use-http <http-or-https-endpoint>");let s=new URL(o);if(!["http:","https:"].includes(s.protocol))throw new Error("External-agent endpoint must use HTTP or HTTPS.");let i=n.model??{},{command:a,commandArgs:c,endpoint:l,...u}=i;n.model={...u,provider:"external-agent",model:"external-agent",endpoint:s.toString()},await et(L.dirname(e),{recursive:!0}),await ke(e,`${JSON.stringify(n,null,2)}
|
|
341
|
+
`,{encoding:"utf8",mode:384}),await $n(e,384),T(`Configured project external agent endpoint ${s.toString()}.`);return}if(r==="use-command"){let o=t.args[1];if(!o)throw new Error("Usage: kpilot agents use-command <executable> [args...]");let s=n.model??{},{command:i,commandArgs:a,endpoint:c,...l}=s;n.model={...l,provider:"external-agent",model:"external-agent",command:o,commandArgs:t.args.slice(2)},await et(L.dirname(e),{recursive:!0}),await ke(e,`${JSON.stringify(n,null,2)}
|
|
342
|
+
`,{encoding:"utf8",mode:384}),await $n(e,384),T(`Configured project external agent command ${o}.`);return}if(r==="clear"){n.model={provider:"kpilot-hosted",baseUrl:"https://api.konsolepilot.ai",model:"auto",route:"auto",streaming:!0},await et(L.dirname(e),{recursive:!0}),await ke(e,`${JSON.stringify(n,null,2)}
|
|
343
|
+
`,{encoding:"utf8",mode:384}),await $n(e,384),T("Removed the project external agent and restored kpilot automatic routing.");return}throw new Error("Usage: kpilot agents [show|use-http|use-command|clear] [endpoint-or-command] [args...]")}async function zr(t){return await new Promise(e=>{let n=process.platform==="win32"?"where":"sh",r=process.platform==="win32"?[t]:["-lc",`command -v "${t}" >/dev/null 2>&1`],o=Wi(n,r,{stdio:"ignore"});o.once("error",()=>e(!1)),o.once("close",s=>e(s===0))})}async function Qd(t){await G(t.cwd);let e=await we(t.cwd),n=oe(t.cwd),r=await n.policy.load(),o=nt(t,e,r),s=0,i=Number(process.version.slice(1).split(".")[0]);console.log(U(D.bold,`kpilot doctor \u2014 ${t.cwd}`)),i>=26?T(`Node.js ${process.version}`):(J(`Node.js ${process.version}; Node.js 26 or newer is required.`),s+=1),await zr("git")?T("Git is available."):A("Git is unavailable; status, diff, and feedback evidence will be limited."),await zr("rg")?T("ripgrep is available."):A("ripgrep is unavailable; search_text will use the slower built-in fallback.");let a=o.model&&o.model!=="auto"?`kpilot capability: ${o.model}`:"kpilot automatic routing (kpilot chooses for you).";T(a);let c=Je(o.provider);T(`Authenticated: ${c.name} (${c.id}).`),o.provider==="kpilot-hosted"?await new ie().load()?T("Your kpilot account is connected."):(J("kpilot needs an account. Run `kpilot login`."),s+=1):o.provider==="external-agent"&&(o.modelConfig.endpoint?T(`External agent endpoint configured: ${o.modelConfig.endpoint}`):o.modelConfig.command&&await zr(o.modelConfig.command)?T(`External agent command is available: ${o.modelConfig.command}`):(J("External agent requires a reachable endpoint or available command."),s+=1)),T(`${(await n.sessions.list()).length} persistent session(s) readable.`),T(`${(await n.memory.list()).length} project memory entr${(await n.memory.list()).length===1?"y":"ies"} readable.`),T(`${(await n.skills.list()).length} reusable skill(s) discovered.`),T(`${(await n.preferences.listRules()).length} learned preference rule(s) readable.`),r?T(`Team policy loaded${r.organization?` for ${r.organization}`:""}.`):$("Team policy: not configured.");let l=await n.usage.check(o.usageBudget);l.allowed?T(`Usage budget available: ${de(l.summary.totalTokens)} token(s) used today.`):(J(`Usage budget blocked: ${l.violations.join(" ")}`),s+=1);let u=await n.audit.verify();u.valid?T(`Audit chain valid: ${u.records} record(s).`):(J(`Audit chain invalid: ${u.reason??"unknown failure"}`),s+=1);let m=new be(t.cwd,{sandbox:e.sandbox});try{T(`Sandbox: ${await m.sandbox.describe()}.`)}catch(y){J(y instanceof Error?y.message:String(y)),s+=1}let d=Object.entries(e.mcp?.servers??{}).filter(([y,S])=>S.enabled!==!1&&(!r?.allowedMcpServers||r.allowedMcpServers.includes(y)));if(d.length===0)$("MCP: no enabled servers configured.");else try{let y=await Ae.connect(Object.fromEntries(d));T(`MCP: ${d.length} server(s), ${y.list().length} tool(s) available.`),await y.close()}catch(y){J(`MCP: ${y instanceof Error?y.message:String(y)}`),s+=1}o.baseUrl&&$(`Endpoint: ${o.baseUrl}`);let p=o.maxSteps===void 0?"unlimited":String(o.maxSteps);return $(`Mode: ${o.mode}; max steps: ${p}; streaming: ${o.streaming?"on":"off"}`),s===0?0:1}var rt;function ot(){rt?.stop(),rt=void 0}function st(){rt?.dispose(),rt=void 0}function Xd(t){return t?`kpilot (${t})`:"kpilot"}function On(t){return U(D.green,Xd(t))}function Ze(t){t.lineOpen&&(process.stdout.write(`
|
|
344
|
+
`),t.lineOpen=!1)}function Ui(t,e,n,r){let o=On(n);return s=>{if((s.type==="assistant_delta"||s.type==="assistant_text"||s.type==="tool_start"||s.type==="tool_output"||s.type==="permission"||s.type==="cancelled")&&(ot(),e.thinking=void 0),s.type==="reasoning_delta"){r?.reasoningDelta(s.delta,!e.lineOpen);return}if(s.type==="assistant_delta"){if(r?.noteOutput(),!e.lineOpen){r?.clearReasoning(),ot(),process.stdout.isTTY||process.stdout.write(`
|
|
345
|
+
`);let i=bo(e,o);i&&(process.stdout.write(i),e.speakerShown=!0),e.lineOpen=!0}e.streamed=!0,process.stdout.write(s.delta)}else if(s.type==="tool_start")Ze(e),e.toolOutputLines=0,r?.clearReasoning(),r?.activity("start",s.call.function.name,Nn(s.args,s.call.function.name)),r?.start(),e.thinking=r,rt=r;else if(s.type==="tool_output"){let i=s.chunk.replace(/\s+$/,"");i&&e.toolOutputLines<20&&(Ze(e),process.stdout.write(`${U(D.dim,` \u2502 ${i.slice(0,160)}`)}
|
|
346
|
+
`),e.toolOutputLines+=1,e.toolOutputLines===20&&process.stdout.write(`${U(D.dim," \u2502 \u2026 (output continues; full result on completion)")}
|
|
347
|
+
`))}else if(s.type==="tool_result"){Ze(e);let i=s.result.ok?go(s.result.metadata):"";r?.activity("result",s.call.function.name,i,s.result.ok),(t||!s.result.ok)&&console.log(U(D.dim,s.result.output))}else s.type==="usage"?(e.inputTokens+=s.inputTokens,e.outputTokens+=s.outputTokens,e.cacheReadTokens+=s.cacheReadTokens??0,e.cacheWriteTokens+=s.cacheWriteTokens??0,r?.addUsage(s.inputTokens,s.outputTokens,s.cacheReadTokens??0)):s.type==="cancelled"&&(Ze(e),r?.dispose(),A(s.reason))}}async function to(t){let e=new AbortController,n=()=>{ct.noteStop("Ctrl+C"),e.abort(Gn())};process.once("SIGINT",n);let r=ct.begin(e);try{return await t(e.signal)}finally{process.removeListener("SIGINT",n),r()}}function Zd(t){return`Approve ${t.category}?
|
|
295
348
|
${t.summary}
|
|
296
|
-
${t.reason}`}function
|
|
297
|
-
${
|
|
298
|
-
[truncated ${t.length-e} characters]`}async function
|
|
299
|
-
|
|
349
|
+
${t.reason}`}function Yi(t,e,n){let r=new Set;return async o=>{if(t.yes||r.has(o.category))return!0;if(!e||!process.stdin.isTTY)return!1;ot(),console.log(""),console.log(Zd(o));let s=await Q({title:"Permission action:",question:e,pauseResume:n,choices:[{value:"yes",label:"yes",description:"Allow this action once",aliases:["y"],default:!0},{value:"no",label:"no",description:"Deny this action",aliases:["n"]},{value:"always",label:"always",description:"Allow this category for the rest of the session",aliases:["a"]}]});return s==="always"?(r.add(o.category),!0):s==="yes"}}function em(t){return async e=>e.category==="filesystem.read"||e.category==="git.read"||e.category==="filesystem.write"&&ji(e.summary)?!0:t(e)}async function Qi(t){$("Inspecting the repository and writing `.kpilot/logbook/project.md`\u2026");let e=t.cli.mode,n=t.created.settings.mode;t.cli.mode="write",t.created.settings.mode="write";let r=L.relative(t.cli.cwd,Ye(t.cli.cwd))||".kpilot/logbook/project.md";try{try{let o=await to(s=>no({cli:t.cli,created:t.created,services:t.services,session:t.session,prompt:Rn,approvalHandler:em(t.approvalHandler),skipSessionNaming:!0,signal:s}));o.streamed||console.log(`
|
|
350
|
+
${On(t.created.settings.showModel?t.created.settings.model:void 0)} \u203A ${o.answer}`)}catch(o){if(await Xe(t.cli.cwd)){let s=o instanceof Error?o.message:String(o);A(`Model call failed after Logbook write (${s}). Using the saved entry.`)}else{if(it(o))throw o;if(qr(o))A("Hub context is too small for a full agent Logbook pass; writing a lite entry from repo metadata\u2026"),await Fr(t.cli.cwd);else throw o}}return await Xe(t.cli.cwd)?(T(`Logbook project entry saved to ${r}`),$("Later turns will load this Logbook entry instead of rediscovering the repo from scratch. Refresh with /logbook"),!0):(A("Onboarding finished but `.kpilot/logbook/project.md` was not found. Ask the agent to write it, or run /logbook again."),!1)}catch(o){if(it(o))return A("Logbook onboarding stopped."),!1;let s=o instanceof Error?o.message:String(o);if(qr(o)||/fetch failed|unreachable/i.test(s))try{return A(`Agent Logbook pass failed (${s}). Falling back to lite capture\u2026`),await Fr(t.cli.cwd),T(`Logbook lite entry saved to ${r}`),$("Re-run /logbook later if you want a richer brief with a larger-context model."),!0}catch(i){return J(`Logbook capture failed: ${s}`),A(`Lite fallback also failed: ${i instanceof Error?i.message:String(i)}`),!1}return J(`Logbook capture failed: ${s}`),$("You can retry with /logbook, or continue chatting without a Logbook entry."),!1}finally{t.cli.mode=e,t.created.settings.mode=n}}async function tm(t){try{if(await Xe(t.cli.cwd)){await $i(t.cli.cwd)&&A("Logbook entry is over a week old; run /logbook to refresh it if the project has changed."),await jt(t);return}if(!await _i(t.cli.cwd)){await jt(t);return}if(!process.stdin.isTTY)return;console.log(""),$("This repository has no Logbook project entry yet.");let e=await Q({title:"Save a Logbook entry under .kpilot/logbook/project.md for later sessions?",question:t.question,pauseResume:t.pauseResume,choices:[{value:"yes",label:"yes",description:"Inspect the repo and write project.md",aliases:["y"],default:!0},{value:"no",label:"no",description:"Skip for now (can run /logbook later)",aliases:["n"]},{value:"skip",label:"skip",description:"Do not auto-offer again"}]});if(e==="no"||e==="skip"){await Jr(t.cli.cwd),$("Skipped. You can run /logbook later."),await jt(t);return}if(e!=="yes"){$("Skipped. You can run /logbook later."),await jt(t);return}await Kr(t.cli.cwd),await Qi(t),await jt(t)}catch(e){let n=e instanceof Error?e.message:String(e);A(`Logbook onboarding interrupted: ${n}`),$("Continuing into chat. Retry later with /logbook.")}}async function jt(t){if(!await Oi(t.cli.cwd)){await It(t.cli.cwd)&&$("Logbook learning is on (.kpilot/logbook/learnings.md). Toggle with /learn off");return}if(!process.stdin.isTTY)return;if(console.log(""),$("Optional: keep learning durable project facts from chats to speed up later work."),await Q({title:"Enable continuous Logbook learning (.kpilot/logbook/learnings.md)?",question:t.question,pauseResume:t.pauseResume,choices:[{value:"yes",label:"yes",description:"Append durable facts from chats",aliases:["y"]},{value:"no",label:"no",description:"Leave learning off",aliases:["n"],default:!0}]})==="yes"){await Dt(t.cli.cwd,!0),T("Logbook learning enabled. Facts from chats will append to .kpilot/logbook/learnings.md");return}await Dt(t.cli.cwd,!1),$("Logbook learning left off. Enable later with /learn on")}async function nm(t,e,n){if(!t.route&&!t.model)return n;if(e.provider!=="kpilot-hosted")throw new Error(`Provider ${e.provider} cannot resolve per-task subagent routes in hosted-only mode.`);let{gateway:r}=await on({...e.modelConfig,route:t.route??"auto",model:t.model??"auto"});return r}function Qr(t){let e=process.env.KPILOT_BROWSER?.trim().toLowerCase()||t.tools?.browser||"auto";return e==="on"?"on":e==="off"?"off":"auto"}async function Xr(t,e,n){let r=await new je(t.cwd).load(),o=nt(t,e,r);if(n&&(o.modelConfig.sessionId=n.id),!o.model)throw new Error("No capability configured. Use kpilot automatic routing.");if(o.provider==="kpilot-hosted"){await pm(t);let p=new ie,y=await p.load();if(!y)throw new Error("kpilot needs an account to continue. Run `kpilot login`.");let S=new ue(t.controlPlaneUrl??y.controlPlaneUrl,`kpilot/${V}`),x=await p.validAccessToken(S);if(!x)throw new Error("kpilot needs an active account session. Run `kpilot login`.");o.modelConfig.accessToken=x.tokens.accessToken,o.modelConfig.baseUrl=t.controlPlaneUrl??x.tokens.controlPlaneUrl,o.baseUrl=o.modelConfig.baseUrl,o.modelConfig.getAccessToken=async()=>{let k=await p.validAccessToken(S);return k?(o.modelConfig.accessToken=k.tokens.accessToken,k.tokens.accessToken):o.modelConfig.accessToken}}let s=new be(t.cwd,{sandbox:e.sandbox,browser:Qr(e)}),i=new Ke(Hd(e.permissions,r)),{gateway:a}=await on(o.modelConfig),c=e.mcp?.servers??{},l=r?.allowedMcpServers?Object.fromEntries(Object.entries(c).filter(([p])=>r.allowedMcpServers.includes(p))):c,u=Object.values(l).some(p=>p.enabled!==!1)?await Ae.connect(l):void 0,m=e.subagents?.enabled===!1?void 0:new hn({rootDir:t.cwd,gateway:a,resolveGateway:p=>nm(p,o,a),localRuntimeOptions:{sandbox:e.sandbox,browser:Qr(e)},maxParallel:e.subagents?.maxParallel,maxSteps:e.subagents?.maxSteps}),d=new xt([s,u,m]);return{agent:new Fe({gateway:a,runtime:d,permissions:i,initialMessages:n?.messages}),runtime:d,localRuntime:s,mcpRuntime:u,settings:o,close:async()=>{await u?.close()}}}async function rm(t,e,n){return t.session?await e.load(t.session):await e.create({title:t.title,mode:n.mode,model:n.model})}function Xi(t){let e=process.env.KPILOT_CONTEXT_WINDOW?.trim();if(e&&/^\d+$/.test(e)){let n=Number(e);if(n>=1024&&n<=1e6)return n}}function Ni(t,e=12e4){if(t)return t.length<=e?t:`${t.slice(0,e)}
|
|
351
|
+
[truncated ${t.length-e} characters]`}async function _n(t,e,n,r){let o=await t.execute("git_diff",{},{rootDir:e,mode:n,signal:r});return o.ok?o.output:void 0}async function Fi(t,e,n){let r=await t.execute("shell",{command:`git checkout -- ${n.map(Lo).join(" ")}`},{rootDir:e,mode:"write",signal:void 0});return{ok:r.ok,output:r.output}}async function om(t,e,n,r){let o=r?await Gr(r):"",s=await t.memory.renderForPrompt(),i=await t.todos.renderForPrompt(),a=new Set(s.split(`
|
|
352
|
+
`).map(u=>u.replace(/^[-*]\s*/,"").trim().toLowerCase()).filter(Boolean)),c=o.split(`
|
|
353
|
+
`).filter(u=>{let m=u.replace(/^[-*]\s*/,"").trim().toLowerCase();return!m||!a.has(m)}).join(`
|
|
354
|
+
`).trim();return{memoryContext:[s,c?`Logbook learnings (.kpilot/logbook):
|
|
355
|
+
${c}`:"",i].filter(Boolean).join(`
|
|
300
356
|
|
|
301
357
|
`),preferenceContext:await t.preferences.renderForPrompt(e.minimumPreferenceConfidence),skillContext:n?`${n.description}
|
|
302
358
|
|
|
303
|
-
${n.instructions}`:void 0}}async function
|
|
304
|
-
|
|
305
|
-
`),null;if(i instanceof Error&&(i.name==="kpilotRetry"||i.message==="retry"))continue;if(!r){let a=Date.now();if(n.armedAt>0&&a-n.armedAt<=2500)return process.stdout.write(`
|
|
306
|
-
`),null;n.armedAt=a,process.stdout.write(`
|
|
307
|
-
`),R("Press Ctrl+C again to exit.")}continue}finally{process.removeListener("SIGINT",s),t.removeListener("SIGINT",s)}}}var Ql="\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";async function Xl(t,e,n){let o=await ls(e),r=$(M.dim,Ql),s=`${$(M.cyan,"you")} \u203A `,i=$(M.dim,o);process.stdout.write(`
|
|
308
|
-
${r}
|
|
309
|
-
${s}
|
|
310
|
-
${r}
|
|
311
|
-
${i}\x1B[2A\r`);try{return await Yl(t,s,n)}finally{process.stdout.write("\x1B[2B\r")}}function Rs(t){return t.controlPlaneUrl??process.env.KPILOT_CONTROL_PLANE_URL??"https://api.konsolepilot.ai"}async function Zl(t){let e=process.platform,n=e==="darwin"?"open":e==="win32"?"cmd":"xdg-open",o=e==="darwin"?[t]:e==="win32"?["/c","start","",t]:[t];return await new Promise(r=>{let s=bs(n,o,{stdio:"ignore",detached:!0});s.unref(),s.once("error",()=>r(!1)),s.once("spawn",()=>r(!0))})}async function eu(t){let e=new Y,n=await e.load(),o=new Z(t.controlPlaneUrl??n?.controlPlaneUrl??Rs(t),`kpilot/${B}`);if(n?await e.validAccessToken(o):void 0)return;if(!process.stdin.isTTY)throw new Error("kpilot needs an account to continue. Run `kpilot login`.");if(P("kpilot needs your account to continue. Starting sign-in\u2026"),await Ms(t),!await e.load())throw new Error("kpilot needs an account to continue. Run `kpilot login`.")}async function Ms(t){let e=new Z(Rs(t),`kpilot/${B}`),n=new Y,o=await n.load();if(o&&!t.force)throw new Error(`Already signed in as ${o.user.email}. Run \`kpilot logout\` first, or use --force.`);let r=await e.createDeviceCode(),s=r.verification_uri_complete||`${r.verification_uri}?code=${encodeURIComponent(r.user_code)}`,i=t.noBrowser||process.env.KPILOT_NO_BROWSER==="1",a=!1;i||(a=await Zl(s)),a?(console.log(`
|
|
312
|
-
Opened ${s}`),console.log(`Confirm code ${$(M.bold,r.user_code)} in your browser if prompted.
|
|
313
|
-
`),P("Approve the device in your browser. Press Ctrl+C to cancel.")):(console.log(`
|
|
314
|
-
Open: ${s}`),console.log(`Code: ${$(M.bold,r.user_code)}
|
|
315
|
-
`),P("Waiting for authorization in your browser. Press Ctrl+C to cancel."));let c=new AbortController,l=()=>c.abort(new Error("Login cancelled."));process.once("SIGINT",l);try{let u=await e.pollDeviceToken(r.device_code,{intervalSeconds:r.interval,expiresInSeconds:r.expires_in,signal:c.signal});await n.save(u),v(`Signed in as ${u.user.email} \xB7 ${u.organization.name}`)}finally{process.removeListener("SIGINT",l)}}async function tu(t){let e=new Y,n=await e.load();if(!n){console.log("Not signed in. Run `kpilot login`.");return}let o=new Z(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${B}`),r=await e.validAccessToken(o);if(!r)throw new Error("Not signed in.");let s=await r.client.profile(r.tokens.accessToken);console.log(`${s.user.name} <${s.user.email}>`),console.log(`Organization: ${s.organization.name} (${s.organization.slug})`),s.device&&console.log(`Device: ${s.device.name}`),console.log(`Control plane: ${r.tokens.controlPlaneUrl}`)}async function nu(t){let e=new Y,n=await e.load();if(!n){console.log("Already signed out.");return}await new Z(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${B}`).logout(n.refreshToken).catch(()=>{}),await e.clear(),v("Signed out and removed local cloud credentials.")}async function ru(t){if(!(t.noCloudSync||process.env.KPILOT_DISABLE_CLOUD_SYNC==="1"))try{let e=new Y,n=await e.load();if(!n)return;let o=new Z(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${B}`),r=await e.validAccessToken(o);if(!r)return;let s=await r.client.checkBudget(r.tokens.accessToken,0);for(let i of s.warnings)R(`Cloud budget: ${i}`);if(!s.allowed)throw new Error(`Cloud budget prevents this run: ${s.violations.join(" ")}`)}catch(e){if(e instanceof Error&&e.message.startsWith("Cloud budget prevents"))throw e;t.debug&&R(`Cloud budget check unavailable: ${e instanceof Error?e.message:String(e)}`)}}async function gs(t){if(t.provider!=="kpilot-hosted"&&!(t.cli.noCloudSync||process.env.KPILOT_DISABLE_CLOUD_SYNC==="1"))try{let e=new Y,n=await e.load();if(!n)return;let o=new Z(t.cli.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${B}`),r=await e.validAccessToken(o);if(!r)return;let s=ws("sha256").update(_.resolve(t.cli.cwd)).digest("hex").slice(0,32);await r.client.ingestUsage(r.tokens.accessToken,[{eventId:t.record.id,occurredAt:t.record.timestamp,projectFingerprint:s,...t.record.sessionId?{sessionId:t.record.sessionId}:{},provider:t.provider,model:t.record.model,inputTokens:t.record.inputTokens,outputTokens:t.record.outputTokens,estimatedCostUsd:t.record.estimatedCostUsd,durationMs:Math.max(0,Math.trunc(t.durationMs)),success:t.success}])}catch(e){t.cli.debug&&R(`Cloud usage sync failed: ${e instanceof Error?e.message:String(e)}`)}}async function ou(t){if(!t.prompt)throw new Error("Provide a prompt, or use `kpilot`.");await L(t.cwd);let e=await oe(t.cwd),n=z(t.cwd),o=Le(t,e,await n.policy.load()),r=await Hl(t,n.sessions,o);t.mode||(t.mode=r.mode);let s=await mr(t,e,r),i=process.stdin.isTTY?vs({input:process.stdin,output:process.stdout}):void 0;try{P(`${s.settings.mode.toUpperCase()} mode \xB7 kpilot \xB7 session ${r.id.slice(0,8)}`),console.log(xt(s.settings.mode,s.settings.model,r.id.slice(0,8)));try{let a=await yr(c=>br({cli:t,created:s,services:n,session:r,prompt:t.prompt,approvalHandler:Ps(t,i?l=>i.question(l):void 0,xs(i)),signal:c}));a.streamed||console.log(`${$(M.bold,"Result")}
|
|
316
|
-
${a.answer}`),P(`Resume with: kpilot chat --session ${r.id.slice(0,8)}`)}catch(a){if(!vr(a))throw a;r.messages=[...s.agent.messages],await n.sessions.save(r),R("Agent run cancelled; partial conversation state was saved."),process.exitCode=130}}finally{i?.close(),await s.close()}}function $s(t){let e=t?.trim().toLowerCase();if(e==="accept")return"accepted";if(e==="reject")return"rejected";if(e==="edit")return"edited";if(e==="accepted"||e==="rejected"||e==="edited")return e;throw new Error("Feedback outcome must be accepted, rejected, or edited.")}async function _s(t){let e=t.session.runs.at(-1);if(!e)throw new Error("The selected session has no completed run to evaluate.");let n=t.outcome==="edited"?await pr(t.runtime,t.rootDir,t.mode):e.diffAfter,o=await t.services.preferences.learn({outcome:t.outcome,task:e.prompt,note:t.note,sessionId:t.session.id,proposedDiff:e.diffAfter,finalDiff:n});if(v(`Recorded ${t.outcome} feedback for session ${t.session.id.slice(0,8)}.`),o.learned.length===0)P("No durable rule was inferred. Add a concrete note to teach an explicit preference.");else for(let r of o.learned)P(`${r.polarity}: ${r.text} (${Math.round(r.confidence*100)}%)`)}async function su(t){await L(t.cwd);let e=z(t.cwd).sessions,n=t.args[0]??"list";if(n==="list"){Vl(await e.list());return}let o=t.args[1]??t.session;if(!o)throw new Error(`sessions ${n} requires a session ID.`);if(n==="show"){let r=await e.load(o);console.log(JSON.stringify(r,null,2));return}if(n==="delete"){await e.delete(o),v(`Deleted session ${o}.`);return}throw new Error(`Unknown sessions action: ${n}`)}async function iu(t){await L(t.cwd);let e=z(t.cwd).memory,n=t.args[0]??"list";if(n==="list"){Es(await e.list());return}if(n==="add"){let o=await e.add(t.args.slice(1).join(" "));v(`Remembered ${o.id.slice(0,8)}: ${o.text}`);return}if(n==="remove"){let o=t.args[1];if(!o)throw new Error("memory remove requires an entry ID.");let r=await e.remove(o);v(`Removed memory: ${r.text}`);return}if(n==="clear"){let o=await e.clear();v(`Removed ${o} memory entr${o===1?"y":"ies"}.`);return}throw new Error(`Unknown memory action: ${n}`)}async function au(t){await L(t.cwd);let e=z(t.cwd).skills,n=t.args[0]??"list";if(n==="list"){Cs(await e.list());return}if(n==="show"){let o=t.args[1];if(!o)throw new Error("skills show requires a skill name.");let r=await e.get(o);console.log(`${r.name} (${r.source})
|
|
317
|
-
${r.description}
|
|
359
|
+
${n.instructions}`:void 0}}async function sm(t,e,n){try{let r=await t.execute("git_status",{},{rootDir:e,mode:n});if(!r.ok)return"";let o=r.output.split(/\r?\n/).filter(c=>c.trim()),i=(o.find(c=>c.startsWith("##"))??"").replace(/^##\s*/,"").split("...")[0]?.trim()||"(unknown)",a=o.filter(c=>!c.startsWith("##")).length;return`Git: branch ${i}, ${a} uncommitted change(s).`}catch{return""}}async function no(t){let e={streamed:!1,lineOpen:!1,speakerShown:!1,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,toolOutputLines:0},n=new Date().toISOString(),r=[],o=new Ft({mode:t.created.settings.mode});e.thinking=o,rt=o,o.start();try{await hm(t.cli);let s=Ji("sha256").update(t.prompt).digest("hex"),i=await t.services.usage.check(t.created.settings.usageBudget);for(let g of i.warnings)ot(),A(`Usage budget: ${g}`);if(!i.allowed)throw ot(),await t.services.audit.append({action:"agent.run",outcome:"denied",category:"usage",sessionId:t.session.id,details:{violations:i.violations}}),new Error(`Usage budget prevents this run: ${i.violations.join(" ")}`);await t.services.audit.append({action:"agent.run",outcome:"info",category:"agent",sessionId:t.session.id,details:{mode:t.created.settings.mode,model:t.created.settings.model,promptHash:s,promptLength:t.prompt.length}});let a=await _n(t.created.localRuntime,t.cli.cwd,t.created.settings.mode,t.signal);t.onDiffBefore?.(a);let c=t.created.settings.autoCompactTokens;if(c&&t.created.agent.messages.length>2){let g=Math.ceil(t.created.agent.messages.reduce((b,v)=>{let O=typeof v.content=="string"?v.content.length:0,H=v.role==="assistant"?(v.tool_calls??[]).reduce((ce,te)=>ce+te.function.arguments.length,0):0;return b+O+H},0)/4);if(g>c){$(`Context ~${de(g)} tokens; auto-compacting history\u2026`);try{await t.created.agent.compact(t.signal)}catch{A("Auto-compaction failed; continuing with full history.")}}}let l=await om(t.services,t.created.settings,t.skill,t.cli.cwd),u=await sm(t.created.localRuntime,t.cli.cwd,t.created.settings.mode),m=t.created.agent.messages.filter(g=>g.role==="user").length===0,d="";if(m){let g=await t.created.localRuntime.execute("workspace_summary",{},{rootDir:t.cli.cwd,mode:t.created.settings.mode});g.ok&&(d=`Workspace summary:
|
|
360
|
+
${g.output.slice(0,1500)}`)}let p=[u,l.memoryContext,l.skillContext,d].filter(Boolean).join(`
|
|
318
361
|
|
|
319
|
-
|
|
362
|
+
`),S=!t.skipSessionNaming&&t.session.titleSource==="auto"&&!t.cli.title?Go(t.created.agent.gateway,t.prompt):void 0,x;try{let g=Xi(t.created.settings.provider);x=await t.created.agent.run({prompt:t.prompt,mode:t.created.settings.mode,rootDir:t.cli.cwd,maxSteps:t.created.settings.maxSteps,maxTotalTokens:t.created.settings.usageBudget.perRunTotalTokens,contextWindowTokens:g,approvalHandler:t.approvalHandler,bypassPermissions:t.bypassPermissions===!0,preferenceContext:l.preferenceContext,volatileContext:p,onEvent:b=>{r.push(b),Ui(t.cli.debug,e,t.created.settings.showModel?t.created.settings.model:void 0,o)(b)},signal:t.signal})}catch(g){if(st(),Ze(e),e.inputTokens||e.outputTokens){let b=await t.services.usage.record({model:t.created.settings.model,sessionId:t.session.id,inputTokens:e.inputTokens,outputTokens:e.outputTokens,price:t.created.settings.modelPrice});await qi({cli:t.cli,provider:t.created.settings.provider,record:b,success:!1,durationMs:Date.now()-new Date(n).getTime()})}throw t.session.messages=[...t.created.agent.messages],await t.services.sessions.save(t.session),await t.services.audit.append({action:"agent.run",outcome:it(g)?"cancelled":"failure",category:"agent",sessionId:t.session.id,details:{model:t.created.settings.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,error:g instanceof Error?g.message.slice(0,500):String(g).slice(0,500)}}),g}Ze(e);let k=await _n(t.created.localRuntime,t.cli.cwd,t.created.settings.mode,t.signal),R=a!==k,P=0,_=0,I=t.created.settings.verifyCommand;if(R&&I&&t.created.settings.mode==="write"){$(`Verifying: ${I}`);let g=await t.created.localRuntime.execute("shell",{command:I},{rootDir:t.cli.cwd,mode:"write",signal:t.signal});if(g.ok)T("Verification passed.");else{A("Verification failed; asking the model to fix it."),console.log(U(D.dim,g.output.slice(-2e3)));try{let b=await t.created.agent.run({prompt:`The verification command \`${I}\` failed after your changes. Fix the cause, then confirm. Output:
|
|
363
|
+
|
|
364
|
+
${g.output.slice(-4e3)}`,mode:"write",rootDir:t.cli.cwd,maxSteps:t.created.settings.maxSteps,approvalHandler:t.approvalHandler,onEvent:O=>{r.push(O),Ui(t.cli.debug,e,t.created.settings.showModel?t.created.settings.model:void 0,o)(O)},signal:t.signal});P+=b.usage.inputTokens,_+=b.usage.outputTokens,(await t.created.localRuntime.execute("shell",{command:I},{rootDir:t.cli.cwd,mode:"write",signal:t.signal})).ok?T("Verification passed after fix."):A("Verification still failing after one fix attempt.")}catch(b){if(it(b))throw b;A(`Verification fix attempt failed: ${b instanceof Error?b.message:String(b)}`)}}}let j=x.usage.inputTokens+P,N=x.usage.outputTokens+_,h=await t.services.usage.record({model:t.created.settings.model,sessionId:t.session.id,inputTokens:j,outputTokens:N,cacheReadTokens:x.usage.cacheReadTokens,cacheWriteTokens:x.usage.cacheWriteTokens,price:t.created.settings.modelPrice});await qi({cli:t.cli,provider:t.created.settings.provider,record:h,success:!0,durationMs:Date.now()-new Date(n).getTime()}),o.setCost(h.estimatedCostUsd);let f=ho(k),w=t.created.settings.mode==="plan"?vo(r):void 0;o.finish({files:f,changed:R,planSummary:w,diff:R?k:void 0}),t.session.mode=t.created.settings.mode,t.session.model=t.created.settings.model,t.session.messages=[...x.messages],t.session.runs.push({id:Dd(),prompt:t.prompt,answer:x.answer,startedAt:n,completedAt:new Date().toISOString(),steps:x.steps,usage:{inputTokens:j,outputTokens:N,estimatedCostUsd:h.estimatedCostUsd},diffBefore:Ni(a),diffAfter:Ni(k)}),t.session.runs.length>100&&(t.session.runs=t.session.runs.slice(-100)),S&&(t.session.title=await S,t.session.titleSource="generated"),await t.services.sessions.save(t.session),await t.services.audit.append({action:"agent.run",outcome:"success",category:"agent",sessionId:t.session.id,details:{model:t.created.settings.model,steps:x.steps,inputTokens:j,outputTokens:N,estimatedCostUsd:h.estimatedCostUsd,changed:R}});try{let g=await Di({rootDir:t.cli.cwd,prompt:t.prompt,answer:x.answer,diffAfter:k,changed:a!==k});g.length&&$(`Learned ${g.length} Logbook fact(s) \u2192 .kpilot/logbook/learnings.md`)}catch(g){t.cli.debug&&A(`Logbook learning failed: ${g instanceof Error?g.message:String(g)}`)}return{answer:x.answer,streamed:e.streamed,tokensUsed:x.usage.inputTokens+x.usage.outputTokens}}finally{st(),e.thinking=void 0}}function im(t){if(t.length===0){console.log("[no sessions]");return}for(let e of t){let n=`${e.updatedAt} ${e.mode.padEnd(5)} ${String(e.runCount).padStart(3)} run(s)`;console.log(`${e.title} ${U(D.dim,n)}`)}}function Zi(t){if(t.length===0){console.log("[no project memory]");return}for(let e of t)console.log(`${e.id.slice(0,8)} ${e.text}`)}function ea(t){if(t.length===0){console.log("[no skills]");return}for(let e of t)console.log(`${e.name.padEnd(20)} ${e.source.padEnd(7)} ${e.description}`)}function it(t){return t instanceof lt||t instanceof Error&&(t.name==="AbortError"||/cancelled/i.test(t.message))}var Mn=2500,am=150,cm=`${D.dim} filter ${D.reset}`,lm="\x1B[?25l",ro="\x1B[?25h";async function um(t,e,n,r={}){let{placeholder:o,store:s}=r,i=new Gt(process.stdout,t),a=!!(process.stdout.isTTY&&process.stdin.isTTY);for(;;){let c=new AbortController,l=0,u,m,d=!1,p=P=>{t.setPrompt(P?cm:e),t.prompt(!0)},y=()=>{d||(d=!0,i.clearPlaceholder(),p(!0),a&&process.stdout.write(lm))},S=(P=!0)=>{d&&(d=!1,P?p(!1):t.setPrompt(e),a&&process.stdout.write(ro),o&&t.line.length===0&&i.showPlaceholder(o))},x=()=>{Ee(t.line)!==null?y():S()},k=P=>{i.setFooter(jo({bypass:r.bypass?.()??!1,exitArmed:P}))},R=()=>{let P=Date.now();if(!(P-l<am)){if(l=P,n.armedAt>0&&P-n.armedAt<=Mn){c.abort(Object.assign(new Error("exit"),{name:"kpilotExit"}));return}n.armedAt=P,i.clear(),S(),o&&i.showPlaceholder(o),setTimeout(()=>k(!0),0),m&&clearTimeout(m),m=setTimeout(()=>{n.armedAt=0,k(!1)},Mn),m.unref?.()}};process.on("SIGINT",R),t.on("SIGINT",R);try{let P=t.question(e,{signal:c.signal});if(i.begin(),k(n.armedAt>0),o&&i.showPlaceholder(o),a){jd(process.stdin);let N=(h,f)=>{if(f){if(f.name==="tab"&&f.shift){let w=r.onShiftTab?.();setTimeout(()=>{k(n.armedAt>0),w&&i.note(w)},0);return}f.name==="return"||f.name==="enter"||f.ctrl&&(f.name==="c"||f.name==="d")||(x(),d||i.syncPlaceholder(),setTimeout(()=>i.paint(),0))}};process.stdin.on("keypress",N),u=()=>process.stdin.off("keypress",N)}let _=await P;S(!1);let I=(_??"").trim();if(!I){i.rewind();continue}return n.armedAt=0,m&&clearTimeout(m),{...s?s.expand(I):{text:I,pasted:!1},display:_??""}}catch{let P=c.signal.reason;if(P instanceof Error&&(P.name==="kpilotExit"||P.message==="exit"))return process.stdout.write(`
|
|
365
|
+
`),null;let _=Date.now();if(n.armedAt>0&&_-n.armedAt<=Mn)return process.stdout.write(`
|
|
366
|
+
`),null;n.armedAt=_,i.clear(),S(),o&&i.showPlaceholder(o),setTimeout(()=>k(!0),0),m&&clearTimeout(m),m=setTimeout(()=>{n.armedAt=0,k(!1)},Mn),m.unref?.();continue}finally{i.end(),i.clearPlaceholder(),S(!1),m&&clearTimeout(m),u?.(),process.removeListener("SIGINT",R),t.removeListener("SIGINT",R)}}}async function dm(t,e,n,r={}){let o=await Ai(e),s=Jn();process.stdout.write(`${s}
|
|
367
|
+
`),o&&process.stdout.write(`${U(D.dim,o)}
|
|
368
|
+
`);let i=Oo(o);r.store?.reset();let a=await um(t,Ht,n,{placeholder:Bn,store:r.store,onShiftTab:r.onShiftTab,bypass:r.bypass});return a===null?(process.stdout.write(`${Io(i)}
|
|
369
|
+
`),null):(process.stdout.write(Do(a.display,{rowsAbove:i,columns:process.stdout.columns})),a)}function ta(t){return t.controlPlaneUrl??process.env.KPILOT_CONTROL_PLANE_URL??"https://api.konsolepilot.ai"}async function mm(t){let e=process.platform,n=e==="darwin"?"open":e==="win32"?"cmd":"xdg-open",r=e==="darwin"?[t]:e==="win32"?["/c","start","",t]:[t];return await new Promise(o=>{let s=Wi(n,r,{stdio:"ignore",detached:!0});s.unref(),s.once("error",()=>o(!1)),s.once("spawn",()=>o(!0))})}async function pm(t){let e=new ie,n=await e.load(),r=new ue(t.controlPlaneUrl??n?.controlPlaneUrl??ta(t),`kpilot/${V}`);if(n?await e.validAccessToken(r):void 0)return;if(!process.stdin.isTTY)throw new Error("kpilot needs an account to continue. Run `kpilot login`.");if($("kpilot needs your account to continue. Starting sign-in\u2026"),await na(t),!await e.load())throw new Error("kpilot needs an account to continue. Run `kpilot login`.")}async function na(t){let e=new ue(ta(t),`kpilot/${V}`),n=new ie,r=await n.load();if(r&&!t.force)throw new Error(`Already signed in as ${r.user.email}. Run \`kpilot logout\` first, or use --force.`);let o=await e.createDeviceCode(),s=o.verification_uri_complete||`${o.verification_uri}?code=${encodeURIComponent(o.user_code)}`,i=t.noBrowser||process.env.KPILOT_NO_BROWSER==="1",a=!1;i||(a=await mm(s)),a?(console.log(`
|
|
370
|
+
Opened ${s}`),console.log(`Confirm code ${U(D.bold,o.user_code)} in your browser if prompted.
|
|
371
|
+
`),$("Approve the device in your browser. Press Ctrl+C to cancel.")):(console.log(`
|
|
372
|
+
Open: ${s}`),console.log(`Code: ${U(D.bold,o.user_code)}
|
|
373
|
+
`),$("Waiting for authorization in your browser. Press Ctrl+C to cancel."));let c=new AbortController,l=()=>c.abort(new Error("Login cancelled."));process.once("SIGINT",l);try{let u=await e.pollDeviceToken(o.device_code,{intervalSeconds:o.interval,expiresInSeconds:o.expires_in,signal:c.signal});await n.save(u),T(`Signed in as ${u.user.email} \xB7 ${u.organization.name}`)}finally{process.removeListener("SIGINT",l)}}async function fm(t){let e=new ie,n=await e.load();if(!n){console.log("Not signed in. Run `kpilot login`.");return}let r=new ue(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${V}`),o=await e.validAccessToken(r);if(!o)throw new Error("Not signed in.");let s=await o.client.profile(o.tokens.accessToken);console.log(`${s.user.name} <${s.user.email}>`),console.log(`Organization: ${s.organization.name} (${s.organization.slug})`),s.device&&console.log(`Device: ${s.device.name}`),console.log(`Control plane: ${o.tokens.controlPlaneUrl}`)}async function gm(t){let e=new ie,n=await e.load();if(!n){console.log("Already signed out.");return}await new ue(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${V}`).logout(n.refreshToken).catch(()=>{}),await e.clear(),T("Signed out and removed local cloud credentials.")}async function hm(t){if(!(t.noCloudSync||process.env.KPILOT_DISABLE_CLOUD_SYNC==="1"))try{let e=new ie,n=await e.load();if(!n)return;let r=new ue(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${V}`),o=await e.validAccessToken(r);if(!o)return;let s=await o.client.checkBudget(o.tokens.accessToken,0);for(let i of s.warnings)A(`Cloud budget: ${i}`);if(!s.allowed)throw new Error(`Cloud budget prevents this run: ${s.violations.join(" ")}`)}catch(e){if(e instanceof Error&&e.message.startsWith("Cloud budget prevents"))throw e;t.debug&&A(`Cloud budget check unavailable: ${e instanceof Error?e.message:String(e)}`)}}async function qi(t){if(t.provider!=="kpilot-hosted"&&!(t.cli.noCloudSync||process.env.KPILOT_DISABLE_CLOUD_SYNC==="1"))try{let e=new ie,n=await e.load();if(!n)return;let r=new ue(t.cli.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${V}`),o=await e.validAccessToken(r);if(!o)return;let s=Ji("sha256").update(L.resolve(t.cli.cwd)).digest("hex").slice(0,32);await o.client.ingestUsage(o.tokens.accessToken,[{eventId:t.record.id,occurredAt:t.record.timestamp,projectFingerprint:s,...t.record.sessionId?{sessionId:t.record.sessionId}:{},provider:t.provider,model:t.record.model,inputTokens:t.record.inputTokens,outputTokens:t.record.outputTokens,estimatedCostUsd:t.record.estimatedCostUsd,durationMs:Math.max(0,Math.trunc(t.durationMs)),success:t.success}])}catch(e){t.cli.debug&&A(`Cloud usage sync failed: ${e instanceof Error?e.message:String(e)}`)}}async function wm(t){if(!t.prompt)throw new Error("Provide a prompt, or use `kpilot`.");await G(t.cwd);let e=await we(t.cwd),n=oe(t.cwd),r=nt(t,e,await n.policy.load()),o=await rm(t,n.sessions,r);t.mode||(t.mode=o.mode);let s=await Xr(t,e,o),i=process.stdin.isTTY?Gi({input:process.stdin,output:process.stdout}):void 0;try{console.log(qt(s.settings.mode,s.settings.showModel?s.settings.model:void 0,o.title,{bypass:t.bypassPermissions}));try{let a=await to(c=>no({cli:t,created:s,services:n,session:o,prompt:t.prompt,approvalHandler:Yi(t,i?l=>i.question(l):void 0,zi(i)),bypassPermissions:t.bypassPermissions,signal:c}));a.streamed||console.log(`${On(s.settings.showModel?s.settings.model:void 0)} \u203A ${a.answer}`),$(`Resume with: kpilot chat --session ${o.id.slice(0,8)} \xB7 ${o.title}`)}catch(a){if(!it(a))throw a;o.messages=[...s.agent.messages],await n.sessions.save(o),st();let c=ct.stopReason;A(c==="Esc"?"Stopped with Esc.":"Stopped."),$(`Nothing else was run. Resume with: kpilot chat --session ${o.id.slice(0,8)} \xB7 ${o.title}`),process.exitCode=130}}finally{i?.close(),await s.close()}}function ra(t){let e=t?.trim().toLowerCase();if(e==="accept")return"accepted";if(e==="reject")return"rejected";if(e==="edit")return"edited";if(e==="accepted"||e==="rejected"||e==="edited")return e;throw new Error("Feedback outcome must be accepted, rejected, or edited.")}async function oa(t){let e=t.session.runs.at(-1);if(!e)throw new Error("The selected session has no completed run to evaluate.");let n=t.outcome==="edited"?await _n(t.runtime,t.rootDir,t.mode):e.diffAfter,r=await t.services.preferences.learn({outcome:t.outcome,task:e.prompt,note:t.note,sessionId:t.session.id,proposedDiff:e.diffAfter,finalDiff:n});if(T(`Recorded ${t.outcome} feedback for ${t.session.title}.`),r.learned.length===0)$("No durable rule was inferred. Add a concrete note to teach an explicit preference.");else for(let o of r.learned)$(`${o.polarity}: ${o.text} (${Math.round(o.confidence*100)}%)`)}async function ym(t){await G(t.cwd);let e=oe(t.cwd).sessions,n=t.args[0]??"list";if(n==="list"){im(await e.list());return}let r=t.args[1]??t.session;if(!r)throw new Error(`sessions ${n} requires a session ID.`);if(n==="show"){let o=await e.load(r);console.log(JSON.stringify(o,null,2));return}if(n==="delete"){await e.delete(r),T(`Deleted session ${r}.`);return}throw new Error(`Unknown sessions action: ${n}`)}async function bm(t){await G(t.cwd);let e=oe(t.cwd).memory,n=t.args[0]??"list";if(n==="list"){Zi(await e.list());return}if(n==="add"){let r=await e.add(t.args.slice(1).join(" "));T(`Remembered ${r.id.slice(0,8)}: ${r.text}`);return}if(n==="remove"){let r=t.args[1];if(!r)throw new Error("memory remove requires an entry ID.");let o=await e.remove(r);T(`Removed memory: ${o.text}`);return}if(n==="clear"){let r=await e.clear();T(`Removed ${r} memory entr${r===1?"y":"ies"}.`);return}throw new Error(`Unknown memory action: ${n}`)}async function vm(t){await G(t.cwd);let e=oe(t.cwd).skills,n=t.args[0]??"list";if(n==="list"){ea(await e.list());return}if(n==="show"){let r=t.args[1];if(!r)throw new Error("skills show requires a skill name.");let o=await e.get(r);console.log(`${o.name} (${o.source})
|
|
374
|
+
${o.description}
|
|
375
|
+
|
|
376
|
+
${o.instructions}
|
|
320
377
|
|
|
321
|
-
${r.filePath}`);return}throw new Error(`Unknown skills action: ${n}`)}async function cu(t){await L(t.cwd);let e=z(t.cwd).preferences,n=t.args[0]??"list";if(n==="list"){let o=await e.listRules();o.length===0&&console.log("[no learned preferences]");for(let r of o)console.log(`${r.id.slice(0,8)} ${String(Math.round(r.confidence*100)).padStart(3)}% ${r.polarity.padEnd(6)} ${r.text}`);return}if(n==="remove"){let o=t.args[1];if(!o)throw new Error("preferences remove requires a rule ID.");let r=await e.removeRule(o);v(`Removed preference: ${r.text}`);return}throw new Error(`Unknown preferences action: ${n}`)}async function lu(t){await L(t.cwd);let e=await oe(t.cwd),n=z(t.cwd),o=await n.policy.load(),r=Le(t,e,o),s=await n.sessions.list(),i=t.session??s[0]?.id;if(!i)throw new Error("No session exists. Pass --session after completing an agent run.");let a=await n.sessions.load(i),c=new ae(t.cwd,{sandbox:e.sandbox});await _s({outcome:$s(t.args[0]),note:t.note??(t.args.slice(1).join(" ").trim()||void 0),session:a,services:n,runtime:c,mode:r.mode,rootDir:t.cwd})}async function uu(t){if(t.args[0]==="serve"){await du(t);return}await L(t.cwd);let e=await oe(t.cwd),n=await new ke(t.cwd).load(),o=e.mcp?.servers??{},r=Object.entries(o).filter(([i,a])=>a.enabled!==!1&&(!n?.allowedMcpServers||n.allowedMcpServers.includes(i)));if(r.length===0){console.log("[no enabled MCP servers]");return}let s=await we.connect(Object.fromEntries(r));try{let i=s.list();i.length===0&&console.log("[MCP servers exposed no tools]");for(let a of i)console.log(`${a.exposedName.padEnd(38)} ${a.server.padEnd(16)} ${a.description}`)}finally{await s.close()}}async function du(t){await L(t.cwd);let e=await oe(t.cwd),n=await new ke(t.cwd).load(),o=new ae(t.cwd,{sandbox:e.sandbox,browser:dr(e)}),r=e.mcp?.servers??{},s=n?.allowedMcpServers?Object.fromEntries(Object.entries(r).filter(([l])=>n.allowedMcpServers.includes(l))):r,i=Object.values(s).some(l=>l.enabled!==!1)?await we.connect(s):void 0,a=new Ze([o,i]);P(`Serving kpilot MCP server on stdio (${a.definitions().length} tools).`);let c=new $t(a,{name:"kpilot",version:B,rootDir:t.cwd,mode:t.mode??"write"});try{await so(c)}finally{await i?.close()}}function As(t){for(let e of t){let n=e.managed?e.name??"[managed]":"[external]",o=e.branch??(e.detached?"[detached]":"[no branch]");console.log(`${n.padEnd(18)} ${o.padEnd(32)} ${e.path}`)}}async function mu(t){await L(t.cwd);let e=new at(t.cwd),n=t.args[0]??"list";if(n==="list"){As(await e.list());return}if(n==="create"){let o=t.args[1];if(!o)throw new Error("worktrees create requires a name.");let r=await e.create(o,{base:t.args[2],branch:t.args[3]});v(`Created worktree ${r.name??o} on ${r.branch??"[detached]"}.`),console.log(r.path);return}if(n==="remove"){let o=t.args[1];if(!o)throw new Error("worktrees remove requires a name.");await e.remove(o,t.force),v(`Removed worktree ${o}.`);return}if(n==="prune"){await e.prune(),v("Pruned stale Git worktree metadata.");return}throw new Error(`Unknown worktrees action: ${n}`)}async function pu(t){await L(t.cwd);let e=z(t.cwd),n=t.args[0]??"show";if(n==="show"){let o=await e.policy.load();console.log(o?JSON.stringify(o,null,2):"[no team policy]");return}if(n==="init"){let o=await oe(t.cwd),r=t.model??process.env.KPILOT_MODEL??o.model?.model,s=await e.policy.initialize(t.organization,r?[r]:[]);await e.audit.append({action:"policy.init",outcome:"success",category:"administration",details:{organization:s.organization??"",allowedModels:s.allowedModels??[]}}),v(`Created ${_.relative(t.cwd,e.policy.filePath)}.`),r||R("No model was configured, so allowedModels is empty. Add approved model names before running the agent.");return}if(n==="validate"){if(!await e.policy.load())throw new Error("No team policy exists. Run `kpilot policy init`.");v("Team policy is valid.");return}throw new Error(`Unknown policy action: ${n}`)}function fr(t){console.log(`date: ${t.date}`),console.log(`runs: ${t.runs}`),console.log(`input tokens: ${je(t.inputTokens)}`),console.log(`output tokens: ${je(t.outputTokens)}`),console.log(`total tokens: ${je(t.totalTokens)}`),console.log(`estimated cost: $${t.estimatedCostUsd.toFixed(6)}`)}async function fu(t){await L(t.cwd);let e=await oe(t.cwd),n=z(t.cwd),o=await n.policy.load(),r=Xt(e.usage?.budget,o?.usage),s=t.args[0]??"summary";if(s==="summary"){fr(await n.usage.summarize(t.args[1]));return}if(s==="list"){let i=await n.usage.list(t.limit);i.length===0&&console.log("[no usage records]");for(let a of i)console.log(`${a.timestamp} ${a.model.padEnd(24)} ${je(a.totalTokens).padStart(8)} tokens $${a.estimatedCostUsd.toFixed(6)} ${a.sessionId?.slice(0,8)??"-"}`);return}if(s==="check"){let i=await n.usage.check(r);fr(i.summary);for(let a of i.warnings)R(a);if(!i.allowed)throw new Error(i.violations.join(" "));v("Usage budget allows another run.");return}throw new Error(`Unknown usage action: ${s}`)}async function gu(t){await L(t.cwd);let e=z(t.cwd).audit,n=t.args[0]??"list";if(n==="list"){let o=await e.list(t.limit);o.length===0&&console.log("[no audit records]");for(let r of o)console.log(`${r.timestamp} ${r.outcome.padEnd(9)} ${r.action.padEnd(24)} ${r.actor}@${r.host} ${r.sessionId?.slice(0,8)??"-"}`);return}if(n==="verify"){let o=await e.verify();if(!o.valid)throw new Error(`Audit verification failed at line ${o.firstInvalidLine??"?"}: ${o.reason??"unknown reason"}`);v(`Audit chain is valid: ${o.records} record(s), head ${o.headHash.slice(0,16)}.`);return}throw new Error(`Unknown audit action: ${n}`)}async function hu(t){await L(t.cwd);let e=t.args[0],n=t.args[1];if(!e||!n)throw new Error("sync requires an action and bundle path.");let o=new Kt(t.cwd),r=z(t.cwd).audit;if(e==="inspect"){console.log(JSON.stringify(await o.inspectBundle(n),null,2));return}let s=process.env[t.passphraseEnv];if(!s)throw new Error(`${t.passphraseEnv} is not set.`);if(e==="export"){let i=await o.exportBundle(n,s,t.includeSessions);await r.append({action:"sync.export",outcome:"success",category:"synchronization",details:{destination:_.resolve(n),includeSessions:i.includeSessions}}),v(`Encrypted sync bundle written to ${_.resolve(n)}.`);return}if(e==="import"){let i=await o.importBundle(n,s,t.overwrite);await r.append({action:"sync.import",outcome:"success",category:"synchronization",details:{source:_.resolve(n),imported:i.imported.length,skipped:i.skipped.length,overwrite:t.overwrite}}),v(`Imported ${i.imported.length} file(s); skipped ${i.skipped.length}.`);for(let a of i.skipped.slice(0,10))R(`Skipped existing file: ${a}`);return}throw new Error(`Unknown sync action: ${e}`)}async function Os(t){await L(t.cwd);let e=t.args[0]??"status";if(e!=="status")throw new Error(`Unknown admin action: ${e}`);let n=await oe(t.cwd),o=z(t.cwd),r=await o.policy.load(),s=await o.usage.check(Xt(n.usage?.budget,r?.usage)),i=await o.audit.verify();if(console.log($(M.bold,"kpilot administration status")),console.log(`project: ${t.cwd}`),console.log(`policy: ${r?`enabled${r.organization?` (${r.organization})`:""}`:"not configured"}`),console.log(`usage: ${s.allowed?"allowed":"blocked"}; ${je(s.summary.totalTokens)} token(s) today`),console.log(`audit: ${i.valid?"valid":"invalid"}; ${i.records} record(s)`),console.log(`sessions: ${(await o.sessions.list()).length}`),console.log(`skills: ${(await o.skills.list()).length}`),console.log(`preferences: ${(await o.preferences.listRules()).length}`),s.warnings.length)for(let a of s.warnings)R(a);if(!s.allowed)for(let a of s.violations)F(a);i.valid||F(i.reason??"Audit chain invalid.")}async function wu(t){if(t.cli.session)return await t.store.load(t.cli.session);if(t.cli.yes)return await t.store.create({title:t.cli.title,mode:t.settings.mode,model:t.settings.model});if((await t.store.list()).length===0)return await t.store.create({title:t.cli.title,mode:t.settings.mode,model:t.settings.model});let n=await tn({store:t.store,question:t.question,pauseResume:t.pauseResume,title:"Re-open a session, or start fresh?",includeFresh:!0,prefer:"recent"});return n.kind==="cancel"?null:n.kind==="session"?n.session:await t.store.create({title:t.cli.title,mode:t.settings.mode,model:t.settings.model})}async function yu(t){if(!process.stdin.isTTY)throw new Error("Interactive chat requires a TTY.");await L(t.cwd);let e=await oe(t.cwd),n=z(t.cwd),o=Le(t,e,await n.policy.load()),r=vs({input:process.stdin,output:process.stdout}),s=u=>r.question(u),i=xs(r),a,c,l=!1;try{let u=await wu({cli:t,store:n.sessions,settings:o,question:s,pauseResume:i});if(!u){P("Cancelled.");return}a=u,t.session=a.id,t.mode||(t.mode=a.mode),c=await mr(t,e,a),l=!0;let d=Ps(t,s,i);console.log($(M.bold,"kpilot persistent interactive session")),P(`${c.settings.mode.toUpperCase()} mode \xB7 kpilot \xB7 ${t.cwd}`),console.log(xt(c.settings.mode,c.settings.model,a.id.slice(0,8))),P(`Session ${a.id.slice(0,8)} \xB7 ${a.title}`),console.log($(M.dim,"Use / for arrow-key commands (or /help). \u2191/\u2193 \xB7 Enter \xB7 Esc. Press Ctrl+C twice to exit."));let p=async()=>{await c.close();let m=await oe(t.cwd);o=Le(t,m,await n.policy.load()),c=await mr(t,m,a)},b=async m=>{a.messages=[...c.agent.messages],await n.sessions.save(a),a=m,t.session=a.id,t.mode=a.mode,await p(),v(`Switched to ${a.id.slice(0,8)} \xB7 ${a.title}`)},f=async(m,g)=>{try{let h=await yr(w=>br({cli:t,created:c,services:n,session:a,prompt:m,approvalHandler:d,skill:g,signal:w}));h.streamed||(de(),console.log(`${wr(c.settings.model)} \u203A ${h.answer}`)),console.log($(M.dim,`saved \xB7 session ${a.id.slice(0,8)}`))}catch(h){if(!vr(h))throw h;a.messages=[...c.agent.messages],await n.sessions.save(a),R("Run cancelled; partial conversation state was saved.")}};await Kl({cli:t,created:c,services:n,session:a,approvalHandler:d,question:s,pauseResume:i});let y={armedAt:0};for(;;){let m=await Xl(r,t.cwd,y);if(m===null)break;if(m){if(nn(m))break;if(m==="/"||El(m)){let g=m,h=await n.skills.list().catch(()=>[]);if(!(g!=="/"&&h.some(k=>k.name===g.slice(1)))){let k=await Rl({question:s,pauseResume:i,skillNames:h.map(C=>C.name),initialQuery:g==="/"?"":g.slice(1)});if(!k)continue;m=k}}if(nn(m))break;if(m==="/help"){Cl();continue}if(m==="/learn"||m.startsWith("/learn ")){let g=m.slice(6).trim().toLowerCase();if(!g){let k=await G({title:"/learn \u2014 choose an action:",question:s,pauseResume:i,choices:[{value:"status",label:"status",description:"Show learning state and facts",default:!0},{value:"on",label:"on",description:"Enable continuous learning"},{value:"off",label:"off",description:"Disable continuous learning"}]});if(!k)continue;g=k}if(g==="on"||g==="enable"){await pt(t.cwd,!0),v("Logbook learning on. New durable facts append to .kpilot/logbook/learnings.md after chats.");continue}if(g==="off"||g==="disable"){await pt(t.cwd,!1),v("Logbook learning off for this project.");continue}let h=await mt(t.cwd),w=await sr(t.cwd);console.log(h?"Logbook learning: on":"Logbook learning: off"),console.log(w?`Learnings:
|
|
322
|
-
|
|
378
|
+
${o.filePath}`);return}throw new Error(`Unknown skills action: ${n}`)}async function km(t){await G(t.cwd);let e=oe(t.cwd).preferences,n=t.args[0]??"list";if(n==="list"){let r=await e.listRules();r.length===0&&console.log("[no learned preferences]");for(let o of r)console.log(`${o.id.slice(0,8)} ${String(Math.round(o.confidence*100)).padStart(3)}% ${o.polarity.padEnd(6)} ${o.text}`);return}if(n==="remove"){let r=t.args[1];if(!r)throw new Error("preferences remove requires a rule ID.");let o=await e.removeRule(r);T(`Removed preference: ${o.text}`);return}throw new Error(`Unknown preferences action: ${n}`)}async function xm(t){await G(t.cwd);let e=await we(t.cwd),n=oe(t.cwd),r=await n.policy.load(),o=nt(t,e,r),s=await n.sessions.list(),i=t.session??s[0]?.id;if(!i)throw new Error("No session exists. Pass --session after completing an agent run.");let a=await n.sessions.load(i),c=new be(t.cwd,{sandbox:e.sandbox});await oa({outcome:ra(t.args[0]),note:t.note??(t.args.slice(1).join(" ").trim()||void 0),session:a,services:n,runtime:c,mode:o.mode,rootDir:t.cwd})}async function Sm(t){if(t.args[0]==="serve"){await Tm(t);return}await G(t.cwd);let e=await we(t.cwd),n=await new je(t.cwd).load(),r=e.mcp?.servers??{},o=Object.entries(r).filter(([i,a])=>a.enabled!==!1&&(!n?.allowedMcpServers||n.allowedMcpServers.includes(i)));if(o.length===0){console.log("[no enabled MCP servers]");return}let s=await Ae.connect(Object.fromEntries(o));try{let i=s.list();i.length===0&&console.log("[MCP servers exposed no tools]");for(let a of i)console.log(`${a.exposedName.padEnd(38)} ${a.server.padEnd(16)} ${a.description}`)}finally{await s.close()}}async function Tm(t){await G(t.cwd);let e=await we(t.cwd),n=await new je(t.cwd).load(),r=new be(t.cwd,{sandbox:e.sandbox,browser:Qr(e)}),o=e.mcp?.servers??{},s=n?.allowedMcpServers?Object.fromEntries(Object.entries(o).filter(([l])=>n.allowedMcpServers.includes(l))):o,i=Object.values(s).some(l=>l.enabled!==!1)?await Ae.connect(s):void 0,a=new xt([r,i]);$(`Serving kpilot MCP server on stdio (${a.definitions().length} tools).`);let c=new cn(a,{name:"kpilot",version:V,rootDir:t.cwd,mode:t.mode??"write"});try{await Ts(c)}finally{await i?.close()}}function sa(t){for(let e of t){let n=e.managed?e.name??"[managed]":"[external]",r=e.branch??(e.detached?"[detached]":"[no branch]");console.log(`${n.padEnd(18)} ${r.padEnd(32)} ${e.path}`)}}async function Pm(t){await G(t.cwd);let e=new $t(t.cwd),n=t.args[0]??"list";if(n==="list"){sa(await e.list());return}if(n==="create"){let r=t.args[1];if(!r)throw new Error("worktrees create requires a name.");let o=await e.create(r,{base:t.args[2],branch:t.args[3]});T(`Created worktree ${o.name??r} on ${o.branch??"[detached]"}.`),console.log(o.path);return}if(n==="remove"){let r=t.args[1];if(!r)throw new Error("worktrees remove requires a name.");await e.remove(r,t.force),T(`Removed worktree ${r}.`);return}if(n==="prune"){await e.prune(),T("Pruned stale Git worktree metadata.");return}throw new Error(`Unknown worktrees action: ${n}`)}async function Em(t){await G(t.cwd);let e=oe(t.cwd),n=t.args[0]??"show";if(n==="show"){let r=await e.policy.load();console.log(r?JSON.stringify(r,null,2):"[no team policy]");return}if(n==="init"){let r=await we(t.cwd),o=t.model??process.env.KPILOT_MODEL??r.model?.model,s=await e.policy.initialize(t.organization,o?[o]:[]);await e.audit.append({action:"policy.init",outcome:"success",category:"administration",details:{organization:s.organization??"",allowedModels:s.allowedModels??[]}}),T(`Created ${L.relative(t.cwd,e.policy.filePath)}.`),o||A("No model was configured, so allowedModels is empty. Add approved model names before running the agent.");return}if(n==="validate"){if(!await e.policy.load())throw new Error("No team policy exists. Run `kpilot policy init`.");T("Team policy is valid.");return}throw new Error(`Unknown policy action: ${n}`)}function Zr(t){console.log(`date: ${t.date}`),console.log(`runs: ${t.runs}`),console.log(`input tokens: ${de(t.inputTokens)}`),console.log(`output tokens: ${de(t.outputTokens)}`),console.log(`total tokens: ${de(t.totalTokens)}`),console.log(`estimated cost: $${t.estimatedCostUsd.toFixed(6)}`)}async function Rm(t){await G(t.cwd);let e=await we(t.cwd),n=oe(t.cwd),r=await n.policy.load(),o=An(e.usage?.budget,r?.usage),s=t.args[0]??"summary";if(s==="summary"){Zr(await n.usage.summarize(t.args[1]));return}if(s==="list"){let i=await n.usage.list(t.limit);i.length===0&&console.log("[no usage records]");for(let a of i)console.log(`${a.timestamp} ${a.model.padEnd(24)} ${de(a.totalTokens).padStart(8)} tokens $${a.estimatedCostUsd.toFixed(6)} ${a.sessionId?.slice(0,8)??"-"}`);return}if(s==="check"){let i=await n.usage.check(o);Zr(i.summary);for(let a of i.warnings)A(a);if(!i.allowed)throw new Error(i.violations.join(" "));T("Usage budget allows another run.");return}throw new Error(`Unknown usage action: ${s}`)}async function Cm(t){await G(t.cwd);let e=oe(t.cwd).audit,n=t.args[0]??"list";if(n==="list"){let r=await e.list(t.limit);r.length===0&&console.log("[no audit records]");for(let o of r)console.log(`${o.timestamp} ${o.outcome.padEnd(9)} ${o.action.padEnd(24)} ${o.actor}@${o.host} ${o.sessionId?.slice(0,8)??"-"}`);return}if(n==="verify"){let r=await e.verify();if(!r.valid)throw new Error(`Audit verification failed at line ${r.firstInvalidLine??"?"}: ${r.reason??"unknown reason"}`);T(`Audit chain is valid: ${r.records} record(s), head ${r.headHash.slice(0,16)}.`);return}throw new Error(`Unknown audit action: ${n}`)}async function Mm(t){await G(t.cwd);let e=t.args[0],n=t.args[1];if(!e||!n)throw new Error("sync requires an action and bundle path.");let r=new xn(t.cwd),o=oe(t.cwd).audit;if(e==="inspect"){console.log(JSON.stringify(await r.inspectBundle(n),null,2));return}let s=process.env[t.passphraseEnv];if(!s)throw new Error(`${t.passphraseEnv} is not set.`);if(e==="export"){let i=await r.exportBundle(n,s,t.includeSessions);await o.append({action:"sync.export",outcome:"success",category:"synchronization",details:{destination:L.resolve(n),includeSessions:i.includeSessions}}),T(`Encrypted sync bundle written to ${L.resolve(n)}.`);return}if(e==="import"){let i=await r.importBundle(n,s,t.overwrite);await o.append({action:"sync.import",outcome:"success",category:"synchronization",details:{source:L.resolve(n),imported:i.imported.length,skipped:i.skipped.length,overwrite:t.overwrite}}),T(`Imported ${i.imported.length} file(s); skipped ${i.skipped.length}.`);for(let a of i.skipped.slice(0,10))A(`Skipped existing file: ${a}`);return}throw new Error(`Unknown sync action: ${e}`)}async function ia(t){await G(t.cwd);let e=t.args[0]??"status";if(e!=="status")throw new Error(`Unknown admin action: ${e}`);let n=await we(t.cwd),r=oe(t.cwd),o=await r.policy.load(),s=await r.usage.check(An(n.usage?.budget,o?.usage)),i=await r.audit.verify();if(console.log(U(D.bold,"kpilot administration status")),console.log(`project: ${t.cwd}`),console.log(`policy: ${o?`enabled${o.organization?` (${o.organization})`:""}`:"not configured"}`),console.log(`usage: ${s.allowed?"allowed":"blocked"}; ${de(s.summary.totalTokens)} token(s) today`),console.log(`audit: ${i.valid?"valid":"invalid"}; ${i.records} record(s)`),console.log(`sessions: ${(await r.sessions.list()).length}`),console.log(`skills: ${(await r.skills.list()).length}`),console.log(`preferences: ${(await r.preferences.listRules()).length}`),s.warnings.length)for(let a of s.warnings)A(a);if(!s.allowed)for(let a of s.violations)J(a);i.valid||J(i.reason??"Audit chain invalid.")}async function $m(t){if(t.cli.session)return await t.store.load(t.cli.session);if(t.cli.yes)return await t.store.create({title:t.cli.title,mode:t.settings.mode,model:t.settings.model});if((await t.store.list()).length===0)return await t.store.create({title:t.cli.title,mode:t.settings.mode,model:t.settings.model});let n=await Dn({store:t.store,question:t.question,pauseResume:t.pauseResume,title:"Re-open a session, or start fresh?",includeFresh:!0,prefer:"recent"});return n.kind==="cancel"?null:n.kind==="session"?n.session:await t.store.create({title:t.cli.title,mode:t.settings.mode,model:t.settings.model})}async function _m(t){if(!process.stdin.isTTY)throw new Error("Interactive chat requires a TTY.");await G(t.cwd);let e=await we(t.cwd),n=oe(t.cwd),r=nt(t,e,await n.policy.load()),o=Gi({input:process.stdin,output:process.stdout}),s=S=>o.question(S),i=zi(o),a=new Kt,c=new Wt(o,process.stdin,a,{prepare:Ro,placeholder:Bn});c.attach();let l=new Jt(o,{input:process.stdin,output:process.stdout});l.setEntries(Li()),l.attach();let u={bypass:t.bypassPermissions},m=()=>(u.bypass=!u.bypass,yo(u.bypass));process.stdout.isTTY&&process.stdout.write(Po);let d,p,y=!1;try{let S=await $m({cli:t,store:n.sessions,settings:r,question:s,pauseResume:i});if(!S){$("Cancelled.");return}d=S,t.session=d.id,t.mode||(t.mode=d.mode),p=await Xr(t,e,d),y=!0;let x=Yi(t,s,i);console.log(qt(p.settings.mode,p.settings.showModel?p.settings.model:void 0,d.title,{bypass:u.bypass})),console.log(U(D.dim,`${t.cwd} \xB7 ${d.title}`));let k=async()=>{await p.close();let I=await we(t.cwd);r=nt(t,I,await n.policy.load()),p=await Xr(t,I,d)},R=async I=>{d.messages=[...p.agent.messages],await n.sessions.save(d),d=I,t.session=d.id,t.mode=d.mode,await k(),T(`Switched to ${d.title}`)},P=async(I,j)=>{let N,h=Date.now();try{let f=p.settings.mode==="plan",w=await to(g=>no({cli:t,created:p,services:n,session:d,prompt:I,approvalHandler:x,bypassPermissions:u.bypass,skill:j,signal:g,onDiffBefore:b=>{N=b}}));if(w.streamed||(ot(),console.log(`${On(p.settings.showModel?p.settings.model:void 0)} \u203A ${w.answer}`)),w.tokensUsed>0&&console.log(U(D.dim,`saved \xB7 ${d.title}`)),f&&w.answer.trim()&&process.stdin.isTTY){let g=Ko(t.cwd,I);await et(L.dirname(g),{recursive:!0}),await ke(g,`${w.answer.trim()}
|
|
379
|
+
`,"utf8");let b=L.relative(t.cwd,g);$(`Plan saved to ${b}`),await Q({title:"Proceed to implement this plan in write mode?",question:s,pauseResume:i,choices:[{value:"yes",label:"yes",description:"Switch to write mode and implement",default:!0},{value:"no",label:"no",description:"Stay in plan mode"}]})==="yes"&&(t.mode="write",d.mode="write",await n.sessions.save(d),await k(),T("Switched to WRITE mode. Implementing the plan\u2026"),await P(`Implement the plan in ${b}. Follow it step by step and verify your changes.`))}}catch(f){if(!it(f))throw f;d.messages=[...p.agent.messages],await n.sessions.save(d),st();let w=ct.stopReason,g=Math.max(1,Math.round((Date.now()-h)/1e3));A(w==="Esc"?`Stopped with Esc after ${g}s. Your request is kept and will be answered next.`:`Stopped after ${g}s. Your request is kept and will be answered next.`);let b=await _n(p.localRuntime,t.cwd,p.settings.mode),v=b!==N,O=!N||!N.trim(),H=v?Hn(b??""):[];if(!process.stdin.isTTY)return;let ce=[{value:"prompt",label:"Back to the prompt",description:"Nothing else runs \u2014 tell me what to change",default:!0},{value:"continue",label:"Continue where it stopped",description:"Resume without redoing finished work"}];O&&H.length>0&&ce.push({value:"undo",label:"Undo this run's changes",description:`Revert ${H.length} file(s) to the last commit`}),p.settings.mode==="write"&&ce.push({value:"plan",label:"Switch to plan mode",description:"Rethink and propose a plan before editing"});let te=await Q({title:"What would you like to do instead?",question:s,pauseResume:i,choices:ce});if(te==="undo"){let ye=await Fi(p.runtime,t.cwd,H);ye.ok?T(`Reverted ${H.length} file(s) to the last commit.`):J(`Undo failed: ${ye.output.slice(0,300)}`);return}if(te==="plan"){t.mode="plan",d.mode="plan",await n.sessions.save(d),await k(),T("Switched to PLAN mode. Describe what you want instead.");return}te==="continue"&&await P(Zo)}};await tm({cli:t,created:p,services:n,session:d,approvalHandler:x,question:s,pauseResume:i});let _={armedAt:0};for(;;){let I=await n.skills.list().catch(()=>[]);l.setEntries(Li(I.map(f=>f.name)));let j=await dm(o,t.cwd,_,{store:a,onShiftTab:m,bypass:()=>u.bypass});if(j===null)break;let N=j.pasted,h=j.text;if(h){if(!N&&jn(h))break;if(!N&&(h==="/"||Ud(h))){let f=h,w=l.takeSelection();if(w)h=`/${w}`;else{let g=await n.skills.list().catch(()=>[]);if(!(f!=="/"&&g.some(v=>v.name===f.slice(1)))){let v=await Fd({question:s,pauseResume:i,skillNames:g.map(O=>O.name),initialQuery:f==="/"?"":f.slice(1)});if(!v)continue;h=v}}}if(!N&&jn(h))break;if(h==="/help"){Nd();continue}if(h==="/learn"||h.startsWith("/learn ")){let f=h.slice(6).trim().toLowerCase();if(!f){let b=await Q({title:"/learn \u2014 choose an action:",question:s,pauseResume:i,choices:[{value:"status",label:"status",description:"Show learning state and facts",default:!0},{value:"on",label:"on",description:"Enable continuous learning"},{value:"off",label:"off",description:"Disable continuous learning"}]});if(!b)continue;f=b}if(f==="on"||f==="enable"){await Dt(t.cwd,!0),T("Logbook learning on. New durable facts append to .kpilot/logbook/learnings.md after chats.");continue}if(f==="off"||f==="disable"){await Dt(t.cwd,!1),T("Logbook learning off for this project.");continue}let w=await It(t.cwd),g=await Gr(t.cwd);console.log(w?"Logbook learning: on":"Logbook learning: off"),console.log(g?`Learnings:
|
|
380
|
+
${g}`:"Learnings: (none yet)");continue}if(h==="/logbook"||h.startsWith("/logbook ")||h==="/understand"||h.startsWith("/understand ")){let w=(h.startsWith("/logbook")?h.slice(8):h.slice(11)).trim().toLowerCase();if(!w&&h==="/logbook"){let g=await Q({title:"/logbook \u2014 choose an action:",question:s,pauseResume:i,choices:[{value:"capture",label:"capture",description:"Inspect repo and write project.md",default:!0},{value:"skip",label:"skip",description:"Do not auto-offer Logbook again"}]});if(!g)continue;w=g==="capture"?"":g}if(w==="skip"){await Jr(t.cwd),T("Will not auto-offer Logbook capture again. Run /logbook to build it later.");continue}await Kr(t.cwd),await Qi({cli:t,created:p,services:n,session:d,approvalHandler:x});continue}if(h==="/save"){d.messages=[...p.agent.messages],await n.sessions.save(d),T(`Saved ${d.title}.`);continue}if(h==="/undo"){let f=d.runs.at(-1);if(!f){A("No completed run to undo.");continue}let w=Hn(f.diffAfter??"");if(w.length===0){A("Last run did not change any tracked files.");continue}let g=await Fi(p.runtime,t.cwd,w);g.ok?(T(`Undid ${w.length} file(s) from the last run.`),$(w.join(" "))):J(`Undo failed: ${g.output.slice(0,300)}`);continue}if(h==="/clear"){p.agent.reset(),d.messages=[],await n.sessions.save(d),T("Conversation history cleared; run history remains available for feedback.");continue}if(h==="/compact"){try{let f=await p.agent.compact();d.messages=[...p.agent.messages],await n.sessions.save(d),f.after<f.before?T(`Compacted context: ${f.before} \u2192 ${f.after} messages.`):$("Nothing to compact yet.")}catch(f){J(`Compaction failed: ${f instanceof Error?f.message:String(f)}`)}continue}if(h==="/cost"){let f=d.runs,w=f.reduce((g,b)=>({inputTokens:g.inputTokens+(b.usage?.inputTokens??0),outputTokens:g.outputTokens+(b.usage?.outputTokens??0),costUsd:g.costUsd+(b.usage?.estimatedCostUsd??0)}),{inputTokens:0,outputTokens:0,costUsd:0});console.log(U(D.bold,"Session cost")),console.log(` runs: ${f.length}`),console.log(` input: ${de(w.inputTokens)} tokens`),console.log(` output: ${de(w.outputTokens)} tokens`),console.log(` est: $${w.costUsd.toFixed(6)}`),$("Automatic routing picks the cheapest capable model; prompt caching reuses earlier context.");continue}if(h==="/context"){let f=[...p.agent.messages],w=f.reduce((O,H)=>{let ce=typeof H.content=="string"?H.content:"",te=H.role==="assistant"?(H.tool_calls??[]).map(ye=>ye.function.arguments).join(""):"";return O+ce.length+te.length},0),g=Math.ceil(w/4),b=Xi(p.settings.provider),v=b?Math.round(g/b*100):void 0;console.log(U(D.bold,"Conversation context")),console.log(` messages: ${f.length}`),console.log(` approx: ~${de(g)} tokens`),b&&v!==void 0&&console.log(` window: ${de(b)} (${Math.min(100,v)}% used)`),v!==void 0&&v>=80?A("Context is nearly full \u2014 run /compact to summarize history."):$("Use /compact to summarize history when it grows large.");continue}if(h==="/checkpoint"||h.startsWith("/checkpoint ")){let f=h.slice(11).trim(),[w="list",...g]=f?f.split(/\s+/):["list"];try{if(w==="save"||w==="s"){let b=await n.checkpoints.save(d.id,[...p.agent.messages],g.join(" "));T(`Checkpoint ${b.id.slice(0,8)} saved (${b.messages.length} messages).`)}else if(w==="restore"||w==="r"){let b=g[0];if(!b){A("Usage: /checkpoint restore <id>");continue}let v=await n.checkpoints.load(d.id,b);p.agent.restore(v.messages),d.messages=[...p.agent.messages],await n.sessions.save(d),T(`Restored checkpoint ${v.id.slice(0,8)} (${v.messages.length} messages).`)}else if(w==="remove"||w==="rm"){let b=g[0];if(!b){A("Usage: /checkpoint remove <id>");continue}await n.checkpoints.remove(d.id,b),T(`Removed checkpoint ${b}.`)}else{let b=await n.checkpoints.list(d.id);b.length===0&&console.log("[no checkpoints]");for(let v of b)console.log(`${v.id.slice(0,8)} ${v.createdAt} ${v.label}`)}}catch(b){J(b instanceof Error?b.message:String(b))}continue}if(h==="/mode"||h.startsWith("/mode ")){let f=h==="/mode"?"":h.slice(6).trim();if(!f){let w=await Q({title:"/mode \u2014 choose write or plan:",question:s,pauseResume:i,choices:[{value:"write",label:"write",description:"Allow file and command changes",default:!0},{value:"plan",label:"plan",description:"Inspect and reason only"}]});if(!w)continue;f=w}if(f!=="plan"&&f!=="write"){A("Mode must be plan or write.");continue}t.mode=f,d.mode=f,await n.sessions.save(d),await k(),T(`Switched to ${f.toUpperCase()} mode.`),console.log(qt(p.settings.mode,p.settings.showModel?p.settings.model:void 0,d.title,{bypass:u.bypass}));continue}if(h==="/status"||h==="/diff"){let f=h==="/status"?"git_status":"git_diff",w=await p.runtime.execute(f,{},{rootDir:t.cwd,mode:p.settings.mode});console.log(w.output);continue}if(h==="/sessions"||h==="/resume"||h.startsWith("/resume ")){let f=h.startsWith("/resume ")?h.slice(8).trim():"";if(f){await R(await n.sessions.load(f));continue}let w=await Dn({store:n.sessions,question:s,pauseResume:i,title:"Switch session (Esc to stay):",currentId:d.id,prefer:"current"});if(w.kind!=="session"){w.kind==="cancel"&&$("Staying on the current session.");continue}if(w.session.id===d.id){$(`Already on ${d.title}`);continue}await R(w.session);continue}if(h==="/new"||h.startsWith("/new ")){let f=h.slice(4).trim()||void 0;d=await n.sessions.create({title:f,mode:p.settings.mode,model:p.settings.model}),t.session=d.id,await k(),T(`Started ${d.title}`);continue}if(h==="/memory"){Zi(await n.memory.list());continue}if(h==="/todo"||h.startsWith("/todo ")){let f=h.slice(5).trim();if(!f){let v=await n.todos.list();if(v.length===0)console.log("[no todos]");else for(let O of v)console.log(`${O.completed?U(D.green,"\u2713"):U(D.cyan,"\xB7")} ${O.id.slice(0,8)} ${O.text}`);continue}let[w="",...g]=f.split(/\s+/),b=g.join(" ").trim();try{if(w==="add"||w==="a"){let v=await n.todos.add(b);T(`Todo ${v.id.slice(0,8)}: ${v.text}`)}else if(w==="done"||w==="complete"||w==="d"){let v=await n.todos.complete(b);T(`Completed ${v.id.slice(0,8)}: ${v.text}`)}else if(w==="remove"||w==="rm"){let v=await n.todos.remove(b);$(`Removed ${v.id.slice(0,8)}: ${v.text}`)}else if(w==="clear"){let v=await n.todos.clear();T(`Cleared ${v} todo(s).`)}else A(`Unknown todo action "${w}". Usage: /todo [add|done|remove|clear] [text|id]`)}catch(v){J(v instanceof Error?v.message:String(v))}continue}if(h.startsWith("/remember ")){let f=await n.memory.add(h.slice(10));T(`Remembered ${f.id.slice(0,8)}: ${f.text}`);continue}if(h.startsWith("/forget ")){let f=await n.memory.remove(h.slice(8).trim());T(`Removed memory: ${f.text}`);continue}if(h==="/skills"){ea(await n.skills.list());continue}if(h.startsWith("/skill ")){let f=h.slice(7).trim(),[w="",...g]=f.split(/\s+/),b=await n.skills.get(w);await P(g.join(" ")||`Run the ${w} skill for the current repository.`,b);continue}if(h==="/preferences"){let f=await n.preferences.listRules();f.length===0&&console.log("[no learned preferences]");for(let w of f)console.log(`${w.id.slice(0,8)} ${Math.round(w.confidence*100)}% ${w.polarity}: ${w.text}`);continue}if(h==="/feedback"||h.startsWith("/feedback ")){let f=h.slice(9).trim();if(!f){let b=await Q({title:"/feedback \u2014 choose an outcome:",question:s,pauseResume:i,choices:[{value:"accepted",label:"accepted",description:"Mark last run accepted"},{value:"rejected",label:"rejected",description:"Mark last run rejected"},{value:"edited",label:"edited",description:"Mark last run edited"}]});if(!b)continue;let v=(await o.question("Optional note \u203A ")).trim();f=v?`${b} ${v}`:b}let[w="",...g]=f.split(/\s+/);await oa({outcome:ra(w),note:g.join(" ")||void 0,session:d,services:n,runtime:p.localRuntime,mode:p.settings.mode,rootDir:t.cwd});continue}if(h==="/models"||h==="/model"){let f=await Yr();if(f.length===0){A("No kpilot capabilities are configured for this account yet.");continue}let w=p.settings.model&&p.settings.model!=="auto"?p.settings.model:"auto",g=await Q({title:"/models \u2014 select a kpilot capability:",question:s,pauseResume:i,typeahead:!0,pageSize:8,choices:[{value:"auto",label:"auto",description:"kpilot chooses automatically (recommended)",default:w==="auto"},...f.map(b=>({value:b.model,label:Bt(b.model),description:xo(b.model),default:b.model===w}))]});if(g==null)continue;if(g===w){T(`Already using ${g==="auto"?"auto":Bt(g)}.`);continue}t.model=g==="auto"?void 0:g,d.messages=[...p.agent.messages],await k(),T(`Switched to ${g==="auto"?"auto":Bt(g)}. Run a prompt to use it.`);continue}if(h==="/agent"){await Vi({...t,args:["show"]});continue}if(h==="/mcp"){let f=p.mcpRuntime?.list()??[];f.length===0&&console.log("[no connected MCP tools]");for(let w of f)console.log(`${w.exposedName.padEnd(38)} ${w.description}`);continue}if(h==="/worktrees"){sa(await new $t(t.cwd).list());continue}if(h==="/policy"){let f=await n.policy.load();console.log(f?JSON.stringify(f,null,2):"[no team policy]");continue}if(h==="/usage"){let f=await n.policy.load(),w=await n.usage.check(An(e.usage?.budget,f?.usage));Zr(w.summary);for(let g of w.warnings)A(g);for(let g of w.violations)J(g);continue}if(h==="/audit"){let f=await n.audit.verify();f.valid?T(`Audit chain valid: ${f.records} record(s).`):J(`Audit chain invalid: ${f.reason??"unknown reason"}`);continue}if(h==="/admin"){await ia({...t,args:["status"]});continue}if(!N&&h.startsWith("/")){let[f="",...w]=h.slice(1).split(/\s+/);if(!Hi.has(f)){try{let b=await n.skills.get(f);await P(w.join(" ")||`Run the ${f} skill for the current repository.`,b)}catch(b){A(b instanceof Error?b.message:String(b))}continue}let g=Lt.find(b=>b.name===f||(b.aliases??[]).includes(f));A(`Unknown arguments for /${f}.${g?` Usage: ${g.usage}`:""} Run /help to list commands.`);continue}try{await P(h)}catch(f){J(f instanceof Error?f.message:String(f))}}}}finally{l.detach(),c.detach(),st(),process.stdout.isTTY&&process.stdout.write(`${Eo}${ro}`),y&&(d.messages=[...p.agent.messages],await n.sessions.save(d),await p.close()),o.close()}}async function Am(){Ld();let t=process.argv.slice(2);if(t.includes("-V")||t.includes("--version")||t[0]==="version"){console.log(V);return}await Jd();let e=Wd(t);if(e.command==="help"){console.log(Kd());return}if(e.command==="version"){console.log(V);return}if(e.command==="init"){await Vd(e.cwd);return}if(e.command==="doctor"){process.exitCode=await Qd(e);return}if(e.command==="login"){await na(e);return}if(e.command==="whoami"){await fm(e);return}if(e.command==="logout"){await gm(e);return}if(e.command==="models"){await Yd(e);return}if(e.command==="agents"){await Vi(e);return}if(e.command==="sessions"){await ym(e);return}if(e.command==="memory"){await bm(e);return}if(e.command==="skills"){await vm(e);return}if(e.command==="preferences"){await km(e);return}if(e.command==="feedback"){await xm(e);return}if(e.command==="mcp"){await Sm(e);return}if(e.command==="worktrees"){await Pm(e);return}if(e.command==="policy"){await Em(e);return}if(e.command==="usage"){await Rm(e);return}if(e.command==="audit"){await Cm(e);return}if(e.command==="sync"){await Mm(e);return}if(e.command==="admin"){await ia(e);return}if(e.command==="chat"){await _m(e);return}await wm(e)}Am().catch(t=>{st(),process.stdout.isTTY&&process.stdout.write(ro),J(t instanceof Error?t.message:String(t)),process.exitCode=1});
|