@gajae-gateway/cli 0.2.3 → 0.3.1

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 +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":"AAcA,OAAO,EAQN,KAAK,eAAe,EAKpB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAClF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5E,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1G,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACtC,KAAK,EAAE,YAAY,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC;CAC9B;AAED,oDAAoD;AACpD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AACzF,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;AAClF,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAErE,2FAA2F;AAC3F,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAC9B,2GAA2G;IAC3G,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD,uDAAuD;IACvD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9D,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,kGAAkG;IAClG,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,mGAAmG;IACnG,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAS1F;AAsDD,mEAAmE;AACnE,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,SAA0B,GAAG,YAAY,CAa1G;AAqED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAezF;AA2OD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,mEAAmE;IACnE,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,KAAK,GAAG,CAAC,UAAU,CAAC;IACrE,2EAA2E;IAC3E,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACtC;AAID,8EAA8E;AAC9E,wBAAgB,UAAU,IAAI,MAAM,EAAE,CAErC;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACvC,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,CAgD/E;AA6BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,MAAM,CAAC,EAAE,MAAM,GACb,MAAM,EAAE,CAcV;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,GAAG,aAAa,CAAC,CAGvC;AAED,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,cAAc,EACvB,KAAK,GAAE,YAAY,GAAG,aAA6B,GACjD,MAAM,EAAE,CAkBV"}
@@ -15,6 +15,10 @@ export interface ResolvePathOptions {
15
15
  }
16
16
  /** Service managers this CLI can write definitions for. */
17
17
  export type ServicePlatform = "darwin" | "linux";
