@yuandc/aica 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acp/agent.js +1 -1
- package/dist/acp/client/acp-events.js +1 -1
- package/dist/acp/plan-events.js +1 -0
- package/dist/acp/providers/codex/events.js +8 -9
- package/dist/acp/providers/codex/plan-events.js +1 -0
- package/dist/acp/providers/codex/provider.js +1 -1
- package/dist/acp/providers/codex/session-import.js +7 -0
- package/dist/acp/providers/codex-acp/provider.js +1 -1
- package/dist/commands/worker-codex.js +8 -0
- package/dist/core/acp-event-coalescer.js +1 -1
- package/dist/core/job-worker.js +4 -4
- package/dist/core/machine-filesystem-worker.js +5 -3
- package/dist/worker-cli.js +1 -1
- package/package.json +1 -1
package/dist/acp/agent.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import r from"node:fs";import{createAgentProvider as t}from"./providers/registry.js";async function a(e){if(!r.existsSync(e.cwd)||!r.statSync(e.cwd).isDirectory())throw new Error(`Project root does not exist or is not a directory: ${e.cwd}`);if(e.requireSessionResume&&!e.acpSessionId)throw new Error("导入的历史 Session 缺少 Provider Session ID,禁止创建新的会话。");const o=await t({agentType:e.agentType||"codex",cliType:e.cliType||"builtin"}).createSession({cwd:e.cwd,providerSessionId:e.acpSessionId??null,timeoutMs:e.timeoutMs});try{const s=await o.sendPrompt({...e,providerSessionId:e.acpSessionId??null});return{...s,acpSessionId:s.providerSessionId}}finally{await o.close().catch(()=>{})}}async function d(e){const o=await t({agentType:e.agentType||"codex",cliType:e.cliType||"builtin"}).createSession({cwd:e.cwd,providerSessionId:e.acpSessionId,timeoutMs:e.timeoutMs});if(!o.compactContext)throw await o.close().catch(()=>{}),new Error(`Provider does not support context compaction: ${e.agentType||"codex"}`);try{const s=await o.compactContext(e);return{...s,acpSessionId:s.providerSessionId}}finally{await o.close().catch(()=>{})}}export{d as compactAgentContext,a as sendAgentPrompt};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{STANDARD_AGENT_EVENT_TYPES as
|
|
1
|
+
import{createPlanEvent as h,normalizePlanSessionUpdate as g}from"../plan-events.js";import{STANDARD_AGENT_EVENT_TYPES as _,createAgentMessageChunk as y,createAgentProgressChunk as A,createAgentThoughtChunk as m,createToolCall as k,createToolCallUpdate as b,firstString as r,normalizeToolKind as x,normalizeToolStatus as T}from"../standard-events.js";function u(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 I(n){const t=u(n);if(!t)return null;const e=String(t.update.sessionUpdate||"");if(e==="agent_message_chunk")return y({text:o(t.update.content),method:"session/update",params:n});if(e==="agent_progress_chunk")return A({text:o(t.update.content),method:"session/update",params:n});if(e==="agent_thought_chunk")return m({text:o(t.update.content),method:"session/update",params:n});if(e==="tool_call"||e==="tool_call_update")return S(e,t.update,n);if(e==="plan"||e==="plan_update"||e==="plan_removed"){const a=g(t.update);return a?h({update:a,method:"session/update",params:n}):null}return _.has(e)?{type:e,label:U(e),...o(t.update.content)?{text:o(t.update.content)}:{},raw:{method:"session/update",params:n,update:t.update},atMs:Date.now()}:null}function E(n){const t=u(n);if(!t)return null;const e=String(t.update.sessionUpdate||"");return e==="agent_message_chunk"?{phase:"thinking",label:"回复中",detail:l(o(t.update.content)),updateType:e}:e==="agent_progress_chunk"?{phase:"thinking",label:"处理中",detail:l(o(t.update.content)),updateType:e}:e==="agent_thought_chunk"?{phase:"thinking",label:"思考中",detail:l(o(t.update.content)),updateType:e}:e==="tool_call"||e==="tool_call_update"?{phase:"exploring",label:"执行工具",detail:r(t.update.title,t.update.kind),updateType:e}:e==="plan"||e==="plan_update"?{phase:"thinking",label:"规划中",updateType:e}:e==="aca_context_maintenance"?{phase:"thinking",label:r(t.update.label)||"正在整理会话上下文",detail:r(t.update.detail),updateType:e}:null}function o(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 S(n,t,e){const a=r(t.toolCallId,t.id)||`acp.${Date.now()}`,c=x(r(t.kind,t.title)),p=T(r(t.status)),d=t.rawInput??t.input,f=t.rawOutput??t.output,s={method:"session/update",params:e,toolCallId:a,kind:c,title:r(t.title,t.kind),status:p,rawInput:d,rawOutput:f,content:t.content,locations:Array.isArray(t.locations)?t.locations.filter(i=>!!(i&&typeof i=="object"&&!Array.isArray(i))):void 0,meta:t._meta&&typeof t._meta=="object"&&!Array.isArray(t._meta)?t._meta:void 0};return n==="tool_call"?k(s):b(s)}function U(n){return n.replace(/_/g," ")}function l(n){const t=n.replace(/\s+/g," ").trim();if(t)return t.length>120?`${t.slice(0,117)}...`:t}export{u as acpSessionUpdateFromParams,I as eventFromAcpSessionUpdate,E as statusFromAcpSessionUpdate,o as textFromAcpContent};
|
|
@@ -0,0 +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,6 +1,6 @@
|
|
|
1
|
-
import{readFileSync as at}from"node:fs";import{applyPatch as ot,parsePatch as rt,reversePatch as st}from"diff";const S=new Set,A=new Set;function
|
|
1
|
+
import{readFileSync as at}from"node:fs";import{applyPatch as ot,parsePatch as rt,reversePatch as st}from"diff";import{createPlanEvent as ut}from"../../plan-events.js";import{codexPlanUpdateFromNotification as z}from"./plan-events.js";const S=new Set,A=new Set;function Kt(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"?[y("agent_progress_chunk",r)]:s&&s!=="final_answer"?[]:[y("agent_message_chunk",r)]:[]}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{const r=a(e,"delta");return r?[y("agent_thought_chunk",r)]:[]}case"turn/plan/updated":{const r=z(e);return r?[r]:[]}case"item/plan/delta":return[];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[];const s=O(t,r);return s?[s]:[t==="item/started"?Ut(r):xt(r)]}case"item/commandExecution/outputDelta":{const r=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),o=c(e,["delta","data","output","text"]);return!r&&!o?[]:[{sessionUpdate:"tool_call_update",toolCallId:r,kind:"execute",status:"in_progress",_meta:b(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:b(r,`
|
|
2
2
|
${o}
|
|
3
|
-
`)}]:[]}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[I({threadStatus:a(e,"status")})];case"thread/archived":return[I({archived:!0})];case"thread/unarchived":return[I({archived:!1})];case"thread/closed":return[I({closed:!0})];case"account/rateLimits/updated":return[
|
|
3
|
+
`)}]:[]}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[I({threadStatus:a(e,"status")})];case"thread/archived":return[I({archived:!0})];case"thread/unarchived":return[I({archived:!1})];case"thread/closed":return[I({closed:!0})];case"account/rateLimits/updated":return[W(e)];case"account/updated":return[I({account:f(e)??e})];case"configWarning":{const r=a(e,"summary"),o=a(e,"details");return[y("agent_message_chunk",`Config warning: ${r}${o?`
|
|
4
4
|
|
|
5
5
|
${o}`:""}
|
|
6
6
|
|
|
@@ -10,19 +10,18 @@ ${o}`:""}
|
|
|
10
10
|
|
|
11
11
|
`)];case"thread/compacted":return[y("agent_message_chunk",`*Context compacted to fit the model's context window.*
|
|
12
12
|
|
|
13
|
-
`)];case"fuzzyFileSearch/sessionUpdated":return[j(e)];case"fuzzyFileSearch/sessionCompleted":return[
|
|
13
|
+
`)];case"fuzzyFileSearch/sessionUpdated":return[j(e)];case"fuzzyFileSearch/sessionCompleted":return[E(e)];case"item/autoApprovalReview/started":return[U(e,"started")];case"item/autoApprovalReview/completed":return[U(e,"completed")];case"error":return[{sessionUpdate:"tool_call_update",toolCallId:"codex.error",kind:"other",status:"failed",title:"Codex error",rawOutput:e}];default:return[]}}function Xt(t,e,n,r={}){switch(t){case"item/agentMessage/delta":{const o=a(e,"delta"),s=a(e,"itemId"),u=s?r.agentMessagePhases?.get(s):"";if(!o||u&&u!=="commentary"&&u!=="final_answer")break;const l=u==="commentary"?"agent_progress_chunk":"agent_message_chunk",d=u==="commentary"?"progress":"message";n.pushStatus("thinking",u==="commentary"?"处理中":"生成回复中",w(o),t),n.pushUpdate({type:l,label:d,text:o,raw:{method:t,params:e,update:y(l,o)},atMs:Date.now()});break}case"item/reasoning/summaryTextDelta":case"item/reasoning/textDelta":{const o=a(e,"delta");n.pushStatus("thinking","思考中",w(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=z(e);if(!o)break;n.pushStatus("thinking","规划中",void 0,t),n.pushUpdate(ut({update:o,method:t,params:e}));break}case"item/plan/delta":break;case"item/started":case"item/completed":{const o=m(e,"item"),s=a(o,"type"),u=O(t,o);if(!u){const _=v(s);(s==="reasoning"||s==="agentMessage")&&n.pushStatus(F(s),_,lt(o),t);break}const l=ct(t,e,o),d=it(s,u);n.pushStatus(F(s),$(s),void 0,t),n.pushUpdate({type:t==="item/started"?"tool_call":"tool_call_update",label:d,status:c(u,["status"])||(t==="item/started"?"in_progress":"completed"),toolCallId:a(o,"id"),raw:{method:t,params:e,tool:l,update:u},atMs:Date.now()});break}case"item/commandExecution/outputDelta":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),s=c(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:b(o,s)}},atMs:Date.now()});break}case"item/commandExecution/terminalInteraction":{const o=a(e,"itemId")||a(e,"id")||a(e,"toolCallId"),u=`
|
|
14
14
|
${a(e,"stdin")}
|
|
15
|
-
`;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:b(o,
|
|
15
|
+
`;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:b(o,u)}},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":T(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":C(n,t,e,{threadStatus:a(e,"status")});break;case"thread/archived":C(n,t,e,{archived:!0});break;case"thread/unarchived":C(n,t,e,{archived:!1});break;case"thread/closed":C(n,t,e,{closed:!0});break;case"account/rateLimits/updated":T(n,{method:t,params:e,type:"session_info_update",label:"rate_limit",update:W(e)});break;case"configWarning":{const o=a(e,"summary"),s=a(e,"details"),u=`Config warning: ${o}${s?`
|
|
16
16
|
|
|
17
17
|
${s}`:""}
|
|
18
18
|
|
|
19
|
-
`;n.pushUpdate({type:"agent_message_chunk",label:"message",text:
|
|
19
|
+
`;n.pushUpdate({type:"agent_message_chunk",label:"message",text:u,raw:{method:t,params:e,update:y("agent_message_chunk",u)},atMs:Date.now()});break}case"warning":{const o=`Warning: ${a(e,"message")}
|
|
20
20
|
|
|
21
21
|
`;n.pushUpdate({type:"agent_message_chunk",label:"message",text:o,raw:{method:t,params:e,update:y("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")}).
|
|
22
22
|
|
|
23
23
|
`;n.pushStatus("thinking","模型已切换",w(o),t),n.pushUpdate({type:"agent_thought_chunk",label:"thought",text:o,raw:{method:t,params:e,update:y("agent_thought_chunk",o)},atMs:Date.now()});break}case"thread/compacted":{const o=`*Context compacted to fit the model's context window.*
|
|
24
24
|
|
|
25
|
-
`;n.pushStatus("thinking","上下文已压缩",void 0,t),n.pushUpdate({type:"agent_message_chunk",label:"message",text:o,raw:{method:t,params:e,update:y("agent_message_chunk",o)},atMs:Date.now()});break}case"fuzzyFileSearch/sessionUpdated":{const o=j(e);n.pushStatus("exploring",a(o,"title")||"Search",
|
|
26
|
-
`).trim()}function v(t){switch(t){case"commandExecution":return"执行命令中";case"fileChange":return"编辑文件中";case"mcpToolCall":case"dynamicToolCall":return"调用工具中";case"webSearch":return"搜索中";case"imageGeneration":return"生成图片中";case"reasoning":return"思考中";case"agentMessage":return"生成回复中";default:return"处理中"}}function $(t){switch(t){case"commandExecution":return"执行命令";case"fileChange":return"编辑文件";case"mcpToolCall":case"dynamicToolCall":return"调用工具";case"webSearch":case"fuzzyFileSearch":return"搜索";case"imageView":return"查看图片";case"imageGeneration":return"生成图片";default:return v(t)}}function it(t,e){const n=c(e,["kind"]);return n==="read"?c(e,["title"])||"读取文件":n==="search"?c(e,["title"])||"搜索":n==="edit"?"编辑文件":n==="execute"?"执行命令":n==="think"?"思考中":n==="other"&&c(e,["title"])||$(t)}function
|
|
27
|
-
`)}}]}function G(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 E(t){if(!t)return"";const e=a(t,"type");if(e==="command")return[N(a(t,"source")),a(t,"command")].filter(Boolean).join(" ");if(e==="execve"){const n=h(t,"argv")?.map(s=>p(s)).filter(Boolean)??[],r=a(t,"program"),o=n.length>0?n:[r].filter(Boolean);return[N(a(t,"source")),ht(o)].filter(Boolean).join(" ")}if(e==="applyPatch"){const n=h(t,"files")?.map(r=>p(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 N(t){return t==="shell"?"shell":t==="unifiedExec"?"exec":t}function ht(t){return t.map(_t).join(" ")}function _t(t){return t.length===0?"''":/^[A-Za-z0-9_/:=+.,@%-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}function yt(t){const e=m(t,"review"),n=e?G(a(e,"status")):"",r=E(m(t,"action"));return[n,r].filter(Boolean).join(" · ")||void 0}function B(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:P(n,"usedPercent")??null,sevenDay:P(r,"usedPercent")??null,fiveHourResetAt:a(n,"resetsAt")||null,sevenDayResetAt:a(r,"resetsAt")||null,raw:e})}})}function mt(t){const e=a(t,"id"),n=a(t,"cwd"),r=a(t,"command"),o=V(t),s=o.length===1?f(o[0]):null;if(s){const i=a(s,"type");if(i==="read"){const l=a(s,"path")||a(s,"name");return u({sessionUpdate:"tool_call",toolCallId:e,status:g(a(t,"status")),kind:"read",title:`Read file '${l}'`,locations:l?[{path:l}]:void 0})}if(i==="search"){const l=a(s,"query"),d=a(s,"path");return u({sessionUpdate:"tool_call",toolCallId:e,status:g(a(t,"status")),kind:"search",title:J(l,d)})}if(i==="listFiles"){const l=a(s,"path");return u({sessionUpdate:"tool_call",toolCallId:e,status:g(a(t,"status")),kind:"read",title:l?`List files in '${l}'`:"List files"})}}return Ot({sessionUpdate:"tool_call",toolCallId:e,status:g(a(t,"status")),kind:"execute",title:Rt(r),rawInput:u({command:r,cwd:n})},e,n)}function wt(t){const e=a(t,"id"),n=c(t,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),r=P(t,"exitCode"),o={sessionUpdate:"tool_call_update",toolCallId:e,status:g(a(t,"status")),rawOutput:u({formatted_output:n,exit_code:r})};return jt(t)&&(o._meta={...n?b(e,n):{},terminal_exit:{exit_code:r,signal:null,terminal_id:e}}),u(o)}function Ct(t){const e=a(t,"id"),n=Q(t);return u({sessionUpdate:"tool_call",toolCallId:e,title:"Editing files",kind:"edit",status:g(a(t,"status")),content:n,locations:Gt(t),rawInput:{changes:D(t)}})}function It(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:g(a(t,"status")),content:Q(t)})}function bt(t){const e=c(t,["tool","name","server"]);return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:g(a(t,"status")),rawInput:f(t)})}function Ut(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:g(a(t,"status")),rawOutput:f(t)})}function xt(t){const e=a(t,"server"),n=a(t,"tool");return u({...L(t,`mcp.${e}.${n}`,W(e,n,t.arguments),q(t.result,t.error)),_meta:{is_mcp_tool_call:!0}})}function kt(t){const e=a(t,"server"),n=a(t,"tool");return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:g(a(t,"status")),rawInput:W(e,n,t.arguments),rawOutput:q(t.result,t.error)})}function St(t){return L(t,a(t,"tool"),{arguments:t.arguments},void 0)}function At(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:g(a(t,"status"))})}function L(t,e,n,r){return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:g(a(t,"status")),rawInput:n,rawOutput:r})}function W(t,e,n){return{server:t,tool:e,arguments:n}}function q(t,e){if(!(t===null&&e===null)&&!(t===void 0&&e===void 0))return{result:t,error:e}}function vt(t){return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"search",title:H(t),status:g(a(t,"status")),rawInput:f(t)})}function $t(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),title:H(t),status:g(a(t,"status")),rawInput:f(t)})}function Tt(t){return u({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"other",title:"Image generation",status:"in_progress",rawInput:{id:a(t,"id")}})}function Mt(t){return u({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:Pt(a(t,"status")),content:zt(t),rawOutput:Ft(t)})}function Dt(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 Pt(t){return t==="completed"?"completed":t==="failed"?"failed":"in_progress"}function zt(t){const e=f(t.result),n=c(e,["url","uri","path"]);if(n)return[{type:"content",content:{type:"resource_link",name:n,uri:n}}]}function Ft(t){const e={status:t.status,revisedPrompt:t.revisedPrompt,result:t.result};return"savedPath"in t&&(e.savedPath=t.savedPath??null),e}function Ot(t,e,n){return u({...t,content:[{type:"terminal",terminalId:e}],_meta:{terminal_info:{cwd:n,terminal_id:e}}})}function jt(t){const e=V(t),n=e.length===1?f(e[0]):null;return!n||a(n,"type")==="unknown"}function V(t){return h(t,"commandActions")||h(t,"command_actions")||h(t,"actions")||[]}function g(t){switch(t){case"inProgress":case"in_progress":case"started":case"":return"in_progress";case"completed":return"completed";case"failed":case"declined":case"cancelled":return"failed";default:return t}}function Rt(t){const e=t.replace(/^(?:\/bin\/)?(?:bash|zsh|sh)\s+(?:-[lc]+\s+)?/,"");return e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function b(t,e){return{terminal_output_delta:{data:e,terminal_id:t}}}function J(t,e){return t&&e?`Search for '${t}' in ${e}`:t?`Search for '${t}'`:e?`Search in '${e}'`:"Search"}function H(t){const e=f(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=h(e,"queries")?.map(s=>p(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 Gt(t){const e=D(t).map(n=>f(n)).map(n=>a(n,"path")).filter(Boolean).map(n=>({path:n}));return e.length>0?e:void 0}function Q(t){const n=(h(t,"changes")??[]).map(r=>{const o=f(r);if(!o)return null;const s=p(o.path),i=o.kind&&typeof o.kind=="object"&&!Array.isArray(o.kind)?p(o.kind.type):p(o.kind),l=p(o.diff);return i==="add"?u({type:"diff",oldText:null,newText:l,path:s,_meta:{kind:"add"}}):i==="delete"?u({type:"diff",oldText:l,newText:"",path:s,_meta:{kind:"delete"}}):Et(o,s,l,i)}).filter(Boolean);return n.length>0?n:void 0}function Et(t,e,n,r){const o=t.kind&&typeof t.kind=="object"&&!Array.isArray(t.kind)?p(t.kind.move_path):"",s=Nt(n),i=Z(e);if(i!==null){const l=M(i,s);if(l!==!1)return x(o||e,i,l,r||"update");const d=K(s);if(d){const _=M(i,d);if(_!==!1)return x(e,_,i,r||"update")}}if(o){const l=Z(o),d=K(s);if(l!==null&&d){const _=M(l,d);if(_!==!1)return x(o,_,l,r||"update")}}return x(o||e,null,s,r||"update")}function x(t,e,n,r){return u({type:"diff",oldText:e,newText:n,path:t,_meta:{kind:r}})}function Z(t){try{return at(t,"utf8")}catch{return null}}function Nt(t){return t.replace(/\n\nMoved to: .*$/,"")}function K(t){try{const[e]=rt(t);return e?st(e):null}catch{return null}}function M(t,e){try{return ot(t,e)}catch{return!1}}function Bt(t,e){if(t==="commandExecution")return"执行命令";if(t==="fileChange")return e.path?`编辑文件: ${qt(e.path)}`:"编辑文件";if(t==="webSearch")return e.rawInput?`搜索: ${w(e.rawInput)}`:"搜索";if(t==="mcpToolCall"||t==="dynamicToolCall"){const n=c(e.item,["tool","name","server"]);return n?`调用工具: ${n}`:"调用工具"}return v(t)}function Lt(t,e,n){if(e)return e;if(t==="fileChange"){const r=X(n),o=c(n,["path","filePath","file_path","relativePath","absolutePath"])||r.path;return[c(n,["action","changeType","operation"])||r.action,o].filter(Boolean).join(" ")}return""}function X(t){const e=h(t,"changes")??[];for(const n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;const r=n,o=p(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?p(r.kind.type):p(r.kind);if(o||s)return{path:o,action:s}}return{path:"",action:""}}function D(t){return(h(t,"changes")??[]).map(n=>{if(!n||typeof n!="object"||Array.isArray(n))return null;const r=n,o=p(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?p(r.kind.type):p(r.kind);return!o&&!s?null:u({type:s||"edit",path:o})}).filter(Boolean).slice(0,50)}function c(t,e){if(!t)return"";for(const n of e){const r=p(t[n]);if(r)return r}return""}function p(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 h(t,e){const n=t?.[e];return Array.isArray(n)?n.slice(0,50):null}function Wt(...t){return t.find(e=>e.trim())||""}function qt(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 Y(t){const e=a(t,"explanation"),r=(Array.isArray(t?.plan)?t.plan:[]).map(o=>a(o,"text")).filter(Boolean);return[e,...r].filter(Boolean).join(`
|
|
28
|
-
`)||void 0}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 f(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 P(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 w(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{Ht as codexAcpSessionUpdatesFromNotification,Zt as extractAssistantTextFromTurn,Qt as mapCodexNotification};
|
|
25
|
+
`;n.pushStatus("thinking","上下文已压缩",void 0,t),n.pushUpdate({type:"agent_message_chunk",label:"message",text:o,raw:{method:t,params:e,update:y("agent_message_chunk",o)},atMs:Date.now()});break}case"fuzzyFileSearch/sessionUpdated":{const o=j(e);n.pushStatus("exploring",a(o,"title")||"Search",pt(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=E(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=U(e,"started");n.pushStatus("exploring","Guardian Review",mt(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=U(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":C(n,t,e,{account:f(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","执行失败",w(JSON.stringify(e)),t),n.pushUpdate({type:"error",label:"error",text:w(JSON.stringify(e)),raw:{method:t,params:e},atMs:Date.now()});break;default:break}}function Yt(t){return(Array.isArray(t?.items)?t.items:[]).map(n=>a(n,"type")!=="agentMessage"?"":a(n,"text")).filter(Boolean).join(`
|
|
26
|
+
`).trim()}function v(t){switch(t){case"commandExecution":return"执行命令中";case"fileChange":return"编辑文件中";case"mcpToolCall":case"dynamicToolCall":return"调用工具中";case"webSearch":return"搜索中";case"imageGeneration":return"生成图片中";case"reasoning":return"思考中";case"agentMessage":return"生成回复中";default:return"处理中"}}function $(t){switch(t){case"commandExecution":return"执行命令";case"fileChange":return"编辑文件";case"mcpToolCall":case"dynamicToolCall":return"调用工具";case"webSearch":case"fuzzyFileSearch":return"搜索";case"imageView":return"查看图片";case"imageGeneration":return"生成图片";default:return v(t)}}function it(t,e){const n=c(e,["kind"]);return n==="read"?c(e,["title"])||"读取文件":n==="search"?c(e,["title"])||"搜索":n==="edit"?"编辑文件":n==="execute"?"执行命令":n==="think"?"思考中":n==="other"&&c(e,["title"])||$(t)}function F(t){return t==="imageGeneration"?"image_generation":t==="reasoning"||t==="agentMessage"||t==="plan"?"thinking":"exploring"}function lt(t){if(t)for(const e of["command","path","tool","server","query","text"]){const n=a(t,e);if(n)return w(n)}}function ct(t,e,n){const r=a(n,"type"),o=a(n,"id")||a(e,"itemId"),s=c(n,["rawInput","raw_input","command","query","path","text","input"]),u=r==="commandExecution"?c(n,["command","rawInput","raw_input"]):"",l=Y(n),d=c(n,["path","filePath","file_path","relativePath","absolutePath"])||l.path,_=c(n,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),k=g(n,"commandActions")||g(n,"command_actions")||g(n,"actions")||P(n),tt=qt(r,_,n),et=Wt(r,{command:u,path:d,rawInput:s,item:n}),nt=w(Bt(u,d,s,_));return i({id:o,type:r,method:t,displayName:et,rawInput:s,raw_input:s,command:u,path:d,action:c(n,["action","changeType","operation"])||l.action,commandActions:k,command_actions:k.length>0?k:void 0,aggregatedOutput:_,aggregated_output:_,formatted_output:tt,summary:nt})}function O(t,e){if(!e)return null;switch(a(e,"type")){case"commandExecution":return t==="item/started"?wt(e):Ct(e);case"fileChange":return t==="item/started"?It(e):bt(e);case"mcpToolCall":return t==="item/started"?kt(e):St(e);case"dynamicToolCall":return t==="item/started"?At(e):vt(e);case"webSearch":return t==="item/started"?$t(e):Tt(e);case"imageView":return Dt(e);case"imageGeneration":return t==="item/started"?Mt(e):Pt(e);default:return null}}function T(t,e){t.pushUpdate({type:e.type,label:e.label,raw:{method:e.method,params:e.params,update:e.update},atMs:Date.now()})}function C(t,e,n,r){T(t,{method:e,params:n,type:"session_info_update",label:"session_info",update:{sessionUpdate:"session_info_update",_meta:{codex:r}}})}function I(t){return{sessionUpdate:"session_info_update",_meta:{codex:t}}}function y(t,e){return{sessionUpdate:t,content:{type:"text",text:e}}}function R(t){return`fuzzyFileSearch.${t}`}function j(t){const e=a(t,"sessionId"),n=R(e),r=!S.has(n);S.add(n);const o=a(t,"query"),s=H(o,""),u=dt(t);return i(r?{sessionUpdate:"tool_call",toolCallId:n,kind:"search",title:s,status:"in_progress",locations:u,rawInput:{query:o}}:{sessionUpdate:"tool_call_update",toolCallId:n,title:s,status:"in_progress",locations:u})}function E(t){const e=a(t,"sessionId"),n=R(e);return S.delete(n),{sessionUpdate:"tool_call_update",toolCallId:n,status:"completed"}}function dt(t){const n=(g(f(t),"files")??[]).map(r=>{const o=f(r);if(!o)return"";const s=a(o,"path"),u=a(o,"root");return s?s.startsWith("/")||!u?s:`${u.replace(/\/+$/,"")}/${s.replace(/^\/+/,"")}`:""}).filter(Boolean).map(r=>({path:r}));return n.length>0?n:void 0}function pt(t){const e=a(t,"query"),r=(g(f(t),"files")??[]).length;if(e&&r)return`${e} · ${r} files`;if(e)return e;if(r)return`${r} files`}function ft(t){return`guardian_assessment:${t}`}function U(t,e){const n=a(t,"reviewId"),r=ft(n),o=e==="started"&&!A.has(n);e==="started"&&A.add(n),e==="completed"&&A.delete(n);const s=m(t,"review")??{},u={sessionUpdate:o?"tool_call":"tool_call_update",toolCallId:r,status:ht(a(s,"status")),content:gt(s,m(t,"action")),...o?{kind:"think",title:"Guardian Review",rawInput:t}:{rawOutput:t}};return i(u)}function ht(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 gt(t,e){const n=[`Status: ${G(a(t,"status"))}`],r=N(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 u=a(t,"rationale").trim();return u&&n.push(`Rationale: ${u}`),[{type:"content",content:{type:"text",text:n.join(`
|
|
27
|
+
`)}}]}function G(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 N(t){if(!t)return"";const e=a(t,"type");if(e==="command")return[L(a(t,"source")),a(t,"command")].filter(Boolean).join(" ");if(e==="execve"){const n=g(t,"argv")?.map(s=>p(s)).filter(Boolean)??[],r=a(t,"program"),o=n.length>0?n:[r].filter(Boolean);return[L(a(t,"source")),_t(o)].filter(Boolean).join(" ")}if(e==="applyPatch"){const n=g(t,"files")?.map(r=>p(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 L(t){return t==="shell"?"shell":t==="unifiedExec"?"exec":t}function _t(t){return t.map(yt).join(" ")}function yt(t){return t.length===0?"''":/^[A-Za-z0-9_/:=+.,@%-]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}function mt(t){const e=m(t,"review"),n=e?G(a(e,"status")):"",r=N(m(t,"action"));return[n,r].filter(Boolean).join(" · ")||void 0}function W(t){const e=m(t,"rateLimits")??{},n=m(e,"primary"),r=m(e,"secondary");return i({sessionUpdate:"session_info_update",_meta:{rateLimits:i({planName:a(e,"planType"),limitName:a(e,"limitName"),limitId:a(e,"limitId"),fiveHour:D(n,"usedPercent")??null,sevenDay:D(r,"usedPercent")??null,fiveHourResetAt:a(n,"resetsAt")||null,sevenDayResetAt:a(r,"resetsAt")||null,raw:e})}})}function wt(t){const e=a(t,"id"),n=a(t,"cwd"),r=a(t,"command"),o=J(t),s=o.length===1?f(o[0]):null;if(s){const u=a(s,"type");if(u==="read"){const l=a(s,"path")||a(s,"name");return i({sessionUpdate:"tool_call",toolCallId:e,status:h(a(t,"status")),kind:"read",title:`Read file '${l}'`,locations:l?[{path:l}]:void 0})}if(u==="search"){const l=a(s,"query"),d=a(s,"path");return i({sessionUpdate:"tool_call",toolCallId:e,status:h(a(t,"status")),kind:"search",title:H(l,d)})}if(u==="listFiles"){const l=a(s,"path");return i({sessionUpdate:"tool_call",toolCallId:e,status:h(a(t,"status")),kind:"read",title:l?`List files in '${l}'`:"List files"})}}return Rt({sessionUpdate:"tool_call",toolCallId:e,status:h(a(t,"status")),kind:"execute",title:Et(r),rawInput:i({command:r,cwd:n})},e,n)}function Ct(t){const e=a(t,"id"),n=c(t,["aggregatedOutput","aggregated_output","formattedOutput","formatted_output","output","stdout","stderr"]),r=D(t,"exitCode"),o={sessionUpdate:"tool_call_update",toolCallId:e,status:h(a(t,"status")),rawOutput:i({formatted_output:n,exit_code:r})};return jt(t)&&(o._meta={...n?b(e,n):{},terminal_exit:{exit_code:r,signal:null,terminal_id:e}}),i(o)}function It(t){const e=a(t,"id"),n=Z(t);return i({sessionUpdate:"tool_call",toolCallId:e,title:"Editing files",kind:"edit",status:h(a(t,"status")),content:n,locations:Gt(t),rawInput:{changes:P(t)}})}function bt(t){return i({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:h(a(t,"status")),content:Z(t)})}function Ut(t){const e=c(t,["tool","name","server"]);return i({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:h(a(t,"status")),rawInput:f(t)})}function xt(t){return i({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:h(a(t,"status")),rawOutput:f(t)})}function kt(t){const e=a(t,"server"),n=a(t,"tool");return i({...q(t,`mcp.${e}.${n}`,B(e,n,t.arguments),V(t.result,t.error)),_meta:{is_mcp_tool_call:!0}})}function St(t){const e=a(t,"server"),n=a(t,"tool");return i({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:h(a(t,"status")),rawInput:B(e,n,t.arguments),rawOutput:V(t.result,t.error)})}function At(t){return q(t,a(t,"tool"),{arguments:t.arguments},void 0)}function vt(t){return i({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:h(a(t,"status"))})}function q(t,e,n,r){return i({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"execute",title:e,status:h(a(t,"status")),rawInput:n,rawOutput:r})}function B(t,e,n){return{server:t,tool:e,arguments:n}}function V(t,e){if(!(t===null&&e===null)&&!(t===void 0&&e===void 0))return{result:t,error:e}}function $t(t){return i({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"search",title:Q(t),status:h(a(t,"status")),rawInput:f(t)})}function Tt(t){return i({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),title:Q(t),status:h(a(t,"status")),rawInput:f(t)})}function Mt(t){return i({sessionUpdate:"tool_call",toolCallId:a(t,"id"),kind:"other",title:"Image generation",status:"in_progress",rawInput:{id:a(t,"id")}})}function Pt(t){return i({sessionUpdate:"tool_call_update",toolCallId:a(t,"id"),status:zt(a(t,"status")),content:Ft(t),rawOutput:Ot(t)})}function Dt(t){const e=a(t,"path");return i({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 zt(t){return t==="completed"?"completed":t==="failed"?"failed":"in_progress"}function Ft(t){const e=f(t.result),n=c(e,["url","uri","path"]);if(n)return[{type:"content",content:{type:"resource_link",name:n,uri:n}}]}function Ot(t){const e={status:t.status,revisedPrompt:t.revisedPrompt,result:t.result};return"savedPath"in t&&(e.savedPath=t.savedPath??null),e}function Rt(t,e,n){return i({...t,content:[{type:"terminal",terminalId:e}],_meta:{terminal_info:{cwd:n,terminal_id:e}}})}function jt(t){const e=J(t),n=e.length===1?f(e[0]):null;return!n||a(n,"type")==="unknown"}function J(t){return g(t,"commandActions")||g(t,"command_actions")||g(t,"actions")||[]}function h(t){switch(t){case"inProgress":case"in_progress":case"started":case"":return"in_progress";case"completed":return"completed";case"failed":case"declined":case"cancelled":return"failed";default:return t}}function Et(t){const e=t.replace(/^(?:\/bin\/)?(?:bash|zsh|sh)\s+(?:-[lc]+\s+)?/,"");return e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e}function b(t,e){return{terminal_output_delta:{data:e,terminal_id:t}}}function H(t,e){return t&&e?`Search for '${t}' in ${e}`:t?`Search for '${t}'`:e?`Search in '${e}'`:"Search"}function Q(t){const e=f(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=>p(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 Gt(t){const e=P(t).map(n=>f(n)).map(n=>a(n,"path")).filter(Boolean).map(n=>({path:n}));return e.length>0?e:void 0}function Z(t){const n=(g(t,"changes")??[]).map(r=>{const o=f(r);if(!o)return null;const s=p(o.path),u=o.kind&&typeof o.kind=="object"&&!Array.isArray(o.kind)?p(o.kind.type):p(o.kind),l=p(o.diff);return u==="add"?i({type:"diff",oldText:null,newText:l,path:s,_meta:{kind:"add"}}):u==="delete"?i({type:"diff",oldText:l,newText:"",path:s,_meta:{kind:"delete"}}):Nt(o,s,l,u)}).filter(Boolean);return n.length>0?n:void 0}function Nt(t,e,n,r){const o=t.kind&&typeof t.kind=="object"&&!Array.isArray(t.kind)?p(t.kind.move_path):"",s=Lt(n),u=K(e);if(u!==null){const l=M(u,s);if(l!==!1)return x(o||e,u,l,r||"update");const d=X(s);if(d){const _=M(u,d);if(_!==!1)return x(e,_,u,r||"update")}}if(o){const l=K(o),d=X(s);if(l!==null&&d){const _=M(l,d);if(_!==!1)return x(o,_,l,r||"update")}}return x(o||e,null,s,r||"update")}function x(t,e,n,r){return i({type:"diff",oldText:e,newText:n,path:t,_meta:{kind:r}})}function K(t){try{return at(t,"utf8")}catch{return null}}function Lt(t){return t.replace(/\n\nMoved to: .*$/,"")}function X(t){try{const[e]=rt(t);return e?st(e):null}catch{return null}}function M(t,e){try{return ot(t,e)}catch{return!1}}function Wt(t,e){if(t==="commandExecution")return"执行命令";if(t==="fileChange")return e.path?`编辑文件: ${Vt(e.path)}`:"编辑文件";if(t==="webSearch")return e.rawInput?`搜索: ${w(e.rawInput)}`:"搜索";if(t==="mcpToolCall"||t==="dynamicToolCall"){const n=c(e.item,["tool","name","server"]);return n?`调用工具: ${n}`:"调用工具"}return v(t)}function qt(t,e,n){if(e)return e;if(t==="fileChange"){const r=Y(n),o=c(n,["path","filePath","file_path","relativePath","absolutePath"])||r.path;return[c(n,["action","changeType","operation"])||r.action,o].filter(Boolean).join(" ")}return""}function Y(t){const e=g(t,"changes")??[];for(const n of e){if(!n||typeof n!="object"||Array.isArray(n))continue;const r=n,o=p(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?p(r.kind.type):p(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=p(r.path),s=r.kind&&typeof r.kind=="object"&&!Array.isArray(r.kind)?p(r.kind.type):p(r.kind);return!o&&!s?null:i({type:s||"edit",path:o})}).filter(Boolean).slice(0,50)}function c(t,e){if(!t)return"";for(const n of e){const r=p(t[n]);if(r)return r}return""}function p(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 Bt(...t){return t.find(e=>e.trim())||""}function Vt(t){return t.replace(/\\/g,"/").split("/").filter(Boolean).pop()||t}function i(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 f(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 D(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 w(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{Kt as codexAcpSessionUpdatesFromNotification,Yt as extractAssistantTextFromTurn,Xt as mapCodexNotification};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{normalizePlanSessionUpdate as i}from"../../plan-events.js";function p(r){const n=e(r);if(!n)return null;const o=Array.isArray(n.plan)?n.plan:[];return i({sessionUpdate:"plan",planId:t(n.planId,n.turnId),entries:o,explanation:t(n.explanation)})}function t(...r){for(const n of r)if(typeof n=="string"&&n.trim())return n.trim()}function e(r){return r&&typeof r=="object"&&!Array.isArray(r)?r:null}export{p as codexPlanUpdateFromNotification};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import c from"node:fs";import{JsonLineRpcClient as u}from"../../client/json-rpc.js";import{startCodexAppServer as h}from"./codex-process.js";import{extractAssistantTextFromTurn as p,mapCodexNotification as m}from"./events.js";import{isCodexApprovalRequest as f,resolveCodexApprovalRequest as g}from"./permissions.js";const C=1500,w={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 _{id="native-codex";name="Native Codex";capabilities=w;async createSession(e){return new v(e.cwd,e.providerSessionId??null,e.timeoutMs)}}class v{cwd;providerSessionId;defaultTimeoutMs;started;rpc;initialized=!1;content="";promptActive=!1;updates=[];statusTimeline=[];statusCallback=null;updateCallback=null;permissionCallback=null;abortHandler=null;completedTurns=new Map;pendingTurnCompletions=new Map;agentMessagePhases=new Map;constructor(e,s,t=I()){this.cwd=e,this.providerSessionId=s,this.defaultTimeoutMs=t,this.started=h(e),this.rpc=new u(this.started.child,{onNotification:(r
|
|
1
|
+
import c from"node:fs";import{JsonLineRpcClient as u}from"../../client/json-rpc.js";import{startCodexAppServer as h}from"./codex-process.js";import{extractAssistantTextFromTurn as p,mapCodexNotification as m}from"./events.js";import{isCodexApprovalRequest as f,resolveCodexApprovalRequest as g}from"./permissions.js";const C=1500,w={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 _{id="native-codex";name="Native Codex";capabilities=w;async createSession(e){return new v(e.cwd,e.providerSessionId??null,e.timeoutMs)}}class v{cwd;providerSessionId;defaultTimeoutMs;started;rpc;initialized=!1;content="";promptActive=!1;updates=[];statusTimeline=[];statusCallback=null;updateCallback=null;permissionCallback=null;abortHandler=null;completedTurns=new Map;pendingTurnCompletions=new Map;agentMessagePhases=new Map;constructor(e,s,t=I()){this.cwd=e,this.providerSessionId=s,this.defaultTimeoutMs=t,this.started=h(e),this.rpc=new u(this.started.child,{onNotification:(n,r)=>this.handleNotification(n,r),onRequest:(n,r)=>this.handleReverseRequest(n,r)})}async sendPrompt(e){const s=Date.now(),t=d(e.mode);this.statusCallback=e.onStatus??null,this.updateCallback=e.onUpdate??null,this.permissionCallback=e.onPermissionRequest??null,this.attachAbortSignal(e.signal),this.emitStatus("initializing","Codex 初始化中","initialize"),await this.initialize();const n=await this.establishThread(e);this.emitStatus("thinking","思考中"),this.content="",this.updates.length=0,this.agentMessagePhases.clear(),this.promptActive=!0;let r,a;try{r=await this.rpc.request("turn/start",{threadId:n,clientUserMessageId:`aca-${Date.now()}-${Math.random().toString(16).slice(2)}`,input:T(e.prompt,e.promptBlocks),cwd:e.cwd,...e.model?{model:e.model}:{},...x(e.configOptionValues)},e.timeoutMs??this.defaultTimeoutMs);const o=String(r?.turn?.id??"");a=o?await this.waitForTurnCompleted(o,e.timeoutMs??this.defaultTimeoutMs):r?.turn}finally{this.promptActive=!1}const l=this.content.trim()||p(a);return this.emitStatus("completed","已完成"),{providerSessionId:n,cliType:"builtin",agentType:"codex",effectiveConfig:t,command:this.started.command,args:this.started.args,cwd:this.cwd,exitCode:this.rpc.exitCode,signal:this.rpc.signal,durationMs:Date.now()-s,stdout:this.rpc.stdout,stderr:this.rpc.stderr,content:l,updates:this.updates,statusTimeline:this.statusTimeline,promptResponse:r}}async cancel(){try{this.providerSessionId&&this.started.child.exitCode===null&&this.started.child.signalCode===null&&await this.rpc.request("turn/interrupt",{threadId:this.providerSessionId},C).catch(()=>{})}finally{await this.close()}}async close(){this.statusCallback=null,this.updateCallback=null,this.permissionCallback=null;for(const e of this.pendingTurnCompletions.values())clearTimeout(e.timer),e.reject(new Error("Codex app-server session closed"));this.pendingTurnCompletions.clear(),this.abortHandler&&(this.abortHandler=null),await this.closeCodexProcess()}async closeCodexProcess(){this.started.child.exitCode!==null||this.started.child.signalCode!==null||(this.started.child.stdin.end(),!await this.waitForProcessClose(2e3)&&(this.started.child.kill("SIGTERM"),!await this.waitForProcessClose(1e3)&&(this.started.child.kill("SIGKILL"),await this.waitForProcessClose(1e3))))}waitForProcessClose(e){return this.started.child.exitCode!==null||this.started.child.signalCode!==null?Promise.resolve(!0):new Promise(s=>{const t=setTimeout(()=>s(!1),e);t.unref(),this.started.child.once("close",()=>{clearTimeout(t),s(!0)})})}async initialize(){this.initialized||(await this.rpc.request("initialize",{clientInfo:{name:"aca",version:"0.1.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}}),this.initialized=!0)}async establishThread(e){const s=d(e.mode);if(this.providerSessionId)try{this.emitStatus("resuming","Codex 会话恢复中","thread/resume");const r=await this.rpc.request("thread/resume",{threadId:this.providerSessionId,cwd:e.cwd,...e.model?{model:e.model}:{},approvalsReviewer:"user",...s},6e4);return this.providerSessionId=String(r?.thread?.id??this.providerSessionId),this.providerSessionId}catch(r){if(e.requireSessionResume){const a=r instanceof Error?r.message:String(r);throw new Error(`无法恢复导入的 Codex Session ${this.providerSessionId}:${a}`)}this.providerSessionId=null}this.emitStatus("acp","Codex 启动中","thread/start");const n=(await this.rpc.request("thread/start",{cwd:e.cwd,...e.model?{model:e.model}:{},approvalsReviewer:"user",...s,ephemeral:!1,threadSource:"aca"},6e4))?.thread?.id;if(!n)throw new Error("Codex app-server thread/start did not return thread id");return this.providerSessionId=n,n}attachAbortSignal(e){if(e){if(this.abortHandler=()=>{this.cancel()},e.aborted)throw new Error("ACP prompt cancelled");e.addEventListener("abort",this.abortHandler,{once:!0})}}handleNotification(e,s){!this.promptActive&&!P(e)||(this.rpc.refreshPendingRequestTimeout("turn/start"),this.updates.push({method:e,params:s}),this.captureAgentMessagePhase(e,s),this.appendFinalAnswerDelta(e,s),e==="turn/completed"&&this.resolveTurnCompleted(s),m(e,s,{pushUpdate:t=>this.updateCallback?.(t),pushStatus:(t,n,r,a)=>this.emitStatus(t,n,r,a)},{agentMessagePhases:this.agentMessagePhases}))}captureAgentMessagePhase(e,s){if(e!=="item/started"&&e!=="item/completed")return;const t=s?.item;t?.type!=="agentMessage"||!t.id||this.agentMessagePhases.set(t.id,t.phase??"")}appendFinalAnswerDelta(e,s){if(e!=="item/agentMessage/delta")return;const t=s;if(!t.itemId||typeof t.delta!="string")return;const n=this.agentMessagePhases.get(t.itemId);(n==="final_answer"||!n)&&(this.content+=t.delta)}waitForTurnCompleted(e,s){const t=this.completedTurns.get(e);return t?Promise.resolve(t):new Promise((n,r)=>{const a=setTimeout(()=>{this.pendingTurnCompletions.delete(e),r(new Error("Codex app-server request timed out while waiting for turn/completed"))},s);a.unref(),this.pendingTurnCompletions.set(e,{resolve:n,reject:r,timer:a})})}resolveTurnCompleted(e){const s=e?.turn,t=s?.id;if(!t)return;this.completedTurns.set(t,s);const n=this.pendingTurnCompletions.get(t);if(n){if(this.pendingTurnCompletions.delete(t),clearTimeout(n.timer),s.status==="failed"){n.reject(new Error(`Codex turn failed: ${JSON.stringify(s.error??{})}`));return}n.resolve(s)}}async handleReverseRequest(e,s){return f(e)?(this.emitStatus("requestPermission","等待授权",S(s),e),g(e,s,this.permissionCallback)):{}}emitStatus(e,s,t,n){const r={phase:e,label:s,...t?{detail:t}:{},...n?{updateType:n}:{},atMs:Date.now()},a=this.statusTimeline[this.statusTimeline.length-1];a&&a.phase===r.phase&&a.label===r.label&&a.detail===r.detail&&a.updateType===r.updateType||(this.statusTimeline.push(r),this.statusCallback?.(r))}}function T(i,e){return(e?.length?e:[{type:"text",text:i}]).map(t=>t.type==="image"?t.uri&&c.existsSync(t.uri)?{type:"localImage",path:t.uri}:{type:"image",url:`data:${t.mimeType};base64,${t.data}`}:{type:"text",text:t.text,text_elements:[]})}function d(i){const e=String(i||"").trim();return e==="read-only"?{approvalPolicy:"on-request",sandbox:"read-only"}:e==="acceptEdits"||e==="accept-edits"?{approvalPolicy:"on-failure",sandbox:"workspace-write"}:["agent-full-access","full-access","bypassPermissions","danger-full-access"].includes(e)?{approvalPolicy:"never",sandbox:"danger-full-access"}:{approvalPolicy:"on-request",sandbox:"workspace-write"}}function x(i){if(!i)return{};const e={},s=i.reasoning_effort??i.reasoningEffort??i.model_reasoning_effort??i.modelReasoningEffort??i.effort;return typeof s=="string"&&s&&(e.effort=s),e}function S(i){if(!i||typeof i!="object"||Array.isArray(i))return;const e=i;for(const s of["command","cwd","reason","grantRoot"]){const t=e[s];if(typeof t=="string"&&t.trim())return y(t)}}function y(i){const e=i.replace(/\s+/g," ").trim();return e.length>120?`${e.slice(0,117)}...`:e}function P(i){return i.startsWith("thread/")?!0:["account/rateLimits/updated","account/updated","configWarning","warning","model/rerouted","thread/compacted"].includes(i)}function I(){const i=Number.parseInt(process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(i)&&i>=3e4?i:360*60*1e3}export{_ as NativeCodexProvider,w as nativeCodexCapabilities};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import h from"node:fs";import{closeAcpProcess as C}from"../../client/acp-process.js";import{JsonLineRpcClient as k}from"../../client/json-rpc.js";import{createPlanEvent as _,normalizePlanSessionUpdate as b}from"../../plan-events.js";import{startCodexAppServer as E}from"./codex-process.js";import{codexAcpSessionUpdatesFromNotification as $}from"./events.js";const A=6e4,D=128*1024,L=2*1024*1024,j=5*1024*1024;async function X(t){const e=t.sessionId.trim();if(!e)throw new Error("Codex Session ID 不能为空。");const n=Math.max(1,Math.min(20,Math.trunc(t.turnLimit))),r=E(process.cwd()),o=new k(r.child,{peerName:"Codex app-server"});try{await o.request("initialize",{clientInfo:{name:"aica-session-import",version:"0.1.0"},capabilities:{experimentalApi:!0,requestAttestation:!1}},A);const s=p(await o.request("thread/read",{threadId:e,includeTurns:!1},A))||{},a=p(s.thread);if(!a||i(a.id)!==e)throw new Error(`找不到 Codex Session:${e}`);const d=i(a.cwd);if(!d||!h.existsSync(d)||!h.statSync(d).isDirectory())throw new Error(`Codex Session 的工作目录不存在:${d||"unknown"}`);const u=t.detailMode==="diagnostic"?"full":"summary",f=p(await o.request("thread/turns/list",{threadId:e,limit:n,sortDirection:"desc",itemsView:u},A))||{};return R({thread:a,turns:Array.isArray(f.data)?f.data:[]},{...t,sessionId:e,turnLimit:n})}finally{await C(r.child).catch(()=>{})}}function R(t,e){const n=p(t.thread)||{},r=e.sessionId.trim(),o=Math.max(1,Math.min(20,Math.trunc(e.turnLimit))),s=i(n.cwd);if(!s||!h.existsSync(s)||!h.statSync(s).isDirectory())throw new Error(`Codex Session 的工作目录不存在:${s||"unknown"}`);const a=t.turns.map(p).filter(g).slice(0,o).reverse(),d=V(e.detailMode==="diagnostic"?j:L),u=a.map(c=>({sourceTurn:c,importedTurn:B(c,d)})).filter(c=>!!c.importedTurn);if(e.detailMode==="diagnostic")for(const{sourceTurn:c,importedTurn:w}of u){const M=(Array.isArray(c.items)?c.items:[]).map(p).filter(g);w.events=M.flatMap((S,I)=>N(S,w.startedAtMs+I,e.diffEnabled,d))}const f=u.map(c=>c.importedTurn),m=i(n.preview);return{provider:"codex",providerSessionId:r,cwd:h.realpathSync(s),title:l(i(n.name)||m||"Codex 历史会话",120),preview:l(m,240),sourceCreatedAtMs:y(n.createdAt),sourceUpdatedAtMs:y(n.updatedAt),sourceCliVersion:l(i(n.cliVersion),80),detailMode:e.detailMode,turnLimit:o,turns:f,truncated:d.truncated}}function B(t,e){const n=i(t.id);if(!n)return null;const r=(Array.isArray(t.items)?t.items:[]).map(p).filter(g),o=e.takeText(r.filter(u=>u.type==="userMessage").map(U).filter(Boolean).join(`
|
|
2
|
+
|
|
3
|
+
`)),s=e.takeText(r.filter(u=>u.type==="agentMessage"&&(!u.phase||u.phase==="final_answer")).map(u=>i(u.text)).filter(Boolean).join(`
|
|
4
|
+
|
|
5
|
+
`)),a=y(t.startedAt)||Date.now(),d=y(t.completedAt)||a;return!o&&!s?null:{sourceTurnId:n,status:l(i(t.status)||"completed",40),startedAtMs:a,completedAtMs:Math.max(a,d),userText:o,assistantText:s,events:[]}}function N(t,e,n,r){const o=i(t.type),s=i(t.id);if(o==="reasoning"){const f=r.takeText(P(t.summary).join(`
|
|
6
|
+
`));return f?r.takeEvent({eventType:"agent_thought_chunk",label:"thought",text:f,raw:{method:"history/item",params:{itemId:s},update:{sessionUpdate:"agent_thought_chunk",content:{type:"text",text:f}}},atMs:e}):[]}if(o==="plan"){const f=r.takeText(i(t.text)),m=b({sessionUpdate:"plan",planId:s,markdown:f});if(!m)return[];const c=_({update:m,method:"history/item",params:{itemId:s},atMs:e});return r.takeEvent({eventType:c.type,label:c.label,...c.text?{text:c.text}:{},...c.status?{status:c.status}:{},...c.toolCallId?{toolCallId:c.toolCallId}:{},raw:c.raw,atMs:c.atMs})}if(["userMessage","agentMessage","hookPrompt"].includes(o))return[];const a=q(t,n),d=$("item/completed",{item:a})[0];if(!d)return[];const u=i(d.status)||O(i(t.status));return r.takeEvent({eventType:"tool_call_update",label:z(o,a),...u?{status:u}:{},...s?{toolCallId:s}:{},raw:{method:"history/item",params:{item:a},update:d},atMs:e})}function U(t){return(Array.isArray(t.content)?t.content:[]).map(n=>{const r=p(n);return r?r.type==="text"?i(r.text):r.type==="localImage"?`[历史图片:${i(r.path)||"本地文件未导入"}]`:r.type==="image"?"[历史图片:远程内容未导入]":r.type==="skill"?`[Skill:${i(r.name)||i(r.path)}]`:r.type==="mention"?`[引用:${i(r.name)||i(r.path)}]`:"[历史内容未导入]":""}).filter(Boolean).join(`
|
|
7
|
+
`)}function q(t,e){const n=x(t,65536);return!e&&n.type==="fileChange"&&Array.isArray(n.changes)&&(n.changes=n.changes.map(r=>{const o=p(r);return o?{path:o.path,kind:o.kind,diff:""}:r})),n}function z(t,e){return t==="commandExecution"?l(i(e.command)||"执行命令",160):t==="fileChange"?"文件修改":t==="webSearch"?l(i(e.query)?`Web Search: ${i(e.query)}`:"Web Search",160):t==="mcpToolCall"?l(`MCP: ${i(e.server)}.${i(e.tool)}`,160):t==="dynamicToolCall"?l(i(e.tool)||"工具调用",160):t==="imageView"?l(`查看图片:${i(e.path)}`,160):t==="imageGeneration"?"生成图片":l(t||"过程记录",160)}function O(t){const e=t.toLowerCase();return["completed","success","succeeded"].includes(e)?"completed":["failed","error","declined"].includes(e)?"failed":["cancelled","canceled"].includes(e)?"cancelled":e||"completed"}function V(t){let e=t,n=0;const r={truncated:!1,takeText(o){const s=l(o,D);if(s.length<o.length&&(r.truncated=!0),e<=0)return s&&(r.truncated=!0),"";const a=s.slice(0,e);return a.length<s.length&&(r.truncated=!0),e-=a.length,a},takeEvent(o){if(n>=300)return r.truncated=!0,[];const s=JSON.stringify(o).length;return s>e?(r.truncated=!0,[]):(e-=s,n+=1,[o])}};return r}function x(t,e,n=0){if(!t||typeof t!="object"||Array.isArray(t))return{};const r={};for(const[o,s]of Object.entries(t))typeof s=="string"?r[o]=l(s,e):Array.isArray(s)?r[o]=s.slice(0,100).map(a=>T(a,e,n+1)):r[o]=T(s,e,n+1);return r}function T(t,e,n){return n>8?"[内容层级过深,已截断]":typeof t=="string"?l(t,e):Array.isArray(t)?t.slice(0,100).map(r=>T(r,e,n+1)):t&&typeof t=="object"?x(t,e,n):t}function p(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function g(t){return!!t}function i(t){return typeof t=="string"?t.trim():""}function P(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"&&!!e.trim()):[]}function y(t){const e=Number(t);return Number.isFinite(e)&&e>0?Math.trunc(e*1e3):0}function l(t,e){return t.length<=e?t:t.slice(0,e)}export{R as buildCodexSessionImport,X as extractCodexSession};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import m from"node:fs";import{promptBlocksToAcpContent as S}from"../../client/acp-content.js";import{eventFromAcpSessionUpdate as y,statusFromAcpSessionUpdate as C}from"../../client/acp-events.js";import{defaultAcpRuntimePool as I}from"../../client/acp-runtime-pool.js";import{resolveCodexAcpLaunch as v}from"./launch.js";import{CodexPromptPerformanceTracker as A,readCodexContextMaintenancePolicy as x}from"./context-maintenance.js";const P={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 F{id="codex-acp";name="Codex ACP";capabilities=P;async createSession(e){return new k(e.cwd,e.providerSessionId??null,e.timeoutMs)}}class k{cwd;providerSessionId;defaultTimeoutMs;lease=null;sessionResponse=null;statusCallback=null;updateCallback=null;permissionCallback=null;userInputCallback=null;abortHandler=null;statusTimeline=[];updates=[];content="";performanceTracker=null;constructor(e,s,t=q()){this.cwd=e,this.providerSessionId=s,this.defaultTimeoutMs=t}async sendPrompt(e){if(!m.existsSync(e.cwd)||!m.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.length=0,this.statusTimeline.length=0,this.performanceTracker=new A(s);let t=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,t=a.client,n=a.started,await this.initialize(a),r=await this.establishSession(a,e),await this.applyConfig(t,r,e),this.emitStatus("thinking","思考中"),c=this.startSlowStatusTimer(),i=await this.promptWithAbort(t,{sessionId:r,prompt:S(e.prompt,e.promptBlocks),timeoutMs:e.timeoutMs??this.defaultTimeoutMs,signal:e.signal});const d=b(i);d&&d!==r&&(r=d,this.providerSessionId=d,a.setProviderSession({providerSessionId:d,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:t.rpc.stdout,stderr:t.rpc.stderr,content:this.content.trim(),updates:[...this.updates],statusTimeline:[...this.statusTimeline],performance:this.performanceTracker?.snapshot(),contextUsage:O(i),promptResponse:i}}async compactContext(e){if(!m.existsSync(e.cwd)||!m.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 t=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),t=await this.establishSession(i,e),await this.applyConfig(i.client,t,e);const c=E(e.timeoutMs);n=await this.compactWithAbort(i.client,{sessionId:t,allowRollover:e.allowRollover===!0,timeoutMs:c,signal:e.signal});const a=b(n);a&&a!==t&&(t=a,this.providerSessionId=a,i.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}))}catch(i){if(this.lease&&T(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=l(n)??{};return{providerSessionId:t||this.providerSessionId||"",contextUsage:w(r.contextUsage),maintenance:l(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=v();return I.acquire({providerId:"codex-acp",cwd:e,providerSessionId:this.providerSessionId,command:s.command,args:s.args,onSessionUpdate:t=>this.handleSessionUpdate(t),onClientRequest:async(t,n)=>{if(t==="session/request_permission")return this.requestPermission(n);if(t==="elicitation/create"||t==="session/request_user_input")return this.requestUserInput(n);throw new Error(`Unsupported Codex ACP client request: ${t}`)}})}async initialize(e){e.initialized||(await e.client.initialize(6e4),e.markInitialized())}async establishSession(e,s){const t=e.client,n=M(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 t.loadSession({sessionId:this.providerSessionId,cwd:s.cwd,config:n},6e4);this.sessionResponse=l(c);const a=f(c)||this.providerSessionId;return this.providerSessionId=a,e.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}),a}catch{this.providerSessionId=null}this.emitStatus("acp","Codex ACP 会话创建中","session/new");const r=await t.newSession({cwd:s.cwd,config:n},12e4);this.sessionResponse=l(r);const i=f(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,t){t.model&&await e.setSessionConfigOption({sessionId:s,configId:"model",value:t.model},6e4).catch(()=>{});const n=h(t.mode);n&&await e.setSessionConfigOption({sessionId:s,configId:"approvalPolicy",value:n},6e4).catch(()=>{});const r=p(t.mode);r&&await e.setSessionConfigOption({sessionId:s,configId:"sandbox",value:r},6e4).catch(()=>{});for(const[i,c]of Object.entries(t.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=y(e);s&&(s.type==="agent_message_chunk"&&(this.content+=s.text??""),this.updateCallback?.(s));const t=C(e);t&&this.emitStatus(t.phase,t.label,t.detail,t.updateType)}startSlowStatusTimer(){const e=x().slowEventThresholdMs,s=setInterval(()=>{const t=this.performanceTracker,n=Date.now();if(!t?.shouldReportSlow(n,e))return;const r=t.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){const t=e.prompt({sessionId:s.sessionId,prompt:s.prompt},s.timeoutMs);if(!s.signal)return t;if(s.signal.aborted)throw await this.lease?.dispose().catch(()=>{}),new Error("Codex ACP prompt cancelled");let n=null;const r=new Promise((i,c)=>{n=()=>{e.cancel(s.sessionId),this.lease?.dispose().catch(()=>{}),c(new Error("Codex ACP prompt cancelled"))},s.signal?.addEventListener("abort",n,{once:!0})});try{return await Promise.race([t,r])}finally{n&&s.signal.removeEventListener("abort",n)}}async compactWithAbort(e,s){const t=e.compactSession({sessionId:s.sessionId,allowRollover:s.allowRollover,timeoutMs:s.timeoutMs},s.timeoutMs);if(!s.signal)return t;if(s.signal.aborted)throw await this.lease?.dispose().catch(()=>{}),new Error("Codex ACP 上下文压缩已取消");let n=null;const r=new Promise((i,c)=>{n=()=>{e.cancel(s.sessionId),this.lease?.dispose().catch(()=>{}),c(new Error("Codex ACP 上下文压缩已取消"))},s.signal?.addEventListener("abort",n,{once:!0})});try{return await Promise.race([t,r])}finally{n&&s.signal.removeEventListener("abort",n)}}async requestPermission(e){if(!this.permissionCallback)return{outcome:{outcome:"cancelled"}};const s=e&&typeof e=="object"&&!Array.isArray(e)?e:{},t=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s,r=(Array.isArray(t.options)?t.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","等待授权",R(t),"session/request_permission"),this.permissionCallback({requestId:String(t.requestId??t.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:{},t=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s;return this.emitStatus("requestPermission","等待输入",_(t),"elicitation/create"),this.userInputCallback({requestId:String(t.requestId??t.id??`codex-acp-input-${Date.now()}`),prompt:String(t.prompt??t.message??t.question??""),params:e,...typeof t.defaultValue=="string"?{defaultValue:t.defaultValue}:{}})}emitStatus(e,s,t,n){const r={phase:e,label:s,...t?{detail:t}:{},...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}}function T(o,e){if(e?.aborted)return!0;const s=o instanceof Error?o.message:String(o||"");return/compact.*timed out|request timed out.*compact|adapter closed|aborted|cancelled/i.test(s)}function f(o){if(!o||typeof o!="object"||Array.isArray(o))return null;const e=o.sessionId;return typeof e=="string"&&e.trim()?e.trim():null}function l(o){return o&&typeof o=="object"&&!Array.isArray(o)?o:null}function p(o){const e=String(o||"").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 h(o){const e=String(o||"").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 M(o){return{...o.model?{model:o.model}:{},...h(o.mode)?{approvalPolicy:h(o.mode)}:{},...p(o.mode)?{sandbox:p(o.mode)}:{},...o.configOptionValues??{}}}function R(o){const e=o.params&&typeof o.params=="object"&&!Array.isArray(o.params)?o.params:o;for(const s of["command","cwd","reason","grantRoot","method"]){const t=e[s];if(typeof t=="string"&&t.trim())return g(t)}}function _(o){for(const e of["prompt","message","question","title"]){const s=o[e];if(typeof s=="string"&&s.trim())return g(s)}}function g(o){const e=o.replace(/\s+/g," ").trim();return e.length>120?`${e.slice(0,117)}...`:e}function q(){const o=Number.parseInt(process.env.ACA_CODEX_ACP_PROMPT_TIMEOUT_MS??process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(o)&&o>=3e4?o:360*60*1e3}function E(o){const e=Number.isInteger(o)?Number(o):Number.parseInt(process.env.ACA_CODEX_ACP_COMPACT_TIMEOUT_MS??"",10);return Number.isFinite(e)&&e>=3e4?Math.min(e,6e5):12e4}function b(o){if(!o||typeof o!="object"||Array.isArray(o))return null;const e=o;return typeof e.sessionId=="string"&&e.sessionId.trim()?e.sessionId:null}function O(o){const e=l(o),s=l(e?._meta);return w(s?.acaContextUsage)}function w(o){const e=l(o);if(!e)return null;const s=u(e.contextWindow),t=u(e.usedTokens),n=u(e.inputTokens),r=String(e.state||"unknown"),i=["active","compacted","new_thread"].includes(r)?r:"unknown";return{usedTokens:t,inputTokens:n,contextWindow:s,ratio:s>0?Math.max(0,u(e.ratio)||t/s):0,observedAtMs:u(e.observedAtMs)||Date.now(),state:i,maintenanceAction:typeof e.maintenanceAction=="string"?e.maintenanceAction:null}}function u(o){return typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0}export{F as CodexAcpProvider,P as codexAcpCapabilities};
|
|
1
|
+
import m from"node:fs";import{promptBlocksToAcpContent as b}from"../../client/acp-content.js";import{eventFromAcpSessionUpdate as y,statusFromAcpSessionUpdate as C}from"../../client/acp-events.js";import{defaultAcpRuntimePool as I}from"../../client/acp-runtime-pool.js";import{resolveCodexAcpLaunch as v}from"./launch.js";import{CodexPromptPerformanceTracker as A,readCodexContextMaintenancePolicy as x}from"./context-maintenance.js";const P={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 F{id="codex-acp";name="Codex ACP";capabilities=P;async createSession(e){return new k(e.cwd,e.providerSessionId??null,e.timeoutMs)}}class k{cwd;providerSessionId;defaultTimeoutMs;lease=null;sessionResponse=null;statusCallback=null;updateCallback=null;permissionCallback=null;userInputCallback=null;abortHandler=null;statusTimeline=[];updates=[];content="";performanceTracker=null;constructor(e,s,t=q()){this.cwd=e,this.providerSessionId=s,this.defaultTimeoutMs=t}async sendPrompt(e){if(!m.existsSync(e.cwd)||!m.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.length=0,this.statusTimeline.length=0,this.performanceTracker=new A(s);let t=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,t=a.client,r=a.started,await this.initialize(a),n=await this.establishSession(a,e),await this.applyConfig(t,n,e),this.emitStatus("thinking","思考中"),c=this.startSlowStatusTimer(),i=await this.promptWithAbort(t,{sessionId:n,prompt:b(e.prompt,e.promptBlocks),timeoutMs:e.timeoutMs??this.defaultTimeoutMs,signal:e.signal});const d=w(i);d&&d!==n&&(n=d,this.providerSessionId=d,a.setProviderSession({providerSessionId:d,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:t.rpc.stdout,stderr:t.rpc.stderr,content:this.content.trim(),updates:[...this.updates],statusTimeline:[...this.statusTimeline],performance:this.performanceTracker?.snapshot(),contextUsage:O(i),promptResponse:i}}async compactContext(e){if(!m.existsSync(e.cwd)||!m.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 t=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),t=await this.establishSession(i,e),await this.applyConfig(i.client,t,e);const c=E(e.timeoutMs);r=await this.compactWithAbort(i.client,{sessionId:t,allowRollover:e.allowRollover===!0,timeoutMs:c,signal:e.signal});const a=w(r);a&&a!==t&&(t=a,this.providerSessionId=a,i.setProviderSession({providerSessionId:a,sessionResponse:this.sessionResponse}))}catch(i){if(this.lease&&T(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:t||this.providerSessionId||"",contextUsage:S(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=v();return I.acquire({providerId:"codex-acp",cwd:e,providerSessionId:this.providerSessionId,command:s.command,args:s.args,onSessionUpdate:t=>this.handleSessionUpdate(t),onClientRequest:async(t,r)=>{if(t==="session/request_permission")return this.requestPermission(r);if(t==="elicitation/create"||t==="session/request_user_input")return this.requestUserInput(r);throw new Error(`Unsupported Codex ACP client request: ${t}`)}})}async initialize(e){e.initialized||(await e.client.initialize(6e4),e.markInitialized())}async establishSession(e,s){const t=e.client,r=M(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 t.loadSession({sessionId:this.providerSessionId,cwd:s.cwd,config:r},6e4);this.sessionResponse=l(c);const a=f(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 t.newSession({cwd:s.cwd,config:r},12e4);this.sessionResponse=l(n);const i=f(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,t){t.model&&await e.setSessionConfigOption({sessionId:s,configId:"model",value:t.model},6e4).catch(()=>{});const r=h(t.mode);r&&await e.setSessionConfigOption({sessionId:s,configId:"approvalPolicy",value:r},6e4).catch(()=>{});const n=p(t.mode);n&&await e.setSessionConfigOption({sessionId:s,configId:"sandbox",value:n},6e4).catch(()=>{});for(const[i,c]of Object.entries(t.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=y(e);s&&(s.type==="agent_message_chunk"&&(this.content+=s.text??""),this.updateCallback?.(s));const t=C(e);t&&this.emitStatus(t.phase,t.label,t.detail,t.updateType)}startSlowStatusTimer(){const e=x().slowEventThresholdMs,s=setInterval(()=>{const t=this.performanceTracker,r=Date.now();if(!t?.shouldReportSlow(r,e))return;const n=t.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){const t=e.prompt({sessionId:s.sessionId,prompt:s.prompt},s.timeoutMs);if(!s.signal)return t;if(s.signal.aborted)throw await this.lease?.dispose().catch(()=>{}),new Error("Codex ACP prompt cancelled");let r=null;const n=new Promise((i,c)=>{r=()=>{e.cancel(s.sessionId),this.lease?.dispose().catch(()=>{}),c(new Error("Codex ACP prompt cancelled"))},s.signal?.addEventListener("abort",r,{once:!0})});try{return await Promise.race([t,n])}finally{r&&s.signal.removeEventListener("abort",r)}}async compactWithAbort(e,s){const t=e.compactSession({sessionId:s.sessionId,allowRollover:s.allowRollover,timeoutMs:s.timeoutMs},s.timeoutMs);if(!s.signal)return t;if(s.signal.aborted)throw await this.lease?.dispose().catch(()=>{}),new Error("Codex ACP 上下文压缩已取消");let r=null;const n=new Promise((i,c)=>{r=()=>{e.cancel(s.sessionId),this.lease?.dispose().catch(()=>{}),c(new Error("Codex ACP 上下文压缩已取消"))},s.signal?.addEventListener("abort",r,{once:!0})});try{return await Promise.race([t,n])}finally{r&&s.signal.removeEventListener("abort",r)}}async requestPermission(e){if(!this.permissionCallback)return{outcome:{outcome:"cancelled"}};const s=e&&typeof e=="object"&&!Array.isArray(e)?e:{},t=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s,n=(Array.isArray(t.options)?t.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","等待授权",R(t),"session/request_permission"),this.permissionCallback({requestId:String(t.requestId??t.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:{},t=s.request&&typeof s.request=="object"&&!Array.isArray(s.request)?s.request:s;return this.emitStatus("requestPermission","等待输入",_(t),"elicitation/create"),this.userInputCallback({requestId:String(t.requestId??t.id??`codex-acp-input-${Date.now()}`),prompt:String(t.prompt??t.message??t.question??""),params:e,...typeof t.defaultValue=="string"?{defaultValue:t.defaultValue}:{}})}emitStatus(e,s,t,r){const n={phase:e,label:s,...t?{detail:t}:{},...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}}function T(o,e){if(e?.aborted)return!0;const s=o instanceof Error?o.message:String(o||"");return/compact.*timed out|request timed out.*compact|adapter closed|aborted|cancelled/i.test(s)}function f(o){if(!o||typeof o!="object"||Array.isArray(o))return null;const e=o.sessionId;return typeof e=="string"&&e.trim()?e.trim():null}function l(o){return o&&typeof o=="object"&&!Array.isArray(o)?o:null}function p(o){const e=String(o||"").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 h(o){const e=String(o||"").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 M(o){return{...o.model?{model:o.model}:{},...h(o.mode)?{approvalPolicy:h(o.mode)}:{},...p(o.mode)?{sandbox:p(o.mode)}:{},...o.configOptionValues??{}}}function R(o){const e=o.params&&typeof o.params=="object"&&!Array.isArray(o.params)?o.params:o;for(const s of["command","cwd","reason","grantRoot","method"]){const t=e[s];if(typeof t=="string"&&t.trim())return g(t)}}function _(o){for(const e of["prompt","message","question","title"]){const s=o[e];if(typeof s=="string"&&s.trim())return g(s)}}function g(o){const e=o.replace(/\s+/g," ").trim();return e.length>120?`${e.slice(0,117)}...`:e}function q(){const o=Number.parseInt(process.env.ACA_CODEX_ACP_PROMPT_TIMEOUT_MS??process.env.ACA_ACP_PROMPT_TIMEOUT_MS??"",10);return Number.isInteger(o)&&o>=3e4?o:360*60*1e3}function E(o){const e=Number.isInteger(o)?Number(o):Number.parseInt(process.env.ACA_CODEX_ACP_COMPACT_TIMEOUT_MS??"",10);return Number.isFinite(e)&&e>=3e4?Math.min(e,6e5):12e4}function w(o){if(!o||typeof o!="object"||Array.isArray(o))return null;const e=o;return typeof e.sessionId=="string"&&e.sessionId.trim()?e.sessionId:null}function O(o){const e=l(o),s=l(e?._meta);return S(s?.acaContextUsage)}function S(o){const e=l(o);if(!e)return null;const s=u(e.contextWindow),t=u(e.usedTokens),r=u(e.inputTokens),n=String(e.state||"unknown"),i=["active","compacted","new_thread"].includes(n)?n:"unknown";return{usedTokens:t,inputTokens:r,contextWindow:s,ratio:s>0?Math.max(0,u(e.ratio)||t/s):0,observedAtMs:u(e.observedAtMs)||Date.now(),state:i,maintenanceAction:typeof e.maintenanceAction=="string"?e.maintenanceAction:null}}function u(o){return typeof o=="number"&&Number.isFinite(o)&&o>=0?o:0}export{F as CodexAcpProvider,P as codexAcpCapabilities};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import{Command as I}from"commander";import C from"node:crypto";import h from"node:fs";import P from"node:os";import f from"node:path";import x from"node:readline/promises";import{stdin as S,stdout as c}from"node:process";import{extractCodexSession as _}from"../acp/providers/codex/session-import.js";import{acaServerRequest as s}from"../core/aca-server-client.js";import{loadAcaConfig as l,upsertLocalProject as E}from"../core/aca-config.js";import{applyRuntimePathOptions as T}from"../core/runtime-options.js";function Z(){return new I("codex").description("管理本机 Codex 会话").addCommand(new I("import").description("将本机 Codex Session 导入 ACA Project").argument("<session-id>","Codex Session ID").option("--aica-home <path>","Runtime home directory (defaults to ~/.aica)").option("--aica-config <path>","Config file path").option("--aca-home <path>","Deprecated alias for --aica-home").option("--aca-config <path>","Deprecated alias for --aica-config").option("--path <path>","项目目录,支持相对路径;默认使用当前目录").option("--workspace <id>","新建 Project 时使用的 Workspace ID").option("--project-name <name>","自动创建 Project 时使用的名称").option("--turns <count>","导入最近多少个 Codex Turn,范围 1-20","20").option("--detail <mode>","详情模式:auto、compact、standard 或 diagnostic","auto").option("--title <name>","导入后的 ACA Session 标题").option("--dry-run","只读取和校验,不写入 ACA Server").option("-y, --yes","跳过交互确认,适用于脚本或非交互环境").action(b))}async function b(t,e){T(e);const o=l();if(!o.token)throw new Error("Worker 尚未登录,请先执行 aica login。");await R();const r=await N(o.machineId,t);if(r){console.log(`Codex Session 已存在:session=${r.sessionId} project=${r.projectId} title=${r.title||"未命名"}`);return}const i=k(e.path||process.cwd()),d=q(e.turns),p=await v(),a=D(e.detail,p),n=await _({sessionId:t,turnLimit:d,detailMode:a,diffEnabled:a==="diagnostic"&&p.diffEnabled===!0});M(i,n.cwd);const m=await W({targetPath:i,workspaceId:e.workspace,projectName:e.projectName,machineId:o.machineId}),g=e.title?.trim()||n.title;if(e.dryRun){console.log(JSON.stringify({dryRun:!0,action:m.action,projectId:m.project.project_id,projectName:m.project.name,providerSessionId:n.providerSessionId,path:i,detailMode:a,turns:n.turns.length,truncated:n.truncated,title:g},null,2));return}if(!e.yes&&!await G({sessionId:n.providerSessionId,targetPath:i,plan:m,turnCount:n.turns.length,detailMode:a})){console.log("已取消导入。");return}const u=await A(m);await L();const j=await s("POST","/api/codex-session-imports",{projectId:u.project_id,workspaceId:u.workspace_id,machineId:o.machineId,title:g,import:n}),$=j.item;console.log(`${j.imported?"已导入":"已存在"} session=${String($.session_id||"")} project=${u.project_id} turns=${n.turns.length} mode=${a}`)}async function N(t,e){const o=new URLSearchParams({machineId:t,providerSessionId:e.trim()});try{const r=await s("GET",`/api/codex-session-imports/status?${o.toString()}`);return r.exists?r.item:null}catch(r){const i=r instanceof Error?r.message:String(r);if(/\b404\b/.test(i))return null;throw r}}async function L(){const t=l();await s("POST","/api/heartbeat",{machineId:t.machineId,machineName:t.machineName,workspaceId:t.defaultWorkspaceId,projects:t.projects.map(e=>({projectId:e.projectId,workspaceId:e.workspaceId,name:e.name,rootPath:e.rootPath}))})}async function R(){try{await s("GET","/api/auth/me")}catch(t){const e=t instanceof Error?t.message:String(t);throw/\b401\b|unauthorized/i.test(e)?new Error("Worker 登录已失效,请先执行 aica login 重新登录。"):t}}async function v(){try{return(await s("GET","/api/process-details/capabilities")).item||{}}catch{return{}}}function D(t,e){const o=String(t||"auto").trim().toLowerCase();if(o==="auto")return e.mode==="diagnostic"?"diagnostic":e.mode==="compact"?"compact":"standard";if(o==="compact"||o==="standard"||o==="diagnostic")return o;throw new Error("--detail 必须是 auto、compact、standard 或 diagnostic。")}async function W(t){const e=l(),o=e.projects.find(a=>t.workspaceId&&a.workspaceId!==t.workspaceId?!1:w(a.rootPath)===t.targetPath),r=t.workspaceId||o?.workspaceId||e.defaultWorkspaceId,i=await s("GET",`/api/projects?workspaceId=${encodeURIComponent(r)}`);if(o){const a=i.items.find(n=>n.project_id===o.projectId&&w(n.root_path)===t.targetPath);if(a)return{action:"reuse",project:a}}const d=i.items.find(a=>w(a.root_path)===t.targetPath);if(d)return{action:"attach",project:d};const p=t.projectName?.trim()||o?.name||f.basename(t.targetPath);return{action:"create",project:{project_id:o?.projectId||O(r,t.machineId,t.targetPath,p),workspace_id:r,name:p,root_path:t.targetPath}}}async function A(t){if(t.action==="reuse")return t.project;if(t.action==="attach")return y(t.project),t.project;const e=await s("POST","/api/projects",{projectId:t.project.project_id,workspaceId:t.project.workspace_id,name:t.project.name,rootPath:t.project.root_path,source:"aica-codex-import",projectType:"project"});return y(e.item),e.item}function y(t){E({projectId:t.project_id,workspaceId:t.workspace_id,name:t.name,rootPath:t.root_path})}function M(t,e){const o=h.realpathSync(e);if(t!==o)throw new Error(`指定目录与 Codex Session 工作目录不一致:path=${t} session=${o}`)}function k(t){const e=t==="~"?P.homedir():t.startsWith("~/")?f.join(P.homedir(),t.slice(2)):t,o=f.resolve(e);if(!h.existsSync(o)||!h.statSync(o).isDirectory())throw new Error(`Project 工作目录不存在:${o}`);return h.realpathSync(o)}function w(t){try{return k(t)}catch{return null}}function O(t,e,o,r){const i=r.toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"project",d=C.createHash("sha256").update(`${t}\0${e}\0${o}`).digest("hex").slice(0,12);return`aica-${i}-${d}`}async function G(t){if(!S.isTTY||!c.isTTY)throw new Error("当前为非交互环境,请确认参数无误后添加 --yes 执行导入。");const e=t.plan.action==="reuse"?`在已有 Project「${t.plan.project.name}」中创建 Session`:t.plan.action==="attach"?`将目录关联到已有 Project「${t.plan.project.name}」,再创建 Session`:`创建 Project「${t.plan.project.name}」,再创建 Session`;c.write(`
|
|
2
|
+
即将导入 Codex Session:
|
|
3
|
+
`),c.write(` 项目路径:${t.targetPath}
|
|
4
|
+
`),c.write(` Session ID:${t.sessionId}
|
|
5
|
+
`),c.write(` 执行动作:${e}
|
|
6
|
+
`),c.write(` 历史范围:最近 ${t.turnCount} 个 Turn
|
|
7
|
+
`),c.write(` 详情模式:${t.detailMode}
|
|
8
|
+
`);const o=x.createInterface({input:S,output:c});try{const r=(await o.question("确认导入?[y/N] ")).trim().toLowerCase();return r==="y"||r==="yes"}finally{o.close()}}function q(t){const e=Number.parseInt(String(t||"20"),10);if(!Number.isInteger(e)||e<1||e>20)throw new Error("--turns 必须是 1 到 20 之间的整数。");return e}export{Z as createWorkerCodexCommand};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const I=1024,S=new Set(["agent_message_chunk","agent_progress_chunk","agent_thought_chunk","user_message_chunk"]),w=new Set(["usage_update","session_info_update"]);function C(t,e){const n=t.at(-1);if(!n)return t.push(e),!1;if(E(n,e)){const r=`${n.text??""}${e.text??""}`;if(r.length<=1024)return n.text=r,n.raw=d(n.raw,e.raw,r),!0}if(x(n,e)){const r=p(n.raw);return n.label=e.label,n.text=e.text,n.status=e.status,n.toolCallId=e.toolCallId,n.raw=d(n.raw,e.raw,e.text,r),!0}return t.push(e),!1}function E(t,e){return S.has(t.eventType)&&t.eventType===e.eventType&&t.turnId===e.turnId&&t.label===e.label&&t.status===e.status&&!t.toolCallId&&!e.toolCallId&&typeof t.text=="string"&&typeof e.text=="string"}function x(t,e){if(t.eventType!==e.eventType||t.turnId!==e.turnId)return!1;if(w.has(t.eventType))return!0;if(t.eventType==="plan")return f(t.raw)===f(e.raw);if(t.eventType!=="config_option_update")return!1;const n=c(t.raw),r=c(e.raw);return!!n&&n===r}function f(t){const e=l(t);for(const n of["planId","plan_id","id"])if(typeof e?.[n]=="string"&&e[n].trim())return e[n].trim();return"default"}function c(t){const e=l(t);for(const n of["configId","optionId","id","key","name"])if(typeof e?.[n]=="string"&&e[n].trim())return e[n].trim();return""}function d(t,e,n,r=p(t)){const u=a(e);if(!u)return e;const _=h(e),T=y(t)+y(e),s={...u,acaSequence:r,acaSequenceEnd:_,sourceEventCount:T};if(n!==void 0){const o=a(u.update);o&&(s.update={...o,content:{type:"text",text:n}})}return s}function l(t){return a(a(t)?.update)}function p(t){const e=a(t)?.acaSequence;return typeof e=="number"?e:void 0}function h(t){const e=a(t),n=e?.acaSequenceEnd;return typeof n=="number"?n:typeof e?.acaSequence=="number"?e.acaSequence:void 0}function y(t){const e=a(t)?.sourceEventCount;return typeof e=="number"&&e>0?e:1}function a(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}export{C as appendCoalescedAcpEvent};
|
package/dist/core/job-worker.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import W from"node:crypto";import x from"node:fs";import S from"node:path";import{compactAgentContext as V,sendAgentPrompt as q}from"../acp/agent.js";import{acaServerDownload as D,acaServerRequest as b}from"./aca-server-client.js";import{loadAcaConfig as H}from"./aca-config.js";import{prepareLocalWorktree as G}from"./worktree.js";import{getAcaHome as $}from"./paths.js";import{collectAffectedFiles as N,extractAffectedFilePathsFromAcpRaw as K}from"./affected-files.js";import{resolveJobPermissionPolicy as X}from"./job-permission-policy.js";import{appendCoalescedAcpEvent as Z}from"./acp-event-coalescer.js";import{shouldUploadAcpEvent as Q}from"./acp-event-upload-filter.js";const Y=1500,ee=5e3,M=1e3,te=320,ne=64,O=900,oe=1e4,
|
|
2
|
-
localPath: ${
|
|
3
|
-
workspacePath: ${
|
|
1
|
+
import W from"node:crypto";import x from"node:fs";import S from"node:path";import{compactAgentContext as V,sendAgentPrompt as q}from"../acp/agent.js";import{acaServerDownload as D,acaServerRequest as b}from"./aca-server-client.js";import{loadAcaConfig as H}from"./aca-config.js";import{prepareLocalWorktree as G}from"./worktree.js";import{getAcaHome as $}from"./paths.js";import{collectAffectedFiles as N,extractAffectedFilePathsFromAcpRaw as K}from"./affected-files.js";import{resolveJobPermissionPolicy as X}from"./job-permission-policy.js";import{appendCoalescedAcpEvent as Z}from"./acp-event-coalescer.js";import{shouldUploadAcpEvent as Q}from"./acp-event-upload-filter.js";const Y=1500,ee=5e3,M=1e3,te=320,ne=64,O=900,oe=1e4,ie=0,ae=12e3;function re(e){return e?e==="~"?S.dirname($()):e.startsWith("~/")?S.join(S.dirname($()),e.slice(2)):e:""}function se(e){const t=e.project_metadata;return t&&typeof t=="object"&&!Array.isArray(t)&&t.kind==="chat"?!0:typeof e.project_root_path=="string"&&(e.project_root_path.startsWith("~/.aca/chats/")||/(^|\/)\.aca\/chats\//.test(e.project_root_path))}function qe(e,t={}){let n=!1,o=null,i=null;const a=new Set,c=new Set,u=new Map,s=async()=>{if(n)return;const r=ce();if(U(a.size,r))try{const m=t.loadConfig?.()??H();if(!m.token)return;for(;!n&&U(a.size,r);){const A=t.claimNextJob?await t.claimNextJob(m):await b("POST","/api/client/jobs/claim",{machineId:m.machineId,workspaceId:m.defaultWorkspaceId});if(!A.item)break;const d=A.item;if(n){await(t.cancelClaimedJob?t.cancelClaimedJob(d,m):P(d.job_id,m.machineId,"cancelled")).catch(()=>{});break}const f=d.session_id;c.has(f)&&e.warn(`claimed job=${d.job_id} for already active session=${f}; running anyway to avoid leaving it stuck`),a.add(d.job_id),c.add(f);const I=new AbortController,C=(t.runJob??ue)(d,m,e,I).catch(p=>{e.warn(`job ${d.job_id} failed outside handler: ${p instanceof Error?p.message:String(p)}`)}).finally(()=>{a.delete(d.job_id),c.delete(f),u.delete(d.job_id)});u.set(d.job_id,{controller:I,promise:C})}}catch(m){n||e.warn(`job worker failed: ${m instanceof Error?m.message:String(m)}`)}},w=()=>{if(n||o)return;const r=s();o=r,r.finally(()=>{o===r&&(o=null)})};w();const T=setInterval(()=>{w()},t.claimIntervalMs??Y);return{timer:T,stop:()=>i||(i=(async()=>{if(n)return;n=!0,clearInterval(T);for(const m of u.values())m.controller.abort();await o?.catch(()=>{});for(const m of u.values())m.controller.abort();const r=[...u.values()].map(m=>m.promise);r.length!==0&&await Promise.race([Promise.allSettled(r).then(()=>{}),E(ae)])})(),i)}}function ce(){const e=process.env.ACA_MAX_CONCURRENT_JOBS||process.env.ACA_MAX_CONCURRENT_PROJECT_JOBS||"",t=Number.parseInt(e,10);return!e.trim()||!Number.isFinite(t)||t<0?ie:t===0?0:Math.max(1,Math.min(t,8))}function U(e,t){return t===0||e<t}function le(){const e=Number.parseInt(process.env.ACA_ACP_EVENT_BATCH_INTERVAL_MS||"",10);return Number.isFinite(e)?Math.max(40,Math.min(e,2e3)):te}async function ue(e,t,n,o){const i=e.job_id,a=e.session_id,c=e.workspace_id,u=e.project_id??null,s=e.input??{},w=String(s.control?.type||"").toLowerCase();if(!w&&!s.message?.trim()&&(s.attachments??[]).length===0){await P(i,t.machineId,"job input missing message");return}const T=t.projects.find(p=>p.projectId===u),r=re(T?.rootPath||e.project_root_path||"");if(!r){await P(i,t.machineId,"job project root is unknown");return}se(e)&&x.mkdirSync(r,{recursive:!0}),n.info(`claimed job=${i} session=${a} project=${T?.name??u??"unknown"}`);const m=setInterval(()=>{b("POST",`/api/client/jobs/${encodeURIComponent(i)}/heartbeat`,{machineId:t.machineId}).catch(()=>{}),xe(i,o).catch(()=>{})},ee);let A=0;const d=be(i,t.machineId),f=ye(i,t.machineId),I=new Set;let C=null;try{await f.sendNow({phase:"initializing",label:"准备工作区",detail:e.worktree_id?"worktree":"project root"}).catch(()=>{});const p=G({projectId:u,sessionId:a,projectRoot:r,worktree:e});C=p,await ve(i,t.machineId,p);const g=de(s.acpRun);if(w==="compact"){if(!e.acp_session_id)throw new Error("Current session does not have an ACP context to compact");const l=await V({agentType:R(g.agentType,"codex"),cliType:R(g.cliType,"builtin"),acpSessionId:e.acp_session_id,cwd:p.cwd,model:s.model,mode:s.mode,configOptionValues:s.configOptionValues,timeoutMs:s.timeoutMs,allowRollover:s.control?.allowRollover===!0,signal:o.signal,onStatus:y=>{f.report({phase:y.phase,label:y.label,detail:y.detail,updateType:y.updateType,raw:y})}});await f.flush(),await b("POST",`/api/client/jobs/${encodeURIComponent(i)}/complete`,{machineId:t.machineId,acpSessionId:l.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"compact",allowRollover:s.control?.allowRollover===!0},acpSessionId:l.acpSessionId,durationMs:l.durationMs,usage:l.contextUsage,maintenance:l.maintenance,worktree:k(p)}}),n.info(`completed context compact job=${i}`);return}const _=await Te({cwd:p.cwd,sessionId:a,jobId:i,attachments:s.attachments??[]});_.length>0&&(n.info(`materialized ${_.length} attachment(s) for job=${i}`),await f.sendNow({phase:"initializing",label:"附件已写入本机",detail:_.map(l=>l.relativePath).join(", "),raw:{attachments:z(_)}}).catch(()=>{}));const j=_e(s,_),F=ge(j,_),h=await q({agentType:R(g.agentType,"codex"),cliType:R(g.cliType,"builtin"),acpSessionId:e.acp_session_id??null,requireSessionResume:me(e.session_raw),prompt:j,promptBlocks:F,cwd:p.cwd,model:s.model,mode:s.mode,configOptionValues:s.configOptionValues,canExecuteTools:s.canExecuteTools,timeoutMs:s.timeoutMs,contextWindow:fe(g.contextWindow),signal:o.signal,onStatus:l=>{f.report({phase:l.phase,label:l.label,detail:l.detail,updateType:l.updateType,raw:l})},onUpdate:l=>{A+=1;for(const L of K(l.raw))I.add(L);const y={turnId:e.user_turn_id??null,eventType:l.type,label:l.label,text:l.text,status:l.status,toolCallId:l.toolCallId,raw:Ie(l.raw,A)};Q(y)&&d.push(y)},onPermissionRequest:l=>{const y=X(s,l);return y?Promise.resolve(y):Re(i,t.machineId,l,o.signal)},onUserInputRequest:l=>ke(i,t.machineId,l,o.signal)});await d.flush(),await f.flush();const J=N({cwd:p.cwd,evidencePaths:I}),v=he(h.promptResponse);if(!(we(v)||!!h.content)){await P(i,t.machineId,`${h.agentType} stopped: ${v??"unknown"}`,{acpSessionId:h.acpSessionId,stopReason:v,exitCode:h.exitCode,stderr:Ee(h.stderr,4e3),worktree:k(p)});return}await b("POST",`/api/client/jobs/${encodeURIComponent(i)}/complete`,{machineId:t.machineId,acpSessionId:h.acpSessionId,assistantText:h.content,result:{ok:!0,acpSessionId:h.acpSessionId,stopReason:v,durationMs:h.durationMs,acpRun:s.acpRun??null,effectiveConfig:h.effectiveConfig??null,performance:h.performance??null,usage:h.contextUsage??null,updateCount:h.updates.length,statusTimeline:h.statusTimeline,worktree:k(p),attachments:z(_),files:J}}),n.info(`completed job=${i}`)}catch(p){await d.flush(),await f.flush();const g=o.signal.aborted?"cancelled":p instanceof Error?p.message:String(p),_=C?N({cwd:C.cwd,evidencePaths:I}):[];await P(i,t.machineId,pe(g),{rawError:g,files:_})}finally{await d.flush(),await f.flush(),clearInterval(m)}}function me(e){if(!e||typeof e!="object"||Array.isArray(e))return!1;const t=e.importedProviderSession;return!!(t&&typeof t=="object"&&!Array.isArray(t)&&t.strictResume===!0)}function pe(e){return/ACP request timed out/i.test(e)?"ACP 长时间没有完成,请稍后重试,或点击停止后重新发送。":/MimoCode request timed out/i.test(e)?"MimoCode 长时间没有完成,请稍后重试,或点击停止后重新发送。":e.replace(/\bsession\/prompt\b/g,"ACP 请求")}function de(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function fe(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function R(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function he(e){if(!e||typeof e!="object"||Array.isArray(e))return;const t=e;if(typeof t.stopReason=="string")return t.stopReason;if(typeof t.reason=="string")return t.reason;const n=t.part;if(n&&typeof n=="object"&&!Array.isArray(n)&&typeof n.reason=="string")return n.reason}function we(e){return e?["end_turn","stop","completed","complete"].includes(e):!1}function be(e,t){let n=[],o=null,i=Promise.resolve();const a=async s=>{s.length!==0&&await b("POST",`/api/client/jobs/${encodeURIComponent(e)}/events/batch`,{machineId:t,events:s})},c=()=>{o&&(clearTimeout(o),o=null);const s=n;return n=[],i=i.then(()=>a(s)).catch(()=>{}),i},u=()=>{o||(o=setTimeout(()=>{c()},le()),o.unref())};return{push(s){if(Z(n,s),n.length>=ne){c();return}u()},flush:c}}function ye(e,t){let n=null,o=0,i="",a=null,c=Promise.resolve();const u=r=>JSON.stringify({phase:r.phase??"",label:r.label??"",detail:r.detail??"",updateType:r.updateType??""}),s=async r=>{await b("POST",`/api/client/jobs/${encodeURIComponent(e)}/presence`,{machineId:t,phase:r.phase,label:r.label,detail:r.detail,updateType:r.updateType,raw:r.raw}),o=Date.now(),i=u(r)},w=()=>{if(a&&(clearTimeout(a),a=null),!n)return c;const r=n;return n=null,c=c.then(()=>s(r)).catch(()=>{}),c},T=r=>{a||(a=setTimeout(()=>{w()},r),a.unref())};return{report(r){const m=Date.now(),d=u(r)!==i,f=m-o>=oe;if(!d&&!f)return;n=r;const I=m-o;if(I>=O||o===0){w();return}T(O-I)},sendNow(r){return n=r,w()},flush:w}}function Ie(e,t){return e&&typeof e=="object"&&!Array.isArray(e)?{...e,acaSequence:t}:{value:e,acaSequence:t}}function _e(e,t=[]){const n=e?.message?.trim()??"";if(t.length===0)return n;const i=["用户随消息上传了以下附件,aca 已将附件写入本机工作区。需要读取附件时请直接使用下面的 localPath;图片附件也已作为 ACP image block 随本轮请求传入。",...t.map((a,c)=>`${c+1}. ${a.name} (${a.kind}, ${a.mimeType}, ${Pe(a.size)})
|
|
2
|
+
localPath: ${a.path}
|
|
3
|
+
workspacePath: ${a.relativePath}`)].join(`
|
|
4
4
|
`);return n?`${n}
|
|
5
5
|
|
|
6
|
-
${
|
|
6
|
+
${i}`:i}function ge(e,t){const n=[{type:"text",text:e}];for(const o of t)o.kind!=="image"||!o.mimeType.startsWith("image/")||n.push({type:"image",data:o.base64,mimeType:o.mimeType,uri:o.path});return n}async function Te(e){if(e.attachments.length===0)return[];const t=S.join(e.cwd,".aca","attachments",B(e.sessionId),B(e.jobId));x.mkdirSync(t,{recursive:!0});const n=[];for(const[o,i]of e.attachments.entries()){const a=i.attachmentId?{mimeType:i.mimeType||"application/octet-stream",bytes:await D(`/api/client/attachments/${encodeURIComponent(i.attachmentId)}`)}:Se(i.dataUrl??""),c=i.mimeType||a.mimeType||"application/octet-stream",u=i.kind==="image"||c.startsWith("image/")?"image":"file",s=Ae(i.name||`attachment-${o+1}`,c),w=S.join(t,`${String(o+1).padStart(2,"0")}-${s}`);x.writeFileSync(w,a.bytes),n.push({name:i.name||s,mimeType:c,size:a.bytes.byteLength,kind:u,path:w,relativePath:S.relative(e.cwd,w),base64:a.bytes.toString("base64"),sha256:W.createHash("sha256").update(a.bytes).digest("hex")})}return n}function Se(e){const t=e.indexOf(",");if(!e.startsWith("data:")||t<0)throw new Error("attachment dataUrl is not a data URL");const n=e.slice(5,t),o=e.slice(t+1),i=n.split(";").filter(Boolean),a=i[0]?.includes("/")?i[0]:"application/octet-stream";if(!i.includes("base64"))throw new Error("attachment dataUrl is not base64 encoded");return{mimeType:a,bytes:Buffer.from(o,"base64")}}function Ae(e,t){const n=S.basename(e).replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").trim(),o=`attachment${Ce(t)}`;return(!n||n==="."||n===".."?o:n).slice(0,180)}function Ce(e){switch(e.toLowerCase()){case"image/png":return".png";case"image/jpeg":return".jpg";case"image/webp":return".webp";case"image/gif":return".gif";case"text/plain":return".txt";case"application/json":return".json";case"text/markdown":case"text/x-markdown":return".md";case"application/pdf":return".pdf";case"application/msword":return".doc";case"application/vnd.openxmlformats-officedocument.wordprocessingml.document":return".docx";case"application/vnd.ms-excel":return".xls";case"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":return".xlsx";case"application/vnd.ms-powerpoint":return".ppt";case"application/vnd.openxmlformats-officedocument.presentationml.presentation":return".pptx";case"application/zip":return".zip";case"application/x-7z-compressed":return".7z";case"application/x-rar-compressed":case"application/vnd.rar":return".rar";case"application/gzip":return".gz";case"application/x-tar":return".tar";default:return""}}function B(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"item"}function z(e){return e.map(t=>({name:t.name,kind:t.kind,mimeType:t.mimeType,size:t.size,path:t.path,relativePath:t.relativePath,sha256:t.sha256}))}function Pe(e){if(!Number.isFinite(e)||e<=0)return"0 B";const t=["B","KB","MB","GB"];let n=e,o=0;for(;n>=1024&&o<t.length-1;)n/=1024,o+=1;return`${n>=10||o===0?n.toFixed(0):n.toFixed(1)} ${t[o]}`}async function ve(e,t,n){!n.usedWorktree||!n.worktreeId||await b("POST",`/api/client/jobs/${encodeURIComponent(e)}/worktree`,{machineId:t,baseCommit:n.baseCommit??null,worktreePath:n.cwd,status:n.status??"active",raw:n.raw??k(n)})}function k(e){return{usedWorktree:e.usedWorktree,worktreeId:e.worktreeId??null,cwd:e.cwd,status:e.status??null,baseCommit:e.baseCommit??null,branchName:e.branchName??null,baseBranch:e.baseBranch??null}}async function Re(e,t,n,o){const a=(await b("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:n})).item.permission_id;for(;!o.aborted;){await E(M);const c=await b("GET",`/api/client/permissions/${encodeURIComponent(a)}`);if(c.item.status==="resolved"&&c.item.response){const u=c.item.response.outcome;return u.outcome==="selected"?{outcome:u}:{outcome:{outcome:"cancelled"}}}}return{outcome:{outcome:"cancelled"}}}async function ke(e,t,n,o){const a=(await b("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:{kind:"elicitation",...n}})).item.permission_id;for(;!o.aborted;){await E(M);const c=await b("GET",`/api/client/permissions/${encodeURIComponent(a)}`);if(c.item.status==="resolved"&&c.item.response){const u=c.item.response.outcome;return u.outcome==="submitted"?{outcome:u}:{outcome:{outcome:"cancelled"}}}}return{outcome:{outcome:"cancelled"}}}async function xe(e,t){if(t.signal.aborted)return;const n=await b("GET",`/api/client/jobs/${encodeURIComponent(e)}`);Number(n.item.cancel_requested??0)===1&&t.abort()}async function P(e,t,n,o){await b("POST",`/api/client/jobs/${encodeURIComponent(e)}/fail`,{machineId:t,error:n,result:o})}function E(e){return new Promise(t=>setTimeout(t,e))}function Ee(e,t){return e.length<=t?e:`${e.slice(0,t)}...`}export{qe as startJobWorkerLoop};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import{execFileSync as
|
|
2
|
-
|
|
3
|
-
`
|
|
1
|
+
import{execFileSync as E}from"node:child_process";import{randomUUID as M}from"node:crypto";import u from"node:fs";import j from"node:os";import c from"node:path";import{acaServerRequest as h}from"./aca-server-client.js";import{loadAcaConfig as G,upsertLocalProject as L}from"./aca-config.js";import{startLongPollWorker as O}from"./long-poll-worker.js";const H=25e3,g=300,W=3e4;let y=null;function vt(t){return O({run:async()=>{const e=G();if(!e.token)throw new Error("Worker 尚未配置认证令牌");const r=await h("GET",`/api/client/machine-operations/claim?machineId=${encodeURIComponent(e.machineId)}&waitMs=${H}`);if(r.item)try{const o=await B(r.item);await h("POST",`/api/client/machine-operations/${encodeURIComponent(r.item.requestId)}/complete`,{result:o})}catch(o){const n=o instanceof Error?o.message:String(o);t.warn(`machine filesystem request failed request=${r.item.requestId}: ${n}`),await h("POST",`/api/client/machine-operations/${encodeURIComponent(r.item.requestId)}/fail`,{message:n}).catch(()=>{})}},onError:(e,r)=>t.warn(`machine filesystem worker failed, retry in ${r}ms: ${e instanceof Error?e.message:String(e)}`)})}async function B(t){if(t.operation==="filesystem_roots")return et();if(t.operation==="list_directory")return rt({directoryPath:String(t.payload.path||""),includeHidden:t.payload.includeHidden===!0});if(t.operation==="register_project")return ct(t.payload);if(t.operation==="list_project_directory")return U(t.payload);if(t.operation==="get_project_git_status")return z(t.payload);if(t.operation==="get_project_git_diff")return K(t.payload);if(t.operation==="get_project_git_log")return J(t.payload);if(t.operation==="get_project_git_commit")return V(t.payload);throw new Error("不支持的 Machine 文件系统操作。 ")}function U(t){const e=w(String(t.rootPath||"")),r=_(String(t.relativePath||"")),o=ut(e,r,!0),n=Math.max(0,Number(t.offset||0)),s=Math.min(300,Math.max(20,Number(t.limit||200))),i=u.readdirSync(o,{withFileTypes:!0}).filter(l=>!l.isSymbolicLink()).map(l=>({name:l.name,path:dt(e,c.join(o,l.name)),type:l.isDirectory()?"directory":l.isFile()?"file":"other",hidden:l.name.startsWith("."),extension:l.isFile()?c.extname(l.name).slice(1).toLowerCase():""})).filter(l=>l.type!=="other").sort((l,p)=>l.type!==p.type?l.type==="directory"?-1:1:l.name.localeCompare(p.name,void 0,{numeric:!0,sensitivity:"base"})),a=i.slice(n,n+s);return{path:r,rootKind:t.rootKind==="worktree"?"worktree":"project",items:a,total:i.length,nextOffset:n+a.length<i.length?n+a.length:null}}const A=500,S=2*1024*1024,f=2*1024*1024;function z(t){const e=w(String(t.rootPath||""));if(!b(e))return{isRepository:!1,branch:null,files:[],ahead:0,behind:0};const o=d(e,["status","--porcelain=v1","-z","--untracked-files=all","--no-renames"],S).split("\0").filter(Boolean).slice(0,A),n=o.map(a=>Y(a)).filter(a=>!!a),s=x(d(e,["diff","--no-ext-diff","--numstat","-z","--no-renames","HEAD","--","."],S));for(const a of n){const l=s.get(a.path);if(l)a.additions=l.additions,a.deletions=l.deletions;else if(a.status==="untracked"){const p=$(e,a.path);a.additions=p.additions,a.deletions=p.deletions}}const i=tt(e);return{isRepository:!0,branch:q(e),files:n,ahead:i.ahead,behind:i.behind,truncated:o.length>=A}}function K(t){const e=w(String(t.rootPath||"")),r=_(String(t.relativePath||""));if(!r)throw new Error("Diff 文件路径不能为空。");if(!b(e))return{isRepository:!1,path:r,diff:"",additions:0,deletions:0};const o=R(e,r),n=Q(e,r),s=n?d(e,["diff","--no-ext-diff","--unified=80","HEAD","--",r],f):N(e,["diff","--no-ext-diff","--no-index","--unified=80",process.platform==="win32"?"NUL":"/dev/null",o],f),i=n?x(d(e,["diff","--no-ext-diff","--numstat","-z","--no-renames","HEAD","--",r],32*1024)).get(r):$(e,r);return{isRepository:!0,path:r,diff:T(s),additions:i?.additions??0,deletions:i?.deletions??0,truncated:s.length>f}}function J(t){const e=w(String(t.rootPath||""));if(!b(e))return{isRepository:!1,items:[]};if(!Z(e))return{isRepository:!0,items:[]};const r=Math.min(200,Math.max(20,Number(t.limit||100)));return{isRepository:!0,items:d(e,["log",`--max-count=${r}`,"--date=iso-strict","--pretty=format:%H%x1f%h%x1f%an%x1f%ae%x1f%aI%x1f%D%x1f%s%x1f%b%x1e"],S).split("").map(i=>X(i)).filter(i=>!!i),limit:r}}function V(t){const e=w(String(t.rootPath||"")),r=String(t.commit||"").trim();if(!/^[0-9a-f]{7,64}$/i.test(r))throw new Error("Git 提交标识无效。");if(!b(e))return{isRepository:!1,commit:r,diff:"",additions:0,deletions:0};d(e,["cat-file","-e",`${r}^{commit}`],8*1024);const o=d(e,["show","--no-ext-diff","--no-color","--format=","--stat","--patch","--unified=40",r],f),n=[...x(d(e,["show","--no-ext-diff","--numstat","-z","--no-renames","--format=",r],S)).values()];return{isRepository:!0,commit:r,diff:T(o),additions:n.reduce((s,i)=>s+(i.additions||0),0),deletions:n.reduce((s,i)=>s+(i.deletions||0),0),changedFiles:n.length,truncated:o.length>f}}function X(t){const e=t.replace(/^\s+|\s+$/g,"");if(!e)return null;const r=e.split(""),o=String(r[0]||"").trim();return o?{hash:o,shortHash:String(r[1]||o.slice(0,8)).trim(),authorName:String(r[2]||"").trim(),authorEmail:String(r[3]||"").trim(),authoredAt:String(r[4]||"").trim(),refs:String(r[5]||"").trim(),subject:String(r[6]||"").trim(),body:r.slice(7).join("").trim()}:null}function Y(t){if(t.length<4)return null;const e=t[0]||" ",r=t[1]||" ",o=_(t.slice(3));return o?{path:o,status:e==="?"&&r==="?"?"untracked":e==="U"||r==="U"?"conflicted":e==="D"||r==="D"?"deleted":e==="A"||r==="A"?"added":e==="R"||r==="R"?"renamed":"modified",indexStatus:e,worktreeStatus:r,staged:e!==" "&&e!=="?",additions:null,deletions:null}:null}function x(t){const e=new Map;for(const r of t.split("\0")){if(!r)continue;const o=D(r);if(!o||!o.path)continue;const n=_(o.path);n&&e.set(n,{additions:o.additions,deletions:o.deletions})}return e}function $(t,e){const r=R(t,e),n=N(t,["diff","--no-ext-diff","--no-index","--numstat","-z","--",process.platform==="win32"?"NUL":"/dev/null",r],32*1024).split("\0",1)[0]||"",s=D(n);return s?{additions:s.additions,deletions:s.deletions}:{additions:null,deletions:null}}function D(t){const e=t.indexOf(" "),r=e<0?-1:t.indexOf(" ",e+1);if(e<0||r<0)return null;const o=t.slice(0,e),n=t.slice(e+1,r);return{additions:/^\d+$/.test(o)?Number(o):null,deletions:/^\d+$/.test(n)?Number(n):null,path:t.slice(r+1)}}function b(t){try{return d(t,["rev-parse","--is-inside-work-tree"],8*1024).trim()==="true"}catch(e){if(String(e.code||"")==="ENOENT")throw new Error("设备未安装 Git。");return!1}}function Q(t,e){try{return d(t,["ls-files","--error-unmatch","--",e],8*1024),!0}catch{return!1}}function Z(t){try{return d(t,["rev-parse","--verify","HEAD"],8*1024),!0}catch{return!1}}function q(t){try{return d(t,["symbolic-ref","--quiet","--short","HEAD"],8*1024).trim()||null}catch{try{return`HEAD (${d(t,["rev-parse","--short","HEAD"],8*1024).trim()})`}catch{return null}}}function tt(t){try{const e=d(t,["rev-list","--left-right","--count","HEAD...@{upstream}"],8192).trim().split(/\s+/).map(Number);return{ahead:Number.isFinite(e[0])?e[0]:0,behind:Number.isFinite(e[1])?e[1]:0}}catch{return{ahead:0,behind:0}}}function R(t,e){const r=c.resolve(t,...e.split("/")),o=c.relative(t,r);if(o.startsWith("..")||c.isAbsolute(o))throw new Error("Diff 路径超出项目范围。");return r}function d(t,e,r){return E("git",["-C",t,...e],{encoding:"utf8",timeout:2e4,maxBuffer:r,stdio:["ignore","pipe","pipe"]})}function N(t,e,r){try{return d(t,e,r)}catch(o){const n=String(o.stdout||"");if(n)return n;if(Number(o.status)===1)return"";throw o}}function T(t){return t.length<=f?t:`${t.slice(0,f)}
|
|
2
|
+
|
|
3
|
+
[Diff 内容过大,已截断]`}function et(){const t=process.platform,e=P(t);return{platform:t,roots:e}}function rt(t){if(!t.directoryPath.trim())throw new Error("目录路径不能为空。");return process.platform==="win32"?st(t.directoryPath,!!t.includeHidden):it(t.directoryPath,!!t.includeHidden)}function m(t,e=process.platform){const r=e==="win32"?c.win32:c.posix,o=r.normalize(t),n=r.parse(o).root,s=o.length>n.length?o.replace(/[\\/]+$/,""):o;return e==="win32"?s.toLocaleLowerCase("en-US"):s}function ot(){const t=u.realpathSync(j.homedir()),e=[{id:"home",label:"用户目录",path:t,kind:"home",available:!0}];return t!==c.parse(t).root&&e.push({id:"root",label:"文件系统",path:"/",kind:"root",available:!0}),e}function P(t){if(y?.platform===t&&y.expiresAtMs>Date.now())return y.roots;const e=t==="win32"?nt():ot();return y={platform:t,roots:e,expiresAtMs:Date.now()+W},e}function nt(){const t=u.realpathSync.native(j.homedir()),e=new Map;e.set(m(t,"win32"),{id:"home",label:"用户目录",path:t,kind:"home",available:!0});try{const r=["$items = Get-CimInstance Win32_LogicalDisk | ForEach-Object {"," [PSCustomObject]@{ Name = $_.DeviceID; Root = ($_.DeviceID + '\\\\'); DriveType = $_.DriveType; VolumeName = $_.VolumeName }","}","@($items) | ConvertTo-Json -Compress"].join(`
|
|
4
|
+
`),o=F(k(r));for(const n of o){const s=String(n.Root||"");if(!s)continue;const i=Number(n.DriveType||0),a=String(n.Name||s.replace(/[\\/]+$/,"")),l=String(n.VolumeName||"").trim();e.set(m(s,"win32"),{id:`drive-${a.replace(/[^a-z0-9]+/gi,"").toLowerCase()}`,label:l?`${l} (${a})`:ht(a,i),path:s,kind:pt(i),available:!0})}}catch{const r=c.win32.parse(t).root;e.set(m(r,"win32"),{id:"drive-system",label:`系统盘 (${r.replace(/\\$/,"")})`,path:r,kind:"fixed",available:!0})}return[...e.values()]}function it(t,e){const r=v(t),n=u.readdirSync(r,{withFileTypes:!0}).filter(i=>i.isDirectory()&&!i.isSymbolicLink()&&(e||!i.name.startsWith("."))),s=n.slice(0,g).map(i=>({name:i.name,path:c.join(r,i.name),kind:"directory",hidden:i.name.startsWith("."),hasChildren:!0}));return s.sort((i,a)=>i.name.localeCompare(a.name,void 0,{numeric:!0,sensitivity:"base"})),C(r,s,n.length>g,"linux")}function st(t,e){const r=v(t),o=["$items = Get-ChildItem -LiteralPath $env:ACA_MACHINE_FS_PATH -Directory -Force -ErrorAction Stop | ForEach-Object {"," [PSCustomObject]@{ Name = $_.Name; FullName = $_.FullName; Attributes = $_.Attributes.ToString() }","}","@($items) | ConvertTo-Json -Compress"].join(`
|
|
5
|
+
`),n=F(k(o,{ACA_MACHINE_FS_PATH:r})),s=n.map(i=>{const a=String(i.Attributes||"");return{name:String(i.Name||""),path:String(i.FullName||""),kind:"directory",hidden:/Hidden|System/i.test(a),hasChildren:!0,reparsePoint:/ReparsePoint/i.test(a)}}).filter(i=>i.name&&i.path&&!i.reparsePoint&&(e||!i.hidden)).slice(0,g).sort((i,a)=>i.name.localeCompare(a.name,void 0,{numeric:!0,sensitivity:"base"}));return C(r,s,n.length>g,"win32")}function C(t,e,r,o){const n=o==="win32"?c.win32:c.posix,s=n.parse(t).root,i=m(t,o)===m(s,o)?null:n.dirname(t);return{platform:o,path:t,parentPath:i,breadcrumbs:at(t,o),readable:I(t,u.constants.R_OK),writable:I(t,u.constants.W_OK),items:e,truncated:r}}function at(t,e){const r=e==="win32"?c.win32:c.posix,o=r.parse(t),n=t.slice(o.root.length).split(/[\\/]+/).filter(Boolean),s=[{label:o.root.replace(/[\\/]+$/,"")||o.root,path:o.root}];let i=o.root;for(const a of n)i=r.join(i,a),s.push({label:a,path:i});return s}async function ct(t){const e=String(t.workspaceId||"").trim(),r=String(t.name||"").trim(),o=t.projectType==="chat_room"?"chat_room":"project";if(!e||!r)throw new Error("项目名称和工作区不能为空。");const n=v(String(t.path||""));u.accessSync(n,u.constants.R_OK|u.constants.W_OK);const i=(await h("GET",`/api/projects?workspaceId=${encodeURIComponent(e)}`)).items.find(l=>m(l.root_path)===m(n)),a=i||(await h("POST","/api/projects",{projectId:M(),workspaceId:e,name:r,rootPath:n,source:"aica",projectType:o})).item;return L(lt(a)),{project:a,duplicate:!!i}}function lt(t){return{projectId:t.project_id,workspaceId:t.workspace_id,name:t.name,rootPath:t.root_path}}function v(t){if(!t.trim()||!c.isAbsolute(t))throw new Error("必须选择绝对目录路径。");if(ft(t),!u.statSync(t).isDirectory())throw new Error("选择的路径不是目录。");const r=u.realpathSync.native(t);return mt(r),r}function w(t){if(!t.trim()||!c.isAbsolute(t))throw new Error("项目根目录无效。");const e=u.realpathSync.native(t);if(!u.statSync(e).isDirectory())throw new Error("项目根目录不存在。");return e}function _(t){const e=t.replace(/\\/g,"/").replace(/^\/+|\/+$/g,"");if(!e)return"";if(e.includes("\0")||e.split("/").some(r=>!r||r==="."||r===".."))throw new Error("项目相对路径无效。");return e}function ut(t,e,r){const o=e?c.join(t,...e.split("/")):t,n=u.realpathSync.native(o),s=c.relative(t,n);if(s.startsWith("..")||c.isAbsolute(s))throw new Error("目录超出项目范围。");const i=u.statSync(n);if(r&&!i.isDirectory())throw new Error("请求路径不是目录。");return n}function dt(t,e){return c.relative(t,e).split(c.sep).join("/")}function ft(t){const e=process.platform==="win32"?c.win32:c.posix;if(!P(process.platform).some(o=>{const n=String(o.path||"");if(!n)return!1;const s=e.relative(n,t);return s===""||!s.startsWith("..")&&!e.isAbsolute(s)}))throw new Error("目录不在允许浏览的位置内。")}function mt(t){const e=process.platform==="win32"?c.win32:c.posix;if(!P(process.platform).some(o=>{const n=String(o.path||"");if(!n)return!1;const s=e.relative(n,t);return s===""||!s.startsWith("..")&&!e.isAbsolute(s)}))throw new Error("目录不在允许浏览的位置内。")}function I(t,e){try{return u.accessSync(t,e),!0}catch{return!1}}function k(t,e={}){return E("powershell.exe",["-NoLogo","-NoProfile","-NonInteractive","-Command",t],{encoding:"utf8",windowsHide:!0,timeout:8e3,maxBuffer:4*1024*1024,env:{...process.env,...e}}).replace(/^\uFEFF/,"").trim()}function F(t){if(!t)return[];const e=JSON.parse(t);return Array.isArray(e)?e.filter(r=>!!(r&&typeof r=="object")):e&&typeof e=="object"?[e]:[]}function pt(t){return t===2?"removable":t===3?"fixed":t===4?"network":t===5?"optical":"drive"}function ht(t,e){return e===2?`移动磁盘 (${t})`:e===4?`网络驱动器 (${t})`:e===5?`光驱 (${t})`:`本地磁盘 (${t})`}export{m as comparableMachinePath,V as getProjectGitCommit,K as getProjectGitDiff,J as getProjectGitLog,z as getProjectGitStatus,rt as listMachineDirectory,et as listMachineFilesystemRoots,U as listProjectDirectory,vt as startMachineFilesystemWorkerLoop};
|
package/dist/worker-cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as a}from"commander";import
|
|
2
|
+
import{Command as a}from"commander";import m from"node:path";import{createStartCommand as n}from"./commands/start.js";import{createWorkerAuthCommand as t}from"./commands/worker-auth.js";import{createWorkerCodexCommand as s}from"./commands/worker-codex.js";import{createWorkerProjectCommand as c}from"./commands/worker-project.js";import{DEFAULT_ACA_SERVER_URL as i}from"./core/aca-config.js";process.env.ACA_DEFAULT_SERVER_URL||=i;async function d(r=process.argv){const o=new a;o.name("aica").description("AICA remote Agent worker").version("0.1.7").enablePositionalOptions(),o.addCommand(n()),o.addCommand(t()),o.addCommand(c()),o.addCommand(s()),await o.parseAsync(r)}const p=process.argv[1]||"",e=m.basename(p).replace(/\.(?:js|ts|cjs|mjs)$/i,"");(e==="worker-cli"||e==="aica"||e==="aca")&&d().catch(r=>{const o=r instanceof Error?r.message:String(r);console.error(o),process.exitCode=1});export{d as runWorkerCli};
|