@yuandc/aica 0.1.29 → 0.1.31

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.
@@ -1 +1 @@
1
- import{createPlanEvent as h,normalizePlanSessionUpdate as y}from"../plan-events.js";import{STANDARD_AGENT_EVENT_TYPES as _,createAgentMessageChunk as m,createAgentProgressChunk as A,createAgentThoughtChunk as b,createToolCall as x,createToolCallUpdate as k,firstString as o,normalizeToolKind as C,normalizeToolStatus as f}from"../standard-events.js";function g(n){if(!n||typeof n!="object"||Array.isArray(n))return null;const t=n,e=t.update;return!e||typeof e!="object"||Array.isArray(e)?null:{sessionId:typeof t.sessionId=="string"?t.sessionId:void 0,update:e}}function E(n){const t=g(n);if(!t)return null;const e=String(t.update.sessionUpdate||"");if(e==="agent_message_chunk")return m({text:s(t.update.content),method:"session/update",params:n});if(e==="agent_progress_chunk")return A({text:s(t.update.content),method:"session/update",params:n});if(e==="agent_thought_chunk")return b({text:s(t.update.content),method:"session/update",params:n});if(e==="tool_call"||e==="tool_call_update")return I(e,t.update,n);if(e==="plan"||e==="plan_update"||e==="plan_removed"){const r=y(t.update);return r?h({update:r,method:"session/update",params:n}):null}return _.has(e)?{type:e,label:w(e),...s(t.update.content)?{text:s(t.update.content)}:{},raw:{method:"session/update",params:n,update:t.update},atMs:Date.now()}:null}function F(n){const t=g(n);if(!t)return null;const e=String(t.update.sessionUpdate||"");if(e==="agent_message_chunk")return{phase:"thinking",label:"回复中",detail:p(s(t.update.content)),updateType:e};if(e==="agent_progress_chunk")return{phase:"thinking",label:"处理中",detail:p(s(t.update.content)),updateType:e};if(e==="agent_thought_chunk")return{phase:"thinking",label:"思考中",detail:p(s(t.update.content)),updateType:e};if(e==="tool_call"||e==="tool_call_update"){const r=o(t.update.toolCallId,t.update.id),a=f(o(t.update.status)),i=o(t.update.title,t.update.kind),u=S(t.update.rawOutput);if(r==="codex.connection")return{phase:a==="failed"?"failed":a==="completed"?"exploring":"resuming",label:i||(a==="completed"?"Codex 连接已恢复":"Codex 正在重连"),detail:u,updateType:e};if(r==="codex.error")return{phase:"failed",label:i||"Codex 执行异常",detail:u,updateType:e};const c=T(t.update.rawInput),l=o(c?.command);return i==="压缩上下文"?{phase:"thinking",label:"压缩上下文",updateType:e}:/^(?:启动|发送|恢复|等待|结束|处理)子任务/.test(i||"")?{phase:"exploring",label:i||"处理子任务",updateType:e}:l?{phase:"exploring",label:"执行命令",detail:i||l,updateType:e}:{phase:"exploring",label:"调用工具",detail:i,updateType:e}}return e==="plan"||e==="plan_update"?{phase:"thinking",label:"规划中",updateType:e}:e==="aca_context_maintenance"?{phase:"thinking",label:o(t.update.label)||"正在整理会话上下文",detail:o(t.update.detail),updateType:e}:null}function s(n){if(typeof n=="string")return n;if(!n||typeof n!="object"||Array.isArray(n))return"";const t=n;return typeof t.text=="string"?t.text:""}function I(n,t,e){const r=o(t.toolCallId,t.id)||`acp.${Date.now()}`,a=C(o(t.kind,t.title)),i=f(o(t.status)),u=t.rawInput??t.input,c=t.rawOutput??t.output,l={method:"session/update",params:e,toolCallId:r,kind:a,title:o(t.title,t.kind),status:i,rawInput:u,rawOutput:c,content:t.content,locations:Array.isArray(t.locations)?t.locations.filter(d=>!!(d&&typeof d=="object"&&!Array.isArray(d))):void 0,meta:t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:void 0};return n==="tool_call"?x(l):k(l)}function w(n){return n.replace(/_/g," ")}function p(n){const t=n.replace(/\s+/g," ").trim();if(t)return t.length>120?`${t.slice(0,117)}...`:t}function S(n){if(!n||typeof n!="object"||Array.isArray(n))return;const t=n,e=t.error&&typeof t.error=="object"&&!Array.isArray(t.error)?t.error:null,r=o(e?.message,t.message),a=/reconnecting\.{3}\s*(\d+)\s*\/\s*(\d+)/i.exec(r||"");return a?`第 ${a[1]}/${a[2]} 次尝试`:/selected model is at capacity/i.test(r||"")?"所选模型当前繁忙,请稍后重试":r}function T(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:null}export{g as acpSessionUpdateFromParams,E as eventFromAcpSessionUpdate,F as statusFromAcpSessionUpdate,s as textFromAcpContent};
1
+ import{createPlanEvent as y,normalizePlanSessionUpdate as _}from"../plan-events.js";import{STANDARD_AGENT_EVENT_TYPES as A,createAgentMessageChunk as b,createAgentProgressChunk as x,createAgentThoughtChunk as k,createToolCall as C,createToolCallUpdate as I,firstString as a,normalizeToolKind as S,normalizeToolStatus as h}from"../standard-events.js";function f(n){if(!n||typeof n!="object"||Array.isArray(n))return null;const t=n,e=t.update;return!e||typeof e!="object"||Array.isArray(e)?null:{sessionId:typeof t.sessionId=="string"?t.sessionId:void 0,update:e}}function E(n){const t=f(n);if(!t)return null;const e=String(t.update.sessionUpdate||""),r=l(t.update._meta)??void 0;if(e==="agent_message_chunk")return b({text:i(t.update.content),method:"session/update",params:n,meta:r});if(e==="agent_progress_chunk")return x({text:i(t.update.content),method:"session/update",params:n,meta:r});if(e==="agent_thought_chunk")return k({text:i(t.update.content),method:"session/update",params:n,meta:r});if(e==="tool_call"||e==="tool_call_update")return w(e,t.update,n);if(e==="plan"||e==="plan_update"||e==="plan_removed"){const o=_(t.update);return o?y({update:o,method:"session/update",params:n,meta:r}):null}return A.has(e)?{type:e,label:T(e),...i(t.update.content)?{text:i(t.update.content)}:{},raw:{method:"session/update",params:n,update:t.update},atMs:Date.now()}:null}function P(n){const t=f(n);if(!t||m(t.update))return null;const e=String(t.update.sessionUpdate||"");if(e==="agent_message_chunk")return{phase:"thinking",label:"回复中",detail:g(i(t.update.content)),updateType:e};if(e==="agent_progress_chunk")return{phase:"thinking",label:"处理中",detail:g(i(t.update.content)),updateType:e};if(e==="agent_thought_chunk")return{phase:"thinking",label:"思考中",detail:g(i(t.update.content)),updateType:e};if(e==="tool_call"||e==="tool_call_update"){const r=a(t.update.toolCallId,t.update.id),o=h(a(t.update.status)),s=a(t.update.title,t.update.kind),c=U(t.update.rawOutput);if(r==="codex.connection")return{phase:o==="failed"?"failed":o==="completed"?"exploring":"resuming",label:s||(o==="completed"?"Codex 连接已恢复":"Codex 正在重连"),detail:c,updateType:e};if(r==="codex.error")return{phase:"failed",label:s||"Codex 执行异常",detail:c,updateType:e};const d=l(t.update.rawInput),u=a(d?.command);return s==="压缩上下文"?{phase:"thinking",label:"压缩上下文",updateType:e}:/^(?:启动|发送|恢复|等待|结束|处理)子任务/.test(s||"")?{phase:"exploring",label:s||"处理子任务",updateType:e}:u?{phase:"exploring",label:"执行命令",detail:s||u,updateType:e}:{phase:"exploring",label:"调用工具",detail:s,updateType:e}}return e==="plan"||e==="plan_update"?{phase:"thinking",label:"规划中",updateType:e}:e==="aca_context_maintenance"?{phase:"thinking",label:a(t.update.label)||"正在整理会话上下文",detail:a(t.update.detail),updateType:e}:null}function D(n){const t=f(n);return t?m(t.update):null}function m(n){const t=l(n._meta),e=l(t?.aca);return l(e?.subtask)}function i(n){if(typeof n=="string")return n;if(!n||typeof n!="object"||Array.isArray(n))return"";const t=n;return typeof t.text=="string"?t.text:""}function w(n,t,e){const r=a(t.toolCallId,t.id)||`acp.${Date.now()}`,o=S(a(t.kind,t.title)),s=h(a(t.status)),c=t.rawInput??t.input,d=t.rawOutput??t.output,u={method:"session/update",params:e,toolCallId:r,kind:o,title:a(t.title,t.kind),status:s,rawInput:c,rawOutput:d,content:t.content,locations:Array.isArray(t.locations)?t.locations.filter(p=>!!(p&&typeof p=="object"&&!Array.isArray(p))):void 0,meta:t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:void 0};return n==="tool_call"?C(u):I(u)}function T(n){return n.replace(/_/g," ")}function g(n){const t=n.replace(/\s+/g," ").trim();if(t)return t.length>120?`${t.slice(0,117)}...`:t}function U(n){if(!n||typeof n!="object"||Array.isArray(n))return;const t=n,e=t.error&&typeof t.error=="object"&&!Array.isArray(t.error)?t.error:null,r=a(e?.message,t.message),o=/reconnecting\.{3}\s*(\d+)\s*\/\s*(\d+)/i.exec(r||"");return o?`第 ${o[1]}/${o[2]} 次尝试`:/selected model is at capacity/i.test(r||"")?"所选模型当前繁忙,请稍后重试":r}function l(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:null}export{f as acpSessionUpdateFromParams,E as eventFromAcpSessionUpdate,P as statusFromAcpSessionUpdate,D as subtaskContextFromAcpSessionUpdate,i as textFromAcpContent};
@@ -1 +1 @@
1
- function x(n){const e=String(n.sessionUpdate||"");if(e==="plan_removed")return{sessionUpdate:"plan_removed",planId:c(n)};if(e!=="plan"&&e!=="plan_update")return null;const t=a(n.plan),r=g(n.entries,n.items,n.steps,n.todos,Array.isArray(n.plan)?n.plan:void 0,t?.entries,t?.items,t?.steps,t?.todos),o=i(n.markdown,l(n.content),t?.markdown,l(t?.content)),s=r?r.map(p).filter(d=>!!d).slice(0,50):u(o||"").slice(0,50);return{sessionUpdate:"plan",planId:c(n),entries:s,explanation:i(n.explanation,t?.explanation),markdown:o}}function w(n){const e=n.update.explanation||n.update.markdown;return{type:n.update.sessionUpdate,label:"plan",...e?{text:e}:{},raw:{method:n.method,params:n.params,update:n.update},atMs:n.atMs??Date.now()}}function f(n){const e=String(n||"pending").replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase();return["done","complete","completed","success"].includes(e)?"completed":["inprogress","in_progress","active","running"].includes(e)?"in_progress":["failed","error"].includes(e)?"failed":["cancelled","canceled"].includes(e)?"cancelled":"pending"}function p(n){const e=a(n);if(!e)return null;const t=i(e.content,e.step,e.text,e.title);if(!t)return null;const r=m(e.priority);return y({id:i(e.id,e.entryId,e.taskId),content:t.slice(0,4e3),status:f(e.status??e.state),priority:r})}function u(n){const e=[];for(const t of n.split(/\r?\n/)){const r=/^\s*(?:[-*]|\d+\.)\s+(?:\[([ xX~-])\]\s*)?(.+?)\s*$/.exec(t);if(!r)continue;const o=String(r[1]||"").toLowerCase(),s=String(r[2]||"").trim();s&&e.push({content:s.slice(0,4e3),status:o==="x"?"completed":o==="~"?"in_progress":o==="-"?"cancelled":"pending"})}return e}function c(n){const e=a(n.plan);return i(n.planId,n.plan_id,n.id,e?.id)}function m(n){const e=String(n||"").toLowerCase();return e==="low"||e==="medium"||e==="high"?e:void 0}function l(n){return typeof n=="string"?n.trim()||void 0:i(a(n)?.text)}function g(...n){return n.find(Array.isArray)}function i(...n){for(const e of n)if(typeof e=="string"&&e.trim())return e.trim()}function a(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:null}function y(n){for(const e of Object.keys(n))n[e]===void 0&&delete n[e];return n}export{w as createPlanEvent,x as normalizePlanSessionUpdate,f as normalizePlanStatus};
1
+ function x(n){const e=String(n.sessionUpdate||"");if(e==="plan_removed")return{sessionUpdate:"plan_removed",planId:c(n)};if(e!=="plan"&&e!=="plan_update")return null;const t=a(n.plan),r=g(n.entries,n.items,n.steps,n.todos,Array.isArray(n.plan)?n.plan:void 0,t?.entries,t?.items,t?.steps,t?.todos),o=s(n.markdown,l(n.content),t?.markdown,l(t?.content)),i=r?r.map(p).filter(d=>!!d).slice(0,50):m(o||"").slice(0,50);return{sessionUpdate:"plan",planId:c(n),entries:i,explanation:s(n.explanation,t?.explanation),markdown:o}}function w(n){const e=n.update.explanation||n.update.markdown;return{type:n.update.sessionUpdate,label:"plan",...e?{text:e}:{},raw:{method:n.method,params:n.params,update:{...n.update,...n.meta?{_meta:n.meta}:{}}},atMs:n.atMs??Date.now()}}function f(n){const e=String(n||"pending").replace(/([a-z])([A-Z])/g,"$1_$2").replace(/[-\s]+/g,"_").toLowerCase();return["done","complete","completed","success"].includes(e)?"completed":["inprogress","in_progress","active","running"].includes(e)?"in_progress":["failed","error"].includes(e)?"failed":["cancelled","canceled"].includes(e)?"cancelled":"pending"}function p(n){const e=a(n);if(!e)return null;const t=s(e.content,e.step,e.text,e.title);if(!t)return null;const r=u(e.priority);return y({id:s(e.id,e.entryId,e.taskId),content:t.slice(0,4e3),status:f(e.status??e.state),priority:r})}function m(n){const e=[];for(const t of n.split(/\r?\n/)){const r=/^\s*(?:[-*]|\d+\.)\s+(?:\[([ xX~-])\]\s*)?(.+?)\s*$/.exec(t);if(!r)continue;const o=String(r[1]||"").toLowerCase(),i=String(r[2]||"").trim();i&&e.push({content:i.slice(0,4e3),status:o==="x"?"completed":o==="~"?"in_progress":o==="-"?"cancelled":"pending"})}return e}function c(n){const e=a(n.plan);return s(n.planId,n.plan_id,n.id,e?.id)}function u(n){const e=String(n||"").toLowerCase();return e==="low"||e==="medium"||e==="high"?e:void 0}function l(n){return typeof n=="string"?n.trim()||void 0:s(a(n)?.text)}function g(...n){return n.find(Array.isArray)}function s(...n){for(const e of n)if(typeof e=="string"&&e.trim())return e.trim()}function a(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:null}function y(n){for(const e of Object.keys(n))n[e]===void 0&&delete n[e];return n}export{w as createPlanEvent,x as normalizePlanSessionUpdate,f as normalizePlanStatus};
@@ -1,6 +1,6 @@
1
- import{readFileSync as ut}from"node:fs";import{applyPatch as lt,parsePatch as it,reversePatch as dt}from"diff";import{createPlanEvent as O}from"../../plan-events.js";import{codexErrorSessionUpdate as pt}from"./connection-events.js";import{codexPlanUpdateFromNotification as F}from"./plan-events.js";const v=new Set,T=new Set;function ce(t,e,n={}){switch(t){case"item/agentMessage/delta":{const r=a(e,"delta"),o=a(e,"itemId"),s=o?n.agentMessagePhases?.get(o):"";return r?s==="commentary"?[h("agent_progress_chunk",r)]:s&&s!=="final_answer"?[]:[h("agent_message_chunk",r)]:[]}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{const r=a(e,"delta");return r?[h("agent_thought_chunk",r)]:[]}case"turn/plan/updated":{const r=n.planDeltas?.fromSnapshot(e)??F(e);return r?[r]:[]}case"item/plan/delta":{const r=n.planDeltas?.fromDelta(e);return r?[r]:[]}case"item/started":case"item/completed":{const r=m(e,"item"),o=a(r,"type");if(!r||!o||o==="userMessage"||o==="agentMessage"||o==="reasoning")return[];if(o==="exitedReviewMode"){const c=a(r,"review");return t==="item/completed"&&c?[h("agent_message_chunk",`${c}
1
+ import{readFileSync as ut}from"node:fs";import{applyPatch as it,parsePatch as dt,reversePatch as pt}from"diff";import{createPlanEvent as O}from"../../plan-events.js";import{codexErrorSessionUpdate as ft}from"./connection-events.js";import{codexPlanUpdateFromNotification as F}from"./plan-events.js";const T=new Set,v=new Set;function ce(t,e,n={}){switch(t){case"item/agentMessage/delta":{const r=a(e,"delta"),o=a(e,"itemId"),s=o?n.agentMessagePhases?.get(o):"";return r?s==="commentary"?[h("agent_progress_chunk",r)]:s&&s!=="final_answer"?[]:[h("agent_message_chunk",r)]:[]}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{const r=a(e,"delta");return r?[h("agent_thought_chunk",r)]:[]}case"turn/plan/updated":{const r=n.planDeltas?.fromSnapshot(e)??F(e);return r?[r]:[]}case"item/plan/delta":{const r=n.planDeltas?.fromDelta(e);return r?[r]:[]}case"item/started":case"item/completed":{const r=w(e,"item"),o=a(r,"type");if(!r||!o||o==="userMessage"||o==="agentMessage"||o==="reasoning")return[];if(o==="exitedReviewMode"){const l=a(r,"review");return t==="item/completed"&&l?[h("agent_message_chunk",`${l}
2
2
 
3
- `)]:[]}const s=E(t,r);return s?[s]:Rt(o)?[]:[t==="item/started"?vt(r):Tt(r)]}case"item/commandExecution/outputDelta":{const r=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),o=i(e,["delta","data","output","text"]);return!r&&!o?[]:[{sessionUpdate:"tool_call_update",toolCallId:r,kind:"execute",status:"in_progress",_meta:U(r,o)}]}case"item/commandExecution/terminalInteraction":{const r=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),o=a(e,"stdin");return r?[{sessionUpdate:"tool_call_update",toolCallId:r,kind:"execute",status:"in_progress",_meta:U(r,`
3
+ `)]:[]}const s=E(t,r);return s?[s]:jt(o)?[]:[t==="item/started"?vt(r):$t(r)]}case"item/commandExecution/outputDelta":{const r=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),o=i(e,["delta","data","output","text"]);return!r&&!o?[]:[{sessionUpdate:"tool_call_update",toolCallId:r,kind:"execute",status:"in_progress",_meta:U(r,o)}]}case"item/commandExecution/terminalInteraction":{const r=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),o=a(e,"stdin");return r?[{sessionUpdate:"tool_call_update",toolCallId:r,kind:"execute",status:"in_progress",_meta:U(r,`
4
4
  ${o}
5
5
  `)}]:[]}case"item/mcpToolCall/progress":{const r=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),o=a(e,"message").trim();return!r||!o?[]:[{sessionUpdate:"tool_call_update",toolCallId:r,kind:"execute",status:"in_progress",_meta:{mcp_output_delta:{data:o,terminal_id:r}}}]}case"turn/diff/updated":{const r=a(e,"diff");return r?[{sessionUpdate:"tool_call_update",toolCallId:a(e,"turnId")||"codex.diff",kind:"edit",title:"Diff updated",status:"completed",content:[{type:"diff",oldText:null,newText:r}],rawOutput:{diff:r}}]:[]}case"thread/tokenUsage/updated":return[{sessionUpdate:"usage_update",_meta:{codex:e}}];case"thread/name/updated":return[{sessionUpdate:"session_info_update",title:a(e,"threadName")||null}];case"thread/status/changed":return[b({threadStatus:a(e,"status")})];case"thread/archived":return[b({archived:!0})];case"thread/unarchived":return[b({archived:!1})];case"thread/closed":return[b({closed:!0})];case"account/rateLimits/updated":return[V(e)];case"account/updated":return[b({account:d(e)??e})];case"configWarning":{const r=a(e,"summary"),o=a(e,"details");return[h("agent_message_chunk",`Config warning: ${r}${o?`
6
6
 
@@ -12,18 +12,18 @@ ${o}`:""}
12
12
 
13
13
  `)];case"thread/compacted":return[h("agent_message_chunk",`*Context compacted to fit the model's context window.*
14
14
 
15
- `)];case"fuzzyFileSearch/sessionUpdated":return[N(e)];case"fuzzyFileSearch/sessionCompleted":return[B(e)];case"item/autoApprovalReview/started":return[k(e,"started")];case"item/autoApprovalReview/completed":return[k(e,"completed")];case"error":return[pt(e)];default:return R(t,e),[]}}function ue(t,e,n,r={}){switch(t){case"item/agentMessage/delta":{const o=a(e,"delta"),s=a(e,"itemId"),c=s?r.agentMessagePhases?.get(s):"";if(!o||c&&c!=="commentary"&&c!=="final_answer")break;const l=c==="commentary"?"agent_progress_chunk":"agent_message_chunk",f=c==="commentary"?"progress":"message";n.pushStatus("thinking",c==="commentary"?"处理中":"生成回复中",C(o),t),n.pushUpdate({type:l,label:f,text:o,raw:{method:t,params:e,update:h(l,o)},atMs:Date.now()});break}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{const o=a(e,"delta");n.pushStatus("thinking","思考中",C(o),t),n.pushUpdate({type:"agent_thought_chunk",label:"thought",...o?{text:o}:{},raw:{method:t,params:e},atMs:Date.now()});break}case"turn/plan/updated":{const o=r.planDeltas?.fromSnapshot(e)??F(e);if(!o)break;n.pushStatus("thinking","规划中",void 0,t),n.pushUpdate(O({update:o,method:t,params:e}));break}case"item/plan/delta":{const o=r.planDeltas?.fromDelta(e);if(!o)break;n.pushStatus("thinking","规划中",void 0,t),n.pushUpdate(O({update:o,method:t,params:e}));break}case"item/started":case"item/completed":{const o=m(e,"item"),s=a(o,"type"),c=E(t,o);if(!c){const _=$(s);(s==="reasoning"||s==="agentMessage")&&n.pushStatus(j(s),_,gt(o),t);break}const l=ht(t,e,o),f=ft(s,c);n.pushStatus(j(s),x(s),void 0,t),n.pushUpdate({type:t==="item/started"?"tool_call":"tool_call_update",label:f,status:i(c,["status"])||(t==="item/started"?"in_progress":"completed"),toolCallId:a(o,"id"),raw:{method:t,params:e,tool:l,update:c},atMs:Date.now()});break}case"item/commandExecution/outputDelta":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),s=i(e,["delta","data","output","text"]);if(!o&&!s)break;n.pushStatus("exploring","执行命令",void 0,t),n.pushUpdate({type:"tool_call_update",label:"tool update",toolCallId:o,raw:{method:t,params:e,update:{sessionUpdate:"tool_call_update",toolCallId:o,_meta:U(o,s)}},atMs:Date.now()});break}case"item/commandExecution/terminalInteraction":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),c=`
15
+ `)];case"fuzzyFileSearch/sessionUpdated":return[N(e)];case"fuzzyFileSearch/sessionCompleted":return[B(e)];case"item/autoApprovalReview/started":return[k(e,"started")];case"item/autoApprovalReview/completed":return[k(e,"completed")];case"error":return[ft(e)];default:return R(t,e),[]}}function ue(t,e,n,r={}){switch(t){case"item/agentMessage/delta":{const o=a(e,"delta"),s=a(e,"itemId"),l=s?r.agentMessagePhases?.get(s):"";if(!o||l&&l!=="commentary"&&l!=="final_answer")break;const u=l==="commentary"?"agent_progress_chunk":"agent_message_chunk",p=l==="commentary"?"progress":"message";n.pushStatus("thinking",l==="commentary"?"处理中":"生成回复中",C(o),t),n.pushUpdate({type:u,label:p,text:o,raw:{method:t,params:e,update:h(u,o)},atMs:Date.now()});break}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{const o=a(e,"delta");n.pushStatus("thinking","思考中",C(o),t),n.pushUpdate({type:"agent_thought_chunk",label:"thought",...o?{text:o}:{},raw:{method:t,params:e},atMs:Date.now()});break}case"turn/plan/updated":{const o=r.planDeltas?.fromSnapshot(e)??F(e);if(!o)break;n.pushStatus("thinking","规划中",void 0,t),n.pushUpdate(O({update:o,method:t,params:e}));break}case"item/plan/delta":{const o=r.planDeltas?.fromDelta(e);if(!o)break;n.pushStatus("thinking","规划中",void 0,t),n.pushUpdate(O({update:o,method:t,params:e}));break}case"item/started":case"item/completed":{const o=w(e,"item"),s=a(o,"type"),l=E(t,o);if(!l){const _=$(s);(s==="reasoning"||s==="agentMessage")&&n.pushStatus(j(s),_,ht(o),t);break}const u=_t(t,e,o),p=gt(s,l);n.pushStatus(j(s),x(s),void 0,t),n.pushUpdate({type:t==="item/started"?"tool_call":"tool_call_update",label:p,status:i(l,["status"])||(t==="item/started"?"in_progress":"completed"),toolCallId:a(o,"id"),raw:{method:t,params:e,tool:u,update:l},atMs:Date.now()});break}case"item/commandExecution/outputDelta":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),s=i(e,["delta","data","output","text"]);if(!o&&!s)break;n.pushStatus("exploring","执行命令",void 0,t),n.pushUpdate({type:"tool_call_update",label:"tool update",toolCallId:o,raw:{method:t,params:e,update:{sessionUpdate:"tool_call_update",toolCallId:o,_meta:U(o,s)}},atMs:Date.now()});break}case"item/commandExecution/terminalInteraction":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),l=`
16
16
  ${a(e,"stdin")}
17
- `;if(!o)break;n.pushStatus("exploring","执行命令",void 0,t),n.pushUpdate({type:"tool_call_update",label:"tool update",toolCallId:o,raw:{method:t,params:e,update:{sessionUpdate:"tool_call_update",toolCallId:o,_meta:U(o,c)}},atMs:Date.now()});break}case"item/mcpToolCall/progress":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),s=a(e,"message").trim();if(!o||!s)break;n.pushStatus("exploring","调用工具",void 0,t),n.pushUpdate({type:"tool_call_update",label:"tool update",toolCallId:o,raw:{method:t,params:e,update:{sessionUpdate:"tool_call_update",toolCallId:o,_meta:{mcp_output_delta:{data:s,terminal_id:o}}}},atMs:Date.now()});break}case"turn/diff/updated":n.pushStatus("exploring","编辑文件中","diff",t),n.pushUpdate({type:"diff",label:"diff",text:a(e,"diff"),raw:{method:t,params:e},atMs:Date.now()});break;case"thread/tokenUsage/updated":n.pushUpdate({type:"usage_update",label:"usage",raw:{method:t,params:e},atMs:Date.now()});break;case"thread/name/updated":M(n,{method:t,params:e,type:"session_info_update",label:"session_info",update:{sessionUpdate:"session_info_update",title:a(e,"threadName")||null}});break;case"thread/status/changed":I(n,t,e,{threadStatus:a(e,"status")});break;case"thread/archived":I(n,t,e,{archived:!0});break;case"thread/unarchived":I(n,t,e,{archived:!1});break;case"thread/closed":I(n,t,e,{closed:!0});break;case"account/rateLimits/updated":M(n,{method:t,params:e,type:"session_info_update",label:"rate_limit",update:V(e)});break;case"configWarning":{const o=a(e,"summary"),s=a(e,"details"),c=`Config warning: ${o}${s?`
17
+ `;if(!o)break;n.pushStatus("exploring","执行命令",void 0,t),n.pushUpdate({type:"tool_call_update",label:"tool update",toolCallId:o,raw:{method:t,params:e,update:{sessionUpdate:"tool_call_update",toolCallId:o,_meta:U(o,l)}},atMs:Date.now()});break}case"item/mcpToolCall/progress":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),s=a(e,"message").trim();if(!o||!s)break;n.pushStatus("exploring","调用工具",void 0,t),n.pushUpdate({type:"tool_call_update",label:"tool update",toolCallId:o,raw:{method:t,params:e,update:{sessionUpdate:"tool_call_update",toolCallId:o,_meta:{mcp_output_delta:{data:s,terminal_id:o}}}},atMs:Date.now()});break}case"turn/diff/updated":n.pushStatus("exploring","编辑文件中","diff",t),n.pushUpdate({type:"diff",label:"diff",text:a(e,"diff"),raw:{method:t,params:e},atMs:Date.now()});break;case"thread/tokenUsage/updated":n.pushUpdate({type:"usage_update",label:"usage",raw:{method:t,params:e},atMs:Date.now()});break;case"thread/name/updated":M(n,{method:t,params:e,type:"session_info_update",label:"session_info",update:{sessionUpdate:"session_info_update",title:a(e,"threadName")||null}});break;case"thread/status/changed":I(n,t,e,{threadStatus:a(e,"status")});break;case"thread/archived":I(n,t,e,{archived:!0});break;case"thread/unarchived":I(n,t,e,{archived:!1});break;case"thread/closed":I(n,t,e,{closed:!0});break;case"account/rateLimits/updated":M(n,{method:t,params:e,type:"session_info_update",label:"rate_limit",update:V(e)});break;case"configWarning":{const o=a(e,"summary"),s=a(e,"details"),l=`Config warning: ${o}${s?`
18
18
 
19
19
  ${s}`:""}
20
20
 
21
- `;n.pushUpdate({type:"agent_message_chunk",label:"message",text:c,raw:{method:t,params:e,update:h("agent_message_chunk",c)},atMs:Date.now()});break}case"warning":{const o=`Warning: ${a(e,"message")}
21
+ `;n.pushUpdate({type:"agent_message_chunk",label:"message",text:l,raw:{method:t,params:e,update:h("agent_message_chunk",l)},atMs:Date.now()});break}case"warning":{const o=`Warning: ${a(e,"message")}
22
22
 
23
23
  `;n.pushUpdate({type:"agent_message_chunk",label:"message",text:o,raw:{method:t,params:e,update:h("agent_message_chunk",o)},atMs:Date.now()});break}case"model/rerouted":{const o=`Model rerouted from ${a(e,"fromModel")} to ${a(e,"toModel")} (${a(e,"reason")}).
24
24
 
25
25
  `;n.pushStatus("thinking","模型已切换",C(o),t),n.pushUpdate({type:"agent_thought_chunk",label:"thought",text:o,raw:{method:t,params:e,update:h("agent_thought_chunk",o)},atMs:Date.now()});break}case"thread/compacted":{const o=`*Context compacted to fit the model's context window.*
26
26
 
27
- `;n.pushStatus("thinking","上下文已压缩",void 0,t),n.pushUpdate({type:"agent_message_chunk",label:"message",text:o,raw:{method:t,params:e,update:h("agent_message_chunk",o)},atMs:Date.now()});break}case"fuzzyFileSearch/sessionUpdated":{const o=N(e);n.pushStatus("exploring",a(o,"title")||"Search",yt(e),t),n.pushUpdate({type:o.sessionUpdate==="tool_call"?"tool_call":"tool_call_update",label:a(o,"title")||"Search",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"fuzzyFileSearch/sessionCompleted":{const o=B(e);n.pushUpdate({type:"tool_call_update",label:"Search",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"item/autoApprovalReview/started":{const o=k(e,"started");n.pushStatus("exploring","Guardian Review",Ut(e),t),n.pushUpdate({type:o.sessionUpdate==="tool_call"?"tool_call":"tool_call_update",label:"Guardian Review",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"item/autoApprovalReview/completed":{const o=k(e,"completed");n.pushUpdate({type:o.sessionUpdate==="tool_call"?"tool_call":"tool_call_update",label:"Guardian Review",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"account/updated":I(n,t,e,{account:d(e)??e});break;case"turn/started":n.pushStatus("thinking","思考中",void 0,t);break;case"turn/completed":n.pushStatus("completed","已完成",void 0,t);break;case"error":n.pushStatus("failed","执行失败",C(JSON.stringify(e)),t),n.pushUpdate({type:"error",label:"error",text:C(JSON.stringify(e)),raw:{method:t,params:e},atMs:Date.now()});break;default:R(t,e);break}}function R(t,e){if(process.env.ACA_CODEX_PROTOCOL_DEBUG!=="1")return;const n=d(e);console.debug("[codex] unhandled notification",{method:t,keys:n?Object.keys(n).slice(0,20):[],itemType:a(m(n,"item"),"type")||void 0})}function le(t){return(Array.isArray(t?.items)?t.items:[]).map(n=>a(n,"type")!=="agentMessage"?"":a(n,"text")).filter(Boolean).join(`
28
- `).trim()}function $(t){switch(t){case"commandExecution":return"执行命令中";case"fileChange":return"编辑文件中";case"mcpToolCall":case"dynamicToolCall":return"调用工具中";case"collabAgentToolCall":return"处理子任务中";case"contextCompaction":return"压缩上下文中";case"webSearch":return"搜索中";case"imageGeneration":return"生成图片中";case"reasoning":return"思考中";case"agentMessage":return"生成回复中";default:return"处理中"}}function x(t){switch(t){case"commandExecution":return"执行命令";case"fileChange":return"编辑文件";case"mcpToolCall":case"dynamicToolCall":return"调用工具";case"collabAgentToolCall":return"处理子任务";case"contextCompaction":return"压缩上下文";case"webSearch":case"fuzzyFileSearch":return"搜索";case"imageView":return"查看图片";case"imageGeneration":return"生成图片";default:return $(t)}}function ft(t,e){const n=i(e,["kind"]);if(n==="read")return i(e,["title"])||"读取文件";if(n==="search")return i(e,["title"])||"搜索";if(n==="edit")return"编辑文件";if(n==="execute"){const r=d(e.rawInput);return a(r,"command")?"执行命令":i(e,["title"])||x(t)}return n==="think"?"思考中":n==="other"&&i(e,["title"])||x(t)}function j(t){return t==="imageGeneration"?"image_generation":t==="reasoning"||t==="agentMessage"||t==="plan"?"thinking":"exploring"}function gt(t){if(t)for(const e of["command","path","tool","server","query","text"]){const n=a(t,e);if(n)return C(n)}}function ht(t,e,n){const r=a(n,"type"),o=a(n,"id")||a(e,"itemId"),s=i(n,["rawInput","raw_input","command","query","path","text","input"]),c=r==="commandExecution"?i(n,["command","rawInput","raw_input"]):"",l=ot(n),f=i(n,["path","filePath","file_path","relativePath","absolutePath"])||l.path,_=i(n,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),A=p(n,"commandActions")||p(n,"command_actions")||p(n,"actions")||P(n),rt=Yt(r,_,n),st=Zt(r,{command:c,path:f,rawInput:s,item:n}),ct=C(te(c,f,s,_));return u({id:o,type:r,method:t,displayName:st,rawInput:s,raw_input:s,command:c,path:f,action:i(n,["action","changeType","operation"])||l.action,commandActions:A,command_actions:A.length>0?A:void 0,aggregatedOutput:_,aggregated_output:_,formatted_output:rt,summary:ct})}function E(t,e){if(!e)return null;switch(a(e,"type")){case"commandExecution":return t==="item/started"?xt(e):kt(e);case"fileChange":return t==="item/started"?St(e):At(e);case"mcpToolCall":return t==="item/started"?$t(e):Mt(e);case"dynamicToolCall":return t==="item/started"?Dt(e):Pt(e);case"collabAgentToolCall":return t==="item/started"?zt(e):Ot(e);case"contextCompaction":return Ft(t,e);case"webSearch":return t==="item/started"?jt(e):Et(e);case"imageView":return Bt(e);case"imageGeneration":return t==="item/started"?Gt(e):Nt(e);default:return null}}function M(t,e){t.pushUpdate({type:e.type,label:e.label,raw:{method:e.method,params:e.params,update:e.update},atMs:Date.now()})}function I(t,e,n,r){M(t,{method:e,params:n,type:"session_info_update",label:"session_info",update:{sessionUpdate:"session_info_update",_meta:{codex:r}}})}function b(t){return{sessionUpdate:"session_info_update",_meta:{codex:t}}}function h(t,e){return{sessionUpdate:t,content:{type:"text",text:e}}}function G(t){return`fuzzyFileSearch.${t}`}function N(t){const e=a(t,"sessionId"),n=G(e),r=!v.has(n);v.add(n);const o=a(t,"query"),s=Y(o,""),c=_t(t);return u(r?{sessionUpdate:"tool_call",toolCallId:n,kind:"search",title:s,status:"in_progress",locations:c,rawInput:{query:o}}:{sessionUpdate:"tool_call_update",toolCallId:n,title:s,status:"in_progress",locations:c})}function B(t){const e=a(t,"sessionId"),n=G(e);return v.delete(n),{sessionUpdate:"tool_call_update",toolCallId:n,status:"completed"}}function _t(t){const n=(p(d(t),"files")??[]).map(r=>{const o=d(r);if(!o)return"";const s=a(o,"path"),c=a(o,"root");return s?s.startsWith("/")||!c?s:`${c.replace(/\/+$/,"")}/${s.replace(/^\/+/,"")}`:""}).filter(Boolean).map(r=>({path:r}));return n.length>0?n:void 0}function yt(t){const e=a(t,"query"),r=(p(d(t),"files")??[]).length;if(e&&r)return`${e} · ${r} files`;if(e)return e;if(r)return`${r} files`}function mt(t){return`guardian_assessment:${t}`}function k(t,e){const n=a(t,"reviewId"),r=mt(n),o=e==="started"&&!T.has(n);e==="started"&&T.add(n),e==="completed"&&T.delete(n);const s=m(t,"review")??{},c={sessionUpdate:o?"tool_call":"tool_call_update",toolCallId:r,status:wt(a(s,"status")),content:Ct(s,m(t,"action")),...o?{kind:"think",title:"Guardian Review",rawInput:t}:{rawOutput:t}};return u(c)}function wt(t){switch(t){case"inProgress":return"in_progress";case"approved":return"completed";case"denied":case"aborted":case"timedOut":return"failed";default:return t||"in_progress"}}function Ct(t,e){const n=[`Status: ${L(a(t,"status"))}`],r=W(e);r&&n.push(`Action: ${r}`);const o=a(t,"riskLevel");o&&n.push(`Risk: ${o}`);const s=a(t,"userAuthorization");s&&n.push(`Authorization: ${s}`);const c=a(t,"rationale").trim();return c&&n.push(`Rationale: ${c}`),[{type:"content",content:{type:"text",text:n.join(`
29
- `)}}]}function L(t){switch(t){case"inProgress":return"In progress";case"approved":return"Approved";case"denied":return"Denied";case"aborted":return"Aborted";case"timedOut":return"Timed out";default:return t||"Unknown"}}function W(t){if(!t)return"";const e=a(t,"type");if(e==="command")return[q(a(t,"source")),a(t,"command")].filter(Boolean).join(" ");if(e==="execve"){const n=p(t,"argv")?.map(s=>g(s)).filter(Boolean)??[],r=a(t,"program"),o=n.length>0?n:[r].filter(Boolean);return[q(a(t,"source")),It(o)].filter(Boolean).join(" ")}if(e==="applyPatch"){const n=p(t,"files")?.map(r=>g(r)).filter(Boolean)??[];return n.length===1?`apply_patch touching ${n[0]}`:`apply_patch touching ${n.length} files`}if(e==="networkAccess"){const n=a(t,"target")||a(t,"host");return n?`network access to ${n}`:"network access"}if(e==="mcpToolCall"){const n=a(t,"connectorName")||a(t,"server");return`MCP ${a(t,"toolName")} on ${n}`.trim()}return e==="requestPermissions"?a(t,"reason")||"request additional permissions":e}function q(t){return t==="shell"?"shell":t==="unifiedExec"?"exec":t}function It(t){return t.map(bt).join(" ")}function bt(t){return t.length===0?"''":/^[A-Za-z0-9_/:=+.,@%-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}function Ut(t){const e=m(t,"review"),n=e?L(a(e,"status")):"",r=W(m(t,"action"));return[n,r].filter(Boolean).join(" · ")||void 0}function V(t){const e=m(t,"rateLimits")??{},n=m(e,"primary"),r=m(e,"secondary");return u({sessionUpdate:"session_info_update",_meta:{rateLimits:u({planName:a(e,"planType"),limitName:a(e,"limitName"),limitId:a(e,"limitId"),fiveHour:z(n,"usedPercent")??null,sevenDay:z(r,"usedPercent")??null,fiveHourResetAt:a(n,"resetsAt")||null,sevenDayResetAt:a(r,"resetsAt")||null,raw:e})}})}function xt(t){const e=a(t,"id"),n=a(t,"cwd"),r=a(t,"command"),o=Z(t),s=o.length===1?d(o[0]):null;if(s){const c=a(s,"type");if(c==="read"){const l=a(s,"path")||a(s,"name");return u({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"read",title:`Read file '${l}'`,locations:l?[{path:l}]:void 0})}if(c==="search"){const l=a(s,"query"),f=a(s,"path");return u({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"search",title:Y(l,f)})}if(c==="listFiles"){const l=a(s,"path");return u({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"read",title:l?`List files in '${l}'`:"List files"})}}return Vt({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"execute",title:Kt(r),rawInput:u({command:r,cwd:n})},e,n)}function kt(t){const e=a(t,"id"),n=i(t,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),r=z(t,"exitCode"),o={sessionUpdate:"tool_call_update",toolCallId:e,status:w(a(t,"status"),r),rawOutput:u({formatted_output:n,exit_code:r})};return Jt(t)&&(o._meta={...n?U(e,n):{},terminal_exit:{exit_code:r,signal:null,terminal_id:e}}),u(o)}function St(t){const e=a(t,"id"),n=et(t);return u({sessionUpdate:"tool_call",toolCallId:e,title:"Editing files",kind:"edit",status:y(a(t,"status")),content:n,locations:Ht(t),rawInput:{changes:P(t)}})}function At(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:w(a(t,"status")),content:et(t)})}function vt(t){const e=i(t,["tool","name","server"]);return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:y(a(t,"status")),rawInput:d(t)})}function Tt(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:w(a(t,"status")),rawOutput:d(t)})}function $t(t){const e=a(t,"server"),n=a(t,"tool");return u({...H(t,`mcp.${e}.${n}`,Q(e,n,t.arguments),X(t.result,t.error)),_meta:{is_mcp_tool_call:!0}})}function Mt(t){const e=a(t,"server"),n=a(t,"tool");return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:w(a(t,"status")),rawInput:Q(e,n,t.arguments),rawOutput:X(t.result,t.error)})}function Dt(t){const e=a(t,"namespace"),n=a(t,"tool");return H(t,J(e,n),{namespace:e,tool:n,arguments:t.arguments},void 0)}function Pt(t){const e=a(t,"namespace"),n=a(t,"tool");return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),kind:"execute",title:J(e,n),status:w(a(t,"status")),rawInput:{namespace:e,tool:n,arguments:t.arguments},rawOutput:u({success:t.success,contentItems:t.contentItems,durationMs:t.durationMs})})}function zt(t){const e=a(t,"tool");return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"other",title:K(e),status:y(a(t,"status")),rawInput:{tool:e,arguments:u({receiverThreadIds:p(t,"receiverThreadIds"),prompt:a(t,"prompt"),model:a(t,"model"),reasoningEffort:a(t,"reasoningEffort")})},_meta:{aca:{processKind:"subtask",action:e}}})}function Ot(t){const e=a(t,"tool");return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),kind:"other",title:K(e),status:w(a(t,"status")),rawOutput:u({agentsStates:t.agentsStates,receiverThreadIds:p(t,"receiverThreadIds")}),_meta:{aca:{processKind:"subtask",action:e}}})}function Ft(t,e){return{sessionUpdate:t==="item/started"?"tool_call":"tool_call_update",toolCallId:a(e,"id")||"codex.context_compaction",kind:"think",title:"压缩上下文",status:t==="item/started"?"in_progress":w(a(e,"status")),_meta:{aca:{processKind:"context_compaction"}}}}function J(t,e){return[t,e].filter(Boolean).join(".")||"内部工具"}function K(t){switch(t){case"spawnAgent":return"启动子任务";case"sendInput":return"发送子任务指令";case"resumeAgent":return"恢复子任务";case"wait":return"等待子任务";case"closeAgent":return"结束子任务";default:return"处理子任务"}}function Rt(t){return["hookPrompt","sleep","subAgentActivity","enteredReviewMode","exitedReviewMode","plan"].includes(t)}function H(t,e,n,r){return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:y(a(t,"status")),rawInput:n,rawOutput:r})}function Q(t,e,n){return{server:t,tool:e,arguments:n}}function X(t,e){if(!(t===null&&e===null)&&!(t===void 0&&e===void 0))return{result:t,error:e}}function jt(t){return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"search",title:tt(t),status:y(a(t,"status")),rawInput:d(t)})}function Et(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),title:tt(t),status:w(a(t,"status")),rawInput:d(t)})}function Gt(t){return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"other",title:"Image generation",status:"in_progress",rawInput:{id:a(t,"id")}})}function Nt(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:Lt(a(t,"status")),content:Wt(t),rawOutput:qt(t)})}function Bt(t){const e=a(t,"path");return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"read",title:`View Image ${e}`,status:"completed",content:[{type:"content",content:{type:"resource_link",name:e,uri:e}}],locations:[{path:e}],rawInput:{path:e}})}function Lt(t){return w(t)}function Wt(t){const e=d(t.result),n=i(e,["url","uri","path"]);if(n)return[{type:"content",content:{type:"resource_link",name:n,uri:n}}]}function qt(t){const e={status:t.status,revisedPrompt:t.revisedPrompt,result:t.result};return"savedPath"in t&&(e.savedPath=t.savedPath??null),e}function Vt(t,e,n){return u({...t,content:[{type:"terminal",terminalId:e}],_meta:{terminal_info:{cwd:n,terminal_id:e}}})}function Jt(t){const e=Z(t),n=e.length===1?d(e[0]):null;return!n||a(n,"type")==="unknown"}function Z(t){return p(t,"commandActions")||p(t,"command_actions")||p(t,"actions")||[]}function y(t){switch(t){case"inProgress":case"in_progress":case"started":case"":return"in_progress";case"completed":return"completed";case"failed":case"declined":return"failed";case"cancelled":case"canceled":return"cancelled";default:return t}}function w(t,e){const n=y(t);return n==="failed"||n==="cancelled"?n:e!=null?e===0?"completed":"failed":n==="in_progress"?"completed":n}function Kt(t){const e=t.replace(/^(?:\/bin\/)?(?:bash|zsh|sh)\s+(?:-[lc]+\s+)?/,"");return e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function U(t,e){return{terminal_output_delta:{data:e,terminal_id:t}}}function Y(t,e){return t&&e?`Search for '${t}' in ${e}`:t?`Search for '${t}'`:e?`Search in '${e}'`:"Search"}function tt(t){const e=d(t.action);if(!e){const r=a(t,"query");return r?`Web search: ${r}`:"Web search"}const n=a(e,"type");if(n==="search"){const r=p(e,"queries")?.map(s=>g(s)).filter(Boolean)??[],o=a(e,"query")||(r.length>0?r.join(", "):"")||a(t,"query");return o?`Web search: ${o}`:"Web search"}if(n==="openPage"){const r=a(e,"url");return r?`Open page: ${r}`:"Open page"}if(n==="findInPage"){const r=a(e,"pattern")?` for '${a(e,"pattern")}'`:"",o=a(e,"url")?` in ${a(e,"url")}`:"";return`Find in page${r}${o}`.trim()}return"Web search"}function Ht(t){const e=P(t).map(n=>d(n)).map(n=>a(n,"path")).filter(Boolean).map(n=>({path:n}));return e.length>0?e:void 0}function et(t){const n=(p(t,"changes")??[]).map(r=>{const o=d(r);if(!o)return null;const s=g(o.path),c=o.kind&&typeof o.kind=="object"&&!Array.isArray(o.kind)?g(o.kind.type):g(o.kind),l=g(o.diff);return c==="add"?u({type:"diff",oldText:null,newText:l,path:s,_meta:{kind:"add"}}):c==="delete"?u({type:"diff",oldText:l,newText:"",path:s,_meta:{kind:"delete"}}):Qt(o,s,l,c)}).filter(Boolean);return n.length>0?n:void 0}function Qt(t,e,n,r){const o=t.kind&&typeof t.kind=="object"&&!Array.isArray(t.kind)?g(t.kind.move_path):"",s=Xt(n),c=nt(e);if(c!==null){const l=D(c,s);if(l!==!1)return S(o||e,c,l,r||"update");const f=at(s);if(f){const _=D(c,f);if(_!==!1)return S(e,_,c,r||"update")}}if(o){const l=nt(o),f=at(s);if(l!==null&&f){const _=D(l,f);if(_!==!1)return S(o,_,l,r||"update")}}return S(o||e,null,s,r||"update")}function S(t,e,n,r){return u({type:"diff",oldText:e,newText:n,path:t,_meta:{kind:r}})}function nt(t){try{return ut(t,"utf8")}catch{return null}}function Xt(t){return t.replace(/\n\nMoved to: .*$/,"")}function at(t){try{const[e]=it(t);return e?dt(e):null}catch{return null}}function D(t,e){try{return lt(t,e)}catch{return!1}}function Zt(t,e){if(t==="commandExecution")return"执行命令";if(t==="fileChange")return e.path?`编辑文件: ${ee(e.path)}`:"编辑文件";if(t==="webSearch")return e.rawInput?`搜索: ${C(e.rawInput)}`:"搜索";if(t==="mcpToolCall"||t==="dynamicToolCall"){const n=i(e.item,["tool","name","server"]);return n?`调用工具: ${n}`:"调用工具"}return $(t)}function Yt(t,e,n){if(e)return e;if(t==="fileChange"){const r=ot(n),o=i(n,["path","filePath","file_path","relativePath","absolutePath"])||r.path;return[i(n,["action","changeType","operation"])||r.action,o].filter(Boolean).join(" ")}return""}function ot(t){const e=p(t,"changes")??[];for(const n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;const r=n,o=g(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?g(r.kind.type):g(r.kind);if(o||s)return{path:o,action:s}}return{path:"",action:""}}function P(t){return(p(t,"changes")??[]).map(n=>{if(!n||typeof n!="object"||Array.isArray(n))return null;const r=n,o=g(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?g(r.kind.type):g(r.kind);return!o&&!s?null:u({type:s||"edit",path:o})}).filter(Boolean).slice(0,50)}function i(t,e){if(!t)return"";for(const n of e){const r=g(t[n]);if(r)return r}return""}function g(t){if(typeof t=="string"&&t.trim())return t.trim();if(typeof t=="number"||typeof t=="boolean")return String(t);if(t&&typeof t=="object")try{const e=JSON.stringify(t);return e.length>2?e:""}catch{return""}return""}function p(t,e){const n=t?.[e];return Array.isArray(n)?n.slice(0,50):null}function te(...t){return t.find(e=>e.trim())||""}function ee(t){return t.replace(/\\/g,"/").split("/").filter(Boolean).pop()||t}function u(t){for(const e of Object.keys(t)){const n=t[e];(n===void 0||n===""||Array.isArray(n)&&n.length===0)&&delete t[e]}return t}function m(t,e){if(!t||typeof t!="object"||Array.isArray(t))return null;const n=t[e];return!n||typeof n!="object"||Array.isArray(n)?null:n}function d(t){return!t||typeof t!="object"||Array.isArray(t)?null:t}function a(t,e){if(!t||typeof t!="object"||Array.isArray(t))return"";const n=t[e];return typeof n=="string"?n:""}function z(t,e){if(!t||typeof t!="object"||Array.isArray(t))return;const n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function C(t){if(typeof t!="string")return;const e=t.replace(/\s+/g," ").trim();if(e)return e.length>120?`${e.slice(0,117)}...`:e}export{ce as codexAcpSessionUpdatesFromNotification,le as extractAssistantTextFromTurn,ue as mapCodexNotification};
27
+ `;n.pushStatus("thinking","上下文已压缩",void 0,t),n.pushUpdate({type:"agent_message_chunk",label:"message",text:o,raw:{method:t,params:e,update:h("agent_message_chunk",o)},atMs:Date.now()});break}case"fuzzyFileSearch/sessionUpdated":{const o=N(e);n.pushStatus("exploring",a(o,"title")||"Search",wt(e),t),n.pushUpdate({type:o.sessionUpdate==="tool_call"?"tool_call":"tool_call_update",label:a(o,"title")||"Search",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"fuzzyFileSearch/sessionCompleted":{const o=B(e);n.pushUpdate({type:"tool_call_update",label:"Search",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"item/autoApprovalReview/started":{const o=k(e,"started");n.pushStatus("exploring","Guardian Review",xt(e),t),n.pushUpdate({type:o.sessionUpdate==="tool_call"?"tool_call":"tool_call_update",label:"Guardian Review",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"item/autoApprovalReview/completed":{const o=k(e,"completed");n.pushUpdate({type:o.sessionUpdate==="tool_call"?"tool_call":"tool_call_update",label:"Guardian Review",status:a(o,"status"),toolCallId:a(o,"toolCallId"),raw:{method:t,params:e,update:o},atMs:Date.now()});break}case"account/updated":I(n,t,e,{account:d(e)??e});break;case"turn/started":n.pushStatus("thinking","思考中",void 0,t);break;case"turn/completed":n.pushStatus("completed","已完成",void 0,t);break;case"error":n.pushStatus("failed","执行失败",C(JSON.stringify(e)),t),n.pushUpdate({type:"error",label:"error",text:C(JSON.stringify(e)),raw:{method:t,params:e},atMs:Date.now()});break;default:R(t,e);break}}function R(t,e){if(process.env.ACA_CODEX_PROTOCOL_DEBUG!=="1")return;const n=d(e);console.debug("[codex] unhandled notification",{method:t,keys:n?Object.keys(n).slice(0,20):[],itemType:a(w(n,"item"),"type")||void 0})}function ie(t){return(Array.isArray(t?.items)?t.items:[]).map(n=>a(n,"type")!=="agentMessage"?"":a(n,"text")).filter(Boolean).join(`
28
+ `).trim()}function $(t){switch(t){case"commandExecution":return"执行命令中";case"fileChange":return"编辑文件中";case"mcpToolCall":case"dynamicToolCall":return"调用工具中";case"collabAgentToolCall":case"collabToolCall":return"处理子任务中";case"contextCompaction":return"压缩上下文中";case"webSearch":return"搜索中";case"imageGeneration":return"生成图片中";case"reasoning":return"思考中";case"agentMessage":return"生成回复中";default:return"处理中"}}function x(t){switch(t){case"commandExecution":return"执行命令";case"fileChange":return"编辑文件";case"mcpToolCall":case"dynamicToolCall":return"调用工具";case"collabAgentToolCall":case"collabToolCall":return"处理子任务";case"contextCompaction":return"压缩上下文";case"webSearch":case"fuzzyFileSearch":return"搜索";case"imageView":return"查看图片";case"imageGeneration":return"生成图片";default:return $(t)}}function gt(t,e){const n=i(e,["kind"]);if(n==="read")return i(e,["title"])||"读取文件";if(n==="search")return i(e,["title"])||"搜索";if(n==="edit")return"编辑文件";if(n==="execute"){const r=d(e.rawInput);return a(r,"command")?"执行命令":i(e,["title"])||x(t)}return n==="think"?"思考中":n==="other"&&i(e,["title"])||x(t)}function j(t){return t==="imageGeneration"?"image_generation":t==="reasoning"||t==="agentMessage"||t==="plan"?"thinking":"exploring"}function ht(t){if(t)for(const e of["command","path","tool","server","query","text"]){const n=a(t,e);if(n)return C(n)}}function _t(t,e,n){const r=a(n,"type"),o=a(n,"id")||a(e,"itemId"),s=i(n,["rawInput","raw_input","command","query","path","text","input"]),l=r==="commandExecution"?i(n,["command","rawInput","raw_input"]):"",u=rt(n),p=i(n,["path","filePath","file_path","relativePath","absolutePath"])||u.path,_=i(n,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),A=g(n,"commandActions")||g(n,"command_actions")||g(n,"actions")||P(n),st=te(r,_,n),lt=Yt(r,{command:l,path:p,rawInput:s,item:n}),ct=C(ee(l,p,s,_));return c({id:o,type:r,method:t,displayName:lt,rawInput:s,raw_input:s,command:l,path:p,action:i(n,["action","changeType","operation"])||u.action,commandActions:A,command_actions:A.length>0?A:void 0,aggregatedOutput:_,aggregated_output:_,formatted_output:st,summary:ct})}function E(t,e){if(!e)return null;switch(a(e,"type")){case"commandExecution":return t==="item/started"?kt(e):St(e);case"fileChange":return t==="item/started"?At(e):Tt(e);case"mcpToolCall":return t==="item/started"?Mt(e):Dt(e);case"dynamicToolCall":return t==="item/started"?Pt(e):zt(e);case"collabAgentToolCall":case"collabToolCall":return t==="item/started"?Ot(e):Ft(e);case"contextCompaction":return Rt(t,e);case"webSearch":return t==="item/started"?Et(e):Gt(e);case"imageView":return Lt(e);case"imageGeneration":return t==="item/started"?Nt(e):Bt(e);default:return null}}function M(t,e){t.pushUpdate({type:e.type,label:e.label,raw:{method:e.method,params:e.params,update:e.update},atMs:Date.now()})}function I(t,e,n,r){M(t,{method:e,params:n,type:"session_info_update",label:"session_info",update:{sessionUpdate:"session_info_update",_meta:{codex:r}}})}function b(t){return{sessionUpdate:"session_info_update",_meta:{codex:t}}}function h(t,e){return{sessionUpdate:t,content:{type:"text",text:e}}}function G(t){return`fuzzyFileSearch.${t}`}function N(t){const e=a(t,"sessionId"),n=G(e),r=!T.has(n);T.add(n);const o=a(t,"query"),s=tt(o,""),l=yt(t);return c(r?{sessionUpdate:"tool_call",toolCallId:n,kind:"search",title:s,status:"in_progress",locations:l,rawInput:{query:o}}:{sessionUpdate:"tool_call_update",toolCallId:n,title:s,status:"in_progress",locations:l})}function B(t){const e=a(t,"sessionId"),n=G(e);return T.delete(n),{sessionUpdate:"tool_call_update",toolCallId:n,status:"completed"}}function yt(t){const n=(g(d(t),"files")??[]).map(r=>{const o=d(r);if(!o)return"";const s=a(o,"path"),l=a(o,"root");return s?s.startsWith("/")||!l?s:`${l.replace(/\/+$/,"")}/${s.replace(/^\/+/,"")}`:""}).filter(Boolean).map(r=>({path:r}));return n.length>0?n:void 0}function wt(t){const e=a(t,"query"),r=(g(d(t),"files")??[]).length;if(e&&r)return`${e} · ${r} files`;if(e)return e;if(r)return`${r} files`}function mt(t){return`guardian_assessment:${t}`}function k(t,e){const n=a(t,"reviewId"),r=mt(n),o=e==="started"&&!v.has(n);e==="started"&&v.add(n),e==="completed"&&v.delete(n);const s=w(t,"review")??{},l={sessionUpdate:o?"tool_call":"tool_call_update",toolCallId:r,status:Ct(a(s,"status")),content:It(s,w(t,"action")),...o?{kind:"think",title:"Guardian Review",rawInput:t}:{rawOutput:t}};return c(l)}function Ct(t){switch(t){case"inProgress":return"in_progress";case"approved":return"completed";case"denied":case"aborted":case"timedOut":return"failed";default:return t||"in_progress"}}function It(t,e){const n=[`Status: ${L(a(t,"status"))}`],r=W(e);r&&n.push(`Action: ${r}`);const o=a(t,"riskLevel");o&&n.push(`Risk: ${o}`);const s=a(t,"userAuthorization");s&&n.push(`Authorization: ${s}`);const l=a(t,"rationale").trim();return l&&n.push(`Rationale: ${l}`),[{type:"content",content:{type:"text",text:n.join(`
29
+ `)}}]}function L(t){switch(t){case"inProgress":return"In progress";case"approved":return"Approved";case"denied":return"Denied";case"aborted":return"Aborted";case"timedOut":return"Timed out";default:return t||"Unknown"}}function W(t){if(!t)return"";const e=a(t,"type");if(e==="command")return[q(a(t,"source")),a(t,"command")].filter(Boolean).join(" ");if(e==="execve"){const n=g(t,"argv")?.map(s=>f(s)).filter(Boolean)??[],r=a(t,"program"),o=n.length>0?n:[r].filter(Boolean);return[q(a(t,"source")),bt(o)].filter(Boolean).join(" ")}if(e==="applyPatch"){const n=g(t,"files")?.map(r=>f(r)).filter(Boolean)??[];return n.length===1?`apply_patch touching ${n[0]}`:`apply_patch touching ${n.length} files`}if(e==="networkAccess"){const n=a(t,"target")||a(t,"host");return n?`network access to ${n}`:"network access"}if(e==="mcpToolCall"){const n=a(t,"connectorName")||a(t,"server");return`MCP ${a(t,"toolName")} on ${n}`.trim()}return e==="requestPermissions"?a(t,"reason")||"request additional permissions":e}function q(t){return t==="shell"?"shell":t==="unifiedExec"?"exec":t}function bt(t){return t.map(Ut).join(" ")}function Ut(t){return t.length===0?"''":/^[A-Za-z0-9_/:=+.,@%-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}function xt(t){const e=w(t,"review"),n=e?L(a(e,"status")):"",r=W(w(t,"action"));return[n,r].filter(Boolean).join(" · ")||void 0}function V(t){const e=w(t,"rateLimits")??{},n=w(e,"primary"),r=w(e,"secondary");return c({sessionUpdate:"session_info_update",_meta:{rateLimits:c({planName:a(e,"planType"),limitName:a(e,"limitName"),limitId:a(e,"limitId"),fiveHour:z(n,"usedPercent")??null,sevenDay:z(r,"usedPercent")??null,fiveHourResetAt:a(n,"resetsAt")||null,sevenDayResetAt:a(r,"resetsAt")||null,raw:e})}})}function kt(t){const e=a(t,"id"),n=a(t,"cwd"),r=a(t,"command"),o=Y(t),s=o.length===1?d(o[0]):null;if(s){const l=a(s,"type");if(l==="read"){const u=a(s,"path")||a(s,"name");return c({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"read",title:`Read file '${u}'`,locations:u?[{path:u}]:void 0})}if(l==="search"){const u=a(s,"query"),p=a(s,"path");return c({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"search",title:tt(u,p)})}if(l==="listFiles"){const u=a(s,"path");return c({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"read",title:u?`List files in '${u}'`:"List files"})}}return Jt({sessionUpdate:"tool_call",toolCallId:e,status:y(a(t,"status")),kind:"execute",title:Ht(r),rawInput:c({command:r,cwd:n})},e,n)}function St(t){const e=a(t,"id"),n=i(t,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),r=z(t,"exitCode"),o={sessionUpdate:"tool_call_update",toolCallId:e,status:m(a(t,"status"),r),rawOutput:c({formatted_output:n,exit_code:r})};return Kt(t)&&(o._meta={...n?U(e,n):{},terminal_exit:{exit_code:r,signal:null,terminal_id:e}}),c(o)}function At(t){const e=a(t,"id"),n=nt(t);return c({sessionUpdate:"tool_call",toolCallId:e,title:"Editing files",kind:"edit",status:y(a(t,"status")),content:n,locations:Qt(t),rawInput:{changes:P(t)}})}function Tt(t){return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:m(a(t,"status")),content:nt(t)})}function vt(t){const e=i(t,["tool","name","server"]);return c({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:y(a(t,"status")),rawInput:d(t)})}function $t(t){return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:m(a(t,"status")),rawOutput:d(t)})}function Mt(t){const e=a(t,"server"),n=a(t,"tool");return c({...Q(t,`mcp.${e}.${n}`,X(e,n,t.arguments),Z(t.result,t.error)),_meta:{is_mcp_tool_call:!0}})}function Dt(t){const e=a(t,"server"),n=a(t,"tool");return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:m(a(t,"status")),rawInput:X(e,n,t.arguments),rawOutput:Z(t.result,t.error)})}function Pt(t){const e=a(t,"namespace"),n=a(t,"tool");return Q(t,K(e,n),{namespace:e,tool:n,arguments:t.arguments},void 0)}function zt(t){const e=a(t,"namespace"),n=a(t,"tool");return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),kind:"execute",title:K(e,n),status:m(a(t,"status")),rawInput:{namespace:e,tool:n,arguments:t.arguments},rawOutput:c({success:t.success,contentItems:t.contentItems,durationMs:t.durationMs})})}function Ot(t){const e=a(t,"tool"),n=J(t);return c({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"other",title:H(e),status:y(a(t,"status")),rawInput:{tool:e,arguments:c({...n,prompt:a(t,"prompt"),model:a(t,"model"),reasoningEffort:a(t,"reasoningEffort")})},_meta:{aca:{processKind:"subtask",action:e,collaboration:n}}})}function Ft(t){const e=a(t,"tool"),n=J(t);return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),kind:"other",title:H(e),status:m(a(t,"status")),rawOutput:c({agentsStates:t.agentsStates,...n}),_meta:{aca:{processKind:"subtask",action:e,collaboration:n}}})}function J(t){const e=new Set((g(t,"receiverThreadIds")??[]).filter(n=>typeof n=="string"&&!!n));for(const n of["receiverThreadId","newThreadId"]){const r=a(t,n);r&&e.add(r)}return c({senderThreadId:a(t,"senderThreadId"),receiverThreadIds:[...e],receiverThreadId:a(t,"receiverThreadId"),newThreadId:a(t,"newThreadId")})}function Rt(t,e){return{sessionUpdate:t==="item/started"?"tool_call":"tool_call_update",toolCallId:a(e,"id")||"codex.context_compaction",kind:"think",title:"压缩上下文",status:t==="item/started"?"in_progress":m(a(e,"status")),_meta:{aca:{processKind:"context_compaction"}}}}function K(t,e){return[t,e].filter(Boolean).join(".")||"内部工具"}function H(t){switch(t){case"spawnAgent":return"启动子任务";case"sendInput":return"发送子任务指令";case"resumeAgent":return"恢复子任务";case"wait":return"等待子任务";case"closeAgent":return"结束子任务";default:return"处理子任务"}}function jt(t){return["hookPrompt","sleep","subAgentActivity","enteredReviewMode","exitedReviewMode","plan"].includes(t)}function Q(t,e,n,r){return c({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:y(a(t,"status")),rawInput:n,rawOutput:r})}function X(t,e,n){return{server:t,tool:e,arguments:n}}function Z(t,e){if(!(t===null&&e===null)&&!(t===void 0&&e===void 0))return{result:t,error:e}}function Et(t){return c({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"search",title:et(t),status:y(a(t,"status")),rawInput:d(t)})}function Gt(t){return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),title:et(t),status:m(a(t,"status")),rawInput:d(t)})}function Nt(t){return c({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"other",title:"Image generation",status:"in_progress",rawInput:{id:a(t,"id")}})}function Bt(t){return c({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:Wt(a(t,"status")),content:qt(t),rawOutput:Vt(t)})}function Lt(t){const e=a(t,"path");return c({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"read",title:`View Image ${e}`,status:"completed",content:[{type:"content",content:{type:"resource_link",name:e,uri:e}}],locations:[{path:e}],rawInput:{path:e}})}function Wt(t){return m(t)}function qt(t){const e=d(t.result),n=i(e,["url","uri","path"]);if(n)return[{type:"content",content:{type:"resource_link",name:n,uri:n}}]}function Vt(t){const e={status:t.status,revisedPrompt:t.revisedPrompt,result:t.result};return"savedPath"in t&&(e.savedPath=t.savedPath??null),e}function Jt(t,e,n){return c({...t,content:[{type:"terminal",terminalId:e}],_meta:{terminal_info:{cwd:n,terminal_id:e}}})}function Kt(t){const e=Y(t),n=e.length===1?d(e[0]):null;return!n||a(n,"type")==="unknown"}function Y(t){return g(t,"commandActions")||g(t,"command_actions")||g(t,"actions")||[]}function y(t){switch(t){case"inProgress":case"in_progress":case"started":case"":return"in_progress";case"completed":return"completed";case"failed":case"declined":return"failed";case"cancelled":case"canceled":return"cancelled";default:return t}}function m(t,e){const n=y(t);return n==="failed"||n==="cancelled"?n:e!=null?e===0?"completed":"failed":n==="in_progress"?"completed":n}function Ht(t){const e=t.replace(/^(?:\/bin\/)?(?:bash|zsh|sh)\s+(?:-[lc]+\s+)?/,"");return e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function U(t,e){return{terminal_output_delta:{data:e,terminal_id:t}}}function tt(t,e){return t&&e?`Search for '${t}' in ${e}`:t?`Search for '${t}'`:e?`Search in '${e}'`:"Search"}function et(t){const e=d(t.action);if(!e){const r=a(t,"query");return r?`Web search: ${r}`:"Web search"}const n=a(e,"type");if(n==="search"){const r=g(e,"queries")?.map(s=>f(s)).filter(Boolean)??[],o=a(e,"query")||(r.length>0?r.join(", "):"")||a(t,"query");return o?`Web search: ${o}`:"Web search"}if(n==="openPage"){const r=a(e,"url");return r?`Open page: ${r}`:"Open page"}if(n==="findInPage"){const r=a(e,"pattern")?` for '${a(e,"pattern")}'`:"",o=a(e,"url")?` in ${a(e,"url")}`:"";return`Find in page${r}${o}`.trim()}return"Web search"}function Qt(t){const e=P(t).map(n=>d(n)).map(n=>a(n,"path")).filter(Boolean).map(n=>({path:n}));return e.length>0?e:void 0}function nt(t){const n=(g(t,"changes")??[]).map(r=>{const o=d(r);if(!o)return null;const s=f(o.path),l=o.kind&&typeof o.kind=="object"&&!Array.isArray(o.kind)?f(o.kind.type):f(o.kind),u=f(o.diff);return l==="add"?c({type:"diff",oldText:null,newText:u,path:s,_meta:{kind:"add"}}):l==="delete"?c({type:"diff",oldText:u,newText:"",path:s,_meta:{kind:"delete"}}):Xt(o,s,u,l)}).filter(Boolean);return n.length>0?n:void 0}function Xt(t,e,n,r){const o=t.kind&&typeof t.kind=="object"&&!Array.isArray(t.kind)?f(t.kind.move_path):"",s=Zt(n),l=at(e);if(l!==null){const u=D(l,s);if(u!==!1)return S(o||e,l,u,r||"update");const p=ot(s);if(p){const _=D(l,p);if(_!==!1)return S(e,_,l,r||"update")}}if(o){const u=at(o),p=ot(s);if(u!==null&&p){const _=D(u,p);if(_!==!1)return S(o,_,u,r||"update")}}return S(o||e,null,s,r||"update")}function S(t,e,n,r){return c({type:"diff",oldText:e,newText:n,path:t,_meta:{kind:r}})}function at(t){try{return ut(t,"utf8")}catch{return null}}function Zt(t){return t.replace(/\n\nMoved to: .*$/,"")}function ot(t){try{const[e]=dt(t);return e?pt(e):null}catch{return null}}function D(t,e){try{return it(t,e)}catch{return!1}}function Yt(t,e){if(t==="commandExecution")return"执行命令";if(t==="fileChange")return e.path?`编辑文件: ${ne(e.path)}`:"编辑文件";if(t==="webSearch")return e.rawInput?`搜索: ${C(e.rawInput)}`:"搜索";if(t==="mcpToolCall"||t==="dynamicToolCall"){const n=i(e.item,["tool","name","server"]);return n?`调用工具: ${n}`:"调用工具"}return $(t)}function te(t,e,n){if(e)return e;if(t==="fileChange"){const r=rt(n),o=i(n,["path","filePath","file_path","relativePath","absolutePath"])||r.path;return[i(n,["action","changeType","operation"])||r.action,o].filter(Boolean).join(" ")}return""}function rt(t){const e=g(t,"changes")??[];for(const n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;const r=n,o=f(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?f(r.kind.type):f(r.kind);if(o||s)return{path:o,action:s}}return{path:"",action:""}}function P(t){return(g(t,"changes")??[]).map(n=>{if(!n||typeof n!="object"||Array.isArray(n))return null;const r=n,o=f(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?f(r.kind.type):f(r.kind);return!o&&!s?null:c({type:s||"edit",path:o})}).filter(Boolean).slice(0,50)}function i(t,e){if(!t)return"";for(const n of e){const r=f(t[n]);if(r)return r}return""}function f(t){if(typeof t=="string"&&t.trim())return t.trim();if(typeof t=="number"||typeof t=="boolean")return String(t);if(t&&typeof t=="object")try{const e=JSON.stringify(t);return e.length>2?e:""}catch{return""}return""}function g(t,e){const n=t?.[e];return Array.isArray(n)?n.slice(0,50):null}function ee(...t){return t.find(e=>e.trim())||""}function ne(t){return t.replace(/\\/g,"/").split("/").filter(Boolean).pop()||t}function c(t){for(const e of Object.keys(t)){const n=t[e];(n===void 0||n===""||Array.isArray(n)&&n.length===0)&&delete t[e]}return t}function w(t,e){if(!t||typeof t!="object"||Array.isArray(t))return null;const n=t[e];return!n||typeof n!="object"||Array.isArray(n)?null:n}function d(t){return!t||typeof t!="object"||Array.isArray(t)?null:t}function a(t,e){if(!t||typeof t!="object"||Array.isArray(t))return"";const n=t[e];return typeof n=="string"?n:""}function z(t,e){if(!t||typeof t!="object"||Array.isArray(t))return;const n=t[e];return typeof n=="number"&&Number.isFinite(n)?n:void 0}function C(t){if(typeof t!="string")return;const e=t.replace(/\s+/g," ").trim();if(e)return e.length>120?`${e.slice(0,117)}...`:e}export{ce as codexAcpSessionUpdatesFromNotification,ie as extractAssistantTextFromTurn,ue as mapCodexNotification};
@@ -1,5 +1,5 @@
1
- import{JsonLineRpcClient as P}from"../../client/json-rpc.js";import{startCodexAppServer as q}from"../codex/codex-process.js";import{CodexConnectionRecoveryTracker as b}from"../codex/connection-events.js";import{codexAcpSessionUpdatesFromNotification as _}from"../codex/events.js";import{CodexPlanDeltaState as k}from"../codex/plan-events.js";import{isCodexApprovalRequest as M,resolveCodexApprovalRequest as E}from"../codex/permissions.js";import{buildCodexContinuityInstructions as U,codexTokenUsageFromNotification as F,decideCodexContextMaintenance as I,readCodexContextMaintenancePolicy as S,rolloutFileSize as N}from"./context-maintenance.js";import{codexNotificationBelongsToCurrentTurn as j}from"./notification-routing.js";class O{lineBuffer="";started=null;rpc=null;codexStartupPromise=null;initialized=!1;currentSessionId=null;currentCwd=process.cwd();promptActive=!1;currentTurnId=null;nextParentRequestId=1;pendingParentRequests=new Map;completedTurns=new Map;pendingTurnCompletions=new Map;agentMessagePhases=new Map;planDeltas=new k;config={};sessionAliases=new Map;currentAffectedFiles=new Set;connectionRecovery=new b;latestTokenUsage=null;currentRolloutPath=null;threadTurnCount=0;currentPromptText="";currentAssistantText="";previousUserText="";previousAssistantText="";previousAffectedFiles=new Set;maintenanceActive=!1;pendingCompaction=null;shutdownPromise=null;managedProvider=null;constructor(){process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>this.handleInput(String(t)));const e=()=>{this.shutdown().finally(()=>process.exit(0))};process.stdin.once("end",e),process.stdin.once("close",e),process.stdin.once("error",e),process.once("SIGTERM",()=>{this.shutdown().finally(()=>process.exit(0))}),process.once("SIGINT",()=>{this.shutdown().finally(()=>process.exit(130))})}handleInput(e){this.lineBuffer+=e;const t=this.lineBuffer.split(`
2
- `);this.lineBuffer=t.pop()??"";for(const s of t){const r=s.trim();if(!r)continue;let o;try{o=JSON.parse(r)}catch{continue}this.handleMessage(o)}}async handleMessage(e){if("id"in e&&("result"in e||"error"in e)&&typeof e.method!="string"){this.handleParentResponse(e);return}const t=typeof e.method=="string"?e.method:"",s=e.id;if(t){if(s===void 0){await this.handleNotification(t,u(e.params));return}try{const r=await this.handleRequest(t,u(e.params));this.write({jsonrpc:"2.0",id:s,result:r})}catch(r){this.write({jsonrpc:"2.0",id:s,error:{code:-32603,message:r instanceof Error?r.message:String(r)}})}}}async handleNotification(e,t){e==="session/cancel"&&await this.cancel(t)}async handleRequest(e,t){switch(e){case"initialize":return this.initializeResponse();case"aca/runtime_config":return this.applyRuntimeConfig(t);case"session/new":return this.newSession(t);case"session/resume":case"session/load":return this.resumeSession(t);case"session/fork":return this.forkSession(t);case"session/prompt":return this.prompt(t);case"session/compact":return this.manualCompact(t);case"session/cancel":return await this.cancel(t),{};case"session/close":return await this.closeSession(t),{};case"session/set_config_option":return this.setConfigOption(t);case"session/set_mode":return this.setMode(t);case"fs/read_text_file":case"fs/write_text_file":case"terminal/create":case"terminal/output":case"terminal/wait_for_exit":case"terminal/kill":case"terminal/release":return{};default:throw new Error(`Unsupported ACP method: ${e}`)}}initializeResponse(){return{protocolVersion:1,agentCapabilities:{loadSession:!0,sessionCapabilities:{resume:!0,close:!0}}}}applyRuntimeConfig(e){if(this.started)throw new Error("Codex runtime config must be applied before app-server starts");const t=u(e.codexProvider);if(Object.keys(t).length===0)return this.managedProvider=null,{configured:!1};const s=a(t,"baseUrl"),r=a(t,"apiKey"),o=Number(t.revision||0);if(!s||!r||!Number.isSafeInteger(o)||o<1)throw new Error("Invalid Codex managed provider runtime config");return this.managedProvider={baseUrl:s,apiKey:r,revision:o},{configured:!0,revision:o}}async newSession(e){const t=a(e,"cwd")||process.cwd();this.applyInitialConfig(e),await this.ensureCodex(t);const s=await this.requireRpc().request("thread/start",{cwd:t,approvalsReviewer:"user",...this.codexConfig(),ephemeral:!1,threadSource:"aca-codex-acp"},6e4),r=C(s);if(!r)throw new Error("Codex thread/start did not return thread id");return this.currentSessionId=r,this.currentCwd=t,this.captureThreadMetadata(s),this.sessionResponse(r)}async resumeSession(e){const t=a(e,"sessionId");if(!t)throw new Error("sessionId is required");const s=a(e,"cwd")||this.currentCwd;this.applyInitialConfig(e),await this.ensureCodex(s);const r=await this.requireRpc().request("thread/resume",{threadId:t,cwd:s,approvalsReviewer:"user",...this.codexConfig()},6e4);return this.currentSessionId=C(r)||t,this.currentCwd=s,this.captureThreadMetadata(r),this.sessionResponse(this.currentSessionId)}async forkSession(e){const t=a(e,"sessionId");if(!t)throw new Error("sessionId is required");const s=a(e,"cwd")||this.currentCwd;this.applyInitialConfig(e),await this.ensureCodex(s);const r=await this.requireRpc().request("thread/fork",{threadId:t,cwd:s,approvalsReviewer:"user",ephemeral:!1,threadSource:"aca-codex-acp-fork",...this.codexConfig()},12e4),o=C(r);if(!o)throw new Error("Codex thread/fork did not return thread id");return this.currentSessionId=o,this.currentCwd=s,this.captureThreadMetadata(r),this.sessionResponse(o)}async prompt(e){const t=a(e,"sessionId")||this.currentSessionId;let s=this.resolveSessionAlias(t);if(!s)throw new Error("sessionId is required");const r=Array.isArray(e.prompt)?e.prompt:[],o=this.requireRpc();this.currentSessionId=s,this.promptActive=!0,this.currentTurnId=null,this.currentPromptText=D(r),this.currentAssistantText="",this.currentAffectedFiles.clear(),this.connectionRecovery.reset(),this.agentMessagePhases.clear(),this.planDeltas.reset();let i;try{i=await o.request("turn/start",{threadId:s,clientUserMessageId:`aca-acp-${Date.now()}-${Math.random().toString(16).slice(2)}`,input:$(r),cwd:this.currentCwd,...B(this.config)},R());const c=String(i?.turn?.id??"");this.currentTurnId=c||null;const d=c?await this.waitForTurnCompleted(c,R()):i?.turn;this.threadTurnCount+=1,this.previousUserText=this.currentPromptText,this.previousAssistantText=this.currentAssistantText,this.previousAffectedFiles.clear();for(const l of this.currentAffectedFiles)this.previousAffectedFiles.add(l);return{stopReason:"end_turn",sessionId:this.currentSessionId,turn:d,_meta:{acaContextUsage:G(this.latestTokenUsage)}}}catch(c){const d=this.connectionRecovery.fail(c);throw d&&this.notifySessionUpdate(d),c}finally{this.promptActive=!1,this.currentTurnId=null}}async cancel(e){const t=a(e,"sessionId")||this.currentSessionId;if(!(!t||!this.rpc)&&(await this.rpc.request("turn/interrupt",{threadId:t}).catch(()=>{}),this.currentTurnId)){const s=this.pendingTurnCompletions.get(this.currentTurnId);s&&(this.pendingTurnCompletions.delete(this.currentTurnId),clearTimeout(s.timer),s.reject(new Error("Codex prompt cancelled")))}}async manualCompact(e){const t=a(e,"sessionId")||this.currentSessionId,s=this.resolveSessionAlias(t);if(!s)throw new Error("sessionId is required");if(this.promptActive||this.maintenanceActive)throw new Error("Codex session is busy");this.currentSessionId=s;const r=S(),o=await this.maintainContext("manual",{userRequest:this.previousUserText,assistantResponse:this.previousAssistantText,affectedFiles:[...this.previousAffectedFiles]},{force:!0,allowRollover:e.allowRollover===!0,compactTimeoutMs:W(e,r.compactTimeoutMs)}),i=String(o.action||"");if(i==="compact_failed"||i==="rollover_failed"){const c=String(o.compactError||"Codex 上下文压缩未完成");throw new Error(`Codex 上下文压缩失败:${c}`)}return{sessionId:this.currentSessionId,maintenance:o,contextUsage:L(o)}}async closeSession(e){await this.shutdown()}async ensureCodex(e){if(this.rpc&&this.started&&this.started.child.exitCode===null&&this.started.child.signalCode===null)return;if(this.codexStartupPromise){await this.codexStartupPromise;return}const t=(async()=>{if(this.rpc&&this.started&&this.started.child.exitCode===null&&this.started.child.signalCode===null)return;const s=q(e,this.managedProvider),r=new P(s.child,{peerName:"Codex app-server",onNotification:(o,i)=>this.handleCodexNotification(o,i),onRequest:async(o,i)=>this.handleCodexRequest(o,i)});this.started=s,this.rpc=r,this.initialized=!1,await r.request("initialize",{clientInfo:{name:"aca-codex-acp",version:"0.1.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}},6e4),this.initialized=!0})();this.codexStartupPromise=t;try{await t}catch(s){throw this.rpc&&this.started&&!this.initialized&&await T(this.started.child,1e3),this.rpc=null,this.started=null,s}finally{this.codexStartupPromise===t&&(this.codexStartupPromise=null)}}handleCodexNotification(e,t){if(!j(t,this.currentSessionId,this.currentTurnId)||(this.captureContextNotification(e,t),this.maintenanceActive)||!this.promptActive&&e!=="turn/completed")return;this.rpc?.refreshPendingRequestTimeout("turn/start"),this.captureAgentMessagePhase(e,t);const s=this.connectionRecovery.beforeNotification(e,t);e==="turn/completed"&&this.resolveTurnCompleted(t);const r=_(e,t,{agentMessagePhases:this.agentMessagePhases,planDeltas:this.planDeltas});for(const o of[...s,...r])this.captureUpdateEvidence(o),this.notifySessionUpdate(o)}notifySessionUpdate(e){this.notify("session/update",{sessionId:this.currentSessionId,update:e})}async handleCodexRequest(e,t){if(M(e))return E(e,t,async s=>{const r=await this.requestParent("session/request_permission",{sessionId:this.currentSessionId,request:{...s,params:t,method:e}}),o=u(r),i=u(o.outcome);return i.outcome==="selected"&&typeof i.optionId=="string"?{outcome:{outcome:"selected",optionId:i.optionId}}:{outcome:{outcome:"cancelled"}}});if(J(e)){const s=await this.requestParent("elicitation/create",{sessionId:this.currentSessionId,request:{...u(t),method:e}}),r=u(s),o=u(r.outcome);return o.outcome==="submitted"?{outcome:{outcome:"submitted",value:typeof o.value=="string"?o.value:""}}:{outcome:{outcome:"cancelled"}}}return{}}captureAgentMessagePhase(e,t){if(e!=="item/started"&&e!=="item/completed")return;const s=h(t,"item");if(a(s,"type")!=="agentMessage")return;const r=a(s,"id");r&&this.agentMessagePhases.set(r,a(s,"phase"))}waitForTurnCompleted(e,t){const s=this.completedTurns.get(e);return s?Promise.resolve(s):new Promise((r,o)=>{const i=setTimeout(()=>{this.pendingTurnCompletions.delete(e),o(new Error("Codex app-server request timed out while waiting for turn/completed"))},t);i.unref(),this.pendingTurnCompletions.set(e,{resolve:r,reject:o,timer:i})})}resolveTurnCompleted(e){const t=h(e,"turn"),s=a(t,"id");if(!s)return;this.completedTurns.set(s,t);const r=this.pendingTurnCompletions.get(s);if(r){if(this.pendingTurnCompletions.delete(s),clearTimeout(r.timer),a(t,"status")==="failed"){r.reject(new Error(`Codex turn failed: ${JSON.stringify(t.error??{})}`));return}r.resolve(t)}}async shutdown(){return this.shutdownPromise?this.shutdownPromise:(this.shutdownPromise=this.performShutdown(),this.shutdownPromise)}async performShutdown(){this.pendingCompaction&&(clearTimeout(this.pendingCompaction.timer),this.pendingCompaction.reject(new Error("Codex ACP adapter closed")),this.pendingCompaction=null);for(const t of this.pendingParentRequests.values())clearTimeout(t.timer),t.reject(new Error("Codex ACP adapter closed"));this.pendingParentRequests.clear();for(const t of this.pendingTurnCompletions.values())clearTimeout(t.timer),t.reject(new Error("Codex ACP adapter closed"));this.pendingTurnCompletions.clear();const e=this.started?.child;!e||e.exitCode!==null||e.signalCode!==null||(e.stdin.end(),!await T(e,2e3)&&(e.kill("SIGTERM"),!await T(e,1e3)&&(e.kill("SIGKILL"),await T(e,1e3))))}sessionResponse(e){return{sessionId:e,modes:{currentModeId:"workspace-write",availableModes:[{id:"read-only",name:"Read Only"},{id:"workspace-write",name:"Workspace Write"},{id:"danger-full-access",name:"Full Access"}]},configOptions:[{id:"model",category:"model",type:"string"},{id:"approvalPolicy",category:"approval",type:"string"},{id:"sandbox",category:"mode",type:"string"}]}}requireRpc(){if(!this.rpc)throw new Error("Codex app-server is not started");return this.rpc}notify(e,t){this.write({jsonrpc:"2.0",method:e,params:t})}requestParent(e,t,s=600*1e3){const r=this.nextParentRequestId++;return new Promise((o,i)=>{const c=setTimeout(()=>{this.pendingParentRequests.delete(r),i(new Error(`ACP client request timed out: ${e}`))},s);c.unref(),this.pendingParentRequests.set(r,{resolve:o,reject:i,timer:c}),this.write({jsonrpc:"2.0",id:r,method:e,params:t})})}handleParentResponse(e){const t=Number(e.id),s=this.pendingParentRequests.get(t);if(s){if(this.pendingParentRequests.delete(t),clearTimeout(s.timer),"error"in e){const r=u(e.error);s.reject(new Error(a(r,"message")||"ACP client request failed"));return}s.resolve(e.result)}}setConfigOption(e){const t=a(e,"configId"),s=e.value;if(!t)throw new Error("configId is required");if(typeof s!="string"&&typeof s!="boolean")throw new Error("config value must be string or boolean");return this.config[t]=s,this.notify("session/update",{sessionId:this.currentSessionId,update:{sessionUpdate:"config_option_update",configId:t,value:s}}),{}}setMode(e){const t=a(e,"modeId");if(!t)throw new Error("modeId is required");return this.config.sandbox=t,this.notify("session/update",{sessionId:this.currentSessionId,update:{sessionUpdate:"current_mode_update",modeId:t}}),{}}applyInitialConfig(e){const t=h(e,"config");for(const[s,r]of Object.entries(t))(typeof r=="string"||typeof r=="boolean")&&(this.config[s]=r)}codexConfig(){return{...typeof this.config.model=="string"&&this.config.model?{model:this.config.model}:{},approvalPolicy:typeof this.config.approvalPolicy=="string"?this.config.approvalPolicy:"on-request",sandbox:typeof this.config.sandbox=="string"?this.config.sandbox:"workspace-write"}}captureContextNotification(e,t){if(e==="thread/tokenUsage/updated"&&(this.latestTokenUsage=F(t)??this.latestTokenUsage),e==="thread/compacted"&&this.pendingCompaction&&this.resolveCompaction(),e==="item/completed"){const s=h(t,"item"),r=a(u(t),"threadId");a(s,"type")==="contextCompaction"&&(!r||r===this.currentSessionId)&&this.resolveCompaction(),a(s,"type")==="agentMessage"&&a(s,"phase")==="final_answer"&&(this.currentAssistantText=f(s)||this.currentAssistantText)}}resolveCompaction(){if(!this.pendingCompaction)return;const e=this.pendingCompaction;this.pendingCompaction=null,clearTimeout(e.timer),e.resolve()}captureUpdateEvidence(e){String(e.sessionUpdate||"")==="agent_message_chunk"&&(this.currentAssistantText+=f(e.content)),x(e,this.currentAffectedFiles)}captureThreadMetadata(e){const t=h(e,"thread");this.currentRolloutPath=a(t,"path")||null,this.threadTurnCount=Array.isArray(t.turns)?t.turns.length:0;const s=z(t.turns);s.userRequest&&(this.previousUserText=s.userRequest),s.assistantResponse&&(this.previousAssistantText=s.assistantResponse),this.previousAffectedFiles.clear();for(const r of s.affectedFiles)this.previousAffectedFiles.add(r);this.latestTokenUsage=null}async maintainContext(e,t,s={}){const r=S(),o=this.contextState(),i=I(o,r);if(!i.compact&&!s.force||!this.currentSessionId)return this.maintenanceResult({stage:e,action:"none",reasons:i.reasons,beforeState:o});const c=this.currentSessionId;this.notifyContextStatus("正在整理会话上下文",A(o)),this.maintenanceActive=!0;let d=!1,l="",g=o,m=i,v=!1,y="";try{const p=o.usage?.observedAtMs??0;await this.compactThread(c,s.compactTimeoutMs??r.compactTimeoutMs),await this.waitForTokenUsageAfter(p,2e3)}catch(p){d=!0,l=p instanceof Error?p.message:String(p)}try{if(g=this.contextState(),m=I(g,r,{compactAttempted:!0,compactFailed:d}),m.rollover&&s.allowRollover!==!1){this.notifyContextStatus("正在创建轻量会话",m.reasons.join(", "));try{await this.rotateThread(c,t),v=!0}catch(p){y=p instanceof Error?p.message:String(p),this.notifyContextStatus("轻量会话创建失败",y)}}else d||this.notifyContextStatus("会话上下文已压缩",A(g))}finally{this.maintenanceActive=!1}return this.maintenanceResult({action:v?"rollover":y?"rollover_failed":d?"compact_failed":"compact",stage:e,reasons:m.reasons,beforeState:o,afterState:g,compactError:[l,y].filter(Boolean).join("; "),previousThreadId:c,rolloverRecommended:m.rollover&&s.allowRollover===!1})}compactThread(e,t){return this.pendingCompaction?Promise.reject(new Error("Codex context compaction is already running")):new Promise((s,r)=>{const o=setTimeout(()=>{this.pendingCompaction?.timer===o&&(this.pendingCompaction=null),r(new Error("Codex thread compaction timed out"))},t);o.unref(),this.pendingCompaction={resolve:s,reject:r,timer:o},this.requireRpc().request("thread/compact/start",{threadId:e},t).catch(i=>{this.pendingCompaction?.timer===o&&(this.pendingCompaction=null,clearTimeout(o),r(i instanceof Error?i:new Error(String(i))))})})}async rotateThread(e,t){const s=U({previousThreadId:e,cwd:this.currentCwd,userRequest:t.userRequest,assistantResponse:t.assistantResponse,affectedFiles:t.affectedFiles}),r=await this.requireRpc().request("thread/start",{cwd:this.currentCwd,approvalsReviewer:"user",...this.codexConfig(),developerInstructions:s,ephemeral:!1,threadSource:"aca-codex-acp-rollover"},6e4),o=C(r);if(!o)throw new Error("Codex rollover thread/start did not return thread id");this.sessionAliases.set(e,o),this.currentSessionId=o,this.captureThreadMetadata(r)}async waitForTokenUsageAfter(e,t){const s=Date.now()+t;for(;Date.now()<s;){if((this.latestTokenUsage?.observedAtMs??0)>e)return;await K(50)}}resolveSessionAlias(e){if(!e)return null;let t=e;const s=new Set;for(;this.sessionAliases.has(t)&&!s.has(t);)s.add(t),t=this.sessionAliases.get(t)??t;return t}contextState(){return{usage:this.latestTokenUsage,rolloutBytes:N(this.currentRolloutPath),turnCount:this.threadTurnCount}}maintenanceResult(e){return{stage:e.stage,action:e.action,reasons:e.reasons,previousThreadId:e.previousThreadId??null,sessionId:this.currentSessionId,before:e.beforeState,after:e.afterState??null,compactError:e.compactError||null,rolloverRecommended:e.rolloverRecommended===!0}}notifyContextStatus(e,t){this.notify("session/update",{sessionId:this.currentSessionId,update:{sessionUpdate:"aca_context_maintenance",label:e,detail:t}})}write(e){process.stdout.write(`${JSON.stringify(e)}
3
- `)}}function $(n){return n.map(e=>{const t=u(e);if(t.type==="image"){const s=a(t,"uri");if(s)return{type:"localImage",path:s};const r=a(t,"data");return{type:"image",url:`data:${a(t,"mimeType")||"image/png"};base64,${r}`}}return{type:"text",text:a(t,"text"),text_elements:[]}})}function D(n){return n.map(e=>a(u(e),"text")).filter(Boolean).join(`
1
+ import{JsonLineRpcClient as q}from"../../client/json-rpc.js";import{startCodexAppServer as M}from"../codex/codex-process.js";import{CodexConnectionRecoveryTracker as U}from"../codex/connection-events.js";import{codexAcpSessionUpdatesFromNotification as T}from"../codex/events.js";import{CodexPlanDeltaState as v}from"../codex/plan-events.js";import{isCodexApprovalRequest as E,resolveCodexApprovalRequest as F}from"../codex/permissions.js";import{buildCodexContinuityInstructions as N,codexTokenUsageFromNotification as j,decideCodexContextMaintenance as b,readCodexContextMaintenancePolicy as k,rolloutFileSize as D}from"./context-maintenance.js";import{codexNotificationBelongsToCurrentTurn as $,codexNotificationRouting as A}from"./notification-routing.js";import{CodexSubtaskRouter as O}from"./subtask-routing.js";class B{lineBuffer="";started=null;rpc=null;codexStartupPromise=null;initialized=!1;currentSessionId=null;currentCwd=process.cwd();promptActive=!1;currentTurnId=null;nextParentRequestId=1;pendingParentRequests=new Map;completedTurns=new Map;pendingTurnCompletions=new Map;agentMessagePhases=new Map;planDeltas=new v;subtaskRouter=new O;subtaskAgentMessagePhases=new Map;subtaskPlanDeltas=new Map;pendingSubtaskNotifications=[];config={};sessionAliases=new Map;currentAffectedFiles=new Set;connectionRecovery=new U;latestTokenUsage=null;currentRolloutPath=null;threadTurnCount=0;currentPromptText="";currentAssistantText="";previousUserText="";previousAssistantText="";previousAffectedFiles=new Set;maintenanceActive=!1;pendingCompaction=null;shutdownPromise=null;managedProvider=null;constructor(){process.stdin.setEncoding("utf8"),process.stdin.on("data",t=>this.handleInput(String(t)));const e=()=>{this.shutdown().finally(()=>process.exit(0))};process.stdin.once("end",e),process.stdin.once("close",e),process.stdin.once("error",e),process.once("SIGTERM",()=>{this.shutdown().finally(()=>process.exit(0))}),process.once("SIGINT",()=>{this.shutdown().finally(()=>process.exit(130))})}handleInput(e){this.lineBuffer+=e;const t=this.lineBuffer.split(`
2
+ `);this.lineBuffer=t.pop()??"";for(const s of t){const n=s.trim();if(!n)continue;let r;try{r=JSON.parse(n)}catch{continue}this.handleMessage(r)}}async handleMessage(e){if("id"in e&&("result"in e||"error"in e)&&typeof e.method!="string"){this.handleParentResponse(e);return}const t=typeof e.method=="string"?e.method:"",s=e.id;if(t){if(s===void 0){await this.handleNotification(t,u(e.params));return}try{const n=await this.handleRequest(t,u(e.params));this.write({jsonrpc:"2.0",id:s,result:n})}catch(n){this.write({jsonrpc:"2.0",id:s,error:{code:-32603,message:n instanceof Error?n.message:String(n)}})}}}async handleNotification(e,t){e==="session/cancel"&&await this.cancel(t)}async handleRequest(e,t){switch(e){case"initialize":return this.initializeResponse();case"aca/runtime_config":return this.applyRuntimeConfig(t);case"session/new":return this.newSession(t);case"session/resume":case"session/load":return this.resumeSession(t);case"session/fork":return this.forkSession(t);case"session/prompt":return this.prompt(t);case"session/compact":return this.manualCompact(t);case"session/cancel":return await this.cancel(t),{};case"session/close":return await this.closeSession(t),{};case"session/set_config_option":return this.setConfigOption(t);case"session/set_mode":return this.setMode(t);case"fs/read_text_file":case"fs/write_text_file":case"terminal/create":case"terminal/output":case"terminal/wait_for_exit":case"terminal/kill":case"terminal/release":return{};default:throw new Error(`Unsupported ACP method: ${e}`)}}initializeResponse(){return{protocolVersion:1,agentCapabilities:{loadSession:!0,sessionCapabilities:{resume:!0,close:!0}}}}applyRuntimeConfig(e){if(this.started)throw new Error("Codex runtime config must be applied before app-server starts");const t=u(e.codexProvider);if(Object.keys(t).length===0)return this.managedProvider=null,{configured:!1};const s=c(t,"baseUrl"),n=c(t,"apiKey"),r=Number(t.revision||0);if(!s||!n||!Number.isSafeInteger(r)||r<1)throw new Error("Invalid Codex managed provider runtime config");return this.managedProvider={baseUrl:s,apiKey:n,revision:r},{configured:!0,revision:r}}async newSession(e){const t=c(e,"cwd")||process.cwd();this.applyInitialConfig(e),await this.ensureCodex(t);const s=await this.requireRpc().request("thread/start",{cwd:t,approvalsReviewer:"user",...this.codexConfig(),ephemeral:!1,threadSource:"aca-codex-acp"},6e4),n=S(s);if(!n)throw new Error("Codex thread/start did not return thread id");return this.currentSessionId=n,this.currentCwd=t,this.resetSubtaskState(),this.captureThreadMetadata(s),this.sessionResponse(n)}async resumeSession(e){const t=c(e,"sessionId");if(!t)throw new Error("sessionId is required");const s=c(e,"cwd")||this.currentCwd;this.applyInitialConfig(e),await this.ensureCodex(s);const n=await this.requireRpc().request("thread/resume",{threadId:t,cwd:s,approvalsReviewer:"user",...this.codexConfig()},6e4);return this.currentSessionId=S(n)||t,this.currentCwd=s,this.resetSubtaskState(n),this.captureThreadMetadata(n),this.sessionResponse(this.currentSessionId)}async forkSession(e){const t=c(e,"sessionId");if(!t)throw new Error("sessionId is required");const s=c(e,"cwd")||this.currentCwd;this.applyInitialConfig(e),await this.ensureCodex(s);const n=await this.requireRpc().request("thread/fork",{threadId:t,cwd:s,approvalsReviewer:"user",ephemeral:!1,threadSource:"aca-codex-acp-fork",...this.codexConfig()},12e4),r=S(n);if(!r)throw new Error("Codex thread/fork did not return thread id");return this.currentSessionId=r,this.currentCwd=s,this.resetSubtaskState(n),this.captureThreadMetadata(n),this.sessionResponse(r)}async prompt(e){const t=c(e,"sessionId")||this.currentSessionId;let s=this.resolveSessionAlias(t);if(!s)throw new Error("sessionId is required");const n=Array.isArray(e.prompt)?e.prompt:[],r=this.requireRpc();this.currentSessionId&&this.currentSessionId!==s&&this.resetSubtaskState(),this.currentSessionId=s,this.promptActive=!0,this.currentTurnId=null,this.currentPromptText=W(n),this.currentAssistantText="",this.currentAffectedFiles.clear(),this.connectionRecovery.reset(),this.agentMessagePhases.clear(),this.planDeltas.reset(),this.pendingSubtaskNotifications=[];let o;try{o=await r.request("turn/start",{threadId:s,clientUserMessageId:`aca-acp-${Date.now()}-${Math.random().toString(16).slice(2)}`,input:z(n),cwd:this.currentCwd,...L(this.config)},_());const a=String(o?.turn?.id??"");this.currentTurnId=a||null;const d=a?await this.waitForTurnCompleted(a,_()):o?.turn;this.threadTurnCount+=1,this.previousUserText=this.currentPromptText,this.previousAssistantText=this.currentAssistantText,this.previousAffectedFiles.clear();for(const l of this.currentAffectedFiles)this.previousAffectedFiles.add(l);return{stopReason:"end_turn",sessionId:this.currentSessionId,turn:d,_meta:{acaContextUsage:V(this.latestTokenUsage)}}}catch(a){const d=this.connectionRecovery.fail(a);throw d&&this.notifySessionUpdate(d),a}finally{this.promptActive=!1,this.currentTurnId=null,this.pendingSubtaskNotifications=[]}}resetSubtaskState(e){this.subtaskRouter.reset(),this.subtaskAgentMessagePhases.clear(),this.subtaskPlanDeltas.clear(),this.pendingSubtaskNotifications=[],e!==void 0&&this.subtaskRouter.restoreFromSessionSnapshot(e,this.currentSessionId)}async cancel(e){const t=c(e,"sessionId")||this.currentSessionId;if(!(!t||!this.rpc)&&(await this.rpc.request("turn/interrupt",{threadId:t}).catch(()=>{}),this.currentTurnId)){const s=this.pendingTurnCompletions.get(this.currentTurnId);s&&(this.pendingTurnCompletions.delete(this.currentTurnId),clearTimeout(s.timer),s.reject(new Error("Codex prompt cancelled")))}}async manualCompact(e){const t=c(e,"sessionId")||this.currentSessionId,s=this.resolveSessionAlias(t);if(!s)throw new Error("sessionId is required");if(this.promptActive||this.maintenanceActive)throw new Error("Codex session is busy");this.currentSessionId=s;const n=k(),r=await this.maintainContext("manual",{userRequest:this.previousUserText,assistantResponse:this.previousAssistantText,affectedFiles:[...this.previousAffectedFiles]},{force:!0,allowRollover:e.allowRollover===!0,compactTimeoutMs:J(e,n.compactTimeoutMs)}),o=String(r.action||"");if(o==="compact_failed"||o==="rollover_failed"){const a=String(r.compactError||"Codex 上下文压缩未完成");throw new Error(`Codex 上下文压缩失败:${a}`)}return{sessionId:this.currentSessionId,maintenance:r,contextUsage:K(r)}}async closeSession(e){await this.shutdown()}async ensureCodex(e){if(this.rpc&&this.started&&this.started.child.exitCode===null&&this.started.child.signalCode===null)return;if(this.codexStartupPromise){await this.codexStartupPromise;return}const t=(async()=>{if(this.rpc&&this.started&&this.started.child.exitCode===null&&this.started.child.signalCode===null)return;const s=M(e,this.managedProvider),n=new q(s.child,{peerName:"Codex app-server",onNotification:(r,o)=>this.handleCodexNotification(r,o),onRequest:async(r,o)=>this.handleCodexRequest(r,o)});this.started=s,this.rpc=n,this.initialized=!1,await n.request("initialize",{clientInfo:{name:"aca-codex-acp",version:"0.1.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}},6e4),this.initialized=!0})();this.codexStartupPromise=t;try{await t}catch(s){throw this.rpc&&this.started&&!this.initialized&&await x(this.started.child,1e3),this.rpc=null,this.started=null,s}finally{this.codexStartupPromise===t&&(this.codexStartupPromise=null)}}handleCodexNotification(e,t){const s=A(t);if(!$(t,this.currentSessionId,this.currentTurnId)){if(!this.promptActive||!s.threadId||s.threadId===this.currentSessionId)return;const a=this.subtaskRouter.routeFor(s.threadId);if(!a){this.bufferPendingSubtaskNotification(e,t,s.threadId);return}this.handleSubtaskNotification(e,t,a),this.flushPendingSubtaskNotifications();return}const n=this.subtaskRouter.observe(t,this.currentSessionId);if(this.captureContextNotification(e,t),this.maintenanceActive||!this.promptActive&&e!=="turn/completed")return;this.rpc?.refreshPendingRequestTimeout("turn/start"),this.captureAgentMessagePhase(e,t);const r=this.connectionRecovery.beforeNotification(e,t);e==="turn/completed"&&this.resolveTurnCompleted(t);const o=T(e,t,{agentMessagePhases:this.agentMessagePhases,planDeltas:this.planDeltas});for(const a of[...r,...o])this.captureUpdateEvidence(a),this.notifySessionUpdate(a);n>0&&this.flushPendingSubtaskNotifications()}handleSubtaskNotification(e,t,s){if(!this.promptActive)return;this.rpc?.refreshPendingRequestTimeout("turn/start");const n=this.subtaskAgentMessagePhases.get(s.sourceThreadId)??new Map;this.subtaskAgentMessagePhases.set(s.sourceThreadId,n);const r=this.subtaskPlanDeltas.get(s.sourceThreadId)??new v;this.subtaskPlanDeltas.set(s.sourceThreadId,r),this.captureAgentMessagePhase(e,t,n),this.subtaskRouter.observe(t,this.currentSessionId);const o=T(e,t,{agentMessagePhases:n,planDeltas:r}),a=A(t).turnId;for(const d of o){if(!H(d))continue;const l=Q(d,s,a);g(l,this.currentAffectedFiles),this.notifySessionUpdate(l)}}bufferPendingSubtaskNotification(e,t,s){this.pendingSubtaskNotifications.push({method:e,params:t,threadId:s}),this.pendingSubtaskNotifications.length>200&&this.pendingSubtaskNotifications.shift()}flushPendingSubtaskNotifications(){if(this.pendingSubtaskNotifications.length===0)return;let e=!0;for(;e&&this.pendingSubtaskNotifications.length>0;){e=!1;const t=[];for(const s of this.pendingSubtaskNotifications){const n=this.subtaskRouter.routeFor(s.threadId);if(!n){t.push(s);continue}e=!0,this.handleSubtaskNotification(s.method,s.params,n)}this.pendingSubtaskNotifications=t}}notifySessionUpdate(e){this.notify("session/update",{sessionId:this.currentSessionId,update:e})}async handleCodexRequest(e,t){if(E(e))return F(e,t,async s=>{const n=await this.requestParent("session/request_permission",{sessionId:this.currentSessionId,request:{...s,params:t,method:e}}),r=u(n),o=u(r.outcome);return o.outcome==="selected"&&typeof o.optionId=="string"?{outcome:{outcome:"selected",optionId:o.optionId}}:{outcome:{outcome:"cancelled"}}});if(X(e)){const s=await this.requestParent("elicitation/create",{sessionId:this.currentSessionId,request:{...u(t),method:e}}),n=u(s),r=u(n.outcome);return r.outcome==="submitted"?{outcome:{outcome:"submitted",value:typeof r.value=="string"?r.value:""}}:{outcome:{outcome:"cancelled"}}}return{}}captureAgentMessagePhase(e,t,s=this.agentMessagePhases){if(e!=="item/started"&&e!=="item/completed")return;const n=p(t,"item");if(c(n,"type")!=="agentMessage")return;const r=c(n,"id");r&&s.set(r,c(n,"phase"))}waitForTurnCompleted(e,t){const s=this.completedTurns.get(e);return s?Promise.resolve(s):new Promise((n,r)=>{const o=setTimeout(()=>{this.pendingTurnCompletions.delete(e),r(new Error("Codex app-server request timed out while waiting for turn/completed"))},t);o.unref(),this.pendingTurnCompletions.set(e,{resolve:n,reject:r,timer:o})})}resolveTurnCompleted(e){const t=p(e,"turn"),s=c(t,"id");if(!s)return;this.completedTurns.set(s,t);const n=this.pendingTurnCompletions.get(s);if(n){if(this.pendingTurnCompletions.delete(s),clearTimeout(n.timer),c(t,"status")==="failed"){n.reject(new Error(`Codex turn failed: ${JSON.stringify(t.error??{})}`));return}n.resolve(t)}}async shutdown(){return this.shutdownPromise?this.shutdownPromise:(this.shutdownPromise=this.performShutdown(),this.shutdownPromise)}async performShutdown(){this.pendingCompaction&&(clearTimeout(this.pendingCompaction.timer),this.pendingCompaction.reject(new Error("Codex ACP adapter closed")),this.pendingCompaction=null);for(const t of this.pendingParentRequests.values())clearTimeout(t.timer),t.reject(new Error("Codex ACP adapter closed"));this.pendingParentRequests.clear();for(const t of this.pendingTurnCompletions.values())clearTimeout(t.timer),t.reject(new Error("Codex ACP adapter closed"));this.pendingTurnCompletions.clear();const e=this.started?.child;!e||e.exitCode!==null||e.signalCode!==null||(e.stdin.end(),!await x(e,2e3)&&(e.kill("SIGTERM"),!await x(e,1e3)&&(e.kill("SIGKILL"),await x(e,1e3))))}sessionResponse(e){return{sessionId:e,modes:{currentModeId:"workspace-write",availableModes:[{id:"read-only",name:"Read Only"},{id:"workspace-write",name:"Workspace Write"},{id:"danger-full-access",name:"Full Access"}]},configOptions:[{id:"model",category:"model",type:"string"},{id:"approvalPolicy",category:"approval",type:"string"},{id:"sandbox",category:"mode",type:"string"}]}}requireRpc(){if(!this.rpc)throw new Error("Codex app-server is not started");return this.rpc}notify(e,t){this.write({jsonrpc:"2.0",method:e,params:t})}requestParent(e,t,s=600*1e3){const n=this.nextParentRequestId++;return new Promise((r,o)=>{const a=setTimeout(()=>{this.pendingParentRequests.delete(n),o(new Error(`ACP client request timed out: ${e}`))},s);a.unref(),this.pendingParentRequests.set(n,{resolve:r,reject:o,timer:a}),this.write({jsonrpc:"2.0",id:n,method:e,params:t})})}handleParentResponse(e){const t=Number(e.id),s=this.pendingParentRequests.get(t);if(s){if(this.pendingParentRequests.delete(t),clearTimeout(s.timer),"error"in e){const n=u(e.error);s.reject(new Error(c(n,"message")||"ACP client request failed"));return}s.resolve(e.result)}}setConfigOption(e){const t=c(e,"configId"),s=e.value;if(!t)throw new Error("configId is required");if(typeof s!="string"&&typeof s!="boolean")throw new Error("config value must be string or boolean");return this.config[t]=s,this.notify("session/update",{sessionId:this.currentSessionId,update:{sessionUpdate:"config_option_update",configId:t,value:s}}),{}}setMode(e){const t=c(e,"modeId");if(!t)throw new Error("modeId is required");return this.config.sandbox=t,this.notify("session/update",{sessionId:this.currentSessionId,update:{sessionUpdate:"current_mode_update",modeId:t}}),{}}applyInitialConfig(e){const t=p(e,"config");for(const[s,n]of Object.entries(t))(typeof n=="string"||typeof n=="boolean")&&(this.config[s]=n)}codexConfig(){return{...typeof this.config.model=="string"&&this.config.model?{model:this.config.model}:{},approvalPolicy:typeof this.config.approvalPolicy=="string"?this.config.approvalPolicy:"on-request",sandbox:typeof this.config.sandbox=="string"?this.config.sandbox:"workspace-write"}}captureContextNotification(e,t){if(e==="thread/tokenUsage/updated"&&(this.latestTokenUsage=j(t)??this.latestTokenUsage),e==="thread/compacted"&&this.pendingCompaction&&this.resolveCompaction(),e==="item/completed"){const s=p(t,"item"),n=c(u(t),"threadId");c(s,"type")==="contextCompaction"&&(!n||n===this.currentSessionId)&&this.resolveCompaction(),c(s,"type")==="agentMessage"&&c(s,"phase")==="final_answer"&&(this.currentAssistantText=f(s)||this.currentAssistantText)}}resolveCompaction(){if(!this.pendingCompaction)return;const e=this.pendingCompaction;this.pendingCompaction=null,clearTimeout(e.timer),e.resolve()}captureUpdateEvidence(e){String(e.sessionUpdate||"")==="agent_message_chunk"&&(this.currentAssistantText+=f(e.content)),g(e,this.currentAffectedFiles)}captureThreadMetadata(e){const t=p(e,"thread");this.currentRolloutPath=c(t,"path")||null,this.threadTurnCount=Array.isArray(t.turns)?t.turns.length:0;const s=G(t.turns);s.userRequest&&(this.previousUserText=s.userRequest),s.assistantResponse&&(this.previousAssistantText=s.assistantResponse),this.previousAffectedFiles.clear();for(const n of s.affectedFiles)this.previousAffectedFiles.add(n);this.latestTokenUsage=null}async maintainContext(e,t,s={}){const n=k(),r=this.contextState(),o=b(r,n);if(!o.compact&&!s.force||!this.currentSessionId)return this.maintenanceResult({stage:e,action:"none",reasons:o.reasons,beforeState:r});const a=this.currentSessionId;this.notifyContextStatus("正在整理会话上下文",P(r)),this.maintenanceActive=!0;let d=!1,l="",y=r,m=o,I=!1,C="";try{const h=r.usage?.observedAtMs??0;await this.compactThread(a,s.compactTimeoutMs??n.compactTimeoutMs),await this.waitForTokenUsageAfter(h,2e3)}catch(h){d=!0,l=h instanceof Error?h.message:String(h)}try{if(y=this.contextState(),m=b(y,n,{compactAttempted:!0,compactFailed:d}),m.rollover&&s.allowRollover!==!1){this.notifyContextStatus("正在创建轻量会话",m.reasons.join(", "));try{await this.rotateThread(a,t),I=!0}catch(h){C=h instanceof Error?h.message:String(h),this.notifyContextStatus("轻量会话创建失败",C)}}else d||this.notifyContextStatus("会话上下文已压缩",P(y))}finally{this.maintenanceActive=!1}return this.maintenanceResult({action:I?"rollover":C?"rollover_failed":d?"compact_failed":"compact",stage:e,reasons:m.reasons,beforeState:r,afterState:y,compactError:[l,C].filter(Boolean).join("; "),previousThreadId:a,rolloverRecommended:m.rollover&&s.allowRollover===!1})}compactThread(e,t){return this.pendingCompaction?Promise.reject(new Error("Codex context compaction is already running")):new Promise((s,n)=>{const r=setTimeout(()=>{this.pendingCompaction?.timer===r&&(this.pendingCompaction=null),n(new Error("Codex thread compaction timed out"))},t);r.unref(),this.pendingCompaction={resolve:s,reject:n,timer:r},this.requireRpc().request("thread/compact/start",{threadId:e},t).catch(o=>{this.pendingCompaction?.timer===r&&(this.pendingCompaction=null,clearTimeout(r),n(o instanceof Error?o:new Error(String(o))))})})}async rotateThread(e,t){const s=N({previousThreadId:e,cwd:this.currentCwd,userRequest:t.userRequest,assistantResponse:t.assistantResponse,affectedFiles:t.affectedFiles}),n=await this.requireRpc().request("thread/start",{cwd:this.currentCwd,approvalsReviewer:"user",...this.codexConfig(),developerInstructions:s,ephemeral:!1,threadSource:"aca-codex-acp-rollover"},6e4),r=S(n);if(!r)throw new Error("Codex rollover thread/start did not return thread id");this.sessionAliases.set(e,r),this.currentSessionId=r,this.resetSubtaskState(n),this.captureThreadMetadata(n)}async waitForTokenUsageAfter(e,t){const s=Date.now()+t;for(;Date.now()<s;){if((this.latestTokenUsage?.observedAtMs??0)>e)return;await Y(50)}}resolveSessionAlias(e){if(!e)return null;let t=e;const s=new Set;for(;this.sessionAliases.has(t)&&!s.has(t);)s.add(t),t=this.sessionAliases.get(t)??t;return t}contextState(){return{usage:this.latestTokenUsage,rolloutBytes:D(this.currentRolloutPath),turnCount:this.threadTurnCount}}maintenanceResult(e){return{stage:e.stage,action:e.action,reasons:e.reasons,previousThreadId:e.previousThreadId??null,sessionId:this.currentSessionId,before:e.beforeState,after:e.afterState??null,compactError:e.compactError||null,rolloverRecommended:e.rolloverRecommended===!0}}notifyContextStatus(e,t){this.notify("session/update",{sessionId:this.currentSessionId,update:{sessionUpdate:"aca_context_maintenance",label:e,detail:t}})}write(e){process.stdout.write(`${JSON.stringify(e)}
3
+ `)}}function z(i){return i.map(e=>{const t=u(e);if(t.type==="image"){const s=c(t,"uri");if(s)return{type:"localImage",path:s};const n=c(t,"data");return{type:"image",url:`data:${c(t,"mimeType")||"image/png"};base64,${n}`}}return{type:"text",text:c(t,"text"),text_elements:[]}})}function W(i){return i.map(e=>c(u(e),"text")).filter(Boolean).join(`
4
4
 
5
- `)}function B(n){const e={};typeof n.model=="string"&&n.model&&(e.model=n.model),typeof n.approvalPolicy=="string"&&n.approvalPolicy&&(e.approvalPolicy=n.approvalPolicy),typeof n.sandbox=="string"&&n.sandbox&&(e.sandbox=n.sandbox);const t=n.reasoning_effort??n.reasoningEffort??n.model_reasoning_effort??n.modelReasoningEffort??n.effort;return typeof t=="string"&&t&&(e.effort=t),e}function C(n){const e=h(n,"thread");return a(e,"id")||null}function h(n,e){const t=u(n);return u(t[e])}function u(n){return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}function f(n){if(typeof n=="string")return n;if(Array.isArray(n))return n.map(f).filter(Boolean).join("");if(!n||typeof n!="object")return"";const e=u(n);for(const t of["text","message","content","output_text"]){const s=f(e[t]);if(s)return s}return""}function x(n,e){if(Array.isArray(n)){for(const o of n)x(o,e);return}const t=u(n),s=a(t,"type").toLowerCase(),r=a(t,"path");if(r&&["diff","resource_link","content"].includes(s)&&e.add(r),Array.isArray(t.locations))for(const o of t.locations){const i=a(u(o),"path");i&&e.add(i)}for(const o of[t.content,t.update,t.rawInput,t.rawOutput])o&&o!==n&&x(o,e)}function z(n){if(!Array.isArray(n)||n.length===0)return{userRequest:"",assistantResponse:"",affectedFiles:[]};const e=n.at(-1),t=new Set;x(e,t);let s="",r="";const o=i=>{if(Array.isArray(i)){for(const l of i)o(l);return}if(!i||typeof i!="object")return;const c=u(i),d=a(c,"type").toLowerCase();d==="usermessage"&&(s=f(c)||s),d==="agentmessage"&&(r=f(c)||r);for(const l of["items","content","input"])c[l]&&o(c[l])};return o(e),{userRequest:s,assistantResponse:r,affectedFiles:[...t]}}function W(n,e){const t=w(n,"timeoutMs");return!Number.isFinite(t)||t<=0?e:Math.max(3e4,Math.min(59e4,t-1e4))}function L(n){const e=String(n.action||"none"),t=u(n.after),s=u(n.before),r=u(t.usage),o=u(s.usage),i=Object.keys(r).length>0?r:o,c=w(i,"contextWindow");if(e==="rollover")return{usedTokens:0,inputTokens:0,contextWindow:c,ratio:0,observedAtMs:Date.now(),state:"new_thread",maintenanceAction:e};if(Object.keys(i).length===0)return null;const d=w(i,"totalTokens"),l=w(i,"inputTokens");return{usedTokens:d||l,inputTokens:l,contextWindow:c,ratio:c>0?(d||l)/c:0,observedAtMs:w(i,"observedAtMs")||Date.now(),state:e==="compact"?"compacted":"active",maintenanceAction:e}}function G(n){return n?{usedTokens:n.totalTokens||n.inputTokens,inputTokens:n.inputTokens,contextWindow:n.contextWindow,ratio:n.contextWindow>0?(n.totalTokens||n.inputTokens)/n.contextWindow:0,observedAtMs:n.observedAtMs,state:"active",maintenanceAction:null}:null}function A(n){const e=n.usage?`${n.usage.inputTokens} tokens`:"token unknown",t=n.rolloutBytes>0?`${Math.round(n.rolloutBytes/1024/1024)}MB rollout`:"rollout unknown";return`${e}, ${t}, ${n.turnCount} turns`}function w(n,e){const t=u(n)[e];return typeof t=="number"&&Number.isFinite(t)?t:0}function a(n,e){const s=u(n)[e];return typeof s=="string"?s:""}function J(n){const e=n.toLowerCase();return e.includes("elicitation")||e.includes("requestuserinput")||e.includes("request_user_input")||e.includes("input/request")}function R(){const n=Number.parseInt(process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(n)&&n>=3e4?n:360*60*1e3}function T(n,e){return n.exitCode!==null||n.signalCode!==null?Promise.resolve(!0):new Promise(t=>{const s=setTimeout(()=>t(!1),e);s.unref(),n.once("close",()=>{clearTimeout(s),t(!0)})})}function K(n){return new Promise(e=>setTimeout(e,n))}function V(){new O}const H=process.argv[1]||"";/(?:^|[\\/])adapter\.(?:js|ts)$/.test(H)&&V();export{V as runCodexAcpAdapter};
5
+ `)}function L(i){const e={};typeof i.model=="string"&&i.model&&(e.model=i.model),typeof i.approvalPolicy=="string"&&i.approvalPolicy&&(e.approvalPolicy=i.approvalPolicy),typeof i.sandbox=="string"&&i.sandbox&&(e.sandbox=i.sandbox);const t=i.reasoning_effort??i.reasoningEffort??i.model_reasoning_effort??i.modelReasoningEffort??i.effort;return typeof t=="string"&&t&&(e.effort=t),e}function S(i){const e=p(i,"thread");return c(e,"id")||null}function p(i,e){const t=u(i);return u(t[e])}function u(i){return i&&typeof i=="object"&&!Array.isArray(i)?i:{}}function f(i){if(typeof i=="string")return i;if(Array.isArray(i))return i.map(f).filter(Boolean).join("");if(!i||typeof i!="object")return"";const e=u(i);for(const t of["text","message","content","output_text"]){const s=f(e[t]);if(s)return s}return""}function g(i,e){if(Array.isArray(i)){for(const r of i)g(r,e);return}const t=u(i),s=c(t,"type").toLowerCase(),n=c(t,"path");if(n&&["diff","resource_link","content"].includes(s)&&e.add(n),Array.isArray(t.locations))for(const r of t.locations){const o=c(u(r),"path");o&&e.add(o)}for(const r of[t.content,t.update,t.rawInput,t.rawOutput])r&&r!==i&&g(r,e)}function G(i){if(!Array.isArray(i)||i.length===0)return{userRequest:"",assistantResponse:"",affectedFiles:[]};const e=i.at(-1),t=new Set;g(e,t);let s="",n="";const r=o=>{if(Array.isArray(o)){for(const l of o)r(l);return}if(!o||typeof o!="object")return;const a=u(o),d=c(a,"type").toLowerCase();d==="usermessage"&&(s=f(a)||s),d==="agentmessage"&&(n=f(a)||n);for(const l of["items","content","input"])a[l]&&r(a[l])};return r(e),{userRequest:s,assistantResponse:n,affectedFiles:[...t]}}function J(i,e){const t=w(i,"timeoutMs");return!Number.isFinite(t)||t<=0?e:Math.max(3e4,Math.min(59e4,t-1e4))}function K(i){const e=String(i.action||"none"),t=u(i.after),s=u(i.before),n=u(t.usage),r=u(s.usage),o=Object.keys(n).length>0?n:r,a=w(o,"contextWindow");if(e==="rollover")return{usedTokens:0,inputTokens:0,contextWindow:a,ratio:0,observedAtMs:Date.now(),state:"new_thread",maintenanceAction:e};if(Object.keys(o).length===0)return null;const d=w(o,"totalTokens"),l=w(o,"inputTokens");return{usedTokens:d||l,inputTokens:l,contextWindow:a,ratio:a>0?(d||l)/a:0,observedAtMs:w(o,"observedAtMs")||Date.now(),state:e==="compact"?"compacted":"active",maintenanceAction:e}}function V(i){return i?{usedTokens:i.totalTokens||i.inputTokens,inputTokens:i.inputTokens,contextWindow:i.contextWindow,ratio:i.contextWindow>0?(i.totalTokens||i.inputTokens)/i.contextWindow:0,observedAtMs:i.observedAtMs,state:"active",maintenanceAction:null}:null}function P(i){const e=i.usage?`${i.usage.inputTokens} tokens`:"token unknown",t=i.rolloutBytes>0?`${Math.round(i.rolloutBytes/1024/1024)}MB rollout`:"rollout unknown";return`${e}, ${t}, ${i.turnCount} turns`}function w(i,e){const t=u(i)[e];return typeof t=="number"&&Number.isFinite(t)?t:0}function H(i){return["agent_message_chunk","agent_progress_chunk","agent_thought_chunk","tool_call","tool_call_update","plan","plan_update","plan_removed"].includes(String(i.sessionUpdate||""))}function Q(i,e,t){const s=String(i.sessionUpdate||""),n={...i};if(s==="tool_call"||s==="tool_call_update"){const a=c(i,"toolCallId");a&&(n.toolCallId=R(e.sourceThreadId,a))}if(s==="plan"||s==="plan_update"||s==="plan_removed"){const a=c(i,"planId")||c(i,"plan_id")||c(i,"id")||"current";n.planId=R(e.sourceThreadId,a),delete n.plan_id}const r=u(i._meta),o=u(r.aca);return n._meta={...r,aca:{...o,subtask:{parentToolCallId:e.parentToolCallId,sourceThreadId:e.sourceThreadId,sourceTurnId:t,depth:e.depth}}},n}function R(i,e){return`subtask.${i}.${e}`}function c(i,e){const s=u(i)[e];return typeof s=="string"?s:""}function X(i){const e=i.toLowerCase();return e.includes("elicitation")||e.includes("requestuserinput")||e.includes("request_user_input")||e.includes("input/request")}function _(){const i=Number.parseInt(process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(i)&&i>=3e4?i:360*60*1e3}function x(i,e){return i.exitCode!==null||i.signalCode!==null?Promise.resolve(!0):new Promise(t=>{const s=setTimeout(()=>t(!1),e);s.unref(),i.once("close",()=>{clearTimeout(s),t(!0)})})}function Y(i){return new Promise(e=>setTimeout(e,i))}function Z(){new B}const ee=process.argv[1]||"";/(?:^|[\\/])adapter\.(?:js|ts)$/.test(ee)&&Z();export{Z as runCodexAcpAdapter};
@@ -1 +1 @@
1
- import d from"node:fs";import{runAbortableRequest as w}from"../../client/abortable-request.js";import{BoundedItemBuffer as P}from"../../client/bounded-buffer.js";import{promptBlocksToAcpContent as k}from"../../client/acp-content.js";import{eventFromAcpSessionUpdate as R,statusFromAcpSessionUpdate as M}from"../../client/acp-events.js";import{defaultAcpRuntimePool as S}from"../../client/acp-runtime-pool.js";import{resolveCodexAcpLaunch as y}from"./launch.js";import{CodexPromptPerformanceTracker as T,readCodexContextMaintenancePolicy as _}from"./context-maintenance.js";import{ensureCodexProviderRuntimeConfig as g}from"../../../core/codex-provider-runtime-config.js";const q={sessionResume:!0,imageInput:!0,fileAttachment:!0,filesystem:!0,terminal:!0,permissionRequest:!0,configOptions:!0,usage:!0,contextUsage:!0,contextCompaction:!0,plan:!0,diff:!0};class Y{id="codex-acp";name="Codex ACP";capabilities=q;async createSession(e){return new E(e.cwd,e.providerSessionId??null,e.timeoutMs)}async forkSession(e){if(!d.existsSync(e.cwd)||!d.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);const s=e.sourceProviderSessionId.trim(),o=await g(),r=await S.acquire({providerId:"codex-acp",cwd:e.cwd,providerSessionId:s,runtimeIdentity:o?.runtimeIdentity||"default",env:b(o),...y(),onSessionUpdate:()=>{}});try{await I(r,o),r.initialized||(await r.client.initialize(6e4),r.markInitialized()),e.onStatus?.({phase:"forking",label:"正在分叉 Codex 会话",detail:s,updateType:"session/fork",atMs:Date.now()});const n=await r.client.forkSession({sessionId:s,cwd:e.cwd,config:C(e)},e.timeoutMs??12e4),i=p(n);if(!i)throw new Error("Codex ACP session/fork did not return sessionId");return{providerSessionId:i}}finally{r.release()}}}class E{cwd;providerSessionId;defaultTimeoutMs;lease=null;sessionResponse=null;statusCallback=null;updateCallback=null;permissionCallback=null;userInputCallback=null;abortHandler=null;statusTimeline=[];updates=new P(16);content="";performanceTracker=null;constructor(e,s,o=j()){this.cwd=e,this.providerSessionId=s,this.defaultTimeoutMs=o}async sendPrompt(e){if(!d.existsSync(e.cwd)||!d.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);const s=Date.now();this.statusCallback=e.onStatus??null,this.updateCallback=e.onUpdate??null,this.permissionCallback=e.onPermissionRequest??null,this.userInputCallback=e.onUserInputRequest??null,this.attachAbortSignal(e.signal),this.content="",this.updates.clear(),this.statusTimeline.length=0,this.performanceTracker=new T(s);let o=null,r=null,n=this.providerSessionId,i,c=null;try{this.emitStatus("initializing","Codex ACP 启动中","codex-acp");const a=await this.acquireRuntime(e.cwd);this.lease=a,o=a.client,r=a.started,await this.initialize(a),n=await this.establishSession(a,e),await this.applyConfig(o,n,e),this.emitStatus("thinking","思考中"),c=this.startSlowStatusTimer(),i=await this.promptWithAbort(o,{sessionId:n,prompt:k(e.prompt,e.promptBlocks),timeoutMs:e.timeoutMs??this.defaultTimeoutMs,signal:e.signal});const u=A(i);u&&u!==n&&(n=u,this.providerSessionId=u,a.setProviderSession({providerSessionId:u,sessionResponse:this.sessionResponse}))}finally{c&&clearInterval(c),this.abortHandler&&e.signal&&(e.signal.removeEventListener("abort",this.abortHandler),this.abortHandler=null),this.releaseLease()}return this.emitStatus("completed","已完成"),{providerSessionId:n,cliType:"builtin",agentType:"codex",effectiveConfig:{model:e.model??null,mode:e.mode??null,configOptionValues:e.configOptionValues??null,command:r.command,processPid:r.child.pid??null,provider:"codex-acp",protocol:"acp"},command:r.command,args:r.args,cwd:e.cwd,exitCode:r.child.exitCode,signal:r.child.signalCode,durationMs:Date.now()-s,stdout:o.rpc.stdout,stderr:o.rpc.stderr,content:this.content.trim(),updateCount:this.updates.count(),updates:this.updates.snapshot(),statusTimeline:[...this.statusTimeline],performance:this.performanceTracker?.snapshot(),contextUsage:H(i),promptResponse:i}}async compactContext(e){if(!d.existsSync(e.cwd)||!d.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);const s=Date.now();this.statusCallback=e.onStatus??null,this.updateCallback=e.onUpdate??null,this.attachAbortSignal(e.signal);let o=this.providerSessionId,r;try{this.emitStatus("initializing","Codex ACP 启动中","codex-acp");const i=await this.acquireRuntime(e.cwd);this.lease=i,await this.initialize(i),o=await this.establishSession(i,e),await this.applyConfig(i.client,o,e);const c=z(e.timeoutMs);r=await this.compactWithAbort(i.client,{sessionId:o,allowRollover:e.allowRollover===!0,timeoutMs:c,signal:e.signal});const a=A(r);a&&a!==o&&(o=a,this.providerSessionId=a,i.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}))}catch(i){if(this.lease&&U(i,e.signal)){const c=this.lease;this.lease=null,await c.dispose().catch(()=>{})}throw this.emitStatus("failed","上下文压缩失败",i instanceof Error?i.message:String(i)),i}finally{this.abortHandler&&e.signal&&(e.signal.removeEventListener("abort",this.abortHandler),this.abortHandler=null),this.releaseLease()}const n=l(r)??{};return{providerSessionId:o||this.providerSessionId||"",contextUsage:x(n.contextUsage),maintenance:l(n.maintenance)??{},durationMs:Date.now()-s}}async cancel(){this.providerSessionId&&this.lease?.client.cancel(this.providerSessionId)}async close(){this.statusCallback=null,this.updateCallback=null,this.permissionCallback=null,this.userInputCallback=null,this.abortHandler&&(this.abortHandler=null),this.releaseLease()}async acquireRuntime(e){const s=y(),o=await g(),r=await S.acquire({providerId:"codex-acp",cwd:e,providerSessionId:this.providerSessionId,runtimeIdentity:o?.runtimeIdentity||"default",env:b(o),command:s.command,args:s.args,onSessionUpdate:n=>this.handleSessionUpdate(n),onClientRequest:async(n,i)=>{if(n==="session/request_permission")return this.requestPermission(i);if(n==="elicitation/create"||n==="session/request_user_input")return this.requestUserInput(i);throw new Error(`Unsupported Codex ACP client request: ${n}`)}});try{return await I(r,o),r}catch(n){throw await r.dispose().catch(()=>{}),n}}async initialize(e){e.initialized||(await e.client.initialize(6e4),e.markInitialized())}async establishSession(e,s){const o=e.client,r=C(s);if(e.providerSessionId&&e.sessionEstablished)return this.providerSessionId=e.providerSessionId,this.sessionResponse=e.sessionResponse,e.providerSessionId;if(this.providerSessionId)try{this.emitStatus("resuming","Codex ACP 会话恢复中","session/load");const c=await o.loadSession({sessionId:this.providerSessionId,cwd:s.cwd,config:r},6e4);this.sessionResponse=l(c);const a=p(c)||this.providerSessionId;return this.providerSessionId=a,e.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}),a}catch(c){if(s.requireSessionResume){const a=c instanceof Error?c.message:String(c);throw new Error(`无法恢复导入的 Codex ACP Session ${this.providerSessionId}:${a}`)}this.providerSessionId=null}this.emitStatus("acp","Codex ACP 会话创建中","session/new");const n=await o.newSession({cwd:s.cwd,config:r},12e4);this.sessionResponse=l(n);const i=p(n);if(!i)throw new Error("Codex ACP session/new did not return sessionId");return this.providerSessionId=i,e.setProviderSession({providerSessionId:i,sessionResponse:this.sessionResponse}),i}async applyConfig(e,s,o){o.model&&await e.setSessionConfigOption({sessionId:s,configId:"model",value:o.model},6e4).catch(()=>{});const r=f(o.mode);r&&await e.setSessionConfigOption({sessionId:s,configId:"approvalPolicy",value:r},6e4).catch(()=>{});const n=h(o.mode);n&&await e.setSessionConfigOption({sessionId:s,configId:"sandbox",value:n},6e4).catch(()=>{});for(const[i,c]of Object.entries(o.configOptionValues??{}))["model","mode","sandbox","approvalPolicy"].includes(i)||await e.setSessionConfigOption({sessionId:s,configId:i,value:c},6e4).catch(()=>{})}handleSessionUpdate(e){this.performanceTracker?.recordEvent(),this.updates.push({method:"session/update",params:e});const s=R(e);s&&(s.type==="agent_message_chunk"&&(this.content+=s.text??""),this.updateCallback?.(s));const o=M(e);o&&this.emitStatus(o.phase,o.label,o.detail,o.updateType)}startSlowStatusTimer(){const e=_().slowEventThresholdMs,s=setInterval(()=>{const o=this.performanceTracker,r=Date.now();if(!o?.shouldReportSlow(r,e))return;const n=o.snapshot(r),i=Math.max(1,Math.round(n.silentForMs/6e4));this.emitStatus("thinking","模型长时间处理中",`已 ${i} 分钟没有收到新的 ACP 事件`,"aca.performance.slow")},Math.min(3e4,Math.max(1e3,Math.floor(e/4))));return s.unref(),s}attachAbortSignal(e){if(e){if(this.abortHandler=()=>{this.cancel()},e.aborted)throw new Error("Codex ACP prompt cancelled");e.addEventListener("abort",this.abortHandler,{once:!0})}}async promptWithAbort(e,s){return w({signal:s.signal,cancelledMessage:"Codex ACP prompt cancelled",startRequest:()=>e.prompt({sessionId:s.sessionId,prompt:s.prompt},s.timeoutMs),onAbort:async()=>{e.cancel(s.sessionId),await this.lease?.dispose()}})}async compactWithAbort(e,s){return w({signal:s.signal,cancelledMessage:"Codex ACP 上下文压缩已取消",startRequest:()=>e.compactSession({sessionId:s.sessionId,allowRollover:s.allowRollover,timeoutMs:s.timeoutMs},s.timeoutMs),onAbort:async()=>{e.cancel(s.sessionId),await this.lease?.dispose()}})}async requestPermission(e){if(!this.permissionCallback)return{outcome:{outcome:"cancelled"}};const s=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s,n=(Array.isArray(o.options)?o.options:[]).map((i,c)=>{const a=i&&typeof i=="object"&&!Array.isArray(i)?i:{};return{optionId:String(a.optionId??a.id??c),kind:String(a.kind??"choice"),...typeof a.label=="string"?{label:a.label}:{}}});return this.emitStatus("requestPermission","等待授权",O(o),"session/request_permission"),this.permissionCallback({requestId:String(o.requestId??o.id??`codex-acp-permission-${Date.now()}`),params:e,options:n})}async requestUserInput(e){if(!this.userInputCallback)return{outcome:{outcome:"cancelled"}};const s=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s;return this.emitStatus("requestPermission","等待输入",D(o),"elicitation/create"),this.userInputCallback({requestId:String(o.requestId??o.id??`codex-acp-input-${Date.now()}`),prompt:String(o.prompt??o.message??o.question??""),params:e,...typeof o.defaultValue=="string"?{defaultValue:o.defaultValue}:{}})}emitStatus(e,s,o,r){const n={phase:e,label:s,...o?{detail:o}:{},...r?{updateType:r}:{},atMs:Date.now()},i=this.statusTimeline[this.statusTimeline.length-1];i&&i.phase===n.phase&&i.label===n.label&&i.detail===n.detail&&i.updateType===n.updateType||(this.statusTimeline.push(n),this.statusCallback?.(n))}releaseLease(){this.lease?.release(),this.lease=null}}async function I(t,e){t.runtimeConfigured||(await t.client.configureRuntime({codexProvider:e?{baseUrl:e.baseUrl,apiKey:e.apiKey,revision:e.revision}:null}),t.markRuntimeConfigured())}function b(t){return t?{OPENAI_API_KEY:t.apiKey,OPENAI_BASE_URL:t.baseUrl}:{}}function U(t,e){if(e?.aborted)return!0;const s=t instanceof Error?t.message:String(t||"");return/compact.*timed out|request timed out.*compact|adapter closed|aborted|cancelled/i.test(s)}function p(t){if(!t||typeof t!="object"||Array.isArray(t))return null;const e=t.sessionId;return typeof e=="string"&&e.trim()?e.trim():null}function l(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function h(t){const e=String(t||"").trim();return e?e==="read-only"?"read-only":["agent-full-access","full-access","bypassPermissions","danger-full-access"].includes(e)?"danger-full-access":"workspace-write":null}function f(t){const e=String(t||"").trim();return e?["agent-full-access","full-access","bypassPermissions","danger-full-access"].includes(e)?"never":e==="acceptEdits"||e==="accept-edits"?"on-failure":"on-request":null}function C(t){return{...t.model?{model:t.model}:{},...f(t.mode)?{approvalPolicy:f(t.mode)}:{},...h(t.mode)?{sandbox:h(t.mode)}:{},...t.configOptionValues??{}}}function O(t){const e=t.params&&typeof t.params=="object"&&!Array.isArray(t.params)?t.params:t;for(const s of["command","cwd","reason","grantRoot","method"]){const o=e[s];if(typeof o=="string"&&o.trim())return v(o)}}function D(t){for(const e of["prompt","message","question","title"]){const s=t[e];if(typeof s=="string"&&s.trim())return v(s)}}function v(t){const e=t.replace(/\s+/g," ").trim();return e.length>120?`${e.slice(0,117)}...`:e}function j(){const t=Number.parseInt(process.env.ACA_CODEX_ACP_PROMPT_TIMEOUT_MS??process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(t)&&t>=3e4?t:360*60*1e3}function z(t){const e=Number.isInteger(t)?Number(t):Number.parseInt(process.env.ACA_CODEX_ACP_COMPACT_TIMEOUT_MS??"",10);return Number.isFinite(e)&&e>=3e4?Math.min(e,6e5):12e4}function A(t){if(!t||typeof t!="object"||Array.isArray(t))return null;const e=t;return typeof e.sessionId=="string"&&e.sessionId.trim()?e.sessionId:null}function H(t){const e=l(t),s=l(e?._meta);return x(s?.acaContextUsage)}function x(t){const e=l(t);if(!e)return null;const s=m(e.contextWindow),o=m(e.usedTokens),r=m(e.inputTokens),n=String(e.state||"unknown"),i=["active","compacted","new_thread"].includes(n)?n:"unknown";return{usedTokens:o,inputTokens:r,contextWindow:s,ratio:s>0?Math.max(0,m(e.ratio)||o/s):0,observedAtMs:m(e.observedAtMs)||Date.now(),state:i,maintenanceAction:typeof e.maintenanceAction=="string"?e.maintenanceAction:null}}function m(t){return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:0}export{Y as CodexAcpProvider,q as codexAcpCapabilities};
1
+ import l from"node:fs";import{runAbortableRequest as w}from"../../client/abortable-request.js";import{BoundedItemBuffer as P}from"../../client/bounded-buffer.js";import{promptBlocksToAcpContent as k}from"../../client/acp-content.js";import{eventFromAcpSessionUpdate as R,statusFromAcpSessionUpdate as M,subtaskContextFromAcpSessionUpdate as T}from"../../client/acp-events.js";import{defaultAcpRuntimePool as S}from"../../client/acp-runtime-pool.js";import{resolveCodexAcpLaunch as y}from"./launch.js";import{CodexPromptPerformanceTracker as _,readCodexContextMaintenancePolicy as q}from"./context-maintenance.js";import{ensureCodexProviderRuntimeConfig as g}from"../../../core/codex-provider-runtime-config.js";const E={sessionResume:!0,imageInput:!0,fileAttachment:!0,filesystem:!0,terminal:!0,permissionRequest:!0,configOptions:!0,usage:!0,contextUsage:!0,contextCompaction:!0,plan:!0,diff:!0};class G{id="codex-acp";name="Codex ACP";capabilities=E;async createSession(e){return new U(e.cwd,e.providerSessionId??null,e.timeoutMs)}async forkSession(e){if(!l.existsSync(e.cwd)||!l.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);const s=e.sourceProviderSessionId.trim(),o=await g(),n=await S.acquire({providerId:"codex-acp",cwd:e.cwd,providerSessionId:s,runtimeIdentity:o?.runtimeIdentity||"default",env:I(o),...y(),onSessionUpdate:()=>{}});try{await b(n,o),n.initialized||(await n.client.initialize(6e4),n.markInitialized()),e.onStatus?.({phase:"forking",label:"正在分叉 Codex 会话",detail:s,updateType:"session/fork",atMs:Date.now()});const r=await n.client.forkSession({sessionId:s,cwd:e.cwd,config:C(e)},e.timeoutMs??12e4),i=p(r);if(!i)throw new Error("Codex ACP session/fork did not return sessionId");return{providerSessionId:i}}finally{n.release()}}}class U{cwd;providerSessionId;defaultTimeoutMs;lease=null;sessionResponse=null;statusCallback=null;updateCallback=null;permissionCallback=null;userInputCallback=null;abortHandler=null;statusTimeline=[];updates=new P(16);content="";performanceTracker=null;constructor(e,s,o=z()){this.cwd=e,this.providerSessionId=s,this.defaultTimeoutMs=o}async sendPrompt(e){if(!l.existsSync(e.cwd)||!l.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);const s=Date.now();this.statusCallback=e.onStatus??null,this.updateCallback=e.onUpdate??null,this.permissionCallback=e.onPermissionRequest??null,this.userInputCallback=e.onUserInputRequest??null,this.attachAbortSignal(e.signal),this.content="",this.updates.clear(),this.statusTimeline.length=0,this.performanceTracker=new _(s);let o=null,n=null,r=this.providerSessionId,i,c=null;try{this.emitStatus("initializing","Codex ACP 启动中","codex-acp");const a=await this.acquireRuntime(e.cwd);this.lease=a,o=a.client,n=a.started,await this.initialize(a),r=await this.establishSession(a,e),await this.applyConfig(o,r,e),this.emitStatus("thinking","思考中"),c=this.startSlowStatusTimer(),i=await this.promptWithAbort(o,{sessionId:r,prompt:k(e.prompt,e.promptBlocks),timeoutMs:e.timeoutMs??this.defaultTimeoutMs,signal:e.signal});const u=A(i);u&&u!==r&&(r=u,this.providerSessionId=u,a.setProviderSession({providerSessionId:u,sessionResponse:this.sessionResponse}))}finally{c&&clearInterval(c),this.abortHandler&&e.signal&&(e.signal.removeEventListener("abort",this.abortHandler),this.abortHandler=null),this.releaseLease()}return this.emitStatus("completed","已完成"),{providerSessionId:r,cliType:"builtin",agentType:"codex",effectiveConfig:{model:e.model??null,mode:e.mode??null,configOptionValues:e.configOptionValues??null,command:n.command,processPid:n.child.pid??null,provider:"codex-acp",protocol:"acp"},command:n.command,args:n.args,cwd:e.cwd,exitCode:n.child.exitCode,signal:n.child.signalCode,durationMs:Date.now()-s,stdout:o.rpc.stdout,stderr:o.rpc.stderr,content:this.content.trim(),updateCount:this.updates.count(),updates:this.updates.snapshot(),statusTimeline:[...this.statusTimeline],performance:this.performanceTracker?.snapshot(),contextUsage:H(i),promptResponse:i}}async compactContext(e){if(!l.existsSync(e.cwd)||!l.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);const s=Date.now();this.statusCallback=e.onStatus??null,this.updateCallback=e.onUpdate??null,this.attachAbortSignal(e.signal);let o=this.providerSessionId,n;try{this.emitStatus("initializing","Codex ACP 启动中","codex-acp");const i=await this.acquireRuntime(e.cwd);this.lease=i,await this.initialize(i),o=await this.establishSession(i,e),await this.applyConfig(i.client,o,e);const c=F(e.timeoutMs);n=await this.compactWithAbort(i.client,{sessionId:o,allowRollover:e.allowRollover===!0,timeoutMs:c,signal:e.signal});const a=A(n);a&&a!==o&&(o=a,this.providerSessionId=a,i.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}))}catch(i){if(this.lease&&O(i,e.signal)){const c=this.lease;this.lease=null,await c.dispose().catch(()=>{})}throw this.emitStatus("failed","上下文压缩失败",i instanceof Error?i.message:String(i)),i}finally{this.abortHandler&&e.signal&&(e.signal.removeEventListener("abort",this.abortHandler),this.abortHandler=null),this.releaseLease()}const r=d(n)??{};return{providerSessionId:o||this.providerSessionId||"",contextUsage:x(r.contextUsage),maintenance:d(r.maintenance)??{},durationMs:Date.now()-s}}async cancel(){this.providerSessionId&&this.lease?.client.cancel(this.providerSessionId)}async close(){this.statusCallback=null,this.updateCallback=null,this.permissionCallback=null,this.userInputCallback=null,this.abortHandler&&(this.abortHandler=null),this.releaseLease()}async acquireRuntime(e){const s=y(),o=await g(),n=await S.acquire({providerId:"codex-acp",cwd:e,providerSessionId:this.providerSessionId,runtimeIdentity:o?.runtimeIdentity||"default",env:I(o),command:s.command,args:s.args,onSessionUpdate:r=>this.handleSessionUpdate(r),onClientRequest:async(r,i)=>{if(r==="session/request_permission")return this.requestPermission(i);if(r==="elicitation/create"||r==="session/request_user_input")return this.requestUserInput(i);throw new Error(`Unsupported Codex ACP client request: ${r}`)}});try{return await b(n,o),n}catch(r){throw await n.dispose().catch(()=>{}),r}}async initialize(e){e.initialized||(await e.client.initialize(6e4),e.markInitialized())}async establishSession(e,s){const o=e.client,n=C(s);if(e.providerSessionId&&e.sessionEstablished)return this.providerSessionId=e.providerSessionId,this.sessionResponse=e.sessionResponse,e.providerSessionId;if(this.providerSessionId)try{this.emitStatus("resuming","Codex ACP 会话恢复中","session/load");const c=await o.loadSession({sessionId:this.providerSessionId,cwd:s.cwd,config:n},6e4);this.sessionResponse=d(c);const a=p(c)||this.providerSessionId;return this.providerSessionId=a,e.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}),a}catch(c){if(s.requireSessionResume){const a=c instanceof Error?c.message:String(c);throw new Error(`无法恢复导入的 Codex ACP Session ${this.providerSessionId}:${a}`)}this.providerSessionId=null}this.emitStatus("acp","Codex ACP 会话创建中","session/new");const r=await o.newSession({cwd:s.cwd,config:n},12e4);this.sessionResponse=d(r);const i=p(r);if(!i)throw new Error("Codex ACP session/new did not return sessionId");return this.providerSessionId=i,e.setProviderSession({providerSessionId:i,sessionResponse:this.sessionResponse}),i}async applyConfig(e,s,o){o.model&&await e.setSessionConfigOption({sessionId:s,configId:"model",value:o.model},6e4).catch(()=>{});const n=f(o.mode);n&&await e.setSessionConfigOption({sessionId:s,configId:"approvalPolicy",value:n},6e4).catch(()=>{});const r=h(o.mode);r&&await e.setSessionConfigOption({sessionId:s,configId:"sandbox",value:r},6e4).catch(()=>{});for(const[i,c]of Object.entries(o.configOptionValues??{}))["model","mode","sandbox","approvalPolicy"].includes(i)||await e.setSessionConfigOption({sessionId:s,configId:i,value:c},6e4).catch(()=>{})}handleSessionUpdate(e){this.performanceTracker?.recordEvent(),this.updates.push({method:"session/update",params:e});const s=T(e),o=R(e);o&&(o.type==="agent_message_chunk"&&!s&&(this.content+=o.text??""),this.updateCallback?.(o));const n=M(e);n&&this.emitStatus(n.phase,n.label,n.detail,n.updateType)}startSlowStatusTimer(){const e=q().slowEventThresholdMs,s=setInterval(()=>{const o=this.performanceTracker,n=Date.now();if(!o?.shouldReportSlow(n,e))return;const r=o.snapshot(n),i=Math.max(1,Math.round(r.silentForMs/6e4));this.emitStatus("thinking","模型长时间处理中",`已 ${i} 分钟没有收到新的 ACP 事件`,"aca.performance.slow")},Math.min(3e4,Math.max(1e3,Math.floor(e/4))));return s.unref(),s}attachAbortSignal(e){if(e){if(this.abortHandler=()=>{this.cancel()},e.aborted)throw new Error("Codex ACP prompt cancelled");e.addEventListener("abort",this.abortHandler,{once:!0})}}async promptWithAbort(e,s){return w({signal:s.signal,cancelledMessage:"Codex ACP prompt cancelled",startRequest:()=>e.prompt({sessionId:s.sessionId,prompt:s.prompt},s.timeoutMs),onAbort:async()=>{e.cancel(s.sessionId),await this.lease?.dispose()}})}async compactWithAbort(e,s){return w({signal:s.signal,cancelledMessage:"Codex ACP 上下文压缩已取消",startRequest:()=>e.compactSession({sessionId:s.sessionId,allowRollover:s.allowRollover,timeoutMs:s.timeoutMs},s.timeoutMs),onAbort:async()=>{e.cancel(s.sessionId),await this.lease?.dispose()}})}async requestPermission(e){if(!this.permissionCallback)return{outcome:{outcome:"cancelled"}};const s=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s,r=(Array.isArray(o.options)?o.options:[]).map((i,c)=>{const a=i&&typeof i=="object"&&!Array.isArray(i)?i:{};return{optionId:String(a.optionId??a.id??c),kind:String(a.kind??"choice"),...typeof a.label=="string"?{label:a.label}:{}}});return this.emitStatus("requestPermission","等待授权",D(o),"session/request_permission"),this.permissionCallback({requestId:String(o.requestId??o.id??`codex-acp-permission-${Date.now()}`),params:e,options:r})}async requestUserInput(e){if(!this.userInputCallback)return{outcome:{outcome:"cancelled"}};const s=e&&typeof e=="object"&&!Array.isArray(e)?e:{},o=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s;return this.emitStatus("requestPermission","等待输入",j(o),"elicitation/create"),this.userInputCallback({requestId:String(o.requestId??o.id??`codex-acp-input-${Date.now()}`),prompt:String(o.prompt??o.message??o.question??""),params:e,...typeof o.defaultValue=="string"?{defaultValue:o.defaultValue}:{}})}emitStatus(e,s,o,n){const r={phase:e,label:s,...o?{detail:o}:{},...n?{updateType:n}:{},atMs:Date.now()},i=this.statusTimeline[this.statusTimeline.length-1];i&&i.phase===r.phase&&i.label===r.label&&i.detail===r.detail&&i.updateType===r.updateType||(this.statusTimeline.push(r),this.statusCallback?.(r))}releaseLease(){this.lease?.release(),this.lease=null}}async function b(t,e){t.runtimeConfigured||(await t.client.configureRuntime({codexProvider:e?{baseUrl:e.baseUrl,apiKey:e.apiKey,revision:e.revision}:null}),t.markRuntimeConfigured())}function I(t){return t?{OPENAI_API_KEY:t.apiKey,OPENAI_BASE_URL:t.baseUrl}:{}}function O(t,e){if(e?.aborted)return!0;const s=t instanceof Error?t.message:String(t||"");return/compact.*timed out|request timed out.*compact|adapter closed|aborted|cancelled/i.test(s)}function p(t){if(!t||typeof t!="object"||Array.isArray(t))return null;const e=t.sessionId;return typeof e=="string"&&e.trim()?e.trim():null}function d(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function h(t){const e=String(t||"").trim();return e?e==="read-only"?"read-only":["agent-full-access","full-access","bypassPermissions","danger-full-access"].includes(e)?"danger-full-access":"workspace-write":null}function f(t){const e=String(t||"").trim();return e?["agent-full-access","full-access","bypassPermissions","danger-full-access"].includes(e)?"never":e==="acceptEdits"||e==="accept-edits"?"on-failure":"on-request":null}function C(t){return{...t.model?{model:t.model}:{},...f(t.mode)?{approvalPolicy:f(t.mode)}:{},...h(t.mode)?{sandbox:h(t.mode)}:{},...t.configOptionValues??{}}}function D(t){const e=t.params&&typeof t.params=="object"&&!Array.isArray(t.params)?t.params:t;for(const s of["command","cwd","reason","grantRoot","method"]){const o=e[s];if(typeof o=="string"&&o.trim())return v(o)}}function j(t){for(const e of["prompt","message","question","title"]){const s=t[e];if(typeof s=="string"&&s.trim())return v(s)}}function v(t){const e=t.replace(/\s+/g," ").trim();return e.length>120?`${e.slice(0,117)}...`:e}function z(){const t=Number.parseInt(process.env.ACA_CODEX_ACP_PROMPT_TIMEOUT_MS??process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(t)&&t>=3e4?t:360*60*1e3}function F(t){const e=Number.isInteger(t)?Number(t):Number.parseInt(process.env.ACA_CODEX_ACP_COMPACT_TIMEOUT_MS??"",10);return Number.isFinite(e)&&e>=3e4?Math.min(e,6e5):12e4}function A(t){if(!t||typeof t!="object"||Array.isArray(t))return null;const e=t;return typeof e.sessionId=="string"&&e.sessionId.trim()?e.sessionId:null}function H(t){const e=d(t),s=d(e?._meta);return x(s?.acaContextUsage)}function x(t){const e=d(t);if(!e)return null;const s=m(e.contextWindow),o=m(e.usedTokens),n=m(e.inputTokens),r=String(e.state||"unknown"),i=["active","compacted","new_thread"].includes(r)?r:"unknown";return{usedTokens:o,inputTokens:n,contextWindow:s,ratio:s>0?Math.max(0,m(e.ratio)||o/s):0,observedAtMs:m(e.observedAtMs)||Date.now(),state:i,maintenanceAction:typeof e.maintenanceAction=="string"?e.maintenanceAction:null}}function m(t){return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:0}export{G as CodexAcpProvider,E as codexAcpCapabilities};
@@ -0,0 +1 @@
1
+ class C{routes=new Map;reset(){this.routes.clear()}routeFor(t){return t?this.routes.get(t)??null:null}restoreFromSessionSnapshot(t,e){const n=s(t),o=s(n.thread),d=s(n.initialTurnsPage),a=[...p(o,"turns"),...p(d,"data")];let u=0;for(const h of a){const y=s(h);for(const l of p(y,"items"))u+=this.observe({threadId:e,item:l},e)}return u}observe(t,e){const n=s(t),o=s(n.item);if(i(o,"type")==="subAgentActivity")return this.observeSubAgentActivity(o,e);if(!b(o))return 0;const d=i(o,"id");if(!d)return 0;const a=i(o,"senderThreadId")||i(n,"threadId"),u=this.routeFor(a||null),h=u?.parentToolCallId||d,y=Math.min(8,(u?.depth??0)+1),l=g(o);if(i(o,"tool")==="wait"&&l.length===0&&a===e)return this.rebindCurrentWait(d);let I=0;for(const c of l)!c||c===e||c===a||this.routes.has(c)||(this.routes.set(c,{parentToolCallId:h,sourceThreadId:c,depth:y}),I+=1);return I}observeSubAgentActivity(t,e){if(i(t,"kind")!=="started")return 0;const n=i(t,"agentThreadId"),o=i(t,"id");return!n||!o||n===e||this.routes.has(n)?0:(this.routes.set(n,{parentToolCallId:o,sourceThreadId:n,depth:1}),1)}rebindCurrentWait(t){let e=0;for(const[n,o]of this.routes)o.parentToolCallId!==t&&(this.routes.set(n,{...o,parentToolCallId:t}),e+=1);return e}}function g(r){const t=s(r),e=new Set;f(e,t.newThreadId),f(e,t.receiverThreadId),A(e,t.receiverThreadIds);const n=t.agentsStates;if(Array.isArray(n))for(const o of n)T(e,o);else{const o=s(n);for(const[d,a]of Object.entries(o))T(e,a),m(d)&&e.add(d)}return[...e]}function b(r){const t=i(s(r),"type");return t==="collabAgentToolCall"||t==="collabToolCall"}function T(r,t){const e=s(t);for(const n of["threadId","thread_id","receiverThreadId","newThreadId"])f(r,e[n])}function f(r,t){typeof t=="string"&&t.trim()&&r.add(t.trim())}function A(r,t){if(Array.isArray(t))for(const e of t)f(r,e)}function p(r,t){const e=r[t];return Array.isArray(e)?e:[]}function m(r){return r.length<8?!1:!["pending","running","completed","failed","cancelled","canceled"].includes(r.toLowerCase())}function s(r){return r&&typeof r=="object"&&!Array.isArray(r)?r:{}}function i(r,t){const e=r[t];return typeof e=="string"?e:""}export{C as CodexSubtaskRouter,g as collaborationChildThreadIds,b as isCollaborationItem};
@@ -1 +1 @@
1
- const u=new Set(["agent_message_chunk","agent_progress_chunk","agent_thought_chunk","tool_call","tool_call_update","plan","plan_update","plan_removed","usage_update","session_info_update","available_commands_update","current_mode_update","config_option_update"]);function _(e){return o("agent_message_chunk","message",e)}function g(e){return o("agent_progress_chunk","progress",e)}function h(e){return o("agent_thought_chunk","thought",e)}function m(e){return l({...e,sessionUpdate:"tool_call",status:e.status||"in_progress"})}function w(e){return l({...e,sessionUpdate:"tool_call_update"})}function c(e){const t=String(e||"").toLowerCase().replace(/[^a-z0-9]+/g,"_");return["read","view","open","list","ls","glob"].some(r=>t.includes(r))?"read":["edit","write","patch","update","create"].some(r=>t.includes(r))?"edit":t.includes("delete")||t.includes("remove")?"delete":t.includes("move")||t.includes("rename")?"move":["search","grep","find","ripgrep","rg"].some(r=>t.includes(r))?"search":["bash","shell","execute","exec","terminal","command","run"].some(r=>t.includes(r))?"execute":t.includes("think")||t.includes("reason")?"think":["fetch","web","http","url"].some(r=>t.includes(r))?"fetch":t.includes("switch_mode")||t.includes("switchmode")?"switch_mode":"other"}function i(e){const t=String(e||"").toLowerCase().replace(/[^a-z0-9]+/g,"_");return["pending","queued"].includes(t)?"pending":["running","started","in_progress","inprogress","working"].includes(t)?"in_progress":["error","failed","failure"].includes(t)?"failed":["cancelled","canceled"].includes(t)?"cancelled":"completed"}function p(e,t){return{sessionUpdate:e,content:{type:"text",text:t}}}function y(e){if(!u.has(e.type))throw new Error(`Provider 输出了非标准事件类型: ${e.type}`);const t=f(e);if(e.type==="agent_message_chunk"||e.type==="agent_progress_chunk"||e.type==="agent_thought_chunk"){if(t.sessionUpdate!==e.type)throw new Error(`${e.type} 缺少匹配的 raw.update.sessionUpdate`);return}if(e.type==="tool_call"||e.type==="tool_call_update"){if(t.sessionUpdate!==e.type)throw new Error(`${e.type} 缺少匹配的 raw.update.sessionUpdate`);a(t.toolCallId,`${e.type}.raw.update.toolCallId`),a(t.kind,`${e.type}.raw.update.kind`),a(t.status,`${e.type}.raw.update.status`)}}function f(e){const t=e.raw;if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e.type} 缺少 raw 对象`);const r=t.update;if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`${e.type} 缺少 raw.update 对象`);return r}function x(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim()}function s(e){for(const t of Object.keys(e))e[t]===void 0&&delete e[t];return e}function o(e,t,r){return{type:e,label:t,...r.text?{text:r.text}:{},raw:{method:r.method,params:r.params,update:p(e,r.text)},atMs:r.atMs??Date.now()}}function l(e){const t=e.sessionUpdate??"tool_call_update",r=c(e.kind),n=i(e.status),d=s({sessionUpdate:t,toolCallId:e.toolCallId,kind:r,title:e.title,status:n,rawInput:e.rawInput,rawOutput:e.rawOutput,content:e.content,locations:e.locations,_meta:e.meta});return{type:t,label:t==="tool_call"?"tool call":"tool update",status:n,toolCallId:e.toolCallId,raw:{method:e.method,params:e.params,tool:s({id:e.toolCallId,kind:r,title:e.title,rawInput:e.rawInput,rawOutput:e.rawOutput}),update:d},atMs:e.atMs??Date.now()}}function a(e,t){if(typeof e!="string"||!e.trim())throw new Error(`Provider 标准事件字段无效: ${t}`)}export{u as STANDARD_AGENT_EVENT_TYPES,y as assertStandardAgentEvent,_ as createAgentMessageChunk,g as createAgentProgressChunk,h as createAgentThoughtChunk,p as createTextChunkUpdate,m as createToolCall,w as createToolCallUpdate,x as firstString,c as normalizeToolKind,i as normalizeToolStatus,s as removeUndefined,f as standardUpdateRecord};
1
+ const c=new Set(["agent_message_chunk","agent_progress_chunk","agent_thought_chunk","tool_call","tool_call_update","plan","plan_update","plan_removed","usage_update","session_info_update","available_commands_update","current_mode_update","config_option_update"]);function _(e){return o("agent_message_chunk","message",e)}function g(e){return o("agent_progress_chunk","progress",e)}function h(e){return o("agent_thought_chunk","thought",e)}function m(e){return l({...e,sessionUpdate:"tool_call",status:e.status||"in_progress"})}function w(e){return l({...e,sessionUpdate:"tool_call_update"})}function u(e){const t=String(e||"").toLowerCase().replace(/[^a-z0-9]+/g,"_");return["read","view","open","list","ls","glob"].some(r=>t.includes(r))?"read":["edit","write","patch","update","create"].some(r=>t.includes(r))?"edit":t.includes("delete")||t.includes("remove")?"delete":t.includes("move")||t.includes("rename")?"move":["search","grep","find","ripgrep","rg"].some(r=>t.includes(r))?"search":["bash","shell","execute","exec","terminal","command","run"].some(r=>t.includes(r))?"execute":t.includes("think")||t.includes("reason")?"think":["fetch","web","http","url"].some(r=>t.includes(r))?"fetch":t.includes("switch_mode")||t.includes("switchmode")?"switch_mode":"other"}function i(e){const t=String(e||"").toLowerCase().replace(/[^a-z0-9]+/g,"_");return["pending","queued"].includes(t)?"pending":["running","started","in_progress","inprogress","working"].includes(t)?"in_progress":["error","failed","failure"].includes(t)?"failed":["cancelled","canceled"].includes(t)?"cancelled":"completed"}function p(e,t){return{sessionUpdate:e,content:{type:"text",text:t}}}function y(e){if(!c.has(e.type))throw new Error(`Provider 输出了非标准事件类型: ${e.type}`);const t=f(e);if(e.type==="agent_message_chunk"||e.type==="agent_progress_chunk"||e.type==="agent_thought_chunk"){if(t.sessionUpdate!==e.type)throw new Error(`${e.type} 缺少匹配的 raw.update.sessionUpdate`);return}if(e.type==="tool_call"||e.type==="tool_call_update"){if(t.sessionUpdate!==e.type)throw new Error(`${e.type} 缺少匹配的 raw.update.sessionUpdate`);a(t.toolCallId,`${e.type}.raw.update.toolCallId`),a(t.kind,`${e.type}.raw.update.kind`),a(t.status,`${e.type}.raw.update.status`)}}function f(e){const t=e.raw;if(!t||typeof t!="object"||Array.isArray(t))throw new Error(`${e.type} 缺少 raw 对象`);const r=t.update;if(!r||typeof r!="object"||Array.isArray(r))throw new Error(`${e.type} 缺少 raw.update 对象`);return r}function x(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim()}function s(e){for(const t of Object.keys(e))e[t]===void 0&&delete e[t];return e}function o(e,t,r){return{type:e,label:t,...r.text?{text:r.text}:{},raw:{method:r.method,params:r.params,update:{...p(e,r.text),...r.meta?{_meta:r.meta}:{}}},atMs:r.atMs??Date.now()}}function l(e){const t=e.sessionUpdate??"tool_call_update",r=u(e.kind),n=i(e.status),d=s({sessionUpdate:t,toolCallId:e.toolCallId,kind:r,title:e.title,status:n,rawInput:e.rawInput,rawOutput:e.rawOutput,content:e.content,locations:e.locations,_meta:e.meta});return{type:t,label:t==="tool_call"?"tool call":"tool update",status:n,toolCallId:e.toolCallId,raw:{method:e.method,params:e.params,tool:s({id:e.toolCallId,kind:r,title:e.title,rawInput:e.rawInput,rawOutput:e.rawOutput}),update:d},atMs:e.atMs??Date.now()}}function a(e,t){if(typeof e!="string"||!e.trim())throw new Error(`Provider 标准事件字段无效: ${t}`)}export{c as STANDARD_AGENT_EVENT_TYPES,y as assertStandardAgentEvent,_ as createAgentMessageChunk,g as createAgentProgressChunk,h as createAgentThoughtChunk,p as createTextChunkUpdate,m as createToolCall,w as createToolCallUpdate,x as firstString,u as normalizeToolKind,i as normalizeToolStatus,s as removeUndefined,f as standardUpdateRecord};
@@ -1 +1 @@
1
- const x=1024,b=2048,T=new Set(["agent_message_chunk","agent_progress_chunk","agent_thought_chunk","user_message_chunk"]),w=new Set(["usage_update","session_info_update"]);function q(e,t){const a=e.at(-1);if(!a)return e.push(t),!1;if(S(a,t)){const n=`${a.text??""}${t.text??""}`;if(n.length<=1024)return a.text=n,a.raw=o(a.raw,t.raw,n),!0}if(I(a,t))return E(a,t),!0;if(A(a,t)){const n=p(a.raw);return a.label=t.label,a.text=t.text,a.status=t.status,a.toolCallId=t.toolCallId,a.raw=o(a.raw,t.raw,t.text,n),!0}return e.push(t),!1}function I(e,t){if(e.eventType!=="tool_call_update"||t.eventType!=="tool_call_update"||!e.toolCallId||e.toolCallId!==t.toolCallId||e.turnId!==t.turnId||e.status!=="in_progress"||t.status!=="in_progress")return!1;const a=d(e.raw),n=d(t.raw);return!a||!n||a.terminalId!==n.terminalId?!1:a.data.length+n.data.length<=2048}function E(e,t){const a=d(e.raw),n=d(t.raw);if(!a||!n)return;e.label=t.label??e.label,e.raw=o(e.raw,t.raw,void 0);const u=r(e.raw),l=r(u?.update),s=r(l?._meta);!u||!l||!s||(u.update={...l,_meta:{...s,terminal_output_delta:{...n.raw,data:a.data+n.data}}})}function d(e){const t=r(r(e)?.update),a=r(r(t?._meta)?.terminal_output_delta);if(!a)return null;const n=typeof a?.data=="string"?a.data:"",u=typeof a?.terminal_id=="string"?a.terminal_id:"";return n&&u?{data:n,terminalId:u,raw:a}:null}function S(e,t){return T.has(e.eventType)&&e.eventType===t.eventType&&e.turnId===t.turnId&&e.label===t.label&&e.status===t.status&&!e.toolCallId&&!t.toolCallId&&typeof e.text=="string"&&typeof t.text=="string"}function A(e,t){if(e.eventType!==t.eventType||e.turnId!==t.turnId)return!1;if(w.has(e.eventType))return!0;if(e.eventType!=="config_option_update")return!1;const a=_(e.raw),n=_(t.raw);return!!a&&a===n}function _(e){const t=C(e);for(const a of["configId","optionId","id","key","name"])if(typeof t?.[a]=="string"&&t[a].trim())return t[a].trim();return""}function o(e,t,a,n=p(e)){const u=r(t);if(!u)return t;const l=h(t),s=y(e)+y(t),f={...u,acaSequence:n,acaSequenceEnd:l,sourceEventCount:s};if(a!==void 0){const c=r(u.update);c&&(f.update={...c,content:{type:"text",text:a}})}return f}function C(e){return r(r(e)?.update)}function p(e){const t=r(e)?.acaSequence;return typeof t=="number"?t:void 0}function h(e){const t=r(e),a=t?.acaSequenceEnd;return typeof a=="number"?a:typeof t?.acaSequence=="number"?t.acaSequence:void 0}function y(e){const t=r(e)?.sourceEventCount;return typeof t=="number"&&t>0?t:1}function r(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}export{q as appendCoalescedAcpEvent};
1
+ const x=1024,k=2048,y=new Set(["agent_message_chunk","agent_progress_chunk","agent_thought_chunk","user_message_chunk"]),I=new Set(["usage_update","session_info_update"]);function q(e,t){const a=e.at(-1);if(!a)return e.push(t),!1;if(C(a,t)){const n=`${a.text??""}${t.text??""}`;if(n.length<=1024)return a.text=n,a.raw=c(a.raw,t.raw,n),!0}if(S(a,t))return E(a,t),!0;if(h(a,t)){const n=T(a.raw);return a.label=t.label,a.text=t.text,a.status=t.status,a.toolCallId=t.toolCallId,a.raw=c(a.raw,t.raw,t.text,n),!0}return e.push(t),!1}function S(e,t){if(e.eventType!=="tool_call_update"||t.eventType!=="tool_call_update"||!e.toolCallId||e.toolCallId!==t.toolCallId||e.turnId!==t.turnId||d(e.raw)!==d(t.raw)||e.status!=="in_progress"||t.status!=="in_progress")return!1;const a=o(e.raw),n=o(t.raw);return!a||!n||a.terminalId!==n.terminalId?!1:a.data.length+n.data.length<=2048}function E(e,t){const a=o(e.raw),n=o(t.raw);if(!a||!n)return;e.label=t.label??e.label,e.raw=c(e.raw,t.raw,void 0);const u=r(e.raw),l=r(u?.update),s=r(l?._meta);!u||!l||!s||(u.update={...l,_meta:{...s,terminal_output_delta:{...n.raw,data:a.data+n.data}}})}function o(e){const t=r(r(e)?.update),a=r(r(t?._meta)?.terminal_output_delta);if(!a)return null;const n=typeof a?.data=="string"?a.data:"",u=typeof a?.terminal_id=="string"?a.terminal_id:"";return n&&u?{data:n,terminalId:u,raw:a}:null}function C(e,t){return y.has(e.eventType)&&e.eventType===t.eventType&&e.turnId===t.turnId&&d(e.raw)===d(t.raw)&&e.label===t.label&&e.status===t.status&&!e.toolCallId&&!t.toolCallId&&typeof e.text=="string"&&typeof t.text=="string"}function h(e,t){if(e.eventType!==t.eventType||e.turnId!==t.turnId||d(e.raw)!==d(t.raw))return!1;if(I.has(e.eventType))return!0;if(e.eventType!=="config_option_update")return!1;const a=_(e.raw),n=_(t.raw);return!!a&&a===n}function d(e){const t=r(r(e)?.update),a=r(t?._meta),n=r(a?.aca),u=r(n?.subtask),l=typeof u?.parentToolCallId=="string"?u.parentToolCallId:"",s=typeof u?.sourceThreadId=="string"?u.sourceThreadId:"";return l||s?`subtask:${l}:${s}`:"main"}function _(e){const t=A(e);for(const a of["configId","optionId","id","key","name"])if(typeof t?.[a]=="string"&&t[a].trim())return t[a].trim();return""}function c(e,t,a,n=T(e)){const u=r(t);if(!u)return t;const l=b(t),s=w(e)+w(t),f={...u,acaSequence:n,acaSequenceEnd:l,sourceEventCount:s};if(a!==void 0){const p=r(u.update);p&&(f.update={...p,content:{type:"text",text:a}})}return f}function A(e){return r(r(e)?.update)}function T(e){const t=r(e)?.acaSequence;return typeof t=="number"?t:void 0}function b(e){const t=r(e),a=t?.acaSequenceEnd;return typeof a=="number"?a:typeof t?.acaSequence=="number"?t.acaSequence:void 0}function w(e){const t=r(e)?.sourceEventCount;return typeof t=="number"&&t>0?t:1}function r(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:null}export{q as appendCoalescedAcpEvent};
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- const o="0.1.29";export{o as AICA_VERSION};
1
+ const o="0.1.31";export{o as AICA_VERSION};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuandc/aica",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "description": "AICA remote Agent worker",
5
5
  "author": "yuandc",
6
6
  "type": "module",