18
+ export interface ServiceCommandOptions {
19
+ readonly allowFailure?: boolean;
20
+ }
21
+ export type ServiceCommandRunner = (command: readonly string[], options?: ServiceCommandOptions) => number | PromiseLike<number>;
18
22
  export interface InstallServicesOptions {
19
23
  readonly binDir: string;
20
24
  readonly launchAgentsDir?: string;
@@ -49,6 +53,12 @@ interface ServiceSpec {
49
53
  export declare const BROKER_UNIT = "gajaeway-broker.service";
50
54
  export declare const GATEWAY_UNIT = "gajaeway-gateway.service";
51
55
  export declare function serviceSpecs(): readonly ServiceSpec[];
56
+ /**
57
+ * The `adapter-<platform>.json` an adapter reads at startup, or undefined for services
58
+ * that are not adapters. A unit whose file is absent can never come up — the adapter
59
+ * exits on the credential read — so supervisors skip it instead of looping on it.
60
+ */
61
+ export declare function adapterConfigPath(home: string, specId: string): string | undefined;
52
62
  export declare function mergePathEntries(binDir: string, userHome: string, loginPath: string): string[];
53
63
  export declare function defaultLoginPathRunner(command: readonly string[]): Promise<string>;
54
64
  export declare function discoverLoginPath(env?: NodeJS.ProcessEnv, runner?: LoginPathRunner): Promise<string>;
@@ -62,6 +72,16 @@ export declare function systemdUnitDir(env: NodeJS.ProcessEnv, userHome: string)
62
72
  export declare function launchAgentPlistPath(spec: ServiceSpec, launchAgentsDir: string): string;
63
73
  /** Gets the path where a service's systemd unit file is stored on linux. */
64
74
  export declare function systemdUnitPath(spec: ServiceSpec, unitDir: string): string;
75
+ export interface RemoveStaleServicesOptions extends Pick<InstallServicesOptions, "launchAgentsDir" | "unitDir"> {
76
+ readonly binDir: string;
77
+ readonly platform: ServicePlatform;
78
+ readonly uid?: number;
79
+ readonly env?: NodeJS.ProcessEnv;
80
+ readonly reloadSystemd?: boolean;
81
+ readonly run: ServiceCommandRunner;
82
+ }
83
+ /** Stops and removes service definitions whose executable is no longer installed. */
84
+ export declare function removeStaleServices(options: RemoveStaleServicesOptions): Promise<void>;
65
85
  /**
66
86
  * The ordered commands that realign the whole stack.
67
87
  *
@@ -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/dist/update.d.ts CHANGED
@@ -73,7 +73,10 @@ export type ReleaseFetcher = (repo: string) => Promise<ReleaseInfo>;
73
73
  export type AssetDownloader = (asset: ReleaseAsset) => Promise<Uint8Array>;
74
74
  export type TarballExtractor = (tarball: Uint8Array, intoDir: string) => Promise<void>;
75
75
  export type RestartQueuer = (home: string, binDir: string, trigger: "update") => Promise<RestartQueueReceipt>;
76
- export type UpdateCommandRunner = (command: readonly string[]) => Promise<number>;
76
+ export interface UpdateCommandOptions {
77
+ readonly allowFailure?: boolean;
78
+ }
79
+ export type UpdateCommandRunner = (command: readonly string[], options?: UpdateCommandOptions) => Promise<number>;
77
80
  type UpdateServiceOptions = Pick<InstallServicesOptions, "launchAgentsDir" | "unitDir" | "loginPathRunner" | "writeFile">;
78
81
  export interface UpdateDeps {
79
82
  readonly fetchLatestRelease?: ReleaseFetcher;
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.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.2.3",
3
+ "version": "0.3.1",
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.2.3",
45
- "@gajae-gateway/protocol": "0.2.3"
44
+ "@gajae-gateway/sdk": "0.3.1",
45
+ "@gajae-gateway/protocol": "0.3.1"
46
46
  },
47
47
  "engines": {
48
48
  "bun": ">=1.4.0"
package/src/list.ts CHANGED
@@ -159,6 +159,7 @@ export const MONITOR_COLUMNS: readonly Column<MonitorListRow>[] = [
159
159
  },
160
160
  { name: "events", value: (row) => [...row.monitor.eventTypes] },
161
161
  { name: "target", value: (row) => (row.monitor.channelTarget ? originKey(row.monitor.channelTarget.origin) : null) },
162
+ { name: "reportTo", value: (row) => (row.monitor.reportTo ? originKey(row.monitor.reportTo) : null) },
162
163
  { name: "enabled", value: (row) => row.monitor.enabled },
163
164
  ];
164
165
 
package/src/main.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
- import { isAbsolute } from "node:path";
3
+ import { isAbsolute, resolve } from "node:path";
4
4
 
5
5
  import type {
6
6
  MonitorEventOperatorResult,
@@ -8,6 +8,7 @@ import type {
8
8
  MonitorRecord,
9
9
  MonitorScheduleProjection,
10
10
  MonitorSpec,
11
+ OpsCycleParams,
11
12
  OpsCycleResult,
12
13
  OpsDeliveriesParams,
13
14
  OpsDeliveriesResult,
@@ -22,7 +23,7 @@ import type {
22
23
  WorkStatusResult,
23
24
  WorkSteerResult,
24
25
  } from "@gajae-gateway/protocol";
25
- import { LOOPBACK_ORIGIN, originKey, WORK_JOBS_MAX_LIMIT } from "@gajae-gateway/protocol";
26
+ import { LOOPBACK_ORIGIN, OPS_CYCLE_MAX_LIMIT, originKey, WORK_JOBS_MAX_LIMIT } from "@gajae-gateway/protocol";
26
27
 
27
28
  import { GajaewayClient } from "@gajae-gateway/sdk";
28
29
  import pkg from "../package.json";
@@ -85,7 +86,7 @@ export const COMMANDS = [
85
86
  ] as const;
86
87
 
87
88
  export const CLI_USAGE =
88
- "usage: gajaeway [--version] [--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 ... (settle <eventId>|retry <eventId>|test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] [--notify originKey (start only)] <text>|work status <name>|work steer <name> <text>|work retire [--force] <name>|work retire --all-dead|work jobs [--limit N] [--offset N]|ops backup <path>|ops deliveries [--since ISO] [--state S] [--limit N] [--json]|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--json]|ops integrity|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux]|migrate [--source PATH] [--target PATH] [--dry-run]|update [--check] [--force] [--bin-dir DIR] [--no-restart]|setup [--from-env] [--adapters discord,slack,telegram] [--owner ID] [--discord-app-id ID]|setup --status|setup --broker-agent [--from DIR] (work run waits for a response; caller timeout does not end the attempt); cron timezone is an IANA zone and defaults to the gateway host's local timezone";
89
+ "usage: gajaeway [--version] [--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 ... (settle <eventId>|retry <eventId>|test <id> [--type T] [--payload J] [--wait[=SECONDS]])|work run|start <name> [--cwd DIR] [--repo PATH|URL [--base REF]] [--resume] [--model ID|--preset NAME] [--notify originKey (start only)] <text>|work status <name>|work steer <name> <text>|work retire [--force] <name>|work retire --all-dead|work jobs [--limit N] [--offset N]|ops backup <path>|ops deliveries [--since ISO] [--state S] [--limit N] [--json]|ops redeliver <deliveryId>|ops redeliver --since <iso>|ops cycle [--limit N] [--offset N] [--json]|ops integrity|ops restart-stack [--status]|services install|repair --bin-dir DIR [--launch-agents-dir DIR] [--unit-dir DIR] [--platform darwin|linux]|migrate [--source PATH] [--target PATH] [--dry-run]|update [--check] [--force] [--bin-dir DIR] [--no-restart]|setup [--from-env] [--adapters discord,slack,telegram] [--owner ID] [--discord-app-id ID]|setup --status|setup --broker-agent [--from DIR] (work run waits for a response; caller timeout does not end the attempt); cron timezone is an IANA zone and defaults to the gateway host's local timezone";
89
90
 
90
91
  /** Usage errors exit 2, as `gajaeway-gateway` does; 1 stays a runtime failure. */
91
92
  export const USAGE_EXIT_CODE = 2;
@@ -309,10 +310,24 @@ function waitForMonitorStage(client: GajaewayClient, eventId: string, timeoutSec
309
310
  * - The aggregate phase line always prints.
310
311
  * - Any gate prints under `gates:` and forces exit code 1 — a gated cycle is
311
312
  * never reported as healthy, so scripting cannot mistake it for idle.
313
+ * - Session details are paged; gates and census totals cover the full home.
312
314
  * - `--json` emits the typed OpsCycleResult verbatim; the exit-code contract
313
315
  * is identical.
314
316
  */
317
+ const OPS_CYCLE_PAGING_UNSUPPORTED =
318
+ "ops.cycle paging is unsupported by the running gateway; restart the gateway after updating it";
319
+
320
+ function hasCyclePagingMetadata(cycle: OpsCycleResult): boolean {
321
+ return (
322
+ Number.isSafeInteger(cycle.sessionsTotal) &&
323
+ cycle.sessionsTotal >= 0 &&
324
+ Number.isSafeInteger(cycle.sessionsOffset) &&
325
+ cycle.sessionsOffset >= 0
326
+ );
327
+ }
328
+
315
329
  export function renderCycle(cycle: OpsCycleResult): string[] {
330
+ if (!hasCyclePagingMetadata(cycle)) throw new Error(OPS_CYCLE_PAGING_UNSUPPORTED);
316
331
  const lines: string[] = [];
317
332
  lines.push(`phase: ${cycle.phase}`);
318
333
  if (cycle.gates.length > 0) lines.push(`gates: ${cycle.gates.join(", ")}`);
@@ -363,15 +378,20 @@ export function renderCycle(cycle: OpsCycleResult): string[] {
363
378
  lines.push(
364
379
  `monitor authoring lost: ${cycle.monitorAuthoringLost.map((m) => `${m.eventType}=${m.consecutive} (last ${m.lastFiredAt})`).join(" ")}`,
365
380
  );
366
- if (cycle.sessions.length > 0) {
367
- lines.push("sessions:");
381
+ if (cycle.sessionsTotal > 0 && cycle.sessions.length === 0) {
382
+ lines.push(`sessions: none at offset ${cycle.sessionsOffset} of ${cycle.sessionsTotal}`);
383
+ } else if (cycle.sessions.length > 0) {
384
+ const shownEnd = cycle.sessionsOffset + cycle.sessions.length;
385
+ lines.push(
386
+ `sessions: ${cycle.sessionsOffset + 1}-${shownEnd} of ${cycle.sessionsTotal}${shownEnd < cycle.sessionsTotal ? ` (next: --offset ${shownEnd})` : ""}`,
387
+ );
368
388
  lines.push("INDEX ORIGIN EPOCH SESSION PENDING UNSETTLED OLDEST");
369
389
  for (const [index, session] of cycle.sessions.entries()) {
370
390
  const sessionId = session.sessionId === "" ? "(rebinding)" : session.sessionId.slice(0, 11);
371
391
  const oldest =
372
392
  session.oldestUnsettledAgeMs === null ? "-" : `${Math.round(session.oldestUnsettledAgeMs / 1000)}s`;
373
393
  lines.push(
374
- `${String(index).padEnd(6)} ${session.originKey.padEnd(43)} ${String(session.epoch).padEnd(6)} ${sessionId.padEnd(12)} ${String(session.pendingInbound).padEnd(8)} ${String(session.unsettledDeliveries).padEnd(10)} ${oldest}`,
394
+ `${String(cycle.sessionsOffset + index).padEnd(6)} ${session.originKey.padEnd(43)} ${String(session.epoch).padEnd(6)} ${sessionId.padEnd(12)} ${String(session.pendingInbound).padEnd(8)} ${String(session.unsettledDeliveries).padEnd(10)} ${oldest}`,
375
395
  );
376
396
  }
377
397
  }
@@ -410,7 +430,36 @@ export function sloExitCode(result: OpsSloResult): number {
410
430
  }
411
431
 
412
432
  const OPS_USAGE =
413
- "usage: gajaeway ops backup <path>|deliveries [--since ISO] [--state S] [--limit N] [--json]|redeliver <deliveryId>|redeliver --since <iso>|slo [--days N] [--json]|cycle [--json]|integrity|restart-stack [--status]";
433
+ "usage: gajaeway ops backup <path>|deliveries [--since ISO] [--state S] [--limit N] [--json]|redeliver <deliveryId>|redeliver --since <iso>|slo [--days N] [--json]|cycle [--limit N] [--offset N] [--json]|integrity|restart-stack [--status]";
434
+
435
+ const OPS_CYCLE_USAGE = "usage: gajaeway ops cycle [--limit N] [--offset N] [--json]";
436
+
437
+ function parseOpsCycleArgs(args: readonly string[]): { params: OpsCycleParams; json: boolean } {
438
+ const params: { limit?: number; offset?: number } = {};
439
+ const seen = new Set<string>();
440
+ let json = false;
441
+ for (let index = 0; index < args.length; index++) {
442
+ const flag = args[index];
443
+ if (flag === "--json") {
444
+ if (json) throw new Error(OPS_CYCLE_USAGE);
445
+ json = true;
446
+ continue;
447
+ }
448
+ if (flag !== "--limit" && flag !== "--offset") throw new Error(OPS_CYCLE_USAGE);
449
+ if (seen.has(flag)) throw new Error(OPS_CYCLE_USAGE);
450
+ seen.add(flag);
451
+ const value = args[++index];
452
+ if (!value || value.startsWith("--") || !/^\d+$/.test(value)) throw new Error(OPS_CYCLE_USAGE);
453
+ const number = Number(value);
454
+ if (!Number.isSafeInteger(number)) throw new Error(OPS_CYCLE_USAGE);
455
+ if (flag === "--limit") {
456
+ if (number < 1 || number > OPS_CYCLE_MAX_LIMIT) throw new Error(OPS_CYCLE_USAGE);
457
+ params.limit = number;
458
+ } else params.offset = number;
459
+ }
460
+ return { params, json };
461
+ }
462
+
414
463
  function parseOpsSloArgs(args: readonly string[]): { params: OpsSloParams; json: boolean } {
415
464
  let days = 7;
416
465
  let json = false;
@@ -486,7 +535,7 @@ export function renderDeliveries(result: OpsDeliveriesResult): string[] {
486
535
  `deliveries: ${result.rows.length}`,
487
536
  ...result.rows.map(
488
537
  (row) =>
489
- `${row.createdAt} ${row.state} delivery=${row.deliveryId} turn=${row.turnId} origin=${row.originKey} conversation=${row.conversationId} text=${JSON.stringify(row.textPrefix)}`,
538
+ `${row.createdAt} ${row.state} delivery=${row.deliveryId} turn=${row.turnId} origin=${row.originKey} conversation=${row.conversationId} lastError=${row.lastError ?? "-"} text=${JSON.stringify(row.textPrefix)}`,
490
539
  ),
491
540
  ];
492
541
  }
@@ -700,6 +749,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
700
749
  throw new Error(`unknown ops command: ${command ?? "(missing)"}\n${OPS_USAGE}`);
701
750
  const deliveries = command === "deliveries" ? parseOpsDeliveriesArgs(parsed.rest.slice(1)) : undefined;
702
751
  const slo = command === "slo" ? parseOpsSloArgs(parsed.rest.slice(1)) : undefined;
752
+ const cycle = command === "cycle" ? parseOpsCycleArgs(parsed.rest.slice(1)) : undefined;
703
753
  if (command === "restart-stack") {
704
754
  // Deliberately socket-free: the reason to run this is a gateway that
705
755
  // has to come back, so it must not need the gateway to answer first.
@@ -752,14 +802,14 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
752
802
  } else if (redeliverParams)
753
803
  console.log(JSON.stringify(await client.request("ops.redeliver", redeliverParams)));
754
804
  else if (command === "integrity") console.log(JSON.stringify(await client.request("ops.integrity")));
755
- else if (command === "cycle") {
756
- const cycle = await client.opsCycle();
757
- if (parsed.rest[1] === "--json") console.log(JSON.stringify(cycle));
758
- else if (parsed.rest[1]) throw new Error("usage: gajaeway ops cycle [--json]");
759
- else for (const line of renderCycle(cycle)) console.log(line);
805
+ else if (cycle) {
806
+ const result = await client.opsCycle(cycle.params);
807
+ if (!hasCyclePagingMetadata(result)) throw new Error(OPS_CYCLE_PAGING_UNSUPPORTED);
808
+ if (cycle.json) console.log(JSON.stringify(result));
809
+ else for (const line of renderCycle(result)) console.log(line);
760
810
  // Fail-closed: a gated/degraded cycle exits non-zero even though the
761
811
  // request itself succeeded, so scripts can never read it as healthy.
762
- process.exitCode = cycleExitCode(cycle);
812
+ process.exitCode = cycleExitCode(result);
763
813
  } else if (slo) {
764
814
  const result = await client.opsSlo(slo.params);
765
815
  if (slo.json) console.log(JSON.stringify(result));
@@ -898,7 +948,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
898
948
  case "work": {
899
949
  const [command, ...args] = parsed.rest;
900
950
  const usage =
901
- 'usage: gajaeway work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] "<task text>"|status <name>|steer <name> <text>|retire <name>|jobs';
951
+ 'usage: gajaeway work run|start <name> [--cwd DIR] [--repo PATH|URL [--base REF]] [--resume] [--model ID|--preset NAME] "<task text>"|status <name>|steer <name> <text>|retire <name>|jobs';
902
952
  if (command === "status" || command === "steer") {
903
953
  const name = args[0];
904
954
  const text = args.slice(1).join(" ").trim();
@@ -1020,7 +1070,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
1020
1070
  cwd = value;
1021
1071
  } else if (arg === "--repo") {
1022
1072
  if (repo !== undefined) throw new Error(usage);
1023
- repo = value;
1073
+ repo = value.includes("://") || /^[^/@\s]+@[^:/\s]+:/.test(value) ? value : resolve(value);
1024
1074
  } else if (arg === "--base") {
1025
1075
  if (base !== undefined) throw new Error(usage);
1026
1076
  base = value;
@@ -1034,6 +1084,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
1034
1084
  }
1035
1085
  const text = textParts.join(" ").trim();
1036
1086
  if (!name || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name) || !text) throw new Error(usage);
1087
+ if (base !== undefined && repo === undefined) throw new Error(usage);
1037
1088
  // This is a caller response-wait budget, never an attempt deadline.
1038
1089
  // Timeout/disconnect leaves the attempt observable via work.status.
1039
1090
  const client = await connectGatewaySocket(parsed.socket, {
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { access, mkdir, readFile, readlink, rename, stat, writeFile } from "node:fs/promises";
2
+ import { access, mkdir, readFile, realpath, rename, stat, writeFile } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
- import { dirname, join } from "node:path";
4
+ import { basename, dirname, join } from "node:path";
5
5
  import {
6
6
  acquireLease,
7
7
  homeLayout,
@@ -13,9 +13,11 @@ import {
13
13
  } from "@gajae-gateway/home";
14
14
 
15
15
  import {
16
+ adapterConfigPath,
16
17
  BROKER_UNIT,
17
18
  currentPlatform,
18
19
  launchAgentPlistPath,
20
+ removeStaleServices,
19
21
  restartOrder,
20
22
  restartStackCommands,
21
23
  type ServicePlatform,
@@ -295,7 +297,26 @@ async function runRestartStackWithLease(options: RunRestartOptions): Promise<Res
295
297
  const sleep = options.sleep ?? ((ms: number) => Bun.sleep(ms));
296
298
  const timeoutMs = options.verifyTimeoutMs ?? VERIFY_TIMEOUT_MS;
297
299
  const pollMs = options.pollMs ?? POLL_MS;
298
- const binDir = options.binDir ?? process.env.GAJAEWAY_BIN_DIR ?? dirname(process.execPath);
300
+ const env = options.env ?? process.env;
301
+ const deployedExecutable = await realpath(process.execPath).catch(() => undefined);
302
+ const installedBinDir =
303
+ options.binDir ??
304
+ env.GAJAEWAY_BIN_DIR ??
305
+ (deployedExecutable !== undefined && basename(deployedExecutable).startsWith("gajaeway")
306
+ ? dirname(deployedExecutable)
307
+ : undefined);
308
+ const binDir = installedBinDir ?? dirname(process.execPath);
309
+ if (installedBinDir !== undefined) {
310
+ await removeStaleServices({
311
+ binDir: installedBinDir,
312
+ platform,
313
+ uid: options.uid,
314
+ env,
315
+ ...(options.launchAgentsDir === undefined ? {} : { launchAgentsDir: options.launchAgentsDir }),
316
+ ...(options.unitDir === undefined ? {} : { unitDir: options.unitDir }),
317
+ run: runner,
318
+ });
319
+ }
299
320
 
300
321
  const originalPids = new Map<string, number | undefined>();
301
322
  for (const spec of restartOrder()) {
@@ -337,6 +358,20 @@ async function runRestartStackWithLease(options: RunRestartOptions): Promise<Res
337
358
  await writeReceipt(options.home, receipt);
338
359
  continue;
339
360
  }
361
+ // An installed unit can still be unable to start: an adapter whose
362
+ // `adapter-<platform>.json` is absent exits on the credential read, and
363
+ // launchd KeepAlive turns that into a crash loop. Skip it the same way an
364
+ // uninstalled service is skipped — the rule `gajaeway update` already
365
+ // applies when it renders adapter units — so one unconfigured adapter
366
+ // cannot abort the rest of the sequence.
367
+ const adapterSpec = serviceSpecs().find((candidate) => candidate.label === step.label);
368
+ const adapterConfig = adapterSpec === undefined ? undefined : adapterConfigPath(options.home, adapterSpec.id);
369
+ if (adapterConfig !== undefined && !(await Bun.file(adapterConfig).exists())) {
370
+ step.result = "skipped";
371
+ step.detail = "adapter is not configured";
372
+ await writeReceipt(options.home, receipt);
373
+ continue;
374
+ }
340
375
 
341
376
  if (step.label === "dev.gajaeway.broker" && receipt.trigger === "update") {
342
377
  const stopCommand = serviceStopCommand(platform, options.uid);
@@ -389,12 +424,7 @@ async function runRestartStackWithLease(options: RunRestartOptions): Promise<Res
389
424
  issuedAt = now();
390
425
  let command = step.command;
391
426
  let status = await runner(command);
392
- if (
393
- status !== 0 &&
394
- receipt.trigger === "update" &&
395
- platform === "darwin" &&
396
- (await probe(step.label)) === undefined
397
- ) {
427
+ if (status !== 0 && platform === "darwin" && (await probe(step.label)) === undefined) {
398
428
  command = serviceBootstrapCommand(options, platform, step.label);
399
429
  step.command = command;
400
430
  issuedAt = now();
package/src/services.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
1
+ import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
2
  import { homedir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { homeLayout } from "@gajae-gateway/home";
@@ -26,6 +26,13 @@ export interface ResolvePathOptions {
26
26
 
27
27
  /** Service managers this CLI can write definitions for. */
28
28
  export type ServicePlatform = "darwin" | "linux";
29
+ export interface ServiceCommandOptions {
30
+ readonly allowFailure?: boolean;
31
+ }
32
+ export type ServiceCommandRunner = (
33
+ command: readonly string[],
34
+ options?: ServiceCommandOptions,
35
+ ) => number | PromiseLike<number>;
29
36
 
30
37
  export interface InstallServicesOptions {
31
38
  readonly binDir: string;
@@ -106,6 +113,16 @@ export function serviceSpecs(): readonly ServiceSpec[] {
106
113
  return SERVICE_SPECS;
107
114
  }
108
115
 
116
+ /**
117
+ * The `adapter-<platform>.json` an adapter reads at startup, or undefined for services
118
+ * that are not adapters. A unit whose file is absent can never come up — the adapter
119
+ * exits on the credential read — so supervisors skip it instead of looping on it.
120
+ */
121
+ export function adapterConfigPath(home: string, specId: string): string | undefined {
122
+ if (!specId.startsWith("adapter-")) return undefined;
123
+ return join(home, `adapter-${specId.slice("adapter-".length)}.json`);
124
+ }
125
+
109
126
  function homeForEnvironment(env: NodeJS.ProcessEnv): string {
110
127
  return env.GAJAEWAY_HOME || join(env.HOME || homedir(), ".gajaeway");
111
128
  }
@@ -288,6 +305,55 @@ export function systemdUnitPath(spec: ServiceSpec, unitDir: string): string {
288
305
  return join(unitDir, systemdUnitName(spec));
289
306
  }
290
307
 
308
+ export interface RemoveStaleServicesOptions extends Pick<InstallServicesOptions, "launchAgentsDir" | "unitDir"> {
309
+ readonly binDir: string;
310
+ readonly platform: ServicePlatform;
311
+ readonly uid?: number;
312
+ readonly env?: NodeJS.ProcessEnv;
313
+ readonly reloadSystemd?: boolean;
314
+ readonly run: ServiceCommandRunner;
315
+ }
316
+
317
+ /** Stops and removes service definitions whose executable is no longer installed. */
318
+ export async function removeStaleServices(options: RemoveStaleServicesOptions): Promise<void> {
319
+ const env = options.env ?? process.env;
320
+ const userHome = env.HOME || homedir();
321
+ const definitionDir =
322
+ options.platform === "darwin"
323
+ ? (options.launchAgentsDir ?? join(userHome, "Library", "LaunchAgents"))
324
+ : (options.unitDir ?? systemdUnitDir(env, userHome));
325
+ const expandedDefinitionDir = expandHome(definitionDir, userHome);
326
+ const staleDefinitions: Array<{ readonly label: string; readonly path: string; readonly unitName: string }> = [];
327
+ for (const spec of SERVICE_SPECS) {
328
+ if (await Bun.file(join(options.binDir, spec.binary)).exists()) continue;
329
+ const path =
330
+ options.platform === "darwin"
331
+ ? launchAgentPlistPath(spec, expandedDefinitionDir)
332
+ : systemdUnitPath(spec, expandedDefinitionDir);
333
+ if (await Bun.file(path).exists())
334
+ staleDefinitions.push({ label: spec.label, path, unitName: systemdUnitName(spec) });
335
+ }
336
+ const execute = async (command: readonly string[], allowFailure = false): Promise<number> => {
337
+ const exitCode = await options.run(command, allowFailure ? { allowFailure: true } : undefined);
338
+ if (exitCode !== 0 && !allowFailure) throw new Error(`${command.join(" ")} exited with status ${exitCode}`);
339
+ return exitCode;
340
+ };
341
+ if (options.platform === "linux") {
342
+ if (staleDefinitions.length === 0) return;
343
+ await execute(["systemctl", "--user", "disable", "--now", ...staleDefinitions.map(({ unitName }) => unitName)]);
344
+ for (const { path } of staleDefinitions) await rm(path, { force: true });
345
+ if (options.reloadSystemd ?? true) await execute(["systemctl", "--user", "daemon-reload"]);
346
+ return;
347
+ }
348
+ const target = `gui/${options.uid ?? process.getuid?.() ?? 0}`;
349
+ for (const { label, path } of staleDefinitions) {
350
+ const serviceTarget = `${target}/${label}`;
351
+ if ((await execute(["launchctl", "print", serviceTarget], true)) === 0)
352
+ await execute(["launchctl", "bootout", serviceTarget]);
353
+ await rm(path, { force: true });
354
+ }
355
+ }
356
+
291
357
  /**
292
358
  * The ordered commands that realign the whole stack.
293
359
  *
@@ -375,10 +441,10 @@ export async function installServices(options: InstallServicesOptions): Promise<
375
441
  await mkdir(targetDir, { recursive: true, mode: 0o700 });
376
442
  const specs: ServiceSpec[] = [];
377
443
  for (const spec of SERVICE_SPECS) {
378
- if (options.configuredAdaptersOnly && spec.id.startsWith("adapter-")) {
379
- const adapter = spec.id.slice("adapter-".length);
380
- if (!(await Bun.file(join(home, `adapter-${adapter}.json`)).exists())) continue;
381
- }
444
+ if (!(await Bun.file(join(binDir, spec.binary)).exists())) continue;
445
+ const adapterConfig = adapterConfigPath(home, spec.id);
446
+ if (options.configuredAdaptersOnly && adapterConfig !== undefined && !(await Bun.file(adapterConfig).exists()))
447
+ continue;
382
448
  specs.push(spec);
383
449
  }
384
450
  const definitions = specs.map((spec) =>
package/src/update.ts CHANGED
@@ -20,6 +20,7 @@ import { launchRestartStack } from "./restart-stack";
20
20
  import {
21
21
  type InstallServicesOptions,
22
22
  installServices,
23
+ removeStaleServices,
23
24
  type ServicePlatform,
24
25
  serviceSpecs,
25
26
  systemdUnitName,
@@ -39,8 +40,6 @@ export const UPDATE_USAGE = "usage: gajaeway update [--check] [--force] [--bin-d
39
40
 
40
41
  export const DEFAULT_RELEASE_REPO = "Yeachan-Heo/gajae-way";
41
42
  const RELEASE_REPO_OVERRIDE_ENV = "GAJAEWAY_UPDATE_REPO";
42
- /** The release manifest carrying the gjc pin; installed beside the binaries. */
43
- const PIN_MANIFEST = "package.json";
44
43
  /** A fork can point updates at its own releases; the declared upstream stays the default. */
45
44
  export function releaseRepo(env: NodeJS.ProcessEnv = process.env): string {
46
45
  const override = env[RELEASE_REPO_OVERRIDE_ENV]?.trim();
@@ -214,7 +213,10 @@ export type ReleaseFetcher = (repo: string) => Promise<ReleaseInfo>;
214
213
  export type AssetDownloader = (asset: ReleaseAsset) => Promise<Uint8Array>;
215
214
  export type TarballExtractor = (tarball: Uint8Array, intoDir: string) => Promise<void>;
216
215
  export type RestartQueuer = (home: string, binDir: string, trigger: "update") => Promise<RestartQueueReceipt>;
217
- export type UpdateCommandRunner = (command: readonly string[]) => Promise<number>;
216
+ export interface UpdateCommandOptions {
217
+ readonly allowFailure?: boolean;
218
+ }
219
+ export type UpdateCommandRunner = (command: readonly string[], options?: UpdateCommandOptions) => Promise<number>;
218
220
 
219
221
  type UpdateServiceOptions = Pick<
220
222
  InstallServicesOptions,
@@ -262,10 +264,10 @@ async function readPinnedGjcVersion(path: string): Promise<string> {
262
264
  return version;
263
265
  }
264
266
 
265
- async function defaultUpdateCommandRunner(command: readonly string[]): Promise<number> {
267
+ async function defaultUpdateCommandRunner(command: readonly string[], options?: UpdateCommandOptions): Promise<number> {
266
268
  const child = Bun.spawn([...command], { stdin: "ignore", stdout: "ignore", stderr: "pipe" });
267
269
  const [stderr, exitCode] = await Promise.all([new Response(child.stderr).text(), child.exited]);
268
- if (exitCode !== 0) {
270
+ if (exitCode !== 0 && !options?.allowFailure) {
269
271
  const detail = stderr.trim();
270
272
  throw new Error(`${command.join(" ")} exited with status ${exitCode}${detail.length === 0 ? "" : `: ${detail}`}`);
271
273
  }
@@ -281,7 +283,22 @@ async function installUpdatedServices(options: {
281
283
  }): Promise<boolean> {
282
284
  const { home, binDir, platform, noRestart, deps } = options;
283
285
  const brokerProvisioned = await exists(homeLayout(home).brokerProvisionManifest);
284
- const env = { ...(deps.env ?? process.env), GAJAEWAY_HOME: home };
286
+ const env: NodeJS.ProcessEnv = { ...(deps.env ?? process.env), GAJAEWAY_HOME: home };
287
+ const run = deps.serviceRunner ?? defaultUpdateCommandRunner;
288
+ const execute = async (command: readonly string[]): Promise<void> => {
289
+ const exitCode = await run(command);
290
+ if (exitCode !== 0) throw new Error(`${command.join(" ")} exited with status ${exitCode}`);
291
+ };
292
+ if (!noRestart) {
293
+ await removeStaleServices({
294
+ binDir,
295
+ platform,
296
+ env,
297
+ reloadSystemd: false,
298
+ ...deps.serviceOptions,
299
+ run,
300
+ });
301
+ }
285
302
  await installServices({
286
303
  binDir,
287
304
  platform,
@@ -291,15 +308,11 @@ async function installUpdatedServices(options: {
291
308
  ...deps.serviceOptions,
292
309
  });
293
310
  if (platform === "linux") {
294
- const run = deps.serviceRunner ?? defaultUpdateCommandRunner;
295
- const execute = async (command: readonly string[]): Promise<void> => {
296
- const exitCode = await run(command);
297
- if (exitCode !== 0) throw new Error(`${command.join(" ")} exited with status ${exitCode}`);
298
- };
299
311
  await execute(["systemctl", "--user", "daemon-reload"]);
300
312
  if (!noRestart) {
301
313
  const enableUnits: string[] = [];
302
314
  for (const spec of serviceSpecs()) {
315
+ if (!(await exists(join(binDir, spec.binary)))) continue;
303
316
  if (spec.id === "broker" && !brokerProvisioned) continue;
304
317
  if (
305
318
  spec.id.startsWith("adapter-") &&
@@ -362,7 +375,7 @@ export async function runUpdate(options: RunUpdateOptions): Promise<UpdateResult
362
375
  throw new Error(`release tarball is missing core binaries: ${missingCore.join(", ")}`);
363
376
  await assertStagedBinariesUsable(staged, toInstall);
364
377
 
365
- const gjcVersion = await readPinnedGjcVersion(join(staged.dir, PIN_MANIFEST));
378
+ const gjcVersion = await readPinnedGjcVersion(join(staged.dir, "package.json"));
366
379
  await installPinnedGjc({
367
380
  home: options.home,
368
381
  version: gjcVersion,
@@ -372,20 +385,22 @@ export async function runUpdate(options: RunUpdateOptions): Promise<UpdateResult
372
385
  const stamp = new Date((deps.now ?? Date.now)()).toISOString().replace(/[-:]/g, "").slice(0, 15);
373
386
  const backupDir = join(binDir, `backup-${current}-${stamp}Z`);
374
387
  await mkdir(backupDir, { recursive: false });
375
- // The compiled gateway and broker host read the gjc pin from the package.json
376
- // beside them; a stale one makes the new binaries refuse the gjc just installed.
377
- const replaced = [...toInstall, PIN_MANIFEST];
378
- for (const name of replaced) {
388
+ for (const name of toInstall) {
379
389
  const target = join(binDir, name);
380
390
  if (await exists(target)) await copyFile(target, join(backupDir, name));
381
391
  }
382
- for (const name of replaced) {
392
+ const packagePath = join(binDir, "package.json");
393
+ if (await exists(packagePath)) await copyFile(packagePath, join(backupDir, "package.json"));
394
+ for (const name of toInstall) {
383
395
  const stagedPath = join(staged.dir, name);
384
396
  const tempPath = join(binDir, `.update-${name}`);
385
397
  await copyFile(stagedPath, tempPath);
386
- await chmod(tempPath, name === PIN_MANIFEST ? 0o644 : 0o755);
398
+ await chmod(tempPath, 0o755);
387
399
  await rename(tempPath, join(binDir, name));
388
400
  }
401
+ const packageTempPath = join(binDir, ".update-package.json");
402
+ await copyFile(join(staged.dir, "package.json"), packageTempPath);
403
+ await rename(packageTempPath, packagePath);
389
404
  await writeFile(releaseMarkerPath(binDir), `${latest}\n`, "utf8");
390
405
  const brokerNotEnabled = await installUpdatedServices({
391
406
  home: options.home,