@gajae-gateway/cli 0.1.2 → 0.1.4

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/main.d.ts CHANGED
@@ -10,7 +10,7 @@ export declare function socketPath(home?: string | undefined): string;
10
10
  * never after, so the list is checked up front.
11
11
  */
12
12
  export declare const COMMANDS: readonly ["status", "shutdown", "chat", "daemon", "sessions", "ops", "memory", "monitors", "work", "services"];
13
- export declare const CLI_USAGE = "usage: gajaeway [--socket PATH] status|shutdown|chat|daemon run|sessions list [--json] [--fields a,b,c] [--limit N] [--offset N]|sessions inspect <originKey-or-index>|memory audit|memory search <query>|monitors ... (test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] <text>|work status <name>|work steer <name> <text>|work retire <name>|work jobs|ops backup <path>|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restore <backupPath>|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux] (work run waits for a response; caller timeout does not end the attempt)";
13
+ export declare const CLI_USAGE = "usage: gajaeway [--socket PATH] status|shutdown|chat|daemon run|sessions list [--json] [--fields a,b,c] [--limit N] [--offset N]|sessions inspect <originKey-or-index>|memory audit|memory search <query>|monitors ... (test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] <text>|work status <name>|work steer <name> <text>|work retire [--force] <name>|work retire --all-dead|work jobs|ops backup <path>|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restore <backupPath>|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux] (work run waits for a response; caller timeout does not end the attempt)";
14
14
  /** Usage errors exit 2, as `gajaeway-gateway` does; 1 stays a runtime failure. */
15
15
  export declare const USAGE_EXIT_CODE = 2;
