kpilot 0.10.9 → 0.10.10

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 CHANGED
@@ -6,7 +6,7 @@ Use `kpilot` directly from your project directory to understand codebases, plan
6
6
 
7
7
  ## Developer Preview
8
8
 
9
- **Current version: 0.10.9**
9
+ **Current version: 0.10.10**
10
10
 
11
11
  kpilot is currently available as a **Developer Preview** and remains under active development.
12
12
 
@@ -69,7 +69,7 @@ kpilot --mode plan "Review this repository and propose a test plan"
69
69
 
70
70
  Documentation, product information, and updates are available at:
71
71
 
72
- https://kpilot.ai/
72
+ https://konsolepilot.ai/
73
73
 
74
74
  ## Feedback
75
75
 
package/dist/cli.mjs CHANGED
@@ -98,8 +98,8 @@ tool calls: ${JSON.stringify(e.tool_calls)}`:`${e.role}: ${e.content??""}`).join
98
98
 
99
99
  `),n=[];for(let o of t)if(o.role!=="system")if(o.role==="user")n.push({role:"user",content:[{text:o.content}]});else if(o.role==="assistant"){let r=[];o.content&&r.push({text:o.content});for(let s of o.tool_calls??[]){let i={};try{i=JSON.parse(s.function.arguments)}catch{i={raw:s.function.arguments}}r.push({toolUse:{toolUseId:s.id,name:s.function.name,input:i}})}n.push({role:"assistant",content:r})}else{let r;try{r={json:JSON.parse(o.content)}}catch{r={text:o.content}}n.push({role:"user",content:[{toolResult:{toolUseId:o.tool_call_id,content:[r]}}]})}return{...e?{system:[{text:e}]}:{},messages:n}}var Je=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 o=$i(e.messages),r=JSON.stringify({...o,toolConfig:e.tools.length?{tools:e.tools.map(d=>({toolSpec:{name:d.function.name,description:d.function.description,inputSchema:{json:d.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 te(s.toString(),{method:"POST",headers:Mi(this.options,s,r),body:r},n,this.options.timeoutMs),a=i?.output?.message?.content??[],c=[],l=[];for(let d of a)typeof d?.text=="string"&&c.push(d.text),d?.toolUse?.name&&l.push({id:d.toolUse.toolUseId??`tool_call_${l.length+1}`,type:"function",function:{name:d.toolUse.name,arguments:JSON.stringify(d.toolUse.input??{})}});let u={role:"assistant",content:c.length?c.join(""):null,...l.length?{tool_calls:l}:{}};return await re(i,n),await ne(u,n),{message:u,model:this.options.model,usage:{inputTokens:i?.usage?.inputTokens,outputTokens:i?.usage?.outputTokens}}}};import{spawn as _i}from"node:child_process";async function Wr(t,e,n,o){return await new Promise((r,s)=>{let i=_i(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")};o.signal?.addEventListener("abort",u,{once:!0}),i.stdout?.on("data",d=>{a+=String(d)}),i.stderr?.on("data",d=>{c+=String(d)}),i.on("error",d=>{clearTimeout(l),o.signal?.removeEventListener("abort",u),s(d)}),i.on("close",d=>{clearTimeout(l),o.signal?.removeEventListener("abort",u),o.signal?.aborted?s(pn(o.signal.reason)):d!==0?s(new Error(`${t} exited with code ${d}: ${c.trim()||a.trim()}`)):r({stdout:a,stderr:c})})})}function Ai(t){let e=t.split(/\r?\n/).filter(Boolean),n=[];for(let o of e)try{let r=JSON.parse(o),s=[r?.item?.text,r?.item?.content,r?.message?.content,r?.message,r?.text,r?.output_text,r?.content];for(let i of s)typeof i=="string"&&i.trim()&&n.push(i.trim())}catch{}return n.at(-1)??t.trim()}var Ke=class{options;constructor(e){this.options=e}async complete(e,n={}){let o=fn(e.messages,e.tools),r=["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",o,"-s","--no-ask-user","--allow-tool=read",`--excluded-tools=${r}`,"--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 Wr(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}}},Ge=class{options;constructor(e){this.options=e}async complete(e,n={}){let o=fn(e.messages,e.tools),r=["exec","--json","--sandbox","read-only","--skip-git-repo-check"];this.options.model&&r.push("--model",this.options.model),r.push(o);let{stdout:s}=await Wr(this.options.command||"codex",r,this.options,n),i=Ai(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 He=class{baseUrl;options;constructor(e){if(this.options=e,!e.accessToken)throw new Error("kpilot login is required to use hosted models. Run `kpilot login`.");this.baseUrl=e.baseUrl.replace(/\/+$/,"")}async complete(e,n={}){let o=new AbortController,r=setTimeout(()=>o.abort("request timeout"),this.options.timeoutMs??18e4),s=()=>o.abort(n.signal?.reason);n.signal?.aborted?o.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:o.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(`Hosted model endpoint returned non-JSON data (HTTP ${a.status}).`)}if(!a.ok){let u=typeof l.message=="string"?l.message:typeof l.error?.message=="string"?l.error.message:`Hosted model endpoint returned HTTP ${a.status}.`,d=typeof l.detail=="string"?l.detail:void 0,p=l.attempts??l.error?.attempts,b=Array.isArray(p)&&p.length>0?p.map(f=>`${f.model??"?"}: ${f.error??"unknown error"}`).join(" | "):void 0;throw new Error([u,d&&d!==u?d:void 0,b].filter(f=>!!(f&&f.trim())).join(" "))}if(l.message?.content&&n.onTextDelta&&await n.onTextDelta(l.message.content),n.onReasoningDelta){let u=Pe(l);u&&await n.onReasoningDelta(u)}return l}finally{clearTimeout(r),n.signal?.removeEventListener("abort",s)}}};import{spawn as Oi}from"node:child_process";function zr(t){if(!t||t.message?.role!=="assistant")throw new Error("External agent response must contain an assistant message.");return t}var We=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 o=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})}),r=await o.text(),s;try{s=JSON.parse(r)}catch{throw new Error(`External agent returned non-JSON data (HTTP ${o.status}).`)}if(!o.ok)throw new Error(s.message??`External agent returned HTTP ${o.status}.`);let i=zr(s);if(n.onReasoningDelta){let a=Pe(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((o,r)=>{let s=Oi(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",r),s.once("close",async u=>{if(clearTimeout(i),n.signal?.removeEventListener("abort",l),n.signal?.aborted)return r(n.signal.reason??new Error("External agent cancelled."));if(u!==0)return r(new Error(`External agent exited with code ${u}: ${c.trim().slice(0,1e3)}`));try{let d=zr(JSON.parse(a.trim()));if(n.onReasoningDelta){let p=Pe(d);p&&await n.onReasoningDelta(p)}d.message.content&&n.onTextDelta&&await n.onTextDelta(d.message.content),o(d)}catch(d){r(d)}}),s.stdin?.end(`${JSON.stringify({protocol:"kpilot-agent-v1",request:e})}
100
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 wn=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=Mt(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=Gi(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",r=>this.consume(r)),this.child.stderr.on("data",r=>{}),this.child.once("error",r=>this.failAll(r)),this.child.once("close",r=>{this.initialized=!1,this.failAll(new Error(`MCP server ${this.name} exited with code ${r??1}.`))});let n=W(await this.request("initialize",{protocolVersion:Zr,capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.9",description:"Local-first AI coding agent"}},e),"MCP initialize result"),o=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!eo.has(o))throw await this.close(),new Error(`MCP server ${this.name} negotiated unsupported protocol version ${o||"[missing]"}.`);this.serverInfo=W(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 o of n){if(!o.trim())continue;let r;try{r=JSON.parse(o)}catch{this.failAll(new Error(`MCP server ${this.name} emitted invalid JSON on stdout.`));continue}if(r.id!==void 0&&(r.result!==void 0||r.error)){let s=this.pending.get(r.id);if(!s)continue;clearTimeout(s.timeout),this.pending.delete(r.id),r.error?s.reject(new Error(`MCP ${this.name}: ${r.error.message??`error ${r.error.code??"unknown"}`}`)):s.resolve(r.result??null)}else r.id!==void 0&&r.method&&this.write({jsonrpc:"2.0",id:r.id,error:{code:-32601,message:`Client method not supported: ${r.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)}
102
- `)}notify(e,n){this.write({jsonrpc:"2.0",method:e,params:n})}async request(e,n,o){if(o?.aborted)throw new Error(`MCP request cancelled: ${String(o.reason??"")}`);let r=this.nextId++;return await new Promise((s,i)=>{let a=setTimeout(()=>{this.pending.delete(r),this.notify("notifications/cancelled",{requestId:r,reason:"timeout"}),i(new Error(`MCP ${this.name} request timed out: ${e}`))},this.config.timeoutMs),c=()=>{clearTimeout(a),this.pending.delete(r);try{this.notify("notifications/cancelled",{requestId:r,reason:"user cancellation"})}catch{}i(new Error(`MCP request cancelled: ${e}`))};o?.addEventListener("abort",c,{once:!0}),this.pending.set(r,{resolve:l=>{o?.removeEventListener("abort",c),s(l)},reject:l=>{o?.removeEventListener("abort",c),i(l)},timeout:a});try{this.write({jsonrpc:"2.0",id:r,method:e,params:n})}catch(l){clearTimeout(a),this.pending.delete(r),i(l instanceof Error?l:new Error(String(l)))}})}async listTools(e){await this.connect(e);let n=[],o;do{let r=W(await this.request("tools/list",o?{cursor:o}:{},e),"MCP tools/list result"),s=r.tools;if(!Array.isArray(s))throw new Error(`MCP server ${this.name} returned an invalid tool list.`);for(let i of s){let a=W(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:W(a.inputSchema,`MCP inputSchema for ${a.name}`)})}o=typeof r.nextCursor=="string"?r.nextCursor:void 0}while(o);return n}async callTool(e,n,o){await this.connect(o);let r=await this.request("tools/call",{name:e,arguments:n},o);return{ok:W(r,"MCP tools/call result").isError!==!0,output:to(r),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 o=!1,r=()=>{o||(o=!0,clearTimeout(s),clearTimeout(i),clearTimeout(a),n())};e.once("close",r),e.stdin?.end();let s=setTimeout(()=>e.kill("SIGTERM"),300),i=setTimeout(()=>e.kill("SIGKILL"),900),a=setTimeout(r,1200)})}},yn=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 o=new URL(n.url);if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`MCP server ${e} http transport requires an http(s) url; got ${o.protocol}`);this.name=Mt(e),this.config={...n,timeoutMs:n.timeoutMs??3e4},this.url=o.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=W(await this.request("initialize",{protocolVersion:"2025-06-18",capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.9",description:"Local-first AI coding agent"}},e),"MCP initialize result"),o=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!eo.has(o))throw new Error(`MCP server ${this.name} negotiated unsupported protocol version ${o||"[missing]"}.`);this.serverInfo=W(n.serverInfo,"MCP serverInfo"),this.notify("notifications/initialized",{}),this.initialized=!0}async request(e,n,o){if(o?.aborted)throw new Error(`MCP request cancelled: ${String(o.reason??"")}`);let r=this.nextId++;return await new Promise((s,i)=>{let a=setTimeout(()=>{this.pending.delete(r),this.notify("notifications/cancelled",{requestId:r,reason:"timeout"}),i(new Error(`MCP ${this.name} request timed out: ${e}`))},this.config.timeoutMs),c=()=>{clearTimeout(a),this.pending.delete(r);try{this.notify("notifications/cancelled",{requestId:r,reason:"user cancellation"})}catch{}i(new Error(`MCP request cancelled: ${e}`))};o?.addEventListener("abort",c,{once:!0});let l=u=>{o?.removeEventListener("abort",c),u()};this.pending.set(r,{resolve:u=>l(()=>s(u)),reject:u=>l(()=>i(u)),timer:a}),this.postBody({jsonrpc:"2.0",id:r,method:e,params:n}).then(u=>this.consumeResponse(u)).catch(u=>{let d=this.pending.get(r);d&&(clearTimeout(d.timer),this.pending.delete(r),l(()=>i(u instanceof Error?u:new Error(String(u)))))})})}notify(e,n){return this.postBody({jsonrpc:"2.0",method:e,params:n}).then(o=>{o?.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(),o=new TextDecoder,r="";for(;;){let{done:s,value:i}=await n.read();if(s)break;r+=o.decode(i,{stream:!0});let a=r.indexOf(`
101
+ `)||JSON.stringify(t,null,2)}var wn=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=Mt(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=Gi(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",r=>this.consume(r)),this.child.stderr.on("data",r=>{}),this.child.once("error",r=>this.failAll(r)),this.child.once("close",r=>{this.initialized=!1,this.failAll(new Error(`MCP server ${this.name} exited with code ${r??1}.`))});let n=W(await this.request("initialize",{protocolVersion:Zr,capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.10",description:"Local-first AI coding agent"}},e),"MCP initialize result"),o=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!eo.has(o))throw await this.close(),new Error(`MCP server ${this.name} negotiated unsupported protocol version ${o||"[missing]"}.`);this.serverInfo=W(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 o of n){if(!o.trim())continue;let r;try{r=JSON.parse(o)}catch{this.failAll(new Error(`MCP server ${this.name} emitted invalid JSON on stdout.`));continue}if(r.id!==void 0&&(r.result!==void 0||r.error)){let s=this.pending.get(r.id);if(!s)continue;clearTimeout(s.timeout),this.pending.delete(r.id),r.error?s.reject(new Error(`MCP ${this.name}: ${r.error.message??`error ${r.error.code??"unknown"}`}`)):s.resolve(r.result??null)}else r.id!==void 0&&r.method&&this.write({jsonrpc:"2.0",id:r.id,error:{code:-32601,message:`Client method not supported: ${r.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)}
102
+ `)}notify(e,n){this.write({jsonrpc:"2.0",method:e,params:n})}async request(e,n,o){if(o?.aborted)throw new Error(`MCP request cancelled: ${String(o.reason??"")}`);let r=this.nextId++;return await new Promise((s,i)=>{let a=setTimeout(()=>{this.pending.delete(r),this.notify("notifications/cancelled",{requestId:r,reason:"timeout"}),i(new Error(`MCP ${this.name} request timed out: ${e}`))},this.config.timeoutMs),c=()=>{clearTimeout(a),this.pending.delete(r);try{this.notify("notifications/cancelled",{requestId:r,reason:"user cancellation"})}catch{}i(new Error(`MCP request cancelled: ${e}`))};o?.addEventListener("abort",c,{once:!0}),this.pending.set(r,{resolve:l=>{o?.removeEventListener("abort",c),s(l)},reject:l=>{o?.removeEventListener("abort",c),i(l)},timeout:a});try{this.write({jsonrpc:"2.0",id:r,method:e,params:n})}catch(l){clearTimeout(a),this.pending.delete(r),i(l instanceof Error?l:new Error(String(l)))}})}async listTools(e){await this.connect(e);let n=[],o;do{let r=W(await this.request("tools/list",o?{cursor:o}:{},e),"MCP tools/list result"),s=r.tools;if(!Array.isArray(s))throw new Error(`MCP server ${this.name} returned an invalid tool list.`);for(let i of s){let a=W(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:W(a.inputSchema,`MCP inputSchema for ${a.name}`)})}o=typeof r.nextCursor=="string"?r.nextCursor:void 0}while(o);return n}async callTool(e,n,o){await this.connect(o);let r=await this.request("tools/call",{name:e,arguments:n},o);return{ok:W(r,"MCP tools/call result").isError!==!0,output:to(r),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 o=!1,r=()=>{o||(o=!0,clearTimeout(s),clearTimeout(i),clearTimeout(a),n())};e.once("close",r),e.stdin?.end();let s=setTimeout(()=>e.kill("SIGTERM"),300),i=setTimeout(()=>e.kill("SIGKILL"),900),a=setTimeout(r,1200)})}},yn=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 o=new URL(n.url);if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`MCP server ${e} http transport requires an http(s) url; got ${o.protocol}`);this.name=Mt(e),this.config={...n,timeoutMs:n.timeoutMs??3e4},this.url=o.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=W(await this.request("initialize",{protocolVersion:"2025-06-18",capabilities:{},clientInfo:{name:"kpilot",title:"kpilot",version:"0.10.10",description:"Local-first AI coding agent"}},e),"MCP initialize result"),o=typeof n.protocolVersion=="string"?n.protocolVersion:"";if(!eo.has(o))throw new Error(`MCP server ${this.name} negotiated unsupported protocol version ${o||"[missing]"}.`);this.serverInfo=W(n.serverInfo,"MCP serverInfo"),this.notify("notifications/initialized",{}),this.initialized=!0}async request(e,n,o){if(o?.aborted)throw new Error(`MCP request cancelled: ${String(o.reason??"")}`);let r=this.nextId++;return await new Promise((s,i)=>{let a=setTimeout(()=>{this.pending.delete(r),this.notify("notifications/cancelled",{requestId:r,reason:"timeout"}),i(new Error(`MCP ${this.name} request timed out: ${e}`))},this.config.timeoutMs),c=()=>{clearTimeout(a),this.pending.delete(r);try{this.notify("notifications/cancelled",{requestId:r,reason:"user cancellation"})}catch{}i(new Error(`MCP request cancelled: ${e}`))};o?.addEventListener("abort",c,{once:!0});let l=u=>{o?.removeEventListener("abort",c),u()};this.pending.set(r,{resolve:u=>l(()=>s(u)),reject:u=>l(()=>i(u)),timer:a}),this.postBody({jsonrpc:"2.0",id:r,method:e,params:n}).then(u=>this.consumeResponse(u)).catch(u=>{let d=this.pending.get(r);d&&(clearTimeout(d.timer),this.pending.delete(r),l(()=>i(u instanceof Error?u:new Error(String(u)))))})})}notify(e,n){return this.postBody({jsonrpc:"2.0",method:e,params:n}).then(o=>{o?.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(),o=new TextDecoder,r="";for(;;){let{done:s,value:i}=await n.read();if(s)break;r+=o.decode(i,{stream:!0});let a=r.indexOf(`
103
103
  `);for(;a!==-1;){let c=r.slice(0,a).trim();if(r=r.slice(a+1),c.startsWith("data:")){let l=c.slice(5).trim();l&&this.routeMessage(this.safelyParse(l))}a=r.indexOf(`
104
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=[],o;do{let r=W(await this.request("tools/list",o?{cursor:o}:{},e),"MCP tools/list result"),s=r.tools;if(!Array.isArray(s))throw new Error(`MCP server ${this.name} returned an invalid tool list.`);for(let i of s){let a=W(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:W(a.inputSchema,`MCP inputSchema for ${a.name}`)})}o=typeof r.nextCursor=="string"?r.nextCursor:void 0}while(o);return n}async callTool(e,n,o){await this.connect(o);let r=await this.request("tools/call",{name:e,arguments:n},o);return{ok:W(r,"MCP tools/call result").isError!==!0,output:to(r),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()}},we=class t{tools=new Map;clients;constructor(e){this.clients=e}static async connect(e,n){let o=Object.entries(e).filter(([,s])=>s.enabled!==!1).map(([s,i])=>(i.transport??"stdio")==="stdio"?new wn(s,i):new yn(s,i)),r=new t(o);for(let s of o){let i=await s.listTools(n);for(let a of i){let c=`mcp_${Mt(s.name)}_${Mt(a.name)}`;if(r.tools.has(c))throw new Error(`Duplicate MCP tool name: ${c}`);r.tools.set(c,{client:s,remoteName:a.name,definition:{type:"function",function:{name:c,description:`[MCP:${s.name}] ${a.description??a.title??a.name}`,parameters:a.inputSchema}}})}}return r}definitions(){return[...this.tools.values()].map(e=>e.definition)}async execute(e,n,o){let r=this.tools.get(e);return r?await r.client.callTool(r.remoteName,n,o.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 Hi="2025-11-25",Wi=["2025-11-25","2025-06-18","2025-03-26"];function zi(t){return t.map(e=>({name:e.function.name,description:e.function.description,inputSchema:e.function.parameters??{type:"object",properties:{}}}))}function no(t,e){if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e} must be an object.`);return t}var $t=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,o=e.method;if(!(typeof n=="number"||typeof n=="string"))return o==="notifications/initialized"&&(this.initialized=!0),null;let s=no(e.params??{},`${o} params`);try{let i=await this.handleMethod(String(o??""),s);return o==="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:o==="tools/call"?-32603:-32601,message:a}}}}async handleMethod(e,n){switch(e){case"initialize":{let o=typeof n.protocolVersion=="string"?n.protocolVersion:"";return{protocolVersion:Wi.includes(o)?o:Hi,capabilities:{tools:{listChanged:!1}},serverInfo:{name:this.name,version:this.version}}}case"ping":return{};case"tools/list":{let o=zi(this.runtime.definitions());return typeof n.cursor=="string"?{tools:[],nextCursor:void 0}:{tools:o}}case"tools/call":{let o=typeof n.name=="string"?n.name:"";if(!o)throw new Error("tools/call requires a name.");let r=no(n.arguments??{},"tools/call arguments"),s={rootDir:this.rootDir,mode:this.mode},i=await this.runtime.execute(o,r,s);return{content:[{type:"text",text:i.output??""}],isError:i.ok!==!0}}default:throw new Error(`Method not found: ${e}`)}}};function ro(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 so(t){await new Promise((e,n)=>{let o="";process.stdin.setEncoding("utf8");let r=(s,i=!1)=>{o+=s;let a=o.indexOf(`
105
105
  `);for(;a!==-1;){let c=o.slice(0,a);o=o.slice(a+1);let l=ro(c);l&&oo(t,l),a=o.indexOf(`
@@ -211,7 +211,7 @@ See \`package.json\` scripts above (or README). Prefer the repo's documented pac
211
211
  `)}
212
212
  `;let c=xe(t);return await zt(c,{recursive:!0,mode:493}),await Xn(tr(t),`# Logbook learnings
213
213
 
214
- ${a}`,{encoding:"utf8",mode:420}),await dt(t,{lastLearnedAt:new Date().toISOString()}),s}function kl(t){let e=[],n=t.prompt.trim();if(!n||n===Vt)return[];let o=s=>{if(!s)return;let i=or(s);!i||i.length<8||e.some(a=>a.toLowerCase()===i.toLowerCase())||e.length>=ss||e.push(i)},r=[/\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 r){let i=s.exec(n);i?.[1]&&o(i[1])}if(t.changed&&t.diffAfter){let s=t.diffAfter;/\bpnpm-lock\.yaml\b/.test(s)||/\bpnpm-workspace\.yaml\b/.test(s)?o("Use pnpm for installs and scripts in this repository."):/\bpackage-lock\.json\b/.test(s)?o("Use npm for installs and scripts in this repository."):/\byarn\.lock\b/.test(s)?o("Use yarn for installs and scripts in this repository."):/\bbun\.lockb?\b/.test(s)&&o("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)?o("Tests in this repository often use *.spec.* filenames."):/\.test\.(ts|tsx|js|jsx)\b/.test(s)&&!/\.spec\.(ts|tsx|js|jsx)\b/.test(s)&&o("Tests in this repository often use *.test.* filenames.")}return e.slice(0,ss)}async function ms(t){if(!await mt(t.rootDir))return[];if(t.prompt.trim()===Vt)return[];let e=kl(t);return e.length?vl(t.rootDir,e):[]}function ps(t){let e=t.replace(/\\/g,"/");return e===".kpilot"||e.startsWith(".kpilot/")||e.includes("/.kpilot/")}var B="0.10.9",ir=[26,0,0];function Tl(){let t=process.version.replace(/^v/,"").split(".").slice(0,3).map(Number);if(!ir.every((n,o)=>{for(let r=0;r<o;r+=1)if((t[r]??0)!==ir[r])return!0;return(t[o]??0)>=n})&&process.env.KPILOT_ALLOW_UNSUPPORTED_NODE!=="1")throw new Error(`kpilot requires Node.js ${ir.join(".")} or newer; detected ${process.version}.`)}var M={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m"},hr=[{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:"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:"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"]}],ks=new Set(hr.flatMap(t=>[t.name,...t.aliases??[]]));function El(t){if(!t.startsWith("/")||t==="/")return!1;let[e="",...n]=t.slice(1).split(/\s+/);return!e||n.length>0?!1:!ks.has(e)}function $(t,e){return process.stdout.isTTY?`${t}${e}${M.reset}`:e}function je(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),o=t/10**(n*3),r=o>=100?0:o>=10?1:2;return`${o.toFixed(r)}${e[n-1]}`}function xs(t){if(t)return{pause:()=>{t.closed||t.pause()},resume:()=>{t.closed||t.resume()}}}function Cl(){console.log($(M.bold,"Slash commands")),console.log($(M.dim,"Type / for arrow-key command picker (or /help)."));for(let t of hr)console.log(` ${$(M.cyan,t.usage.padEnd(28))} ${t.description}`);console.log(` ${$(M.cyan,"/<skill-name> [args]".padEnd(28))} Run a skill directly`)}async function Rl(t){let e=(t.skillNames??[]).map(s=>({name:s,usage:`/${s}`,description:`Run skill \u201C${s}\u201D`})),n=[...hr,...e],o=await G({title:"Select a slash 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(!o)return null;let r=n.find(s=>s.name===o);if(!r)return null;if(r.choices&&r.choices.length>0){let s=await G({title:`${r.usage} \u2014 choose an action:`,question:t.question,pauseResume:t.pauseResume,choices:r.choices});if(!s)return P("Cancelled."),null;if(r.name==="logbook"&&s==="capture")return"/logbook";if(r.name==="feedback"){let i=(await t.question("Optional note \u203A ")).trim();return i?`/feedback ${s} ${i}`:`/feedback ${s}`}return`/${r.name} ${s}`}if(r.needsArgs){let s=(await t.question(r.argPrompt??"Args \u203A ")).trim();return s?`/${r.name} ${s}`:(P("Cancelled."),null)}return`/${r.name}`}function P(t){console.log(`${$(M.cyan,"\u25C6")} ${t}`)}function v(t){console.log(`${$(M.green,"\u2713")} ${t}`)}function R(t){console.log(`${$(M.yellow,"!")} ${t}`)}function F(t){console.error(`${$(M.red,"\u2717")} ${t}`)}function Ml(){return _.join(ys(),".config","kpilot","installed-version")}function $l(t,e){let n=s=>s.split(".").map(i=>Number(i)||0),o=n(t),r=n(e);for(let s=0;s<3;s+=1)if((o[s]??0)!==(r[s]??0))return(o[s]??0)<(r[s]??0)?-1:1;return 0}async function _l(){if(process.env.KPILOT_SILENT_VERSION_NOTICE==="1")return;let t=Ml(),e;try{e=(await gr(t,"utf8")).trim()||void 0}catch{e=void 0}if(e!==B){if(e){let n=$l(e,B)<0?"Updated":"Changed";P(`kpilot CLI ${n}: ${e} \u2192 ${B}`)}else P(`kpilot CLI installed: ${B}`);try{await gt(_.dirname(t),{recursive:!0}),await me(t,`${B}
214
+ ${a}`,{encoding:"utf8",mode:420}),await dt(t,{lastLearnedAt:new Date().toISOString()}),s}function kl(t){let e=[],n=t.prompt.trim();if(!n||n===Vt)return[];let o=s=>{if(!s)return;let i=or(s);!i||i.length<8||e.some(a=>a.toLowerCase()===i.toLowerCase())||e.length>=ss||e.push(i)},r=[/\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 r){let i=s.exec(n);i?.[1]&&o(i[1])}if(t.changed&&t.diffAfter){let s=t.diffAfter;/\bpnpm-lock\.yaml\b/.test(s)||/\bpnpm-workspace\.yaml\b/.test(s)?o("Use pnpm for installs and scripts in this repository."):/\bpackage-lock\.json\b/.test(s)?o("Use npm for installs and scripts in this repository."):/\byarn\.lock\b/.test(s)?o("Use yarn for installs and scripts in this repository."):/\bbun\.lockb?\b/.test(s)&&o("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)?o("Tests in this repository often use *.spec.* filenames."):/\.test\.(ts|tsx|js|jsx)\b/.test(s)&&!/\.spec\.(ts|tsx|js|jsx)\b/.test(s)&&o("Tests in this repository often use *.test.* filenames.")}return e.slice(0,ss)}async function ms(t){if(!await mt(t.rootDir))return[];if(t.prompt.trim()===Vt)return[];let e=kl(t);return e.length?vl(t.rootDir,e):[]}function ps(t){let e=t.replace(/\\/g,"/");return e===".kpilot"||e.startsWith(".kpilot/")||e.includes("/.kpilot/")}var B="0.10.10",ir=[26,0,0];function Tl(){let t=process.version.replace(/^v/,"").split(".").slice(0,3).map(Number);if(!ir.every((n,o)=>{for(let r=0;r<o;r+=1)if((t[r]??0)!==ir[r])return!0;return(t[o]??0)>=n})&&process.env.KPILOT_ALLOW_UNSUPPORTED_NODE!=="1")throw new Error(`kpilot requires Node.js ${ir.join(".")} or newer; detected ${process.version}.`)}var M={reset:"\x1B[0m",bold:"\x1B[1m",dim:"\x1B[2m",cyan:"\x1B[36m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",magenta:"\x1B[35m"},hr=[{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:"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:"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"]}],ks=new Set(hr.flatMap(t=>[t.name,...t.aliases??[]]));function El(t){if(!t.startsWith("/")||t==="/")return!1;let[e="",...n]=t.slice(1).split(/\s+/);return!e||n.length>0?!1:!ks.has(e)}function $(t,e){return process.stdout.isTTY?`${t}${e}${M.reset}`:e}function je(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),o=t/10**(n*3),r=o>=100?0:o>=10?1:2;return`${o.toFixed(r)}${e[n-1]}`}function xs(t){if(t)return{pause:()=>{t.closed||t.pause()},resume:()=>{t.closed||t.resume()}}}function Cl(){console.log($(M.bold,"Slash commands")),console.log($(M.dim,"Type / for arrow-key command picker (or /help)."));for(let t of hr)console.log(` ${$(M.cyan,t.usage.padEnd(28))} ${t.description}`);console.log(` ${$(M.cyan,"/<skill-name> [args]".padEnd(28))} Run a skill directly`)}async function Rl(t){let e=(t.skillNames??[]).map(s=>({name:s,usage:`/${s}`,description:`Run skill \u201C${s}\u201D`})),n=[...hr,...e],o=await G({title:"Select a slash 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(!o)return null;let r=n.find(s=>s.name===o);if(!r)return null;if(r.choices&&r.choices.length>0){let s=await G({title:`${r.usage} \u2014 choose an action:`,question:t.question,pauseResume:t.pauseResume,choices:r.choices});if(!s)return P("Cancelled."),null;if(r.name==="logbook"&&s==="capture")return"/logbook";if(r.name==="feedback"){let i=(await t.question("Optional note \u203A ")).trim();return i?`/feedback ${s} ${i}`:`/feedback ${s}`}return`/${r.name} ${s}`}if(r.needsArgs){let s=(await t.question(r.argPrompt??"Args \u203A ")).trim();return s?`/${r.name} ${s}`:(P("Cancelled."),null)}return`/${r.name}`}function P(t){console.log(`${$(M.cyan,"\u25C6")} ${t}`)}function v(t){console.log(`${$(M.green,"\u2713")} ${t}`)}function R(t){console.log(`${$(M.yellow,"!")} ${t}`)}function F(t){console.error(`${$(M.red,"\u2717")} ${t}`)}function Ml(){return _.join(ys(),".config","kpilot","installed-version")}function $l(t,e){let n=s=>s.split(".").map(i=>Number(i)||0),o=n(t),r=n(e);for(let s=0;s<3;s+=1)if((o[s]??0)!==(r[s]??0))return(o[s]??0)<(r[s]??0)?-1:1;return 0}async function _l(){if(process.env.KPILOT_SILENT_VERSION_NOTICE==="1")return;let t=Ml(),e;try{e=(await gr(t,"utf8")).trim()||void 0}catch{e=void 0}if(e!==B){if(e){let n=$l(e,B)<0?"Updated":"Changed";P(`kpilot CLI ${n}: ${e} \u2192 ${B}`)}else P(`kpilot CLI installed: ${B}`);try{await gt(_.dirname(t),{recursive:!0}),await me(t,`${B}
215
215
  `,{mode:384})}catch{}}}function Al(){return`${$(M.bold,`kpilot ${B}`)} \u2014 governed engineering agent
216
216
 
217
217
  All requests go through kpilot \u2014 sign in once, and kpilot handles the rest.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kpilot",
3
- "version": "0.10.9",
3
+ "version": "0.10.10",
4
4
  "description": "Proprietary terminal AI coding pilot with hosted automatic model routing, account management, and billing.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -32,9 +32,9 @@
32
32
  "bring-your-own-agent",
33
33
  "proprietary"
34
34
  ],
35
- "homepage": "https://kpilot.ai",
35
+ "homepage": "https://konsolepilot.ai",
36
36
  "author": {
37
37
  "name": "UAB Tagrise Technologies",
38
- "url": "https://kpilot.ai/"
38
+ "url": "https://konsolepilot.ai/"
39
39
  }
40
40
  }