@messenger-agent/client 0.38.0-alpha.1 → 0.38.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/supervisor.js +1 -1
- package/package.json +5 -5
package/dist/supervisor.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawn as
|
|
1
|
+
import{spawn as x}from"node:child_process";import{randomUUID as k}from"node:crypto";import{createRequire as $}from"node:module";import{dirname as g,join as p,resolve as m}from"node:path";import{parse as b}from"yaml";import{readFile as C,unlink as P}from"node:fs/promises";import{readAgentServer as y,readClientPath as v,readUpgradeChannel as I,writeClientPath as R}from"./config-file.js";import{readControlSocketPath as L,startControlServer as N}from"./control.js";import{MaintenanceScheduler as q}from"./maintenance.js";import{activateRuntime as O,currentBundledSkillsDir as F,currentPackageVersion as _,defaultAgentHomes as U,installRuntime as T,prepareRuntime as j,rollbackRuntime as S,syncBundledSkills as D}from"./runtime.js";import{launchdLabel as G,serviceCommandsForConfig as W,serviceName as B,systemdUserEnvironment as E}from"./service.js";import{legacyLaunchdLabel as H,legacyServiceName as K}from"./identity.js";import{legacyCodingAgentPaths as M}from"./paths.js";import{runCommand as d}from"./exec.js";import{AutoUpgradeScheduler as Y}from"./auto-upgrade.js";import{migrateLegacyClient as V}from"./migration.js";import{scheduleMigrationHandoff as X,shouldAttemptAutomaticMigration as z}from"./install.js";import{isAgentActivityResponse as J}from"@messenger-agent/shared/agent-activity";import{isAgentWorkspacesReloadResponse as Q}from"@messenger-agent/shared/agent-workspaces";const A=$(import.meta.url);function Z(){return[{name:"codex",entry:A.resolve("@messenger-agent/codex-agent")},{name:"claude",entry:A.resolve("@messenger-agent/claude-agent")},{name:"workspace",entry:A.resolve("@messenger-agent/messenger-agent")}]}function tt(r,t){let e=r;for(const s of t){if(!e||typeof e!="object"||Array.isArray(e))return;e=e[s]}return e}async function et(r){const t=b(await C(r,"utf8")),e=tt(t,["workspaces"]);if(Array.isArray(e)){const s=e.find(i=>!!i&&typeof i=="object"&&!Array.isArray(i)&&typeof i.path=="string");if(typeof s?.path=="string"&&s.path.trim())return s.path}return g(r)}class rt{options;stopping=!1;running;restartBaseMs;restartMaxMs;workspaceReloadTimeoutMs;constructor(t){this.options=t,this.running=(t.agents??Z()).map(e=>({definition:e,restartAttempts:0})),this.restartBaseMs=t.restartBaseMs??1e3,this.restartMaxMs=t.restartMaxMs??3e4,this.workspaceReloadTimeoutMs=t.workspaceReloadTimeoutMs??5e3}start(){for(const t of this.running)this.startAgent(t)}async stop(){this.stopping=!0;for(const t of this.running)t.restartTimer&&clearTimeout(t.restartTimer),t.process?.kill("SIGTERM");await Promise.all(this.running.map(t=>t.process).filter(t=>!!t&&t.exitCode===null&&!t.killed).map(t=>new Promise(e=>{const s=setTimeout(()=>{t.kill("SIGKILL"),e()},8e3);t.once("exit",()=>{clearTimeout(s),e()})})))}restartAgent(t){const e=this.running.find(({definition:s})=>s.name===t);return e?(e.restartPromise||(e.restartPromise=this.restartAgentProcess(e).finally(()=>{e.restartPromise=void 0})),e.restartPromise):Promise.reject(new Error(`Agent is not managed by this client: ${t}`))}async activityStatus(t=1e3){const[e,s]=await Promise.all([this.agentActivityStatus("codex",t),this.agentActivityStatus("claude",t)]),i=[e,s].filter(a=>a.available);return{active:i.reduce((a,o)=>a+o.active,0),waiting:i.reduce((a,o)=>a+o.waiting,0),agents:{codex:e,claude:s}}}agentActivityStatus(t,e){const s=this.running.find(({definition:i})=>i.name===t)?.process;return!s||!s.connected||!s.send?Promise.resolve({available:!1,error:`${t} agent is not connected`}):new Promise(i=>{const a=k(),o={type:"client.activity.request",requestId:a};let c=!1;const l=n=>{c||(c=!0,clearTimeout(h),s.off("message",u),i(n))},u=n=>{!J(n)||n.requestId!==a||n.agent!==t||l({available:!0,...n.snapshot})},h=setTimeout(()=>l({available:!1,error:`${t} agent did not respond`}),e);s.on("message",u),s.send(o,n=>{n&&l({available:!1,error:n.message})})})}async restartAgentProcess(t){t.restartTimer&&(clearTimeout(t.restartTimer),t.restartTimer=void 0);const e=t.process;if(e&&e.exitCode===null&&!e.killed&&(e.kill("SIGTERM"),await nt(e)),this.stopping)throw new Error("Client service is stopping");t.restartAttempts=0,this.startAgent(t)}async reloadAgentWorkspaces(){await Promise.all([this.requestAgentWorkspacesReload("codex"),this.requestAgentWorkspacesReload("claude")])}requestAgentWorkspacesReload(t){const e=this.running.find(({definition:s})=>s.name===t)?.process;return!e||!e.connected||!e.send?Promise.reject(new Error(`${t} agent is not connected`)):new Promise((s,i)=>{const a=k(),o={type:"client.workspaces.reload.request",requestId:a};let c=!1;const l=n=>{c||(c=!0,clearTimeout(h),e.off("message",u),n?i(n):s())},u=n=>{if(!(!Q(n)||n.requestId!==a||n.agent!==t)){if(!n.success){l(new Error(`${t} agent failed to reload workspaces: ${n.error??"unknown error"}`));return}console.log(`[client] reloaded ${t}-agent workspaces count=${n.workspaceCount??0}`),l()}},h=setTimeout(()=>l(new Error(`${t} agent did not reload workspaces`)),this.workspaceReloadTimeoutMs);e.on("message",u),e.send(o,n=>{n&&l(n)})})}startAgent(t){const e={...process.env,AGENT_CONFIG_PATH:this.options.configPath};t.definition.name==="workspace"&&(delete e.OPENAI_API_KEY,delete e.CODEX_API_KEY,delete e.ANTHROPIC_API_KEY,delete e.ANTHROPIC_AUTH_TOKEN);const s=(this.options.spawnProcess??x)(process.execPath,[t.definition.entry],{cwd:this.options.workspacePath,env:e,stdio:["inherit","inherit","inherit","ipc"]});t.process=s,t.definition.name==="workspace"&&s.on("message",i=>{i&&typeof i=="object"&&"type"in i&&i.type==="client.workspaces.changed"&&this.reloadAgentWorkspaces().catch(a=>{console.error("[client] failed to reload agents after workspace configuration changed",a)})}),console.log(`[client] started ${t.definition.name}-agent pid=${s.pid}`),s.once("exit",(i,a)=>{if(t.process=void 0,this.stopping||t.restartPromise)return;const o=Math.min(this.restartBaseMs*2**t.restartAttempts,this.restartMaxMs);t.restartAttempts+=1,console.error(`[client] ${t.definition.name}-agent exited with code=${i??"null"} signal=${a??"null"}; restarting in ${o}ms`),t.restartTimer=setTimeout(()=>{t.restartTimer=void 0,this.startAgent(t)},o)})}}async function Mt(r){if(await st(r))return;await D(F(),U());const t=await et(r),e=new rt({configPath:r,workspacePath:t}),s=await L(r),i=new q({statePath:p(g(s),"maintenance.json"),getActivity:()=>e.activityStatus(),execute:(l,u)=>at(l,r,e,u)});await i.start();const a=new Y({statePath:p(g(s),"auto-upgrade.json"),maintenance:i,getChannel:()=>I(r),prepareUpgrade:async l=>j({version:l,configPath:r,server:await y(r),path:await v(r)})});await a.start();const o=await N(s,{restartAgent:l=>e.restartAgent(l),getActivity:()=>e.activityStatus(),maintenance:i});e.start();const c=async()=>{a.stop(),i.stop(),await o.close(),await e.stop(),process.exit(0)};process.once("SIGINT",()=>{c()}),process.once("SIGTERM",()=>{c()})}async function st(r,t={}){const e=M();if(m(r)!==m(e.configPath))return!1;const s=await(t.currentVersion??_)();if(!await(t.shouldAttempt??z)(e.rootDir,s))return!1;let i;try{const a=await(t.migrate??V)();if(!a.migrated)return!1;const o=await(t.readPath??v)(a.paths.configPath),c=await(t.readServer??y)(a.paths.configPath);return i=await(t.install??T)({version:s,configPath:a.paths.configPath,runtimeDir:a.paths.runtimeDir,binDir:a.paths.binDir,path:o,server:c}),await(t.handoff??X)(a,i,a.paths.configPath,o),!0}catch(a){return i&&await(t.rollback??S)(i).catch(()=>{}),console.error(`[client] automatic legacy migration failed: ${a instanceof Error?a.message:String(a)}`),!1}}async function at(r,t,e,s){if(r.type==="upgrade"){if(r.path&&await R(t,r.path),r.prepared&&r.prepared.version!==r.version)throw new Error(`Prepared runtime ${r.prepared.version} does not match upgrade ${r.version}`);if(r.prepared&&m(r.prepared.configPath)!==m(t))throw new Error("Prepared runtime does not match the active client configuration");const i=r.prepared?await O(r.prepared):await T({version:r.version,configPath:t,server:await y(t),path:r.path??await v(t)});await s("restarting");try{await w(f(t).restart)}catch(a){throw await S(i),await w(f(t).restart).catch(()=>{}),a}return}if(r.type==="restart"&&r.agent){await e.restartAgent(r.agent);return}if(r.type==="restart"){await s("restarting"),await w(f(t).restart);return}if(r.type==="stop"){await s("stopping"),await w(f(t).stop);return}await s("stopping"),await it(t)}function f(r){return W(r)}async function w(r){const t=process.getuid?.(),e=await d("/bin/sh",["-lc",r],{allowFailure:!0,env:process.platform==="linux"&&t!==void 0?E(t):void 0});if(e.status!==0)throw new Error(e.stderr||e.stdout||`Service command failed: ${r}`)}async function it(r){const t=process.env.HOME??"",e=r===M().configPath,s=e?K:B,i=e?H:G;if(process.platform==="linux"){const a=process.getuid?.(),o=a===void 0?void 0:E(a);await d("systemctl",["--user","disable",`${s}.service`],{allowFailure:!0,env:o}),await P(p(t,".config","systemd","user",`${s}.service`)).catch(c=>{if(c.code!=="ENOENT")throw c}),await d("systemctl",["--user","daemon-reload"],{allowFailure:!0,env:o}),await d("systemctl",["--user","stop",`${s}.service`],{allowFailure:!0,env:o});return}if(process.platform==="darwin"){const a=process.getuid?.();if(a===void 0)throw new Error("Unable to determine current uid for launchctl");const o=p(t,"Library","LaunchAgents",`${i}.plist`);await P(o).catch(c=>{if(c.code!=="ENOENT")throw c}),await d("launchctl",["bootout",`gui/${a}/${i}`],{allowFailure:!0});return}throw new Error("Only Linux and macOS are supported")}function nt(r){return new Promise(t=>{const e=setTimeout(()=>{r.kill("SIGKILL")},8e3);r.once("exit",()=>{clearTimeout(e),t()})})}export{rt as AgentSupervisor,st as migrateLegacyServiceAtStartup,et as readWorkspacePathFromConfig,Z as resolveAgentEntries,Mt as runSupervisor};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@messenger-agent/client",
|
|
3
|
-
"version": "0.38.0-alpha.
|
|
3
|
+
"version": "0.38.0-alpha.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"cac": "^7.0.0",
|
|
23
23
|
"yaml": "^2.9.0",
|
|
24
|
-
"@messenger-agent/
|
|
25
|
-
"@messenger-agent/
|
|
26
|
-
"@messenger-agent/
|
|
27
|
-
"@messenger-agent/
|
|
24
|
+
"@messenger-agent/claude-agent": "0.38.0-alpha.3",
|
|
25
|
+
"@messenger-agent/messenger-agent": "0.38.0-alpha.3",
|
|
26
|
+
"@messenger-agent/codex-agent": "0.38.0-alpha.3",
|
|
27
|
+
"@messenger-agent/shared": "0.38.0-alpha.3"
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"build": "rm -rf dist && tsc -p tsconfig.json && node ../../scripts/copy-client-assets.mjs && chmod +x dist/index.js",
|