kpilot 0.10.10 → 0.10.42
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 +192 -145
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,26 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{access as
|
|
3
|
-
`)
|
|
4
|
-
`),
|
|
5
|
-
`)
|
|
6
|
-
`);
|
|
7
|
-
|
|
8
|
-
`)
|
|
9
|
-
|
|
10
|
-
${s
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`)
|
|
14
|
-
`)
|
|
15
|
-
`)
|
|
16
|
-
`)
|
|
17
|
-
|
|
18
|
-
`)
|
|
2
|
+
import{access as wd,appendFile as yd,chmod as En,mkdir as et,readFile as Vr,stat as Ci,writeFile as ve}from"node:fs/promises";import{createHash as Mi,randomUUID as bd}from"node:crypto";import{homedir as $i}from"node:os";import D from"node:path";import{spawn as _i}from"node:child_process";import{createInterface as Ai}from"node:readline/promises";import{emitKeypressEvents as Zr}from"node:readline";var N={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m"};function F(t,e){return process.stdout.isTTY?`${t}${e}${N.reset}`:e}var eo="\x1B[?25l",to="\x1B[?25h",jt=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 zi(t){let e=t.findIndex(n=>n.default);return e>=0?e:0}function Vi(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 Yi(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 Qi(t){let e=t.choices;if(e.length===0)return null;console.log(`${F(N.cyan,"\u25C6")} ${t.title}`);for(let[i,a]of e.entries()){let c=`${String(i+1).padStart(2)}.`,l=a.default?F(N.green,"*"):" ",u=a.description?F(N.dim,a.description):"";console.log(` ${F(N.cyan,c)}${l} ${F(N.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=Yi(e,o);return o.trim()&&s===null&&console.log(`${F(N.yellow,"!")} Unknown selection: ${o.trim()}`),s}function no(t,e,n){let r=n?F(N.green,"\u203A"):" ",o=F(N.cyan,`${String(e+1).padStart(2)}.`),s=n?F(N.bold,t.label.padEnd(16)):t.label.padEnd(16),i=t.description?F(N.dim,t.description):"";return` ${r} ${o} ${s} ${i}`}async function Xi(t){let e=t.choices;if(e.length===0)return null;let n=zi(e),r=new jt(process.stdout),o=()=>[`${F(N.cyan,"\u25C6")} ${t.title}`,F(N.dim,"\u2191/\u2193 move \xB7 Enter select \xB7 Esc cancel \xB7 1-9 jump"),...e.map((i,a)=>no(i,a,a===n))];r.paint(o()),t.pauseResume?.pause(),Zr(process.stdin);let s=process.stdin.isRaw;return process.stdin.setRawMode?.(!0),process.stdin.isPaused()&&process.stdin.resume(),process.stdout.write(eo),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(to),u!==null){let m=e.find(d=>d.value===u);process.stdout.write(`${F(N.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 Zi(t){let e=t.pageSize??5,n=t.initialQuery??"",r=0,o=0,s=()=>Vi(t.choices,n),i=m=>Math.max(1,Math.ceil(m.length/e)),a=m=>{o=Math.min(o,i(m)-1)},c=new jt(process.stdout),l=()=>{let m=s();a(m);let d=o*e,f=m.slice(d,d+e),w=m.length?F(N.dim,`\u2191/\u2193 move \xB7 Tab complete \xB7 Enter select \xB7 Esc cancel \xB7 ${m.length} match${m.length===1?"":"es"}`):F(N.dim,"No matches \u2014 keep typing or Esc to cancel");return[`${F(N.cyan,"\u25C6")} ${t.title}`,`${F(N.dim,"Filter")} ${F(N.bold,"/"+n)}`,w,...f.map((x,P)=>no(x,d+P,P===r))]};t.pauseResume?.pause(),Zr(process.stdin);let u=process.stdin.isRaw;return process.stdin.setRawMode?.(!0),process.stdin.isPaused()&&process.stdin.resume(),c.paint(l()),process.stdout.write(eo),await new Promise(m=>{let d=!1,f=P=>{if(!d){d=!0,process.stdin.off("keypress",x);try{process.stdin.setRawMode?.(u??!1)}catch{}if(t.pauseResume?.resume(),c.clear(),process.stdout.write(to),P!==null){let S=t.choices.find(C=>C.value===P);process.stdout.write(`${F(N.green,"\u2713")} /${P}${S&&S.description?F(N.dim,` \u2014 ${S.description}`):""}
|
|
5
|
+
`)}else process.stdout.write(`${F(N.dim,"\xB7")} cancelled
|
|
6
|
+
`);m(P)}},w=()=>{let S=s()[o*e+r];return S?S.value:null},x=(P,S)=>{if(!S||d)return;if(S.ctrl&&S.name==="c"||S.name==="escape")return f(null);if(S.name==="return"||S.name==="enter")return f(w());if(S.name==="tab"){let b=w();b&&(n=b,r=0,o=0,c.paint(l()));return}if(S.name==="backspace"){n=n.slice(0,-1),r=0,o=0,c.paint(l());return}if(S.name==="up"||S.name==="k"||S.name==="p"&&S.ctrl){let b=s();if(b.length===0)return;r>0?r-=1:o>0&&(o-=1,r=Math.min(e-1,Math.max(0,b.length-1-o*e))),c.paint(l());return}if(S.name==="down"||S.name==="j"||S.name==="n"&&S.ctrl){let b=s();if(b.length===0)return;r<e-1&&o*e+r+1<b.length?r+=1:o+1<i(b)&&(o+=1,r=0),c.paint(l());return}if(S.name&&/^[1-9]$/.test(S.name)){let b=Number(S.name)-1;b<s().length&&(o=Math.floor(b/e),r=b%e,c.paint(l()));return}let C=S.sequence??P;C&&C.length===1&&C.charCodeAt(0)>=32&&(n+=C,r=0,o=0,c.paint(l()))};process.stdin.on("keypress",x)})}async function Q(t){let e=!!(process.stdin.isTTY&&process.stdout.isTTY&&typeof process.stdin.setRawMode=="function");return e&&t.typeahead===!0?Zi(t):e?Xi(t):Qi(t)}var Lt="__fresh__";function ea(t,e={}){let n=e.prefer??(e.currentId?"current":"recent"),r=[];e.includeFresh&&r.push({value:Lt,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:i,description:`${s.updatedAt} ${s.mode.padEnd(5)} ${String(s.runCount).padStart(3)} run(s) ${s.title}${a}`,aliases:[i],default:c})}if(!r.some(o=>o.default)&&r.length>0){let o=n==="fresh"?r.find(s=>s.value===Lt)??r[0]:r.find(s=>s.value!==Lt)??r[0];o&&(o.default=!0)}return r}async function $n(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:ea(e,{includeFresh:t.includeFresh,currentId:t.currentId,prefer:t.prefer})});return n?n===Lt?{kind:"fresh"}:{kind:"session",session:await t.store.load(n)}:{kind:"cancel"}}var ta=new Set(["exit","quit","q","bye",":q",":quit",":exit","/exit","/quit","/q"]);function _n(t){return ta.has(t.trim().toLowerCase())}import{emitKeypressEvents as vd}from"node:readline";var R={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}${R.reset}`:e}function oo(t){return t.replace(/\u001b\[[0-9;]*m/g,"")}function so(t){let e=0;for(let n of oo(t)){let r=n.codePointAt(0)??0;e+=r>11904?2:1}return e}function io(t,e){let n=so(t);return n>=e?t:t+" ".repeat(e-n)}var ao={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 na(t){return ao[t]?.label??t.replace(/^mcp_/,"MCP").replace(/_/g," ").toUpperCase()}function co(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;if(typeof n=="number")return typeof r=="number"&&typeof o=="number"?`lines ${r}-${o} of ${n}`:`${n} lines`;if(typeof s=="number")return`${s} matches`;let i=[],a=!1;for(let[l,u]of Object.entries(t)){let m=typeof u=="object"&&u!==null?JSON.stringify(u):String(u);if(m.length>24){a=!0;continue}i.push(`${l}: ${m}`)}let c=i.join(", ");return c.length>60&&(c=c.slice(0,57).trimEnd(),a=!0),a?`${c}${c?" ":""}\u2026`:c}function In(t,e){let n=ao[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 lo(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 ro(t){return Number.isFinite(t)?String(t):"0"}function uo(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 ra(t){return t===void 0||!Number.isFinite(t)||t<=0?"":t>=.01?`\xB7 est $${t.toFixed(4)}`:`\xB7 est $${t.toFixed(6)}`}function Nt(t,e,n,r={}){let s=[e?M(R.dim,e):"",n?M(R.dim,`session ${n}`):""].filter(Boolean).join(M(R.dim," \xB7 "));if(r.bypass&&t!=="plan"){let a=M(R.red,"BYPASS MODE"),c=M(R.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(R.yellow,"PLAN MODE"),c=M(R.dim,"\xB7 read-only \xB7 edits & mutating commands are blocked");return`\u2500\u2500 ${a} ${c}${s?` ${s}`:""} \u2500\u2500`}return`\u2500\u2500 ${M(R.green,"WRITE MODE")}${s?` ${s}`:""} \u2500\u2500`}function mo(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 oa(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(C=>C.length===1).length>=r.length*.5,s=o?n.replace(/ /g,""):n;if(!s)return`\u250C\u2500 ${M(R.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 C="";for(let b of r){let A=C?`${C} ${b}`:b;so(A)>i-2&&C?(c.push(C),C=b):C=A}C&&c.push(C)}else for(let C=0;C<a.length;C+=l)c.push(a.slice(C,C+l).join(""));let u=process.stdout.isTTY,m=u?"\x1B[100m":"",d=u?R.reset:"",f=12,w=c.length>f?[...c.slice(0,f),M(R.dim,`\u2026 ${c.length-f} more lines`)]:c,x=`${m}\u250C\u2500 ${M(R.dim,"thinking")} ${M(R.dim,"\u2500".repeat(Math.max(0,i-10)))}\u2510${d}`,P=`${m}\u2514${M(R.dim,"\u2500".repeat(i))}\u2518${d}`,S=w.map(C=>`${m}\u2502 ${M(R.dim,io(C,i-2))} \u2502${d}`).join(`
|
|
8
|
+
`);return`${x}
|
|
9
|
+
${S}
|
|
10
|
+
${P}`}function sa(t){let e=[];return t.elapsedMs!==void 0&&e.push(uo(t.elapsedMs)),e.push(`${Ue(t.inputTokens)}\u25B2 \xB7 ${Ue(t.outputTokens)}\u25BC`),t.cacheReadTokens&&t.cacheReadTokens>0&&e.push(M(R.green,`${Ue(t.cacheReadTokens)} cached`)),t.costUsd&&e.push(ra(t.costUsd)),t.mode==="plan"&&e.push(M(R.yellow,"plan \xB7 edits blocked")),e.join(M(R.dim," \xB7 "))}function ia(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(R.green,i):i.startsWith("-")?M(R.red,i):i.startsWith("@@")?M(R.cyan,i):(i.startsWith("diff --git")||i.startsWith("index ")||i.startsWith("---")||i.startsWith("+++"),M(R.dim,i))).join(`
|
|
11
|
+
`);return r>e&&(s+=`
|
|
12
|
+
${M(R.dim,`\u2026 ${r-e} more diff lines`)}`),s}var An=["\u2722","\u2740","\u273F","\u2744","\u2748","\u2734","\u2736","\u2605","\u272E","\u272A","\u263C","\u25C6"],On=["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 aa(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=R.dim;s>=0&&s<n&&(s===0?i=R.green:s<Math.ceil(n/2)?i=R.cyan:i=R.yellow),r+=M(i,t[o])}return r}var Ut=class{mode;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.tty=!!process.stdout.isTTY}clearLine(){this.tty&&process.stdout.write("\r\x1B[2K")}writeLine(e){if(this.tty)process.stdout.write(`\r\x1B[2K${e}
|
|
13
|
+
`);else{let n=oo(e);console.log(n)}this.lastLineOpen=!1}noteOutput(){this.sawOutput=!0}activity(e,n,r,o){if(this.finished)return;this.sawOutput=!0,this.clearReasoningIfOpen();let s=na(n),i=this.tty?`\x1B[7m ${s} \x1B[0m`:`[${s}]`,a=r?M(R.dim,` ${r}`):"";if(e==="start")this.writeLine(`${M(R.magenta,"\u2192")} ${i}${a}`);else if(e==="result"){let c=o===!1?M(R.red,"\u2717"):M(R.green,"\u2713");this.writeLine(`${c} ${i}${a}`)}else this.writeLine(` ${i}${a}`)}reasoningDelta(e){this.finished||(this.sawOutput=!0,this.reasoning.push(e),this.reasoningOpen=!0,this.redrawFooter())}clearReasoning(){this.clearReasoningIfOpen()}clearReasoningIfOpen(){this.reasoningOpen&&(this.reasoningOpen=!1,this.reasoning.length>0&&!this.finished&&this.writeLine(oa(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(`
|
|
14
|
+
`),this.writeLine("")):console.log("");let n=e?.files??[];if(e?.changed&&n.length>0){this.writeLine(M(R.bold,`Files changed (${n.length}):`));for(let o of n)this.writeLine(` ${M(R.dim,o.file.padEnd(40))} ${M(R.green,`+${ro(o.added)}`)} ${M(R.red,`\u2212${ro(o.deleted)}`)}`);if(e.diff){this.writeLine(""),this.writeLine(M(R.dim,"Diff:"));for(let o of ia(e.diff).split(`
|
|
15
|
+
`))this.writeLine(o)}}else e&&!e.changed&&this.mode==="plan"&&this.writeLine(M(R.dim,"No files changed \xB7 plan-only run."));if(e?.planSummary){this.writeLine(M(R.bold,"Plan summary"));for(let o of e.planSummary.split(`
|
|
16
|
+
`))this.writeLine(M(R.dim,` ${o}`))}let r=sa({elapsedMs:Date.now()-this.startedAt,inputTokens:this.inputTokens,outputTokens:this.outputTokens,costUsd:this.costUsd,cacheReadTokens:this.cacheReadTokens,mode:this.mode});this.writeLine(M(R.dim,r))}renderFrame(){if(this.finished||!this.tty)return;let e=this.frame,n=An[Math.floor(e/2)%An.length]??An[0],r=this.reasoningOpen?this.reasoning.join("").replace(/\s+/g," ").trim().slice(-60):"",o;if(!this.sawOutput)o=M(R.dim,"connecting\u2026");else if(r)o=M(R.dim,`thinking: ${r}`);else{let u=On[Math.floor(e/8)%On.length]??On[0],m=Math.floor(e/2)%Math.max(1,u.length+6);o=aa(u,m)}let s=uo(Date.now()-this.startedAt),i=` \xB7 ${Ue(this.inputTokens)}\u25B2 ${Ue(this.outputTokens)}\u25BC${this.cacheReadTokens>0?M(R.green,` ${Ue(this.cacheReadTokens)} cached`):""}`,a=`${o}${M(R.dim,`${i} \xB7 ${s}`)}`,c=Math.max(30,(process.stdout.columns??80)-4);process.stdout.write(`\r\x1B[2K${M(R.cyan,n)} ${io(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(`
|
|
17
|
+
`),this.renderFrame(),this.timer=setInterval(()=>{this.frame+=1,this.renderFrame()},140)):this.nonTtyAnnounced||(this.nonTtyAnnounced=!0,console.log(M(R.dim,"\u25C6 working\u2026"))))}stop(){this.stopTimer(),this.tty&&(this.clearLine(),this.lastLineOpen=!1)}stopTimer(){this.timer&&(clearInterval(this.timer),this.timer=void 0)}};function po(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(In(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(`
|
|
18
|
+
`)}var fo={"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 Ft(t){let e=fo[t]?.name;return e||(t.includes("/")?t.slice(t.lastIndexOf("/")+1):t).replace(/[-_]/g," ").replace(/\b\w/g,r=>r.toUpperCase())}function go(t){return fo[t]?.description??"Hosted model available through kpilot"}import{emitKeypressEvents as ca}from"node:readline";var Se={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m"},Dn="\x1B[2K";function Ee(t,e){return`${t}${e}${Se.reset}`}function Re(t){if(!t.startsWith("/"))return null;let e=t.slice(1);return e.includes(" ")||e.includes(" ")?null:e}function la(t){return[t.name,...t.aliases??[]].map(e=>e.toLowerCase())}function ho(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;la(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 Bt=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,ca(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=Re(this.rl.line);return e===null?[]:ho(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=Re(this.rl.line);return}this.render()},0))}render(){if(!this.attached||this.suspended||!this.tty)return;let e=Re(this.rl.line);if(this.syncHistory(e!==null),e===null){this.erase();return}let n=ho(this.entries,e);if(this.current=n,n.length===0){this.hover=0,this.lastQuery=e,this.draw([` ${Ee(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(` ${Ee(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?Ee(Se.green,"\u203A"):" ",s=n?Ee(Se.bold,Ee(Se.cyan,r)):Ee(Se.cyan,r);return` ${o} ${s} ${Ee(Se.dim,e.description)}`}draw(e){if(this.erase(),e.length===0)return;let{output:n}=this.streams;n.write(`\r
|
|
19
|
+
`);for(let r=0;r<e.length;r+=1)n.write(`${Dn}${e[r]}`),r<e.length-1&&n.write(`\r
|
|
20
|
+
`);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
|
|
21
|
+
`);for(let r=0;r<e;r+=1)n.write(Dn),r<e-1&&n.write(`\r
|
|
22
|
+
`);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(Dn),r<e-1&&n.write(`\r
|
|
23
|
+
`);e>1&&n.write(`\x1B[${e-1}A\r`)}};import{readFile as ua,stat as da}from"node:fs/promises";import wo from"node:path";var yo="\x1B[?2004h",bo="\x1B[?2004l",ma=200,pa=5e3,fa=5*1024*1024,ga={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".bmp":"image/bmp"};function ha(t){if(t.length===0)return null;let n=t.replace(/\r\n|\r/g,`
|
|
24
|
+
`).replace(/\n+$/,"").split(`
|
|
25
|
+
`).length;if(n>1)return`[pasted ${n} lines]`;let r=[...t].length;return r>ma?`[pasted ${r} chars]`:null}var qt=class{entries=[];pasted=!1;record(e,n){let r=n??ha(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 vo(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=wo.extname(e).toLowerCase(),r=ga[n];if(!r)return{text:t};try{let o=await da(e);if(!o.isFile()||o.size>fa)return{text:t};let s=await ua(e);return{text:`data:${r};base64,${s.toString("base64")}`,label:`[pasted image ${wo.basename(e)}]`}}catch{return{text:t}}}var Jt=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(),pa)}}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 wa=["--yolo","--bypass-permissions","--yes-always","--dangerously-skip-permissions","--auto-accept","--force"];function So(t){return wa.includes(t)}var ko=new Set(["bypass","bypass-permissions","yolo","auto-accept","autoaccept","accept","accept-edits","auto","skip","all"]),xo=new Set(["ask","default","manual","normal","prompt","confirm"]);function To(t){let e=t.trim().toLowerCase();if(ko.has(e))return!0;if(xo.has(e))return!1;let n=[...ko,...xo].join(", ");throw new Error(`--permission-mode must be one of: ${n}.`)}var Te={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",yellow:"\x1B[33m",cyan:"\x1B[36m"};function Ne(t,e,n){return n?`${t}${e}${Te.reset}`:e}function Po(){return process.stdout.isTTY===!0}var jn=`${Ne(Te.cyan,"\u276F",!0)} `,Ln="Ask your question...",ya=2;function Un(t=process.stdout.columns,e=Po()){return Ne(Te.dim,"\u2500".repeat(Math.max(20,Eo(t)-1)),e)}function Eo(t=process.stdout.columns){return typeof t=="number"&&Number.isFinite(t)&&t>0?t:80}function ba(t){return t.replace(/\u001b\[[0-9;]*m/g,"").length}function Ro(t,e=Po()){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[Ne(Te.dim,o+n,e),Ne(t.exitArmed?Te.yellow:Te.dim,o+r,e)]}var Kt=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 Eo(this.output.columns)}column(){return(ya+this.rl.cursor)%this.columns()+1}suppressed(){return Re(this.rl.line)!==null}belowLines(){let e=[Un(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();this.output.write(`
|
|
26
|
+
\x1B[0J${e.join(`
|
|
27
|
+
`)}\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=Ne(Te.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(`${Ne(Te.dim,this.placeholder,!0)}\x1B[${ba(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${jn}${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 va}from"node:readline";var ka=1e4;function Fn(){let t=new Error("Stopped by user");return t.name="AbortError",t}var Nn=class{active=null;installed=!1;stopped=null;stream;constructor(e=process.stdin){this.stream=e}install(){this.installed||!this.stream.isTTY||(this.installed=!0,va(this.stream),this.stream.on("keypress",this.onKeypress))}onKeypress=(e,n)=>{this.handleKey(n)};handleKey(e){return!e||e.name!=="escape"?!1:this.stop("Esc")}noteStop(e){this.stopped={reason:e,at:Date.now()}}get stopReason(){return!this.stopped||Date.now()-this.stopped.at>ka?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(Fn()),!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.isPaused?.()&&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{}}}}},st=new Nn;function Bn(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 Co(t){return`'${t.replace(/'/g,"'\\''")}'`}import Ea from"node:path";import{mkdir as $o,readdir as Kn,rename as xa,rm as qn,stat as _o}from"node:fs/promises";import Ce from"node:path";var E=".kpilot",Ao=".konsolepilot";async function Mo(t){try{return await _o(t),!0}catch{return!1}}async function Oo(t){try{return(await _o(t)).isDirectory()}catch{return!1}}async function Jn(t){return await Oo(t)?(await Kn(t)).length===0:!1}async function Sa(t,e){if(await Mo(t)&&!await Mo(e)){await $o(Ce.dirname(e),{recursive:!0});try{await xa(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 Wt(t){let e=Ce.resolve(t),n=Ce.join(e,Ao),r=Ce.join(e,E);if(await $o(r,{recursive:!0}),!await Oo(n))return{migrated:!1};let o=await Kn(n);for(let s of o)await Sa(Ce.join(n,s),Ce.join(r,s));if(await Jn(n))await qn(n,{recursive:!0,force:!0});else{let s=await Kn(n);for(let i of s){let a=Ce.join(n,i);await Jn(a)&&await qn(a,{recursive:!0,force:!0})}await Jn(n)&&await qn(n,{recursive:!0,force:!0})}return{migrated:!0}}function Ta(t,e="value"){if(typeof t!="object"||t===null||Array.isArray(t))throw new Error(`${e} must be a JSON object.`);return t}function U(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 te(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 Io(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 Ta(n,e)}function Pa(t){try{return JSON.parse(t&&t.trim()?t:"{}"),!0}catch{return!1}}function me(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(Pa(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(`
|
|
28
|
+
|
|
29
|
+
`)||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 Ra(t){return t.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,48)||"plan"}function Ca(t=new Date){return t.toISOString().slice(0,16).replace(/[:T]/g,"").replace(/-/g,"")}function Do(t,e,n=new Date){return Ea.join(t,E,"plans",`${Ra(e)}-${Ca(n)}.md`)}import{readFile as Ma,stat as $a}from"node:fs/promises";import _a from"node:path";var Aa=[".kpilot/logbook/project.md",".kpilot/logbook/learnings.md",".kpilot/instructions.md","KPILOT.md","AGENTS.md","KONSOLEPILOT.md",".kpilot/understanding.md",".kpilot/learnings.md"],Oa=8e3,Ia=50,Da={"AGENTS.md":1500,"KPILOT.md":2e3,"KONSOLEPILOT.md":2e3};async function ja(t){try{return await $a(t),!0}catch{return!1}}async function La(t){let e=[],n=0;for(let r of Aa){let o=_a.join(t,r);if(!await ja(o))continue;let s=await Ma(o,"utf8"),i=Oa-n;if(i<=0)break;let a=Da[r]??i,c=s.slice(0,Math.min(i,a));e.push(`## ${r}
|
|
19
30
|
${c}`),n+=c.length}return e.join(`
|
|
20
31
|
|
|
21
|
-
`)}function
|
|
32
|
+
`)}function Ua(t){return`You are kpilot, a precise local coding agent operating inside one repository.
|
|
22
33
|
|
|
23
|
-
${t.mode==="plan"
|
|
34
|
+
${t.mode==="plan"?`You are in PLAN mode \u2014 read-only. Inspect and reason; do not change files or run mutating commands.
|
|
35
|
+
Produce a concrete, actionable implementation plan for the request:
|
|
36
|
+
1. What you inspected (key files and findings).
|
|
37
|
+
2. The exact changes proposed, file by file (paths and what changes).
|
|
38
|
+
3. The verification steps (tests/build commands to run).
|
|
39
|
+
4. Risks or open questions.
|
|
40
|
+
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
41
|
|
|
25
42
|
Repository root: ${t.rootDir}
|
|
26
43
|
|
|
@@ -43,123 +60,140 @@ Operating rules:
|
|
|
43
60
|
- 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
61
|
- When finished, summarize what you did (commands run, URLs, files changed), not a tutorial for the user to repeat.
|
|
45
62
|
|
|
63
|
+
Tool guide (use the right tool, keep it economical):
|
|
64
|
+
- Find code with \`search_text\` (ripgrep) and \`list_files\` before reading; do not scan the whole tree.
|
|
65
|
+
- Read with \`read_file\` in focused windows (about 120 lines around what you need) \u2014 not whole large files.
|
|
66
|
+
- Use \`git_status\` and \`git_diff\` tools rather than shelling out to \`git status\`/\`git diff\`.
|
|
67
|
+
- Use \`replace_in_file\` for surgical edits; \`write_file\` for new files or full rewrites.
|
|
68
|
+
- Use \`shell\` for project scripts (\`pnpm test\`, \`pnpm build\`, \`pnpm lint\`) and other commands; long-lived servers must use \`background=true\`.
|
|
69
|
+
- The sandbox may strip environment variables, disable network, and enforce a timeout \u2014 if a command needs them, expect failure and report it.
|
|
70
|
+
- Delegate broad read-only investigation to \`delegate_subagents\` instead of reading many files yourself.
|
|
71
|
+
|
|
72
|
+
Verification and git hygiene:
|
|
73
|
+
- After changing code, run the most relevant test/build/lint command and confirm it passes before finishing.
|
|
74
|
+
- Before finishing a change, review \`git_diff\` to confirm the edit is correct and limited to the intended files.
|
|
75
|
+
- Do not modify unrelated files; keep the change scoped to the request.
|
|
76
|
+
- If the same step fails three times, stop and report the blocker instead of looping.
|
|
77
|
+
|
|
78
|
+
Stopping:
|
|
79
|
+
- Stop as soon as the request is satisfied; do not gold-plate or add unrequested features.
|
|
80
|
+
- If a write task is ambiguous, ask for clarification instead of guessing.
|
|
81
|
+
|
|
46
82
|
${t.projectInstructions?`Project instructions:
|
|
47
83
|
${t.projectInstructions}
|
|
48
84
|
`:""}
|
|
49
|
-
${t.memoryContext?`Persistent project memory:
|
|
50
|
-
${t.memoryContext}
|
|
51
|
-
`:""}
|
|
52
85
|
${t.preferenceContext?`Learned coding preferences:
|
|
53
86
|
${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).
|
|
87
|
+
`:""}`}var at=class extends Error{constructor(e){super(typeof e=="string"&&e.trim()?`Agent run cancelled: ${e}`:"Agent run cancelled."),this.name="AgentCancelledError"}};function Gt(t){if(t?.aborted)throw new at(t.reason)}function Na(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 Fa=`Your previous tool call failed because the tool-argument JSON was invalid (usually unescaped quotes/newlines in a raw "content" string).
|
|
61
88
|
|
|
62
89
|
Retry with ONE of these safer approaches:
|
|
63
90
|
1. For .env / markdown / plain config: write_file with content set to the raw text (escape newlines as \\n in JSON), OR
|
|
64
91
|
2. replace_in_file with a short exact old_string and new_string, OR
|
|
65
92
|
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
93
|
|
|
67
|
-
Do not keep retrying the same broken content_b64.`,
|
|
94
|
+
Do not keep retrying the same broken content_b64.`,Ba=`Stop. write_file for that path already succeeded earlier in this turn (or was refused as a repeat).
|
|
68
95
|
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
|
|
96
|
+
If needed, call read_file once to verify, then finish with a short confirmation and no more tools.`;function jo(t){return typeof t.path=="string"?t.path:""}function qa(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 Ja(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 Wn(t){return t?Math.max(1,Math.ceil(t.length/3.5)):0}function Gn(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 Fo(t){if(t.role==="assistant"){let e=t.tool_calls?.map(n=>n.function.arguments).join(`
|
|
70
97
|
`)??"";return`${t.content??""}
|
|
71
|
-
${e}`}return t.content??""}function
|
|
72
|
-
\u2026[${n}]`}function
|
|
73
|
-
`)}function
|
|
74
|
-
\u2026[
|
|
75
|
-
\u2026[
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
\u2026[skill truncated for hub context]`));let d={role:"system",content:si({rootDir:e.rootDir,mode:e.mode,projectInstructions:u,workspaceSummary:i,memoryContext:a,preferenceContext:c,skillContext:l})};this.conversation[0]?.role==="system"?this.conversation[0]=d:this.conversation.unshift(d)}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??ti;Pt(e.signal),this.conversation=ie(this.conversation),await this.refreshSystemMessage(e),Pt(e.signal),this.conversation.push({role:"user",content:e.prompt});let o={inputTokens:0,outputTokens:0,cacheReadTokens:0},r=0,s=0,i=e.contextWindowTokens,a=new Map,c=new Map,l=0,u=this.runtime.definitions(),d=JSON.stringify(u),p=async f=>{s+=1;let y=fi(this.conversation)??e.prompt,m=gi(this.conversation);this.conversation=[],await this.refreshSystemMessage({...e,contextWindowTokens:i}),this.conversation.push({role:"user",content:y}),m&&this.conversation.push({role:"user",content:`Context reset: hub window was full. Continue without redoing finished work.
|
|
98
|
+
${e}`}return t.content??""}function Ht(t){let e=0;for(let n of t)e+=Wn(Fo(n))+8;return e}function it(t,e,n){return t.length<=e?t:`${t.slice(0,Math.max(0,e))}
|
|
99
|
+
\u2026[${n}]`}function Bo(t,e){return t.map(n=>n.role==="system"?{role:"system",content:it(n.content,e.systemChars,"system truncated for hub context")}:n.role==="tool"?{role:"tool",tool_call_id:n.tool_call_id,content:it(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:it(r.function.arguments,e.argumentChars,"args truncated")}}))}:n.role==="user"&&n.content.length>e.systemChars?{role:"user",content:it(n.content,e.systemChars,"user truncated for hub context")}:Gn(n))}function Ka(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 Lo(t,e){let n=t.map(Gn),r=800,o=2e3;for(let s=0;s<8&&Ht(n)>e;s+=1)r=Math.max(240,Math.floor(r*.6)),o=Math.max(600,Math.floor(o*.7)),n=Bo(n,{toolChars:r,systemChars:o,argumentChars:Math.max(200,r)});return n}function Wa(t){return/^(Context reset:|Hub context full|Your previous tool call failed|Stop\. write_file|Tool JSON parse failed)/i.test(t.trim())}function Uo(t){for(let e=t.length-1;e>=0;e-=1){let n=t[e];if(n?.role==="user"&&!Wa(n.content))return n.content}}function Ga(t,e=6){let n=t.filter(r=>r.role==="tool").slice(-e);return n.length===0?"":n.map((r,o)=>{let s=it(r.content,240,"truncated");return`${o+1}. ${s}`}).join(`
|
|
100
|
+
`)}function No(t,e){let n=Math.max(1,e.aggressiveness??1),r=(e.reserveOutputTokens??384)*n,o=Wn(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=Bo(t.map(Gn),{toolChars:a,systemChars:c,argumentChars:Math.min(2e3,a*2)}),u=0;for(;Ht(l)>i&&u<40;){u+=1;let m=Ka(l);if(m.length===l.length){l=Lo(l,i);break}l=m}return Ht(l)>i&&(l=Lo(l,i)),me(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?me(e.initialMessages):[]}reset(){this.conversation=[]}restore(e){this.conversation=me(e)}get messages(){return this.conversation}async refreshSystemMessage(e){let n=await La(e.rootDir),r=(e.contextWindowTokens??Number.POSITIVE_INFINITY)<=8192,o=e.preferenceContext,s=n;r&&(s&&s.length>3500&&(s=`${s.slice(0,3500)}
|
|
101
|
+
\u2026[project instructions truncated for hub context]`),o&&o.length>600&&(o=`${o.slice(0,600)}
|
|
102
|
+
\u2026[preferences truncated for hub context]`));let i={role:"system",content:Ua({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??Ia;Gt(e.signal),this.conversation=me(this.conversation),await this.refreshSystemMessage(e),Gt(e.signal),this.conversation.push({role:"user",content:[e.volatileContext?.trim(),e.prompt].filter(Boolean).join(`
|
|
103
|
+
|
|
104
|
+
`)});let r={inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0},o=new Set(["read_file","list_files","search_text","git_status","git_diff","workspace_summary"]),s=new Map,i=new Set(["write_file","replace_in_file","make_directory","delete_path","shell"]),a=0,c=0,l=e.contextWindowTokens,u=new Map,m=new Map,d=0,f=0,w=!1,x=this.runtime.definitions(),P=JSON.stringify(x),S=async b=>{c+=1;let A=Uo(this.conversation)??e.prompt,O=Ga(this.conversation);this.conversation=[],await this.refreshSystemMessage({...e,contextWindowTokens:l}),this.conversation.push({role:"user",content:A}),O&&this.conversation.push({role:"user",content:`Context reset: hub window was full. Continue without redoing finished work.
|
|
79
105
|
Recent tool results:
|
|
80
|
-
${
|
|
81
|
-
`})};for(let
|
|
82
|
-
`}),this.conversation.push({role:"user",content:
|
|
83
|
-
\u2026[truncated ${
|
|
84
|
-
|
|
85
|
-
`)
|
|
86
|
-
`
|
|
106
|
+
${O}`}),l&&(this.conversation=No(this.conversation,{contextWindowTokens:l,toolsJson:P,aggressiveness:2})),await e.onEvent?.({type:"assistant_text",text:`${b} Context reset (${c}/2)\u2026
|
|
107
|
+
`})};for(let b=1;b<=n;b+=1){Gt(e.signal),await e.onEvent?.({type:"step",current:b,maximum:n});let A=!1,O;if(e.maxTotalTokens){let T=r.inputTokens+r.outputTokens+Ht(this.conversation)+Wn(P);if(T>e.maxTotalTokens)throw new Error(`Per-run token budget exceeded (projected ${T}/${e.maxTotalTokens}).`)}try{this.conversation=me(this.conversation);let h=l?No(this.conversation,{contextWindowTokens:l,toolsJson:P,aggressiveness:1}):this.conversation;O=await this.gateway.complete({messages:h,tools:x},{signal:e.signal,onTextDelta:async T=>{A=!0,await e.onEvent?.({type:"assistant_delta",delta:T})},onReasoningDelta:async T=>{A=!0,await e.onEvent?.({type:"reasoning_delta",delta:T})}})}catch(h){if(Na(h)&&a<2){a+=1,this.conversation=me(this.conversation),await e.onEvent?.({type:"assistant_text",text:`Tool JSON parse failed; cleaned history and guiding a safer retry (${a}/2).
|
|
108
|
+
`}),this.conversation.push({role:"user",content:Fa});continue}if(qa(h)&&c<2){let T=Ja(h);T&&(l=T.availableTokens),await S("Hub context full."),b-=1;continue}throw h}let L=O.message,B=O.usage?.inputTokens??0,y=O.usage?.outputTokens??0,p=O.usage?.cacheReadTokens??0,g=O.usage?.cacheWriteTokens??0;if(r.inputTokens+=B,r.outputTokens+=y,r.cacheReadTokens+=p,r.cacheWriteTokens+=g,await e.onEvent?.({type:"usage",model:O.model,inputTokens:B,outputTokens:y,...p?{cacheReadTokens:p}:{},...g?{cacheWriteTokens:g}:{}}),this.conversation.push(L),e.maxTotalTokens&&r.inputTokens+r.outputTokens>e.maxTotalTokens)throw new Error(`Per-run token budget exceeded (${r.inputTokens+r.outputTokens}/${e.maxTotalTokens}).`);!A&&L.content?.trim()&&await e.onEvent?.({type:"assistant_text",text:L.content});let k=L.tool_calls??[];if(k.length===0)return{answer:L.content?.trim()||"[The model returned no text.]",messages:[...this.conversation],steps:b,usage:r};for(let h of k){Gt(e.signal);let T;try{T=Io(h.function.arguments||"{}",`Arguments for ${h.function.name}`)}catch(Y){let ot=Y instanceof Error?Y.message:String(Y),xe={role:"tool",tool_call_id:h.id,content:JSON.stringify({ok:!1,output:`${ot}. 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(h.function.name==="write_file"){let Y=jo(T),ot=(m.get(Y)??0)+1;if(m.set(Y,ot),(u.get(Y)??0)>=1&&ot>=2){let Xr={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:h,args:T}),await e.onEvent?.({type:"tool_result",call:h,result:Xr}),this.conversation.push({role:"tool",tool_call_id:h.id,content:JSON.stringify(Xr)}),d<2&&(d+=1,this.conversation.push({role:"user",content:Ba}));continue}}await e.onEvent?.({type:"tool_start",call:h,args:T});let G=await this.permissions.authorize(h.function.name,T,e.mode,e.approvalHandler,{bypassPermissions:e.bypassPermissions});if(await e.onEvent?.({type:"permission",request:G,approved:G.approved}),!G.approved){this.conversation.push({role:"tool",tool_call_id:h.id,content:JSON.stringify({ok:!1,output:`Permission denied: ${G.reason}`,permission:G.category})});continue}let V=`${h.function.name}:${h.function.arguments}`;if(o.has(h.function.name)&&s.has(V)){let Y=s.get(V);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:h,result:xe}),this.conversation.push({role:"tool",tool_call_id:h.id,content:JSON.stringify(xe)});continue}}let ae=await this.runtime.execute(h.function.name,T,{rootDir:e.rootDir,mode:e.mode,signal:e.signal,...e.onEvent?{onOutput:Y=>{e.onEvent?.({type:"tool_output",call:h,chunk:Y})}}:{}});if(o.has(h.function.name)&&ae.ok&&s.set(V,h.id),ae.ok&&i.has(h.function.name)&&s.clear(),await e.onEvent?.({type:"tool_result",call:h,result:ae}),ae.ok){if(f=0,h.function.name==="write_file"){let Y=jo(T);u.set(Y,(u.get(Y)??0)+1)}}else f+=1;if(f>=12)throw new Error(`Agent stopped after ${f} consecutive tool failures.`);f>=6&&!w&&(w=!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 de=JSON.stringify(ae),ke=this.toolResultCharCap(l),Hi=de.length<=ke?de:`${de.slice(0,ke)}
|
|
109
|
+
\u2026[truncated ${de.length-ke} chars to fit local hub context]`;this.conversation.push({role:"tool",tool_call_id:h.id,content:Hi})}}let C=e.maxSteps===void 0?"internal step backstop":`${e.maxSteps}-step`;throw new Error(`Agent stopped after reaching the ${C} safety limit.`)}async compact(e){let n=this.conversation.length,r=this.conversation.find(l=>l.role==="system"),o=Uo(this.conversation)??"Continue the current task.",s=this.conversation.filter(l=>l.role!=="system").map(l=>Fo(l)).join(`
|
|
110
|
+
|
|
111
|
+
`).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):
|
|
112
|
+
${a}`}),c.push({role:"user",content:o}),this.conversation=me(c),{before:n,after:this.conversation.length}}};import{mkdir as Ha,readFile as za,rename as Va,stat as Ya,writeFile as Qa}from"node:fs/promises";import{randomUUID as qo}from"node:crypto";import zn from"node:path";async function Xa(t){try{return await Ya(t),!0}catch{return!1}}async function Hn(t,e){await Ha(zn.dirname(t),{recursive:!0});let n=`${t}.${qo()}.tmp`;await Qa(n,`${JSON.stringify(e,null,2)}
|
|
113
|
+
`,"utf8"),await Va(n,t)}function Za(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 zt=class{rootDir;filePath;constructor(e){this.rootDir=zn.resolve(e),this.filePath=zn.join(this.rootDir,E,"memory.json")}async readDocument(){return await Xa(this.filePath)?Za(await za(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:qo(),text:r,createdAt:i,updatedAt:i,source:n};return o.entries.push(a),await Hn(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 Hn(this.filePath,n),o}async clear(){let n=(await this.readDocument()).entries.length;return await Hn(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(`
|
|
114
|
+
`)}};import{mkdir as ec,readFile as tc,rename as nc,stat as rc,writeFile as oc}from"node:fs/promises";import{randomUUID as Jo}from"node:crypto";import Ko from"node:path";async function sc(t){try{return await rc(t),!0}catch{return!1}}async function ic(t){try{return JSON.parse(await tc(t,"utf8"))}catch{return{schemaVersion:1,todos:[]}}}async function Vt(t,e){await ec(Ko.dirname(t),{recursive:!0});let n=`${t}.${Jo()}.tmp`;await oc(n,`${JSON.stringify(e,null,2)}
|
|
115
|
+
`,"utf8"),await nc(n,t)}var Yt=class{rootDir;filePath;constructor(e){this.rootDir=e,this.filePath=Ko.join(e,E,"todos.json")}async list(){return await sc(this.filePath)?(await ic(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:Jo(),text:n,completed:!1,createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return r.push(o),await Vt(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 Vt(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 Vt(this.filePath,{schemaVersion:1,todos:n}),s}async clear(){let n=(await this.list()).length;return await Vt(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>):
|
|
116
|
+
`+e.map(n=>`- [ ] ${n.text} (${n.id.slice(0,8)})`).join(`
|
|
117
|
+
`)}};import{mkdir as ac,readFile as Wo,readdir as cc,rename as lc,rm as uc,stat as dc,writeFile as mc}from"node:fs/promises";import{randomUUID as Go}from"node:crypto";import Qt from"node:path";async function pc(t){try{return await dc(t),!0}catch{return!1}}async function fc(t,e){await ac(Qt.dirname(t),{recursive:!0});let n=`${t}.${Go()}.tmp`;await mc(n,`${JSON.stringify(e,null,2)}
|
|
118
|
+
`,"utf8"),await lc(n,t)}var Xt=class{rootDir;constructor(e){this.rootDir=e}dir(e){return Qt.join(this.rootDir,E,"checkpoints",e)}file(e,n){return Qt.join(this.dir(e),`${n}.json`)}async save(e,n,r){let o=Go(),s={id:o,label:(r??"").trim()||`checkpoint ${new Date().toISOString()}`,createdAt:new Date().toISOString(),sessionId:e,messages:n};return await fc(this.file(e,o),s),s}async list(e){let n=this.dir(e);if(!await pc(n))return[];let r=(await cc(n)).filter(s=>s.endsWith(".json")),o=[];for(let s of r)try{let i=JSON.parse(await Wo(Qt.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 Wo(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 uc(this.file(e,o.id),{force:!0})}};function Pe(t){return t.replace(/\/+$/,"")}function Vn(t){let e=typeof t=="string"&&t.trim()?`: ${t}`:"",n=new Error(`Model request cancelled${e}`);return n.name="AbortError",n}function gc(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 pe(t,e,n,r){let o=gc(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?Vn(n.signal.reason):s}finally{o.cleanup()}}async function fe(t,e){t.content&&await e.onTextDelta?.(t.content)}function Be(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(`
|
|
119
|
+
`)}async function ge(t,e){if(!e.onReasoningDelta)return;let n=Be(t);n&&await e.onReasoningDelta(n)}function Ho(t){return t.map(e=>({type:"function",name:e.function.name,description:e.function.description,parameters:e.function.parameters,strict:e.function.strict}))}function zo(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 Vo(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 hc(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
120
|
tool calls: ${JSON.stringify(e.tool_calls)}`:`${e.role}: ${e.content??""}`).join(`
|
|
88
121
|
|
|
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
|
|
122
|
+
`)}function Yn(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),"",hc(t)].join(`
|
|
123
|
+
`)}var $e=class{options;constructor(e){if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Pe(e.baseUrl),model:e.model,timeoutMs:e.timeoutMs??12e4}}async complete(e,n={}){let r=this.options.accessToken??this.options.apiKey,o=await pe(`${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:zo(e.messages),tools:Ho(e.tools),tool_choice:"auto",...this.options.maxOutputTokens===void 0?{}:{max_output_tokens:this.options.maxOutputTokens}})},n,this.options.timeoutMs),s=Vo(o);return await ge(o,n),await fe(s.message,n),s}};function wc(t){let e=t.filter(s=>s.role==="system").map(s=>s.content).join(`
|
|
124
|
+
|
|
125
|
+
`),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 ct=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:Pe(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=wc(e.messages),o=await pe(`${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 ge(o,n),await fe(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 yc(t){let e=t.filter(o=>o.role==="system").map(o=>o.content).join(`
|
|
126
|
+
|
|
127
|
+
`),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 qe=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:Pe(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=yc(e.messages),o=await pe(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 ge(o,n),await fe(c,n),{message:c,model:this.options.model,usage:{inputTokens:o?.usageMetadata?.promptTokenCount,outputTokens:o?.usageMetadata?.candidatesTokenCount}}}};var lt=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:Pe(e.baseUrl??"https://api.cohere.com"),model:e.model,timeoutMs:e.timeoutMs??12e4}}async complete(e,n={}){let r=await pe(`${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 ge(r,n),await fe(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 bc,createHmac as Qo}from"node:crypto";function Yo(t){return bc("sha256").update(t).digest("hex")}function Zt(t,e){return Qo("sha256",t).update(e).digest()}function vc(t){let e=t.toISOString().replace(/[:-]|\.\d{3}/g,"");return{timestamp:e,day:e.slice(0,8)}}function kc(t,e,n,r=new Date){let{timestamp:o,day:s}=vc(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(C=>`${C}:${a[C].trim()}
|
|
128
|
+
`).join(""),u=["POST",e.pathname,"",l,c.join(";"),Yo(n)].join(`
|
|
129
|
+
`),m=`${s}/${t.region}/bedrock/aws4_request`,d=["AWS4-HMAC-SHA256",o,m,Yo(u)].join(`
|
|
130
|
+
`),f=Zt(`AWS4${t.secretAccessKey}`,s),w=Zt(f,t.region),x=Zt(w,"bedrock"),P=Zt(x,"aws4_request"),S=Qo("sha256",P).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=${S}`}}function xc(t){let e=t.filter(r=>r.role==="system").map(r=>r.content).join(`
|
|
131
|
+
|
|
132
|
+
`),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 ut=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=xc(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 pe(s.toString(),{method:"POST",headers:kc(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 ge(i,n),await fe(u,n),{message:u,model:this.options.model,usage:{inputTokens:i?.usage?.inputTokens,outputTokens:i?.usage?.outputTokens}}}};import{spawn as Sc}from"node:child_process";async function Xo(t,e,n,r){return await new Promise((o,s)=>{let i=Sc(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(Vn(r.signal.reason)):m!==0?s(new Error(`${t} exited with code ${m}: ${c.trim()||a.trim()}`)):o({stdout:a,stderr:c})})})}function Tc(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 dt=class{options;constructor(e){this.options=e}async complete(e,n={}){let r=Yn(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 Xo(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}}},mt=class{options;constructor(e){this.options=e}async complete(e,n={}){let r=Yn(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 Xo(this.options.command||"codex",o,this.options,n),i=Tc(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 pt=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,f=Array.isArray(d)&&d.length>0?d.map(w=>`${w.model??"?"}: ${w.error??"unknown error"}`).join(" | "):void 0;throw new Error([u,m&&m!==u?m:void 0,f].filter(w=>!!(w&&w.trim())).join(" "))}if(l.message?.content&&n.onTextDelta&&await n.onTextDelta(l.message.content),n.onReasoningDelta){let u=Be(l);u&&await n.onReasoningDelta(u)}return l}finally{clearTimeout(o),n.signal?.removeEventListener("abort",s)}}};import{spawn as Pc}from"node:child_process";function Zo(t){if(!t||t.message?.role!=="assistant")throw new Error("External agent response must contain an assistant message.");return t}var ft=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=Zo(s);if(n.onReasoningDelta){let a=Be(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=Pc(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=Zo(JSON.parse(a.trim()));if(n.onReasoningDelta){let d=Be(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})}
|
|
133
|
+
`)})}};import{spawn as Ec}from"node:child_process";var es=[{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=es.find(n=>n.id===t);if(!e)throw new Error(`Unknown model provider: ${t}`);return e}async function Rc(t,e){return t.length?await new Promise((n,r)=>{let o=Ec(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 Cc(t){if(t.accessToken)return t.accessToken;if(t.credentialCommand?.length)return await Rc(t.credentialCommand,t.rootDir)}function oe(t,e){if(!t)throw new Error(e);return t}async function en(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 Cc(t),s;switch(e){case"openai-compatible":s=new gt({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 ct({baseUrl:t.baseUrl,model:r,apiKey:oe(t.apiKey,"ANTHROPIC_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"gemini":s=new qe({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:oe(t.apiKey,"XAI_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"mistral":s=new gt({baseUrl:t.baseUrl??n.defaultBaseUrl,model:r,apiKey:oe(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 lt({baseUrl:t.baseUrl,model:r,apiKey:oe(t.apiKey,"COHERE_API_KEY is required."),timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"aws-bedrock":s=new ut({baseUrl:t.baseUrl,model:r,region:oe(t.region,"AWS region is required."),accessKeyId:oe(t.awsAccessKeyId,"AWS_ACCESS_KEY_ID is required."),secretAccessKey:oe(t.awsSecretAccessKey,"AWS_SECRET_ACCESS_KEY is required."),sessionToken:t.awsSessionToken,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"google-vertex":s=new qe({baseUrl:t.baseUrl,model:r,accessToken:oe(o,"Google OAuth access token is required."),project:oe(t.project,"Google Cloud project is required."),location:oe(t.location,"Vertex AI location is required."),vertex:!0,timeoutMs:t.timeoutMs,maxOutputTokens:t.maxOutputTokens});break;case"azure-openai":{let i=oe(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 pt({baseUrl:t.baseUrl??n.defaultBaseUrl,accessToken:oe(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 ft({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 dt({command:t.command??"copilot",model:r==="default"?void 0:r,rootDir:t.rootDir??process.cwd(),timeoutMs:t.timeoutMs});break;case"chatgpt-codex":s=new mt({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 ts(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 Mc(t){return t.replace(/\/+$/,"")}function ns(t,e){return e?.aborted?Promise.reject(ht(e.reason)):new Promise((n,r)=>{let s=setTimeout(()=>{e?.removeEventListener("abort",i),n()},t),i=()=>{clearTimeout(s),e?.removeEventListener("abort",i),r(ht(e?.reason))};e?.addEventListener("abort",i,{once:!0})})}function ht(t){let e=typeof t=="string"&&t.trim()?`: ${t}`:"",n=new Error(`Model request cancelled${e}`);return n.name="AbortError",n}function $c(t){return me(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 _c(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 rs(t){return[{type:"text",text:t,cache_control:{type:"ephemeral"}}]}function Ac(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=rs(n.content));let r=e[e.length-1];return r.role==="user"&&typeof r.content=="string"&&(r.content=rs(r.content)),e}function Oc(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 os(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 ss(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 Ic(t){return!/unreachable|fetch failed|ECONNREFUSED|ECONNRESET|ENOTFOUND/i.test(t.message)}var gt=class{options;isOpenRouter;constructor(e){if(!e.model.trim())throw new Error("A model name is required.");this.options={...e,baseUrl:Mc(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=$c(e.messages);return this.isOpenRouter&&_c(this.options.model)&&(r=Ac(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=os(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 w=m.error?.message??`HTTP ${l.status}`;if((l.status===408||l.status===409||l.status===429||l.status>=500)&&a<i){await ns(500*2**a,n.signal);continue}throw new Error(`Model request failed: ${w}`)}let d=m.choices?.[0]?.message?.reasoning_content;d&&n.onReasoningDelta&&await n.onReasoningDelta(d);let f=ts(m.usage);return{message:Oc(m),model:m.model,usage:{inputTokens:m.usage?.prompt_tokens,outputTokens:m.usage?.completion_tokens,...f.read===void 0?{}:{cacheReadTokens:f.read},...f.write===void 0?{}:{cacheWriteTokens:f.write}}}}catch(l){if(r=n.signal?.aborted?ht(n.signal.reason):ss(l,this.options.baseUrl),r.name==="AbortError")break;if(a<i&&Ic(r)){await ns(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=os(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 b=await o.text(),A=`HTTP ${o.status}`;try{A=JSON.parse(b).error?.message??A}catch{b&&(A=b.slice(0,500))}throw new Error(`Model request failed: ${A}`)}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,f,w,x=new Map,P=async b=>{let A=b.trim();if(!A||A.startsWith(":")||!A.startsWith("data:"))return!1;let O=A.slice(5).trim();if(O==="[DONE]")return!0;let L;try{L=JSON.parse(O)}catch{throw new Error(`Invalid streaming JSON chunk: ${O.slice(0,300)}`)}if(L.error?.message)throw new Error(`Model request failed: ${L.error.message}`);u=L.model??u,m=L.usage?.prompt_tokens??m,d=L.usage?.completion_tokens??d;let B=ts(L.usage);f=B.read??f,w=B.write??w;let y=L.choices?.[0]?.delta;typeof y?.content=="string"&&y.content&&(c+=y.content,await n.onTextDelta?.(y.content)),typeof y?.reasoning_content=="string"&&y.reasoning_content&&(l+=y.reasoning_content,await n.onReasoningDelta?.(y.reasoning_content));for(let p of y?.tool_calls??[]){let g=p.index??x.size,k=x.get(g)??{id:p.id??`tool_call_${g+1}`,type:"function",function:{name:"",arguments:""}};p.id&&(k.id=p.id),p.function?.name&&(k.function.name+=p.function.name),p.function?.arguments&&(k.function.arguments+=p.function.arguments),x.set(g,k)}return!1},S=!1;for(;!S;){if(n.signal?.aborted)throw ht(n.signal.reason);let b=await s.read();a+=i.decode(b.value??new Uint8Array,{stream:!b.done});let A=a.split(/\r?\n/);a=A.pop()??"";for(let O of A)if(await P(O)){S=!0;break}if(b.done){a.trim()&&await P(a);break}}let C=[...x.entries()].sort(([b],[A])=>b-A).map(([,b],A)=>{if(!b.function.name)throw new Error(`Streaming tool call ${A+1} is missing a function name.`);return b});return{message:{role:"assistant",content:c||null,...C.length?{tool_calls:C}:{}},model:u,usage:{inputTokens:m,outputTokens:d,...f===void 0?{}:{cacheReadTokens:f},...w===void 0?{}:{cacheWriteTokens:w}}}}catch(o){throw n.signal?.aborted?ht(n.signal.reason):ss(o,this.options.baseUrl)}finally{r.cleanup()}}};var _e=["fast","balanced","complex","reasoning","large-context","vision","security"];function wt(t){return _e.includes(t)}var Dc=[{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 Qn(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 tn(t,e={}){let n=Qn(t,e);if(n)return n;let r=t.toLowerCase(),o=new Map;for(let l of Dc)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 Nc}from"node:child_process";var is="2025-11-25",as=new Set([is,"2025-06-18","2025-03-26"]);function ne(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be an object.`);return t}function nn(t){return t.replace(/[^a-zA-Z0-9_-]/g,"_").replace(/^_+|_+$/g,"")||"unnamed"}function Fc(t,e=200){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function cs(t){if(!t)return"[MCP tool returned no result]";let e=ne(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(`
|
|
134
|
+
`)||JSON.stringify(t,null,2)}var Xn=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=nn(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=Nc(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=ne(await this.request("initialize",{protocolVersion:is,capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.42",description:"Local-first AI coding agent"}},e),"MCP initialize result"),r=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!as.has(r))throw await this.close(),new Error(`MCP server ${this.name} negotiated unsupported protocol version ${r||"[missing]"}.`);this.serverInfo=ne(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)}
|
|
135
|
+
`)}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=ne(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=ne(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:ne(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:ne(o,"MCP tools/call result").isError!==!0,output:cs(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)})}},Zn=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=nn(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=ne(await this.request("initialize",{protocolVersion:"2025-06-18",capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.42",description:"Local-first AI coding agent"}},e),"MCP initialize result"),r=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!as.has(r))throw new Error(`MCP server ${this.name} negotiated unsupported protocol version ${r||"[missing]"}.`);this.serverInfo=ne(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(`
|
|
136
|
+
`);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(`
|
|
137
|
+
`)}}}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=ne(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=ne(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:ne(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:ne(o,"MCP tools/call result").isError!==!0,output:cs(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 Xn(s,i):new Zn(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_${nn(s.name)}_${nn(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}] ${Fc(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 Bc="2025-11-25",qc=["2025-11-25","2025-06-18","2025-03-26"];function Jc(t){return t.map(e=>({name:e.function.name,description:e.function.description,inputSchema:e.function.parameters??{type:"object",properties:{}}}))}function ls(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be an object.`);return t}var rn=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=ls(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:qc.includes(r)?r:Bc,capabilities:{tools:{listChanged:!1}},serverInfo:{name:this.name,version:this.version}}}case"ping":return{};case"tools/list":{let r=Jc(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=ls(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 us(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 ms(t){await new Promise((e,n)=>{let r="";process.stdin.setEncoding("utf8");let o=(s,i=!1)=>{r+=s;let a=r.indexOf(`
|
|
138
|
+
`);for(;a!==-1;){let c=r.slice(0,a);r=r.slice(a+1);let l=us(c);l&&ds(t,l),a=r.indexOf(`
|
|
139
|
+
`)}if(i&&r.trim()){let c=us(r.trim());c&&ds(t,c),r=""}};process.stdin.on("data",s=>o(s)),process.stdin.on("end",()=>{o("",!0),e()}),process.stdin.on("error",n)})}async function ds(t,e){let n=await t.dispatch(e);n&&process.stdout.write(`${JSON.stringify(n)}
|
|
140
|
+
`)}var ce={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"}},Kc=[/\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],Wc=[/^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 Gc(t){let e=t.trim();if(Kc.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=>Wc.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 yt(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=ce){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.",yt(n));case"write_file":case"replace_in_file":case"make_directory":return r==="plan"?Z(e,"filesystem.write","deny","Plan mode cannot change files.",yt(n)):Z(e,"filesystem.write",this.policy.filesystem.write,"Changes a project file.",yt(n));case"delete_path":return r==="plan"?Z(e,"filesystem.delete","deny","Plan mode cannot delete files.",yt(n)):Z(e,"filesystem.delete",this.policy.filesystem.delete,"Deletes a path inside the project.",yt(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=U(n,"command",{maximumLength:2e4}),s=Gc(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 Hc,readFile as zc,rename as Vc,stat as Yc,writeFile as Qc}from"node:fs/promises";import{randomUUID as tr}from"node:crypto";import er from"node:path";async function Xc(t){try{return await Yc(t),!0}catch{return!1}}async function fs(t,e){await Hc(er.dirname(t),{recursive:!0});let n=`${t}.${tr()}.tmp`;await Qc(n,`${JSON.stringify(e,null,2)}
|
|
141
|
+
`,"utf8"),await Vc(n,t)}function Zc(){return{schemaVersion:1,rules:[],feedback:[]}}function el(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 tl(t){return t.split(/\r?\n/).filter(e=>e.startsWith("+")&&!e.startsWith("+++")).map(e=>e.slice(1))}function nl(t){return t.split(/\r?\n/).filter(e=>e.startsWith("+++ b/")).map(e=>e.slice(6))}function rl(t){let e=tl(t),n=nl(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 ol(t){return t.trim().replace(/\s+/g," ")}function gs(t,e){let n=ol(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:tr(),text:n,polarity:e.polarity,confidence:e.confidence,evidenceCount:1,createdAt:o,updatedAt:o,sources:[e.source]};return t.rules.push(s),s}var on=class{rootDir;filePath;constructor(e){this.rootDir=er.resolve(e),this.filePath=er.join(this.rootDir,E,"preferences.json")}async readDocument(){return await Xc(this.filePath)?el(await zc(this.filePath,"utf8")):Zc()}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(gs(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 rl(s))r.push(gs(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:tr(),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 fs(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 fs(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(`
|
|
142
|
+
`)}};import{mkdir as sl,readFile as hs,readdir as il,rename as al,rm as cl,stat as ll,writeFile as ul}from"node:fs/promises";import{randomUUID as bs}from"node:crypto";import We from"node:path";function nr(t){let e=t.trim();if(!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/.test(e))throw new Error("Session ID may contain only letters, numbers, underscores, and hyphens.");return e}async function ws(t){try{return await ll(t),!0}catch{return!1}}async function dl(t,e){await sl(We.dirname(t),{recursive:!0});let n=`${t}.${process.pid??"tmp"}.${bs()}.tmp`;await ul(n,`${JSON.stringify(e,null,2)}
|
|
143
|
+
`,"utf8"),await al(n,t)}function ys(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 sn=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,`${nr(e)}.json`)}async create(e){let n=new Date().toISOString(),o={schemaVersion:1,id:bs(),title:e.title?.trim()||`Session ${n.slice(0,16).replace("T"," ")}`,rootDir:this.rootDir,createdAt:n,updatedAt:n,mode:e.mode,model:e.model,messages:[],runs:[]};return await this.save(o),o}async save(e){if(nr(e.id),We.resolve(e.rootDir)!==this.rootDir)throw new Error("Session belongs to a different project root.");e.updatedAt=new Date().toISOString(),await dl(this.filePath(e.id),e)}async load(e){let n=await this.resolveId(e),r=this.filePath(n);return ys(await hs(r,"utf8"),r)}async resolveId(e){let n=nr(e),r=this.filePath(n);if(await ws(r))return n;let s=(await this.list()).filter(i=>i.id.startsWith(n));if(s.length===0)throw new Error(`Session not found: ${e}`);if(s.length>1)throw new Error(`Session prefix is ambiguous: ${e}`);return s[0].id}async list(){if(!await ws(this.directory))return[];let e=await il(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=ys(await hs(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 cl(this.filePath(n),{force:!1})}};import{readFile as ml,readdir as pl,stat as fl}from"node:fs/promises";import{homedir as gl}from"node:os";import bt from"node:path";async function vs(t){try{return await fl(t),!0}catch{return!1}}function hl(t){if(!t.startsWith(`---
|
|
111
144
|
`))return{metadata:{},body:t.trim()};let e=t.indexOf(`
|
|
112
145
|
---
|
|
113
|
-
`,4);if(e<0)return{metadata:{},body:t.trim()};let n={};for(let
|
|
146
|
+
`,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 xs(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 ks(t,e){if(!await vs(t))return[];let n=await pl(t,{withFileTypes:!0}),r=[];for(let o of n){let s,i=o.name;if(o.isDirectory()?s=bt.join(t,o.name,"SKILL.md"):o.isFile()&&o.name.endsWith(".md")&&(s=bt.join(t,o.name),i=o.name.slice(0,-3)),!s||!await vs(s))continue;let a=hl(await ml(s,"utf8")),c=xs(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 an=class{rootDir;projectDirectory;globalDirectory;constructor(e,n=bt.join(gl(),".config","kpilot","skills")){this.rootDir=bt.resolve(e),this.projectDirectory=bt.join(this.rootDir,E,"skills"),this.globalDirectory=n}async list(){let[e,n]=await Promise.all([ks(this.globalDirectory,"global"),ks(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=xs(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
147
|
|
|
115
148
|
Skill instructions:
|
|
116
|
-
${
|
|
149
|
+
${r.instructions}
|
|
117
150
|
|
|
118
151
|
Invocation arguments:
|
|
119
|
-
${n.trim()||"[none]"}`}};var
|
|
152
|
+
${n.trim()||"[none]"}`}};var vt=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 br,open as Zl,readFile as dn,readdir as eu,realpath as wr,rm as tu,stat as De,writeFile as vr}from"node:fs/promises";import K from"node:path";import{spawn as Js}from"node:child_process";import{spawn as wl}from"node:child_process";import{realpath as Ss}from"node:fs/promises";import cn from"node:path";var yl=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 bl(t){return process.platform==="win32"?Promise.resolve(!1):new Promise(e=>{let n=wl("/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 vl(t){let e=new Set([...yl,...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 ln=class{rootDir;config;constructor(e,n={}){if(this.rootDir=cn.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 bl("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=cn.resolve(n),[s,i]=await Promise.all([Ss(this.rootDir).catch(()=>this.rootDir),Ss(o).catch(()=>o)]),a=cn.relative(s,i);if(a.startsWith("..")||cn.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:vl(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 kl}from"node:dns/promises";import{isIP as sr}from"node:net";var xl="https://api.search.brave.com/res/v1/web/search",Es="https://html.duckduckgo.com/html/",Sl="https://api.tavily.com/search",Tl="https://api.exa.ai/search",Pl="https://google.serper.dev/search",El=5,Rl=10,Oe=2e4,Cl=1e6,Ml=5e4,$l=2e5,rr=5;function ar(t=process.env){return t.BRAVE_API_KEY?.trim()||t.BRAVE_SEARCH_API_KEY?.trim()||void 0}function _l(t=process.env){let e=ar(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 cr(t=process.env){return t.TAVILY_API_KEY?.trim()||void 0}function Al(t=process.env){let e=cr(t);if(!e)throw new Error("Tavily search requires TAVILY_API_KEY. Get a key at https://tavily.com/");return e}function lr(t=process.env){return t.EXA_API_KEY?.trim()||void 0}function Ol(t=process.env){let e=lr(t);if(!e)throw new Error("Exa search requires EXA_API_KEY. Get a key at https://exa.ai/");return e}function ur(t=process.env){return t.SERPER_API_KEY?.trim()||void 0}function Il(t=process.env){let e=ur(t);if(!e)throw new Error("Serper search requires SERPER_API_KEY. Get a key at https://serper.dev/");return e}function dr(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??El,1),Rl)}function Rs(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 Ts(t){return Rs(t.replace(/<[^>]+>/g," ").replace(/\s+/g," ").trim())}function Dl(t){try{let e=new URL(t,Es);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 jl(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=Dl(Rs(s[1]??"")).trim();if(!i||!/^https?:\/\//i.test(i)||r.has(i))continue;let a=Ts(s[2]??"")||i,l=(s[3]??"").match(/class="[^"]*result__snippet[^"]*"[^>]*>([\s\S]*?)<\/(?:a|td|div)/i),u=l?Ts(l[1]??""):"";r.add(i),n.push({title:a,url:i,description:u})}return n}function Ll(t){let e=t.trim().toLowerCase().replace(/\.$/,"");return!!(!e||e==="localhost"||e.endsWith(".localhost")||e.endsWith(".local")||e==="metadata.google.internal"||e==="metadata")}function ir(t){let e=sr(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(sr(r)===4)return ir(r)}return!1}return!0}async function mr(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(Ll(n))throw new Error(`Blocked hostname: ${n}`);if(sr(n)){if(ir(n))throw new Error(`Blocked IP address: ${n}`);return e}let o;try{o=await kl(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(ir(s.address))throw new Error(`Hostname ${n} resolves to blocked address ${s.address}`);return e}function kt(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
153
|
`).replace(/<[^>]+>/g," ").replace(/ /gi," ").replace(/&/gi,"&").replace(/</gi,"<").replace(/>/gi,">").replace(/"/gi,'"').replace(/'/gi,"'").replace(/\r/g,"").replace(/[ \t]+\n/g,`
|
|
121
154
|
`).replace(/\n{3,}/g,`
|
|
122
155
|
|
|
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)}
|
|
156
|
+
`).replace(/[ \t]{2,}/g," ").trim()}async function Ul(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 Nl(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(Es,{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=jl(i,n);return{query:e,count:a.length,results:a,provider:"duckduckgo"}}async function Fl(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??_l(),o=new URL(xl);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 Bl(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??Al(),s=await(t.fetchImpl??fetch)(Sl,{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 ql(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??Ol(),s=await(t.fetchImpl??fetch)(Tl,{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 Jl(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.apiKey??Il(),s=await(t.fetchImpl??fetch)(Pl,{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 Kl(t){let e=t.query.trim();if(!e)throw new Error("query is required.");let n=Ge(t.count),r=t.baseUrl??dr();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 or(t,e){let{query:n,count:r,signal:o,fetchImpl:s,env:i}=e;switch(t){case"duckduckgo":return Nl({query:n,count:r,signal:o,fetchImpl:s});case"tavily":return Bl({query:n,count:r,signal:o,fetchImpl:s,apiKey:cr(i)});case"exa":return ql({query:n,count:r,signal:o,fetchImpl:s,apiKey:lr(i)});case"serper":return Jl({query:n,count:r,signal:o,fetchImpl:s,apiKey:ur(i)});case"searxng":return Kl({query:n,count:r,signal:o,fetchImpl:s,baseUrl:dr(i)});case"brave":return Fl({query:n,count:r,signal:o,fetchImpl:e.braveFetchImpl??s,apiKey:ar(i)})}}function Ps(t,e){switch(t){case"duckduckgo":return!0;case"tavily":return!!cr(e);case"exa":return!!lr(e);case"serper":return!!ur(e);case"searxng":return!!dr(e);case"brave":return!!ar(e)}}var Wl=["tavily","exa","serper","searxng","brave"];async function Cs(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(!Ps(t.provider,e))throw new Error(`Web search provider "${t.provider}" is not configured. Set the required key or enabling variable.`);return await or(t.provider,r)}let o;try{let s=await or("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 Wl)if(Ps(s,e))try{let i=await or(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 Ms(t){let e=Math.min(Math.max(t.maxChars??Ml,1),$l),n=t.fetchImpl??fetch,r=t.assertPublicUrlFn??mr,o=await r(t.url),s,i=0;for(;i<=rr;){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>rr)throw new Error(`Too many redirects (max ${rr}).`);if(!s.ok)throw new Error(`HTTP ${s.status} fetching ${o.href}`);let a=s.headers.get("content-type")??void 0,c=await Ul(s,Cl),l=new TextDecoder().decode(c),u=a&&/html|xml|sgml/i.test(a)||/html/i.test(l.slice(0,512))?kt(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 gr,spawnSync as Gl}from"node:child_process";import{mkdir as _s,writeFile as Hl}from"node:fs/promises";import{tmpdir as zl}from"node:os";import Ie from"node:path";var xt="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.",Vl=["google-chrome-stable","google-chrome","chromium-browser","chromium","microsoft-edge","microsoft-edge-stable"],Yl=["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome","/Applications/Chromium.app/Contents/MacOS/Chromium","/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"],He;function pr(t){try{let e=Gl(t,["--version"],{timeout:3e3,stdio:"ignore"});return e.error===void 0&&e.status===0}catch{return!1}}function St(t=process.env){if(He!==void 0)return He||void 0;let e=t.KPILOT_CHROME_PATH?.trim();if(e&&pr(e))return He=e,e;for(let n of Vl)if(pr(n))return He=n,n;for(let n of Yl)if(pr(n))return He=n,n;He=null}function $s(t){return new Promise(e=>{setTimeout(()=>e(),t)})}var As=1280,Os=1200,fr=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(zl(),`kpilot-browser-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,7)}`),r=gr(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 $s(120)}r==="networkidle2"&&await $s(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=As,o=Os;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 _s(a,{recursive:!0});let c=Ie.join(".kpilot","run",`browser-${Date.now().toString(36)}.png`);return await Hl(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 Tt(){if(ze)return ze;let t=St();if(!t)throw new Error(xt);return ze=await fr.launch(t),ze}async function Is(){await ze?.close(),ze=void 0}async function hr(t){let n=(await mr(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 Tt();await i.navigate(n,s,o);let a=await i.readPage(r);return{mode:"cdp",...a,title:a.title||n}}catch{let a=await Ql(n);return{mode:"static",url:n,title:String(a.title??""),text:a.text.slice(0,r),truncated:a.text.length>r}}}async function Ds(t){let e=t.fullPage===!0;t.url&&await hr({url:t.url,waitUntil:"load",waitMs:15e3,maxChars:4e3});try{return{path:await(await Tt()).screenshot(e,t.rootDir),mode:"cdp"}}catch{if(t.url){let n=await Xl(t.url,e,t.rootDir);if(n)return{path:n,mode:"static"}}throw new Error("Unable to capture a screenshot without a browser. "+xt)}}async function js(t){return await(await Tt()).click(t)}async function Ls(t,e){return await(await Tt()).typeText(t,e)}async function Us(t){return await(await Tt()).evaluateExpression(t)}async function Ql(t){let e=St();if(!e)throw new Error(xt);let n=await new Promise((o,s)=>{let i=gr(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:kt(r?.[1]??""),text:kt(n)}}async function Xl(t,e,n){let r=St();if(!r)return null;let o=Ie.join(n,".kpilot","run");await _s(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=${As},${Os*3}`),a.push(`--screenshot=${i}`,t),await new Promise(l=>{let u=gr(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 nu=new Set([".git","node_modules","dist","build",".next",".turbo","coverage",".cache",".idea"]),kr=1e6,xr=2e5,ru=/(?:✓\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,Ns=/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,ou=/\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 Pt(t,e=xr){if(t.length<=e)return t;let n=t.length-e;return`${t.slice(0,e)}
|
|
124
157
|
|
|
125
|
-
[output truncated: ${n} characters omitted]`}function
|
|
158
|
+
[output truncated: ${n} characters omitted]`}function Sr(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 un(t,e,n){let r=n.timeoutMs??3e4,o=n.env??process.env;return await new Promise((s,i)=>{let a=Js(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="",f=P=>{if(!n.onOutput)return;d+=P;let S=d.split(/\r?\n/);d=S.pop()??"";for(let C of S)n.onOutput(C)};a.stdout?.on("data",P=>{c.length<xr*2&&(c+=P),f(P)}),a.stderr?.on("data",P=>{l.length<xr*2&&(l+=P),f(P)});let w=()=>{m=!0,a.kill("SIGTERM"),setTimeout(()=>a.kill("SIGKILL"),1e3)};n.signal?.aborted?w():n.signal?.addEventListener("abort",w,{once:!0});let x=setTimeout(()=>{u=!0,a.kill("SIGTERM"),setTimeout(()=>a.kill("SIGKILL"),1e3)},r);a.once("error",P=>{clearTimeout(x),n.signal?.removeEventListener("abort",w),i(P)}),a.once("close",P=>{clearTimeout(x),n.signal?.removeEventListener("abort",w),s({code:P??1,stdout:Pt(Sr(c,o)),stderr:Pt(Sr(l,o)),timedOut:u,cancelled:m})})})}function yr(t,e){let n=K.relative(t,e);return n===""||!n.startsWith("..")&&!K.isAbsolute(n)}async function su(t){let e=t;for(;;)try{return await De(e),e}catch{let n=K.dirname(e);if(n===e)throw new Error(`No existing ancestor found for ${t}`);e=n}}var Tr=class{rootDir;canonicalRoot;constructor(e){this.rootDir=K.resolve(e)}async root(){this.canonicalRoot??=await wr(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=K.resolve(r,e||".");if(!yr(r,o))throw new Error(`Path escapes the project root: ${e}`);if(n.mustExist){let a=await wr(o);if(!yr(r,a))throw new Error(`Resolved path escapes the project root: ${e}`);return a}let s=await su(o),i=await wr(s);if(!yr(r,i))throw new Error(`Path crosses a symlink outside the project root: ${e}`);return o}};function J(t,e,n,r=[]){return{type:"function",function:{name:t,description:e,parameters:{type:"object",properties:n,required:r,additionalProperties:!1}}}}var Fs=[J("workspace_summary","Return a concise repository overview, top-level files, detected manifests, and Git status.",{}),J("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."}}),J("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"]),J("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"]),J("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"]),J("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"]),J("make_directory","Create a directory recursively inside the project.",{path:{type:"string"}},["path"]),J("delete_path","Delete a file, or a directory only when recursive is explicitly true.",{path:{type:"string"},recursive:{type:"boolean"}},["path"]),J("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"]),J("git_status","Show concise Git working-tree status.",{}),J("git_diff","Show the current Git diff, optionally staged and optionally limited to a path.",{staged:{type:"boolean"},path:{type:"string"}}),J("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"]),J("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"])],iu=[J("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"]),J("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."}}),J("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"]),J("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"]),J("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"]),J("browser_close","Close the browser session and release the Chromium process.",{})];async function Bs(t){try{return await De(t),!0}catch{return!1}}async function Pr(t,e,n,r){let o=[];async function s(i,a){if(o.length>=r)return;let c=await eu(i,{withFileTypes:!0});c.sort((l,u)=>l.name.localeCompare(u.name));for(let l of c){if(o.length>=r)break;if(nu.has(l.name))continue;let u=K.join(i,l.name),m=K.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 au(t,e,n,r,o){let s=r?new RegExp(n,"i"):void 0,i=await Pr(t,e,8,5e3),a=[];for(let c of i){if(!c.startsWith("f "))continue;let l=c.slice(2),u=K.join(e,l);if((await De(u)).size>kr)continue;let d;try{d=await dn(u,"utf8")}catch{continue}if(d.includes("\0"))continue;let f=d.split(/\r?\n/);for(let w=0;w<f.length;w+=1){let x=f[w]??"";if((s?s.test(x):x.toLowerCase().includes(n.toLowerCase()))&&a.push(`${l}:${w+1}:${x}`),a.length>=o)return a}}return a}function cu(t){let e=[`exit_code: ${t.code}`,`timed_out: ${t.timedOut}`,`cancelled: ${t.cancelled}`];return t.stdout&&e.push(`stdout:
|
|
126
159
|
${t.stdout}`),t.stderr&&e.push(`stderr:
|
|
127
160
|
${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:
|
|
161
|
+
`)}function lu(t){return ou.test(t.trim())}function uu(t){return new Promise(e=>{setTimeout(()=>e(),t)})}async function Er(t,e=4e3){try{let n=await dn(t,"utf8");return n.length<=e?n:n.slice(-e)}catch{return""}}async function du(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 Er(t.logPath,8e4);if(Ns.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 uu(250)}try{process.kill(t.pid,0);let n=await Er(t.logPath,8e4);return Ns.test(n)?{ready:!1,failed:!0,exitedEarly:!1}:{ready:!1,failed:!1,exitedEarly:!1}}catch{return{ready:!1,failed:!1,exitedEarly:!0}}}function mu(t){let e=t.match(/https?:\/\/(?:localhost|127\.0\.0\.1):\d+\b/gi)??[];return[...new Set(e.map(n=>n.replace(/\/$/,"")))]}async function qs(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 pu(t){let e=K.join(t.rootDir,E,"run");await br(e,{recursive:!0});let n=`bg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`,r=K.join(E,"run",`${n}.log`),o=K.join(E,"run",`${n}.json`),s=K.join(t.rootDir,r),i=K.join(t.rootDir,o),a=await Zl(s,"a"),c;try{c=Js(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 vr(i,`${JSON.stringify(u,null,2)}
|
|
162
|
+
`,"utf8");let m=null;c.once("exit",A=>{m=A});let d=t.readyPattern?new RegExp(t.readyPattern,"i"):ru,f=await du({logPath:s,pid:l,pattern:d,waitMs:t.waitMs,signal:t.signal}),w=Sr(await Er(s),t.env),x=mu(w),P=f.ready?await qs(x):void 0;!f.ready&&!f.failed&&!f.exitedEarly&&x.length>0&&(P=await qs(x));let S=(()=>{try{return process.kill(l,0),m===null}catch{return!1}})(),C=!!(S&&(f.ready||P?.ok)&&!f.failed&&m===null),b=()=>{try{process.kill(-l,"SIGTERM")}catch{try{process.kill(l,"SIGTERM")}catch{}}};return f.exitedEarly||m!==null||!S?{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}`,w?`--- log ---
|
|
163
|
+
${Pt(w)}`:"[empty log]"].join(`
|
|
164
|
+
`),metadata:{background:!0,pid:l,id:n,log:r,ready:!1}}:f.failed||!C?(b(),{ok:!1,output:[`Background process started (pid=${l}) but is NOT ready. Do not tell the user the server is up.`,`command: ${t.originalCommand}`,f.failed?"ready: no (failure detected in log \u2014 install/build/runtime error)":`ready: no (no server startup line after ${t.waitMs}ms; http probe ${P?.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.",w?`--- log (tail) ---
|
|
165
|
+
${Pt(w)}`:"[empty log so far]"].join(`
|
|
166
|
+
`),metadata:{background:!0,pid:l,id:n,log:r,ready:!1,failed:f.failed}}):{ok:!0,output:[`Started background process pid=${l} id=${n}`,`command: ${t.originalCommand}`,f.ready?"ready: yes (matched startup pattern in log)":`ready: yes (HTTP probe succeeded at ${P?.url})`,P?.url?`url: ${P.url}`:x[0]?`url: ${x[0]} (from log)`:void 0,`log: ${r}`,`meta: ${o}`,`sandbox: ${t.backend}`,"Process keeps running after this tool returns.",w?`--- log (tail) ---
|
|
167
|
+
${Pt(w)}`:"[empty log so far]"].filter(Boolean).join(`
|
|
168
|
+
`),metadata:{background:!0,pid:l,id:n,log:r,ready:!0,url:P?.url??x[0]}}}function fu(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 ye=class{rootDir;guard;sandbox;browserEnabled;browserClosed=!1;constructor(e,n={}){this.rootDir=K.resolve(e),this.guard=new Tr(this.rootDir),this.sandbox=new ln(this.rootDir,n.sandbox);let r=n.browser??"auto";this.browserEnabled=r==="on"?!0:r==="off"?!1:St()!==void 0}definitions(){return this.browserEnabled?[...Fs,...iu]:Fs}async execute(e,n,r){if(K.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 Pr(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 Bs(K.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
169
|
`)}
|
|
137
|
-
\u2026[${s.length-i} more git status lines omitted]`,c=[`root: ${this.rootDir}`,`manifests: ${
|
|
170
|
+
\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
171
|
`),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]`}}async listFiles(e){let n=
|
|
140
|
-
`)||"[empty directory]"}}async readFile(e){let n=
|
|
141
|
-
`),metadata:{total_lines:c.length,start_line:
|
|
142
|
-
`)||"[no matches]"}}catch{}return{ok:!0,output:(await
|
|
143
|
-
`)||"[no matches]"}}async writeFile(e){let n=
|
|
144
|
-
sandbox: ${d.backend}`,metadata:{sandbox:d.backend}}}async gitStatus(e){try{let n=await
|
|
172
|
+
\u2026[workspace_summary truncated ${c.length-l} chars for hub context]`}}async listFiles(e){let n=X(e,"path")??".",r=te(e,"max_depth",3,0,8),o=te(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.`);return{ok:!0,output:(await Pr(s,this.rootDir,r,o)).join(`
|
|
173
|
+
`)||"[empty directory]"}}async readFile(e){let n=U(e,"path"),r=te(e,"start_line",1,1,1e7),o=te(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>kr)throw new Error(`File exceeds ${kr} bytes.`);let a=await dn(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(`
|
|
174
|
+
`),metadata:{total_lines:c.length,start_line:r,end_line:Math.min(o,c.length)}}}async searchText(e){let n=U(e,"query",{maximumLength:2e3}),r=X(e,"path")??".",o=Me(e,"regex",!1),s=te(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 un("rg",a,{cwd:this.rootDir,timeoutMs:15e3});if(l.code===0||l.code===1)return{ok:!0,output:l.stdout.split(/\r?\n/).filter(Boolean).slice(0,s).map(m=>m.replace(`${this.rootDir}${K.sep}`,"")).join(`
|
|
175
|
+
`)||"[no matches]"}}catch{}return{ok:!0,output:(await au(i,this.rootDir,n,o,s)).join(`
|
|
176
|
+
`)||"[no matches]"}}async writeFile(e){let n=U(e,"path"),r=X(e,"content_b64"),o;if(r!==void 0){if(o=fu(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=U(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 Bs(i))throw new Error(`${n} already exists.`);await br(K.dirname(i),{recursive:!0}),await vr(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=U(e,"path"),r=U(e,"old_string",{allowEmpty:!1}),o=U(e,"new_string",{allowEmpty:!0}),s=te(e,"expected_occurrences",1,1,1e3),i=await this.guard.resolve(n,{mustExist:!0}),a=await dn(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 vr(i,l,"utf8"),{ok:!0,output:`Replaced ${c} occurrence(s) in ${n}.`}}async makeDirectory(e){let n=U(e,"path"),r=await this.guard.resolve(n);return await br(r,{recursive:!0}),{ok:!0,output:`Created directory ${n}.`}}async deletePath(e){let n=U(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 tu(o,{recursive:r,force:!1}),{ok:!0,output:`Deleted ${n}.`}}async shell(e,n,r){let o=U(e,"command",{maximumLength:2e4}),s=X(e,"cwd")??".",i=te(e,"timeout_ms",3e4,100,36e5),a=e.background===void 0?lu(o):Me(e,"background",!1),c=te(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 pu({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 f=await un(d.command,d.args,{cwd:d.cwd,timeoutMs:d.timeoutMs,env:d.env,signal:n,...r?{onOutput:r}:{}});return{ok:f.code===0&&!f.timedOut&&!f.cancelled,output:`${cu(f)}
|
|
177
|
+
sandbox: ${d.backend}`,metadata:{sandbox:d.backend}}}async gitStatus(e){try{let n=await un("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 un("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=U(e,"query",{maximumLength:500}),o=te(e,"count",5,1,10),s=X(e,"provider"),i=await Cs({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=U(e,"url",{maximumLength:2e3}),o=te(e,"max_chars",5e4,1,2e5),s=await Ms({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
178
|
`)}
|
|
146
179
|
|
|
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=
|
|
180
|
+
${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=U(e,"url",{maximumLength:2e3}),r=X(e,"wait_until"),o=te(e,"wait_ms",15e3,1e3,6e4),s=te(e,"max_chars",5e4,1,2e5),i=await hr({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
181
|
`)}
|
|
149
182
|
|
|
150
|
-
${i.text}`,metadata:{mode:i.mode,url:i.url,truncated:i.truncated}}}async browserScreenshot(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=
|
|
183
|
+
${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 Ds({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=U(e,"selector",{maximumLength:2e3});return{ok:!0,output:await js(n)}}async browserType(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=U(e,"selector",{maximumLength:2e3}),r=U(e,"text",{maximumLength:2e4});return{ok:!0,output:await Ls(n,r)}}async browserEvaluate(e){if(!this.browserToolsAvailable())return this.browserUnavailable();let n=U(e,"expression",{maximumLength:1e4});return{ok:!0,output:await Us(n)}}async browserClose(){return await Is(),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). "+xt}}};var Gs={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 Ks(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 gu(){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 hu(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=U(s,"role");if(!(i in Gs))throw new Error(`Unsupported subagent role: ${i}`);let a=Ks(s,"route");if(a&&!wt(a))throw new Error(`tasks[${o}].route must be one of ${_e.join(", ")}.`);let c=Ks(s,"model");return{role:i,task:U(s,"task",{maximumLength:1e4}),...a?{route:a}:{},...c?{model:c}:{}}})}var wu=12,Ws=4e3,mn=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[gu()]}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=hu(n,this.options.maxParallel),s=await Promise.all(o.map(async i=>{let a=new ye(this.options.rootDir,this.options.localRuntimeOptions),c=new Ke({...ce,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:`${Gs[i.role]}
|
|
151
184
|
|
|
152
185
|
Assigned task:
|
|
153
|
-
${i.task}`,mode:"plan",rootDir:this.options.rootDir,maxSteps:this.options.maxSteps,approvalHandler:async()=>!1,signal:
|
|
186
|
+
${i.task}`,mode:"plan",rootDir:this.options.rootDir,maxSteps:this.options.maxSteps??wu,approvalHandler:async()=>!1,signal:r.signal}),f=d.answer.length>Ws?`${d.answer.slice(0,Ws)}
|
|
187
|
+
\u2026[subagent answer truncated]`:d.answer;return{role:i.role,task:i.task,ok:!0,answer:f,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
188
|
`)}).join(`
|
|
155
189
|
|
|
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
|
|
190
|
+
`),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 yu,realpath as Et,rm as bu,stat as vu}from"node:fs/promises";import be from"node:path";import{spawn as ku}from"node:child_process";function Rt(t,e){return new Promise((n,r)=>{let o=ku("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 Hs(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 zs(t){try{return await vu(t),!0}catch{return!1}}var Ct=class{rootDir;storageDir;constructor(e){this.rootDir=be.resolve(e),this.storageDir=be.join(be.dirname(this.rootDir),`.${be.basename(this.rootDir)}-kpilot-worktrees`)}async assertRepository(){let e=await Rt(this.rootDir,["rev-parse","--show-toplevel"]);if(e.code!==0)throw new Error(e.stderr.trim()||"Not a Git repository.");let n=be.resolve(e.stdout.trim()),r=await Et(this.rootDir);if(n!==r)throw new Error(`Use the repository root as --cwd: ${n}`)}pathFor(e){return be.join(this.storageDir,Hs(e))}async create(e,n={}){await this.assertRepository();let r=Hs(e),o=this.pathFor(r);if(await zs(o))throw new Error(`Worktree path already exists: ${o}`);await yu(this.storageDir,{recursive:!0});let s=n.branch?.trim()||`kpilot/${r}`,i=n.base?.trim()||"HEAD",a=await Rt(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 Et(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 Rt(this.rootDir,["worktree","list","--porcelain"]);if(e.code!==0)throw new Error(e.stderr.trim()||"Unable to list worktrees.");let n=await Et(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 Et(i).catch(()=>i),c=be.relative(n,a),l=c!==""&&!c.startsWith("..")&&!be.isAbsolute(c);o={path:a,bare:!1,detached:!1,managed:l,name:l?c.split(be.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 Et(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 Rt(this.rootDir,a);if(c.code!==0)throw new Error(c.stderr.trim()||c.stdout.trim()||"Unable to remove worktree.");await zs(r)&&await bu(r,{recursive:!0,force:!0})}async prune(){await this.assertRepository();let e=await Rt(this.rootDir,["worktree","prune"]);if(e.code!==0)throw new Error(e.stderr.trim()||"Unable to prune worktrees.")}};import{appendFile as xu,mkdir as Vs,readFile as Su,rm as Ys,stat as Xs}from"node:fs/promises";import{createHash as Tu,randomUUID as Pu}from"node:crypto";import{hostname as Eu,userInfo as Ru}from"node:os";import pn from"node:path";function Rr(t){if(Array.isArray(t))return`[${t.map(Rr).join(",")}]`;if(t&&typeof t=="object"){let e=t;return`{${Object.keys(e).sort().map(n=>`${JSON.stringify(n)}:${Rr(e[n])}`).join(",")}}`}return JSON.stringify(t)}function Qs(t){return Tu("sha256").update(Rr(t)).digest("hex")}async function Cu(t){try{return await Xs(t),!0}catch{return!1}}function Mu(){try{return Ru().username||"unknown"}catch{return"unknown"}}var fn=class{rootDir;filePath;lockPath;constructor(e){this.rootDir=pn.resolve(e),this.filePath=pn.join(this.rootDir,E,"audit","audit.jsonl"),this.lockPath=pn.join(this.rootDir,E,"audit",".append-lock")}async parseAll(){if(!await Cu(this.filePath))return[];let e=await Su(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 Vs(pn.dirname(this.lockPath),{recursive:!0});let n=Date.now();for(;;)try{return await Vs(this.lockPath),async()=>{await Ys(this.lockPath,{recursive:!0,force:!0})}}catch(r){if(r.code!=="EEXIST")throw r;try{let s=await Xs(this.lockPath);if(Date.now()-s.mtimeMs>3e4){await Ys(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:Pu(),timestamp:new Date().toISOString(),actor:e.actor?.trim()||Mu(),host:Eu(),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:Qs(s)};return await xu(this.filePath,`${JSON.stringify(i)}
|
|
191
|
+
`,{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=Qs(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 $u,mkdir as _u,readFile as Au,stat as Ou}from"node:fs/promises";import{randomUUID as Iu}from"node:crypto";import Cr from"node:path";async function Du(t){try{return await Ou(t),!0}catch{return!1}}function gn(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 ju(t){let e={dailyInputTokens:gn(t.dailyInputTokens,"dailyInputTokens"),dailyOutputTokens:gn(t.dailyOutputTokens,"dailyOutputTokens"),dailyTotalTokens:gn(t.dailyTotalTokens,"dailyTotalTokens"),perRunTotalTokens:gn(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 hn=class{rootDir;filePath;constructor(e){this.rootDir=Cr.resolve(e),this.filePath=Cr.join(this.rootDir,E,"usage","usage.jsonl")}async records(){return await Du(this.filePath)?(await Au(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:Iu(),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 _u(Cr.dirname(this.filePath),{recursive:!0}),await $u(this.filePath,`${JSON.stringify(l)}
|
|
192
|
+
`,{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=ju(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 Lu,mkdir as Uu,readFile as Nu,rename as Fu,rm as Bu,writeFile as qu}from"node:fs/promises";import{homedir as Ju,hostname as Ku}from"node:os";import Mr from"node:path";var Mt=class extends Error{status;code;constructor(e,n,r){super(e),this.name="ControlPlaneError",this.status=n,this.code=r}};function Wu(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 le=class{baseUrl;userAgent;constructor(e="https://api.konsolepilot.ai",n="kpilot CLI"){this.baseUrl=Wu(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 Mt(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??Ku(),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 Mt))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})}},se=class{filePath;constructor(e=Mr.join(Ju(),".config","kpilot","cloud-auth.json")){this.filePath=Mr.resolve(e)}async load(){try{let e=JSON.parse(await Nu(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 Uu(Mr.dirname(this.filePath),{recursive:!0,mode:448});let n=`${this.filePath}.${process.pid??"tmp"}.tmp`;await qu(n,`${JSON.stringify(e,null,2)}
|
|
193
|
+
`,{encoding:"utf8",mode:384}),await Fu(n,this.filePath),await Lu(this.filePath,384)}async clear(){try{await Bu(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 le(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 Mt&&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 Gu,mkdir as Zs,readFile as $r,readdir as Hu,stat as oi,writeFile as ei}from"node:fs/promises";import{createCipheriv as zu,createDecipheriv as Vu,randomBytes as ti,scryptSync as Yu}from"node:crypto";import ee from"node:path";var Qu=[`${E}/instructions.md`,`${E}/memory.json`,`${E}/preferences.json`,`${E}/team-policy.json`,`${E}/skills`];async function wn(t){try{return await oi(t),!0}catch{return!1}}async function _r(t,e,n){let r=ee.join(t,e);if(!await wn(r))return;let o=await Hu(r,{withFileTypes:!0});for(let s of o){let i=ee.posix.join(e.replaceAll("\\","/"),s.name);if(s.isDirectory())await _r(t,i,n);else if(s.isFile()){let a=await $r(ee.join(t,i));n.push({path:i,contentBase64:a.toString("base64")})}}}function Xu(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 Zu(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 wn(r))continue;if((await Gu(r)).isSymbolicLink())throw new Error(`Refusing to import through symbolic link: ${ee.relative(t,r)}`)}}function ni(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 ri(t,e){if(t.length<12)throw new Error("Sync passphrase must contain at least 12 characters.");return Yu(t,e,32,{N:32768,r:8,p:1,maxmem:64*1024*1024})}var yn=class{rootDir;constructor(e){this.rootDir=ee.resolve(e)}async exportBundle(e,n,r=!1){let o=[];for(let w of Qu){let x=ee.join(this.rootDir,w);if(!await wn(x))continue;(await oi(x)).isDirectory()?await _r(this.rootDir,w,o):o.push({path:w,contentBase64:(await $r(x)).toString("base64")})}r&&await _r(this.rootDir,`${E}/sessions`,o),o.sort((w,x)=>w.path.localeCompare(x.path));let s={schemaVersion:1,files:o},i=ti(16),a=ti(12),c=ri(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=zu("aes-256-gcm",c,a);u.setAAD(ni(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")},f=ee.resolve(e);return await Zs(ee.dirname(f),{recursive:!0}),await ei(f,`${JSON.stringify(d,null,2)}
|
|
194
|
+
`,{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=ri(n,s),l;try{let f=Vu("aes-256-gcm",c,i);f.setAuthTag(a);let{ciphertext:w,...x}=o;f.setAAD(ni(x)),l=Buffer.concat([f.update(Buffer.from(o.ciphertext,"base64")),f.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 f of u.files){let w=Xu(f.path),x=ee.join(this.rootDir,w);if(await Zu(this.rootDir,w),!r&&await wn(x)){d.push(w);continue}await Zs(ee.dirname(x),{recursive:!0}),await ei(x,Buffer.from(f.contentBase64,"base64"),{mode:384}),m.push(w)}return{imported:m,skipped:d}}async readEnvelope(e){let n;try{n=JSON.parse(await $r(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 si,readFile as ed,stat as td,writeFile as ii}from"node:fs/promises";import bn from"node:path";async function ai(t){try{return await td(t),!0}catch{return!1}}function ci(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=bn.resolve(e),this.filePath=bn.join(this.rootDir,E,"team-policy.json")}async load(){if(!await ai(this.filePath))return;let e;try{e=JSON.parse(await ed(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=ci(n);if(!r.valid)throw new Error(`Invalid team policy: ${r.errors.join(" ")}`);return n}async initialize(e,n=[]){if(await ai(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 si(bn.dirname(this.filePath),{recursive:!0}),await ii(this.filePath,`${JSON.stringify(r,null,2)}
|
|
195
|
+
`,"utf8"),r}async save(e){let n=ci(e);if(!n.valid)throw new Error(`Invalid team policy: ${n.errors.join(" ")}`);await si(bn.dirname(this.filePath),{recursive:!0}),await ii(this.filePath,`${JSON.stringify(e,null,2)}
|
|
196
|
+
`,"utf8")}};function ui(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 li={allow:0,ask:1,deny:2};function vn(t,e){return e&&li[e]>li[t]?e:t}function di(t,e){return e?{...t,search:vn(t.search,"deny"),fetch:vn(t.fetch,"deny")}:t}import{mkdir as xn,readFile as Ve,readdir as nd,rename as rd,writeFile as Or,chmod as od,unlink as fi,stat as gi}from"node:fs/promises";import H from"node:path";var kn=".kpilot",sd="logbook",id="project.md",ad="learnings.md",cd="meta.json",ld=220,ud=12e3,mi=3,Ar={project:H.join(kn,"understanding.md"),learnings:H.join(kn,"learnings.md"),meta:H.join(kn,"meta.json")},Sn=`Write the project's Logbook entry (.kpilot/logbook/project.md). Keep the tool chain tiny for small-context models (~8k context).
|
|
163
197
|
|
|
164
198
|
Allowed steps only:
|
|
165
199
|
1. workspace_summary once
|
|
@@ -169,8 +203,8 @@ Allowed steps only:
|
|
|
169
203
|
5. write_file .kpilot/logbook/project.md using content_b64 (preferred) or a short content string
|
|
170
204
|
|
|
171
205
|
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
|
|
206
|
+
When done, one short confirmation sentence.`;async function Ir(t){let e=H.resolve(t),n=await nd(e).catch(()=>[]),r=[];for(let l of n.slice(0,60))if(!(l===".git"||l==="node_modules"||l==="dist"))try{let u=await gi(H.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(H.join(e,"README.md"),"utf8")).split(/\r?\n/).slice(0,50).join(`
|
|
207
|
+
`).trim()}catch{}let a="";try{let l=JSON.parse(await Ve(H.join(e,"package.json"),"utf8")),u=l.scripts?Object.keys(l.scripts).slice(0,12).map(m=>`- \`${m}\`: \`${l.scripts[m]}\``).join(`
|
|
174
208
|
`):"_none_";a=[l.name?`- name: \`${l.name}\``:"",l.description?`- description: ${l.description}`:"",l.packageManager?`- packageManager: \`${l.packageManager}\``:"","- scripts:",u].filter(Boolean).join(`
|
|
175
209
|
`)}catch{}let c=`# Project Logbook
|
|
176
210
|
|
|
@@ -190,7 +224,7 @@ ${a}
|
|
|
190
224
|
`:""}
|
|
191
225
|
## Top-level layout
|
|
192
226
|
\`\`\`
|
|
193
|
-
${
|
|
227
|
+
${r.join(`
|
|
194
228
|
`)||"[empty]"}
|
|
195
229
|
\`\`\`
|
|
196
230
|
|
|
@@ -201,18 +235,18 @@ See \`package.json\` scripts above (or README). Prefer the repo's documented pac
|
|
|
201
235
|
- Keep secrets out of git (\`.env\`).
|
|
202
236
|
- Prefer small, permission-gated edits.
|
|
203
237
|
- 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
|
|
238
|
+
`;return pd(e,c)}function Dr(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 dd(t){return H.join(H.resolve(t),kn)}function Le(t){return H.join(dd(t),sd)}function Ye(t){return H.join(Le(t),id)}async function hi(t,e=7){try{let n=await gi(Ye(t));return Date.now()-n.mtimeMs>e*24*60*60*1e3}catch{return!1}}function jr(t){return H.join(Le(t),ad)}function Tn(t){return H.join(Le(t),cd)}async function pi(t){try{return await Ve(t),!0}catch{return!1}}async function Qe(t){let e=H.resolve(t),n=Le(e);await xn(n,{recursive:!0,mode:493});let r=[[H.join(e,Ar.project),Ye(e)],[H.join(e,Ar.learnings),jr(e)],[H.join(e,Ar.meta),Tn(e)]];for(let[o,s]of r)if(await pi(o)){if(await pi(s)){try{await fi(o)}catch{}continue}try{await rd(o,s)}catch{}}}async function md(t){try{return JSON.parse(await Ve(t,"utf8"))}catch{return{}}}async function $t(t){await Qe(t);let e=await md(Tn(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 _t(t,e){await Qe(t);let n=await $t(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 xn(l,{recursive:!0,mode:448});let u=Tn(t);await Or(u,`${JSON.stringify(r,null,2)}
|
|
239
|
+
`,{encoding:"utf8",mode:384}),await od(u,384)}async function Xe(t){await Qe(t);try{return(await Ve(Ye(t),"utf8")).trim().length>0}catch{return!1}}async function pd(t,e){await Qe(t);let n=Le(t);await xn(n,{recursive:!0,mode:493});let r=Ye(t),o=e.trim().endsWith(`
|
|
206
240
|
`)?e.trimStart():`${e.trim()}
|
|
207
|
-
`;return await
|
|
208
|
-
`)}async function
|
|
241
|
+
`;return await Or(r,o,{encoding:"utf8",mode:420}),await _t(t,{projectCapturedAt:new Date().toISOString(),declined:!1}),r}async function Lr(t){await _t(t,{declined:!0})}async function Ur(t){let e=await $t(t);if(!e.declined&&!e.projectCapturedAt&&!e.learningEnabled&&!e.learningOffered&&!e.lastLearnedAt){try{await fi(Tn(t))}catch{}return}await _t(t,{declined:!1})}async function wi(t){return await Xe(t)?!1:!(await $t(t)).declined}async function At(t){return(await $t(t)).learningEnabled===!0}async function yi(t){let e=await Xe(t),n=await At(t);return e&&!n?"":e?"Logbook: learning on \xB7 /learn off":"Logbook: no project entry \xB7 /logbook to capture"}async function Ot(t,e){await _t(t,{learningEnabled:e,learningOffered:!0})}async function bi(t){let e=await $t(t);return!(e.learningEnabled||e.learningOffered)}function Nr(t){return t.replace(/\s+/g," ").trim().replace(/^[-*•]\s*/,"").slice(0,ld)}function fd(t){let e=[];for(let n of t.split(/\r?\n/)){let r=/^\s*[-*]\s+(.+)$/.exec(n);if(!r?.[1])continue;let o=Nr(r[1]);o&&e.push(o)}return e}async function vi(t){await Qe(t);try{let e=await Ve(jr(t),"utf8");return fd(e)}catch{return[]}}async function Fr(t,e=8e3){let n=await vi(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(`
|
|
242
|
+
`)}async function gd(t,e){await Qe(t);let n=e.map(Nr).filter(Boolean);if(!n.length)return[];let r=await vi(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
243
|
`)}
|
|
210
|
-
`;for(;a.length>
|
|
244
|
+
`;for(;a.length>ud&&i.length>1;)i=i.slice(1),a=`${i.map(l=>`- ${l}`).join(`
|
|
211
245
|
`)}
|
|
212
|
-
`;let c=
|
|
246
|
+
`;let c=Le(t);return await xn(c,{recursive:!0,mode:493}),await Or(jr(t),`# Logbook learnings
|
|
213
247
|
|
|
214
|
-
${a}`,{encoding:"utf8",mode:420}),await
|
|
215
|
-
`,{mode:384})}catch{}}}function
|
|
248
|
+
${a}`,{encoding:"utf8",mode:420}),await _t(t,{lastLearnedAt:new Date().toISOString()}),s}function hd(t){let e=[],n=t.prompt.trim();if(!n||n===Sn)return[];let r=s=>{if(!s)return;let i=Nr(s);!i||i.length<8||e.some(a=>a.toLowerCase()===i.toLowerCase())||e.length>=mi||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,mi)}async function ki(t){if(!await At(t.rootDir))return[];if(t.prompt.trim()===Sn)return[];let e=hd(t);return e.length?gd(t.rootDir,e):[]}function xi(t){let e=t.replace(/\\/g,"/");return e===".kpilot"||e.startsWith(".kpilot/")||e.includes("/.kpilot/")}var z="0.10.42",Br=[26,0,0];function kd(){let t=process.version.replace(/^v/,"").split(".").slice(0,3).map(Number);if(!Br.every((n,r)=>{for(let o=0;o<r;o+=1)if((t[o]??0)!==Br[o])return!0;return(t[r]??0)>=n})&&process.env.KPILOT_ALLOW_UNSUPPORTED_NODE!=="1")throw new Error(`kpilot requires Node.js ${Br.join(".")} or newer; detected ${process.version}.`)}var I={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m"},Dt=[{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"]}],Oi=new Set(Dt.flatMap(t=>[t.name,...t.aliases??[]]));function xd(t){if(!t.startsWith("/")||t==="/")return!1;let[e="",...n]=t.slice(1).split(/\s+/);return!e||n.length>0?!1:!Oi.has(e)}function j(t,e){return process.stdout.isTTY?`${t}${e}${I.reset}`:e}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 Ii(t){if(t)return{pause:()=>{t.closed||t.pause()},resume:()=>{t.closed||t.resume()}}}function Sd(){console.log(j(I.bold,"Slash commands")),console.log(j(I.dim,"Type / to list commands as you type \u2014 \u2191/\u2193 to move, Enter to run."));for(let t of Dt)console.log(` ${j(I.cyan,t.usage.padEnd(28))} ${t.description}`);console.log(` ${j(I.cyan,"/<skill-name> [args]".padEnd(28))} Run a skill directly`)}function Si(t=[]){let e=t.map(n=>({name:n,usage:`/${n}`,description:`Run skill \u201C${n}\u201D`}));return[...Dt.map(n=>({name:n.name,usage:n.usage,description:n.description,aliases:n.aliases})),...e]}async function Td(t){let e=(t.skillNames??[]).map(s=>({name:s,usage:`/${s}`,description:`Run skill \u201C${s}\u201D`})),n=[...Dt,...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(`${j(I.cyan,"\u25C6")} ${t}`)}function v(t){console.log(`${j(I.green,"\u2713")} ${t}`)}function _(t){console.log(`${j(I.yellow,"!")} ${t}`)}function q(t){console.error(`${j(I.red,"\u2717")} ${t}`)}function Pd(){return D.join($i(),".config","kpilot","installed-version")}function Ed(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 Rd(){if(process.env.KPILOT_SILENT_VERSION_NOTICE==="1")return;let t=Pd(),e;try{e=(await Vr(t,"utf8")).trim()||void 0}catch{e=void 0}if(e!==z){if(e){let n=Ed(e,z)<0?"Updated":"Changed";$(`kpilot CLI ${n}: ${e} \u2192 ${z}`)}else $(`kpilot CLI installed: ${z}`);try{await et(D.dirname(t),{recursive:!0}),await ve(t,`${z}
|
|
249
|
+
`,{mode:384})}catch{}}}function Cd(){return`${j(I.bold,`kpilot ${z}`)} \u2014 governed engineering agent
|
|
216
250
|
|
|
217
251
|
All requests go through kpilot \u2014 sign in once, and kpilot handles the rest.
|
|
218
252
|
|
|
@@ -258,65 +292,78 @@ Options:
|
|
|
258
292
|
--no-browser Do not open a browser during \`kpilot login\`
|
|
259
293
|
--limit <number> Row limit for usage and audit lists
|
|
260
294
|
--yes Approve all policy decisions marked "ask"
|
|
295
|
+
--yolo Bypass tool approvals (--force, --yes-always,
|
|
296
|
+
--dangerously-skip-permissions, --auto-accept,
|
|
297
|
+
--permission-mode <mode>; Shift+Tab toggles live)
|
|
261
298
|
--debug Print complete tool results
|
|
262
|
-
--force
|
|
299
|
+
--force Bypass approvals AND force destructive management ops
|
|
263
300
|
-h, --help Show this help
|
|
264
301
|
-V, --version Print the CLI version
|
|
265
302
|
|
|
266
303
|
Interactive additions:
|
|
267
|
-
/sessions, /resume [id], /new [title], /save
|
|
304
|
+
/sessions, /resume [id], /new [title], /save, /clear, /undo
|
|
305
|
+
/compact, /cost, /context, /checkpoint [save|restore|list] [id]
|
|
268
306
|
/memory, /remember <text>, /forget <id>
|
|
307
|
+
/todo [add|done|remove|clear] [text|id]
|
|
269
308
|
/skills, /skill <name> [arguments], /<skill-name> [arguments]
|
|
270
309
|
/preferences, /feedback <accepted|rejected|edited> [note]
|
|
271
310
|
/models, /agent, /mcp, /worktrees, /policy, /usage, /audit, /admin
|
|
272
|
-
`}function
|
|
311
|
+
`}function ie(t,e,n){let r=t[e+1];if(!r||r.startsWith("--"))throw new Error(`${n} requires a value.`);return[r,e+1]}function Md(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(So(i)){e.bypassPermissions=!0,i==="--force"&&(e.force=!0);continue}if(i==="--permission-mode"){let[a,c]=ie(t,s,i);e.bypassPermissions=To(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]=ie(t,s,i);e.cwd=D.resolve(a),s=c;continue}if(i==="--mode"){let[a,c]=ie(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]=ie(t,s,i);e.session=a,s=c;continue}if(i==="--title"){let[a,c]=ie(t,s,i);e.title=a,s=c;continue}if(i==="--note"){let[a,c]=ie(t,s,i);e.note=a,s=c;continue}if(i==="--model"){let[a,c]=ie(t,s,i);e.model=a,s=c;continue}if(i==="--passphrase-env"){let[a,c]=ie(t,s,i);e.passphraseEnv=a,s=c;continue}if(i==="--control-plane-url"){let[a,c]=ie(t,s,i);e.controlPlaneUrl=a,s=c;continue}if(i==="--organization"){let[a,c]=ie(t,s,i);e.organization=a,s=c;continue}if(i==="--limit"){let[a,c]=ie(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]=ie(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 Ci(t),!0}catch{return!1}}async function Jr(t){if(!await tt(t))return{};let e=await Vr(t,"utf8");try{return JSON.parse(e)}catch(n){throw new Error(`Invalid JSON in ${t}: ${n instanceof Error?n.message:String(n)}`)}}function $d(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 Wt(t);let e=D.join($i(),".config","kpilot","config.json"),n=D.join(t,E,"config.json");return $d(await Jr(e),await Jr(n))}function _d(t,e){let n={filesystem:{...ce.filesystem,...t?.filesystem},shell:{...ce.shell,...t?.shell},git:{...ce.git,...t?.git},network:{...ce.network,...t?.network},mcp:{...ce.mcp,...t?.mcp},subagents:{...ce.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]=vn(s[i],a))}return e?.requireNetworkIsolation&&(n.network=di(n.network,!0)),n}function Cn(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";ui({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:Cn(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 re(t){return{sessions:new sn(t),memory:new zt(t),todos:new Yt(t),checkpoints:new Xt(t),skills:new an(t),preferences:new on(t),audit:new fn(t),usage:new hn(t),policy:new je(t)}}async function W(t){if(!(await Ci(t)).isDirectory())throw new Error(`${t} is not a directory.`);await wd(t),await Wt(t)}async function Ad(t,e){let n=D.join(t,".gitignore"),r=await tt(n)?await Vr(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
312
|
`)?`
|
|
274
|
-
`:"";await
|
|
313
|
+
`:"";await tt(n)?await yd(n,`${i}${s.join(`
|
|
275
314
|
`)}
|
|
276
|
-
`,"utf8"):await
|
|
315
|
+
`,"utf8"):await ve(n,`${s.join(`
|
|
277
316
|
`)}
|
|
278
|
-
`,"utf8"),v(`Updated .gitignore with ${s.length} kpilot runtime path(s).`)}async function
|
|
279
|
-
`,{encoding:"utf8",mode:384}),await
|
|
317
|
+
`,"utf8"),v(`Updated .gitignore with ${s.length} kpilot runtime path(s).`)}async function Od(t){await W(t);let e=D.join(t,E),n=D.join(e,"config.json"),r=D.join(e,"instructions.md"),o=D.join(e,"skills","review","SKILL.md");await et(D.dirname(o),{recursive:!0}),await tt(n)?_(`${D.relative(t,n)} already exists; left unchanged.`):(await ve(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:ce},null,2)}
|
|
318
|
+
`,{encoding:"utf8",mode:384}),await En(n,384),v(`Created ${D.relative(t,n)}.`)),await tt(r)?_(`${D.relative(t,r)} already exists; left unchanged.`):(await ve(r,`# Project instructions
|
|
280
319
|
|
|
281
320
|
- Follow the repository's existing architecture and naming conventions.
|
|
282
321
|
- Do not introduce placeholder implementations.
|
|
283
322
|
- Run relevant tests after code changes.
|
|
284
|
-
`,"utf8"),v(`Created ${
|
|
323
|
+
`,"utf8"),v(`Created ${D.relative(t,r)}.`)),await tt(o)||(await ve(o,`---
|
|
285
324
|
name: review
|
|
286
325
|
description: Inspect a change for correctness, safety, and missing validation.
|
|
287
326
|
---
|
|
288
327
|
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"),v(`Created ${
|
|
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(`${
|
|
328
|
+
`,"utf8"),v(`Created ${D.relative(t,o)}.`)),await Ad(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 ${z} 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 Id(t){let e=t.args[0]??"routes";if(e==="routes"||e==="list"||e==="show"){let n=await Kr();if(!n.length){console.log("No kpilot capabilities are configured for this account yet.");return}console.log(j(I.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} ${j(I.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=tn(n),s=(await Kr()).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 Kr(){let e=await new se().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 Di(t){await W(t.cwd);let e=D.join(t.cwd,E,"config.json"),n=await Jr(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(D.dirname(e),{recursive:!0}),await ve(e,`${JSON.stringify(n,null,2)}
|
|
329
|
+
`,{encoding:"utf8",mode:384}),await En(e,384),v(`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(D.dirname(e),{recursive:!0}),await ve(e,`${JSON.stringify(n,null,2)}
|
|
330
|
+
`,{encoding:"utf8",mode:384}),await En(e,384),v(`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(D.dirname(e),{recursive:!0}),await ve(e,`${JSON.stringify(n,null,2)}
|
|
331
|
+
`,{encoding:"utf8",mode:384}),await En(e,384),v("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 qr(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=_i(n,r,{stdio:"ignore"});o.once("error",()=>e(!1)),o.once("close",s=>e(s===0))})}async function Dd(t){await W(t.cwd);let e=await we(t.cwd),n=re(t.cwd),r=await n.policy.load(),o=nt(t,e,r),s=0,i=Number(process.version.slice(1).split(".")[0]);console.log(j(I.bold,`kpilot doctor \u2014 ${t.cwd}`)),i>=26?v(`Node.js ${process.version}`):(q(`Node.js ${process.version}; Node.js 26 or newer is required.`),s+=1),await qr("git")?v("Git is available."):_("Git is unavailable; status, diff, and feedback evidence will be limited."),await qr("rg")?v("ripgrep is available."):_("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).";v(a);let c=Je(o.provider);v(`Authenticated: ${c.name} (${c.id}).`),o.provider==="kpilot-hosted"?await new se().load()?v("Your kpilot account is connected."):(q("kpilot needs an account. Run `kpilot login`."),s+=1):o.provider==="external-agent"&&(o.modelConfig.endpoint?v(`External agent endpoint configured: ${o.modelConfig.endpoint}`):o.modelConfig.command&&await qr(o.modelConfig.command)?v(`External agent command is available: ${o.modelConfig.command}`):(q("External agent requires a reachable endpoint or available command."),s+=1)),v(`${(await n.sessions.list()).length} persistent session(s) readable.`),v(`${(await n.memory.list()).length} project memory entr${(await n.memory.list()).length===1?"y":"ies"} readable.`),v(`${(await n.skills.list()).length} reusable skill(s) discovered.`),v(`${(await n.preferences.listRules()).length} learned preference rule(s) readable.`),r?v(`Team policy loaded${r.organization?` for ${r.organization}`:""}.`):$("Team policy: not configured.");let l=await n.usage.check(o.usageBudget);l.allowed?v(`Usage budget available: ${ue(l.summary.totalTokens)} token(s) used today.`):(q(`Usage budget blocked: ${l.violations.join(" ")}`),s+=1);let u=await n.audit.verify();u.valid?v(`Audit chain valid: ${u.records} record(s).`):(q(`Audit chain invalid: ${u.reason??"unknown failure"}`),s+=1);let m=new ye(t.cwd,{sandbox:e.sandbox});try{v(`Sandbox: ${await m.sandbox.describe()}.`)}catch(w){q(w instanceof Error?w.message:String(w)),s+=1}let d=Object.entries(e.mcp?.servers??{}).filter(([w,x])=>x.enabled!==!1&&(!r?.allowedMcpServers||r.allowedMcpServers.includes(w)));if(d.length===0)$("MCP: no enabled servers configured.");else try{let w=await Ae.connect(Object.fromEntries(d));v(`MCP: ${d.length} server(s), ${w.list().length} tool(s) available.`),await w.close()}catch(w){q(`MCP: ${w instanceof Error?w.message:String(w)}`),s+=1}o.baseUrl&&$(`Endpoint: ${o.baseUrl}`);let f=o.maxSteps===void 0?"unlimited":String(o.maxSteps);return $(`Mode: ${o.mode}; max steps: ${f}; streaming: ${o.streaming?"on":"off"}`),s===0?0:1}var Wr;function he(){Wr?.stop(),Wr=void 0}function jd(t){return t?`kpilot (${t})`:"kpilot"}function Mn(t){return j(I.green,jd(t))}function Ze(t){t.lineOpen&&(process.stdout.write(`
|
|
332
|
+
`),t.lineOpen=!1)}function Ti(t,e,n,r){let o=Mn(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")&&(he(),e.thinking=void 0),s.type==="reasoning_delta"){r?.reasoningDelta(s.delta);return}if(s.type==="assistant_delta")r?.noteOutput(),e.lineOpen||(r?.clearReasoning(),he(),process.stdout.isTTY||process.stdout.write(`
|
|
333
|
+
`),process.stdout.write(`${o} \u203A `),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,In(s.args,s.call.function.name)),r?.start();else if(s.type==="tool_output"){let i=s.chunk.replace(/\s+$/,"");i&&e.toolOutputLines<20&&(Ze(e),process.stdout.write(`${j(I.dim,` \u2502 ${i.slice(0,160)}`)}
|
|
334
|
+
`),e.toolOutputLines+=1,e.toolOutputLines===20&&process.stdout.write(`${j(I.dim," \u2502 \u2026 (output continues; full result on completion)")}
|
|
335
|
+
`))}else if(s.type==="tool_result"){Ze(e);let i=s.result.ok?co(s.result.metadata):"";r?.activity("result",s.call.function.name,i,s.result.ok),(t||!s.result.ok)&&console.log(j(I.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?.finish(),_(s.reason))}}async function Yr(t){let e=new AbortController,n=()=>{st.noteStop("Ctrl+C"),e.abort(Fn())};process.once("SIGINT",n);let r=st.begin(e);try{return await t(e.signal)}finally{process.removeListener("SIGINT",n),r()}}function Ld(t){return`Approve ${t.category}?
|
|
295
336
|
${t.summary}
|
|
296
|
-
${t.reason}`}function
|
|
297
|
-
${
|
|
298
|
-
[truncated ${t.length-e} characters]`}async function
|
|
299
|
-
|
|
337
|
+
${t.reason}`}function ji(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;he(),console.log(""),console.log(Ld(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 Ud(t){return async e=>e.category==="filesystem.read"||e.category==="git.read"||e.category==="filesystem.write"&&xi(e.summary)?!0:t(e)}async function Li(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=D.relative(t.cli.cwd,Ye(t.cli.cwd))||".kpilot/logbook/project.md";try{try{let o=await Yr(s=>Qr({cli:t.cli,created:t.created,services:t.services,session:t.session,prompt:Sn,approvalHandler:Ud(t.approvalHandler),signal:s}));o.streamed||console.log(`
|
|
338
|
+
${Mn(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);_(`Model call failed after Logbook write (${s}). Using the saved entry.`)}else{if(rt(o))throw o;if(Dr(o))_("Hub context is too small for a full agent Logbook pass; writing a lite entry from repo metadata\u2026"),await Ir(t.cli.cwd);else throw o}}return await Xe(t.cli.cwd)?(v(`Logbook project entry saved to ${r}`),$("Later turns will load this Logbook entry instead of rediscovering the repo from scratch. Refresh with /logbook"),!0):(_("Onboarding finished but `.kpilot/logbook/project.md` was not found. Ask the agent to write it, or run /logbook again."),!1)}catch(o){if(rt(o))return _("Logbook onboarding stopped."),!1;let s=o instanceof Error?o.message:String(o);if(Dr(o)||/fetch failed|unreachable/i.test(s))try{return _(`Agent Logbook pass failed (${s}). Falling back to lite capture\u2026`),await Ir(t.cli.cwd),v(`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 q(`Logbook capture failed: ${s}`),_(`Lite fallback also failed: ${i instanceof Error?i.message:String(i)}`),!1}return q(`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 Nd(t){try{if(await Xe(t.cli.cwd)){await hi(t.cli.cwd)&&_("Logbook entry is over a week old; run /logbook to refresh it if the project has changed."),await It(t);return}if(!await wi(t.cli.cwd)){await It(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 Lr(t.cli.cwd),$("Skipped. You can run /logbook later."),await It(t);return}if(e!=="yes"){$("Skipped. You can run /logbook later."),await It(t);return}await Ur(t.cli.cwd),await Li(t),await It(t)}catch(e){let n=e instanceof Error?e.message:String(e);_(`Logbook onboarding interrupted: ${n}`),$("Continuing into chat. Retry later with /logbook.")}}async function It(t){if(!await bi(t.cli.cwd)){await At(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 Ot(t.cli.cwd,!0),v("Logbook learning enabled. Facts from chats will append to .kpilot/logbook/learnings.md");return}await Ot(t.cli.cwd,!1),$("Logbook learning left off. Enable later with /learn on")}async function Fd(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 en({...e.modelConfig,route:t.route??"auto",model:t.model??"auto"});return r}function Gr(t){let e=process.env.KPILOT_BROWSER?.trim().toLowerCase()||t.tools?.browser||"auto";return e==="on"?"on":e==="off"?"off":"auto"}async function Hr(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 Xd(t);let f=new se,w=await f.load();if(!w)throw new Error("kpilot needs an account to continue. Run `kpilot login`.");let x=new le(t.controlPlaneUrl??w.controlPlaneUrl,`kpilot/${z}`),P=await f.validAccessToken(x);if(!P)throw new Error("kpilot needs an active account session. Run `kpilot login`.");o.modelConfig.accessToken=P.tokens.accessToken,o.modelConfig.baseUrl=t.controlPlaneUrl??P.tokens.controlPlaneUrl,o.baseUrl=o.modelConfig.baseUrl,o.modelConfig.getAccessToken=async()=>{let S=await f.validAccessToken(x);return S?(o.modelConfig.accessToken=S.tokens.accessToken,S.tokens.accessToken):o.modelConfig.accessToken}}let s=new ye(t.cwd,{sandbox:e.sandbox,browser:Gr(e)}),i=new Ke(_d(e.permissions,r)),{gateway:a}=await en(o.modelConfig),c=e.mcp?.servers??{},l=r?.allowedMcpServers?Object.fromEntries(Object.entries(c).filter(([f])=>r.allowedMcpServers.includes(f))):c,u=Object.values(l).some(f=>f.enabled!==!1)?await Ae.connect(l):void 0,m=e.subagents?.enabled===!1?void 0:new mn({rootDir:t.cwd,gateway:a,resolveGateway:f=>Fd(f,o,a),localRuntimeOptions:{sandbox:e.sandbox,browser:Gr(e)},maxParallel:e.subagents?.maxParallel,maxSteps:e.subagents?.maxSteps}),d=new vt([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 Bd(t,e,n){return t.session?await e.load(t.session):await e.create({title:t.title,mode:n.mode,model:n.model})}function Ui(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 Pi(t,e=12e4){if(t)return t.length<=e?t:`${t.slice(0,e)}
|
|
339
|
+
[truncated ${t.length-e} characters]`}async function Rn(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 Ei(t,e,n){let r=await t.execute("shell",{command:`git checkout -- ${n.map(Co).join(" ")}`},{rootDir:e,mode:"write",signal:void 0});return{ok:r.ok,output:r.output}}async function qd(t,e,n,r){let o=r?await Fr(r):"",s=await t.memory.renderForPrompt(),i=await t.todos.renderForPrompt(),a=new Set(s.split(`
|
|
340
|
+
`).map(u=>u.replace(/^[-*]\s*/,"").trim().toLowerCase()).filter(Boolean)),c=o.split(`
|
|
341
|
+
`).filter(u=>{let m=u.replace(/^[-*]\s*/,"").trim().toLowerCase();return!m||!a.has(m)}).join(`
|
|
342
|
+
`).trim();return{memoryContext:[s,c?`Logbook learnings (.kpilot/logbook):
|
|
343
|
+
${c}`:"",i].filter(Boolean).join(`
|
|
300
344
|
|
|
301
345
|
`),preferenceContext:await t.preferences.renderForPrompt(e.minimumPreferenceConfidence),skillContext:n?`${n.description}
|
|
302
346
|
|
|
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}
|
|
347
|
+
${n.instructions}`:void 0}}async function Jd(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 Qr(t){let e={streamed:!1,lineOpen:!1,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,toolOutputLines:0},n=new Date().toISOString(),r=[],o=new Ut({mode:t.created.settings.mode});e.thinking=o,Wr=o,o.start();try{await tm(t.cli);let s=Mi("sha256").update(t.prompt).digest("hex"),i=await t.services.usage.check(t.created.settings.usageBudget);for(let p of i.warnings)he(),_(`Usage budget: ${p}`);if(!i.allowed)throw he(),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 Rn(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 p=Math.ceil(t.created.agent.messages.reduce((g,k)=>{let h=typeof k.content=="string"?k.content.length:0,T=k.role==="assistant"?(k.tool_calls??[]).reduce((G,V)=>G+V.function.arguments.length,0):0;return g+h+T},0)/4);if(p>c){$(`Context ~${ue(p)} tokens; auto-compacting history\u2026`);try{await t.created.agent.compact(t.signal)}catch{_("Auto-compaction failed; continuing with full history.")}}}let l=await qd(t.services,t.created.settings,t.skill,t.cli.cwd),u=await Jd(t.created.localRuntime,t.cli.cwd,t.created.settings.mode),m=t.created.agent.messages.filter(p=>p.role==="user").length===0,d="";if(m){let p=await t.created.localRuntime.execute("workspace_summary",{},{rootDir:t.cli.cwd,mode:t.created.settings.mode});p.ok&&(d=`Workspace summary:
|
|
348
|
+
${p.output.slice(0,1500)}`)}let f=[u,l.memoryContext,l.skillContext,d].filter(Boolean).join(`
|
|
318
349
|
|
|
319
|
-
|
|
350
|
+
`),w;try{let p=Ui(t.created.settings.provider);w=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:p,approvalHandler:t.approvalHandler,bypassPermissions:t.bypassPermissions===!0,preferenceContext:l.preferenceContext,volatileContext:f,onEvent:g=>{r.push(g),Ti(t.cli.debug,e,t.created.settings.showModel?t.created.settings.model:void 0,o)(g)},signal:t.signal})}catch(p){if(he(),Ze(e),e.inputTokens||e.outputTokens){let g=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 Ri({cli:t.cli,provider:t.created.settings.provider,record:g,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:rt(p)?"cancelled":"failure",category:"agent",sessionId:t.session.id,details:{model:t.created.settings.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,error:p instanceof Error?p.message.slice(0,500):String(p).slice(0,500)}}),p}Ze(e);let x=await Rn(t.created.localRuntime,t.cli.cwd,t.created.settings.mode,t.signal),P=a!==x,S=0,C=0,b=t.created.settings.verifyCommand;if(P&&b&&t.created.settings.mode==="write"){$(`Verifying: ${b}`);let p=await t.created.localRuntime.execute("shell",{command:b},{rootDir:t.cli.cwd,mode:"write",signal:t.signal});if(p.ok)v("Verification passed.");else{_("Verification failed; asking the model to fix it."),console.log(j(I.dim,p.output.slice(-2e3)));try{let g=await t.created.agent.run({prompt:`The verification command \`${b}\` failed after your changes. Fix the cause, then confirm. Output:
|
|
351
|
+
|
|
352
|
+
${p.output.slice(-4e3)}`,mode:"write",rootDir:t.cli.cwd,maxSteps:t.created.settings.maxSteps,approvalHandler:t.approvalHandler,onEvent:h=>{r.push(h),Ti(t.cli.debug,e,t.created.settings.showModel?t.created.settings.model:void 0,o)(h)},signal:t.signal});S+=g.usage.inputTokens,C+=g.usage.outputTokens,(await t.created.localRuntime.execute("shell",{command:b},{rootDir:t.cli.cwd,mode:"write",signal:t.signal})).ok?v("Verification passed after fix."):_("Verification still failing after one fix attempt.")}catch(g){if(rt(g))throw g;_(`Verification fix attempt failed: ${g instanceof Error?g.message:String(g)}`)}}}let A=w.usage.inputTokens+S,O=w.usage.outputTokens+C,L=await t.services.usage.record({model:t.created.settings.model,sessionId:t.session.id,inputTokens:A,outputTokens:O,cacheReadTokens:w.usage.cacheReadTokens,cacheWriteTokens:w.usage.cacheWriteTokens,price:t.created.settings.modelPrice});await Ri({cli:t.cli,provider:t.created.settings.provider,record:L,success:!0,durationMs:Date.now()-new Date(n).getTime()}),o.setCost(L.estimatedCostUsd);let B=lo(x),y=t.created.settings.mode==="plan"?po(r):void 0;o.finish({files:B,changed:P,planSummary:y,diff:P?x:void 0}),t.session.mode=t.created.settings.mode,t.session.model=t.created.settings.model,t.session.messages=[...w.messages],t.session.runs.push({id:bd(),prompt:t.prompt,answer:w.answer,startedAt:n,completedAt:new Date().toISOString(),steps:w.steps,usage:{inputTokens:A,outputTokens:O,estimatedCostUsd:L.estimatedCostUsd},diffBefore:Pi(a),diffAfter:Pi(x)}),t.session.runs.length>100&&(t.session.runs=t.session.runs.slice(-100)),t.session.runs.length===1&&!t.cli.title&&(t.session.title=t.prompt.length>72?`${t.prompt.slice(0,69)}...`:t.prompt),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:w.steps,inputTokens:A,outputTokens:O,estimatedCostUsd:L.estimatedCostUsd,changed:P}});try{let p=await ki({rootDir:t.cli.cwd,prompt:t.prompt,answer:w.answer,diffAfter:x,changed:a!==x});p.length&&$(`Learned ${p.length} Logbook fact(s) \u2192 .kpilot/logbook/learnings.md`)}catch(p){t.cli.debug&&_(`Logbook learning failed: ${p instanceof Error?p.message:String(p)}`)}return{answer:w.answer,streamed:e.streamed,tokensUsed:w.usage.inputTokens+w.usage.outputTokens}}finally{he(),e.thinking=void 0}}function Kd(t){if(t.length===0){console.log("[no sessions]");return}for(let e of t)console.log(`${e.id.slice(0,8)} ${e.updatedAt} ${e.mode.padEnd(5)} ${String(e.runCount).padStart(3)} run(s) ${e.title}`)}function Ni(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 Fi(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 rt(t){return t instanceof at||t instanceof Error&&(t.name==="AbortError"||/cancelled/i.test(t.message))}var Pn=2500,Wd=150,Gd=`${I.dim} filter ${I.reset}`,Hd="\x1B[?25l",zd="\x1B[?25h";async function Vd(t,e,n,r={}){let{placeholder:o,store:s}=r,i=new Kt(process.stdout,t),a=!!(process.stdout.isTTY&&process.stdin.isTTY);for(;;){let c=new AbortController,l=0,u,m,d=!1,f=b=>{t.setPrompt(b?Gd:e),t.prompt(!0)},w=()=>{d||(d=!0,i.clearPlaceholder(),f(!0),a&&process.stdout.write(Hd))},x=(b=!0)=>{d&&(d=!1,b?f(!1):t.setPrompt(e),a&&process.stdout.write(zd),o&&t.line.length===0&&i.showPlaceholder(o))},P=()=>{Re(t.line)!==null?w():x()},S=b=>{i.setFooter(Ro({bypass:r.bypass?.()??!1,exitArmed:b}))},C=()=>{let b=Date.now();if(!(b-l<Wd)){if(l=b,n.armedAt>0&&b-n.armedAt<=Pn){c.abort(Object.assign(new Error("exit"),{name:"kpilotExit"}));return}n.armedAt=b,i.clear(),x(),o&&i.showPlaceholder(o),setTimeout(()=>S(!0),0),m&&clearTimeout(m),m=setTimeout(()=>{n.armedAt=0,S(!1)},Pn),m.unref?.()}};process.on("SIGINT",C),t.on("SIGINT",C);try{let b=t.question(e,{signal:c.signal});if(i.begin(),S(n.armedAt>0),o&&i.showPlaceholder(o),a){vd(process.stdin);let B=(y,p)=>{if(p){if(p.name==="tab"&&p.shift){let g=r.onShiftTab?.();setTimeout(()=>{S(n.armedAt>0),g&&i.note(g)},0);return}p.name==="return"||p.name==="enter"||p.ctrl&&(p.name==="c"||p.name==="d")||(P(),d||i.syncPlaceholder(),setTimeout(()=>i.paint(),0))}};process.stdin.on("keypress",B),u=()=>process.stdin.off("keypress",B)}let A=await b;x(!1);let O=(A??"").trim();if(!O){i.rewind();continue}return n.armedAt=0,m&&clearTimeout(m),s?s.expand(O):{text:O,pasted:!1}}catch{let b=c.signal.reason;if(b instanceof Error&&(b.name==="kpilotExit"||b.message==="exit"))return process.stdout.write(`
|
|
353
|
+
`),null;let A=Date.now();if(n.armedAt>0&&A-n.armedAt<=Pn)return process.stdout.write(`
|
|
354
|
+
`),null;n.armedAt=A,i.clear(),x(),o&&i.showPlaceholder(o),setTimeout(()=>S(!0),0),m&&clearTimeout(m),m=setTimeout(()=>{n.armedAt=0,S(!1)},Pn),m.unref?.();continue}finally{i.end(),i.clearPlaceholder(),x(!1),m&&clearTimeout(m),u?.(),process.removeListener("SIGINT",C),t.removeListener("SIGINT",C)}}}async function Yd(t,e,n,r={}){let o=await yi(e),s=Un();process.stdout.write(`${s}
|
|
355
|
+
`),o&&process.stdout.write(`${j(I.dim,o)}
|
|
356
|
+
`),r.store?.reset();let i=await Vd(t,jn,n,{placeholder:Ln,store:r.store,onShiftTab:r.onShiftTab,bypass:r.bypass});return i===null?(process.stdout.write(`
|
|
357
|
+
\x1B[0J`),null):(process.stdout.write(`\x1B[0J${s}
|
|
358
|
+
`),i)}function Bi(t){return t.controlPlaneUrl??process.env.KPILOT_CONTROL_PLANE_URL??"https://api.konsolepilot.ai"}async function Qd(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=_i(n,r,{stdio:"ignore",detached:!0});s.unref(),s.once("error",()=>o(!1)),s.once("spawn",()=>o(!0))})}async function Xd(t){let e=new se,n=await e.load(),r=new le(t.controlPlaneUrl??n?.controlPlaneUrl??Bi(t),`kpilot/${z}`);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 qi(t),!await e.load())throw new Error("kpilot needs an account to continue. Run `kpilot login`.")}async function qi(t){let e=new le(Bi(t),`kpilot/${z}`),n=new se,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 Qd(s)),a?(console.log(`
|
|
359
|
+
Opened ${s}`),console.log(`Confirm code ${j(I.bold,o.user_code)} in your browser if prompted.
|
|
360
|
+
`),$("Approve the device in your browser. Press Ctrl+C to cancel.")):(console.log(`
|
|
361
|
+
Open: ${s}`),console.log(`Code: ${j(I.bold,o.user_code)}
|
|
362
|
+
`),$("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),v(`Signed in as ${u.user.email} \xB7 ${u.organization.name}`)}finally{process.removeListener("SIGINT",l)}}async function Zd(t){let e=new se,n=await e.load();if(!n){console.log("Not signed in. Run `kpilot login`.");return}let r=new le(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${z}`),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 em(t){let e=new se,n=await e.load();if(!n){console.log("Already signed out.");return}await new le(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${z}`).logout(n.refreshToken).catch(()=>{}),await e.clear(),v("Signed out and removed local cloud credentials.")}async function tm(t){if(!(t.noCloudSync||process.env.KPILOT_DISABLE_CLOUD_SYNC==="1"))try{let e=new se,n=await e.load();if(!n)return;let r=new le(t.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${z}`),o=await e.validAccessToken(r);if(!o)return;let s=await o.client.checkBudget(o.tokens.accessToken,0);for(let i of s.warnings)_(`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&&_(`Cloud budget check unavailable: ${e instanceof Error?e.message:String(e)}`)}}async function Ri(t){if(t.provider!=="kpilot-hosted"&&!(t.cli.noCloudSync||process.env.KPILOT_DISABLE_CLOUD_SYNC==="1"))try{let e=new se,n=await e.load();if(!n)return;let r=new le(t.cli.controlPlaneUrl??n.controlPlaneUrl,`kpilot/${z}`),o=await e.validAccessToken(r);if(!o)return;let s=Mi("sha256").update(D.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&&_(`Cloud usage sync failed: ${e instanceof Error?e.message:String(e)}`)}}async function nm(t){if(!t.prompt)throw new Error("Provide a prompt, or use `kpilot`.");await W(t.cwd);let e=await we(t.cwd),n=re(t.cwd),r=nt(t,e,await n.policy.load()),o=await Bd(t,n.sessions,r);t.mode||(t.mode=o.mode);let s=await Hr(t,e,o),i=process.stdin.isTTY?Ai({input:process.stdin,output:process.stdout}):void 0;try{console.log(Nt(s.settings.mode,s.settings.showModel?s.settings.model:void 0,o.id.slice(0,8),{bypass:t.bypassPermissions}));try{let a=await Yr(c=>Qr({cli:t,created:s,services:n,session:o,prompt:t.prompt,approvalHandler:ji(t,i?l=>i.question(l):void 0,Ii(i)),bypassPermissions:t.bypassPermissions,signal:c}));a.streamed||console.log(`${Mn(s.settings.showModel?s.settings.model:void 0)} \u203A ${a.answer}`),$(`Resume with: kpilot chat --session ${o.id.slice(0,8)}`)}catch(a){if(!rt(a))throw a;o.messages=[...s.agent.messages],await n.sessions.save(o),he();let c=st.stopReason;_(c==="Esc"?"Stopped with Esc.":"Stopped."),$(`Nothing else was run. Resume with: kpilot chat --session ${o.id.slice(0,8)}`),process.exitCode=130}}finally{i?.close(),await s.close()}}function Ji(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 Ki(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 Rn(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(v(`Recorded ${t.outcome} feedback for session ${t.session.id.slice(0,8)}.`),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 rm(t){await W(t.cwd);let e=re(t.cwd).sessions,n=t.args[0]??"list";if(n==="list"){Kd(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),v(`Deleted session ${r}.`);return}throw new Error(`Unknown sessions action: ${n}`)}async function om(t){await W(t.cwd);let e=re(t.cwd).memory,n=t.args[0]??"list";if(n==="list"){Ni(await e.list());return}if(n==="add"){let r=await e.add(t.args.slice(1).join(" "));v(`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);v(`Removed memory: ${o.text}`);return}if(n==="clear"){let r=await e.clear();v(`Removed ${r} memory entr${r===1?"y":"ies"}.`);return}throw new Error(`Unknown memory action: ${n}`)}async function sm(t){await W(t.cwd);let e=re(t.cwd).skills,n=t.args[0]??"list";if(n==="list"){Fi(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})
|
|
363
|
+
${o.description}
|
|
364
|
+
|
|
365
|
+
${o.instructions}
|
|
320
366
|
|
|
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
|
-
|
|
367
|
+
${o.filePath}`);return}throw new Error(`Unknown skills action: ${n}`)}async function im(t){await W(t.cwd);let e=re(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);v(`Removed preference: ${o.text}`);return}throw new Error(`Unknown preferences action: ${n}`)}async function am(t){await W(t.cwd);let e=await we(t.cwd),n=re(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 ye(t.cwd,{sandbox:e.sandbox});await Ki({outcome:Ji(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 cm(t){if(t.args[0]==="serve"){await lm(t);return}await W(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 lm(t){await W(t.cwd);let e=await we(t.cwd),n=await new je(t.cwd).load(),r=new ye(t.cwd,{sandbox:e.sandbox,browser:Gr(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 vt([r,i]);$(`Serving kpilot MCP server on stdio (${a.definitions().length} tools).`);let c=new rn(a,{name:"kpilot",version:z,rootDir:t.cwd,mode:t.mode??"write"});try{await ms(c)}finally{await i?.close()}}function Wi(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 um(t){await W(t.cwd);let e=new Ct(t.cwd),n=t.args[0]??"list";if(n==="list"){Wi(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]});v(`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),v(`Removed worktree ${r}.`);return}if(n==="prune"){await e.prune(),v("Pruned stale Git worktree metadata.");return}throw new Error(`Unknown worktrees action: ${n}`)}async function dm(t){await W(t.cwd);let e=re(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??[]}}),v(`Created ${D.relative(t.cwd,e.policy.filePath)}.`),o||_("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 zr(t){console.log(`date: ${t.date}`),console.log(`runs: ${t.runs}`),console.log(`input tokens: ${ue(t.inputTokens)}`),console.log(`output tokens: ${ue(t.outputTokens)}`),console.log(`total tokens: ${ue(t.totalTokens)}`),console.log(`estimated cost: $${t.estimatedCostUsd.toFixed(6)}`)}async function mm(t){await W(t.cwd);let e=await we(t.cwd),n=re(t.cwd),r=await n.policy.load(),o=Cn(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)} ${ue(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);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 pm(t){await W(t.cwd);let e=re(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"}`);v(`Audit chain is valid: ${r.records} record(s), head ${r.headHash.slice(0,16)}.`);return}throw new Error(`Unknown audit action: ${n}`)}async function fm(t){await W(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 yn(t.cwd),o=re(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:D.resolve(n),includeSessions:i.includeSessions}}),v(`Encrypted sync bundle written to ${D.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:D.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))_(`Skipped existing file: ${a}`);return}throw new Error(`Unknown sync action: ${e}`)}async function Gi(t){await W(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=re(t.cwd),o=await r.policy.load(),s=await r.usage.check(Cn(n.usage?.budget,o?.usage)),i=await r.audit.verify();if(console.log(j(I.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"}; ${ue(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);if(!s.allowed)for(let a of s.violations)q(a);i.valid||q(i.reason??"Audit chain invalid.")}async function gm(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 $n({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 hm(t){if(!process.stdin.isTTY)throw new Error("Interactive chat requires a TTY.");await W(t.cwd);let e=await we(t.cwd),n=re(t.cwd),r=nt(t,e,await n.policy.load()),o=Ai({input:process.stdin,output:process.stdout}),s=x=>o.question(x),i=Ii(o),a=new qt,c=new Jt(o,process.stdin,a,{prepare:vo,placeholder:Ln});c.attach();let l=new Bt(o,{input:process.stdin,output:process.stdout});l.setEntries(Si()),l.attach();let u={bypass:t.bypassPermissions},m=()=>(u.bypass=!u.bypass,mo(u.bypass));process.stdout.isTTY&&process.stdout.write(yo);let d,f,w=!1;try{let x=await gm({cli:t,store:n.sessions,settings:r,question:s,pauseResume:i});if(!x){$("Cancelled.");return}d=x,t.session=d.id,t.mode||(t.mode=d.mode),f=await Hr(t,e,d),w=!0;let P=ji(t,s,i);console.log(Nt(f.settings.mode,f.settings.showModel?f.settings.model:void 0,d.id.slice(0,8),{bypass:u.bypass})),console.log(j(I.dim,`${t.cwd} \xB7 session ${d.id.slice(0,8)}`));let S=async()=>{await f.close();let O=await we(t.cwd);r=nt(t,O,await n.policy.load()),f=await Hr(t,O,d)},C=async O=>{d.messages=[...f.agent.messages],await n.sessions.save(d),d=O,t.session=d.id,t.mode=d.mode,await S(),v(`Switched to ${d.id.slice(0,8)} \xB7 ${d.title}`)},b=async(O,L)=>{let B,y=Date.now();try{let p=f.settings.mode==="plan",g=await Yr(k=>Qr({cli:t,created:f,services:n,session:d,prompt:O,approvalHandler:P,bypassPermissions:u.bypass,skill:L,signal:k,onDiffBefore:h=>{B=h}}));if(g.streamed||(he(),console.log(`${Mn(f.settings.showModel?f.settings.model:void 0)} \u203A ${g.answer}`)),g.tokensUsed>0&&console.log(j(I.dim,`saved \xB7 session ${d.id.slice(0,8)}`)),p&&g.answer.trim()&&process.stdin.isTTY){let k=Do(t.cwd,O);await et(D.dirname(k),{recursive:!0}),await ve(k,`${g.answer.trim()}
|
|
368
|
+
`,"utf8");let h=D.relative(t.cwd,k);$(`Plan saved to ${h}`),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 S(),v("Switched to WRITE mode. Implementing the plan\u2026"),await b(`Implement the plan in ${h}. Follow it step by step and verify your changes.`))}}catch(p){if(!rt(p))throw p;d.messages=[...f.agent.messages],await n.sessions.save(d),he();let g=st.stopReason,k=Math.max(1,Math.round((Date.now()-y)/1e3));_(g==="Esc"?`Stopped with Esc after ${k}s. Partial conversation saved.`:`Stopped after ${k}s. Partial conversation saved.`);let h=await Rn(f.localRuntime,t.cwd,f.settings.mode),T=h!==B,G=!B||!B.trim(),V=T?Bn(h??""):[];if(!process.stdin.isTTY)return;let ae=[{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"}];G&&V.length>0&&ae.push({value:"undo",label:"Undo this run's changes",description:`Revert ${V.length} file(s) to the last commit`}),f.settings.mode==="write"&&ae.push({value:"plan",label:"Switch to plan mode",description:"Rethink and propose a plan before editing"});let de=await Q({title:"What would you like to do instead?",question:s,pauseResume:i,choices:ae});if(de==="undo"){let ke=await Ei(f.runtime,t.cwd,V);ke.ok?v(`Reverted ${V.length} file(s) to the last commit.`):q(`Undo failed: ${ke.output.slice(0,300)}`);return}if(de==="plan"){t.mode="plan",d.mode="plan",await n.sessions.save(d),await S(),v("Switched to PLAN mode. Describe what you want instead.");return}de==="continue"&&await b("Continue from where you stopped. Check the current state first and do not redo work that is already finished.")}};await Nd({cli:t,created:f,services:n,session:d,approvalHandler:P,question:s,pauseResume:i});let A={armedAt:0};for(;;){let O=await n.skills.list().catch(()=>[]);l.setEntries(Si(O.map(p=>p.name)));let L=await Yd(o,t.cwd,A,{store:a,onShiftTab:m,bypass:()=>u.bypass});if(L===null)break;let B=L.pasted,y=L.text;if(y){if(!B&&_n(y))break;if(!B&&(y==="/"||xd(y))){let p=y,g=l.takeSelection();if(g)y=`/${g}`;else{let k=await n.skills.list().catch(()=>[]);if(!(p!=="/"&&k.some(T=>T.name===p.slice(1)))){let T=await Td({question:s,pauseResume:i,skillNames:k.map(G=>G.name),initialQuery:p==="/"?"":p.slice(1)});if(!T)continue;y=T}}}if(!B&&_n(y))break;if(y==="/help"){Sd();continue}if(y==="/learn"||y.startsWith("/learn ")){let p=y.slice(6).trim().toLowerCase();if(!p){let h=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(!h)continue;p=h}if(p==="on"||p==="enable"){await Ot(t.cwd,!0),v("Logbook learning on. New durable facts append to .kpilot/logbook/learnings.md after chats.");continue}if(p==="off"||p==="disable"){await Ot(t.cwd,!1),v("Logbook learning off for this project.");continue}let g=await At(t.cwd),k=await Fr(t.cwd);console.log(g?"Logbook learning: on":"Logbook learning: off"),console.log(k?`Learnings:
|
|
369
|
+
${k}`:"Learnings: (none yet)");continue}if(y==="/logbook"||y.startsWith("/logbook ")||y==="/understand"||y.startsWith("/understand ")){let g=(y.startsWith("/logbook")?y.slice(8):y.slice(11)).trim().toLowerCase();if(!g&&y==="/logbook"){let k=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(!k)continue;g=k==="capture"?"":k}if(g==="skip"){await Lr(t.cwd),v("Will not auto-offer Logbook capture again. Run /logbook to build it later.");continue}await Ur(t.cwd),await Li({cli:t,created:f,services:n,session:d,approvalHandler:P});continue}if(y==="/save"){d.messages=[...f.agent.messages],await n.sessions.save(d),v(`Saved session ${d.id.slice(0,8)}.`);continue}if(y==="/undo"){let p=d.runs.at(-1);if(!p){_("No completed run to undo.");continue}let g=Bn(p.diffAfter??"");if(g.length===0){_("Last run did not change any tracked files.");continue}let k=await Ei(f.runtime,t.cwd,g);k.ok?(v(`Undid ${g.length} file(s) from the last run.`),$(g.join(" "))):q(`Undo failed: ${k.output.slice(0,300)}`);continue}if(y==="/clear"){f.agent.reset(),d.messages=[],await n.sessions.save(d),v("Conversation history cleared; run history remains available for feedback.");continue}if(y==="/compact"){try{let p=await f.agent.compact();d.messages=[...f.agent.messages],await n.sessions.save(d),p.after<p.before?v(`Compacted context: ${p.before} \u2192 ${p.after} messages.`):$("Nothing to compact yet.")}catch(p){q(`Compaction failed: ${p instanceof Error?p.message:String(p)}`)}continue}if(y==="/cost"){let p=d.runs,g=p.reduce((k,h)=>({inputTokens:k.inputTokens+(h.usage?.inputTokens??0),outputTokens:k.outputTokens+(h.usage?.outputTokens??0),costUsd:k.costUsd+(h.usage?.estimatedCostUsd??0)}),{inputTokens:0,outputTokens:0,costUsd:0});console.log(j(I.bold,"Session cost")),console.log(` runs: ${p.length}`),console.log(` input: ${ue(g.inputTokens)} tokens`),console.log(` output: ${ue(g.outputTokens)} tokens`),console.log(` est: $${g.costUsd.toFixed(6)}`),$("Automatic routing picks the cheapest capable model; prompt caching reuses earlier context.");continue}if(y==="/context"){let p=[...f.agent.messages],g=p.reduce((G,V)=>{let ae=typeof V.content=="string"?V.content:"",de=V.role==="assistant"?(V.tool_calls??[]).map(ke=>ke.function.arguments).join(""):"";return G+ae.length+de.length},0),k=Math.ceil(g/4),h=Ui(f.settings.provider),T=h?Math.round(k/h*100):void 0;console.log(j(I.bold,"Conversation context")),console.log(` messages: ${p.length}`),console.log(` approx: ~${ue(k)} tokens`),h&&T!==void 0&&console.log(` window: ${ue(h)} (${Math.min(100,T)}% used)`),T!==void 0&&T>=80?_("Context is nearly full \u2014 run /compact to summarize history."):$("Use /compact to summarize history when it grows large.");continue}if(y==="/checkpoint"||y.startsWith("/checkpoint ")){let p=y.slice(11).trim(),[g="list",...k]=p?p.split(/\s+/):["list"];try{if(g==="save"||g==="s"){let h=await n.checkpoints.save(d.id,[...f.agent.messages],k.join(" "));v(`Checkpoint ${h.id.slice(0,8)} saved (${h.messages.length} messages).`)}else if(g==="restore"||g==="r"){let h=k[0];if(!h){_("Usage: /checkpoint restore <id>");continue}let T=await n.checkpoints.load(d.id,h);f.agent.restore(T.messages),d.messages=[...f.agent.messages],await n.sessions.save(d),v(`Restored checkpoint ${T.id.slice(0,8)} (${T.messages.length} messages).`)}else if(g==="remove"||g==="rm"){let h=k[0];if(!h){_("Usage: /checkpoint remove <id>");continue}await n.checkpoints.remove(d.id,h),v(`Removed checkpoint ${h}.`)}else{let h=await n.checkpoints.list(d.id);h.length===0&&console.log("[no checkpoints]");for(let T of h)console.log(`${T.id.slice(0,8)} ${T.createdAt} ${T.label}`)}}catch(h){q(h instanceof Error?h.message:String(h))}continue}if(y==="/mode"||y.startsWith("/mode ")){let p=y==="/mode"?"":y.slice(6).trim();if(!p){let g=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(!g)continue;p=g}if(p!=="plan"&&p!=="write"){_("Mode must be plan or write.");continue}t.mode=p,d.mode=p,await n.sessions.save(d),await S(),v(`Switched to ${p.toUpperCase()} mode.`),console.log(Nt(f.settings.mode,f.settings.showModel?f.settings.model:void 0,d.id.slice(0,8),{bypass:u.bypass}));continue}if(y==="/status"||y==="/diff"){let p=y==="/status"?"git_status":"git_diff",g=await f.runtime.execute(p,{},{rootDir:t.cwd,mode:f.settings.mode});console.log(g.output);continue}if(y==="/sessions"||y==="/resume"||y.startsWith("/resume ")){let p=y.startsWith("/resume ")?y.slice(8).trim():"";if(p){await C(await n.sessions.load(p));continue}let g=await $n({store:n.sessions,question:s,pauseResume:i,title:"Switch session (Esc to stay):",currentId:d.id,prefer:"current"});if(g.kind!=="session"){g.kind==="cancel"&&$("Staying on the current session.");continue}if(g.session.id===d.id){$(`Already on ${d.id.slice(0,8)} \xB7 ${d.title}`);continue}await C(g.session);continue}if(y==="/new"||y.startsWith("/new ")){let p=y.slice(4).trim()||void 0;d=await n.sessions.create({title:p,mode:f.settings.mode,model:f.settings.model}),t.session=d.id,await S(),v(`Started session ${d.id.slice(0,8)} \xB7 ${d.title}`);continue}if(y==="/memory"){Ni(await n.memory.list());continue}if(y==="/todo"||y.startsWith("/todo ")){let p=y.slice(5).trim();if(!p){let T=await n.todos.list();if(T.length===0)console.log("[no todos]");else for(let G of T)console.log(`${G.completed?j(I.green,"\u2713"):j(I.cyan,"\xB7")} ${G.id.slice(0,8)} ${G.text}`);continue}let[g="",...k]=p.split(/\s+/),h=k.join(" ").trim();try{if(g==="add"||g==="a"){let T=await n.todos.add(h);v(`Todo ${T.id.slice(0,8)}: ${T.text}`)}else if(g==="done"||g==="complete"||g==="d"){let T=await n.todos.complete(h);v(`Completed ${T.id.slice(0,8)}: ${T.text}`)}else if(g==="remove"||g==="rm"){let T=await n.todos.remove(h);$(`Removed ${T.id.slice(0,8)}: ${T.text}`)}else if(g==="clear"){let T=await n.todos.clear();v(`Cleared ${T} todo(s).`)}else _(`Unknown todo action "${g}". Usage: /todo [add|done|remove|clear] [text|id]`)}catch(T){q(T instanceof Error?T.message:String(T))}continue}if(y.startsWith("/remember ")){let p=await n.memory.add(y.slice(10));v(`Remembered ${p.id.slice(0,8)}: ${p.text}`);continue}if(y.startsWith("/forget ")){let p=await n.memory.remove(y.slice(8).trim());v(`Removed memory: ${p.text}`);continue}if(y==="/skills"){Fi(await n.skills.list());continue}if(y.startsWith("/skill ")){let p=y.slice(7).trim(),[g="",...k]=p.split(/\s+/),h=await n.skills.get(g);await b(k.join(" ")||`Run the ${g} skill for the current repository.`,h);continue}if(y==="/preferences"){let p=await n.preferences.listRules();p.length===0&&console.log("[no learned preferences]");for(let g of p)console.log(`${g.id.slice(0,8)} ${Math.round(g.confidence*100)}% ${g.polarity}: ${g.text}`);continue}if(y==="/feedback"||y.startsWith("/feedback ")){let p=y.slice(9).trim();if(!p){let h=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(!h)continue;let T=(await o.question("Optional note \u203A ")).trim();p=T?`${h} ${T}`:h}let[g="",...k]=p.split(/\s+/);await Ki({outcome:Ji(g),note:k.join(" ")||void 0,session:d,services:n,runtime:f.localRuntime,mode:f.settings.mode,rootDir:t.cwd});continue}if(y==="/models"||y==="/model"){let p=await Kr();if(p.length===0){_("No kpilot capabilities are configured for this account yet.");continue}let g=f.settings.model&&f.settings.model!=="auto"?f.settings.model:"auto",k=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:g==="auto"},...p.map(h=>({value:h.model,label:Ft(h.model),description:go(h.model),default:h.model===g}))]});if(k==null)continue;if(k===g){v(`Already using ${k==="auto"?"auto":Ft(k)}.`);continue}t.model=k==="auto"?void 0:k,d.messages=[...f.agent.messages],await S(),v(`Switched to ${k==="auto"?"auto":Ft(k)}. Run a prompt to use it.`);continue}if(y==="/agent"){await Di({...t,args:["show"]});continue}if(y==="/mcp"){let p=f.mcpRuntime?.list()??[];p.length===0&&console.log("[no connected MCP tools]");for(let g of p)console.log(`${g.exposedName.padEnd(38)} ${g.description}`);continue}if(y==="/worktrees"){Wi(await new Ct(t.cwd).list());continue}if(y==="/policy"){let p=await n.policy.load();console.log(p?JSON.stringify(p,null,2):"[no team policy]");continue}if(y==="/usage"){let p=await n.policy.load(),g=await n.usage.check(Cn(e.usage?.budget,p?.usage));zr(g.summary);for(let k of g.warnings)_(k);for(let k of g.violations)q(k);continue}if(y==="/audit"){let p=await n.audit.verify();p.valid?v(`Audit chain valid: ${p.records} record(s).`):q(`Audit chain invalid: ${p.reason??"unknown reason"}`);continue}if(y==="/admin"){await Gi({...t,args:["status"]});continue}if(!B&&y.startsWith("/")){let[p="",...g]=y.slice(1).split(/\s+/);if(!Oi.has(p)){try{let h=await n.skills.get(p);await b(g.join(" ")||`Run the ${p} skill for the current repository.`,h)}catch(h){_(h instanceof Error?h.message:String(h))}continue}let k=Dt.find(h=>h.name===p||(h.aliases??[]).includes(p));_(`Unknown arguments for /${p}.${k?` Usage: ${k.usage}`:""} Run /help to list commands.`);continue}try{await b(y)}catch(p){q(p instanceof Error?p.message:String(p))}}}}finally{l.detach(),c.detach(),process.stdout.isTTY&&process.stdout.write(bo),w&&(d.messages=[...f.agent.messages],await n.sessions.save(d),await f.close()),o.close()}}async function wm(){kd();let t=process.argv.slice(2);if(t.includes("-V")||t.includes("--version")||t[0]==="version"){console.log(z);return}await Rd();let e=Md(t);if(e.command==="help"){console.log(Cd());return}if(e.command==="version"){console.log(z);return}if(e.command==="init"){await Od(e.cwd);return}if(e.command==="doctor"){process.exitCode=await Dd(e);return}if(e.command==="login"){await qi(e);return}if(e.command==="whoami"){await Zd(e);return}if(e.command==="logout"){await em(e);return}if(e.command==="models"){await Id(e);return}if(e.command==="agents"){await Di(e);return}if(e.command==="sessions"){await rm(e);return}if(e.command==="memory"){await om(e);return}if(e.command==="skills"){await sm(e);return}if(e.command==="preferences"){await im(e);return}if(e.command==="feedback"){await am(e);return}if(e.command==="mcp"){await cm(e);return}if(e.command==="worktrees"){await um(e);return}if(e.command==="policy"){await dm(e);return}if(e.command==="usage"){await mm(e);return}if(e.command==="audit"){await pm(e);return}if(e.command==="sync"){await fm(e);return}if(e.command==="admin"){await Gi(e);return}if(e.command==="chat"){await hm(e);return}await nm(e)}wm().catch(t=>{q(t instanceof Error?t.message:String(t)),process.exitCode=1});
|