16
16
  /** The usage text when `command` cannot be dispatched, undefined when it can. */
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAIX,cAAc,EAQd,MAAM,yBAAyB,CAAC;AAYjC,OAAO,EAEN,KAAK,oBAAoB,EAEzB,KAAK,iBAAiB,EAItB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,sBAAsB,EAAmB,KAAK,eAAe,EAAgB,MAAM,YAAY,CAAC;AAE9G,wBAAgB,UAAU,CAAC,IAAI,qBAA4B,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,gHAWX,CAAC;AAEX,eAAO,MAAM,SAAS,+vBACuuB,CAAC;AAE9vB,kFAAkF;AAClF,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAExE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAQ9F;AAMD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,iBAAiB,GAAG,WAAW,CAAC,CAAC;IAClF,oFAAoF;IACpF,QAAQ,CAAC,YAAY,CAAC,EAAE;QACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QACrD,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;KACtD,CAAC;CACF;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;CACpC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CA8B7E;AAqID;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CA+C3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAwB9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B7E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBvF;AA8DD,wBAAsB,IAAI,CAAC,IAAI,WAAwB,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+XjG"}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAIX,cAAc,EAQd,MAAM,yBAAyB,CAAC;AAYjC,OAAO,EAEN,KAAK,oBAAoB,EAEzB,KAAK,iBAAiB,EAItB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,sBAAsB,EAAmB,KAAK,eAAe,EAAgB,MAAM,YAAY,CAAC;AAE9G,wBAAgB,UAAU,CAAC,IAAI,qBAA4B,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,gHAWX,CAAC;AAEX,eAAO,MAAM,SAAS,gyBACwwB,CAAC;AAE/xB,kFAAkF;AAClF,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,iFAAiF;AACjF,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAExE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAQ9F;AAMD,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,iBAAiB,GAAG,WAAW,CAAC,CAAC;IAClF,oFAAoF;IACpF,QAAQ,CAAC,YAAY,CAAC,EAAE;QACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QACrD,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;KACtD,CAAC;CACF;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,QAAQ,CAAC;AAElD,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;CACpC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CA8B7E;AAqID;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CA+C3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAwB9D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,SAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B7E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBvF;AA8DD,wBAAsB,IAAI,CAAC,IAAI,WAAwB,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ZjG"}
package/dist/main.js CHANGED
@@ -129,7 +129,8 @@ function renderList(columns, rows, options, envelope) {
129
129
 
130
130
  // src/restart-stack.ts
131
131
  import { randomUUID } from "crypto";
132
- import { mkdir as mkdir2, readFile as readFile2, rename, stat, writeFile as writeFile2 } from "fs/promises";
132
+ import { access, mkdir as mkdir2, readFile as readFile2, rename, stat, writeFile as writeFile2 } from "fs/promises";
133
+ import { homedir as homedir2 } from "os";
133
134
  import { join as join2 } from "path";
134
135
 
135
136
  // src/services.ts
@@ -288,6 +289,12 @@ function systemdUnitDir(env, userHome) {
288
289
  const base = env.XDG_CONFIG_HOME || join(userHome, ".config");
289
290
  return join(base, "systemd", "user");
290
291
  }
292
+ function launchAgentPlistPath(spec, launchAgentsDir) {
293
+ return join(launchAgentsDir, `dev.gajaeway.${spec.id}.plist`);
294
+ }
295
+ function systemdUnitPath(spec, unitDir) {
296
+ return join(unitDir, systemdUnitName(spec));
297
+ }
291
298
  function restartStackCommands(platform, uid) {
292
299
  if (platform === "linux")
293
300
  return [["systemctl", "--user", "restart", GATEWAY_UNIT]];
@@ -462,6 +469,33 @@ function defaultServiceProbe(platform) {
462
469
  async function defaultBinaryModifiedAt(path) {
463
470
  return (await stat(path)).mtimeMs;
464
471
  }
472
+ function defaultIsServiceInstalled(options) {
473
+ return async (label) => {
474
+ const spec = serviceSpecs().find((s) => s.label === label);
475
+ if (spec === undefined)
476
+ return false;
477
+ if (options.platform === "darwin") {
478
+ const userHome2 = options.env.HOME || homedir2();
479
+ const agentsDir = options.launchAgentsDir || join2(userHome2, "Library", "LaunchAgents");
480
+ const plistPath = launchAgentPlistPath(spec, agentsDir);
481
+ try {
482
+ await access(plistPath);
483
+ return true;
484
+ } catch {
485
+ return false;
486
+ }
487
+ }
488
+ const userHome = options.env.HOME || homedir2();
489
+ const unitDirPath = options.unitDir || systemdUnitDir(options.env, userHome);
490
+ const unitPath = systemdUnitPath(spec, unitDirPath);
491
+ try {
492
+ await access(unitPath);
493
+ return true;
494
+ } catch {
495
+ return false;
496
+ }
497
+ };
498
+ }
465
499
  function floorSecond(ms) {
466
500
  return Math.floor(ms / 1000) * 1000;
467
501
  }
@@ -470,6 +504,12 @@ async function runRestartStack(options) {
470
504
  const runner = options.runner ?? defaultCommandRunner;
471
505
  const probe = options.probe ?? defaultServiceProbe(platform);
472
506
  const modifiedAt = options.binaryModifiedAt ?? defaultBinaryModifiedAt;
507
+ const isInstalled = options.isServiceInstalled ?? defaultIsServiceInstalled({
508
+ platform,
509
+ env: options.env ?? process.env,
510
+ launchAgentsDir: options.launchAgentsDir,
511
+ unitDir: options.unitDir
512
+ });
473
513
  const now = options.now ?? Date.now;
474
514
  const sleep = options.sleep ?? ((ms) => Bun.sleep(ms));
475
515
  const timeoutMs = options.verifyTimeoutMs ?? VERIFY_TIMEOUT_MS;
@@ -486,6 +526,13 @@ async function runRestartStack(options) {
486
526
  continue;
487
527
  }
488
528
  try {
529
+ const installed = await isInstalled(step.label);
530
+ if (!installed) {
531
+ step.result = "skipped";
532
+ step.detail = "service is not installed";
533
+ await writeReceipt(options.home, receipt);
534
+ continue;
535
+ }
489
536
  if (step.command !== undefined) {
490
537
  issuedAt = now();
491
538
  const status = await runner(step.command);
@@ -501,8 +548,9 @@ async function runRestartStack(options) {
501
548
  step.result = "failed";
502
549
  step.detail = error instanceof Error ? error.message : String(error);
503
550
  }
504
- if (step.result !== "ok")
551
+ if (step.result !== "ok" && step.result !== "skipped") {
505
552
  receipt.state = step.result === "stale" ? "stale" : "failed";
553
+ }
506
554
  await writeReceipt(options.home, receipt);
507
555
  }
508
556
  if (receipt.state === "running")
@@ -625,7 +673,7 @@ var COMMANDS = [
625
673
  "work",
626
674
  "services"
627
675
  ];
628
- var CLI_USAGE = "usage: gajaeway [--socket PATH] status|shutdown|chat|daemon run|sessions list [--json] [--fields a,b,c] [--limit N] [--offset N]|sessions inspect <originKey-or-index>|memory audit|memory search <query>|monitors ... (test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] <text>|work status <name>|work steer <name> <text>|work retire <name>|work jobs|ops backup <path>|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restore <backupPath>|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux] (work run waits for a response; caller timeout does not end the attempt)";
676
+ var CLI_USAGE = "usage: gajaeway [--socket PATH] status|shutdown|chat|daemon run|sessions list [--json] [--fields a,b,c] [--limit N] [--offset N]|sessions inspect <originKey-or-index>|memory audit|memory search <query>|monitors ... (test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] <text>|work status <name>|work steer <name> <text>|work retire [--force] <name>|work retire --all-dead|work jobs|ops backup <path>|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restore <backupPath>|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux] (work run waits for a response; caller timeout does not end the attempt)";
629
677
  var USAGE_EXIT_CODE = 2;
630
678
  function usageFor(command) {
631
679
  return command !== undefined && COMMANDS.includes(command) ? undefined : CLI_USAGE;
@@ -1211,20 +1259,55 @@ async function main(args = process.argv.slice(2), options = {}) {
1211
1259
  break;
1212
1260
  }
1213
1261
  if (command === "retire" || command === "jobs") {
1214
- if (command === "retire" ? args2.length !== 1 || !args2[0] || args2[0].startsWith("--") : args2.length !== 0)
1262
+ let force = false;
1263
+ let allDead = false;
1264
+ let name2;
1265
+ if (command === "retire") {
1266
+ for (let i = 0;i < args2.length; i++) {
1267
+ const arg = args2[i];
1268
+ if (arg === "--force") {
1269
+ if (force)
1270
+ throw new Error(usage2);
1271
+ force = true;
1272
+ } else if (arg === "--all-dead") {
1273
+ if (allDead)
1274
+ throw new Error(usage2);
1275
+ allDead = true;
1276
+ } else if (!arg.startsWith("--")) {
1277
+ if (name2)
1278
+ throw new Error(usage2);
1279
+ name2 = arg;
1280
+ } else
1281
+ throw new Error(usage2);
1282
+ }
1283
+ if (!allDead && !name2)
1284
+ throw new Error(usage2);
1285
+ if (allDead && name2)
1286
+ throw new Error(usage2);
1287
+ } else if (args2.length !== 0) {
1215
1288
  throw new Error(usage2);
1289
+ }
1216
1290
  const client2 = await GajaewayClient.connectSocket(parsed.socket);
1217
1291
  try {
1218
1292
  if (command === "retire") {
1219
- const result = await client2.request("work.retire", { name: args2[0] });
1220
- console.log(result.retired ? `retired: ${result.sessionKey} session=${result.sessionId} closed=${result.closed}` : `not retired: ${result.reason}`);
1293
+ const result = await client2.request("work.retire", {
1294
+ ...name2 !== undefined ? { name: name2 } : {},
1295
+ ...force ? { force } : {},
1296
+ ...allDead ? { allDead } : {}
1297
+ });
1298
+ if (allDead) {
1299
+ console.log(`Retired all dead lanes`);
1300
+ } else {
1301
+ const forced = result.retired && result.forced ? " (forced)" : "";
1302
+ console.log(result.retired ? `retired: ${result.sessionKey} session=${result.sessionId} closed=${result.closed}${forced}` : `not retired: ${result.reason}`);
1303
+ }
1221
1304
  } else {
1222
1305
  const result = await client2.request("work.jobs");
1223
1306
  for (const job of result.jobs) {
1224
- const name2 = job.lane_key.startsWith("work-") ? job.lane_key.slice("work-".length) : job.lane_key;
1307
+ const name3 = job.lane_key.startsWith("work-") ? job.lane_key.slice("work-".length) : job.lane_key;
1225
1308
  const state = job.quarantined ? `HELD: quarantined reason=${job.reason} historical_state=${job.state}` : job.state;
1226
1309
  const head = job.last_commit ? `${job.last_commit.sha.slice(0, 7)}@${job.last_commit.committed_at} ${JSON.stringify(job.last_commit.subject)}` : "-";
1227
- console.log(`${name2} ${state} session=${job.session_id || "-"} accepted=${job.accepted_at || "-"} op=${job.attempt?.op_ref || "-"} last=${job.last_activity_at || "-"} head=${head} ${job.worktree_path}${job.reports && (job.reports.pending !== 0 || job.reports.claimed !== 0 || job.reports.held !== 0 || job.reports.undeliverable !== 0) ? ` reports=p:${job.reports.pending} c:${job.reports.claimed} h:${job.reports.held} u:${job.reports.undeliverable}` : ""}`);
1310
+ console.log(`${name3} ${state} session=${job.session_id || "-"} accepted=${job.accepted_at || "-"} op=${job.attempt?.op_ref || "-"} last=${job.last_activity_at || "-"} head=${head} ${job.worktree_path}${job.reports && (job.reports.pending !== 0 || job.reports.claimed !== 0 || job.reports.held !== 0 || job.reports.undeliverable !== 0) ? ` reports=p:${job.reports.pending} c:${job.reports.claimed} h:${job.reports.held} u:${job.reports.undeliverable}` : ""}`);
1228
1311
  }
1229
1312
  }
1230
1313
  } finally {
@@ -42,6 +42,7 @@ export interface ServiceProcess {
42
42
  }
43
43
  export type CommandRunner = (command: readonly string[]) => number | PromiseLike<number>;
44
44
  export type ServiceProbe = (label: string) => Promise<ServiceProcess | undefined>;
45
+ export type IsServiceInstalled = (label: string) => Promise<boolean>;
45
46
  export interface RunRestartOptions {
46
47
  readonly home: string;
47
48
  readonly id: string;
@@ -49,6 +50,8 @@ export interface RunRestartOptions {
49
50
  readonly uid?: number;
50
51
  readonly runner?: CommandRunner;
51
52
  readonly probe?: ServiceProbe;
53
+ /** Checks if a service is installed; if not provided, defaults to checking the service manager's files. */
54
+ readonly isServiceInstalled?: IsServiceInstalled;
52
55
  /** Epoch ms modification time of a deployed binary. */
53
56
  readonly binaryModifiedAt?: (path: string) => Promise<number>;
54
57
  readonly now?: () => number;
@@ -56,6 +59,12 @@ export interface RunRestartOptions {
56
59
  /** How long one service may take to come back verified; covers the gateway's ordered shutdown. */
57
60
  readonly verifyTimeoutMs?: number;
58
61
  readonly pollMs?: number;
62
+ /** Environment variables; used to determine systemd unit dir on linux. Defaults to process.env. */
63
+ readonly env?: NodeJS.ProcessEnv;
64
+ /** LaunchAgents directory on darwin. Defaults to ~/Library/LaunchAgents. */
65
+ readonly launchAgentsDir?: string;
66
+ /** systemd unit directory on linux. Defaults to $XDG_CONFIG_HOME/systemd/user. */
67
+ readonly unitDir?: string;
59
68
  }
60
69
  export declare function restartReceiptPath(home: string): string;
61
70
  export declare function readRestartReceipt(home: string): Promise<RestartReceipt | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"restart-stack.d.ts","sourceRoot":"","sources":["../src/restart-stack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"restart-stack.d.ts","sourceRoot":"","sources":["../src/restart-stack.ts"],"names":[],"mappings":"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"}
@@ -52,6 +52,11 @@ export declare function escapeXml(value: string): string;
52
52
  export declare function renderLaunchAgent(spec: ServiceSpec, binDir: string, home: string, path: string): string;
53
53
  export declare function systemdUnitName(spec: ServiceSpec): string;
54
54
  export declare function renderSystemdUnit(spec: ServiceSpec, binDir: string, home: string, path: string): string;
55
+ export declare function systemdUnitDir(env: NodeJS.ProcessEnv, userHome: string): string;
56
+ /** Gets the path where a service's LaunchAgent plist is stored on darwin. */
57
+ export declare function launchAgentPlistPath(spec: ServiceSpec, launchAgentsDir: string): string;
58
+ /** Gets the path where a service's systemd unit file is stored on linux. */
59
+ export declare function systemdUnitPath(spec: ServiceSpec, unitDir: string): string;
55
60
  /**
56
61
  * The ordered commands that realign the whole stack.
57
62
  *
@@ -1 +1 @@
1
- {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gajae-gateway/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "description": "Owner CLI for the gajaeway gateway: status, sessions, chat, monitors, and worker lanes over the gateway socket. Requires the Bun runtime (uses Bun.file/Bun.spawn).",
6
6
  "license": "AGPL-3.0-only",
@@ -41,8 +41,8 @@
41
41
  "prepublishOnly": "bun run build"
42
42
  },
43
43
  "dependencies": {
44
- "@gajae-gateway/sdk": "0.1.2",
45
- "@gajae-gateway/protocol": "0.1.2"
44
+ "@gajae-gateway/sdk": "0.1.4",
45
+ "@gajae-gateway/protocol": "0.1.4"
46
46
  },
47
47
  "engines": {
48
48
  "bun": ">=1.4.0"
package/src/main.ts CHANGED
@@ -61,7 +61,7 @@ export const COMMANDS = [
61
61
  ] as const;
62
62
 
63
63
  export const CLI_USAGE =
64
- "usage: gajaeway [--socket PATH] status|shutdown|chat|daemon run|sessions list [--json] [--fields a,b,c] [--limit N] [--offset N]|sessions inspect <originKey-or-index>|memory audit|memory search <query>|monitors ... (test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] <text>|work status <name>|work steer <name> <text>|work retire <name>|work jobs|ops backup <path>|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restore <backupPath>|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux] (work run waits for a response; caller timeout does not end the attempt)";
64
+ "usage: gajaeway [--socket PATH] status|shutdown|chat|daemon run|sessions list [--json] [--fields a,b,c] [--limit N] [--offset N]|sessions inspect <originKey-or-index>|memory audit|memory search <query>|monitors ... (test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] <text>|work status <name>|work steer <name> <text>|work retire [--force] <name>|work retire --all-dead|work jobs|ops backup <path>|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restore <backupPath>|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux] (work run waits for a response; caller timeout does not end the attempt)";
65
65
 
66
66
  /** Usage errors exit 2, as `gajaeway-gateway` does; 1 stays a runtime failure. */
67
67
  export const USAGE_EXIT_CODE = 2;
@@ -753,17 +753,46 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
753
753
  break;
754
754
  }
755
755
  if (command === "retire" || command === "jobs") {
756
- if (command === "retire" ? args.length !== 1 || !args[0] || args[0].startsWith("--") : args.length !== 0)
756
+ let force = false;
757
+ let allDead = false;
758
+ let name: string | undefined;
759
+ if (command === "retire") {
760
+ for (let i = 0; i < args.length; i++) {
761
+ const arg = args[i];
762
+ if (arg === "--force") {
763
+ if (force) throw new Error(usage);
764
+ force = true;
765
+ } else if (arg === "--all-dead") {
766
+ if (allDead) throw new Error(usage);
767
+ allDead = true;
768
+ } else if (!arg.startsWith("--")) {
769
+ if (name) throw new Error(usage); // Already have a name, reject duplicate
770
+ name = arg;
771
+ } else throw new Error(usage);
772
+ }
773
+ if (!allDead && !name) throw new Error(usage);
774
+ if (allDead && name) throw new Error(usage);
775
+ } else if (args.length !== 0) {
757
776
  throw new Error(usage);
777
+ }
758
778
  const client = await GajaewayClient.connectSocket(parsed.socket);
759
779
  try {
760
780
  if (command === "retire") {
761
- const result = await client.request<WorkRetireResult>("work.retire", { name: args[0] });
762
- console.log(
763
- result.retired
764
- ? `retired: ${result.sessionKey} session=${result.sessionId} closed=${result.closed}`
765
- : `not retired: ${result.reason}`,
766
- );
781
+ const result = await client.request<WorkRetireResult>("work.retire", {
782
+ ...(name !== undefined ? { name } : {}),
783
+ ...(force ? { force } : {}),
784
+ ...(allDead ? { allDead } : {}),
785
+ });
786
+ if (allDead) {
787
+ console.log(`Retired all dead lanes`);
788
+ } else {
789
+ const forced = result.retired && result.forced ? " (forced)" : "";
790
+ console.log(
791
+ result.retired
792
+ ? `retired: ${result.sessionKey} session=${result.sessionId} closed=${result.closed}${forced}`
793
+ : `not retired: ${result.reason}`,
794
+ );
795
+ }
767
796
  } else {
768
797
  const result = await client.request<WorkJobsResult>("work.jobs");
769
798
  for (const job of result.jobs) {
@@ -1,13 +1,17 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
2
+ import { access, mkdir, readFile, rename, stat, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
3
4
  import { join } from "node:path";
4
5
  import {
5
6
  currentPlatform,
7
+ launchAgentPlistPath,
6
8
  restartOrder,
7
9
  restartStackCommands,
8
10
  type ServicePlatform,
9
11
  serviceSpecs,
12
+ systemdUnitDir,
10
13
  systemdUnitName,
14
+ systemdUnitPath,
11
15
  } from "./services";
12
16
 
13
17
  /**
@@ -58,6 +62,7 @@ export interface ServiceProcess {
58
62
 
59
63
  export type CommandRunner = (command: readonly string[]) => number | PromiseLike<number>;
60
64
  export type ServiceProbe = (label: string) => Promise<ServiceProcess | undefined>;
65
+ export type IsServiceInstalled = (label: string) => Promise<boolean>;
61
66
 
62
67
  export interface RunRestartOptions {
63
68
  readonly home: string;
@@ -66,6 +71,8 @@ export interface RunRestartOptions {
66
71
  readonly uid?: number;
67
72
  readonly runner?: CommandRunner;
68
73
  readonly probe?: ServiceProbe;
74
+ /** Checks if a service is installed; if not provided, defaults to checking the service manager's files. */
75
+ readonly isServiceInstalled?: IsServiceInstalled;
69
76
  /** Epoch ms modification time of a deployed binary. */
70
77
  readonly binaryModifiedAt?: (path: string) => Promise<number>;
71
78
  readonly now?: () => number;
@@ -73,6 +80,12 @@ export interface RunRestartOptions {
73
80
  /** How long one service may take to come back verified; covers the gateway's ordered shutdown. */
74
81
  readonly verifyTimeoutMs?: number;
75
82
  readonly pollMs?: number;
83
+ /** Environment variables; used to determine systemd unit dir on linux. Defaults to process.env. */
84
+ readonly env?: NodeJS.ProcessEnv;
85
+ /** LaunchAgents directory on darwin. Defaults to ~/Library/LaunchAgents. */
86
+ readonly launchAgentsDir?: string;
87
+ /** systemd unit directory on linux. Defaults to $XDG_CONFIG_HOME/systemd/user. */
88
+ readonly unitDir?: string;
76
89
  }
77
90
 
78
91
  const RECEIPT_FILE = "restart-stack.json";
@@ -166,6 +179,42 @@ async function defaultBinaryModifiedAt(path: string): Promise<number> {
166
179
  return (await stat(path)).mtimeMs;
167
180
  }
168
181
 
182
+ /** Checks if a service is installed by verifying the service manager's definition file exists. */
183
+ function defaultIsServiceInstalled(options: {
184
+ readonly platform: ServicePlatform;
185
+ readonly env: NodeJS.ProcessEnv;
186
+ readonly launchAgentsDir?: string;
187
+ readonly unitDir?: string;
188
+ }): IsServiceInstalled {
189
+ return async (label: string) => {
190
+ const spec = serviceSpecs().find((s) => s.label === label);
191
+ if (spec === undefined) return false;
192
+
193
+ if (options.platform === "darwin") {
194
+ const userHome = options.env.HOME || homedir();
195
+ const agentsDir = options.launchAgentsDir || join(userHome, "Library", "LaunchAgents");
196
+ const plistPath = launchAgentPlistPath(spec, agentsDir);
197
+ try {
198
+ await access(plistPath);
199
+ return true;
200
+ } catch {
201
+ return false;
202
+ }
203
+ }
204
+
205
+ // linux
206
+ const userHome = options.env.HOME || homedir();
207
+ const unitDirPath = options.unitDir || systemdUnitDir(options.env, userHome);
208
+ const unitPath = systemdUnitPath(spec, unitDirPath);
209
+ try {
210
+ await access(unitPath);
211
+ return true;
212
+ } catch {
213
+ return false;
214
+ }
215
+ };
216
+ }
217
+
169
218
  function floorSecond(ms: number): number {
170
219
  return Math.floor(ms / 1_000) * 1_000;
171
220
  }
@@ -180,6 +229,14 @@ export async function runRestartStack(options: RunRestartOptions): Promise<Resta
180
229
  const runner = options.runner ?? defaultCommandRunner;
181
230
  const probe = options.probe ?? defaultServiceProbe(platform);
182
231
  const modifiedAt = options.binaryModifiedAt ?? defaultBinaryModifiedAt;
232
+ const isInstalled =
233
+ options.isServiceInstalled ??
234
+ defaultIsServiceInstalled({
235
+ platform,
236
+ env: options.env ?? process.env,
237
+ launchAgentsDir: options.launchAgentsDir,
238
+ unitDir: options.unitDir,
239
+ });
183
240
  const now = options.now ?? Date.now;
184
241
  const sleep = options.sleep ?? ((ms: number) => Bun.sleep(ms));
185
242
  const timeoutMs = options.verifyTimeoutMs ?? VERIFY_TIMEOUT_MS;
@@ -201,6 +258,15 @@ export async function runRestartStack(options: RunRestartOptions): Promise<Resta
201
258
  continue;
202
259
  }
203
260
  try {
261
+ // Check if the service is installed before trying to restart it
262
+ const installed = await isInstalled(step.label);
263
+ if (!installed) {
264
+ step.result = "skipped";
265
+ step.detail = "service is not installed";
266
+ await writeReceipt(options.home, receipt);
267
+ continue;
268
+ }
269
+
204
270
  if (step.command !== undefined) {
205
271
  issuedAt = now();
206
272
  const status = await runner(step.command);
@@ -215,7 +281,9 @@ export async function runRestartStack(options: RunRestartOptions): Promise<Resta
215
281
  step.result = "failed";
216
282
  step.detail = error instanceof Error ? error.message : String(error);
217
283
  }
218
- if (step.result !== "ok") receipt.state = step.result === "stale" ? "stale" : "failed";
284
+ if (step.result !== "ok" && step.result !== "skipped") {
285
+ receipt.state = step.result === "stale" ? "stale" : "failed";
286
+ }
219
287
  await writeReceipt(options.home, receipt);
220
288
  }
221
289
  if (receipt.state === "running") receipt.state = "ok";
package/src/services.ts CHANGED
@@ -235,11 +235,21 @@ export function renderSystemdUnit(spec: ServiceSpec, binDir: string, home: strin
235
235
  return unit.join("\n");
236
236
  }
237
237
 
238
- function systemdUnitDir(env: NodeJS.ProcessEnv, userHome: string): string {
238
+ export function systemdUnitDir(env: NodeJS.ProcessEnv, userHome: string): string {
239
239
  const base = env.XDG_CONFIG_HOME || join(userHome, ".config");
240
240
  return join(base, "systemd", "user");
241
241
  }
242
242
 
243
+ /** Gets the path where a service's LaunchAgent plist is stored on darwin. */
244
+ export function launchAgentPlistPath(spec: ServiceSpec, launchAgentsDir: string): string {
245
+ return join(launchAgentsDir, `dev.gajaeway.${spec.id}.plist`);
246
+ }
247
+
248
+ /** Gets the path where a service's systemd unit file is stored on linux. */
249
+ export function systemdUnitPath(spec: ServiceSpec, unitDir: string): string {
250
+ return join(unitDir, systemdUnitName(spec));
251
+ }
252
+
243
253
  /**
244
254
  * The ordered commands that realign the whole stack.
245
255
  *