@yuandc/aica 0.1.94 → 0.1.96
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
|
|
2
|
-
|
|
1
|
+
import f from"node:path";import{getLogDir as s}from"../core/paths.js";import{RotatingLog as u}from"../core/logging/rotating-log.js";const p=new Set(["jobId","threadId","turnId","toolCallId","itemType","status","sequence","method","reason","uploadRunId","batchNo","attempt","firstSequence","lastSequence","eventCount"]);let n;function g(l){let c=0;const i=process.env.ACA_TOOL_LIFECYCLE_TRACE==="1";return(r,a)=>{if(!i||c++>=1e3)return;const o={};for(const[t,e]of Object.entries(a))p.has(t)&&(typeof e=="string"?o[t]=e.slice(0,160):typeof e=="number"&&Number.isFinite(e)&&(o[t]=e));try{const t=`[tool-lifecycle] ${JSON.stringify({at:Date.now(),stage:r,...o})}`;if(l){l(t);return}const e=f.join(s(),"tool-lifecycle.log");n?.file!==e&&(n=new u(e,{legacyPattern:/^tool-lifecycle-\d+\.log(?:\.1)?$/})),n.append(`${t}
|
|
2
|
+
`)}catch{}}}export{g as createToolLifecycleTrace};
|
package/dist/commands/daemon.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{assertManualStartAllowed as
|
|
1
|
+
import{assertManualStartAllowed as C,prepareManualWorkerAction as f}from"../core/management/manual.js";import{Command as i}from"commander";import s from"chalk";import d from"node:fs";import c from"node:path";import{randomUUID as k}from"node:crypto";import{getLogDir as a,getRuntimeStatePath as $}from"../core/paths.js";import{ensureDir as g,readJsonFile as A}from"../core/fs.js";import{isProcessAlive as v,readPidFile as w,removePidFile as h}from"../core/process.js";import{ACA_WORKER_INSTANCE_ENV as E,readProcessStartTicks as R}from"../core/process-identity.js";import{assertNoWorkerInstances as I,findWorkerInstances as p,sameWorkerInstance as u}from"../core/worker-instances.js";import{applyRuntimePathOptions as l}from"../core/runtime-options.js";import{spawnLoggedProcess as _}from"../core/logging/rotating-log.js";const x=3e4;function Q(){return new i("daemon").description("Run aca as a background daemon service").addCommand(m(new i("start").description("Start aca daemon in the background")).allowUnknownOption(!0).action(async o=>{l(o),C(),I();const e=w();if(process.platform!=="linux"&&e&&v(e)){console.log(`Daemon is already running (PID ${e}).`),process.exitCode=1;return}const n=await P(D("start"));console.log(`Daemon started (PID ${n.pid})`),S()})).addCommand(m(new i("stop").description("Stop the running aca daemon")).action(async o=>{l(o),await f();const e=p();if(!e.length){console.log("当前运行目录没有存活的 Worker。");return}await y(e)?console.log(`Worker 已停止:${e.map(n=>n.pid).join(", ")}`):process.exitCode=1})).addCommand(m(new i("status").description("Show daemon status")).action(o=>{l(o);const e=A($()),n=p(),t=w();if(n.length){console.log(s.green("● Daemon is running")),console.log(` PID: ${n.map(r=>r.pid).join(", ")}`),n.length>1&&console.log(" 检测到重复 Worker;daemon restart 会先停止该运行目录下的全部已确认实例。"),n.some(r=>r.pid===t)||console.log(" PID 文件缺失或失效,已从存活进程恢复实例清单。"),n.some(r=>r.pid===e?.pid)&&(e?.phase&&console.log(` Phase: ${e.phase}`),e?.startupStage&&console.log(` Stage: ${e.startupStage}`));return}t?(console.log(s.red("● Daemon is not running (stale PID file)")),h(t)):console.log(s.red("● Daemon is not running")),process.exitCode=1})).addCommand(m(new i("logs").description("Show daemon logs")).option("-n, --lines <count>","number of lines to show","50").action(o=>{l(o);const e=Number.parseInt(o.lines,10)||50,n=O();if(!n){console.log(`No log files found in ${a()}`),process.exitCode=1;return}const t=d.readFileSync(n,"utf8").trimEnd().split(`
|
|
2
2
|
`);console.log(s.dim(`--- ${n} (last ${e} lines) ---`)),console.log(t.slice(-e).join(`
|
|
3
|
-
`))})).addCommand(
|
|
3
|
+
`))})).addCommand(m(new i("restart").description("Restart the aca daemon")).allowUnknownOption(!0).action(async o=>{if(l(o),await f(),!await y(p())){process.exitCode=1;return}I();const e=await P(D("restart"));console.log(`Daemon started (PID ${e.pid})`),S()}))}function m(o){return o.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")}function D(o){const e=process.argv.findIndex((t,r)=>r>=2&&t==="daemon"),n=process.argv.findIndex((t,r)=>r>e&&t===o);return n>=0?process.argv.slice(n+1):[]}async function P(o){const e=W();return g(a()),_({command:e.command,args:e.prefixArgs},{command:e.command,args:[...e.prefixArgs,"start",...o],file:c.join(a(),"daemon-stderr.log"),stdout:!1,legacyPattern:"^daemon-stderr-\\d{4}-\\d{2}-\\d{2}\\.log$"},{...process.env,[E]:k()})}function W(){if(process.env.ACA_SINGLE_FILE_WORKER==="1")return{command:process.execPath,prefixArgs:[]};const o=process.argv[1];if(!o)throw new Error("Unable to resolve the current ACA CLI entrypoint");return{command:process.execPath,prefixArgs:[c.resolve(o)]}}function S(){const o=N();console.log(`Use ${s.yellow(`${o} daemon status`)} to check status`),console.log(`Use ${s.yellow(`${o} daemon stop`)} to stop`),console.log(`Use ${s.yellow(`${o} daemon logs`)} to view logs`)}function N(){if(process.env.ACA_SINGLE_FILE_WORKER==="1")return process.execPath;const o=c.basename(process.argv[1]||"");return/worker-cli|aica/i.test(o)?"aica":"aca"}function O(){g(a());const o=c.join(a(),"worker.log");return d.existsSync(o)?o:d.readdirSync(a()).filter(n=>/^\d{4}-\d{2}-\d{2}\.log$/.test(n)).map(n=>c.join(a(),n)).sort().at(-1)??null}async function U(o,e){const n=Date.now();for(;Date.now()-n<e;){if(!u(o))return!0;await new Promise(t=>setTimeout(t,100))}return!u(o)}async function L(o,e=x,n){const t=n||{pid:o,startTicks:R(o)};if(!u(t))return!0;try{process.kill(o,"SIGTERM")}catch(r){if(r.code!=="ESRCH")throw r}return U(t,e)}async function y(o,e=x){return(await Promise.all(o.map(async t=>{const r=await L(t.pid,e,t);return r?h(t.pid):console.error(`Worker PID ${t.pid} 未在 ${e}ms 内退出,已中止重启,请检查该实例的任务和日志。`),r}))).every(Boolean)}export{Q as createDaemonCommand,S as printStartTips,P as spawnDaemon,L as stopDaemonProcess,y as stopWorkerInstances};
|
package/dist/commands/start.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{openCodeAuthManager as N}from"../core/opencode/worker.js";import{mimoAuthManager as L}from"../core/mimo-auth-worker.js";import{stopProviderInstaller as U}from"../core/provider-installer.js";import{startProviderUpdates as F,stopProviderUpdates as H}from"../core/provider-updates/service.js";import{activateWorkBuddyCredits as B,stopWorkBuddyCredits as K}from"../core/workbuddy-credits/worker.js";import{stopManagedClaims as V}from"../core/management/claims.js";import{workBuddyAuthManager as G}from"../core/workbuddy-auth-worker.js";import{assertManualStartAllowed as J}from"../core/management/manual.js";import{startManagementControl as q}from"../core/management/control-server.js";import{managementActivity as u}from"../core/management/activity.js";import{acquireWorkerLease as z,assertNoWorkerInstances as Q}from"../core/worker-instances.js";import{getAcaHome as X}from"../core/paths.js";import{Command as Y}from"commander";import I from"node:fs";import D from"node:os";import c from"node:path";import t from"node:process";import{randomUUID as Z}from"node:crypto";import{Logger as ee}from"../core/logger.js";import{loadCredentials as te,saveApiKeyCredential as re}from"../core/auth.js";import{getRuntimeStatePath as oe}from"../core/paths.js";import{writeJsonFile as ae}from"../core/fs.js";import{HEARTBEAT_INTERVAL_MS as ie,startHeartbeatLoop as ne}from"../core/heartbeat.js";import{startJobWorkerLoop as se}from"../core/job-worker.js";import{startFileTransferWorkerLoop as me}from"../core/file-transfer-worker.js";import{startTerminalWorker as ce}from"../core/terminal/worker.js";import{startMachineFilesystemWorkerLoop as de}from"../core/machine-filesystem-worker.js";import{cleanupOrphanedAcpProcesses as fe}from"../core/acp-orphan-cleanup.js";import{defaultAcpRuntimePool as _}from"../acp/client/acp-runtime-pool.js";import{isProcessAlive as h,readPidFile as d,writePidFile as pe,removePidFile as W}from"../core/process.js";import{applyRuntimePathOptions as x}from"../core/runtime-options.js";import{loadAcaConfig as $,updateAcaConfig as R}from"../core/aca-config.js";import{acaServerRequest as le}from"../core/aca-server-client.js";import{restoreProjectsAfterLogin as ue}from"../core/project-recovery.js";import{syncCodexProviderRuntimeConfig as he}from"../core/codex-provider-runtime-config.js";import{ACA_WORKER_INSTANCE_ENV as O,ACA_WORKER_PID_ENV as ge,ACA_WORKER_START_TICKS_ENV as we,readProcessStartTicks as ve}from"../core/process-identity.js";import{printStartTips as Ae,spawnDaemon as Ie}from"./daemon.js";import{startDesktopControl as Se}from"../core/desktop-control.js";function lt(){return new Y("start").description("Start agent service in native mode").option("--aica-home <path>","Runtime home directory (defaults to ~/.aica or AICA_HOME)").option("--aica-config <path>","Config file path (defaults to <aica-home>/config.json)").option("--aca-home <path>","Deprecated alias for --aica-home").option("--aca-config <path>","Deprecated alias for --aica-config").option("--server <url>","ACA Server URL override").option("--machine-id <id>","Machine ID override for this runtime").option("--machine-name <name>","Machine name to register (defaults to hostname)").option("--cli-types <types...>","Specify CLI types to register, `claude` or `codex`").option("--managed-start <operationId>","受管理启动:保持业务入口关闭,等待 Proxy 激活").option("--debug","enable debug output").option("--heartbeat-log","output current timestamp every 5 seconds").option("--auth <api-key>","Use a CLI API key for non-interactive authentication").option("--token <enrollment-token>","Use a one-time Web-generated token to register this machine").option("-b, --background","在后台启动 Worker").action(async e=>{if(e.background){await ke(e);return}await Pe(e)})}async function ke(e){x(e),Q();const a=d();if(t.platform!=="linux"&&a&&h(a))throw new Error(`Worker 已在后台运行,PID ${a}。`);a&&W(a);const n=Ie(ye());if(n.
|
|
1
|
+
import{openCodeAuthManager as N}from"../core/opencode/worker.js";import{mimoAuthManager as L}from"../core/mimo-auth-worker.js";import{stopProviderInstaller as U}from"../core/provider-installer.js";import{startProviderUpdates as F,stopProviderUpdates as H}from"../core/provider-updates/service.js";import{activateWorkBuddyCredits as B,stopWorkBuddyCredits as K}from"../core/workbuddy-credits/worker.js";import{stopManagedClaims as V}from"../core/management/claims.js";import{workBuddyAuthManager as G}from"../core/workbuddy-auth-worker.js";import{assertManualStartAllowed as J}from"../core/management/manual.js";import{startManagementControl as q}from"../core/management/control-server.js";import{managementActivity as u}from"../core/management/activity.js";import{acquireWorkerLease as z,assertNoWorkerInstances as Q}from"../core/worker-instances.js";import{getAcaHome as X}from"../core/paths.js";import{Command as Y}from"commander";import I from"node:fs";import D from"node:os";import c from"node:path";import t from"node:process";import{randomUUID as Z}from"node:crypto";import{Logger as ee}from"../core/logger.js";import{loadCredentials as te,saveApiKeyCredential as re}from"../core/auth.js";import{getRuntimeStatePath as oe}from"../core/paths.js";import{writeJsonFile as ae}from"../core/fs.js";import{HEARTBEAT_INTERVAL_MS as ie,startHeartbeatLoop as ne}from"../core/heartbeat.js";import{startJobWorkerLoop as se}from"../core/job-worker.js";import{startFileTransferWorkerLoop as me}from"../core/file-transfer-worker.js";import{startTerminalWorker as ce}from"../core/terminal/worker.js";import{startMachineFilesystemWorkerLoop as de}from"../core/machine-filesystem-worker.js";import{cleanupOrphanedAcpProcesses as fe}from"../core/acp-orphan-cleanup.js";import{defaultAcpRuntimePool as _}from"../acp/client/acp-runtime-pool.js";import{isProcessAlive as h,readPidFile as d,writePidFile as pe,removePidFile as W}from"../core/process.js";import{applyRuntimePathOptions as x}from"../core/runtime-options.js";import{loadAcaConfig as $,updateAcaConfig as R}from"../core/aca-config.js";import{acaServerRequest as le}from"../core/aca-server-client.js";import{restoreProjectsAfterLogin as ue}from"../core/project-recovery.js";import{syncCodexProviderRuntimeConfig as he}from"../core/codex-provider-runtime-config.js";import{ACA_WORKER_INSTANCE_ENV as O,ACA_WORKER_PID_ENV as ge,ACA_WORKER_START_TICKS_ENV as we,readProcessStartTicks as ve}from"../core/process-identity.js";import{printStartTips as Ae,spawnDaemon as Ie}from"./daemon.js";import{startDesktopControl as Se}from"../core/desktop-control.js";function lt(){return new Y("start").description("Start agent service in native mode").option("--aica-home <path>","Runtime home directory (defaults to ~/.aica or AICA_HOME)").option("--aica-config <path>","Config file path (defaults to <aica-home>/config.json)").option("--aca-home <path>","Deprecated alias for --aica-home").option("--aca-config <path>","Deprecated alias for --aica-config").option("--server <url>","ACA Server URL override").option("--machine-id <id>","Machine ID override for this runtime").option("--machine-name <name>","Machine name to register (defaults to hostname)").option("--cli-types <types...>","Specify CLI types to register, `claude` or `codex`").option("--managed-start <operationId>","受管理启动:保持业务入口关闭,等待 Proxy 激活").option("--debug","enable debug output").option("--heartbeat-log","output current timestamp every 5 seconds").option("--auth <api-key>","Use a CLI API key for non-interactive authentication").option("--token <enrollment-token>","Use a one-time Web-generated token to register this machine").option("-b, --background","在后台启动 Worker").action(async e=>{if(e.background){await ke(e);return}await Pe(e)})}async function ke(e){x(e),Q();const a=d();if(t.platform!=="linux"&&a&&h(a))throw new Error(`Worker 已在后台运行,PID ${a}。`);a&&W(a);const n=await Ie(ye());if(!n.pid)throw new Error("后台 Worker 启动失败:未获得进程 PID。");if(!await Ce(n.pid,3e3)&&!h(n.pid))throw new Error(`后台 Worker 启动失败,请检查 ${c.join(t.env.AICA_HOME||t.env.ACA_HOME||c.join(D.homedir(),".aica"),"logs")}。`);console.log(`Worker 已在后台启动,PID ${n.pid}。`),Ae()}function ye(){const e=t.argv.findIndex((a,n)=>n>=2&&a==="start");return e<0?[]:t.argv.slice(e+1).filter(a=>a!=="--background"&&a!=="-b")}async function Ce(e,a){const n=Date.now();for(;Date.now()-n<a;){if(d()===e)return!0;if(!h(e))return!1;await new Promise(o=>setTimeout(o,50))}return d()===e}async function Pe(e){x(e);const a=await z();try{await Ee(e)}finally{a()}}async function Ee(e){if(e.managedStart||J(),e.managedStart){if(t.platform!=="linux")throw new Error("当前平台尚未支持受管理启动");if(!t.env.AICA_MANAGER_ID)throw new Error("受管理启动缺少管理实例");t.env.AICA_UPDATE_OPERATION=e.managedStart}const a=t.env[O]||Z(),n=ve(t.pid)||"";t.env[O]=a,t.env[ge]=String(t.pid),t.env[we]=n;const o=new ee("start",e.debug?"debug":"info"),g=$(),S={...e.server?.trim()?{serverUrl:e.server.trim()}:{},...e.machineId?{machineId:e.machineId.trim()}:{},...e.machineName?{machineName:e.machineName.trim()}:{}};let m=Object.keys(S).length>0?R(S):g;const f=e.machineName?.trim()||m.machineName||D.hostname();if(e.token?.trim()){const r=await le("POST","/api/auth/machine-enroll",{token:e.token.trim(),machineId:m.machineId,machineName:f},{serverUrl:m.serverUrl});m=R({machineId:r.machineId,machineName:f,token:r.token,username:r.username}),o.info(`Machine enrollment completed for user ${r.username}`);try{const i=await ue();i.restored>0&&o.info(`restored ${i.restored} local project(s) after machine enrollment`),i.unavailable>0&&o.warn(`skipped ${i.unavailable} unavailable project path(s) during machine enrollment recovery`),m=$()}catch(i){o.warn(`project recovery after machine enrollment failed: ${i instanceof Error?i.message:String(i)}`)}}const M=e.auth?re(e.auth,f):te(),l=d();if(t.platform!=="linux"&&l&&l!==t.pid&&h(l))throw new Error(`Worker 已在运行,PID ${l}`);pe(t.pid),j({pid:t.pid,workerInstanceId:a,workerStartTicks:n,phase:"running",startupStage:"local-compatible",machineId:m.machineId||M?.machine?.machineId||"local-machine",machineName:f,cliTypes:e.cliTypes??be(),startedAt:new Date().toISOString(),heartbeatIntervalMs:ie,issues:[{severity:"info",message:"aca is running in aca-server compatibility mode; ACP execution happens on this machine."}]}),o.info(`Starting aca local-compatible service on machine ${f}`),o.info(`PID ${t.pid}`);const w=await fe();w.terminated>0&&o.warn(`terminated ${w.terminated} orphaned ACP process(es): ${w.pids.join(",")}`),he().then(r=>o.info(r?`Codex Provider runtime config loaded revision=${r.revision}`:"Codex Provider runtime config is not configured")).catch(r=>o.warn(`Codex Provider runtime config sync failed: ${r instanceof Error?r.message:String(r)}`));let k=!1,v,y,C,P,E;const p=async r=>{if(k)return;k=!0,V(),o.info("Shutting down"),v&&clearInterval(v),C?.stop(),E?.stop(),P?.stop(),await H(),await U(),await K(),await G.stop(),await N.stop(),await L.stop(),await y?.stop().catch(s=>o.warn(`job worker shutdown failed: ${s instanceof Error?s.message:String(s)}`));const i=_.stats();await _.disposeAll().catch(s=>o.warn(`ACP runtime shutdown failed: ${s instanceof Error?s.message:String(s)}`)),o.info(`ACP runtimes stopped total=${i.total} inUse=${i.inUse} idle=${i.idle}`),d()===t.pid&&(j({pid:t.pid,phase:"stopped",stoppedAt:new Date().toISOString(),issues:[]}),W(t.pid)),t.exit(r)},b=r=>{if(!u.stopping&&d()===t.pid){const i=c.join(X(),"management");I.mkdirSync(i,{recursive:!0,mode:448}),I.writeFileSync(c.join(i,"manual-stop.json"),JSON.stringify({workerInstanceId:a,at:Date.now()}),{mode:384})}p(r)};t.once("SIGINT",()=>b(130)),t.once("SIGTERM",()=>b(0)),t.once("uncaughtException",r=>{o.error(`uncaught exception: ${r.stack||r.message}`),p(1)}),t.once("unhandledRejection",r=>{const i=r instanceof Error?r.stack||r.message:String(r);o.error(`unhandled rejection: ${i}`),p(1)}),e.heartbeatLog&&setInterval(()=>o.info(`heartbeat: ${new Date().toISOString()}`),5e3);let T=!1;const A=()=>{T||(T=!0,F(),B(),y=se(o),C=me(o),E=de(o),P=ce(o))};try{await q(a,()=>p(0),A)}catch(r){if(e.managedStart||r instanceof Error&&r.message.includes("已有 Worker 管理实例"))throw r;u.paused=!1,o.warn(`可选管理通道不可用: ${r instanceof Error?r.message:String(r)}`)}v=ne(o),t.env.ACA_DESKTOP_CHILD==="1"&&t.env.ACA_DESKTOP_STAGED==="1"&&(u.paused=!0),u.paused||A(),Se(()=>p(0),A),await new Promise(()=>{})}function be(){return["codex","claude"].filter(e=>Te(e))}function Te(e){const a=t.env.PATH||"";for(const n of a.split(c.delimiter))try{const o=t.platform==="win32"?["",".exe",".cmd",".bat"]:[""];if(n&&o.some(g=>I.existsSync(c.join(n,e+g))))return!0}catch{}return!1}function j(e){ae(oe(),e)}export{lt as createStartCommand};
|
package/dist/core/logger.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
`)}}export{
|
|
1
|
+
import n from"node:path";import{getLogDir as p}from"./paths.js";import{RotatingLog as u}from"./logging/rotating-log.js";const i={debug:10,info:20,warn:30,error:40},s=new Map;class h{scope;minLevel;output;constructor(t,o="info"){this.scope=t,this.minLevel=o;const r=n.join(p(),"worker.log");let e=s.get(r);e||(e=new u(r,{legacyPattern:/^\d{4}-\d{2}-\d{2}\.log$/}),s.set(r,e)),this.output=e}debug(t){this.write("debug",t)}info(t){this.write("info",t)}warn(t){this.write("warn",t)}error(t){this.write("error",t)}write(t,o){const r=`${new Date().toISOString()} [${t.toUpperCase()}] [${this.scope}] ${o}`;this.output.append(`${r}
|
|
2
|
+
`),i[t]>=i[this.minLevel]&&(t==="error"?process.stderr:process.stdout).write(`${r}
|
|
3
|
+
`)}}export{h as Logger};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import o from"node:fs";import m from"node:path";import{Writable as u}from"node:stream";import{spawn as p}from"node:child_process";const x=10*1024*1024,w=7,y="--internal-worker-log-collector";class S{file;options;maxBytes;maxFiles;initialized=!1;retryAt=0;constructor(e,t={}){if(this.file=e,this.options=t,this.maxBytes=t.maxBytes??x,this.maxFiles=t.maxFiles??w,!Number.isSafeInteger(this.maxBytes)||this.maxBytes<1||!Number.isSafeInteger(this.maxFiles)||this.maxFiles<1)throw new Error("日志大小和文件数量必须是正整数");this.append("")}append(e){if(Date.now()<this.retryAt)return!1;try{return this.initialize(),this.writeBuffer(Buffer.isBuffer(e)?e:Buffer.from(e)),!0}catch(t){this.initialized=!1,this.retryAt=Date.now()+3e4;try{o.writeSync(2,`Worker 日志写入失败,30 秒后重试:${String(t)}
|
|
2
|
+
`)}catch{}return!1}}initialize(){if(this.initialized)return;const e=m.dirname(this.file);o.mkdirSync(e,{recursive:!0});const t=m.basename(this.file);for(const i of o.readdirSync(e)){if(!i.startsWith(`${t}.`))continue;const s=i.slice(t.length+1);/^\d+$/.test(s)&&Number(s)>=this.maxFiles&&o.rmSync(m.join(e,i),{force:!0})}const r=this.options.legacyPattern?o.readdirSync(e,{withFileTypes:!0}).filter(i=>i.isFile()&&this.options.legacyPattern.test(i.name)).map(i=>({file:m.join(e,i.name),at:o.statSync(m.join(e,i.name)).mtimeMs})).sort((i,s)=>i.at-s.at||i.file.localeCompare(s.file)):[];for(let i=0;i<this.maxFiles;i++)this.limitExisting(this.archive(i));for(const i of r.slice(-this.maxFiles)){const s=o.statSync(i.file).size;this.writeBuffer(this.readTail(i.file,Math.min(s,this.maxBytes)))}for(const i of r)o.unlinkSync(i.file);this.initialized=!0}archive(e){return e?`${this.file}.${e}`:this.file}readTail(e,t){const r=o.openSync(e,"r");try{const i=Math.max(0,o.fstatSync(r).size-t),s=Buffer.alloc(t);let n=0;for(;n<t;){const l=o.readSync(r,s,n,t-n,i+n);if(!l)break;n+=l}return s.subarray(0,n)}finally{o.closeSync(r)}}limitExisting(e){try{o.statSync(e).size>this.maxBytes&&o.writeFileSync(e,this.readTail(e,this.maxBytes),{mode:384})}catch(t){if(t.code!=="ENOENT")throw t}}size(){try{return o.statSync(this.file).size}catch(e){if(e.code==="ENOENT")return 0;throw e}}rotate(){o.rmSync(this.archive(this.maxFiles-1),{force:!0});for(let e=this.maxFiles-2;e>=0;e--)try{o.renameSync(this.archive(e),this.archive(e+1))}catch(t){if(t.code!=="ENOENT")throw t}}writeBuffer(e){let t=this.size();t&&t+e.length>this.maxBytes&&(this.rotate(),t=0);for(let r=0;r<e.length;){t>=this.maxBytes&&(this.rotate(),t=0);const i=Math.min(e.length,r+this.maxBytes-t);o.appendFileSync(this.file,e.subarray(r,i),{mode:384}),t+=i-r,r=i}}}function g(c,e){const t=new S(c,e);return new u({write(r,i,s){t.append(r),s()}})}async function R(c,e,t=process.env){const r=new Set(["ACA_WORKER_INSTANCE_ID","ACA_WORKER_PID","ACA_WORKER_START_TICKS","ACA_ACP_WORKER_INSTANCE_ID","AICA_MANAGER_ID"]),i=Object.fromEntries(Object.entries(t).filter(([n])=>!r.has(n)&&!n.startsWith("ACA_ACP_RUNTIME_"))),s=p(c.command,[...c.args,y],{detached:!0,windowsHide:!0,env:i,stdio:["ignore","ignore","ignore","ipc"]});return new Promise((n,l)=>{let f=!1;const d=setTimeout(()=>h(new Error("日志收集进程启动超时")),15e3),h=a=>{f||(f=!0,clearTimeout(d),s.connected&&s.disconnect(),s.unref(),l(a))};s.once("error",h),s.once("exit",a=>h(new Error(`日志收集进程退出:${a}`))),s.once("message",a=>{if(clearTimeout(d),!a.pid){h(new Error(a.error||"Worker 启动失败"));return}f=!0,s.removeAllListeners("exit"),s.disconnect(),s.unref(),n({pid:a.pid})}),s.send({...e,env:t},a=>{a&&h(a)})})}async function I(c=process.argv){if(c.at(-1)!==y)return!1;const e=await new Promise(n=>process.once("message",n)),t=g(e.file,{legacyPattern:e.legacyPattern?new RegExp(e.legacyPattern):void 0});let r;r=p(e.command,e.args,{windowsHide:!0,env:e.env??process.env,stdio:["ignore",e.stdout===!1?"ignore":"pipe","pipe"]}),r.stdout?.pipe(t,{end:!1}),r.stderr.pipe(t,{end:!1});const i=()=>{r.kill("SIGINT")},s=()=>{r.kill("SIGTERM")};return process.on("SIGINT",i),process.on("SIGTERM",s),r.once("spawn",()=>process.send?.({pid:r.pid},()=>{})),r.once("error",n=>{t.write(`Worker 启动失败:${n.message}
|
|
3
|
+
`),process.send?.({error:n.message},()=>{})}),await new Promise(n=>r.once("close",(l,f)=>{process.exitCode=l??(f?1:0),n()})),t.end(),process.off("SIGINT",i),process.off("SIGTERM",s),!0}export{y as LOG_COLLECTOR_ARGUMENT,S as RotatingLog,x as WORKER_LOG_MAX_BYTES,w as WORKER_LOG_MAX_FILES,g as createLogSink,I as handleLogCollector,R as spawnLoggedProcess};
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const o="0.1.
|
|
1
|
+
const o="0.1.96";export{o as AICA_VERSION};
|
package/dist/worker-cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as m}from"commander";import a from"node:path";import{createStartCommand as n}from"./commands/start.js";import{createDaemonCommand as t}from"./commands/daemon.js";import{createWorkerAuthCommand as
|
|
2
|
+
import{Command as m}from"commander";import a from"node:path";import{createStartCommand as n}from"./commands/start.js";import{createDaemonCommand as t}from"./commands/daemon.js";import{createWorkerAuthCommand as i}from"./commands/worker-auth.js";import{createWorkerCodexCommand as c}from"./commands/worker-codex.js";import{createWorkerProjectCommand as s}from"./commands/worker-project.js";import{DEFAULT_ACA_SERVER_URL as d}from"./core/aca-config.js";import{AICA_VERSION as p}from"./version.js";import{applyToolEnvironment as C}from"./core/tool-environment.js";import{checkDesktopWorker as f}from"./core/desktop-check.js";import{handleLogCollector as A}from"./core/logging/rotating-log.js";process.env.ACA_DEFAULT_SERVER_URL||=d;async function k(r=process.argv){if(await A(r))return;C();const o=new m;o.name("aica").description("AICA remote Agent worker").version(p).enablePositionalOptions(),o.addCommand(n()),o.addCommand(t()),o.addCommand(i()),o.addCommand(s()),o.addCommand(c()),o.addCommand(new m("desktop-check").description("检查桌面运行环境,不连接 Server").action(f)),await o.parseAsync(r)}const l=process.argv[1]||"",e=a.basename(l).replace(/\.(?:js|ts|cjs|mjs)$/i,"");(e==="worker-cli"||e==="aica"||e==="aca")&&k().catch(r=>{const o=r instanceof Error?r.message:String(r);console.error(o),process.exitCode=1});export{k as runWorkerCli};
|