kslock-daemon 0.1.1 → 0.1.4
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 +8 -0
- package/dist/index.js +28 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,14 @@ npx -y kslock-daemon@0.1.1 start \
|
|
|
10
10
|
--machine-key mk_xxx
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
For local source development, root `.env.dev` can provide the same parameters:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
KSLOCK_SERVER_URL=http://127.0.0.1:3001
|
|
17
|
+
KSLOCK_MACHINE_KEY=mk_xxx
|
|
18
|
+
pnpm dev:daemon
|
|
19
|
+
```
|
|
20
|
+
|
|
13
21
|
The daemon connects to the API websocket gateway and executes configured local runtimes such as Codex, Claude, kscc, and opencode.
|
|
14
22
|
|
|
15
23
|
## Runtime Paths
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
`);import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`);return
|
|
2
|
+
import be from"node:os";import{existsSync as Bn,readFileSync as ct}from"node:fs";import{join as V}from"node:path";function lt(t,e=process.env){let n=e.KSLOCK_SERVER_URL||e.DAEMON_SERVER_URL||"",r=e.KSLOCK_MACHINE_KEY||e.DAEMON_MACHINE_KEY||"";for(let s=0;s<t.length;s+=1){let o=t[s];if(o!=="start"){if(o==="--server-url"&&t[s+1]){n=t[++s];continue}o==="--machine-key"&&t[s+1]&&(r=t[++s])}}return!n||!r?null:{serverUrl:n.replace(/\/$/,""),machineKey:r,daemonVersion:ke(e),hostname:be.hostname(),os:be.platform(),arch:be.arch(),reconnectBaseMs:1e3}}function dt(t=process.env,e=process.cwd()){let n=Un(t.KSLOCK_ENV??t.NODE_ENV),r=zn(e),s=[n?V(r,`.env.${n}`):null,V(r,".env")];for(let o of s)o&&Bn(o)&&qn(o,t)}function ke(t=process.env){let e=t.KSLOCK_DAEMON_VERSION?.trim();return e||(Jn()??"0.0.0-dev")}function Jn(){try{let t=JSON.parse(ct(new URL("../package.json",import.meta.url),"utf8"));return typeof t.version=="string"&&t.version.trim()?t.version.trim():null}catch{return null}}function zn(t){return t.endsWith(V("apps","daemon"))?V(t,"..",".."):t}function qn(t,e){for(let n of ct(t,"utf8").split(/\r?\n/)){let r=n.trim();if(!r||r.startsWith("#"))continue;let s=r.indexOf("=");if(s===-1)continue;let o=r.slice(0,s).trim();if(e[o]!==void 0)continue;let i=r.slice(s+1).trim();i.startsWith('"')&&i.endsWith('"')&&(i=i.slice(1,-1)),i.startsWith("'")&&i.endsWith("'")&&(i=i.slice(1,-1)),e[o]=i}}function Un(t){let e=t?.trim().toLowerCase();if(e)return e==="development"||e==="local"?"dev":e==="production"?"prod":e}var Ce=["Usage: kslock-daemon [start] --server-url <url> --machine-key <key>"," kslock-daemon check-messages --agent-id <agent-id> [--channel-id <channel-id>] [--json]","","Environment:"," KSLOCK_SERVER_URL API server URL, for example https://api.kslock.ai"," KSLOCK_MACHINE_KEY Machine key created from the web console"," KSLOCK_DAEMON_VERSION Override reported daemon version, optional"].join(`
|
|
3
|
+
`);import On from"ws";var H=class{constructor(e){this.sendFrame=e}delivered(e){this.sendFrame({type:"agent:delivery_ack",deliveryId:e.deliveryId,agentId:e.agentId,status:"delivered"})}completed(e){this.sendFrame({type:"agent:delivery_ack",deliveryId:e.deliveryId,agentId:e.agentId,status:"completed"})}failed(e,n){this.sendFrame({type:"agent:delivery_ack",deliveryId:e.deliveryId,agentId:e.agentId,status:"failed",error:n})}status(e,n,r){this.sendFrame({type:"agent:status",agentId:e.agentId,status:n,...r!==void 0?{sessionId:r}:{}})}runtimeLog(e,n,r){this.sendFrame({type:"runtime:log",agentId:e.agentId,deliveryId:e.deliveryId,stream:n,content:r})}message(e,n){this.sendFrame({type:"agent:message",agentId:e.agentId,channelId:e.channelId,threadId:e.threadId,replyToMessageId:e.messageId,deliveryId:e.deliveryId,content:n})}messageDelta(e,n,r){!n&&!r||this.sendFrame({type:"agent:message_delta",agentId:e.agentId,channelId:e.channelId,threadId:e.threadId,replyToMessageId:e.messageId,deliveryId:e.deliveryId,contentDelta:n,...r!==void 0?{contentSnapshot:r}:{}})}taskInProgress(e){e.taskId&&this.sendFrame({type:"task:status",taskId:e.taskId,agentId:e.agentId,status:"in_progress",message:`${e.runtimeType} agent started working on the task.`})}taskInReview(e){e.taskId&&this.sendFrame({type:"task:status",taskId:e.taskId,agentId:e.agentId,status:"in_review",message:`${e.runtimeType} agent completed the task and requested review.`})}};function g(t){return`${t.agentId}:${t.channelId}`}function Ae(t){return encodeURIComponent(t)}var Q=class{constructor(e){this.onCancelledBeforeStart=e}deliveryQueues=new Map;activeDeliveries=new Map;activeScopes=new Map;cancelledDeliveries=new Map;async enqueue(e,n,r={}){if(this.canRunAsBusyDelivery(e,r))try{await r.onBusyDelivery?.(e)}catch{}let s=g(e),i=(this.deliveryQueues.get(s)??Promise.resolve()).catch(()=>{}).then(()=>this.run(e,n));this.deliveryQueues.set(s,i),await i.finally(()=>{this.deliveryQueues.get(s)===i&&this.deliveryQueues.delete(s)})}cancel(e,n="cancelled_by_user"){this.cancelledDeliveries.set(e,n),this.activeDeliveries.get(e)?.abort(n)}canRunAsBusyDelivery(e,n){if(!n.allowBusyDelivery)return!1;let r=this.activeScopes.get(g(e));return!!(r&&r.runtimeType===e.runtimeType&&r.deliveryIds.size>0)}async run(e,n){let r=this.cancelledDeliveries.get(e.deliveryId);if(r){this.cancelledDeliveries.delete(e.deliveryId),this.onCancelledBeforeStart(e,r);return}let s=new AbortController;this.activeDeliveries.set(e.deliveryId,s),this.markAgentActive(e);try{await n(e,s.signal)}finally{this.activeDeliveries.delete(e.deliveryId),this.cancelledDeliveries.delete(e.deliveryId),this.markAgentInactive(e)}}markAgentActive(e){let n=g(e),r=this.activeScopes.get(n)??{runtimeType:e.runtimeType,deliveryIds:new Set};r.runtimeType=e.runtimeType,r.deliveryIds.add(e.deliveryId),this.activeScopes.set(n,r)}markAgentInactive(e){let n=g(e),r=this.activeScopes.get(n);r&&(r.deliveryIds.delete(e.deliveryId),r.deliveryIds.size===0&&this.activeScopes.delete(n))}};import{mkdir as Vn,readdir as Hn,readFile as Qn,rename as Xn,writeFile as Yn}from"node:fs/promises";import{join as Te}from"node:path";import{homedir as Gn}from"node:os";import{join as X}from"node:path";function Wn(){return X(Gn(),".agent-collab")}function Ee(t){return X(Wn(),"agents",Ae(t))}function R(t){return X(Ee(t.agentId),"channels",Ae(t.channelId))}function mt(t){return X(R(t),"logs")}var Zn="inbox.json",er="inbox.md",Y=new Map;function gt(t){return Te(R(t),Zn)}function De(t){return Te(R(t),er)}async function ft(t){return vt(t,async()=>{let e=await ee(t);return e.messages.some(n=>n.deliveryId===t.deliveryId)||e.messages.push(nr(t)),ht(e)})}async function Z(t,e){return vt(t,async()=>{let n=await ee(t),r=n.messages.filter(s=>s.deliveryId!==e);return r.length===n.messages.length?n:ht({...n,updatedAt:new Date().toISOString(),messages:r})})}async function yt(t){return t.channelId?ee({agentId:t.agentId,channelId:t.channelId}):tr(t.agentId)}function Me(t){return t.messages.length===0?["# kslock inbox","","No pending messages.",""].join(`
|
|
4
|
+
`):["# kslock inbox","",`Scope: ${t.runtimeScopeKey??`${t.agentId}/all-channels`}`,"",`Pending messages: ${t.messages.length}`,`Updated at: ${t.updatedAt}`,"",...t.messages.flatMap((e,n)=>[`## ${n+1}. delivery ${e.deliveryId}`,"",`- messageId: ${e.messageId}`,`- channelId: ${e.channelId}`,`- threadId: ${e.threadId??"none"}`,`- taskId: ${e.taskId??"none"}`,`- createdAt: ${e.createdAt}`,"",e.content,"",...rr(e)])].join(`
|
|
5
|
+
`)}async function ee(t){try{let e=await Qn(gt(t),"utf8"),n=JSON.parse(e);return{agentId:t.agentId,channelId:t.channelId,runtimeScopeKey:g(t),updatedAt:typeof n.updatedAt=="string"?n.updatedAt:new Date().toISOString(),messages:Array.isArray(n.messages)?n.messages.filter(sr):[]}}catch{return{agentId:t.agentId,channelId:t.channelId,runtimeScopeKey:g(t),updatedAt:new Date().toISOString(),messages:[]}}}async function tr(t){let e=Te(Ee(t),"channels"),n=[],r=new Date().toISOString();try{let s=await Hn(e,{withFileTypes:!0});for(let o of s){if(!o.isDirectory())continue;let i=decodeURIComponent(o.name),a=await ee({agentId:t,channelId:i});n.push(...a.messages),a.updatedAt>r&&(r=a.updatedAt)}}catch{}return{agentId:t,channelId:null,runtimeScopeKey:null,updatedAt:r,messages:n.sort((s,o)=>s.createdAt.localeCompare(o.createdAt))}}async function ht(t){let e={...t,updatedAt:new Date().toISOString()};if(!t.channelId)throw new Error("cannot write aggregate agent inbox");let n={agentId:t.agentId,channelId:t.channelId},r=R(n);return await Vn(r,{recursive:!0}),await pt(gt(n),`${JSON.stringify(e,null,2)}
|
|
6
|
+
`),await pt(De(n),Me(e)),e}async function pt(t,e){let n=`${t}.${process.pid}.${Date.now()}.tmp`;await Yn(n,e,"utf8"),await Xn(n,t)}async function vt(t,e){let n=g(t),r=Y.get(n)??Promise.resolve(),s=()=>{},o=r.catch(()=>{}).then(()=>new Promise(i=>{s=i}));Y.set(n,o),await r.catch(()=>{});try{return await e()}finally{s(),Y.get(n)===o&&Y.delete(n)}}function nr(t){return{deliveryId:t.deliveryId,messageId:t.messageId,serverId:t.serverId,channelId:t.channelId,threadId:t.threadId,taskId:t.taskId,content:t.content,attachments:t.attachments.map(e=>({id:e.id,filename:e.filename,contentType:e.contentType,size:e.size})),createdAt:new Date().toISOString()}}function rr(t){return t.attachments.length===0?[]:["Attachments:",...t.attachments.map(e=>`- ${e.filename} (${e.contentType}, ${e.size} bytes)`),""]}function sr(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.deliveryId=="string"&&typeof e.messageId=="string"&&typeof e.serverId=="string"&&typeof e.channelId=="string"&&(typeof e.threadId=="string"||e.threadId===null)&&(typeof e.taskId=="string"||e.taskId===null)&&typeof e.content=="string"&&Array.isArray(e.attachments)&&typeof e.createdAt=="string"}import{appendFile as or,mkdir as ir,rename as ar,stat as ur}from"node:fs/promises";import{join as cr}from"node:path";var lr="session.log",dr=1e6,mr=5;async function C(t,e,n){let r=mt(t);await ir(r,{recursive:!0});let s=cr(r,lr);await pr(s);let o=JSON.stringify({time:new Date().toISOString(),agentId:t.agentId,channelId:t.channelId,stream:e,content:n});await or(s,`${o}
|
|
7
|
+
`,"utf8")}async function pr(t){try{if((await ur(t)).size<dr)return}catch{return}for(let e=mr-1;e>=1;e-=1)await wt(`${t}.${e}`,`${t}.${e+1}`);await wt(t,`${t}.1`)}async function wt(t,e){try{await ar(t,e)}catch{}}function xt(t){let e=t.pendingCount===1?"message":"messages";return[`[System notification: You have ${t.pendingCount} pending inbox ${e}.]`,"","Do not lose your current task context. At the next safe breakpoint, inspect the inbox before context-sensitive side effects.",`Run: ${t.checkMessagesCommand}`,`Fallback file: ${t.inboxFile}`,"","Pending inbox deliveries remain queued and will be delivered as their own turns after the current turn finishes."].join(`
|
|
8
|
+
`)}function M(t){let e=["kslock-daemon check-messages",`--agent-id ${It(t.agentId)}`,`--channel-id ${It(t.channelId)}`].join(" "),n=De(t);return{KSLOCK_RUNTIME_SCOPE_KEY:g(t),KSLOCK_INBOX_FILE:n,KSLOCK_CHECK_MESSAGES_COMMAND:e}}function St(t){let e=M(t);return["Runtime inbox:",`- Current runtime scope: ${e.KSLOCK_RUNTIME_SCOPE_KEY}`,"- While you are busy, kslock may notify you about pending inbox messages.",`- Inspect them with: ${e.KSLOCK_CHECK_MESSAGES_COMMAND}`,`- If the command is unavailable, read: ${e.KSLOCK_INBOX_FILE}`,"- Pending inbox deliveries are queued and will arrive as their own turns; keep replies scoped to the current delivered message unless the user explicitly asks otherwise."].join(`
|
|
9
|
+
`)}function It(t){return/^[A-Za-z0-9_./:@-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}var te=class{constructor(e){this.publisher=e}create(e,n,r){return{cwd:e.workspacePath??void 0,abortSignal:n,env:{...process.env,AGENT_ID:e.agentId,SERVER_ID:e.serverId,CHANNEL_ID:e.channelId,RUNTIME_SCOPE_KEY:g(e),WORKSPACE_ID:e.workspaceId??"",AGENT_TOKEN:e.agentToken,AGENT_PROXY_URL:"",AGENT_RUNTIME:e.runtimeType,...M(e)},onLog:(s,o)=>{r?.(),this.publisher.runtimeLog(e,s,o),C(e,s,o)},onPartial:(s,o)=>{r?.(),this.publisher.messageDelta(e,s,o)}}}};function Rt(t){let e=gr(t.env??process.env),n=new AbortController,r=Date.now(),s=!1,o=null,i=()=>{n.abort(t.parentSignal?.reason??"runtime_cancelled")};t.parentSignal?.aborted?i():t.parentSignal?.addEventListener("abort",i,{once:!0});let a=()=>{e<=0||n.signal.aborted||(o&&clearTimeout(o),o=setTimeout(()=>{let u=Date.now()-r;if(u<e){a();return}s=!0;let c=`runtime stalled: no output for ${Math.round(u/1e3)}s on delivery ${t.frame.deliveryId}`;t.onStall(c),n.abort("runtime_stalled")},e))};return a(),{get signal(){return n.signal},get stalled(){return s},progress(){r=Date.now(),a()},dispose(){o&&(clearTimeout(o),o=null),t.parentSignal?.removeEventListener("abort",i)}}}function gr(t){let e=t.KSLOCK_DELIVERY_STALL_MS;if(!e)return 9e5;let n=Number(e);return!Number.isFinite(n)||n<0?9e5:n}var ne=class{constructor(e,n){this.runtimes=e;this.publisher=n;this.contextFactory=new te(n)}contextFactory;activeDeliveriesByAgent=new Map;async run(e,n){await Z(e,e.deliveryId),this.publisher.delivered(e),this.publisher.taskInProgress(e),this.startAgentWork(e);try{this.publisher.runtimeLog(e,"system",`using ${e.executionPolicy.preset} execution policy for @${e.agentHandle}`);let r=this.runtimes.get(e.runtimeType),s=Rt({frame:e,parentSignal:n,onStall:i=>{this.publisher.runtimeLog(e,"stderr",i),C(e,"stderr",i)}}),o;try{o=await r.handleDelivery(e,this.contextFactory.create(e,s.signal,()=>s.progress()))}catch(i){throw s.stalled?new Error("runtime_stalled"):i}finally{s.dispose()}e.attachments.length>0&&await C(e,"system",`delivery has attachments: ${e.attachments.map(i=>i.filename).join(", ")}`),o.sessionId&&this.activeAgentCount(e.agentId)<=1&&this.publisher.status(e,"working",o.sessionId),!o.suppressMessage&&o.content.trim()&&this.publisher.message(e,o.content),this.publisher.taskInReview(e),this.publisher.completed(e),this.finishAgentWork(e,"idle",o.sessionId??null)}catch(r){let s=r instanceof Error?r.message:`${e.runtimeType} runtime failed`;C(e,"stderr",s),this.publisher.failed(e,s),this.finishAgentWork(e,"error")}}startAgentWork(e){let n=this.activeAgentCount(e.agentId);this.activeDeliveriesByAgent.set(e.agentId,n+1),n===0&&this.publisher.status(e,"working")}finishAgentWork(e,n,r){let s=this.activeAgentCount(e.agentId),o=Math.max(0,s-1);if(o===0){this.activeDeliveriesByAgent.delete(e.agentId),this.publisher.status(e,n,r);return}this.activeDeliveriesByAgent.set(e.agentId,o)}activeAgentCount(e){return this.activeDeliveriesByAgent.get(e)??0}};import{randomUUID as Ht}from"node:crypto";import{mkdir as fr,readFile as yr,writeFile as hr}from"node:fs/promises";import{join as bt}from"node:path";function h(t){return R(t)}async function I(t){try{let e=await yr(bt(h(t),"session.json"),"utf8");return{...JSON.parse(e),agentId:t.agentId,channelId:t.channelId,runtimeScopeKey:g(t)}}catch{return null}}async function x(t){let e=h(t);await fr(e,{recursive:!0}),await hr(bt(e,"session.json"),`${JSON.stringify(t,null,2)}
|
|
10
|
+
`,"utf8")}import{spawn as _e}from"node:child_process";import{constants as vr}from"node:fs";import{access as wr,readdir as Ir}from"node:fs/promises";import{homedir as Pe}from"node:os";import{delimiter as xr,join as b}from"node:path";var Sr=/^[a-zA-Z0-9._-]+$/,Fe=new Map;async function S(t,e){let n=Rr(t,e),r=`${n.command}:${n.envVars.join(",")}:${n.extraCandidates.join(",")}`,s=[...br(n),...n.extraCandidates,...Er(n.command)],o=Fe.get(r);if(o&&(s.length===0||s.includes(o))&&await kt(o))return o;o&&Fe.delete(r);let i=[...s,await Cr(n.command),...await Ar(n.command),n.command].filter(Boolean);for(let a of Mr(i))if(await kt(a))return Fe.set(r,a),a;return null}function Le(t,e=[]){return new Promise(n=>{let r="",s="",o=!1,i=c=>{o||(o=!0,n(c))},a=_e(t,[...e,"--version"],{stdio:["ignore","pipe","pipe"]}),u=setTimeout(()=>{a.kill("SIGTERM"),i(null)},3e3);u.unref?.(),a.stdout.on("data",c=>{r+=c.toString()}),a.stderr.on("data",c=>{s+=c.toString()}),a.on("error",()=>{clearTimeout(u),i(null)}),a.on("exit",()=>{clearTimeout(u),i((r||s).trim().split(/\r?\n/)[0]||null)})})}function Rr(t,e){return typeof t!="string"?{command:t.command,envVars:t.envVars??[],extraCandidates:t.extraCandidates??[]}:{command:t,envVars:e?[e]:[],extraCandidates:[]}}function br(t){return[...t.envVars,...kr(t.command)].map(e=>process.env[e]?.trim()).filter(Boolean)}function kr(t){let e=t.toUpperCase().replace(/[^A-Z0-9]+/g,"_");return[`${e}_BIN`,`${e}_PATH`,`KSLOCK_${e}_BIN`,`KSLOCK_RUNTIME_${e}_BIN`]}async function Cr(t){if(!Sr.test(t))return null;let e=process.env.SHELL||"/bin/zsh";return new Promise(n=>{let r="",s=_e(e,["-lc",`command -v ${t}`],{stdio:["ignore","pipe","ignore"]});s.stdout.on("data",o=>{r+=o.toString()}),s.on("error",()=>n(null)),s.on("exit",o=>{let i=r.trim().split(/\r?\n/)[0];n(o===0&&i?i:null)})})}async function Ar(t){return[...await Dr(t),b(Pe(),".local","bin",t),b(Pe(),"bin",t),b("/opt/homebrew/bin",t),b("/usr/local/bin",t)]}function Er(t){return Tr(process.env.KSLOCK_RUNTIME_PATHS||process.env.KSLOCK_RUNTIME_PATH).map(e=>b(e,t))}function Tr(t){return(t??"").split(xr).map(e=>e.trim()).filter(Boolean)}async function Dr(t){let e=b(Pe(),".nvm","versions","node");try{return(await Ir(e)).sort((r,s)=>s.localeCompare(r)).map(r=>b(e,r,"bin",t))}catch{return[]}}async function kt(t){if(t.includes("/"))try{return await wr(t,vr.X_OK),!0}catch{return!1}return new Promise(e=>{let n=!1,r=i=>{n||(n=!0,e(i))},s=_e(t,["--version"],{stdio:"ignore"}),o=setTimeout(()=>{s.kill("SIGTERM"),r(!1)},3e3);o.unref?.(),s.on("error",()=>{clearTimeout(o),r(!1)}),s.on("exit",()=>{clearTimeout(o),r(!0)})})}function Mr(t){return[...new Set(t)]}import{Buffer as Ct}from"node:buffer";import{mkdir as Fr,writeFile as Pr}from"node:fs/promises";import{tmpdir as At}from"node:os";import{join as re}from"node:path";var je=16e3;async function v(t,e={}){return`${t.attachments.length===0?t.content:await _r(t,e)}
|
|
11
|
+
|
|
12
|
+
${St(t)}`}async function _r(t,e){let r=(await Promise.all(t.attachments.map(s=>Lr(t,s,e)))).map(jr).join(`
|
|
13
|
+
`);return`${t.content}
|
|
7
14
|
|
|
8
15
|
Attachments:
|
|
9
|
-
${
|
|
10
|
-
`).trim()}function Ge(e){return e.map(t=>t.trim()).filter(Boolean).at(-1)??""}import{mkdir as bn,readFile as Rn,writeFile as qe}from"node:fs/promises";import{join as An}from"node:path";var En="claude-last-message.txt";function Sn(e){return An(y(e),En)}async function Ve(e){await bn(y(e),{recursive:!0});let t=Sn(e);return await qe(t,"","utf8"),t}async function We(e,t){await qe(e,t,"utf8")}async function He(e){try{return await Rn(e,"utf8")}catch{return""}}var A=class{type="claude";capabilities={supportsSession:!0,supportsStreaming:!0,supportsExecutionPolicy:!0};async detect(){return!!await this.resolveCommand()}async handleDelivery(t,n){let r=await this.resolveCommand();if(!r)throw new Error("claude runtime is not available");let s=await h(t.agentId),o=s?.runtimeType===this.type?s.runtimeSessionId:null,i=o??Qe(),u=o?`resuming ${o}`:`starting new session ${i}`;n.onLog("system",`claude ${u} in ${n.cwd??process.cwd()}`);let a;try{a=await this.runClaude(r,t,n,i,!!o)}catch(l){if(!o)throw l;let c=Qe();n.onLog("stderr",`claude resume ${o} failed; starting a new session ${c}. ${l instanceof Error?l.message:""}`),a=await this.runClaude(r,t,n,c,!1)}return await w({agentId:t.agentId,runtimeType:this.type,runtimeSessionId:a.sessionId,workspacePath:n.cwd??null,updatedAt:new Date().toISOString()}),n.onLog("system",`claude session ${a.sessionId}`),{content:a.output.trim()||"claude runtime completed without output",sessionId:a.sessionId}}async runClaude(t,n,r,s,o){let i=x(n),u=oe(r.env),a=await Ve(n.agentId);r.onLog("system",u?`claude using model override ${u}`:"claude using configured model"),r.onLog("system",o?`claude resume ${s}`:`claude session-id ${s}`);let l=new Set,c=await Ue({command:t,args:se({frame:n,message:i,sessionId:s,resume:o,model:u}),cwd:r.cwd,env:r.env,signal:r.abortSignal,onPartial:r.onPartial,onJson:m=>{let p=ae(m);p&&l.add(p);let d=$e(m);d&&r.onLog("system",`[claude:event] ${d}`);let g=B(R(m));return g?(r.onLog("stderr",`[claude:error] ${g}`),g):null},onLog:r.onLog});return await We(a,c.output),{output:c.output||await He(a),sessionId:[...l].at(-1)??s}}async resolveCommand(){return v({command:"claude",envVars:["CLAUDE_BIN"]})}};import{mkdir as Tn,writeFile as jn}from"node:fs/promises";import{join as Nn}from"node:path";function K(e){return e.preset==="read_only"?"read-only":e.preset==="full_access"?"danger-full-access":"workspace-write"}function ce(e){let t=["-a","never","-s",K(e.frame.executionPolicy),"exec"];return e.sessionId?[...t,"resume","--json","--skip-git-repo-check",...Xe(e.model),"--output-last-message",e.outputFile,e.sessionId,e.prompt]:[...t,"--json","--skip-git-repo-check",...Xe(e.model),"--output-last-message",e.outputFile,e.prompt]}function de(e){return e.CODEX_MODEL?.trim()||null}function Xe(e){return e?["--model",e]:[]}var me="Codex \u8FD4\u56DE\u9519\u8BEF\uFF0C\u672A\u63D0\u4F9B\u8BE6\u7EC6\u539F\u56E0",kn=/The ['‘"]?([^'’"]+)['’"]? model requires a newer version of Codex\. Please upgrade to the latest app or CLI and try again\./i;function z(e){if(!e||typeof e!="object")return null;let t=e;for(let n of["type","event","event_name","method"])if(typeof t[n]=="string")return t[n];return null}function pe(e){if(!e||typeof e!="object")return null;let t=e;for(let n of["session_id","sessionId","thread_id","threadId","conversation_id","conversationId"])if(typeof t[n]=="string"&&t[n])return t[n];for(let n of Object.values(t)){let r=pe(n);if(r)return r}return null}function Ye(e){if(!e)return null;let t=Dn(e),r=(t?E(t):e)?.trim();return!r||J(r)?null:Fn(r)}function Ze(e){if(!e||typeof e!="object")return null;let t=z(e);return t!=="error"&&t!=="turn.failed"?null:me}function et(e){if(!e||typeof e!="object")return null;let t=e,n=z(e);if(n!=="error"&&n!=="turn.failed")return null;for(let s of["message","detail","reason"])if(typeof t[s]=="string"&&t[s]&&!J(t[s]))return t[s];let r=E(t.error);if(r)return r;for(let[s,o]of Object.entries(t)){if(["type","event","event_name","method","status","error"].includes(s))continue;let i=E(o);if(i)return i}return null}function ge(e,t){return!e||e===me&&t!==me?t:e}function E(e){if(typeof e=="string"&&e&&!J(e))return e;if(!e||typeof e!="object")return null;let t=e;for(let r of["message","detail","reason"])if(typeof t[r]=="string"&&t[r]&&!J(t[r]))return t[r];let n=E(t.error);if(n)return n;for(let r of Object.values(t)){let s=E(r);if(s)return s}return null}function J(e){let t=e.trim().toLowerCase();return t==="error"||t==="turn.failed"}function Fn(e){let t=e.match(kn);return t?`Codex CLI \u7248\u672C\u8FC7\u4F4E\uFF0C\u6682\u4E0D\u652F\u6301\u6A21\u578B ${t[1]??"\u5F53\u524D\u6A21\u578B"}\u3002\u8BF7\u5347\u7EA7 Codex CLI \u540E\u91CD\u542F daemon\uFF0C\u6216\u5C06 CODEX_MODEL \u8C03\u6574\u4E3A\u5F53\u524D CLI \u652F\u6301\u7684\u6A21\u578B\u540E\u91CD\u8BD5\u3002`:e}function Dn(e){try{return JSON.parse(e)}catch{return null}}import{spawn as On}from"node:child_process";var Ln="Reading additional input from stdin...";function rt(e){return new Promise((t,n)=>{let r=[],s="",o="",i="",u=On(e.command,e.args,{cwd:e.cwd||process.cwd(),env:e.env,stdio:["ignore","pipe","pipe"]});if(e.signal?.aborted){u.kill("SIGTERM"),n(new Error("runtime_cancelled"));return}e.signal?.addEventListener("abort",()=>{u.kill("SIGTERM"),n(new Error("runtime_cancelled"))},{once:!0}),u.stdout.on("data",a=>{o=tt(o+a.toString(),l=>{let c=nt(l);if(c){let m=e.onJson(c);m&&(s=ge(s,m));return}e.onLog("stdout",l)})}),u.stderr.on("data",a=>{i=tt(i+a.toString(),l=>{fe(l)||(r.push(l),e.onLog("stderr",l))})}),u.on("error",n),u.on("exit",a=>{if(o.trim()){let l=nt(o.trim());if(l){let c=e.onJson(l);c&&(s=ge(s,c))}else e.onLog("stdout",o.trim())}if(i.trim()&&!fe(i.trim())&&(r.push(i.trim()),e.onLog("stderr",i.trim())),e.onLog("system",`${e.command} exited with code ${a??"unknown"}`),a===0){t();return}n(new Error(s||Pn(r)||`${e.command} exited with code ${a}`))})})}function tt(e,t){let n=e.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&t(s);return r}function nt(e){try{return JSON.parse(e)}catch{return null}}function fe(e){return e.trim()===Ln}function Pn(e){return e.map(t=>t.trim()).filter(t=>t&&!fe(t)).at(-1)??""}import{readFile as _n}from"node:fs/promises";async function st(e){try{return await _n(e,"utf8")}catch{return""}}function ot(e){if(!e||typeof e!="object")return null;let t=e,n=Mn(e)??"";for(let s of["delta","text_delta","content_delta"])if(typeof t[s]=="string"&&t[s])return t[s];if(n.includes("delta")||n.includes("stream")){for(let s of["text","content","message"])if(typeof t[s]=="string"&&t[s])return t[s]}return it(t.delta??t.message??t.item)}function it(e){if(typeof e=="string"&&e)return e;if(!e||typeof e!="object")return null;let t=e;for(let n of["delta","text_delta","content_delta","text"])if(typeof t[n]=="string"&&t[n])return t[n];for(let n of Object.values(t)){let r=it(n);if(r)return r}return null}function Mn(e){if(!e||typeof e!="object")return null;let t=e;for(let n of["type","event","event_name","method"])if(typeof t[n]=="string")return t[n];return null}var S=class{type="codex";capabilities={supportsSession:!0,supportsStreaming:!0,supportsExecutionPolicy:!0};async detect(){return!!await this.resolveCommand()}async handleDelivery(t,n){let r=await this.resolveCommand();if(!r)throw new Error("codex runtime is not available");let s=await h(t.agentId),o=s?.runtimeType===this.type?s.runtimeSessionId:null,i=o?`resuming ${o}`:"starting new session";n.onLog("system",`codex ${i} in ${n.cwd??process.cwd()}`);let u;try{u=await this.runCodex(r,t,n,o)}catch(l){if(!o)throw l;n.onLog("stderr",`codex resume ${o} failed; starting a new session. ${l instanceof Error?l.message:""}`),u=await this.runCodex(r,t,n,null)}let a=u.sessionId??o??null;return await w({agentId:t.agentId,runtimeType:this.type,runtimeSessionId:a,workspacePath:n.cwd??null,updatedAt:new Date().toISOString()}),a?n.onLog("system",`codex session ${a}`):n.onLog("system","codex completed without exposing a resumable session id"),{content:u.output.trim()||"codex runtime completed without output",sessionId:a}}async runCodex(t,n,r,s){let o=y(n.agentId);await Tn(o,{recursive:!0});let i=Nn(o,"last-message.txt");await jn(i,"","utf8");let u=x(n),a=de(r.env);r.onLog("system",a?`codex using model override ${a}`:"codex using configured model"),r.onLog("system",`codex sandbox ${K(n.executionPolicy)}`);let l=new Set;return await rt({command:t,args:ce({frame:n,prompt:u,outputFile:i,model:a,sessionId:s}),cwd:r.cwd,env:r.env,signal:r.abortSignal,onJson:c=>{let m=ot(c);m&&r.onPartial?.(m);let p=pe(c);p&&l.add(p);let d=z(c);d&&r.onLog("system",`[codex:event] ${d}`);let g=Ye(et(c))??Ze(c);return g?(r.onLog("stderr",`[codex:error] ${g}`),g):null},onLog:r.onLog}),{output:await st(i),sessionId:[...l].at(-1)??null}}async resolveCommand(){return v({command:"codex",envVars:["CODEX_BIN","CODEX_CLI_PATH"]})}};import{randomUUID as xt}from"node:crypto";function at(e){return e.preset==="read_only"?["--permission-mode","dontAsk","--tools","Read,Grep,Glob,LS"]:e.preset==="full_access"?["--dangerously-skip-permissions"]:["--permission-mode","acceptEdits","--allowedTools",["Read","Grep","Glob","LS","Edit","MultiEdit","Write","Bash(git status *)","Bash(git diff *)","Bash(git log *)","Bash(git show *)","Bash(pnpm test *)","Bash(pnpm run test *)","Bash(pnpm typecheck *)","Bash(pnpm run typecheck *)","Bash(pnpm lint *)","Bash(pnpm run lint *)","Bash(pnpm build *)","Bash(pnpm run build *)","Bash(npm test *)","Bash(npm run test *)","Bash(npm run typecheck *)","Bash(npm run lint *)","Bash(npm run build *)","Bash(yarn test *)","Bash(yarn typecheck *)","Bash(yarn lint *)","Bash(yarn build *)","Bash(tsc *)","Bash(vitest *)"].join(","),"--disallowedTools",["Bash(rm *)","Bash(sudo *)","Bash(chmod *)","Bash(chown *)","Bash(curl *)","Bash(wget *)"].join(",")]}function ye(e){return["-p","--output-format","stream-json","--verbose","--include-partial-messages",...e.resume?["--resume",e.sessionId]:["--session-id",e.sessionId],...$n(e.model),...at(e.frame.executionPolicy),e.message]}function he(e){return e.KSCC_MODEL?.trim()||e.ANTHROPIC_MODEL?.trim()||null}function $n(e){return e?["--model",e]:[]}var G="kscc \u8FD4\u56DE\u9519\u8BEF\uFF0C\u672A\u63D0\u4F9B\u8BE6\u7EC6\u539F\u56E0";function lt(e){if(!e||typeof e!="object")return null;let t=e;for(let n of["type","subtype","event","event_name"])if(typeof t[n]=="string")return t[n];return null}function ve(e){if(!e||typeof e!="object")return null;let t=e;for(let n of["session_id","sessionId"])if(typeof t[n]=="string"&&Bn(t[n]))return t[n];for(let n of Object.values(t)){let r=ve(n);if(r)return r}return null}function xe(e){if(!e||typeof e!="object")return null;let t=e;if(typeof t.result=="string"&&t.result.trim())return t.result;if(typeof t.content=="string"&&t.content.trim())return t.content;let n=t.message;if(n&&typeof n=="object"){let r=ut(n.content);if(r)return r}return ut(t.content)}function U(e){if(!e)return null;let t=Kn(e),r=(t?k(t):e)?.trim();return!r||we(r)?null:r}function F(e){if(!e||typeof e!="object")return null;let t=e,n=typeof t.type=="string"?t.type:"",r=typeof t.subtype=="string"?t.subtype:"";return n==="error"||r==="error"||r==="failure"||t.is_error===!0||n==="result"&&r&&r!=="success"?k(e)??G:null}function Ie(e,t){return!e||e===G&&t!==G?t:e}function ut(e){if(typeof e=="string"&&e.trim())return e;if(!Array.isArray(e))return null;let t=e.map(n=>{if(!n||typeof n!="object")return"";let r=n;return typeof r.text=="string"?r.text:""}).filter(Boolean).join("");return t.trim()?t:null}function k(e){if(typeof e=="string"&&e&&!we(e))return e;if(!e||typeof e!="object")return null;let t=e;for(let r of["message","detail","reason","error"]){let s=t[r];if(typeof s=="string"&&s&&!we(s))return s}let n=k(t.error);if(n)return n;for(let r of Object.values(t)){let s=k(r);if(s)return s}return null}function Bn(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}function we(e){let t=e.trim().toLowerCase();return t==="error"||t==="failure"}function Kn(e){try{return JSON.parse(e)}catch{return null}}import{spawn as Jn}from"node:child_process";function ft(e){return new Promise((t,n)=>{let r=[],s=[],o="",i=[],u="",a="",l="",c=Jn(e.command,e.args,{cwd:e.cwd||process.cwd(),env:e.env,stdio:["ignore","pipe","pipe"]});if(e.signal?.aborted){c.kill("SIGTERM"),n(new Error("runtime_cancelled"));return}e.signal?.addEventListener("abort",()=>{c.kill("SIGTERM"),n(new Error("runtime_cancelled"))},{once:!0}),c.stdout.on("data",m=>{a=ct(a+m.toString(),p=>{let d=dt(p);if(d){let g=e.onJson(d)??F(d);g&&(u=Ie(u,g));let f=xe(d);f&&(mt(d)?s.push(f):o=pt(f,o,e.onPartial));return}r.push(p),e.onLog("stdout",p)})}),c.stderr.on("data",m=>{l=ct(l+m.toString(),p=>{i.push(p),e.onLog("stderr",p)})}),c.on("error",n),c.on("exit",m=>{if(a.trim()){let d=dt(a.trim());if(d){let g=e.onJson(d)??F(d);g&&(u=Ie(u,g));let f=xe(d);f&&(mt(d)?s.push(f):o=pt(f,o,e.onPartial))}else r.push(a.trim()),e.onLog("stdout",a.trim())}if(l.trim()&&(i.push(l.trim()),e.onLog("stderr",l.trim())),e.onLog("system",`${e.command} exited with code ${m??"unknown"}`),m===0){t({output:zn(s,o,r)});return}let p=U(gt(i))??gt(i);n(new Error(u||p||`${e.command} exited with code ${m}`))})})}function ct(e,t){let n=e.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&t(s);return r}function dt(e){try{return JSON.parse(e)}catch{return null}}function mt(e){return!!(e&&typeof e=="object"&&e.type==="result")}function pt(e,t,n){let r=e.startsWith(t)?e:`${t}${e}`,s=r.slice(t.length);return s&&n?.(s,r),r}function zn(e,t,n){let r=e.at(-1)?.trim();if(r)return r;let s=t.trim();return s||n.join(`
|
|
11
|
-
`).
|
|
12
|
-
|
|
16
|
+
${r}`}async function Lr(t,e,n){let r=e.downloadUrl??e.previewUrl,s=$r(r);if(!s)return{filename:e.filename,contentType:e.contentType,size:e.size,localPath:null,textPreview:null,sourceUrl:r&&!r.startsWith("data:")?r:null,warning:r?"attachment content is not embedded in the daemon frame":null};let o=null,i=null;try{o=await Or(t,e.id,e.filename,s.buffer,n.workspacePath)}catch(a){i=a instanceof Error?`failed to write local attachment file: ${a.message}`:"failed to write local attachment file"}return{filename:e.filename,contentType:e.contentType||s.contentType,size:e.size,localPath:o,textPreview:Nr(s.contentType||e.contentType,e.filename)?Kr(s.buffer.toString("utf8")):null,sourceUrl:null,warning:i}}function jr(t){let e=[`- ${t.filename} (${t.contentType}, ${t.size} bytes)`];return t.localPath&&e.push(` Local path: ${t.localPath}`),t.sourceUrl&&e.push(` Source URL: ${t.sourceUrl}`),t.textPreview?(e.push(" Text preview:"),e.push(Br(t.textPreview))):t.contentType.startsWith("image/")&&t.localPath&&e.push(" Image attachment saved as a local file. Inspect the local path when image/file tools are available."),t.warning&&e.push(` Warning: ${t.warning}`),e.join(`
|
|
17
|
+
`)}async function Or(t,e,n,r,s){let o=`${Et(e,"attachment")}-${Et(n,"file")}`;if(s)try{return await Oe(re(s,".kslock","attachments",t.deliveryId),o,r)}catch{return Oe(re(At(),"kslock-daemon","attachments",t.deliveryId),o,r)}return Oe(re(At(),"kslock-daemon","attachments",t.deliveryId),o,r)}async function Oe(t,e,n){await Fr(t,{recursive:!0});let r=re(t,e);return await Pr(r,n),r}function $r(t){if(!t?.startsWith("data:"))return null;let e=t.indexOf(",");if(e<0)return null;let n=t.slice(5,e),r=t.slice(e+1),s=n.split(";").filter(Boolean),o=s[0]||"application/octet-stream",i=s.includes("base64");try{return{buffer:i?Ct.from(r.replace(/\s/g,""),"base64"):Ct.from(decodeURIComponent(r)),contentType:o}}catch{return null}}function Nr(t,e){let n=t.toLowerCase();return n.startsWith("text/")||["application/json","application/ld+json","application/xml","application/javascript","application/x-javascript","application/yaml","application/x-yaml"].includes(n)?!0:/\.(csv|env|html?|js|json|log|md|markdown|sql|styl|svg|ts|tsx|txt|vue|xml|ya?ml)$/i.test(e)}function Kr(t){let e=t.replace(/\r\n/g,`
|
|
18
|
+
`).replace(/\u0000/g,"");return e.length<=je?e:`${e.slice(0,je)}
|
|
19
|
+
...[truncated ${e.length-je} chars]`}function Br(t){return t.split(`
|
|
20
|
+
`).map(e=>` ${e}`).join(`
|
|
21
|
+
`)}function Et(t,e){return t.trim().replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").replace(/^\.+$/,"").slice(0,160)||e}import{spawn as Jr}from"node:child_process";var zr=5e3,Tt=8*1024*1024;async function Mt(t){let e=await $e(t,["debug","models"]);return e.code!==0?[]:qr(e.stdout)}async function Ft(t){let e=await $e(t,["models"]);return e.code!==0?[]:Pt(e.stdout)}async function se(t){let e=await $e(t,["models"]);return e.code!==0?[]:Pt(e.stdout)}function qr(t){let e=t.indexOf("{");if(e<0)return[];try{let n=JSON.parse(t.slice(e));return Array.isArray(n.models)?_t(n.models.flatMap(r=>{if(!r||typeof r!="object")return[];let s=r;return s.visibility&&s.visibility!=="list"?[]:typeof s.slug!="string"||!s.slug.trim()?[]:[{id:s.slug.trim(),label:typeof s.display_name=="string"&&s.display_name.trim()?s.display_name.trim():s.slug.trim()}]})):[]}catch{return[]}}function Pt(t){return _t(t.split(/\r?\n/).map(e=>e.trim()).flatMap(e=>{if(!e||/^[\s#=-]+$/.test(e))return[];let r=e.match(/[a-z0-9][a-z0-9_.-]+\/[a-z0-9][a-z0-9_.:-]+/i)?.[0]??e.match(/^[a-z0-9][a-z0-9_.:-]+/i)?.[0]??"";return!r||["id","model","models","provider"].includes(r.toLowerCase())?[]:[{id:r,label:r}]}))}function $e(t,e){return new Promise(n=>{let r="",s="",o=!1,i=null,a=Jr(t,e,{stdio:["ignore","pipe","pipe"]}),u=c=>{o||(o=!0,i&&clearTimeout(i),n(c))};i=setTimeout(()=>{a.kill("SIGTERM"),u({stdout:r,stderr:s,code:null})},zr),i.unref?.(),a.stdout.on("data",c=>{r=Dt(r,c.toString())}),a.stderr.on("data",c=>{s=Dt(s,c.toString())}),a.on("error",()=>u({stdout:r,stderr:s,code:null})),a.on("exit",c=>u({stdout:r,stderr:s,code:c}))})}function Dt(t,e){return t.length>=Tt?t:(t+e).slice(0,Tt)}function _t(t){let e=new Map;for(let n of t)n.id&&e.set(n.id,n);return[...e.values()]}function w(t,e){return t.runtimeModel?.trim()||e}import{spawn as Ur}from"node:child_process";function oe(t){try{return JSON.parse(t)}catch{return null}}var A=class{constructor(e){this.spec=e}states=new Map;runTurn(e){return new Promise((n,r)=>{let s={frame:e.frame,context:e.context,prompt:e.prompt,resolve:n,reject:r,output:"",snapshot:"",injected:!1,abort:()=>{}};if(s.abort=()=>{this.removeTurn(e.frame,s),r(new Error("runtime_cancelled"))},e.context.abortSignal?.aborted){s.abort();return}e.context.abortSignal?.addEventListener("abort",s.abort,{once:!0});try{let o=this.ensureState(e);if(o.current){s.injected=!0,o.injected.push(s),s.context.onLog("system",`${this.spec.displayName} busy stdin delivery`),o.child.stdin.write(this.encodeUserMessage(s.prompt,o.sessionId)+`
|
|
22
|
+
`);return}o.queue.push(s),this.pump(o)}catch(o){r(o instanceof Error?o:new Error(String(o)))}})}dispose(e){let n=g(e),r=this.states.get(n);r&&(r.closed=!0,this.clearIdleTimer(r),r.child.kill("SIGTERM"),this.states.delete(n))}notify(e,n){let r=this.states.get(g(e));return!r||r.closed||!r.current?!1:(r.child.stdin.write(this.encodeUserMessage(n,r.sessionId)+`
|
|
23
|
+
`),!0)}ensureState(e){let n=e.context.cwd||process.cwd(),r=g(e.frame),s=this.states.get(r);if(s&&!s.closed&&s.command===e.command&&s.cwd===n)return this.clearIdleTimer(s),s;s&&this.dispose(e.frame);let o=w(e.frame,this.spec.resolveModel(e.context.env));e.context.onLog("system",o?`${this.spec.displayName} using model override ${o}`:`${this.spec.displayName} using configured model`);let i=Ur(e.command,this.spec.buildArgs({frame:e.frame,sessionId:e.sessionId,resume:e.resume,model:o}),{cwd:n,env:e.context.env,stdio:["pipe","pipe","pipe"]}),a={agentId:e.frame.agentId,scopeKey:r,command:e.command,cwd:n,env:e.context.env,child:i,stdoutBuffer:"",stderrBuffer:"",sessionId:e.sessionId,current:null,injected:[],queue:[],idleTimer:null,closed:!1};return this.states.set(r,a),this.bindProcess(a),a}bindProcess(e){e.child.stdout.on("data",n=>{e.stdoutBuffer=Lt(e.stdoutBuffer+n.toString(),r=>{this.handleLine(e,r)})}),e.child.stderr.on("data",n=>{e.stderrBuffer=Lt(e.stderrBuffer+n.toString(),r=>{e.current?.context.onLog("stderr",r)})}),e.child.on("error",n=>{this.rejectState(e,n instanceof Error?n:new Error(String(n)))}),e.child.on("close",n=>{e.closed=!0,this.states.delete(e.scopeKey),(e.current||e.queue.length>0)&&this.rejectState(e,new Error(`${this.spec.displayName} process exited with code ${n??"unknown"}`))})}handleLine(e,n){let r=oe(n);if(!r){e.current?.context.onLog("stdout",n);return}let s=this.spec.extractSessionId(r);s&&(e.sessionId=s);let o=this.spec.extractEventName(r);o&&e.current?.context.onLog("system",`[${this.spec.type}:event] ${o}`);let i=this.spec.normalizeError(this.spec.summarizeError(r));if(i){this.finishCurrent(e,new Error(i));return}let a=this.spec.extractText(r);if(a&&e.current){let u=e.current;if(jt(r))u.output.trim()||(u.output=a);else{let c=a.startsWith(u.snapshot)?a:`${u.snapshot}${a}`,l=c.slice(u.snapshot.length);u.snapshot=c,u.output=c,l&&u.context.onPartial?.(l,c)}}jt(r)&&this.finishCurrent(e)}pump(e){if(e.closed||e.current)return;let n=e.queue.shift();if(!n){this.scheduleIdleDispose(e);return}this.clearIdleTimer(e),e.current=n,n.context.onLog("system",`${this.spec.displayName} session ${e.sessionId}`),e.child.stdin.write(this.encodeUserMessage(n.prompt,e.sessionId)+`
|
|
24
|
+
`)}finishCurrent(e,n){let r=e.current;if(!r)return;let s=e.injected.splice(0);if(e.current=null,n){this.rejectTurn(r,n);for(let o of s)this.rejectTurn(o,n);for(let o of e.queue.splice(0))this.rejectTurn(o,n);e.closed=!0,e.child.kill("SIGTERM"),this.states.delete(e.scopeKey)}else{this.resolveTurn(r,e.sessionId);for(let o of s)this.resolveTurn(o,e.sessionId);this.pump(e)}}resolveTurn(e,n){this.cleanupTurn(e);let r=e.output.trim();e.resolve({content:r,sessionId:n,suppressMessage:e.injected&&!r})}rejectTurn(e,n){this.cleanupTurn(e),e.reject(n)}cleanupTurn(e){e.context.abortSignal?.removeEventListener("abort",e.abort)}removeTurn(e,n){let r=g(e),s=this.states.get(r);s&&(s.queue=s.queue.filter(o=>o!==n),s.injected=s.injected.filter(o=>o!==n),s.current===n&&(s.current=null,this.clearIdleTimer(s),s.child.kill("SIGTERM"),this.states.delete(r)))}rejectState(e,n){let r=e.current;e.current=null,this.clearIdleTimer(e),r&&this.rejectTurn(r,n);for(let s of e.injected.splice(0))this.rejectTurn(s,n);for(let s of e.queue.splice(0))this.rejectTurn(s,n);this.states.delete(e.scopeKey)}scheduleIdleDispose(e){if(e.closed||e.current||e.queue.length>0||e.idleTimer)return;let n=Gr();n<=0||(e.idleTimer=setTimeout(()=>{e.closed||e.current||e.queue.length>0||(e.closed=!0,e.child.kill("SIGTERM"),this.states.delete(e.scopeKey))},n),e.idleTimer.unref?.())}clearIdleTimer(e){e.idleTimer&&(clearTimeout(e.idleTimer),e.idleTimer=null)}encodeUserMessage(e,n){return JSON.stringify({type:"user",message:{role:"user",content:[{type:"text",text:e}]},session_id:n})}};function Lt(t,e){let n=t.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&e(s);return r}function jt(t){return!!(t&&typeof t=="object"&&t.type==="result")}function Gr(){let t=process.env.KSLOCK_RUNTIME_IDLE_TTL_MS;if(!t)return 1800*1e3;let e=Number(t);return!Number.isFinite(e)||e<0?1800*1e3:e}function Ne(t){return t.preset==="read_only"?["--permission-mode","dontAsk","--tools","Read,Grep,Glob,LS"]:t.preset==="full_access"?["--dangerously-skip-permissions"]:["--permission-mode","acceptEdits","--allowedTools",["Read","Grep","Glob","LS","Edit","MultiEdit","Write","Bash(git status *)","Bash(git diff *)","Bash(git log *)","Bash(git show *)","Bash(pnpm test *)","Bash(pnpm run test *)","Bash(pnpm typecheck *)","Bash(pnpm run typecheck *)","Bash(pnpm lint *)","Bash(pnpm run lint *)","Bash(pnpm build *)","Bash(pnpm run build *)","Bash(npm test *)","Bash(npm run test *)","Bash(npm run typecheck *)","Bash(npm run lint *)","Bash(npm run build *)","Bash(yarn test *)","Bash(yarn typecheck *)","Bash(yarn lint *)","Bash(yarn build *)","Bash(tsc *)","Bash(vitest *)"].join(","),"--disallowedTools",["Bash(rm *)","Bash(sudo *)","Bash(chmod *)","Bash(chown *)","Bash(curl *)","Bash(wget *)"].join(",")]}function Ke(t){return["-p","--output-format","stream-json","--verbose","--include-partial-messages",...t.resume?["--resume",t.sessionId]:["--session-id",t.sessionId],...Ot(t.model),...Ne(t.frame.executionPolicy),t.message]}function Be(t){return["--output-format","stream-json","--input-format","stream-json","--verbose","--include-partial-messages",...t.resume?["--resume",t.sessionId]:["--session-id",t.sessionId],...Ot(t.model),...Ne(t.frame.executionPolicy)]}function ie(t){return t.CLAUDE_MODEL?.trim()||t.ANTHROPIC_MODEL?.trim()||null}function Ot(t){return t?["--model",t]:[]}var ae="Claude \u8FD4\u56DE\u9519\u8BEF\uFF0C\u672A\u63D0\u4F9B\u8BE6\u7EC6\u539F\u56E0";function ze(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["type","subtype","event","event_name"])if(typeof e[n]=="string")return e[n];return null}function ue(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["session_id","sessionId"])if(typeof e[n]=="string"&&Wr(e[n]))return e[n];for(let n of Object.values(e)){let r=ue(n);if(r)return r}return null}function P(t){if(!t||typeof t!="object")return null;let e=t;if(typeof e.result=="string"&&e.result.trim())return e.result;if(typeof e.content=="string"&&e.content.trim())return e.content;let n=e.message;if(n&&typeof n=="object"){let r=$t(n.content);if(r)return r}return $t(e.content)}function _(t){if(!t)return null;let e=Vr(t),r=(e?F(e):t)?.trim();return!r||Je(r)?null:r}function E(t){if(!t||typeof t!="object")return null;let e=t,n=typeof e.type=="string"?e.type:"",r=typeof e.subtype=="string"?e.subtype:"";return n==="error"||r==="error"||r==="failure"||e.is_error===!0||n==="result"&&r&&r!=="success"?F(t)??ae:null}function L(t,e){return!t||t===ae&&e!==ae?e:t}function $t(t){if(typeof t=="string"&&t.trim())return t;if(!Array.isArray(t))return null;let e=t.map(n=>{if(!n||typeof n!="object")return"";let r=n;return typeof r.text=="string"?r.text:""}).filter(Boolean).join("");return e.trim()?e:null}function F(t){if(typeof t=="string"&&t&&!Je(t))return t;if(!t||typeof t!="object")return null;let e=t;for(let r of["message","detail","reason","error"]){let s=e[r];if(typeof s=="string"&&s&&!Je(s))return s}let n=F(e.error);if(n)return n;for(let r of Object.values(e)){let s=F(r);if(s)return s}return null}function Wr(t){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t)}function Je(t){let e=t.trim().toLowerCase();return e==="error"||e==="failure"}function Vr(t){try{return JSON.parse(t)}catch{return null}}import{spawn as Hr}from"node:child_process";function qt(t){return new Promise((e,n)=>{let r=[],s=[],o="",i=[],a="",u="",c="",l=Hr(t.command,t.args,{cwd:t.cwd||process.cwd(),env:t.env,stdio:["ignore","pipe","pipe"]});if(t.signal?.aborted){l.kill("SIGTERM"),n(new Error("runtime_cancelled"));return}t.signal?.addEventListener("abort",()=>{l.kill("SIGTERM"),n(new Error("runtime_cancelled"))},{once:!0}),l.stdout.on("data",d=>{u=Nt(u+d.toString(),p=>{let m=Kt(p);if(m){let f=t.onJson(m)??E(m);f&&(a=L(a,f));let y=P(m);y&&(Bt(m)?s.push(y):o=Jt(y,o,t.onPartial));return}r.push(p),t.onLog("stdout",p)})}),l.stderr.on("data",d=>{c=Nt(c+d.toString(),p=>{i.push(p),t.onLog("stderr",p)})}),l.on("error",n),l.on("exit",d=>{if(u.trim()){let m=Kt(u.trim());if(m){let f=t.onJson(m)??E(m);f&&(a=L(a,f));let y=P(m);y&&(Bt(m)?s.push(y):o=Jt(y,o,t.onPartial))}else r.push(u.trim()),t.onLog("stdout",u.trim())}if(c.trim()&&(i.push(c.trim()),t.onLog("stderr",c.trim())),t.onLog("system",`${t.command} exited with code ${d??"unknown"}`),d===0){e({output:Qr(s,o,r)});return}let p=_(zt(i))??zt(i);n(new Error(a||p||`${t.command} exited with code ${d}`))})})}function Nt(t,e){let n=t.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&e(s);return r}function Kt(t){try{return JSON.parse(t)}catch{return null}}function Bt(t){return!!(t&&typeof t=="object"&&t.type==="result")}function Jt(t,e,n){let r=t.startsWith(e)?t:`${e}${t}`,s=r.slice(e.length);return s&&n?.(s,r),r}function Qr(t,e,n){let r=t.at(-1)?.trim();if(r)return r;let s=e.trim();return s||n.join(`
|
|
25
|
+
`).trim()}function zt(t){return t.map(e=>e.trim()).filter(Boolean).at(-1)??""}import{mkdir as Xr,readFile as Yr,writeFile as Ut}from"node:fs/promises";import{join as Zr}from"node:path";var es="claude-last-message.txt";function ts(t){return Zr(h(t),es)}async function Gt(t){await Xr(h(t),{recursive:!0});let e=ts(t);return await Ut(e,"","utf8"),e}async function Wt(t,e){await Ut(t,e,"utf8")}async function Vt(t){try{return await Yr(t,"utf8")}catch{return""}}var j=class{type="claude";busyDeliveryMode="gated";sessions=new A({type:"claude",displayName:"claude",buildArgs:Be,resolveModel:ie,extractSessionId:ue,extractText:P,extractEventName:ze,summarizeError:E,normalizeError:_,preferFailure:L});capabilities={supportsSession:!0,supportsStreaming:!0,supportsExecutionPolicy:!0};async detect(){return!!await this.resolveCommand()}notifyInbox(e,n){return this.sessions.notify(e,n)}async listModels(){let e=await this.resolveCommand();return e?se(e):[]}async handleDelivery(e,n){let r=await this.resolveCommand();if(!r)throw new Error("claude runtime is not available");let s=await I(e),o=s?.runtimeType===this.type?s.runtimeSessionId:null,i=o??Ht(),a=o?`resuming ${o}`:`starting new session ${i}`;n.onLog("system",`claude ${a} in ${n.cwd??process.cwd()}`);let u;try{u=await this.runClaudeStream(r,e,n,i,!!o)}catch(c){if(Qt(c))n.onLog("stderr",`claude stream-json session failed; falling back to print mode. ${c instanceof Error?c.message:""}`),u=await this.runClaude(r,e,n,i,!!o);else if(o){let l=Ht();n.onLog("stderr",`claude resume ${o} failed; starting a new session ${l}. ${c instanceof Error?c.message:""}`),u=await this.runClaudeStream(r,e,n,l,!1).catch(d=>{if(!Qt(d))throw d;return n.onLog("stderr",`claude stream retry failed; falling back to print mode. ${d instanceof Error?d.message:""}`),this.runClaude(r,e,n,l,!1)})}else throw c}return await x({agentId:e.agentId,channelId:e.channelId,runtimeScopeKey:g(e),runtimeType:this.type,runtimeSessionId:u.sessionId,workspacePath:n.cwd??null,updatedAt:new Date().toISOString()}),n.onLog("system",`claude session ${u.sessionId}`),u.suppressMessage?{content:u.output.trim(),sessionId:u.sessionId,suppressMessage:!0}:{content:u.output.trim()||"claude runtime completed without output",sessionId:u.sessionId}}async runClaudeStream(e,n,r,s,o){r.onLog("system",o?`claude stream resume ${s}`:`claude stream session-id ${s}`);let i=await this.sessions.runTurn({command:e,frame:n,context:r,prompt:await v(n,{workspacePath:r.cwd}),sessionId:s,resume:o});return{output:i.content,sessionId:i.sessionId??s,suppressMessage:i.suppressMessage}}async runClaude(e,n,r,s,o){let i=await v(n,{workspacePath:r.cwd}),a=w(n,ie(r.env)),u=await Gt(n);r.onLog("system",a?`claude using model override ${a}`:"claude using configured model"),r.onLog("system",o?`claude resume ${s}`:`claude session-id ${s}`);let c=new Set,l=await qt({command:e,args:Ke({frame:n,message:i,sessionId:s,resume:o,model:a}),cwd:r.cwd,env:r.env,signal:r.abortSignal,onPartial:r.onPartial,onJson:d=>{let p=ue(d);p&&c.add(p);let m=ze(d);m&&r.onLog("system",`[claude:event] ${m}`);let f=_(E(d));return f?(r.onLog("stderr",`[claude:error] ${f}`),f):null},onLog:r.onLog});return await Wt(u,l.output),{output:l.output||await Vt(u),sessionId:[...c].at(-1)??s}}async resolveCommand(){return S({command:"claude",envVars:["CLAUDE_BIN"]})}};function Qt(t){if(process.env.KSLOCK_CLAUDE_DISABLE_PRINT_FALLBACK==="1")return!1;let e=t instanceof Error?t.message:String(t);return/process exited|unknown option|unrecognized|input-format|stream-json|stdin|not supported/i.test(e)}import{mkdir as ps,writeFile as gs}from"node:fs/promises";import{join as fs}from"node:path";function k(t){return t.preset==="read_only"?"read-only":t.preset==="full_access"?"danger-full-access":"workspace-write"}function qe(t){let e=["-a","never","-s",k(t.frame.executionPolicy),"exec"];return t.sessionId?[...e,"resume","--json","--skip-git-repo-check",...Xt(t.model),"--output-last-message",t.outputFile,t.sessionId,t.prompt]:[...e,"--json","--skip-git-repo-check",...Xt(t.model),"--output-last-message",t.outputFile,t.prompt]}function ce(t){return t.CODEX_MODEL?.trim()||null}function Xt(t){return t?["--model",t]:[]}var Ue="Codex \u8FD4\u56DE\u9519\u8BEF\uFF0C\u672A\u63D0\u4F9B\u8BE6\u7EC6\u539F\u56E0",ns=/The ['‘"]?([^'’"]+)['’"]? model requires a newer version of Codex\. Please upgrade to the latest app or CLI and try again\./i;function de(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["type","event","event_name","method"])if(typeof e[n]=="string")return e[n];return null}function Ge(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["session_id","sessionId","thread_id","threadId","conversation_id","conversationId"])if(typeof e[n]=="string"&&e[n])return e[n];for(let n of Object.values(e)){let r=Ge(n);if(r)return r}return null}function $(t){if(!t)return null;let e=ss(t),r=(e?O(e):t)?.trim();return!r||le(r)?null:rs(r)}function me(t){if(!t||typeof t!="object")return null;let e=de(t);return e!=="error"&&e!=="turn.failed"?null:Ue}function T(t){if(!t||typeof t!="object")return null;let e=t,n=de(t);if(n!=="error"&&n!=="turn.failed")return null;for(let s of["message","detail","reason"])if(typeof e[s]=="string"&&e[s]&&!le(e[s]))return e[s];let r=O(e.error);if(r)return r;for(let[s,o]of Object.entries(e)){if(["type","event","event_name","method","status","error"].includes(s))continue;let i=O(o);if(i)return i}return null}function We(t,e){return!t||t===Ue&&e!==Ue?e:t}function O(t){if(typeof t=="string"&&t&&!le(t))return t;if(!t||typeof t!="object")return null;let e=t;for(let r of["message","detail","reason"])if(typeof e[r]=="string"&&e[r]&&!le(e[r]))return e[r];let n=O(e.error);if(n)return n;for(let r of Object.values(e)){let s=O(r);if(s)return s}return null}function le(t){let e=t.trim().toLowerCase();return e==="error"||e==="turn.failed"}function rs(t){let e=t.match(ns);return e?`Codex CLI \u7248\u672C\u8FC7\u4F4E\uFF0C\u6682\u4E0D\u652F\u6301\u6A21\u578B ${e[1]??"\u5F53\u524D\u6A21\u578B"}\u3002\u8BF7\u5347\u7EA7 Codex CLI \u540E\u91CD\u542F daemon\uFF0C\u6216\u5C06 CODEX_MODEL \u8C03\u6574\u4E3A\u5F53\u524D CLI \u652F\u6301\u7684\u6A21\u578B\u540E\u91CD\u8BD5\u3002`:t}function ss(t){try{return JSON.parse(t)}catch{return null}}import{spawn as os}from"node:child_process";var pe=class{states=new Map;async runTurn(e){return new Promise((n,r)=>{let s={frame:e.frame,context:e.context,prompt:e.prompt,resolve:n,reject:r,output:"",streamedAgentMessageIds:new Set,streamedReasoningIds:new Set,injected:!1,steerSent:!1,abort:()=>{}};if(s.abort=()=>{this.removeTurn(e.frame,s),r(new Error("runtime_cancelled"))},e.context.abortSignal?.aborted){s.abort();return}e.context.abortSignal?.addEventListener("abort",s.abort,{once:!0});try{let o=this.ensureState(e);if(o.current||o.queue.length>0){s.injected=!0,o.injected.push(s),s.context.onLog("system","codex steering active turn"),this.flushInjectedSteers(o);return}o.queue.push(s),this.pump(o)}catch(o){r(o instanceof Error?o:new Error(String(o)))}})}dispose(e){let n=g(e),r=this.states.get(n);r&&(r.closed=!0,this.clearIdleTimer(r),r.child.kill("SIGTERM"),this.states.delete(n))}notify(e,n){let r=this.states.get(g(e));return!r||r.closed||!r.current&&r.queue.length===0?!1:(r.pendingNotifications.push(n),this.flushPendingNotifications(r),!0)}ensureState(e){let n=g(e.frame),r=e.context.cwd||process.cwd(),s=this.states.get(n);if(s&&!s.closed&&s.command===e.command&&s.cwd===r)return this.clearIdleTimer(s),s;s&&this.dispose(e.frame);let o=os(e.command,["app-server","--listen","stdio://"],{cwd:r,env:e.context.env,stdio:["pipe","pipe","pipe"]}),i={agentId:e.frame.agentId,scopeKey:n,command:e.command,cwd:r,env:e.context.env,child:o,stdoutBuffer:"",stderrBuffer:"",requestId:0,initializeRequestId:null,pendingThreadRequest:this.buildThreadRequest(e.frame,e.sessionId,e.model,r),threadId:null,activeTurnId:null,sessionAnnounced:!1,current:null,injected:[],pendingNotifications:[],queue:[],idleTimer:null,closed:!1};return this.states.set(n,i),this.bindProcess(n,i),i.initializeRequestId=this.sendRequest(i,"initialize",{clientInfo:{name:"kslock-daemon",version:"1.0.0"},capabilities:{experimentalApi:!0}}),i}buildThreadRequest(e,n,r,s){let o={cwd:s,approvalPolicy:"never",sandbox:k(e.executionPolicy),developerInstructions:[`You are @${e.agentHandle} in kslock channel ${e.channelId}.`,"Reply with the final answer for the delivered message."].join(`
|
|
26
|
+
`)};return r&&(o.model=r),n?{method:"thread/resume",params:{threadId:n,...o}}:{method:"thread/start",params:o}}bindProcess(e,n){n.child.stdout.on("data",r=>{n.stdoutBuffer=Yt(n.stdoutBuffer+r.toString(),s=>{for(let o of this.parseLine(n,s))this.handleEvent(n,o)})}),n.child.stderr.on("data",r=>{n.stderrBuffer=Yt(n.stderrBuffer+r.toString(),s=>{n.current?.context.onLog("stderr",s)})}),n.child.on("error",r=>{this.rejectState(e,n,r instanceof Error?r:new Error(String(r)))}),n.child.on("close",r=>{n.closed=!0,this.states.delete(e);let s=new Error(`codex app-server exited with code ${r??"unknown"}`);(n.current||n.queue.length>0)&&this.rejectState(e,n,s)})}parseLine(e,n){let r=oe(n);if(!r||typeof r!="object")return[];let s=r,o=[];if(s.result&&typeof s.result=="object"){if(s.id===e.initializeRequestId)return e.initializeRequestId=null,this.sendNotification(e,"initialized",{}),e.pendingThreadRequest&&(this.sendRequest(e,e.pendingThreadRequest.method,e.pendingThreadRequest.params),e.pendingThreadRequest=null),o;let i=s.result,a=i.thread;if(a&&typeof a=="object"&&typeof a.id=="string")return this.handleThreadReady(e,String(a.id),o),o;let u=i.turn;if(u&&typeof u=="object"&&typeof u.id=="string")return e.activeTurnId=String(u.id),this.flushInjectedSteers(e),this.flushPendingNotifications(e),o;if(typeof i.turnId=="string")return e.activeTurnId=i.turnId,this.flushInjectedSteers(e),this.flushPendingNotifications(e),o}if(s.error){let i=$(T(s.error))??T(s.error);return o.push({kind:"error",message:i||"Codex app-server request failed"}),o}switch(s.method){case"thread/started":{let i=s.params,a=i&&typeof i=="object"?i.thread:null,u=a&&typeof a=="object"?a.id:null;typeof u=="string"&&this.handleThreadReady(e,u,o);break}case"turn/started":{let i=s.params,a=i&&typeof i=="object"?i.turn:null,u=a&&typeof a=="object"?a.id:null;typeof u=="string"&&(e.activeTurnId=u,this.flushInjectedSteers(e),this.flushPendingNotifications(e)),o.push({kind:"thinking",text:""});break}case"item/agentMessage/delta":{let i=s.params,a=i?.delta,u=i?.itemId;typeof u=="string"&&e.current?.streamedAgentMessageIds.add(u),typeof a=="string"&&a.length>0&&o.push({kind:"text",text:a});break}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{let i=s.params,a=i?.delta,u=i?.itemId;typeof u=="string"&&e.current?.streamedReasoningIds.add(u),typeof a=="string"&&a.length>0&&o.push({kind:"thinking",text:a});break}case"item/started":case"item/completed":o.push(...this.parseItemEvent(e,s));break;case"turn/completed":{let a=s.params?.turn,u=a?.error;if(a?.status==="failed"&&u&&typeof u=="object"){let c=u.message;o.push({kind:"error",message:typeof c=="string"?c:"Codex turn failed"})}e.activeTurnId=null,o.push({kind:"turn_end",sessionId:e.threadId});break}case"error":{let i=$(T(s.params))??me(s);o.push({kind:"error",message:i||"Unknown Codex app-server error"});break}}return o}parseItemEvent(e,n){let r=[],o=n.params?.item;if(!o||typeof o.type!="string")return r;let i=n.method==="item/started",a=n.method==="item/completed";switch(o.type){case"reasoning":if(a&&typeof o.id=="string"&&!e.current?.streamedReasoningIds.has(o.id)){let u=is(o);u&&r.push({kind:"thinking",text:u})}break;case"agentMessage":a&&typeof o.id=="string"&&!e.current?.streamedAgentMessageIds.has(o.id)&&typeof o.text=="string"&&o.text&&r.push({kind:"text",text:o.text});break;case"commandExecution":i&&typeof o.command=="string"&&r.push({kind:"tool_call",name:"shell",input:{command:o.command}}),a&&r.push({kind:"tool_output",name:"shell"});break;case"contextCompaction":i&&r.push({kind:"compaction_started"}),a&&r.push({kind:"compaction_finished"});break;case"mcpToolCall":i&&r.push({kind:"tool_call",name:typeof o.tool=="string"?o.tool:"mcp_tool",input:o.arguments}),a&&r.push({kind:"tool_output",name:typeof o.tool=="string"?o.tool:"mcp_tool"});break}return r}handleEvent(e,n){let r=e.current;if(!(!r&&n.kind!=="session"))switch(n.kind){case"session":e.threadId=n.sessionId,r?.context.onLog("system",`codex session ${n.sessionId}`);break;case"thinking":n.text&&r?.context.onLog("system",`[codex:thinking] ${n.text}`);break;case"text":this.appendText(e,n.text);break;case"tool_call":r?.context.onLog("system",`[codex:tool] ${n.name}`);break;case"tool_output":r?.context.onLog("system",`[codex:tool_result] ${n.name}`);break;case"compaction_started":r?.context.onLog("system","codex compacting context");break;case"compaction_finished":r?.context.onLog("system","codex context compaction finished");break;case"error":this.finishCurrent(e,new Error(n.message));break;case"turn_end":n.sessionId&&(e.threadId=n.sessionId),this.finishCurrent(e);break}}handleThreadReady(e,n,r){e.threadId=n,e.sessionAnnounced||(r.push({kind:"session",sessionId:n}),e.sessionAnnounced=!0),this.pump(e)}pump(e){if(e.current||e.closed||!e.threadId)return;let n=e.queue.shift();if(!n){this.scheduleIdleDispose(e);return}this.clearIdleTimer(e),e.current=n,n.context.onLog("system",e.activeTurnId?"codex steering active turn":"codex starting turn"),this.sendRequest(e,"turn/start",{threadId:e.threadId,input:[{type:"text",text:n.prompt}]})}finishCurrent(e,n){let r=e.current;if(!r)return;let s=e.injected.splice(0);if(e.current=null,n){this.rejectTurn(r,n);for(let o of s)this.rejectTurn(o,n);for(let o of e.queue.splice(0))this.rejectTurn(o,n);e.closed=!0,this.clearIdleTimer(e),e.child.kill("SIGTERM"),this.states.delete(g(r.frame))}else{this.resolveTurn(r,e.threadId);for(let o of s)this.resolveTurn(o,e.threadId);this.pump(e)}}appendText(e,n){let r=e.current;r&&(r.output+=n,r.context.onPartial?.(n,r.output))}flushInjectedSteers(e){if(!(!e.threadId||!e.activeTurnId))for(let n of e.injected)n.steerSent||(n.steerSent=!0,this.sendRequest(e,"turn/steer",{threadId:e.threadId,expectedTurnId:e.activeTurnId,input:[{type:"text",text:n.prompt}]}))}flushPendingNotifications(e){if(!(!e.threadId||!e.activeTurnId||e.pendingNotifications.length===0))for(let n of e.pendingNotifications.splice(0))this.sendRequest(e,"turn/steer",{threadId:e.threadId,expectedTurnId:e.activeTurnId,input:[{type:"text",text:n}]})}resolveTurn(e,n){this.cleanupTurn(e);let r=e.output.trim();e.resolve({content:r,sessionId:n,suppressMessage:e.injected&&!r})}rejectTurn(e,n){this.cleanupTurn(e),e.reject(n)}cleanupTurn(e){e.context.abortSignal?.removeEventListener("abort",e.abort),e.streamedAgentMessageIds.clear(),e.streamedReasoningIds.clear()}removeTurn(e,n){let r=g(e),s=this.states.get(r);s&&(s.queue=s.queue.filter(o=>o!==n),s.injected=s.injected.filter(o=>o!==n),s.current===n&&(s.current=null,this.clearIdleTimer(s),s.child.kill("SIGTERM"),this.states.delete(r)))}rejectState(e,n,r){let s=n.current;n.current=null,this.clearIdleTimer(n),s&&this.rejectTurn(s,r);for(let o of n.injected.splice(0))this.rejectTurn(o,r);for(let o of n.queue.splice(0))this.rejectTurn(o,r);this.states.delete(e)}scheduleIdleDispose(e){if(e.closed||e.current||e.queue.length>0||e.idleTimer)return;let n=as();n<=0||(e.idleTimer=setTimeout(()=>{e.closed||e.current||e.queue.length>0||(e.closed=!0,e.child.kill("SIGTERM"),this.states.delete(e.scopeKey))},n),e.idleTimer.unref?.())}clearIdleTimer(e){e.idleTimer&&(clearTimeout(e.idleTimer),e.idleTimer=null)}sendRequest(e,n,r){return e.requestId+=1,e.child.stdin.write(JSON.stringify({jsonrpc:"2.0",id:e.requestId,method:n,params:r})+`
|
|
27
|
+
`),e.requestId}sendNotification(e,n,r){e.child.stdin.write(JSON.stringify({jsonrpc:"2.0",method:n,params:r})+`
|
|
28
|
+
`)}};function Yt(t,e){let n=t.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&e(s);return r}function is(t){let e=Array.isArray(t.summary)?t.summary.filter(r=>typeof r=="string"):[],n=Array.isArray(t.content)?t.content.filter(r=>typeof r=="string"):[];return[...e,...n].join(`
|
|
29
|
+
`).trim()}function as(){let t=process.env.KSLOCK_RUNTIME_IDLE_TTL_MS;if(!t)return 1800*1e3;let e=Number(t);return!Number.isFinite(e)||e<0?1800*1e3:e}import{spawn as us}from"node:child_process";var cs="Reading additional input from stdin...";function tn(t){return new Promise((e,n)=>{let r=[],s="",o="",i="",a=us(t.command,t.args,{cwd:t.cwd||process.cwd(),env:t.env,stdio:["ignore","pipe","pipe"]});if(t.signal?.aborted){a.kill("SIGTERM"),n(new Error("runtime_cancelled"));return}t.signal?.addEventListener("abort",()=>{a.kill("SIGTERM"),n(new Error("runtime_cancelled"))},{once:!0}),a.stdout.on("data",u=>{o=Zt(o+u.toString(),c=>{let l=en(c);if(l){let d=t.onJson(l);d&&(s=We(s,d));return}t.onLog("stdout",c)})}),a.stderr.on("data",u=>{i=Zt(i+u.toString(),c=>{Ve(c)||(r.push(c),t.onLog("stderr",c))})}),a.on("error",n),a.on("exit",u=>{if(o.trim()){let c=en(o.trim());if(c){let l=t.onJson(c);l&&(s=We(s,l))}else t.onLog("stdout",o.trim())}if(i.trim()&&!Ve(i.trim())&&(r.push(i.trim()),t.onLog("stderr",i.trim())),t.onLog("system",`${t.command} exited with code ${u??"unknown"}`),u===0){e();return}n(new Error(s||ls(r)||`${t.command} exited with code ${u}`))})})}function Zt(t,e){let n=t.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&e(s);return r}function en(t){try{return JSON.parse(t)}catch{return null}}function Ve(t){return t.trim()===cs}function ls(t){return t.map(e=>e.trim()).filter(e=>e&&!Ve(e)).at(-1)??""}import{readFile as ds}from"node:fs/promises";async function nn(t){try{return await ds(t,"utf8")}catch{return""}}function rn(t){if(!t||typeof t!="object")return null;let e=t,n=ms(t)??"";for(let s of["delta","text_delta","content_delta"])if(typeof e[s]=="string"&&e[s])return e[s];if(n.includes("delta")||n.includes("stream")){for(let s of["text","content","message"])if(typeof e[s]=="string"&&e[s])return e[s]}return sn(e.delta??e.message??e.item)}function sn(t){if(typeof t=="string"&&t)return t;if(!t||typeof t!="object")return null;let e=t;for(let n of["delta","text_delta","content_delta","text"])if(typeof e[n]=="string"&&e[n])return e[n];for(let n of Object.values(e)){let r=sn(n);if(r)return r}return null}function ms(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["type","event","event_name","method"])if(typeof e[n]=="string")return e[n];return null}var N=class{type="codex";appServers=new pe;busyDeliveryMode="direct";capabilities={supportsSession:!0,supportsStreaming:!0,supportsExecutionPolicy:!0};async detect(){return!!await this.resolveCommand()}notifyInbox(e,n){return this.appServers.notify(e,n)}async listModels(){let e=await this.resolveCommand();return e?Mt(e):[]}async handleDelivery(e,n){let r=await this.resolveCommand();if(!r)throw new Error("codex runtime is not available");let s=await I(e),o=s?.runtimeType===this.type?s.runtimeSessionId:null,i=o?`resuming ${o}`:"starting new session";n.onLog("system",`codex ${i} in ${n.cwd??process.cwd()}`);let a;try{a=await this.runCodexAppServer(r,e,n,o)}catch(c){if(on(c))n.onLog("stderr",`codex app-server failed; falling back to codex exec. ${c instanceof Error?c.message:""}`),a=await this.runCodex(r,e,n,o);else if(o)n.onLog("stderr",`codex resume ${o} failed; starting a new session. ${c instanceof Error?c.message:""}`),a=await this.runCodexAppServer(r,e,n,null).catch(l=>{if(!on(l))throw l;return n.onLog("stderr",`codex app-server retry failed; falling back to codex exec. ${l instanceof Error?l.message:""}`),this.runCodex(r,e,n,null)});else throw c}let u=a.sessionId??o??null;return await x({agentId:e.agentId,channelId:e.channelId,runtimeScopeKey:g(e),runtimeType:this.type,runtimeSessionId:u,workspacePath:n.cwd??null,updatedAt:new Date().toISOString()}),u?n.onLog("system",`codex session ${u}`):n.onLog("system","codex completed without exposing a resumable session id"),a.suppressMessage?{content:a.output.trim(),sessionId:u,suppressMessage:!0}:{content:a.output.trim()||"codex runtime completed without output",sessionId:u}}async runCodexAppServer(e,n,r,s){let o=await v(n,{workspacePath:r.cwd}),i=w(n,ce(r.env));r.onLog("system",i?`codex app-server using model override ${i}`:"codex app-server using configured model"),r.onLog("system",`codex app-server sandbox ${k(n.executionPolicy)}`);let a=await this.appServers.runTurn({command:e,frame:n,context:r,prompt:o,sessionId:s,model:i});return{output:a.content,sessionId:a.sessionId??null,suppressMessage:a.suppressMessage}}async runCodex(e,n,r,s){let o=h(n);await ps(o,{recursive:!0});let i=fs(o,"last-message.txt");await gs(i,"","utf8");let a=await v(n,{workspacePath:r.cwd}),u=w(n,ce(r.env));r.onLog("system",u?`codex using model override ${u}`:"codex using configured model"),r.onLog("system",`codex sandbox ${k(n.executionPolicy)}`);let c=new Set;return await tn({command:e,args:qe({frame:n,prompt:a,outputFile:i,model:u,sessionId:s}),cwd:r.cwd,env:r.env,signal:r.abortSignal,onJson:l=>{let d=rn(l);d&&r.onPartial?.(d);let p=Ge(l);p&&c.add(p);let m=de(l);m&&r.onLog("system",`[codex:event] ${m}`);let f=$(T(l))??me(l);return f?(r.onLog("stderr",`[codex:error] ${f}`),f):null},onLog:r.onLog}),{output:await nn(i),sessionId:[...c].at(-1)??null}}async resolveCommand(){return S({command:"codex",envVars:["CODEX_BIN","CODEX_CLI_PATH"]})}};function on(t){if(process.env.KSLOCK_CODEX_DISABLE_EXEC_FALLBACK==="1")return!1;let e=t instanceof Error?t.message:String(t);return/app-server exited|unrecognized|unknown command|invalid subcommand|not supported/i.test(e)}import{randomUUID as wn}from"node:crypto";function He(t){return t.preset==="read_only"?["--permission-mode","dontAsk","--tools","Read,Grep,Glob,LS"]:t.preset==="full_access"?["--dangerously-skip-permissions"]:["--permission-mode","acceptEdits","--allowedTools",["Read","Grep","Glob","LS","Edit","MultiEdit","Write","Bash(git status *)","Bash(git diff *)","Bash(git log *)","Bash(git show *)","Bash(pnpm test *)","Bash(pnpm run test *)","Bash(pnpm typecheck *)","Bash(pnpm run typecheck *)","Bash(pnpm lint *)","Bash(pnpm run lint *)","Bash(pnpm build *)","Bash(pnpm run build *)","Bash(npm test *)","Bash(npm run test *)","Bash(npm run typecheck *)","Bash(npm run lint *)","Bash(npm run build *)","Bash(yarn test *)","Bash(yarn typecheck *)","Bash(yarn lint *)","Bash(yarn build *)","Bash(tsc *)","Bash(vitest *)"].join(","),"--disallowedTools",["Bash(rm *)","Bash(sudo *)","Bash(chmod *)","Bash(chown *)","Bash(curl *)","Bash(wget *)"].join(",")]}function Qe(t){return["-p","--output-format","stream-json","--verbose","--include-partial-messages",...t.resume?["--resume",t.sessionId]:["--session-id",t.sessionId],...an(t.model),...He(t.frame.executionPolicy)]}function Xe(t){return["--output-format","stream-json","--input-format","stream-json","--verbose","--include-partial-messages",...t.resume?["--resume",t.sessionId]:["--session-id",t.sessionId],...an(t.model),...He(t.frame.executionPolicy)]}function ge(t){return t.KSCC_MODEL?.trim()||t.ANTHROPIC_MODEL?.trim()||null}function an(t){return t?["--model",t]:[]}var fe="kscc \u8FD4\u56DE\u9519\u8BEF\uFF0C\u672A\u63D0\u4F9B\u8BE6\u7EC6\u539F\u56E0";function Ze(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["type","subtype","event","event_name"])if(typeof e[n]=="string")return e[n];return null}function ye(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["session_id","sessionId"])if(typeof e[n]=="string"&&ys(e[n]))return e[n];for(let n of Object.values(e)){let r=ye(n);if(r)return r}return null}function B(t){if(!t||typeof t!="object")return null;let e=t;if(typeof e.result=="string"&&e.result.trim())return e.result;if(typeof e.content=="string"&&e.content.trim())return e.content;let n=e.message;if(n&&typeof n=="object"){let r=un(n.content);if(r)return r}return un(e.content)}function J(t){if(!t)return null;let e=hs(t),r=(e?K(e):t)?.trim();return!r||Ye(r)?null:r}function D(t){if(!t||typeof t!="object")return null;let e=t,n=typeof e.type=="string"?e.type:"",r=typeof e.subtype=="string"?e.subtype:"";return n==="error"||r==="error"||r==="failure"||e.is_error===!0||n==="result"&&r&&r!=="success"?K(t)??fe:null}function z(t,e){return!t||t===fe&&e!==fe?e:t}function un(t){if(typeof t=="string"&&t.trim())return t;if(!Array.isArray(t))return null;let e=t.map(n=>{if(!n||typeof n!="object")return"";let r=n;return typeof r.text=="string"?r.text:""}).filter(Boolean).join("");return e.trim()?e:null}function K(t){if(typeof t=="string"&&t&&!Ye(t))return t;if(!t||typeof t!="object")return null;let e=t;for(let r of["message","detail","reason","error"]){let s=e[r];if(typeof s=="string"&&s&&!Ye(s))return s}let n=K(e.error);if(n)return n;for(let r of Object.values(e)){let s=K(r);if(s)return s}return null}function ys(t){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(t)}function Ye(t){let e=t.trim().toLowerCase();return e==="error"||e==="failure"}function hs(t){try{return JSON.parse(t)}catch{return null}}import{spawn as vs}from"node:child_process";function gn(t){return new Promise((e,n)=>{let r=[],s=[],o="",i=[],a="",u="",c="",l=vs(t.command,t.args,{cwd:t.cwd||process.cwd(),env:t.env,stdio:["pipe","pipe","pipe"]});if(l.stdin.on("error",()=>{}),t.signal?.aborted){l.kill("SIGTERM"),n(new Error("runtime_cancelled"));return}t.signal?.addEventListener("abort",()=>{l.kill("SIGTERM"),n(new Error("runtime_cancelled"))},{once:!0}),l.stdin.end(t.stdin??""),l.stdout.on("data",d=>{u=cn(u+d.toString(),p=>{let m=ln(p);if(m){let f=t.onJson(m)??D(m);f&&(a=z(a,f));let y=B(m);y&&(dn(m)?s.push(y):o=mn(y,o,t.onPartial));return}r.push(p),t.onLog("stdout",p)})}),l.stderr.on("data",d=>{c=cn(c+d.toString(),p=>{i.push(p),t.onLog("stderr",p)})}),l.on("error",n),l.on("exit",d=>{if(u.trim()){let m=ln(u.trim());if(m){let f=t.onJson(m)??D(m);f&&(a=z(a,f));let y=B(m);y&&(dn(m)?s.push(y):o=mn(y,o,t.onPartial))}else r.push(u.trim()),t.onLog("stdout",u.trim())}if(c.trim()&&(i.push(c.trim()),t.onLog("stderr",c.trim())),t.onLog("system",`${t.command} exited with code ${d??"unknown"}`),d===0){e({output:ws(s,o,r)});return}let p=J(pn(i))??pn(i);n(new Error(a||p||`${t.command} exited with code ${d}`))})})}function cn(t,e){let n=t.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&e(s);return r}function ln(t){try{return JSON.parse(t)}catch{return null}}function dn(t){return!!(t&&typeof t=="object"&&t.type==="result")}function mn(t,e,n){let r=t.startsWith(e)?t:`${e}${t}`,s=r.slice(e.length);return s&&n?.(s,r),r}function ws(t,e,n){let r=t.at(-1)?.trim();if(r)return r;let s=e.trim();return s||n.join(`
|
|
30
|
+
`).trim()}function pn(t){return t.map(e=>e.trim()).filter(Boolean).at(-1)??""}import{mkdir as Is,readFile as xs,writeFile as fn}from"node:fs/promises";import{join as Ss}from"node:path";var Rs="kscc-last-message.txt";function bs(t){return Ss(h(t),Rs)}async function yn(t){await Is(h(t),{recursive:!0});let e=bs(t);return await fn(e,"","utf8"),e}async function hn(t,e){await fn(t,e,"utf8")}async function vn(t){try{return await xs(t,"utf8")}catch{return""}}var q=class{type="kscc";busyDeliveryMode="gated";sessions=new A({type:"kscc",displayName:"kscc",buildArgs:Xe,resolveModel:ge,extractSessionId:ye,extractText:B,extractEventName:Ze,summarizeError:D,normalizeError:J,preferFailure:z});capabilities={supportsSession:!0,supportsStreaming:!0,supportsExecutionPolicy:!0};async detect(){return!!await this.resolveCommand()}notifyInbox(e,n){return this.sessions.notify(e,n)}async listModels(){let e=await this.resolveCommand();return e?se(e):[]}async handleDelivery(e,n){let r=await this.resolveCommand();if(!r)throw new Error("kscc runtime is not available");let s=await I(e),o=s?.runtimeType===this.type?s.runtimeSessionId:null,i=o??wn(),a=o?`resuming ${o}`:`starting new session ${i}`;n.onLog("system",`kscc ${a} in ${n.cwd??process.cwd()}`);let u;try{u=await this.runKsccStream(r,e,n,i,!!o)}catch(c){if(In(c))n.onLog("stderr",`kscc stream-json session failed; falling back to print mode. ${c instanceof Error?c.message:""}`),u=await this.runKscc(r,e,n,i,!!o);else if(o){let l=wn();n.onLog("stderr",`kscc resume ${o} failed; starting a new session ${l}. ${c instanceof Error?c.message:""}`),u=await this.runKsccStream(r,e,n,l,!1).catch(d=>{if(!In(d))throw d;return n.onLog("stderr",`kscc stream retry failed; falling back to print mode. ${d instanceof Error?d.message:""}`),this.runKscc(r,e,n,l,!1)})}else throw c}return await x({agentId:e.agentId,channelId:e.channelId,runtimeScopeKey:g(e),runtimeType:this.type,runtimeSessionId:u.sessionId,workspacePath:n.cwd??null,updatedAt:new Date().toISOString()}),n.onLog("system",`kscc session ${u.sessionId}`),u.suppressMessage?{content:u.output.trim(),sessionId:u.sessionId,suppressMessage:!0}:{content:u.output.trim()||"kscc runtime completed without output",sessionId:u.sessionId}}async runKsccStream(e,n,r,s,o){r.onLog("system",o?`kscc stream resume ${s}`:`kscc stream session-id ${s}`);let i=await this.sessions.runTurn({command:e,frame:n,context:r,prompt:await v(n,{workspacePath:r.cwd}),sessionId:s,resume:o});return{output:i.content,sessionId:i.sessionId??s,suppressMessage:i.suppressMessage}}async runKscc(e,n,r,s,o){let i=await v(n,{workspacePath:r.cwd}),a=w(n,ge(r.env)),u=await yn(n);r.onLog("system",a?`kscc using model override ${a}`:"kscc using configured model"),r.onLog("system",o?`kscc resume ${s}`:`kscc session-id ${s}`);let c=new Set,l=await gn({command:e,args:Qe({frame:n,sessionId:s,resume:o,model:a}),stdin:i,cwd:r.cwd,env:r.env,signal:r.abortSignal,onPartial:r.onPartial,onJson:d=>{let p=ye(d);p&&c.add(p);let m=Ze(d);m&&r.onLog("system",`[kscc:event] ${m}`);let f=J(D(d));return f?(r.onLog("stderr",`[kscc:error] ${f}`),f):null},onLog:r.onLog});return await hn(u,l.output),{output:l.output||await vn(u),sessionId:[...c].at(-1)??s}}async resolveCommand(){return S({command:"kscc",envVars:["KSCC_BIN"]})}};function In(t){if(process.env.KSLOCK_KSCC_DISABLE_PRINT_FALLBACK==="1")return!1;let e=t instanceof Error?t.message:String(t);return/process exited|unknown option|unrecognized|input-format|stream-json|stdin|not supported/i.test(e)}function xn(t){return t.preset==="full_access"?"allow":t.preset==="read_only"?{"*":"deny",read:{"*":"allow","*.env":"deny","*.env.*":"deny","*.env.example":"allow"},glob:"allow",grep:"allow",list:"allow",lsp:"allow",todoread:"allow",edit:"deny",bash:"deny",task:"deny",skill:"deny",todowrite:"deny",webfetch:"deny",websearch:"deny",codesearch:"deny",external_directory:"deny",doom_loop:"deny"}:{"*":"deny",read:{"*":"allow","*.env":"deny","*.env.*":"deny","*.env.example":"allow"},glob:"allow",grep:"allow",list:"allow",lsp:"allow",todoread:"allow",todowrite:"allow",edit:"allow",skill:"allow",bash:{"*":"deny","git status *":"allow","git diff *":"allow","git log *":"allow","git show *":"allow","pnpm test *":"allow","pnpm run test *":"allow","pnpm typecheck *":"allow","pnpm run typecheck *":"allow","pnpm lint *":"allow","pnpm run lint *":"allow","pnpm build *":"allow","pnpm run build *":"allow","npm test *":"allow","npm run test *":"allow","npm run typecheck *":"allow","npm run lint *":"allow","npm run build *":"allow","yarn test *":"allow","yarn typecheck *":"allow","yarn lint *":"allow","yarn build *":"allow","tsc *":"allow","vitest *":"allow","rm *":"deny","sudo *":"deny","chmod *":"deny","chown *":"deny","curl *":"deny","wget *":"deny"},task:"deny",webfetch:"deny",websearch:"deny",codesearch:"deny",external_directory:"deny",doom_loop:"deny"}}var et="1.14.30";function tt(t){return["run","--format","json","--pure",...Cs(t.workspacePath),...ks(t.sessionId),...As(t.model),...Es(t.frame.executionPolicy),"--",t.message]}function nt(t,e){return{...t,OPENCODE_PERMISSION:JSON.stringify(xn(e))}}function rt(t){return t.OPENCODE_MODEL?.trim()||null}function he(t){return!t||Rn(t)?null:`OpenCode CLI ${t} \u6682\u4E0D\u652F\u6301\uFF0C\u5F53\u524D\u8FD0\u884C\u65F6\u8981\u6C42 opencode >= ${et}\u3002\u8BF7\u5347\u7EA7 opencode \u540E\u91CD\u542F daemon\u3002`}function Rn(t){if(!t)return!0;let e=Sn(t),n=Sn(et);if(!e||!n)return!0;for(let r=0;r<3;r+=1){if(e[r]>n[r])return!0;if(e[r]<n[r])return!1}return!0}function Sn(t){let e=t.match(/(\d+)\.(\d+)\.(\d+)/);return e?[Number(e[1]),Number(e[2]),Number(e[3])]:null}function ks(t){return t?["--session",t]:[]}function Cs(t){return t?["--dir",t]:[]}function As(t){return t?["--model",t]:[]}function Es(t){return t.preset==="full_access"?["--dangerously-skip-permissions"]:[]}var ve="opencode \u8FD4\u56DE\u9519\u8BEF\uFF0C\u672A\u63D0\u4F9B\u8BE6\u7EC6\u539F\u56E0";function kn(t){if(!t||typeof t!="object")return null;let e=t;for(let n of["type","subtype","event","event_name","eventName"])if(typeof e[n]=="string")return e[n];return null}function ot(t){if(!t||typeof t!="object")return null;let e=t;for(let r of["sessionID","sessionId","session_id"])if(typeof e[r]=="string"&&e[r].trim())return e[r];let n=e.session;if(n&&typeof n=="object"){let r=n.id;if(typeof r=="string"&&r.trim())return r}for(let r of Object.values(e)){let s=ot(r);if(s)return s}return null}function it(t){if(!t||typeof t!="object")return null;let e=t;if(typeof e.result=="string"&&e.result.trim())return e.result;if(typeof e.output=="string"&&e.output.trim())return e.output;let n=bn(e.message);if(n)return n;let r=bn(e.part);if(r)return r;if(Ts(e)){if(typeof e.content=="string"&&e.content.trim())return e.content;if(typeof e.text=="string"&&e.text.trim())return e.text;let s=we(e.content);if(s)return s;let o=we(e.parts);if(o)return o}return null}function Ie(t){if(!t)return null;let e=Ds(t),r=(e?U(e):t)?.trim();return!r||st(r)?null:r}function G(t){if(!t||typeof t!="object")return null;let e=t,n=typeof e.type=="string"?e.type.toLowerCase():"",r=typeof e.subtype=="string"?e.subtype.toLowerCase():"";return n.includes("error")||r==="error"||r==="failure"||e.is_error===!0||n==="result"&&r&&r!=="success"?U(t)??ve:null}function at(t,e){return!t||t===ve&&e!==ve?e:t}function bn(t){if(!t||typeof t!="object")return null;let e=t,n=typeof e.role=="string"?e.role.toLowerCase():"",r=typeof e.type=="string"?e.type.toLowerCase():"";return n&&n!=="assistant"?null:typeof e.text=="string"&&e.text.trim()?e.text:typeof e.content=="string"&&e.content.trim()?e.content:r&&r!=="text"&&!r.includes("assistant")&&!r.includes("message")&&!r.includes("part")?null:we(e.content)??we(e.parts)}function we(t){if(typeof t=="string"&&t.trim())return t;if(!Array.isArray(t))return null;let e=t.map(n=>{if(!n||typeof n!="object")return"";let r=n;return typeof r.text=="string"?r.text:typeof r.content=="string"?r.content:""}).filter(Boolean).join("");return e.trim()?e:null}function Ts(t){let e=typeof t.role=="string"?t.role.toLowerCase():"";if(e&&e!=="assistant")return!1;let n=typeof t.type=="string"?t.type.toLowerCase():"";return n?n==="result"||n==="text"||n.includes("assistant")||n.includes("message")||n.includes("part"):e==="assistant"}function U(t){if(typeof t=="string"&&t&&!st(t))return t;if(!t||typeof t!="object")return null;let e=t;for(let r of["message","detail","reason","error"]){let s=e[r];if(typeof s=="string"&&s&&!st(s))return s}let n=U(e.error);if(n)return n;for(let r of Object.values(e)){let s=U(r);if(s)return s}return null}function st(t){let e=t.trim().toLowerCase();return e==="error"||e==="failure"}function Ds(t){try{return JSON.parse(t)}catch{return null}}import{spawn as Ms}from"node:child_process";function Mn(t){return new Promise((e,n)=>{let r=[],s=[],o="",i=[],a="",u="",c="",l=Ms(t.command,t.args,{cwd:t.cwd||process.cwd(),env:t.env,stdio:["ignore","pipe","pipe"]});if(t.signal?.aborted){l.kill("SIGTERM"),n(new Error("runtime_cancelled"));return}t.signal?.addEventListener("abort",()=>{l.kill("SIGTERM"),n(new Error("runtime_cancelled"))},{once:!0}),l.stdout.on("data",d=>{u=Cn(u+d.toString(),p=>{let m=An(p);if(m){let f=t.onJson(m)??G(m);f&&(a=at(a,f));let y=it(m);y&&(En(m)?s.push(y):o=Tn(y,o,t.onPartial));return}r.push(p),t.onLog("stdout",p)})}),l.stderr.on("data",d=>{c=Cn(c+d.toString(),p=>{i.push(p),t.onLog("stderr",p)})}),l.on("error",n),l.on("exit",d=>{if(u.trim()){let m=An(u.trim());if(m){let f=t.onJson(m)??G(m);f&&(a=at(a,f));let y=it(m);y&&(En(m)?s.push(y):o=Tn(y,o,t.onPartial))}else r.push(u.trim()),t.onLog("stdout",u.trim())}if(c.trim()&&(i.push(c.trim()),t.onLog("stderr",c.trim())),t.onLog("system",`${t.command} exited with code ${d??"unknown"}`),d===0){e({output:Fs(s,o,r)});return}let p=Ie(Dn(i))??Dn(i);n(new Error(a||p||`${t.command} exited with code ${d}`))})})}function Cn(t,e){let n=t.split(/\r?\n/),r=n.pop()??"";for(let s of n)s.trim()&&e(s);return r}function An(t){try{return JSON.parse(t)}catch{return null}}function En(t){if(!t||typeof t!="object")return!1;let e=t,n=typeof e.type=="string"?e.type.toLowerCase():"";return n==="result"||n.includes("result")||n.includes("complete")}function Tn(t,e,n){let r=t.startsWith(e)?t:`${e}${t}`,s=r.slice(e.length);return s&&n?.(s,r),r}function Fs(t,e,n){let r=t.at(-1)?.trim();if(r)return r;let s=e.trim();return s||n.join(`
|
|
31
|
+
`).trim()}function Dn(t){return t.map(e=>e.trim()).filter(Boolean).at(-1)??""}import{mkdir as Ps,readFile as _s,writeFile as Fn}from"node:fs/promises";import{join as Ls}from"node:path";var js="opencode-last-message.txt";function Os(t){return Ls(h(t),js)}async function Pn(t){await Ps(h(t),{recursive:!0});let e=Os(t);return await Fn(e,"","utf8"),e}async function _n(t,e){await Fn(t,e,"utf8")}async function Ln(t){try{return await _s(t,"utf8")}catch{return""}}var W=class{type="opencode";busyDeliveryMode="queue";capabilities={supportsSession:!0,supportsStreaming:!0,supportsExecutionPolicy:!0};async detect(){let e=await this.resolveCommand();return e?!he(await Le(e)):!1}async listModels(){let e=await this.resolveCommand();return e?Ft(e):[]}async handleDelivery(e,n){let r=await this.resolveCommand();if(!r)throw new Error("opencode runtime is not available");let s=he(await Le(r));if(s)throw new Error(s);let o=await I(e),i=o?.runtimeType===this.type?o.runtimeSessionId:null,a=i?`resuming ${i}`:"starting new session";n.onLog("system",`opencode ${a} in ${n.cwd??process.cwd()}`);let u;try{u=await this.runOpenCode(r,e,n,i)}catch(c){if(!i)throw c;n.onLog("stderr",`opencode resume ${i} failed; starting a new session. ${c instanceof Error?c.message:""}`),u=await this.runOpenCode(r,e,n,null)}return await x({agentId:e.agentId,channelId:e.channelId,runtimeScopeKey:g(e),runtimeType:this.type,runtimeSessionId:u.sessionId,workspacePath:n.cwd??null,updatedAt:new Date().toISOString()}),u.sessionId&&n.onLog("system",`opencode session ${u.sessionId}`),{content:u.output.trim()||"opencode runtime completed without output",sessionId:u.sessionId}}async runOpenCode(e,n,r,s){let o=await v(n,{workspacePath:r.cwd}),i=w(n,rt(r.env)),a=await Pn(n),u=nt(r.env,n.executionPolicy);r.onLog("system",i?`opencode using model override ${i}`:"opencode using configured model"),r.onLog("system",s?`opencode session ${s}`:"opencode new session");let c=new Set,l=await Mn({command:e,args:tt({frame:n,message:o,sessionId:s,model:i,workspacePath:r.cwd}),cwd:r.cwd,env:u,signal:r.abortSignal,onPartial:r.onPartial,onJson:d=>{let p=ot(d);p&&c.add(p);let m=kn(d);m&&r.onLog("system",`[opencode:event] ${m}`);let f=Ie(G(d));return f?(r.onLog("stderr",`[opencode:error] ${f}`),f):null},onLog:r.onLog});return await _n(a,l.output),{output:l.output||await Ln(a),sessionId:[...c].at(-1)??s}}async resolveCommand(){return S({command:"opencode",envVars:["OPENCODE_BIN"]})}};var ut=class{runtimes=new Map;constructor(e){for(let n of e)this.runtimes.set(n.type,n)}get(e){let n=this.runtimes.get(e);if(!n)throw new Error(`runtime ${e} is not registered`);return n}detectable(){return[...this.runtimes.values()]}async detectCapabilities(){return Promise.all(this.detectable().map(async e=>{try{let n=e.detect?await e.detect():!0,r=n&&e.listModels?await e.listModels().catch(()=>[]):[];return{type:e.type,available:n,...e.capabilities,...r.length>0?{models:r}:{}}}catch{return{type:e.type,available:!1,...e.capabilities}}}))}};function jn(){return new ut([new N,new j,new q,new W])}var xe=class{runtimes=jn();publisher;runner;queue;constructor(e){this.publisher=new H(e),this.runner=new ne(this.runtimes,this.publisher),this.queue=new Q((n,r)=>{Z(n,n.deliveryId),this.publisher.failed(n,r),this.publisher.status(n,"error")})}async deliver(e){await this.queue.enqueue(e,(n,r)=>this.runner.run(n,r),{allowBusyDelivery:!0,onBusyDelivery:n=>this.handleBusyDelivery(n)})}cancelDelivery(e,n="cancelled_by_user"){this.queue.cancel(e,n)}handlePermissionResponse(e){}async detectAvailableRuntimes(){return(await this.detectRuntimeCapabilities()).filter(n=>n.available).map(n=>n.type)}async detectRuntimeCapabilities(){return(await this.runtimes.detectCapabilities()).map(n=>({...n,available:n.available}))}async handleBusyDelivery(e){let n=this.runtimes.get(e.runtimeType),r=await ft(e),s=M(e),o=xt({pendingCount:r.messages.length,checkMessagesCommand:s.KSLOCK_CHECK_MESSAGES_COMMAND,inboxFile:s.KSLOCK_INBOX_FILE});this.publisher.delivered(e),this.publisher.runtimeLog(e,"system",`queued in agent inbox (${r.messages.length} pending)`),await n.notifyInbox?.(e,o)||this.publisher.runtimeLog(e,"system","agent inbox notification deferred until the queued delivery starts")}};var Se=class{frames=[];enqueue(e){return $s(e)?(this.frames.push(e),this.frames.length>200&&this.frames.splice(0,this.frames.length-200),!0):!1}drain(){return this.frames.splice(0)}get size(){return this.frames.length}};function $s(t){return t.type==="agent:delivery_ack"||t.type==="agent:message"||t.type==="agent:status"||t.type==="task:status"}var Re=class{constructor(e){this.config=e}ws=null;reconnectAttempts=0;reconnectTimer=null;stopped=!1;outbox=new Se;agentManager=new xe(e=>this.send(e));connect(){this.stopped=!1;let e=this.buildWebSocketUrl();this.ws=new On(e),this.ws.on("open",()=>{this.handleOpen()}),this.ws.on("message",n=>{let r=Ns(n.toString());r&&this.handleFrame(r)}),this.ws.on("close",(n,r)=>{console.log(`[Daemon] Disconnected${Ks(n,r)}`),this.ws=null,this.scheduleReconnect()}),this.ws.on("error",n=>{console.error(`[Daemon] WebSocket error: ${n.message}`)})}close(){this.stopped=!0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.ws?.close()}async handleFrame(e){if(e.type==="ping"){this.send({type:"pong",requestId:e.requestId});return}if(e.type==="error"){console.error(`[Daemon] Server error ${e.code}: ${e.message}`),(e.code==="invalid_machine_key"||e.code==="machine_key_revoked")&&(this.stopped=!0);return}if(e.type==="agent:deliver"){await this.agentManager.deliver(e);return}if(e.type==="agent:cancel"){this.agentManager.cancelDelivery(e.deliveryId,e.reason);return}e.type==="permission:response"&&this.agentManager.handlePermissionResponse(e)}async handleOpen(){this.reconnectAttempts=0,console.log(`[Daemon] Connected to ${this.config.serverUrl}`);let e=await this.agentManager.detectRuntimeCapabilities();this.send({type:"machine:ready",daemonVersion:this.config.daemonVersion,hostname:this.config.hostname,os:this.config.os,arch:this.config.arch,availableRuntimes:e.filter(n=>n.available).map(n=>n.type),runtimeCapabilities:e}),this.flushOutbox()}send(e){this.sendNow(e)||this.stopped||this.outbox.enqueue(e)&&console.warn(`[Daemon] Queued ${e.type}; websocket is not open`)}sendNow(e){if(!this.ws||this.ws.readyState!==On.OPEN)return!1;try{return this.ws.send(JSON.stringify(e)),!0}catch{return!1}}flushOutbox(){if(this.outbox.size===0)return;let e=this.outbox.drain();console.log(`[Daemon] Flushing ${e.length} queued frame(s)`);for(let n of e)this.sendNow(n)||this.outbox.enqueue(n)}buildWebSocketUrl(){return`${this.config.serverUrl.replace(/^http/,"ws")}/daemon/connect?key=${encodeURIComponent(this.config.machineKey)}`}scheduleReconnect(){if(this.stopped||this.reconnectTimer)return;let e=Math.min(this.config.reconnectBaseMs*2**this.reconnectAttempts,3e4);this.reconnectAttempts+=1,console.log(`[Daemon] Reconnecting in ${e}ms`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.stopped||this.connect()},e)}};function Ns(t){try{return JSON.parse(t)}catch{return null}}function Ks(t,e){let n=e.toString();return!t&&!n?"":` (code ${t}${n?`, reason: ${n}`:""})`}function Nn(t=process.argv.slice(2)){if(t[0]==="check-messages"||t[0]==="check_messages")return Bs(t.slice(1)),null;if(t.includes("--help")||t.includes("-h"))return console.log(Ce),null;if(t.includes("--version")||t.includes("-v"))return console.log(ke()),null;dt();let e=lt(t);if(!e)return console.error(Ce),process.exitCode=1,null;let n=new Re(e);n.connect();let r=()=>{n.close(),process.exit(0)};return process.once("SIGINT",r),process.once("SIGTERM",r),n}async function Bs(t){let e=$n(t,"--agent-id")??process.env.AGENT_ID,n=$n(t,"--channel-id")??process.env.CHANNEL_ID;if(!e){console.error("Usage: kslock-daemon check-messages --agent-id <agent-id> [--channel-id <channel-id>]"),process.exitCode=1;return}let r=await yt({agentId:e,channelId:n});if(t.includes("--json")){console.log(JSON.stringify(r,null,2));return}console.log(Me(r))}function $n(t,e){let n=t.indexOf(e);return n<0?null:t[n+1]??null}Nn();
|