@yuandc/aica 0.1.64 → 0.1.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{execFileSync as
|
|
2
|
-
`)||
|
|
1
|
+
import{execFileSync as l}from"node:child_process";import d from"node:fs";import c from"node:path";import h from"node:crypto";const m=50*1024*1024,g=["path","file","filePath","file_path","filename","targetPath","target_path","move_path"];function T(t){if(!b(t))return null;const e=v(t);if(!e)return null;const n=new Map;for(const r of e)n.set(r.path,{status:r.status,objectHash:r.status.includes("D")?null:w(t,r.path)});return n}function R(t){const e=new Map;for(const n of t.evidencePaths)x(e,t.cwd,n,"unknown","acp_tool");return[...e.values()].filter(n=>n.relativePath&&!n.relativePath.startsWith(".git/")).sort((n,r)=>n.relativePath.localeCompare(r.relativePath))}function E(t){const e=new Set;return u(t,(n,r)=>{if(typeof n=="string"&&(S(r)&&p(e,n),r==="command"))for(const s of F(n))p(e,s)}),A(t,e),j(t,e),[...e]}function x(t,e,n,r,s){const a=y(e,n);if(!a)return;const i=t.get(a.relativePath),o=C(a.absolutePath),f={path:a.absolutePath,absolutePath:a.absolutePath,relativePath:a.relativePath,changeType:P(i?.changeType,r),source:i?.source==="acp_tool"||i?.source==="acp_diff"?i.source:s,exists:!!o?.isFile(),downloadable:!!o?.isFile(),...o?.isFile()?{size:o.size,mime:z(a.absolutePath),sha256:o.size<=m?_(a.absolutePath):void 0}:{}};t.set(a.relativePath,f)}function P(t,e){return!t||t==="unknown"?e:e==="unknown"||t===e?t:t==="created"&&e==="modified"?"created":e}function y(t,e){if(!e||e.includes("\0"))return null;const n=c.resolve(t),r=c.isAbsolute(e)?c.resolve(e):c.resolve(n,e),s=c.relative(n,r).replace(/\\/g,"/");return!s||s.startsWith("..")||c.isAbsolute(s)?null:{absolutePath:r,relativePath:s}}function b(t){try{return l("git",["-C",t,"rev-parse","--is-inside-work-tree"],{encoding:"utf8",stdio:["ignore","pipe","ignore"]}),!0}catch{return!1}}function v(t){try{const n=l("git",["-C",t,"status","--porcelain=v1","-z","--untracked-files=all"],{encoding:"buffer",maxBuffer:20971520}).toString("utf8").split("\0").filter(Boolean),r=[];for(let s=0;s<n.length;s+=1){const a=n[s],i=a.slice(0,2),o=a.slice(3);if(o)if(i.startsWith("R")||i.startsWith("C")){const f=n[s+1];f&&(r.push({status:i,path:f}),s+=1)}else r.push({status:i,path:o})}return r}catch{return null}}function w(t,e){try{const n=l("git",["-C",t,"hash-object","--",e],{encoding:"utf8",stdio:["ignore","pipe","ignore"],maxBuffer:1048576}).trim();return/^[0-9a-f]{40,64}$/i.test(n)?n:null}catch{return null}}function u(t,e,n,r=0){if(!(r>8)&&(e(t,n),!(!t||typeof t!="object"))){if(Array.isArray(t)){for(const s of t)u(s,e,void 0,r+1);return}for(const[s,a]of Object.entries(t))u(a,e,s,r+1)}}function A(t,e){u(t,n=>{if(!n||typeof n!="object"||Array.isArray(n))return;const r=n;r.type==="diff"&&p(e,r.path)})}function j(t,e){u(t,(n,r)=>{if(!(r!=="changes"||!n||typeof n!="object"||Array.isArray(n)))for(const s of Object.keys(n))p(e,s)})}function S(t){return t?g.includes(t):!1}function p(t,e){if(typeof e!="string")return;const n=k(e);!n||n.length>500||n.includes(`
|
|
2
|
+
`)||n==="."||n===".."||t.add(n)}function k(t){let e=t.trim();e=e.replace(/\s+\+\d+\s*\/\s*-\d+(?:\s+.*)?$/,""),e=e.replace(/\s+\(\s*\+\d+\s*[,/ ]\s*-\d+\s*\)(?:\s+.*)?$/,""),e=e.replace(/\s+(?:source|event|workspace|session|last)=\S+.*$/,"");const n=e.split(/\s+/)[0]||"";return n&&/\.[A-Za-z][A-Za-z0-9+-]{0,12}$/.test(n)&&(e=n),e.replace(/^["']|["']$/g,"").trim()}function F(t){const e=[],n=/(?:^|\s)(?:\d?>|>>)\s*(?:"([^"]+)"|'([^']+)'|([^\s;&|<>]+))/g;let r;for(;r=n.exec(t);){const a=r[1]||r[2]||r[3];a&&e.push(a)}const s=/(?:^|\s)touch\s+(?:"([^"]+)"|'([^']+)'|([^\s;&|<>]+))/g;for(;r=s.exec(t);){const a=r[1]||r[2]||r[3];a&&!a.startsWith("-")&&e.push(a)}return e}function C(t){try{return d.statSync(t)}catch{return null}}function _(t){try{return h.createHash("sha256").update(d.readFileSync(t)).digest("hex")}catch{return}}function z(t){switch(c.extname(t).toLowerCase()){case".doc":return"application/msword";case".xls":return"application/vnd.ms-excel";case".xlsm":return"application/vnd.ms-excel.sheet.macroEnabled.12";case".ppt":return"application/vnd.ms-powerpoint";case".pptx":return"application/vnd.openxmlformats-officedocument.presentationml.presentation";case".odt":return"application/vnd.oasis.opendocument.text";case".ods":return"application/vnd.oasis.opendocument.spreadsheet";case".odp":return"application/vnd.oasis.opendocument.presentation";case".rtf":return"application/rtf";case".svg":return"image/svg+xml";case".bmp":return"image/bmp";case".tif":case".tiff":return"image/tiff";case".avif":return"image/avif";case".pdf":return"application/pdf";case".md":case".markdown":return"text/markdown; charset=utf-8";case".txt":case".log":return"text/plain; charset=utf-8";case".json":return"application/json; charset=utf-8";case".csv":return"text/csv; charset=utf-8";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".gif":return"image/gif";case".webp":return"image/webp";case".zip":return"application/zip";case".docx":return"application/vnd.openxmlformats-officedocument.wordprocessingml.document";case".xlsx":return"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";default:return"application/octet-stream"}}export{T as captureGitSnapshot,R as collectAffectedFiles,E as extractAffectedFilePathsFromAcpRaw,z as mimeForPath};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import l from"node:fs";import n from"node:path";import{mimeForPath as x}from"../affected-files.js";const A=new Set([".pdf",".doc",".docx",".odt",".rtf",".xls",".xlsx",".xlsm",".ods",".csv",".ppt",".pptx",".odp",".png",".jpg",".jpeg",".gif",".webp",".bmp",".tif",".tiff",".svg",".avif"]),_=new Set([".git","node_modules",".venv","venv","__pycache__"]),z=[".aca/attachments",".aica/attachments",".aca/artifacts",".aica/artifacts",".aca/logs",".aica/logs",".aca/server-data",".aica/server-data"],M=8192,S=1e4,u=new Map;function m(o){const t=n.basename(o);return!f(o)&&!t.startsWith("~$")&&A.has(n.extname(t).toLowerCase())}function f(o){const t=o.split(n.sep).join("/");return t.split("/").some(e=>_.has(e))||z.some(e=>t===e||t.startsWith(`${e}/`))}class N{root;warn;watches=new Map;subscribers=new Set;pending=new Set;timer;closed=!1;warned=!1;draining=!1;constructor(t,e){this.root=t,this.warn=e}degraded(t){this.warned||this.closed||(this.warned=!0,this.warn(`文档监听部分不可用,将以结束扫描补偿(仍可能遗漏瞬时变化):${String(t)}`))}watchDirectory(t){if(!(this.closed||this.watches.has(t))){if(this.watches.size>=M){this.degraded("目录监听数量达到上限");return}try{const e=l.watch(t,{persistent:!1},(i,s)=>{if(this.closed||!s)return;const a=n.join(t,s.toString()),r=n.relative(this.root,a);if(!f(r)){if(m(r))for(const c of this.subscribers)c.size<S?c.add(r):this.degraded("文件事件候选数量达到上限");i==="rename"&&this.schedule(a)}});e.on("error",i=>{e.close(),this.watches.get(t)===e&&this.watches.delete(t),this.degraded(i)}),this.watches.set(t,e)}catch(e){this.degraded(e)}}}schedule(t){if(this.pending.size>=S){this.degraded("目录事件积压");return}this.pending.add(t),!(this.timer||this.draining)&&(this.timer=setTimeout(()=>{this.timer=void 0,this.drain()},50),this.timer.unref())}async drain(){this.draining=!0;try{for(;!this.closed&&this.pending.size>0;){const t=this.pending.values().next().value;if(this.pending.delete(t),this.watches.has(t))for(const[e,i]of this.watches)(e===t||e.startsWith(`${t}${n.sep}`))&&(i.close(),this.watches.delete(e));await this.walk(t,new Map)}}finally{this.draining=!1}}async snapshot(){const t=new Map;return await this.walk(this.root,t),t}async walk(t,e){if(this.closed)return;const i=n.relative(this.root,t);if(!f(i))try{const s=await l.promises.lstat(t);if(s.isSymbolicLink())return;if(s.isDirectory()){this.watchDirectory(t);const a=await l.promises.opendir(t);for await(const r of a){if(this.closed)break;if(r.isSymbolicLink())continue;const c=n.join(t,r.name),d=n.relative(this.root,c);f(d)||(r.isDirectory()||m(d))&&await this.walk(c,e)}}else if(s.isFile()&&m(i)){const a=await l.promises.realpath(t),r=n.relative(this.root,a);if(r.startsWith(`..${n.sep}`)||n.isAbsolute(r)||f(r))return;e.set(i,{size:s.size,signature:`${s.dev}:${s.ino}:${s.size}:${s.mtimeMs}:${s.ctimeMs}`})}}catch(s){const a=s.code;a!=="ENOENT"&&a!=="ENOTDIR"&&this.degraded(s)}}close(){this.closed=!0,this.timer&&clearTimeout(this.timer);for(const t of this.watches.values())t.close();this.watches.clear(),this.pending.clear()}}async function j(o,t){const e=await l.promises.realpath(o);let i=u.get(e);i||(i=new N(e,t),u.set(e,i));const s=i,a=new Set;s.subscribers.add(a);let r=!1;const c=()=>{r||(r=!0,s.subscribers.delete(a),s.subscribers.size===0&&(s.close(),u.delete(e)))};let d;try{d=await s.snapshot(),a.clear()}catch(w){throw c(),w}let b;return{dispose:c,finish(){return b??=(async()=>{if(r)return[];try{const w=await s.snapshot(),g=[];for(const[h,p]of w){const v=d.get(h);if(!a.has(h)&&v?.signature===p.signature)continue;const y=n.join(e,h);g.push({path:y,absolutePath:y,relativePath:h.split(n.sep).join("/"),changeType:v?"modified":"created",source:"job_time_window",exists:!0,downloadable:!0,size:p.size,mime:x(h)})}return g.sort((h,p)=>h.relativePath.localeCompare(p.relativePath))}finally{c()}})()}}}function k(o,t){const e=new Map(o.map(i=>[i.relativePath,i]));for(const i of t)e.set(i.relativePath,i);return[...e.values()]}export{m as isArtifactPath,f as isIgnoredArtifactPath,k as mergeArtifactFiles,j as startJobArtifactMonitor};
|
package/dist/core/job-worker.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import X from"node:crypto";import{appendSessionReferenceContext as Z}from"./session-reference-prompt.js";import N from"node:fs";import M from"node:path";import{compactAgentContext as Q,forkAgentSession as Y,sendAgentPrompt as ee}from"../acp/agent.js";import{acaServerDownload as te,acaServerRequest as S}from"./aca-server-client.js";import{loadAcaConfig as ne}from"./aca-config.js";import{prepareLocalWorktree as oe}from"./worktree.js";import{expandWorkerRuntimePath as ie}from"./worker-runtime-paths.js";import{collectAffectedFiles as J,extractAffectedFilePathsFromAcpRaw as ae}from"./affected-files.js";import{resolveJobPermissionPolicy as re}from"./job-permission-policy.js";import{createAcpEventBatcher as se}from"./acp-event-batcher.js";import{createToolLifecycleTrace as ce}from"../acp/tool-lifecycle-trace.js";import{shouldBufferAcpEvent as le}from"./acp-event-upload-filter.js";import{userFacingAcpError as de}from"../acp/error-display.js";import{ensureCodexProviderRuntimeRevision as ue}from"./codex-provider-runtime-config.js";import{acpSessionInvalidationFromError as pe}from"../acp/session-errors.js";const me=1500,B=5e3,L=1e3,W=900,fe=1e4,he=0,we=12e3;function Ie(e){return ie(e)}function ye(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 lt(e,t={}){let n=!1,i=null,o=null,s=0,l=0;const u=new Set,r=new Map,b=new Map,A=async()=>{if(n||Date.now()<l)return;const m=ve();if(D(u.size,m))try{const p=t.loadConfig?.()??ne();if(!p.token)return;for(;!n&&D(u.size,m);){const v=t.claimNextJob?await t.claimNextJob(p,[...r.keys()]):await S("POST","/api/client/jobs/claim",{machineId:p.machineId,workspaceId:p.defaultWorkspaceId,activeSessionIds:[...r.keys()]});if(s=0,l=0,!v.item)break;const f=v.item;if(n){await(t.cancelClaimedJob?t.cancelClaimedJob(f,p):j(f.job_id,p.machineId,"cancelled")).catch(()=>{});break}const h=f.session_id,w=r.get(h);u.add(f.job_id);const P=new AbortController;let x;x=(async()=>{w&&(e.warn(`claimed job=${f.job_id} for already active session=${h}; waiting for the previous run to release its ACP runtime`),await be(w,f,p,P)),!P.signal.aborted&&await(t.runJob??ge)(f,p,e,P)})().catch(c=>{e.warn(`job ${f.job_id} failed outside handler: ${c instanceof Error?c.message:String(c)}`)}).finally(()=>{u.delete(f.job_id),r.get(h)===x&&r.delete(h),b.delete(f.job_id)}),r.set(h,x),b.set(f.job_id,{controller:P,promise:x})}}catch(p){if(!n){s+=1;const v=We(s);l=Date.now()+v,e.warn(`job worker failed, retry in ${v}ms: ${p instanceof Error?p.message:String(p)}`)}}},C=()=>{if(n||i)return;const m=A();i=m,m.finally(()=>{i===m&&(i=null)})};C();const d=setInterval(()=>{C()},t.claimIntervalMs??me);return{timer:d,stop:()=>o||(o=(async()=>{if(n)return;n=!0,clearInterval(d);for(const p of b.values())p.controller.abort();await i?.catch(()=>{});for(const p of b.values())p.controller.abort();const m=[...b.values()].map(p=>p.promise);m.length!==0&&await Promise.race([Promise.allSettled(m).then(()=>{}),F(we)])})(),o)}}async function be(e,t,n,i){let o=!1;const l=setInterval(()=>{o||i.signal.aborted||(o=!0,Promise.allSettled([S("POST",`/api/client/jobs/${encodeURIComponent(t.job_id)}/heartbeat`,{machineId:n.machineId}),G(t.job_id,i)]).finally(()=>{o=!1}))},B);try{await Promise.race([e,Se(i.signal)])}finally{clearInterval(l)}}function Se(e){return e.aborted?Promise.resolve():new Promise(t=>e.addEventListener("abort",()=>t(),{once:!0}))}function ve(){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?he:t===0?0:Math.max(1,Math.min(t,8))}function D(e,t){return t===0||e<t}async function ge(e,t,n,i){const o=e.job_id,s=e.session_id,l=e.workspace_id,u=e.project_id??null,r=e.input??{},b=String(r.control?.type||"").toLowerCase();if(!b&&!r.message?.trim()&&(r.attachments??[]).length===0&&!r.sessionReferences?.length){await j(o,t.machineId,"job input missing message");return}const A=t.projects.find(c=>c.projectId===u),C=Ie(A?.rootPath||e.project_root_path||"");if(!C){await j(o,t.machineId,"job project root is unknown");return}ye(e)&&N.mkdirSync(C,{recursive:!0}),n.info(`claimed job=${o} session=${s} project=${A?.name??u??"unknown"}`);let d=!1,m=!1;const p=setInterval(()=>{d||(d=!0,S("POST",`/api/client/jobs/${encodeURIComponent(o)}/heartbeat`,{machineId:t.machineId}).catch(()=>{}).finally(()=>{d=!1})),m||(m=!0,G(o,i).catch(()=>{}).finally(()=>{m=!1}))},B);let v=0;const f=ce(c=>n.info(c)),h=se(o,t.machineId,{warn:c=>n.warn(c),trace:f}),w=Re(o,t.machineId),P=new Set;let x=null;try{await w.sendNow({phase:"initializing",label:"准备工作区",detail:e.worktree_id?"worktree":"project root"}).catch(()=>{});const c=oe({projectId:u,sessionId:s,projectRoot:C,worktree:e});x=c,await ze(o,t.machineId,c);const g=Te(r.acpRun);if(Ae(g.agentType)&&await ue(e.codex_provider_revision),b==="compact"){if(!e.acp_session_id)throw new Error("Current session does not have an ACP context to compact");const a=await Q({agentType:k(g.agentType,"codex"),cliType:k(g.cliType,"builtin"),acpSessionId:e.acp_session_id,cwd:c.cwd,model:r.model,mode:r.mode,configOptionValues:r.configOptionValues,timeoutMs:r.timeoutMs,allowRollover:r.control?.allowRollover===!0,signal:i.signal,onStatus:y=>{w.report({phase:y.phase,label:y.label,detail:y.detail,updateType:y.updateType,raw:y})}});await w.flush(),await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:a.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"compact",allowRollover:r.control?.allowRollover===!0},acpSessionId:a.acpSessionId,durationMs:a.durationMs,usage:a.contextUsage,maintenance:a.maintenance,worktree:$(c)}}),n.info(`completed context compact job=${o}`);return}if(b==="fork"){const a=String(r.control?.sourceAcpSessionId||"").trim();if(!a)throw new Error("Source session does not have a Codex ACP context to fork");await w.sendNow({phase:"forking",label:"正在分叉 Codex 会话",detail:r.control?.sourceSessionId?`源会话 ${r.control.sourceSessionId}`:void 0}).catch(()=>{});const y=await Y({agentType:k(g.agentType,"codex"),cliType:k(g.cliType,"builtin"),sourceProviderSessionId:a,cwd:c.cwd,model:r.model,mode:r.mode,configOptionValues:r.configOptionValues,timeoutMs:r.timeoutMs,signal:i.signal,onStatus:R=>{w.report({phase:R.phase,label:R.label,detail:R.detail,updateType:R.updateType,raw:R})}});await w.flush(),await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:y.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"fork",sourceSessionId:r.control?.sourceSessionId||null},acpSessionId:y.acpSessionId,worktree:$(c)}}),n.info(`completed Codex session fork job=${o}`);return}const _=await Ee({cwd:c.cwd,sessionId:s,jobId:o,attachments:r.attachments??[]});_.length>0&&(n.info(`materialized ${_.length} attachment(s) for job=${o}`),await w.sendNow({phase:"initializing",label:"附件已写入本机",detail:_.map(a=>a.relativePath).join(", "),raw:{attachments:q(_)}}).catch(()=>{}));const T=$e(r,_),O=je(T,_),I=await ee({agentType:k(g.agentType,"codex"),cliType:k(g.cliType,"builtin"),acpSessionId:e.acp_session_id??null,requireSessionResume:_e(e.session_raw),prompt:T,promptBlocks:O,cwd:c.cwd,model:r.model,mode:r.mode,configOptionValues:r.configOptionValues,canExecuteTools:r.canExecuteTools,timeoutMs:r.timeoutMs,contextWindow:Ce(g.contextWindow),signal:i.signal,onStatus:a=>{w.report({phase:a.phase,label:a.label,detail:a.detail,updateType:a.updateType,raw:a})},onUpdate:a=>{v+=1,(a.type==="tool_call"||a.type==="tool_call_update"&&["completed","failed","cancelled"].includes(a.status||""))&&f("worker_event",{jobId:o,uploadRunId:h.uploadRunId,toolCallId:a.toolCallId,status:a.status,sequence:v});for(const R of ae(a.raw))P.add(R);const y={turnId:e.user_turn_id??null,eventType:a.type,label:a.label,text:a.text,status:a.status,toolCallId:a.toolCallId,raw:ke(a.raw,v)};le(y)&&h.push(y)},onPermissionRequest:a=>{const y=re(r,a);return y?Promise.resolve(y):Ue(o,t.machineId,a,i.signal)},onUserInputRequest:a=>Je(o,t.machineId,a,i.signal),onProviderSessionMigration:async a=>{const y=await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/acp-session`,{machineId:t.machineId,previousAcpSessionId:a.previousProviderSessionId,acpSessionId:a.providerSessionId,reason:a.reason,migratedAtMs:a.migratedAtMs});e.acp_session_id=a.providerSessionId,n.info(`migrated ACP session for job=${o} ${a.previousProviderSessionId} -> ${a.providerSessionId}`),await h.flush().catch(()=>{}),await w.sendNow({phase:"resuming",label:"Codex 会话已迁移",detail:a.providerSessionId,updateType:"aca.performance.provider_session_migrated",raw:{migration:a,server:{migrated:y.migrated===!0}}}).catch(()=>{})}}),U=await h.finish();await w.flush();const H=J({cwd:c.cwd,evidencePaths:P}),E=Pe(I.promptResponse);if(!(xe(E)||!!I.content)){await j(o,t.machineId,`${I.agentType} stopped: ${E??"unknown"}`,{acpSessionId:I.acpSessionId,stopReason:E,eventUpload:U,exitCode:I.exitCode,stderr:De(I.stderr,4e3),worktree:$(c)});return}await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:I.acpSessionId,assistantText:I.content,result:{ok:!0,eventUpload:U,acpSessionId:I.acpSessionId,stopReason:E,durationMs:I.durationMs,acpRun:r.acpRun??null,effectiveConfig:I.effectiveConfig??null,performance:I.performance??null,usage:I.contextUsage??null,providerDiagnostics:I.providerDiagnostics??null,updateCount:I.updateCount,statusTimeline:I.statusTimeline,worktree:$(c),attachments:q(_),files:H}}),n.info(`completed job=${o}`)}catch(c){if(Le(i.signal)){h.discard(),w.discard(),n.warn(`stopped local job=${o} because ACA Server already finalized it`);return}const g=await h.finish();await w.flush();const _=i.signal.aborted?"cancelled":c instanceof Error?c.message:String(c),T=pe(c),O=x?J({cwd:x.cwd,evidencePaths:P}):[];await j(o,t.machineId,de(_),{rawError:_,eventUpload:g,files:O,providerDiagnostics:z(c,"providerDiagnostics"),statusTimeline:z(c,"statusTimeline"),performance:z(c,"performance"),...T?{acpSessionInvalidated:!0,invalidatedAcpSessionId:T.providerSessionId,failure:{category:T.category,actions:T.actions,details:T.details}}:{}},T?{invalidateAcpSession:!0,invalidatedAcpSessionId:T.providerSessionId}:void 0)}finally{h.discard(),clearInterval(p),await w.flush()}}function _e(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 Te(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function Ae(e){const t=String(e||"codex").toLowerCase().replace(/[^a-z0-9]+/g,"");return t==="codex"||t==="codexacp"||t==="codexstandard"}function Ce(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function k(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function Pe(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 xe(e){return e?["end_turn","stop","completed","complete"].includes(e):!1}function Re(e,t){let n=null,i=0,o="",s=null,l=Promise.resolve(),u=!1;const r=d=>JSON.stringify({phase:d.phase??"",label:d.label??"",detail:d.detail??"",updateType:d.updateType??""}),b=async d=>{await S("POST",`/api/client/jobs/${encodeURIComponent(e)}/presence`,{machineId:t,phase:d.phase,label:d.label,detail:d.detail,updateType:d.updateType,raw:d.raw}),i=Date.now(),o=r(d)},A=()=>{if(s&&(clearTimeout(s),s=null),u)return n=null,l;if(!n)return l;const d=n;return n=null,l=l.then(()=>b(d)).catch(()=>{}),l},C=d=>{s||(s=setTimeout(()=>{A()},d),s.unref())};return{report(d){if(u)return;const m=Date.now(),v=r(d)!==o,f=m-i>=fe;if(!v&&!f)return;n=d;const h=m-i;if(h>=W||i===0){A();return}C(W-h)},sendNow(d){return u?l:(n=d,A())},flush:A,discard(){u=!0,n=null,s&&clearTimeout(s),s=null}}}function ke(e,t){return e&&typeof e=="object"&&!Array.isArray(e)?{...e,acaSequence:t}:{value:e,acaSequence:t}}function $e(e,t=[]){const n=Z(e?.message?.trim()??"",e?.sessionReferences);if(t.length===0)return n;const o=["用户随消息上传了以下附件,aca 已将附件写入本机工作区。需要读取附件时请直接使用下面的 localPath;图片附件也已作为 ACP image block 随本轮请求传入。",...t.map((s,l)=>`${l+1}. ${s.name} (${s.kind}, ${s.mimeType}, ${Fe(s.size)})
|
|
1
|
+
import ee from"node:crypto";import{startJobArtifactMonitor as te,mergeArtifactFiles as W}from"./artifacts/job-artifact-monitor.js";import{appendSessionReferenceContext as ne}from"./session-reference-prompt.js";import F from"node:fs";import N from"node:path";import{compactAgentContext as oe,forkAgentSession as ie,sendAgentPrompt as ae}from"../acp/agent.js";import{acaServerDownload as re,acaServerRequest as S}from"./aca-server-client.js";import{loadAcaConfig as se}from"./aca-config.js";import{prepareLocalWorktree as ce}from"./worktree.js";import{expandWorkerRuntimePath as le}from"./worker-runtime-paths.js";import{collectAffectedFiles as D,extractAffectedFilePathsFromAcpRaw as de}from"./affected-files.js";import{resolveJobPermissionPolicy as ue}from"./job-permission-policy.js";import{createAcpEventBatcher as pe}from"./acp-event-batcher.js";import{createToolLifecycleTrace as me}from"../acp/tool-lifecycle-trace.js";import{shouldBufferAcpEvent as fe}from"./acp-event-upload-filter.js";import{userFacingAcpError as he}from"../acp/error-display.js";import{ensureCodexProviderRuntimeRevision as we}from"./codex-provider-runtime-config.js";import{acpSessionInvalidationFromError as be}from"../acp/session-errors.js";const ye=1500,V=5e3,q=1e3,G=900,Ie=1e4,Se=0,ve=12e3;function ge(e){return le(e)}function _e(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 ht(e,t={}){let n=!1,i=null,o=null,s=0,l=0;const u=new Set,r=new Map,I=new Map,_=async()=>{if(n||Date.now()<l)return;const f=Ce();if(K(u.size,f))try{const p=t.loadConfig?.()??se();if(!p.token)return;for(;!n&&K(u.size,f);){const v=t.claimNextJob?await t.claimNextJob(p,[...r.keys()]):await S("POST","/api/client/jobs/claim",{machineId:p.machineId,workspaceId:p.defaultWorkspaceId,activeSessionIds:[...r.keys()]});if(s=0,l=0,!v.item)break;const h=v.item;if(n){await(t.cancelClaimedJob?t.cancelClaimedJob(h,p):M(h.job_id,p.machineId,"cancelled")).catch(()=>{});break}const w=h.session_id,b=r.get(w);u.add(h.job_id);const P=new AbortController;let x;x=(async()=>{b&&(e.warn(`claimed job=${h.job_id} for already active session=${w}; waiting for the previous run to release its ACP runtime`),await Te(b,h,p,P)),!P.signal.aborted&&await(t.runJob??Pe)(h,p,e,P)})().catch(R=>{e.warn(`job ${h.job_id} failed outside handler: ${R instanceof Error?R.message:String(R)}`)}).finally(()=>{u.delete(h.job_id),r.get(w)===x&&r.delete(w),I.delete(h.job_id)}),r.set(w,x),I.set(h.job_id,{controller:P,promise:x})}}catch(p){if(!n){s+=1;const v=Ke(s);l=Date.now()+v,e.warn(`job worker failed, retry in ${v}ms: ${p instanceof Error?p.message:String(p)}`)}}},C=()=>{if(n||i)return;const f=_();i=f,f.finally(()=>{i===f&&(i=null)})};C();const d=setInterval(()=>{C()},t.claimIntervalMs??ye);return{timer:d,stop:()=>o||(o=(async()=>{if(n)return;n=!0,clearInterval(d);for(const p of I.values())p.controller.abort();await i?.catch(()=>{});for(const p of I.values())p.controller.abort();const f=[...I.values()].map(p=>p.promise);f.length!==0&&await Promise.race([Promise.allSettled(f).then(()=>{}),z(ve)])})(),o)}}async function Te(e,t,n,i){let o=!1;const l=setInterval(()=>{o||i.signal.aborted||(o=!0,Promise.allSettled([S("POST",`/api/client/jobs/${encodeURIComponent(t.job_id)}/heartbeat`,{machineId:n.machineId}),Z(t.job_id,i)]).finally(()=>{o=!1}))},V);try{await Promise.race([e,Ae(i.signal)])}finally{clearInterval(l)}}function Ae(e){return e.aborted?Promise.resolve():new Promise(t=>e.addEventListener("abort",()=>t(),{once:!0}))}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?Se:t===0?0:Math.max(1,Math.min(t,8))}function K(e,t){return t===0||e<t}async function Pe(e,t,n,i){const o=e.job_id,s=e.session_id,l=e.workspace_id,u=e.project_id??null,r=e.input??{},I=String(r.control?.type||"").toLowerCase();if(!I&&!r.message?.trim()&&(r.attachments??[]).length===0&&!r.sessionReferences?.length){await M(o,t.machineId,"job input missing message");return}const _=t.projects.find(c=>c.projectId===u),C=ge(_?.rootPath||e.project_root_path||"");if(!C){await M(o,t.machineId,"job project root is unknown");return}_e(e)&&F.mkdirSync(C,{recursive:!0}),n.info(`claimed job=${o} session=${s} project=${_?.name??u??"unknown"}`);let d=!1,f=!1;const p=setInterval(()=>{d||(d=!0,S("POST",`/api/client/jobs/${encodeURIComponent(o)}/heartbeat`,{machineId:t.machineId}).catch(()=>{}).finally(()=>{d=!1})),f||(f=!0,Z(o,i).catch(()=>{}).finally(()=>{f=!1}))},V);let v=0;const h=me(c=>n.info(c)),w=pe(o,t.machineId,{warn:c=>n.warn(c),trace:h}),b=Me(o,t.machineId),P=new Set;let x=null,R;const J=async()=>R?.finish().catch(c=>(n.warn(`artifact collection failed job=${o}: ${String(c)}`),[]))??[];try{await b.sendNow({phase:"initializing",label:"准备工作区",detail:e.worktree_id?"worktree":"project root"}).catch(()=>{});const c=ce({projectId:u,sessionId:s,projectRoot:C,worktree:e});x=c,await We(o,t.machineId,c);const g=Re(r.acpRun);if(ke(g.agentType)&&await we(e.codex_provider_revision),I==="compact"){if(!e.acp_session_id)throw new Error("Current session does not have an ACP context to compact");const a=await oe({agentType:$(g.agentType,"codex"),cliType:$(g.cliType,"builtin"),acpSessionId:e.acp_session_id,cwd:c.cwd,model:r.model,mode:r.mode,configOptionValues:r.configOptionValues,timeoutMs:r.timeoutMs,allowRollover:r.control?.allowRollover===!0,signal:i.signal,onStatus:y=>{b.report({phase:y.phase,label:y.label,detail:y.detail,updateType:y.updateType,raw:y})}});await b.flush(),await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:a.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"compact",allowRollover:r.control?.allowRollover===!0},acpSessionId:a.acpSessionId,durationMs:a.durationMs,usage:a.contextUsage,maintenance:a.maintenance,worktree:E(c)}}),n.info(`completed context compact job=${o}`);return}if(I==="fork"){const a=String(r.control?.sourceAcpSessionId||"").trim();if(!a)throw new Error("Source session does not have a Codex ACP context to fork");await b.sendNow({phase:"forking",label:"正在分叉 Codex 会话",detail:r.control?.sourceSessionId?`源会话 ${r.control.sourceSessionId}`:void 0}).catch(()=>{});const y=await ie({agentType:$(g.agentType,"codex"),cliType:$(g.cliType,"builtin"),sourceProviderSessionId:a,cwd:c.cwd,model:r.model,mode:r.mode,configOptionValues:r.configOptionValues,timeoutMs:r.timeoutMs,signal:i.signal,onStatus:k=>{b.report({phase:k.phase,label:k.label,detail:k.detail,updateType:k.updateType,raw:k})}});await b.flush(),await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:y.acpSessionId,suppressTurn:!0,result:{ok:!0,control:{type:"fork",sourceSessionId:r.control?.sourceSessionId||null},acpSessionId:y.acpSessionId,worktree:E(c)}}),n.info(`completed Codex session fork job=${o}`);return}const T=await ze({cwd:c.cwd,sessionId:s,jobId:o,attachments:r.attachments??[]});T.length>0&&(n.info(`materialized ${T.length} attachment(s) for job=${o}`),await b.sendNow({phase:"initializing",label:"附件已写入本机",detail:T.map(a=>a.relativePath).join(", "),raw:{attachments:X(T)}}).catch(()=>{}));const j=Ne(r,T),A=Fe(j,T);R=await te(c.cwd,a=>n.warn(a)).catch(a=>{n.warn(`artifact monitor unavailable job=${o}: ${String(a)}`)});const m=await ae({agentType:$(g.agentType,"codex"),cliType:$(g.cliType,"builtin"),acpSessionId:e.acp_session_id??null,requireSessionResume:xe(e.session_raw),prompt:j,promptBlocks:A,cwd:c.cwd,model:r.model,mode:r.mode,configOptionValues:r.configOptionValues,canExecuteTools:r.canExecuteTools,timeoutMs:r.timeoutMs,contextWindow:$e(g.contextWindow),signal:i.signal,onStatus:a=>{b.report({phase:a.phase,label:a.label,detail:a.detail,updateType:a.updateType,raw:a})},onUpdate:a=>{v+=1,(a.type==="tool_call"||a.type==="tool_call_update"&&["completed","failed","cancelled"].includes(a.status||""))&&h("worker_event",{jobId:o,uploadRunId:w.uploadRunId,toolCallId:a.toolCallId,status:a.status,sequence:v});for(const k of de(a.raw))P.add(k);const y={turnId:e.user_turn_id??null,eventType:a.type,label:a.label,text:a.text,status:a.status,toolCallId:a.toolCallId,raw:Oe(a.raw,v)};fe(y)&&w.push(y)},onPermissionRequest:a=>{const y=ue(r,a);return y?Promise.resolve(y):De(o,t.machineId,a,i.signal)},onUserInputRequest:a=>Ve(o,t.machineId,a,i.signal),onProviderSessionMigration:async a=>{const y=await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/acp-session`,{machineId:t.machineId,previousAcpSessionId:a.previousProviderSessionId,acpSessionId:a.providerSessionId,reason:a.reason,migratedAtMs:a.migratedAtMs});e.acp_session_id=a.providerSessionId,n.info(`migrated ACP session for job=${o} ${a.previousProviderSessionId} -> ${a.providerSessionId}`),await w.flush().catch(()=>{}),await b.sendNow({phase:"resuming",label:"Codex 会话已迁移",detail:a.providerSessionId,updateType:"aca.performance.provider_session_migrated",raw:{migration:a,server:{migrated:y.migrated===!0}}}).catch(()=>{})}}),Y=await J(),B=await w.finish();await b.flush();const L=W(D({cwd:c.cwd,evidencePaths:P}),Y),O=je(m.promptResponse);if(!(Ee(O)||!!m.content)){await M(o,t.machineId,`${m.agentType} stopped: ${O??"unknown"}`,{acpSessionId:m.acpSessionId,stopReason:O,eventUpload:B,files:L,exitCode:m.exitCode,stderr:He(m.stderr,4e3),worktree:E(c)});return}await S("POST",`/api/client/jobs/${encodeURIComponent(o)}/complete`,{machineId:t.machineId,acpSessionId:m.acpSessionId,assistantText:m.content,result:{ok:!0,eventUpload:B,acpSessionId:m.acpSessionId,stopReason:O,durationMs:m.durationMs,acpRun:r.acpRun??null,effectiveConfig:m.effectiveConfig??null,performance:m.performance??null,usage:m.contextUsage??null,providerDiagnostics:m.providerDiagnostics??null,updateCount:m.updateCount,statusTimeline:m.statusTimeline,worktree:E(c),attachments:X(T),files:L}}),n.info(`completed job=${o}`)}catch(c){if(Ge(i.signal)){w.discard(),b.discard(),n.warn(`stopped local job=${o} because ACA Server already finalized it`);return}const g=await J(),T=await w.finish();await b.flush();const j=i.signal.aborted?"cancelled":c instanceof Error?c.message:String(c),A=be(c),m=W(x?D({cwd:x.cwd,evidencePaths:P}):[],g);await M(o,t.machineId,he(j),{rawError:j,eventUpload:T,files:m,providerDiagnostics:U(c,"providerDiagnostics"),statusTimeline:U(c,"statusTimeline"),performance:U(c,"performance"),...A?{acpSessionInvalidated:!0,invalidatedAcpSessionId:A.providerSessionId,failure:{category:A.category,actions:A.actions,details:A.details}}:{}},A?{invalidateAcpSession:!0,invalidatedAcpSessionId:A.providerSessionId}:void 0)}finally{R?.dispose(),w.discard(),clearInterval(p),await b.flush()}}function xe(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 Re(e){return!e||typeof e!="object"||Array.isArray(e)?{}:e}function ke(e){const t=String(e||"codex").toLowerCase().replace(/[^a-z0-9]+/g,"");return t==="codex"||t==="codexacp"||t==="codexstandard"}function $e(e){return typeof e=="number"&&Number.isFinite(e)&&e>0?e:void 0}function $(...e){for(const t of e)if(typeof t=="string"&&t.trim())return t.trim();return""}function je(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 Ee(e){return e?["end_turn","stop","completed","complete"].includes(e):!1}function Me(e,t){let n=null,i=0,o="",s=null,l=Promise.resolve(),u=!1;const r=d=>JSON.stringify({phase:d.phase??"",label:d.label??"",detail:d.detail??"",updateType:d.updateType??""}),I=async d=>{await S("POST",`/api/client/jobs/${encodeURIComponent(e)}/presence`,{machineId:t,phase:d.phase,label:d.label,detail:d.detail,updateType:d.updateType,raw:d.raw}),i=Date.now(),o=r(d)},_=()=>{if(s&&(clearTimeout(s),s=null),u)return n=null,l;if(!n)return l;const d=n;return n=null,l=l.then(()=>I(d)).catch(()=>{}),l},C=d=>{s||(s=setTimeout(()=>{_()},d),s.unref())};return{report(d){if(u)return;const f=Date.now(),v=r(d)!==o,h=f-i>=Ie;if(!v&&!h)return;n=d;const w=f-i;if(w>=G||i===0){_();return}C(G-w)},sendNow(d){return u?l:(n=d,_())},flush:_,discard(){u=!0,n=null,s&&clearTimeout(s),s=null}}}function Oe(e,t){return e&&typeof e=="object"&&!Array.isArray(e)?{...e,acaSequence:t}:{value:e,acaSequence:t}}function Ne(e,t=[]){const n=ne(e?.message?.trim()??"",e?.sessionReferences);if(t.length===0)return n;const o=["用户随消息上传了以下附件,aca 已将附件写入本机工作区。需要读取附件时请直接使用下面的 localPath;图片附件也已作为 ACP image block 随本轮请求传入。",...t.map((s,l)=>`${l+1}. ${s.name} (${s.kind}, ${s.mimeType}, ${Le(s.size)})
|
|
2
2
|
localPath: ${s.path}
|
|
3
3
|
workspacePath: ${s.relativePath}`)].join(`
|
|
4
4
|
`);return n?`${n}
|
|
5
5
|
|
|
6
|
-
${o}`:o}function
|
|
6
|
+
${o}`:o}function Fe(e,t){const n=[{type:"text",text:e}];for(const i of t)i.kind!=="image"||!i.mimeType.startsWith("image/")||n.push({type:"image",data:i.base64,mimeType:i.mimeType,uri:i.path});return n}async function ze(e){if(e.attachments.length===0)return[];const t=N.join(e.cwd,".aca","attachments",H(e.sessionId),H(e.jobId));F.mkdirSync(t,{recursive:!0});const n=[];for(const[i,o]of e.attachments.entries()){const s=o.attachmentId?{mimeType:o.mimeType||"application/octet-stream",bytes:await re(`/api/client/attachments/${encodeURIComponent(o.attachmentId)}`)}:Ue(o.dataUrl??""),l=o.mimeType||s.mimeType||"application/octet-stream",u=o.kind==="image"||l.startsWith("image/")?"image":"file",r=Je(o.name||`attachment-${i+1}`,l),I=N.join(t,`${String(i+1).padStart(2,"0")}-${r}`);F.writeFileSync(I,s.bytes),n.push({name:o.name||r,mimeType:l,size:s.bytes.byteLength,kind:u,path:I,relativePath:N.relative(e.cwd,I),base64:s.bytes.toString("base64"),sha256:ee.createHash("sha256").update(s.bytes).digest("hex")})}return n}function Ue(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),i=e.slice(t+1),o=n.split(";").filter(Boolean),s=o[0]?.includes("/")?o[0]:"application/octet-stream";if(!o.includes("base64"))throw new Error("attachment dataUrl is not base64 encoded");return{mimeType:s,bytes:Buffer.from(i,"base64")}}function Je(e,t){const n=N.basename(e).replace(/[<>:"/\\|?*\x00-\x1F]/g,"_").trim(),i=`attachment${Be(t)}`;return(!n||n==="."||n===".."?i:n).slice(0,180)}function Be(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 H(e){return e.replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"item"}function X(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 Le(e){if(!Number.isFinite(e)||e<=0)return"0 B";const t=["B","KB","MB","GB"];let n=e,i=0;for(;n>=1024&&i<t.length-1;)n/=1024,i+=1;return`${n>=10||i===0?n.toFixed(0):n.toFixed(1)} ${t[i]}`}async function We(e,t,n){!n.usedWorktree||!n.worktreeId||await S("POST",`/api/client/jobs/${encodeURIComponent(e)}/worktree`,{machineId:t,baseCommit:n.baseCommit??null,worktreePath:n.cwd,status:n.status??"active",raw:n.raw??E(n)})}function E(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 De(e,t,n,i){const s=(await S("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:n})).item.permission_id;for(;!i.aborted;){await z(q);const l=await S("GET",`/api/client/permissions/${encodeURIComponent(s)}`);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 Ve(e,t,n,i){const s=(await S("POST",`/api/client/jobs/${encodeURIComponent(e)}/permissions`,{machineId:t,request:{kind:"elicitation",...n}})).item.permission_id;for(;!i.aborted;){await z(q);const l=await S("GET",`/api/client/permissions/${encodeURIComponent(s)}`);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 Z(e,t){if(t.signal.aborted)return;const n=await S("GET",`/api/client/jobs/${encodeURIComponent(e)}`);if(Number(n.item.cancel_requested??0)===1){t.abort();return}const i=qe(n.item);i&&t.abort(new Q(e,i))}function qe(e){const t=String(e.status||"").toLowerCase();return t&&!["claimed","running"].includes(t)?t:null}class Q extends Error{constructor(t,n){super(`ACA Server already finalized job=${t} status=${n}`),this.name="ServerFinalizedJobError"}}function Ge(e){return e.aborted&&e.reason instanceof Q}async function M(e,t,n,i,o){await S("POST",`/api/client/jobs/${encodeURIComponent(e)}/fail`,{machineId:t,error:n,result:i,...o?.invalidateAcpSession?{invalidateAcpSession:!0,invalidatedAcpSessionId:o.invalidatedAcpSessionId}:{}})}function z(e){return new Promise(t=>setTimeout(t,e))}function Ke(e){return Math.min(1e4,500*2**Math.min(5,Math.max(0,e-1)))+Math.floor(Math.random()*250)}function He(e,t){return e.length<=t?e:`${e.slice(0,t)}...`}function U(e,t){return!e||typeof e!="object"||Array.isArray(e)?null:e[t]??null}export{qe as serverFinalizedJobStatus,ht as startJobWorkerLoop};
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const o="0.1.
|
|
1
|
+
const o="0.1.65";export{o as AICA_VERSION};
|