@yuandc/aica 0.1.18 → 0.1.19

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.
@@ -0,0 +1 @@
1
+ const o="所选模型当前繁忙,请稍后重试。";function c(r){return/ACP request timed out/i.test(r)?"ACP 长时间没有完成,请稍后重试,或点击停止后重新发送。":/MimoCode request timed out/i.test(r)?"MimoCode 长时间没有完成,请稍后重试,或点击停止后重新发送。":s(r)?o:r.replace(/\bsession\/prompt\b/g,"ACP 请求")}function s(r){const t=String(r||"").trim();if(!t)return!1;if(/selected model is at capacity/i.test(t)||/"codexErrorInfo"\s*:\s*"serverOverloaded"/i.test(t))return!0;const e=u(t);return String(e?.codexErrorInfo||"")==="serverOverloaded"||/selected model is at capacity/i.test(String(e?.message||""))}function u(r){const t="Codex turn failed:",e=r.indexOf(t);if(e<0)return null;const n=r.slice(e+t.length).trim();if(!n.startsWith("{"))return null;try{const i=JSON.parse(n);return i&&typeof i=="object"&&!Array.isArray(i)?i:null}catch{return null}}export{s as isCodexCapacityFailure,c as userFacingAcpError};
@@ -1,6 +1,6 @@
1
- import L from"node:crypto";import E from"node:fs";import x from"node:path";import{compactAgentContext as W,forkAgentSession as V,sendAgentPrompt as q}from"../acp/agent.js";import{acaServerDownload as D,acaServerRequest as y}from"./aca-server-client.js";import{loadAcaConfig as H}from"./aca-config.js";import{prepareLocalWorktree as G}from"./worktree.js";import{expandWorkerRuntimePath as K}from"./worker-runtime-paths.js";import{collectAffectedFiles as M,extractAffectedFilePathsFromAcpRaw as X}from"./affected-files.js";import{resolveJobPermissionPolicy as Z}from"./job-permission-policy.js";import{appendCoalescedAcpEvent as Q}from"./acp-event-coalescer.js";import{shouldUploadAcpEvent as Y}from"./acp-event-upload-filter.js";const ee=1500,te=5e3,N=1e3,ne=200,oe=64,O=900,ae=1e4,ie=0,re=12e3;function se(e){return K(e)}function ce(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("~/.aica/chats/")||e.project_root_path.startsWith("~/.aca/chats/")||/(^|\/)\.aica\/chats\//.test(e.project_root_path)||/(^|\/)\.aca\/chats\//.test(e.project_root_path))}function He(e,t={}){let n=!1,a=null,o=null;const r=new Set,l=new Set,u=new Map,i=async()=>{if(n)return;const s=le();if(U(r.size,s))try{const p=t.loadConfig?.()??H();if(!p.token)return;for(;!n&&U(r.size,s);){const A=t.claimNextJob?await t.claimNextJob(p):await y("POST","/api/client/jobs/claim",{machineId:p.machineId,workspaceId:p.defaultWorkspaceId});if(!A.item)break;const f=A.item;if(n){await(t.cancelClaimedJob?t.cancelClaimedJob(f,p):k(f.job_id,p.machineId,"cancelled")).catch(()=>{});break}const m=f.session_id;l.has(m)&&e.warn(`claimed job=${f.job_id} for already active session=${m}; running anyway to avoid leaving it stuck`),r.add(f.job_id),l.add(m);const _=new AbortController,P=(t.runJob??pe)(f,p,e,_).catch(d=>{e.warn(`job ${f.job_id} failed outside handler: ${d instanceof Error?d.message:String(d)}`)}).finally(()=>{r.delete(f.job_id),l.delete(m),u.delete(f.job_id)});u.set(f.job_id,{controller:_,promise:P})}}catch(p){n||e.warn(`job worker failed: ${p instanceof Error?p.message:String(p)}`)}},h=()=>{if(n||a)return;const s=i();a=s,s.finally(()=>{a===s&&(a=null)})};h();const S=setInterval(()=>{h()},t.claimIntervalMs??ee);return{timer:S,stop:()=>o||(o=(async()=>{if(n)return;n=!0,clearInterval(S);for(const p of u.values())p.controller.abort();await a?.catch(()=>{});for(const p of u.values())p.controller.abort();const s=[...u.values()].map(p=>p.promise);s.length!==0&&await Promise.race([Promise.allSettled(s).then(()=>{}),j(re)])})(),o)}}function le(){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 ue(){const e=Number.parseInt(process.env.ACA_ACP_EVENT_BATCH_INTERVAL_MS||"",10);return Number.isFinite(e)?Math.max(40,Math.min(e,2e3)):ne}async function pe(e,t,n,a){const o=e.job_id,r=e.session_id,l=e.workspace_id,u=e.project_id??null,i=e.input??{},h=String(i.control?.type||"").toLowerCase();if(!h&&!i.message?.trim()&&(i.attachments??[]).length===0){await k(o,t.machineId,"job input missing message");return}const S=t.projects.find(d=>d.projectId===u),s=se(S?.rootPath||e.project_root_path||"");if(!s){await k(o,t.machineId,"job project root is unknown");return}ce(e)&&E.mkdirSync(s,{recursive:!0}),n.info(`claimed job=${o} session=${r} project=${S?.name??u??"unknown"}`);const p=setInterval(()=>{y("POST",`/api/client/jobs/${encodeURIComponent(o)}/heartbeat`,{machineId:t.machineId}).catch(()=>{}),je(o,a).catch(()=>{})},te);let A=0;const f=ye(o,t.machineId),m=_e(o,t.machineId),_=new Set;let P=null;try{await m.sendNow({phase:"initializing",label:"准备工作区",detail:e.worktree_id?"worktree":"project root"}).catch(()=>{});const d=G({projectId:u,sessionId:r,projectRoot:s,worktree:e});P=d,await Re(o,t.machineId,d);const I=fe(i.acpRun);if(h==="compact"){if(!e.acp_session_id)throw new Error("Current session does not have an ACP context to compact");const c=await W({agentType:C(I.agentType,"codex"),cliType:C(I.cliType,"builtin"),acpSessionId:e.acp_session_id,cwd:d.cwd,model:i.model,mode:i.mode,configOptionValues:i.configOptionValues,timeoutMs:i.timeoutMs,allowRollover:i.control?.allowRollover===!0,signal:a.signal,onStatus:b=>{m.report({phase:b.phase,label:b.label,detail:b.detail,updateType:b.updateType,raw:b})}});await m.flush(),await y("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:c.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"compact",allowRollover:i.control?.allowRollover===!0},acpSessionId:c.acpSessionId,durationMs:c.durationMs,usage:c.contextUsage,maintenance:c.maintenance,worktree:v(d)}}),n.info(`completed context compact job=${o}`);return}if(h==="fork"){const c=String(i.control?.sourceAcpSessionId||"").trim();if(!c)throw new Error("Source session does not have a Codex ACP context to fork");await m.sendNow({phase:"forking",label:"正在分叉 Codex 会话",detail:i.control?.sourceSessionId?`源会话 ${i.control.sourceSessionId}`:void 0}).catch(()=>{});const b=await V({agentType:C(I.agentType,"codex"),cliType:C(I.cliType,"builtin"),sourceProviderSessionId:c,cwd:d.cwd,model:i.model,mode:i.mode,configOptionValues:i.configOptionValues,timeoutMs:i.timeoutMs,signal:a.signal,onStatus:g=>{m.report({phase:g.phase,label:g.label,detail:g.detail,updateType:g.updateType,raw:g})}});await m.flush(),await y("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:b.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"fork",sourceSessionId:i.control?.sourceSessionId||null},acpSessionId:b.acpSessionId,worktree:v(d)}}),n.info(`completed Codex session fork job=${o}`);return}const T=await Ae({cwd:d.cwd,sessionId:r,jobId:o,attachments:i.attachments??[]});T.length>0&&(n.info(`materialized ${T.length} attachment(s) for job=${o}`),await m.sendNow({phase:"initializing",label:"附件已写入本机",detail:T.map(c=>c.relativePath).join(", "),raw:{attachments:z(T)}}).catch(()=>{}));const $=Se(i,T),F=ge($,T),w=await q({agentType:C(I.agentType,"codex"),cliType:C(I.cliType,"builtin"),acpSessionId:e.acp_session_id??null,requireSessionResume:de(e.session_raw),prompt:$,promptBlocks:F,cwd:d.cwd,model:i.model,mode:i.mode,configOptionValues:i.configOptionValues,canExecuteTools:i.canExecuteTools,timeoutMs:i.timeoutMs,contextWindow:he(I.contextWindow),signal:a.signal,onStatus:c=>{m.report({phase:c.phase,label:c.label,detail:c.detail,updateType:c.updateType,raw:c})},onUpdate:c=>{A+=1;for(const g of X(c.raw))_.add(g);const b={turnId:e.user_turn_id??null,eventType:c.type,label:c.label,text:c.text,status:c.status,toolCallId:c.toolCallId,raw:Te(c.raw,A)};Y(b)&&f.push(b)},onPermissionRequest:c=>{const b=Z(i,c);return b?Promise.resolve(b):xe(o,t.machineId,c,a.signal)},onUserInputRequest:c=>Ee(o,t.machineId,c,a.signal)});await f.flush(),await m.flush();const J=M({cwd:d.cwd,evidencePaths:_}),R=we(w.promptResponse);if(!(be(R)||!!w.content)){await k(o,t.machineId,`${w.agentType} stopped: ${R??"unknown"}`,{acpSessionId:w.acpSessionId,stopReason:R,exitCode:w.exitCode,stderr:$e(w.stderr,4e3),worktree:v(d)});return}await y("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:w.acpSessionId,assistantText:w.content,result:{ok:!0,acpSessionId:w.acpSessionId,stopReason:R,durationMs:w.durationMs,acpRun:i.acpRun??null,effectiveConfig:w.effectiveConfig??null,performance:w.performance??null,usage:w.contextUsage??null,updateCount:w.updates.length,statusTimeline:w.statusTimeline,worktree:v(d),attachments:z(T),files:J}}),n.info(`completed job=${o}`)}catch(d){await f.flush(),await m.flush();const I=a.signal.aborted?"cancelled":d instanceof Error?d.message:String(d),T=P?M({cwd:P.cwd,evidencePaths:_}):[];await k(o,t.machineId,me(I),{rawError:I,files:T})}finally{await f.flush(),await m.flush(),clearInterval(p)}}function de(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 me(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 fe(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function he(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function C(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function we(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 be(e){return e?["end_turn","stop","completed","complete"].includes(e):!1}function ye(e,t){let n=[],a=null,o=Promise.resolve();const r=async i=>{i.length!==0&&await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/events/batch`,{machineId:t,events:i})},l=()=>{a&&(clearTimeout(a),a=null);const i=n;return n=[],o=o.then(()=>r(i)).catch(()=>{}),o},u=()=>{a||(a=setTimeout(()=>{l()},ue()),a.unref())};return{push(i){if(Q(n,i),Ie(i)||n.length>=oe){l();return}u()},flush:l}}function Ie(e){return e.eventType==="tool_call"?!0:e.eventType!=="tool_call_update"?!1:["completed","failed","cancelled"].includes(String(e.status||"").toLowerCase())}function _e(e,t){let n=null,a=0,o="",r=null,l=Promise.resolve();const u=s=>JSON.stringify({phase:s.phase??"",label:s.label??"",detail:s.detail??"",updateType:s.updateType??""}),i=async s=>{await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/presence`,{machineId:t,phase:s.phase,label:s.label,detail:s.detail,updateType:s.updateType,raw:s.raw}),a=Date.now(),o=u(s)},h=()=>{if(r&&(clearTimeout(r),r=null),!n)return l;const s=n;return n=null,l=l.then(()=>i(s)).catch(()=>{}),l},S=s=>{r||(r=setTimeout(()=>{h()},s),r.unref())};return{report(s){const p=Date.now(),f=u(s)!==o,m=p-a>=ae;if(!f&&!m)return;n=s;const _=p-a;if(_>=O||a===0){h();return}S(O-_)},sendNow(s){return n=s,h()},flush:h}}function Te(e,t){return e&&typeof e=="object"&&!Array.isArray(e)?{...e,acaSequence:t}:{value:e,acaSequence:t}}function Se(e,t=[]){const n=e?.message?.trim()??"";if(t.length===0)return n;const o=["用户随消息上传了以下附件,aca 已将附件写入本机工作区。需要读取附件时请直接使用下面的 localPath;图片附件也已作为 ACP image block 随本轮请求传入。",...t.map((r,l)=>`${l+1}. ${r.name} (${r.kind}, ${r.mimeType}, ${ke(r.size)})
1
+ import L from"node:crypto";import E from"node:fs";import x from"node:path";import{compactAgentContext as W,forkAgentSession as V,sendAgentPrompt as q}from"../acp/agent.js";import{acaServerDownload as D,acaServerRequest as y}from"./aca-server-client.js";import{loadAcaConfig as H}from"./aca-config.js";import{prepareLocalWorktree as G}from"./worktree.js";import{expandWorkerRuntimePath as K}from"./worker-runtime-paths.js";import{collectAffectedFiles as N,extractAffectedFilePathsFromAcpRaw as X}from"./affected-files.js";import{resolveJobPermissionPolicy as Z}from"./job-permission-policy.js";import{appendCoalescedAcpEvent as Q}from"./acp-event-coalescer.js";import{shouldUploadAcpEvent as Y}from"./acp-event-upload-filter.js";import{userFacingAcpError as ee}from"../acp/error-display.js";const te=1500,ne=5e3,M=1e3,oe=200,ae=64,O=900,ie=1e4,re=0,se=12e3;function ce(e){return K(e)}function le(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("~/.aica/chats/")||e.project_root_path.startsWith("~/.aca/chats/")||/(^|\/)\.aica\/chats\//.test(e.project_root_path)||/(^|\/)\.aca\/chats\//.test(e.project_root_path))}function Ge(e,t={}){let n=!1,a=null,o=null;const r=new Set,l=new Set,u=new Map,i=async()=>{if(n)return;const s=ue();if(U(r.size,s))try{const p=t.loadConfig?.()??H();if(!p.token)return;for(;!n&&U(r.size,s);){const A=t.claimNextJob?await t.claimNextJob(p):await y("POST","/api/client/jobs/claim",{machineId:p.machineId,workspaceId:p.defaultWorkspaceId});if(!A.item)break;const f=A.item;if(n){await(t.cancelClaimedJob?t.cancelClaimedJob(f,p):P(f.job_id,p.machineId,"cancelled")).catch(()=>{});break}const m=f.session_id;l.has(m)&&e.warn(`claimed job=${f.job_id} for already active session=${m}; running anyway to avoid leaving it stuck`),r.add(f.job_id),l.add(m);const _=new AbortController,C=(t.runJob??de)(f,p,e,_).catch(d=>{e.warn(`job ${f.job_id} failed outside handler: ${d instanceof Error?d.message:String(d)}`)}).finally(()=>{r.delete(f.job_id),l.delete(m),u.delete(f.job_id)});u.set(f.job_id,{controller:_,promise:C})}}catch(p){n||e.warn(`job worker failed: ${p instanceof Error?p.message:String(p)}`)}},h=()=>{if(n||a)return;const s=i();a=s,s.finally(()=>{a===s&&(a=null)})};h();const g=setInterval(()=>{h()},t.claimIntervalMs??te);return{timer:g,stop:()=>o||(o=(async()=>{if(n)return;n=!0,clearInterval(g);for(const p of u.values())p.controller.abort();await a?.catch(()=>{});for(const p of u.values())p.controller.abort();const s=[...u.values()].map(p=>p.promise);s.length!==0&&await Promise.race([Promise.allSettled(s).then(()=>{}),j(se)])})(),o)}}function ue(){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?re:t===0?0:Math.max(1,Math.min(t,8))}function U(e,t){return t===0||e<t}function pe(){const e=Number.parseInt(process.env.ACA_ACP_EVENT_BATCH_INTERVAL_MS||"",10);return Number.isFinite(e)?Math.max(40,Math.min(e,2e3)):oe}async function de(e,t,n,a){const o=e.job_id,r=e.session_id,l=e.workspace_id,u=e.project_id??null,i=e.input??{},h=String(i.control?.type||"").toLowerCase();if(!h&&!i.message?.trim()&&(i.attachments??[]).length===0){await P(o,t.machineId,"job input missing message");return}const g=t.projects.find(d=>d.projectId===u),s=ce(g?.rootPath||e.project_root_path||"");if(!s){await P(o,t.machineId,"job project root is unknown");return}le(e)&&E.mkdirSync(s,{recursive:!0}),n.info(`claimed job=${o} session=${r} project=${g?.name??u??"unknown"}`);const p=setInterval(()=>{y("POST",`/api/client/jobs/${encodeURIComponent(o)}/heartbeat`,{machineId:t.machineId}).catch(()=>{}),je(o,a).catch(()=>{})},ne);let A=0;const f=ye(o,t.machineId),m=_e(o,t.machineId),_=new Set;let C=null;try{await m.sendNow({phase:"initializing",label:"准备工作区",detail:e.worktree_id?"worktree":"project root"}).catch(()=>{});const d=G({projectId:u,sessionId:r,projectRoot:s,worktree:e});C=d,await Re(o,t.machineId,d);const I=fe(i.acpRun);if(h==="compact"){if(!e.acp_session_id)throw new Error("Current session does not have an ACP context to compact");const c=await W({agentType:v(I.agentType,"codex"),cliType:v(I.cliType,"builtin"),acpSessionId:e.acp_session_id,cwd:d.cwd,model:i.model,mode:i.mode,configOptionValues:i.configOptionValues,timeoutMs:i.timeoutMs,allowRollover:i.control?.allowRollover===!0,signal:a.signal,onStatus:b=>{m.report({phase:b.phase,label:b.label,detail:b.detail,updateType:b.updateType,raw:b})}});await m.flush(),await y("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:c.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"compact",allowRollover:i.control?.allowRollover===!0},acpSessionId:c.acpSessionId,durationMs:c.durationMs,usage:c.contextUsage,maintenance:c.maintenance,worktree:k(d)}}),n.info(`completed context compact job=${o}`);return}if(h==="fork"){const c=String(i.control?.sourceAcpSessionId||"").trim();if(!c)throw new Error("Source session does not have a Codex ACP context to fork");await m.sendNow({phase:"forking",label:"正在分叉 Codex 会话",detail:i.control?.sourceSessionId?`源会话 ${i.control.sourceSessionId}`:void 0}).catch(()=>{});const b=await V({agentType:v(I.agentType,"codex"),cliType:v(I.cliType,"builtin"),sourceProviderSessionId:c,cwd:d.cwd,model:i.model,mode:i.mode,configOptionValues:i.configOptionValues,timeoutMs:i.timeoutMs,signal:a.signal,onStatus:S=>{m.report({phase:S.phase,label:S.label,detail:S.detail,updateType:S.updateType,raw:S})}});await m.flush(),await y("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:b.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"fork",sourceSessionId:i.control?.sourceSessionId||null},acpSessionId:b.acpSessionId,worktree:k(d)}}),n.info(`completed Codex session fork job=${o}`);return}const T=await Ae({cwd:d.cwd,sessionId:r,jobId:o,attachments:i.attachments??[]});T.length>0&&(n.info(`materialized ${T.length} attachment(s) for job=${o}`),await m.sendNow({phase:"initializing",label:"附件已写入本机",detail:T.map(c=>c.relativePath).join(", "),raw:{attachments:z(T)}}).catch(()=>{}));const $=ge(i,T),F=Se($,T),w=await q({agentType:v(I.agentType,"codex"),cliType:v(I.cliType,"builtin"),acpSessionId:e.acp_session_id??null,requireSessionResume:me(e.session_raw),prompt:$,promptBlocks:F,cwd:d.cwd,model:i.model,mode:i.mode,configOptionValues:i.configOptionValues,canExecuteTools:i.canExecuteTools,timeoutMs:i.timeoutMs,contextWindow:he(I.contextWindow),signal:a.signal,onStatus:c=>{m.report({phase:c.phase,label:c.label,detail:c.detail,updateType:c.updateType,raw:c})},onUpdate:c=>{A+=1;for(const S of X(c.raw))_.add(S);const b={turnId:e.user_turn_id??null,eventType:c.type,label:c.label,text:c.text,status:c.status,toolCallId:c.toolCallId,raw:Te(c.raw,A)};Y(b)&&f.push(b)},onPermissionRequest:c=>{const b=Z(i,c);return b?Promise.resolve(b):xe(o,t.machineId,c,a.signal)},onUserInputRequest:c=>Ee(o,t.machineId,c,a.signal)});await f.flush(),await m.flush();const J=N({cwd:d.cwd,evidencePaths:_}),R=we(w.promptResponse);if(!(be(R)||!!w.content)){await P(o,t.machineId,`${w.agentType} stopped: ${R??"unknown"}`,{acpSessionId:w.acpSessionId,stopReason:R,exitCode:w.exitCode,stderr:$e(w.stderr,4e3),worktree:k(d)});return}await y("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:w.acpSessionId,assistantText:w.content,result:{ok:!0,acpSessionId:w.acpSessionId,stopReason:R,durationMs:w.durationMs,acpRun:i.acpRun??null,effectiveConfig:w.effectiveConfig??null,performance:w.performance??null,usage:w.contextUsage??null,updateCount:w.updates.length,statusTimeline:w.statusTimeline,worktree:k(d),attachments:z(T),files:J}}),n.info(`completed job=${o}`)}catch(d){await f.flush(),await m.flush();const I=a.signal.aborted?"cancelled":d instanceof Error?d.message:String(d),T=C?N({cwd:C.cwd,evidencePaths:_}):[];await P(o,t.machineId,ee(I),{rawError:I,files:T})}finally{await f.flush(),await m.flush(),clearInterval(p)}}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 fe(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function he(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function v(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function we(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 be(e){return e?["end_turn","stop","completed","complete"].includes(e):!1}function ye(e,t){let n=[],a=null,o=Promise.resolve();const r=async i=>{i.length!==0&&await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/events/batch`,{machineId:t,events:i})},l=()=>{a&&(clearTimeout(a),a=null);const i=n;return n=[],o=o.then(()=>r(i)).catch(()=>{}),o},u=()=>{a||(a=setTimeout(()=>{l()},pe()),a.unref())};return{push(i){if(Q(n,i),Ie(i)||n.length>=ae){l();return}u()},flush:l}}function Ie(e){return e.eventType==="tool_call"?!0:e.eventType!=="tool_call_update"?!1:["completed","failed","cancelled"].includes(String(e.status||"").toLowerCase())}function _e(e,t){let n=null,a=0,o="",r=null,l=Promise.resolve();const u=s=>JSON.stringify({phase:s.phase??"",label:s.label??"",detail:s.detail??"",updateType:s.updateType??""}),i=async s=>{await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/presence`,{machineId:t,phase:s.phase,label:s.label,detail:s.detail,updateType:s.updateType,raw:s.raw}),a=Date.now(),o=u(s)},h=()=>{if(r&&(clearTimeout(r),r=null),!n)return l;const s=n;return n=null,l=l.then(()=>i(s)).catch(()=>{}),l},g=s=>{r||(r=setTimeout(()=>{h()},s),r.unref())};return{report(s){const p=Date.now(),f=u(s)!==o,m=p-a>=ie;if(!f&&!m)return;n=s;const _=p-a;if(_>=O||a===0){h();return}g(O-_)},sendNow(s){return n=s,h()},flush:h}}function Te(e,t){return e&&typeof e=="object"&&!Array.isArray(e)?{...e,acaSequence:t}:{value:e,acaSequence:t}}function ge(e,t=[]){const n=e?.message?.trim()??"";if(t.length===0)return n;const o=["用户随消息上传了以下附件,aca 已将附件写入本机工作区。需要读取附件时请直接使用下面的 localPath;图片附件也已作为 ACP image block 随本轮请求传入。",...t.map((r,l)=>`${l+1}. ${r.name} (${r.kind}, ${r.mimeType}, ${Pe(r.size)})
2
2
  localPath: ${r.path}
3
3
  workspacePath: ${r.relativePath}`)].join(`
4
4
  `);return n?`${n}
5
5
 
6
- ${o}`:o}function ge(e,t){const n=[{type:"text",text:e}];for(const a of t)a.kind!=="image"||!a.mimeType.startsWith("image/")||n.push({type:"image",data:a.base64,mimeType:a.mimeType,uri:a.path});return n}async function Ae(e){if(e.attachments.length===0)return[];const t=x.join(e.cwd,".aca","attachments",B(e.sessionId),B(e.jobId));E.mkdirSync(t,{recursive:!0});const n=[];for(const[a,o]of e.attachments.entries()){const r=o.attachmentId?{mimeType:o.mimeType||"application/octet-stream",bytes:await D(`/api/client/attachments/${encodeURIComponent(o.attachmentId)}`)}:Ce(o.dataUrl??""),l=o.mimeType||r.mimeType||"application/octet-stream",u=o.kind==="image"||l.startsWith("image/")?"image":"file",i=Pe(o.name||`attachment-${a+1}`,l),h=x.join(t,`${String(a+1).padStart(2,"0")}-${i}`);E.writeFileSync(h,r.bytes),n.push({name:o.name||i,mimeType:l,size:r.bytes.byteLength,kind:u,path:h,relativePath:x.relative(e.cwd,h),base64:r.bytes.toString("base64"),sha256:L.createHash("sha256").update(r.bytes).digest("hex")})}return n}function Ce(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),a=e.slice(t+1),o=n.split(";").filter(Boolean),r=o[0]?.includes("/")?o[0]:"application/octet-stream";if(!o.includes("base64"))throw new Error("attachment dataUrl is not base64 encoded");return{mimeType:r,bytes:Buffer.from(a,"base64")}}function Pe(e,t){const n=x.basename(e).replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").trim(),a=`attachment${ve(t)}`;return(!n||n==="."||n===".."?a:n).slice(0,180)}function ve(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 ke(e){if(!Number.isFinite(e)||e<=0)return"0 B";const t=["B","KB","MB","GB"];let n=e,a=0;for(;n>=1024&&a<t.length-1;)n/=1024,a+=1;return`${n>=10||a===0?n.toFixed(0):n.toFixed(1)} ${t[a]}`}async function Re(e,t,n){!n.usedWorktree||!n.worktreeId||await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/worktree`,{machineId:t,baseCommit:n.baseCommit??null,worktreePath:n.cwd,status:n.status??"active",raw:n.raw??v(n)})}function v(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 xe(e,t,n,a){const r=(await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:n})).item.permission_id;for(;!a.aborted;){await j(N);const l=await y("GET",`/api/client/permissions/${encodeURIComponent(r)}`);if(l.item.status==="resolved"&&l.item.response){const u=l.item.response.outcome;return u.outcome==="selected"?{outcome:u}:{outcome:{outcome:"cancelled"}}}}return{outcome:{outcome:"cancelled"}}}async function Ee(e,t,n,a){const r=(await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:{kind:"elicitation",...n}})).item.permission_id;for(;!a.aborted;){await j(N);const l=await y("GET",`/api/client/permissions/${encodeURIComponent(r)}`);if(l.item.status==="resolved"&&l.item.response){const u=l.item.response.outcome;return u.outcome==="submitted"?{outcome:u}:{outcome:{outcome:"cancelled"}}}}return{outcome:{outcome:"cancelled"}}}async function je(e,t){if(t.signal.aborted)return;const n=await y("GET",`/api/client/jobs/${encodeURIComponent(e)}`);Number(n.item.cancel_requested??0)===1&&t.abort()}async function k(e,t,n,a){await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/fail`,{machineId:t,error:n,result:a})}function j(e){return new Promise(t=>setTimeout(t,e))}function $e(e,t){return e.length<=t?e:`${e.slice(0,t)}...`}export{He as startJobWorkerLoop};
6
+ ${o}`:o}function Se(e,t){const n=[{type:"text",text:e}];for(const a of t)a.kind!=="image"||!a.mimeType.startsWith("image/")||n.push({type:"image",data:a.base64,mimeType:a.mimeType,uri:a.path});return n}async function Ae(e){if(e.attachments.length===0)return[];const t=x.join(e.cwd,".aca","attachments",B(e.sessionId),B(e.jobId));E.mkdirSync(t,{recursive:!0});const n=[];for(const[a,o]of e.attachments.entries()){const r=o.attachmentId?{mimeType:o.mimeType||"application/octet-stream",bytes:await D(`/api/client/attachments/${encodeURIComponent(o.attachmentId)}`)}:ve(o.dataUrl??""),l=o.mimeType||r.mimeType||"application/octet-stream",u=o.kind==="image"||l.startsWith("image/")?"image":"file",i=Ce(o.name||`attachment-${a+1}`,l),h=x.join(t,`${String(a+1).padStart(2,"0")}-${i}`);E.writeFileSync(h,r.bytes),n.push({name:o.name||i,mimeType:l,size:r.bytes.byteLength,kind:u,path:h,relativePath:x.relative(e.cwd,h),base64:r.bytes.toString("base64"),sha256:L.createHash("sha256").update(r.bytes).digest("hex")})}return n}function ve(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),a=e.slice(t+1),o=n.split(";").filter(Boolean),r=o[0]?.includes("/")?o[0]:"application/octet-stream";if(!o.includes("base64"))throw new Error("attachment dataUrl is not base64 encoded");return{mimeType:r,bytes:Buffer.from(a,"base64")}}function Ce(e,t){const n=x.basename(e).replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").trim(),a=`attachment${ke(t)}`;return(!n||n==="."||n===".."?a:n).slice(0,180)}function ke(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,a=0;for(;n>=1024&&a<t.length-1;)n/=1024,a+=1;return`${n>=10||a===0?n.toFixed(0):n.toFixed(1)} ${t[a]}`}async function Re(e,t,n){!n.usedWorktree||!n.worktreeId||await y("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 xe(e,t,n,a){const r=(await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:n})).item.permission_id;for(;!a.aborted;){await j(M);const l=await y("GET",`/api/client/permissions/${encodeURIComponent(r)}`);if(l.item.status==="resolved"&&l.item.response){const u=l.item.response.outcome;return u.outcome==="selected"?{outcome:u}:{outcome:{outcome:"cancelled"}}}}return{outcome:{outcome:"cancelled"}}}async function Ee(e,t,n,a){const r=(await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:{kind:"elicitation",...n}})).item.permission_id;for(;!a.aborted;){await j(M);const l=await y("GET",`/api/client/permissions/${encodeURIComponent(r)}`);if(l.item.status==="resolved"&&l.item.response){const u=l.item.response.outcome;return u.outcome==="submitted"?{outcome:u}:{outcome:{outcome:"cancelled"}}}}return{outcome:{outcome:"cancelled"}}}async function je(e,t){if(t.signal.aborted)return;const n=await y("GET",`/api/client/jobs/${encodeURIComponent(e)}`);Number(n.item.cancel_requested??0)===1&&t.abort()}async function P(e,t,n,a){await y("POST",`/api/client/jobs/${encodeURIComponent(e)}/fail`,{machineId:t,error:n,result:a})}function j(e){return new Promise(t=>setTimeout(t,e))}function $e(e,t){return e.length<=t?e:`${e.slice(0,t)}...`}export{Ge as startJobWorkerLoop};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{Command as a}from"commander";import m from"node:path";import{createStartCommand as n}from"./commands/start.js";import{createDaemonCommand as t}from"./commands/daemon.js";import{createWorkerAuthCommand as s}from"./commands/worker-auth.js";import{createWorkerCodexCommand as c}from"./commands/worker-codex.js";import{createWorkerProjectCommand as i}from"./commands/worker-project.js";import{DEFAULT_ACA_SERVER_URL as d}from"./core/aca-config.js";process.env.ACA_DEFAULT_SERVER_URL||=d;async function p(r=process.argv){const o=new a;o.name("aica").description("AICA remote Agent worker").version("0.1.18").enablePositionalOptions(),o.addCommand(n()),o.addCommand(t()),o.addCommand(s()),o.addCommand(i()),o.addCommand(c()),await o.parseAsync(r)}const C=process.argv[1]||"",e=m.basename(C).replace(/\.(?:js|ts|cjs|mjs)$/i,"");(e==="worker-cli"||e==="aica"||e==="aca")&&p().catch(r=>{const o=r instanceof Error?r.message:String(r);console.error(o),process.exitCode=1});export{p as runWorkerCli};
2
+ import{Command as a}from"commander";import m from"node:path";import{createStartCommand as n}from"./commands/start.js";import{createDaemonCommand as t}from"./commands/daemon.js";import{createWorkerAuthCommand as s}from"./commands/worker-auth.js";import{createWorkerCodexCommand as c}from"./commands/worker-codex.js";import{createWorkerProjectCommand as i}from"./commands/worker-project.js";import{DEFAULT_ACA_SERVER_URL as d}from"./core/aca-config.js";process.env.ACA_DEFAULT_SERVER_URL||=d;async function p(r=process.argv){const o=new a;o.name("aica").description("AICA remote Agent worker").version("0.1.19").enablePositionalOptions(),o.addCommand(n()),o.addCommand(t()),o.addCommand(s()),o.addCommand(i()),o.addCommand(c()),await o.parseAsync(r)}const C=process.argv[1]||"",e=m.basename(C).replace(/\.(?:js|ts|cjs|mjs)$/i,"");(e==="worker-cli"||e==="aica"||e==="aca")&&p().catch(r=>{const o=r instanceof Error?r.message:String(r);console.error(o),process.exitCode=1});export{p as runWorkerCli};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuandc/aica",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "AICA remote Agent worker",
5
5
  "author": "yuandc",
6
6
  "type": "module",