@messenger-agent/client 0.33.0-alpha.8 → 0.33.0

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/install.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { type RuntimeInstallResult } from "./runtime.js";
2
- import { type ServiceInstallResult } from "./service.js";
1
+ import { rollbackRuntime, type RuntimeInstallResult } from "./runtime.js";
2
+ import { startLegacyService, uninstallService, type ServiceInstallResult } from "./service.js";
3
3
  import { type InstallArgs } from "./args.js";
4
4
  import { runCommand } from "./exec.js";
5
5
  import { type ClientMigrationResult } from "./migration.js";
@@ -11,6 +11,7 @@ export type InstallResult = {
11
11
  service: ServiceInstallResult;
12
12
  };
13
13
  export declare function activateMigratedService(migration: ClientMigrationResult, runtime: RuntimeInstallResult, configPath: string, path?: string): Promise<boolean>;
14
+ declare function activateMigratedServiceInline(migration: ClientMigrationResult, runtime: RuntimeInstallResult, configPath: string, path?: string): Promise<void>;
14
15
  export declare function scheduleDarwinMigrationHandoff(migration: ClientMigrationResult, runtime: RuntimeInstallResult, configPath: string, path?: string, dependencies?: {
15
16
  run?: typeof runCommand;
16
17
  wait?: (milliseconds: number) => Promise<unknown>;
@@ -23,7 +24,14 @@ export declare function scheduleMigrationHandoff(migration: ClientMigrationResul
23
24
  platform?: NodeJS.Platform;
24
25
  }): Promise<boolean>;
25
26
  export declare function shouldAttemptAutomaticMigration(rootDir: string, version: string): Promise<boolean>;
26
- export declare function completeMigrationHandoff(handoffPath: string): Promise<void>;
27
+ export declare function completeMigrationHandoff(handoffPath: string, dependencies?: {
28
+ activate?: typeof activateMigratedServiceInline;
29
+ rollback?: typeof rollbackRuntime;
30
+ uninstall?: typeof uninstallService;
31
+ startLegacy?: typeof startLegacyService;
32
+ run?: typeof runCommand;
33
+ activeHelperLabel?: string;
34
+ }): Promise<void>;
27
35
  type ResolvedInstallArgs = Omit<InstallArgs, "tunnelId" | "token" | "workspace" | "workspaceId" | "workspaceName"> & {
28
36
  tunnelId: string;
29
37
  token: string;
package/dist/install.js CHANGED
@@ -1,2 +1,3 @@
1
- import{randomUUID as N}from"node:crypto";import{mkdir as x,readFile as T,realpath as $,rename as O,stat as _,writeFile as L}from"node:fs/promises";import{join as y}from"node:path";import{setTimeout as C}from"node:timers/promises";import{normalizeAgentServer as H}from"@messenger-agent/shared/agent-config";import{readConfigYaml as v,updateClientConfig as j,writeUpgradeChannel as R}from"./config-file.js";import{installRuntime as W,rollbackRuntime as g}from"./runtime.js";import{installService as k,startLegacyService as P,stopLegacyService as A,uninstallLegacyService as S,uninstallService as D}from"./service.js";import{UsageError as w}from"./args.js";import{defaultWorkspacePath as E,legacyCodingAgentPaths as U,messengerAgentPaths as G}from"./paths.js";import{runCommand as q}from"./exec.js";import{completeLegacyMigration as I,migrateLegacyClient as z,rollbackLegacyMigration as F}from"./migration.js";const V="vip.elevo.messenger.agent.migration";async function lt(t,e,r,i){if(!t.migrated)return!1;if(process.platform==="darwin")return B(t,e,r,i);try{return await b(t,e,r,i),!0}catch(n){throw await g(e).catch(()=>{}),await M(t),n}}async function b(t,e,r,i){const n=await v(r),o=m(n,"data_dir")??t.paths.dataDir,s=Array.isArray(n.workspaces)?n.workspaces.find(c=>!!c&&typeof c=="object"&&!Array.isArray(c)&&typeof c.path=="string"):void 0,a=m(s,"path");if(!a)throw new Error("Migrated config does not contain a workspace path");await A(),await k({configPath:r,dataDir:o,workspacePath:a,serviceCommandPath:e.wrapperPath,path:i}),await S(),await I(t)}async function B(t,e,r,i,n={}){return J(t,e,r,i,{...n,platform:"darwin"})}async function J(t,e,r,i,n={}){const o=n.run??q,s=n.wait??C,a=n.attempts??1200,c=n.platform??process.platform;if(c!=="darwin"&&c!=="linux")throw new Error("Only Linux and macOS are supported");const d=y(t.paths.rootDir,"migration-handoff.json"),u=c==="darwin"?`${V}.${process.pid}`:`messenger-agent-migration-${process.pid}`;await p(d,{schemaVersion:1,status:"scheduled",helperLabel:u,migration:t,runtime:e,configPath:r,...i?{path:i}:{},updatedAt:new Date().toISOString()});try{c==="darwin"?await o("launchctl",["submit","-l",u,"--",e.cliWrapperPath,"complete-migration","--handoff",d]):await o("systemd-run",["--user","--quiet","--collect","--unit",u,"--",e.cliWrapperPath,"complete-migration","--handoff",d])}catch(f){throw await p(d,{...await l(d),status:"failed",message:f instanceof Error?f.message:String(f),updatedAt:new Date().toISOString()}),f}for(let f=0;f<a;f+=1){const h=await l(d);if(h.status==="completed")return c==="darwin"&&await o("launchctl",["remove",u],{allowFailure:!0}),!0;if(h.status==="failed")throw new Error(h.message??"Service migration failed");await s(100)}throw new Error(`Timed out waiting for service migration; inspect ${d}`)}async function mt(t,e){try{const r=await l(y(t,"migration-handoff.json"));return r.status!=="completed"&&r.runtime.version!==e}catch(r){if(r.code==="ENOENT")return!0;throw r}}async function ht(t){const e=await l(t);await p(t,{...e,status:"running",updatedAt:new Date().toISOString()});try{await b(e.migration,e.runtime,e.configPath,e.path),await p(t,{...e,status:"completed",updatedAt:new Date().toISOString()})}catch(r){const i=[];await g(e.runtime).catch(o=>{i.push(`runtime rollback failed: ${String(o)}`)}),await D().catch(o=>{i.push(`new service cleanup failed: ${String(o)}`)}),await P().catch(o=>{i.push(`legacy service restart failed: ${String(o)}`)});const n=[r instanceof Error?r.message:String(r),...i].join("; ");throw await p(t,{...e,status:"failed",message:n,updatedAt:new Date().toISOString()}),r}}async function l(t){const e=JSON.parse(await T(t,"utf8"));if(e.schemaVersion!==1||!e.migration||!e.runtime||typeof e.configPath!="string"||typeof e.helperLabel!="string"||e.status!=="scheduled"&&e.status!=="running"&&e.status!=="completed"&&e.status!=="failed")throw new Error(`Invalid Messenger Agent migration handoff: ${t}`);return e}async function p(t,e){const r=`${t}.${process.pid}.tmp`;await L(r,`${JSON.stringify(e,null,2)}
2
- `,{mode:384}),await O(r,t)}function Z(t=process.platform){if(t!=="linux"&&t!=="darwin")throw new Error("Only Linux and macOS are supported")}function Y(t=process.versions.node){const e=/^(\d+)\.(\d+)\.(\d+)(?:[.-]|$)/.exec(t),r=Number(e?.[1]),i=Number(e?.[2]);if(!(r>22||r===22&&i>=19))throw new Error("Node.js 22.19.0 or newer is required")}function K(t){if(t.server)try{H(t.server)}catch{throw new Error("--server must be a valid HTTP or HTTPS server address")}if(t.tunnelId&&!/^[A-Za-z0-9._:-]+$/.test(t.tunnelId))throw new Error("--tunnel-id may only contain letters, numbers, '.', '_', ':', and '-'");if(t.workspaceId&&!/^[A-Za-z0-9._:-]+$/.test(t.workspaceId))throw new Error("--workspace-id may only contain letters, numbers, '.', '_', ':', and '-'");if(t.workspaceName&&(t.workspaceName.trim().length===0||t.workspaceName.trim().length>128))throw new Error("--workspace-name must be between 1 and 128 characters")}async function Q(t,e=!1){e&&await x(t,{recursive:!0});const r=await $(t);if(!(await _(r)).isDirectory())throw new Error("--workspace must point to an existing directory");return r}async function gt(t){Z(),Y();const e=G(),r=U(),n=t.configPath===e.configPath||t.configPath===r.configPath?await z():void 0;let o;try{const s=n?{...t,configPath:t.configPath===n.legacyPaths.configPath?n.paths.configPath:t.configPath,dataDir:t.dataDir===n.legacyPaths.dataDir?n.paths.dataDir:t.dataDir}:t,a=await X(s);K(a);const c=await Q(a.workspace,a.createWorkspace);await j({configPath:a.configPath,dataDir:a.dataDir,workspacePath:c,workspaceId:a.workspaceId,workspaceName:a.workspaceName,tunnelId:a.tunnelId,token:a.token,server:a.server,serverUrl:a.serverUrl,preserveWorkspaces:a.preserveWorkspaces,path:process.env.PATH}),t.channel&&await R(a.configPath,t.channel),o=await W({version:"current",configPath:a.configPath,runtimeDir:n?.paths.runtimeDir,binDir:n?.paths.binDir,path:process.env.PATH,hostArtifactDirectory:process.env.MESSENGER_AGENT_BOOTSTRAP_HOST_DIR,clientDirectory:process.env.MESSENGER_AGENT_BOOTSTRAP_CLIENT_DIR}),n?.migrated&&await A();const d=await k({configPath:a.configPath,dataDir:a.dataDir,workspacePath:c,serviceCommandPath:o.wrapperPath,path:process.env.PATH});return n?.migrated&&(await S(),await I(n)),{configPath:a.configPath,dataDir:a.dataDir,workspacePath:c,runtime:o,service:d}}catch(s){throw o&&await g(o).catch(()=>{}),n?.migrated&&await M(n),s}}async function M(t){await D().catch(()=>{}),await F(t),await P().catch(()=>{})}async function X(t){const e=await v(t.configPath),r=et(e,"tunnel"),i=t.tunnelId??m(r,"tunnel_id"),n=t.token??m(r,"token"),o=tt(e,t.workspaceId,i),s=t.workspace??o?.path??E,a=t.workspaceId??o?.id??N(),c=t.workspaceName??o?.name??(i?`${i} Default`:void 0),d=s===E;if(!i)throw new w("Missing required option: --tunnel-id");if(!n)throw new w("Missing required option: --token");if(!a)throw new w("Missing required option: --workspace-id");if(!c)throw new w("Missing required option: --workspace-name");return{...t,tunnelId:i,token:n,workspace:s,workspaceId:a,workspaceName:c,preserveWorkspaces:!t.workspace&&!!o,createWorkspace:d}}function tt(t,e,r){const i=t.workspaces;if(!Array.isArray(i))return;const n=i.filter(a=>!!a&&typeof a=="object"&&!Array.isArray(a)&&typeof a.path=="string");if(e){const a=n.find(c=>c.id===e);return!a||typeof a.path!="string"?void 0:{id:e,name:typeof a.name=="string"&&a.name?a.name:`${r??e} Default`,path:a.path}}const o=e??(r?`${r}--default`:void 0),s=(o?n.find(a=>a.id===o):void 0)??n.find(a=>a.id==="default")??n[0];if(!(!s||typeof s.path!="string"))return{id:typeof s.id=="string"&&s.id?s.id:o??"default",name:typeof s.name=="string"&&s.name?s.name:`${r??o??"default"} Default`,path:s.path}}function et(t,e){const r=t[e];if(!(!r||typeof r!="object"||Array.isArray(r)))return r}function m(t,e){const r=t?.[e];return typeof r=="string"&&r?r:void 0}export{lt as activateMigratedService,Y as assertNodeVersion,Z as assertSupportedPlatform,ht as completeMigrationHandoff,gt as installClient,X as resolveInstallArgs,Q as resolveWorkspacePath,B as scheduleDarwinMigrationHandoff,J as scheduleMigrationHandoff,mt as shouldAttemptAutomaticMigration,K as validateInstallArgs};
1
+ import{randomUUID as _}from"node:crypto";import{mkdir as C,readFile as L,realpath as H,rename as j,stat as R,writeFile as W}from"node:fs/promises";import{join as P}from"node:path";import{setTimeout as U}from"node:timers/promises";import{normalizeAgentServer as z}from"@messenger-agent/shared/agent-config";import{readConfigYaml as S,updateClientConfig as F,writeUpgradeChannel as G}from"./config-file.js";import{installRuntime as V,rollbackRuntime as g}from"./runtime.js";import{installService as A,startLegacyService as D,stopLegacyService as E,uninstallLegacyService as b,uninstallService as M}from"./service.js";import{UsageError as p}from"./args.js";import{defaultWorkspacePath as I,legacyCodingAgentPaths as q,messengerAgentPaths as B}from"./paths.js";import{runCommand as y}from"./exec.js";import{completeLegacyMigration as N,migrateLegacyClient as J,rollbackLegacyMigration as Z}from"./migration.js";const x="vip.elevo.messenger.agent.migration";async function gt(t,a,e,o){if(!t.migrated)return!1;if(process.platform==="darwin")return X(t,a,e,o);try{return await T(t,a,e,o),!0}catch(n){throw await g(a).catch(()=>{}),await O(t),n}}async function T(t,a,e,o){const n=await S(e),i=m(n,"data_dir")??t.paths.dataDir,s=Array.isArray(n.workspaces)?n.workspaces.find(c=>!!c&&typeof c=="object"&&!Array.isArray(c)&&typeof c.path=="string"):void 0,r=m(s,"path");if(!r)throw new Error("Migrated config does not contain a workspace path");await E(),await A({configPath:e,dataDir:i,workspacePath:r,serviceCommandPath:a.wrapperPath,path:o}),await b(),await N(t)}async function X(t,a,e,o,n={}){return Y(t,a,e,o,{...n,platform:"darwin"})}async function Y(t,a,e,o,n={}){const i=n.run??y,s=n.wait??U,r=n.attempts??1200,c=n.platform??process.platform;if(c!=="darwin"&&c!=="linux")throw new Error("Only Linux and macOS are supported");const f=P(t.paths.rootDir,"migration-handoff.json"),l=c==="darwin"?`${x}.${process.pid}`:`messenger-agent-migration-${process.pid}`;c==="darwin"&&await $(i,[],void 0,!0),await u(f,{schemaVersion:1,status:"scheduled",helperLabel:l,migration:t,runtime:a,configPath:e,...o?{path:o}:{},updatedAt:new Date().toISOString()});try{c==="darwin"?await i("launchctl",["submit","-l",l,"--",a.cliWrapperPath,"complete-migration","--handoff",f]):await i("systemd-run",["--user","--quiet","--collect","--unit",l,"--",a.cliWrapperPath,"complete-migration","--handoff",f])}catch(d){throw await u(f,{...await w(f),status:"failed",message:d instanceof Error?d.message:String(d),updatedAt:new Date().toISOString()}),d}for(let d=0;d<r;d+=1){const h=await w(f);if(h.status==="completed")return c==="darwin"&&await i("launchctl",["remove",l],{allowFailure:!0}),!0;if(h.status==="failed")throw new Error(h.message??"Service migration failed");await s(100)}throw new Error(`Timed out waiting for service migration; inspect ${f}`)}async function yt(t,a){try{const e=await w(P(t,"migration-handoff.json"));return e.status!=="completed"&&e.runtime.version!==a}catch(e){if(e.code==="ENOENT")return!0;throw e}}async function vt(t,a={}){const e=await w(t),o=a.run??y;if(e.status==="completed"||e.status==="failed"){await v(e,o,a.activeHelperLabel);return}await u(t,{...e,status:"running",updatedAt:new Date().toISOString()});try{await(a.activate??T)(e.migration,e.runtime,e.configPath,e.path),await u(t,{...e,status:"completed",updatedAt:new Date().toISOString()}),await v(e,o,a.activeHelperLabel)}catch(n){const i=[];await(a.rollback??g)(e.runtime).catch(r=>{i.push(`runtime rollback failed: ${String(r)}`)}),await(a.uninstall??M)().catch(r=>{i.push(`new service cleanup failed: ${String(r)}`)}),await(a.startLegacy??D)().catch(r=>{i.push(`legacy service restart failed: ${String(r)}`)});const s=[n instanceof Error?n.message:String(n),...i].join("; ");throw await u(t,{...e,status:"failed",message:s,updatedAt:new Date().toISOString()}),await v(e,o,a.activeHelperLabel),n}}async function v(t,a=y,e=process.env.XPC_SERVICE_NAME){await $(a,[t.helperLabel],e)}async function $(t,a=[],e,o=!1){const n=new Set(a.filter(k));if(e&&k(e)&&n.add(e),n.size===0&&!o)return;if(o||n.size>0){const s=await t("launchctl",["list"],{allowFailure:!0,logCommand:!1}).catch(()=>{});for(const r of s?.stdout.split(`
2
+ `)??[]){const c=r.trim().split(/\s+/).at(-1);c&&k(c)&&n.add(c)}}const i=[...n].filter(s=>s!==e);e&&n.has(e)&&i.push(e);for(const s of i)await t("launchctl",["remove",s],{allowFailure:!0}).catch(()=>{})}function k(t){return t.startsWith(`${x}.`)}async function w(t){const a=JSON.parse(await L(t,"utf8"));if(a.schemaVersion!==1||!a.migration||!a.runtime||typeof a.configPath!="string"||typeof a.helperLabel!="string"||a.status!=="scheduled"&&a.status!=="running"&&a.status!=="completed"&&a.status!=="failed")throw new Error(`Invalid Messenger Agent migration handoff: ${t}`);return a}async function u(t,a){const e=`${t}.${process.pid}.tmp`;await W(e,`${JSON.stringify(a,null,2)}
3
+ `,{mode:384}),await j(e,t)}function K(t=process.platform){if(t!=="linux"&&t!=="darwin")throw new Error("Only Linux and macOS are supported")}function Q(t=process.versions.node){const a=/^(\d+)\.(\d+)\.(\d+)(?:[.-]|$)/.exec(t),e=Number(a?.[1]),o=Number(a?.[2]);if(!(e>22||e===22&&o>=19))throw new Error("Node.js 22.19.0 or newer is required")}function tt(t){if(t.server)try{z(t.server)}catch{throw new Error("--server must be a valid HTTP or HTTPS server address")}if(t.tunnelId&&!/^[A-Za-z0-9._:-]+$/.test(t.tunnelId))throw new Error("--tunnel-id may only contain letters, numbers, '.', '_', ':', and '-'");if(t.workspaceId&&!/^[A-Za-z0-9._:-]+$/.test(t.workspaceId))throw new Error("--workspace-id may only contain letters, numbers, '.', '_', ':', and '-'");if(t.workspaceName&&(t.workspaceName.trim().length===0||t.workspaceName.trim().length>128))throw new Error("--workspace-name must be between 1 and 128 characters")}async function et(t,a=!1){a&&await C(t,{recursive:!0});const e=await H(t);if(!(await R(e)).isDirectory())throw new Error("--workspace must point to an existing directory");return e}async function kt(t){K(),Q();const a=B(),e=q(),n=t.configPath===a.configPath||t.configPath===e.configPath?await J():void 0;let i;try{const s=n?{...t,configPath:t.configPath===n.legacyPaths.configPath?n.paths.configPath:t.configPath,dataDir:t.dataDir===n.legacyPaths.dataDir?n.paths.dataDir:t.dataDir}:t,r=await at(s);tt(r);const c=await et(r.workspace,r.createWorkspace);await F({configPath:r.configPath,dataDir:r.dataDir,workspacePath:c,workspaceId:r.workspaceId,workspaceName:r.workspaceName,tunnelId:r.tunnelId,token:r.token,server:r.server,serverUrl:r.serverUrl,preserveWorkspaces:r.preserveWorkspaces,path:process.env.PATH}),t.channel&&await G(r.configPath,t.channel),i=await V({version:"current",configPath:r.configPath,runtimeDir:n?.paths.runtimeDir,binDir:n?.paths.binDir,path:process.env.PATH,hostArtifactDirectory:process.env.MESSENGER_AGENT_BOOTSTRAP_HOST_DIR,clientDirectory:process.env.MESSENGER_AGENT_BOOTSTRAP_CLIENT_DIR}),n?.migrated&&await E();const f=await A({configPath:r.configPath,dataDir:r.dataDir,workspacePath:c,serviceCommandPath:i.wrapperPath,path:process.env.PATH});return n?.migrated&&(await b(),await N(n)),{configPath:r.configPath,dataDir:r.dataDir,workspacePath:c,runtime:i,service:f}}catch(s){throw i&&await g(i).catch(()=>{}),n?.migrated&&await O(n),s}}async function O(t){await M().catch(()=>{}),await Z(t),await D().catch(()=>{})}async function at(t){const a=await S(t.configPath),e=nt(a,"tunnel"),o=t.tunnelId??m(e,"tunnel_id"),n=t.token??m(e,"token"),i=rt(a,t.workspaceId,o),s=t.workspace??i?.path??I,r=t.workspaceId??i?.id??_(),c=t.workspaceName??i?.name??(o?`${o} Default`:void 0),f=s===I;if(!o)throw new p("Missing required option: --tunnel-id");if(!n)throw new p("Missing required option: --token");if(!r)throw new p("Missing required option: --workspace-id");if(!c)throw new p("Missing required option: --workspace-name");return{...t,tunnelId:o,token:n,workspace:s,workspaceId:r,workspaceName:c,preserveWorkspaces:!t.workspace&&!!i,createWorkspace:f}}function rt(t,a,e){const o=t.workspaces;if(!Array.isArray(o))return;const n=o.filter(r=>!!r&&typeof r=="object"&&!Array.isArray(r)&&typeof r.path=="string");if(a){const r=n.find(c=>c.id===a);return!r||typeof r.path!="string"?void 0:{id:a,name:typeof r.name=="string"&&r.name?r.name:`${e??a} Default`,path:r.path}}const i=a??(e?`${e}--default`:void 0),s=(i?n.find(r=>r.id===i):void 0)??n.find(r=>r.id==="default")??n[0];if(!(!s||typeof s.path!="string"))return{id:typeof s.id=="string"&&s.id?s.id:i??"default",name:typeof s.name=="string"&&s.name?s.name:`${e??i??"default"} Default`,path:s.path}}function nt(t,a){const e=t[a];if(!(!e||typeof e!="object"||Array.isArray(e)))return e}function m(t,a){const e=t?.[a];return typeof e=="string"&&e?e:void 0}export{gt as activateMigratedService,Q as assertNodeVersion,K as assertSupportedPlatform,vt as completeMigrationHandoff,kt as installClient,at as resolveInstallArgs,et as resolveWorkspacePath,X as scheduleDarwinMigrationHandoff,Y as scheduleMigrationHandoff,yt as shouldAttemptAutomaticMigration,tt as validateInstallArgs};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@messenger-agent/client",
3
- "version": "0.33.0-alpha.8",
3
+ "version": "0.33.0",
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/claude-agent": "0.33.0-alpha.8",
25
- "@messenger-agent/shared": "0.33.0-alpha.8",
26
- "@messenger-agent/codex-agent": "0.33.0-alpha.8",
27
- "@messenger-agent/messenger-agent": "0.33.0-alpha.8"
24
+ "@messenger-agent/claude-agent": "0.33.0",
25
+ "@messenger-agent/codex-agent": "0.33.0",
26
+ "@messenger-agent/shared": "0.33.0",
27
+ "@messenger-agent/messenger-agent": "0.33.0"
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",