@gajae-gateway/cli 0.2.3 → 0.3.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/list.d.ts.map +1 -1
- package/dist/main.d.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +140 -55
- package/dist/restart-stack.d.ts.map +1 -1
- package/dist/services.d.ts +20 -0
- package/dist/services.d.ts.map +1 -1
- package/dist/update.d.ts +4 -1
- package/dist/update.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/list.ts +1 -0
- package/src/main.ts +6 -5
- package/src/restart-stack.ts +39 -9
- package/src/services.ts +71 -5
- package/src/update.ts +33 -18
package/dist/list.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAmBpD,MAAM,WAAW,MAAM,CAAC,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CACnD;AAED,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAEtE;AASD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,WAAW,CAyBvG;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,CAGvG;AAED,oFAAoF;AACpF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,WAAW,GAAG,KAAK,CAAC;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAItG;AAED,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKjD;AAED,wBAAgB,WAAW,CAAC,CAAC,EAC5B,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,EAC7B,OAAO,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAC/C,MAAM,EAAE,CAcV;AAED,wBAAgB,WAAW,CAAC,CAAC,EAC5B,OAAO,EAAE,SAAS,MAAM,CAAC,CAAC,CAAC,EAAE,EAC7B,OAAO,EAAE,aAAa,CAAC;IAAE,GAAG,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAC/C,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAIhC;AAgBD,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI,CAAC;CACpD;AAED,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../src/list.ts"],"names":[],"mappings":"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"}
|
package/dist/main.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare function socketPath(home?: string | undefined): string;
|
|
|
13
13
|
* never after, so the list is checked up front.
|
|
14
14
|
*/
|
|
15
15
|
export declare const COMMANDS: readonly ["status", "shutdown", "chat", "daemon", "sessions", "ops", "memory", "monitors", "work", "services", "migrate", "update", "setup"];
|
|
16
|
-
export declare const CLI_USAGE = "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";
|
|
16
|
+
export declare const CLI_USAGE = "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 [--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";
|
|
17
17
|
/** Usage errors exit 2, as `gajaeway-gateway` does; 1 stays a runtime failure. */
|
|
18
18
|
export declare const USAGE_EXIT_CODE = 2;
|
|
19
19
|
/** The usage text when `command` cannot be dispatched, undefined when it can. */
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAMX,cAAc,EAEd,mBAAmB,EAEnB,YAAY,EASZ,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAcpD,OAAO,EAEN,KAAK,oBAAoB,EAEzB,KAAK,iBAAiB,EAItB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,sBAAsB,EAAmB,KAAK,eAAe,EAAgB,MAAM,YAAY,CAAC;AAC9G,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,SAAS,CAAC;AACzD,OAAO,EAA4C,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AASrF,wBAAgB,UAAU,CAAC,IAAI,qBAA4B,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,8IAcX,CAAC;AAEX,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAIA,OAAO,KAAK,EAMX,cAAc,EAEd,mBAAmB,EAEnB,YAAY,EASZ,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAcpD,OAAO,EAEN,KAAK,oBAAoB,EAEzB,KAAK,iBAAiB,EAItB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,sBAAsB,EAAmB,KAAK,eAAe,EAAgB,MAAM,YAAY,CAAC;AAC9G,OAAO,EAAE,KAAK,eAAe,EAAY,MAAM,SAAS,CAAC;AACzD,OAAO,EAA4C,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC;AASrF,wBAAgB,UAAU,CAAC,IAAI,qBAA4B,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,8IAcX,CAAC;AAEX,eAAO,MAAM,SAAS,sxCAC8vC,CAAC;AAErxC,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,mEAAmE;IACnE,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,OAAO,GAAG,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,gBAAgB,CAAC,CAAC;IACnG,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;IACF,kFAAkF;IAClF,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;CAC7B;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;AA4ID;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,EAAE,CAgE3D;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAE3D;AACD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,EAAE,CAkBxD;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAExD;AAyED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,MAAM,EAAE,CAStE;AA8DD;;;;GAIG;AACH,wBAAsB,YAAY,CACjC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,SAAU,EAAE,4BAA4B;AACjD,cAAc,SAAQ,GACpB,OAAO,CAAC;IAAE,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,eAAe,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+BpH;AAED,wBAAsB,IAAI,CAAC,IAAI,WAAwB,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAugBjG"}
|
package/dist/main.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/main.ts
|
|
5
|
-
import { isAbsolute } from "path";
|
|
5
|
+
import { isAbsolute, resolve } from "path";
|
|
6
6
|
import { LOOPBACK_ORIGIN, originKey as originKey2, WORK_JOBS_MAX_LIMIT } from "@gajae-gateway/protocol";
|
|
7
7
|
import { GajaewayClient } from "@gajae-gateway/sdk";
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "@gajae-gateway/cli",
|
|
11
|
-
version: "0.
|
|
11
|
+
version: "0.3.0",
|
|
12
12
|
type: "module",
|
|
13
13
|
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).",
|
|
14
14
|
license: "AGPL-3.0-only",
|
|
@@ -172,6 +172,7 @@ var MONITOR_COLUMNS = [
|
|
|
172
172
|
},
|
|
173
173
|
{ name: "events", value: (row) => [...row.monitor.eventTypes] },
|
|
174
174
|
{ name: "target", value: (row) => row.monitor.channelTarget ? originKey(row.monitor.channelTarget.origin) : null },
|
|
175
|
+
{ name: "reportTo", value: (row) => row.monitor.reportTo ? originKey(row.monitor.reportTo) : null },
|
|
175
176
|
{ name: "enabled", value: (row) => row.monitor.enabled }
|
|
176
177
|
];
|
|
177
178
|
var SESSION_COLUMNS = [
|
|
@@ -1418,12 +1419,12 @@ function parseMigrateArgs(args) {
|
|
|
1418
1419
|
|
|
1419
1420
|
// src/restart-stack.ts
|
|
1420
1421
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1421
|
-
import { access, mkdir as mkdir4, readFile as readFile5, rename as rename2, stat, writeFile as writeFile3 } from "fs/promises";
|
|
1422
|
+
import { access, mkdir as mkdir4, readFile as readFile5, realpath, rename as rename2, stat, writeFile as writeFile3 } from "fs/promises";
|
|
1422
1423
|
import { homedir as homedir3 } from "os";
|
|
1423
|
-
import { dirname, join as join7 } from "path";
|
|
1424
|
+
import { basename, dirname, join as join7 } from "path";
|
|
1424
1425
|
|
|
1425
1426
|
// src/services.ts
|
|
1426
|
-
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
|
|
1427
|
+
import { chmod as chmod2, mkdir as mkdir3, readFile as readFile4, rm as rm2, writeFile as writeFile2 } from "fs/promises";
|
|
1427
1428
|
import { homedir as homedir2 } from "os";
|
|
1428
1429
|
import { join as join6 } from "path";
|
|
1429
1430
|
import { parseRuntimeConfig, RuntimeConfigError } from "@gajae-gateway/protocol";
|
|
@@ -1473,6 +1474,11 @@ var SERVICE_SPECS = [
|
|
|
1473
1474
|
function serviceSpecs() {
|
|
1474
1475
|
return SERVICE_SPECS;
|
|
1475
1476
|
}
|
|
1477
|
+
function adapterConfigPath(home, specId) {
|
|
1478
|
+
if (!specId.startsWith("adapter-"))
|
|
1479
|
+
return;
|
|
1480
|
+
return join6(home, `adapter-${specId.slice("adapter-".length)}.json`);
|
|
1481
|
+
}
|
|
1476
1482
|
function homeForEnvironment(env) {
|
|
1477
1483
|
return env.GAJAEWAY_HOME || join6(env.HOME || homedir2(), ".gajaeway");
|
|
1478
1484
|
}
|
|
@@ -1608,6 +1614,43 @@ function launchAgentPlistPath(spec, launchAgentsDir) {
|
|
|
1608
1614
|
function systemdUnitPath(spec, unitDir) {
|
|
1609
1615
|
return join6(unitDir, systemdUnitName(spec));
|
|
1610
1616
|
}
|
|
1617
|
+
async function removeStaleServices(options) {
|
|
1618
|
+
const env = options.env ?? process.env;
|
|
1619
|
+
const userHome = env.HOME || homedir2();
|
|
1620
|
+
const definitionDir = options.platform === "darwin" ? options.launchAgentsDir ?? join6(userHome, "Library", "LaunchAgents") : options.unitDir ?? systemdUnitDir(env, userHome);
|
|
1621
|
+
const expandedDefinitionDir = expandHome2(definitionDir, userHome);
|
|
1622
|
+
const staleDefinitions = [];
|
|
1623
|
+
for (const spec of SERVICE_SPECS) {
|
|
1624
|
+
if (await Bun.file(join6(options.binDir, spec.binary)).exists())
|
|
1625
|
+
continue;
|
|
1626
|
+
const path = options.platform === "darwin" ? launchAgentPlistPath(spec, expandedDefinitionDir) : systemdUnitPath(spec, expandedDefinitionDir);
|
|
1627
|
+
if (await Bun.file(path).exists())
|
|
1628
|
+
staleDefinitions.push({ label: spec.label, path, unitName: systemdUnitName(spec) });
|
|
1629
|
+
}
|
|
1630
|
+
const execute = async (command, allowFailure = false) => {
|
|
1631
|
+
const exitCode = await options.run(command, allowFailure ? { allowFailure: true } : undefined);
|
|
1632
|
+
if (exitCode !== 0 && !allowFailure)
|
|
1633
|
+
throw new Error(`${command.join(" ")} exited with status ${exitCode}`);
|
|
1634
|
+
return exitCode;
|
|
1635
|
+
};
|
|
1636
|
+
if (options.platform === "linux") {
|
|
1637
|
+
if (staleDefinitions.length === 0)
|
|
1638
|
+
return;
|
|
1639
|
+
await execute(["systemctl", "--user", "disable", "--now", ...staleDefinitions.map(({ unitName }) => unitName)]);
|
|
1640
|
+
for (const { path } of staleDefinitions)
|
|
1641
|
+
await rm2(path, { force: true });
|
|
1642
|
+
if (options.reloadSystemd ?? true)
|
|
1643
|
+
await execute(["systemctl", "--user", "daemon-reload"]);
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1646
|
+
const target = `gui/${options.uid ?? process.getuid?.() ?? 0}`;
|
|
1647
|
+
for (const { label, path } of staleDefinitions) {
|
|
1648
|
+
const serviceTarget = `${target}/${label}`;
|
|
1649
|
+
if (await execute(["launchctl", "print", serviceTarget], true) === 0)
|
|
1650
|
+
await execute(["launchctl", "bootout", serviceTarget]);
|
|
1651
|
+
await rm2(path, { force: true });
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1611
1654
|
function restartStackCommands(platform, uid) {
|
|
1612
1655
|
if (platform === "linux")
|
|
1613
1656
|
return [
|
|
@@ -1682,11 +1725,11 @@ async function installServices(options) {
|
|
|
1682
1725
|
await mkdir3(targetDir, { recursive: true, mode: 448 });
|
|
1683
1726
|
const specs = [];
|
|
1684
1727
|
for (const spec of SERVICE_SPECS) {
|
|
1685
|
-
if (
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1728
|
+
if (!await Bun.file(join6(binDir, spec.binary)).exists())
|
|
1729
|
+
continue;
|
|
1730
|
+
const adapterConfig = adapterConfigPath(home, spec.id);
|
|
1731
|
+
if (options.configuredAdaptersOnly && adapterConfig !== undefined && !await Bun.file(adapterConfig).exists())
|
|
1732
|
+
continue;
|
|
1690
1733
|
specs.push(spec);
|
|
1691
1734
|
}
|
|
1692
1735
|
const definitions = specs.map((spec) => platform === "darwin" ? {
|
|
@@ -1872,7 +1915,23 @@ async function runRestartStackWithLease(options) {
|
|
|
1872
1915
|
const sleep = options.sleep ?? ((ms) => Bun.sleep(ms));
|
|
1873
1916
|
const timeoutMs = options.verifyTimeoutMs ?? VERIFY_TIMEOUT_MS;
|
|
1874
1917
|
const pollMs = options.pollMs ?? POLL_MS;
|
|
1875
|
-
const
|
|
1918
|
+
const env = options.env ?? process.env;
|
|
1919
|
+
const deployedExecutable = await realpath(process.execPath).catch(() => {
|
|
1920
|
+
return;
|
|
1921
|
+
});
|
|
1922
|
+
const installedBinDir = options.binDir ?? env.GAJAEWAY_BIN_DIR ?? (deployedExecutable !== undefined && basename(deployedExecutable).startsWith("gajaeway") ? dirname(deployedExecutable) : undefined);
|
|
1923
|
+
const binDir = installedBinDir ?? dirname(process.execPath);
|
|
1924
|
+
if (installedBinDir !== undefined) {
|
|
1925
|
+
await removeStaleServices({
|
|
1926
|
+
binDir: installedBinDir,
|
|
1927
|
+
platform,
|
|
1928
|
+
uid: options.uid,
|
|
1929
|
+
env,
|
|
1930
|
+
...options.launchAgentsDir === undefined ? {} : { launchAgentsDir: options.launchAgentsDir },
|
|
1931
|
+
...options.unitDir === undefined ? {} : { unitDir: options.unitDir },
|
|
1932
|
+
run: runner
|
|
1933
|
+
});
|
|
1934
|
+
}
|
|
1876
1935
|
const originalPids = new Map;
|
|
1877
1936
|
for (const spec of restartOrder()) {
|
|
1878
1937
|
if (SERVICE_LEASES[spec.id] === undefined && await isInstalled(spec.label))
|
|
@@ -1905,6 +1964,14 @@ async function runRestartStackWithLease(options) {
|
|
|
1905
1964
|
await writeReceipt(options.home, receipt);
|
|
1906
1965
|
continue;
|
|
1907
1966
|
}
|
|
1967
|
+
const adapterSpec = serviceSpecs().find((candidate) => candidate.label === step.label);
|
|
1968
|
+
const adapterConfig = adapterSpec === undefined ? undefined : adapterConfigPath(options.home, adapterSpec.id);
|
|
1969
|
+
if (adapterConfig !== undefined && !await Bun.file(adapterConfig).exists()) {
|
|
1970
|
+
step.result = "skipped";
|
|
1971
|
+
step.detail = "adapter is not configured";
|
|
1972
|
+
await writeReceipt(options.home, receipt);
|
|
1973
|
+
continue;
|
|
1974
|
+
}
|
|
1908
1975
|
if (step.label === "dev.gajaeway.broker" && receipt.trigger === "update") {
|
|
1909
1976
|
const stopCommand = serviceStopCommand(platform, options.uid);
|
|
1910
1977
|
const stopStatus = await runner(stopCommand);
|
|
@@ -1952,7 +2019,7 @@ async function runRestartStackWithLease(options) {
|
|
|
1952
2019
|
issuedAt = now();
|
|
1953
2020
|
let command = step.command;
|
|
1954
2021
|
let status = await runner(command);
|
|
1955
|
-
if (status !== 0 &&
|
|
2022
|
+
if (status !== 0 && platform === "darwin" && await probe(step.label) === undefined) {
|
|
1956
2023
|
command = serviceBootstrapCommand(options, platform, step.label);
|
|
1957
2024
|
step.command = command;
|
|
1958
2025
|
issuedAt = now();
|
|
@@ -2152,8 +2219,8 @@ function renderRestartReceipt(receipt, state = receipt.state) {
|
|
|
2152
2219
|
|
|
2153
2220
|
// src/setup.ts
|
|
2154
2221
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2155
|
-
import { chmod as chmod3, mkdir as mkdir5, readFile as readFile6, realpath, rename as rename3, rm as
|
|
2156
|
-
import { basename, dirname as dirname2, join as join8 } from "path";
|
|
2222
|
+
import { chmod as chmod3, mkdir as mkdir5, readFile as readFile6, realpath as realpath2, rename as rename3, rm as rm3, writeFile as writeFile4 } from "fs/promises";
|
|
2223
|
+
import { basename as basename2, dirname as dirname2, join as join8 } from "path";
|
|
2157
2224
|
|
|
2158
2225
|
// src/discord-setup.ts
|
|
2159
2226
|
var DEVELOPER_PORTAL_URL = "https://discord.com/developers/applications";
|
|
@@ -2463,7 +2530,7 @@ async function writePrivateFile(path, contents) {
|
|
|
2463
2530
|
await chmod3(temporary, 384);
|
|
2464
2531
|
await rename3(temporary, path);
|
|
2465
2532
|
} finally {
|
|
2466
|
-
await
|
|
2533
|
+
await rm3(temporary, { force: true });
|
|
2467
2534
|
}
|
|
2468
2535
|
}
|
|
2469
2536
|
async function readJsonObject(path) {
|
|
@@ -2660,10 +2727,10 @@ async function setupBinDir(options) {
|
|
|
2660
2727
|
const env = options.env ?? process.env;
|
|
2661
2728
|
if (env.GAJAEWAY_BIN_DIR)
|
|
2662
2729
|
return env.GAJAEWAY_BIN_DIR;
|
|
2663
|
-
const executable = await
|
|
2730
|
+
const executable = await realpath2(process.execPath).catch(() => {
|
|
2664
2731
|
return;
|
|
2665
2732
|
});
|
|
2666
|
-
if (executable !== undefined &&
|
|
2733
|
+
if (executable !== undefined && basename2(executable).startsWith("gajaeway"))
|
|
2667
2734
|
return dirname2(executable);
|
|
2668
2735
|
throw new SetupError("setup --broker-agent requires the installed gajaeway binary or an explicit bin directory");
|
|
2669
2736
|
}
|
|
@@ -2742,14 +2809,14 @@ import {
|
|
|
2742
2809
|
mkdtemp as mkdtemp2,
|
|
2743
2810
|
readdir as readdir3,
|
|
2744
2811
|
readFile as readFile7,
|
|
2745
|
-
realpath as
|
|
2812
|
+
realpath as realpath3,
|
|
2746
2813
|
rename as rename5,
|
|
2747
|
-
rm as
|
|
2814
|
+
rm as rm5,
|
|
2748
2815
|
stat as stat2,
|
|
2749
2816
|
writeFile as writeFile6
|
|
2750
2817
|
} from "fs/promises";
|
|
2751
2818
|
import { tmpdir } from "os";
|
|
2752
|
-
import { basename as
|
|
2819
|
+
import { basename as basename3, dirname as dirname3, join as join10 } from "path";
|
|
2753
2820
|
|
|
2754
2821
|
// src/gjc-install.ts
|
|
2755
2822
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
@@ -2760,9 +2827,9 @@ import {
|
|
|
2760
2827
|
mkdir as mkdir6,
|
|
2761
2828
|
mkdtemp,
|
|
2762
2829
|
readdir as readdir2,
|
|
2763
|
-
readlink
|
|
2830
|
+
readlink,
|
|
2764
2831
|
rename as rename4,
|
|
2765
|
-
rm as
|
|
2832
|
+
rm as rm4,
|
|
2766
2833
|
symlink,
|
|
2767
2834
|
writeFile as writeFile5
|
|
2768
2835
|
} from "fs/promises";
|
|
@@ -2798,7 +2865,7 @@ ${result.stderr}`);
|
|
|
2798
2865
|
}
|
|
2799
2866
|
async function currentVersion(prefix, current) {
|
|
2800
2867
|
try {
|
|
2801
|
-
const target = await
|
|
2868
|
+
const target = await readlink(current);
|
|
2802
2869
|
if (target.includes("/") || !VERSION_PATTERN.test(target))
|
|
2803
2870
|
return;
|
|
2804
2871
|
const targetPath = join9(prefix, target);
|
|
@@ -2820,7 +2887,7 @@ async function pruneVersions(prefix, keep) {
|
|
|
2820
2887
|
}
|
|
2821
2888
|
for (const version of versions)
|
|
2822
2889
|
if (!retained.has(version))
|
|
2823
|
-
await
|
|
2890
|
+
await rm4(join9(prefix, version), { recursive: true, force: true });
|
|
2824
2891
|
}
|
|
2825
2892
|
async function installPinnedGjc(options) {
|
|
2826
2893
|
const { home, version } = options;
|
|
@@ -2868,12 +2935,12 @@ async function installPinnedGjc(options) {
|
|
|
2868
2935
|
await symlink(version, temporaryLink, "dir");
|
|
2869
2936
|
await rename4(temporaryLink, layout.gjcCurrent);
|
|
2870
2937
|
} finally {
|
|
2871
|
-
await
|
|
2938
|
+
await rm4(temporaryLink, { force: true });
|
|
2872
2939
|
}
|
|
2873
2940
|
return layout.gjcExecutable();
|
|
2874
2941
|
} finally {
|
|
2875
2942
|
if (staging !== undefined)
|
|
2876
|
-
await
|
|
2943
|
+
await rm4(staging, { recursive: true, force: true });
|
|
2877
2944
|
}
|
|
2878
2945
|
}
|
|
2879
2946
|
|
|
@@ -2881,7 +2948,6 @@ async function installPinnedGjc(options) {
|
|
|
2881
2948
|
var UPDATE_USAGE = "usage: gajaeway update [--check] [--force] [--bin-dir DIR] [--no-restart]";
|
|
2882
2949
|
var DEFAULT_RELEASE_REPO = "Yeachan-Heo/gajae-way";
|
|
2883
2950
|
var RELEASE_REPO_OVERRIDE_ENV = "GAJAEWAY_UPDATE_REPO";
|
|
2884
|
-
var PIN_MANIFEST = "package.json";
|
|
2885
2951
|
function releaseRepo(env = process.env) {
|
|
2886
2952
|
const override = env[RELEASE_REPO_OVERRIDE_ENV]?.trim();
|
|
2887
2953
|
return override ? override : declaredReleaseRepo();
|
|
@@ -2958,12 +3024,12 @@ async function readInstalledRelease(binDir) {
|
|
|
2958
3024
|
async function resolveBinDir(flag, execPath = process.execPath) {
|
|
2959
3025
|
if (flag !== undefined)
|
|
2960
3026
|
return flag;
|
|
2961
|
-
const real = await
|
|
3027
|
+
const real = await realpath3(execPath).catch(() => {
|
|
2962
3028
|
return;
|
|
2963
3029
|
});
|
|
2964
3030
|
if (real === undefined)
|
|
2965
3031
|
return;
|
|
2966
|
-
return
|
|
3032
|
+
return basename3(real).startsWith("gajaeway") ? dirname3(real) : undefined;
|
|
2967
3033
|
}
|
|
2968
3034
|
function renderUpdate(result) {
|
|
2969
3035
|
const lines = [];
|
|
@@ -3004,10 +3070,10 @@ async function readPinnedGjcVersion(path) {
|
|
|
3004
3070
|
throw new Error(`release package metadata at ${path} has no gjc.version`);
|
|
3005
3071
|
return version;
|
|
3006
3072
|
}
|
|
3007
|
-
async function defaultUpdateCommandRunner(command) {
|
|
3073
|
+
async function defaultUpdateCommandRunner(command, options) {
|
|
3008
3074
|
const child = Bun.spawn([...command], { stdin: "ignore", stdout: "ignore", stderr: "pipe" });
|
|
3009
3075
|
const [stderr, exitCode] = await Promise.all([new Response(child.stderr).text(), child.exited]);
|
|
3010
|
-
if (exitCode !== 0) {
|
|
3076
|
+
if (exitCode !== 0 && !options?.allowFailure) {
|
|
3011
3077
|
const detail = stderr.trim();
|
|
3012
3078
|
throw new Error(`${command.join(" ")} exited with status ${exitCode}${detail.length === 0 ? "" : `: ${detail}`}`);
|
|
3013
3079
|
}
|
|
@@ -3017,6 +3083,22 @@ async function installUpdatedServices(options) {
|
|
|
3017
3083
|
const { home, binDir, platform, noRestart, deps } = options;
|
|
3018
3084
|
const brokerProvisioned = await exists(homeLayout(home).brokerProvisionManifest);
|
|
3019
3085
|
const env = { ...deps.env ?? process.env, GAJAEWAY_HOME: home };
|
|
3086
|
+
const run = deps.serviceRunner ?? defaultUpdateCommandRunner;
|
|
3087
|
+
const execute = async (command) => {
|
|
3088
|
+
const exitCode = await run(command);
|
|
3089
|
+
if (exitCode !== 0)
|
|
3090
|
+
throw new Error(`${command.join(" ")} exited with status ${exitCode}`);
|
|
3091
|
+
};
|
|
3092
|
+
if (!noRestart) {
|
|
3093
|
+
await removeStaleServices({
|
|
3094
|
+
binDir,
|
|
3095
|
+
platform,
|
|
3096
|
+
env,
|
|
3097
|
+
reloadSystemd: false,
|
|
3098
|
+
...deps.serviceOptions,
|
|
3099
|
+
run
|
|
3100
|
+
});
|
|
3101
|
+
}
|
|
3020
3102
|
await installServices({
|
|
3021
3103
|
binDir,
|
|
3022
3104
|
platform,
|
|
@@ -3026,16 +3108,12 @@ async function installUpdatedServices(options) {
|
|
|
3026
3108
|
...deps.serviceOptions
|
|
3027
3109
|
});
|
|
3028
3110
|
if (platform === "linux") {
|
|
3029
|
-
const run = deps.serviceRunner ?? defaultUpdateCommandRunner;
|
|
3030
|
-
const execute = async (command) => {
|
|
3031
|
-
const exitCode = await run(command);
|
|
3032
|
-
if (exitCode !== 0)
|
|
3033
|
-
throw new Error(`${command.join(" ")} exited with status ${exitCode}`);
|
|
3034
|
-
};
|
|
3035
3111
|
await execute(["systemctl", "--user", "daemon-reload"]);
|
|
3036
3112
|
if (!noRestart) {
|
|
3037
3113
|
const enableUnits = [];
|
|
3038
3114
|
for (const spec of serviceSpecs()) {
|
|
3115
|
+
if (!await exists(join10(binDir, spec.binary)))
|
|
3116
|
+
continue;
|
|
3039
3117
|
if (spec.id === "broker" && !brokerProvisioned)
|
|
3040
3118
|
continue;
|
|
3041
3119
|
if (spec.id.startsWith("adapter-") && !await Bun.file(join10(home, `adapter-${spec.id.slice(8)}.json`)).exists())
|
|
@@ -3092,7 +3170,7 @@ async function runUpdate(options) {
|
|
|
3092
3170
|
if (missingCore.length > 0)
|
|
3093
3171
|
throw new Error(`release tarball is missing core binaries: ${missingCore.join(", ")}`);
|
|
3094
3172
|
await assertStagedBinariesUsable(staged, toInstall);
|
|
3095
|
-
const gjcVersion = await readPinnedGjcVersion(join10(staged.dir,
|
|
3173
|
+
const gjcVersion = await readPinnedGjcVersion(join10(staged.dir, "package.json"));
|
|
3096
3174
|
await installPinnedGjc({
|
|
3097
3175
|
home: options.home,
|
|
3098
3176
|
version: gjcVersion,
|
|
@@ -3101,19 +3179,24 @@ async function runUpdate(options) {
|
|
|
3101
3179
|
const stamp = new Date((deps.now ?? Date.now)()).toISOString().replace(/[-:]/g, "").slice(0, 15);
|
|
3102
3180
|
const backupDir = join10(binDir, `backup-${current}-${stamp}Z`);
|
|
3103
3181
|
await mkdir7(backupDir, { recursive: false });
|
|
3104
|
-
const
|
|
3105
|
-
for (const name of replaced) {
|
|
3182
|
+
for (const name of toInstall) {
|
|
3106
3183
|
const target = join10(binDir, name);
|
|
3107
3184
|
if (await exists(target))
|
|
3108
3185
|
await copyFile(target, join10(backupDir, name));
|
|
3109
3186
|
}
|
|
3110
|
-
|
|
3187
|
+
const packagePath = join10(binDir, "package.json");
|
|
3188
|
+
if (await exists(packagePath))
|
|
3189
|
+
await copyFile(packagePath, join10(backupDir, "package.json"));
|
|
3190
|
+
for (const name of toInstall) {
|
|
3111
3191
|
const stagedPath = join10(staged.dir, name);
|
|
3112
3192
|
const tempPath = join10(binDir, `.update-${name}`);
|
|
3113
3193
|
await copyFile(stagedPath, tempPath);
|
|
3114
|
-
await chmod5(tempPath,
|
|
3194
|
+
await chmod5(tempPath, 493);
|
|
3115
3195
|
await rename5(tempPath, join10(binDir, name));
|
|
3116
3196
|
}
|
|
3197
|
+
const packageTempPath = join10(binDir, ".update-package.json");
|
|
3198
|
+
await copyFile(join10(staged.dir, "package.json"), packageTempPath);
|
|
3199
|
+
await rename5(packageTempPath, packagePath);
|
|
3117
3200
|
await writeFile6(releaseMarkerPath(binDir), `${latest}
|
|
3118
3201
|
`, "utf8");
|
|
3119
3202
|
const brokerNotEnabled = await installUpdatedServices({
|
|
@@ -3126,7 +3209,7 @@ async function runUpdate(options) {
|
|
|
3126
3209
|
return { toInstall, backupDir, brokerNotEnabled };
|
|
3127
3210
|
} finally {
|
|
3128
3211
|
if (staged !== undefined)
|
|
3129
|
-
await
|
|
3212
|
+
await rm5(staged.dir, { recursive: true, force: true });
|
|
3130
3213
|
await lease.release();
|
|
3131
3214
|
}
|
|
3132
3215
|
})();
|
|
@@ -3222,9 +3305,9 @@ async function defaultExtractTarball(tarball, intoDir) {
|
|
|
3222
3305
|
const exitCode = await process2.exited;
|
|
3223
3306
|
if (exitCode !== 0) {
|
|
3224
3307
|
const detail = await new Response(process2.stderr).text();
|
|
3225
|
-
throw new Error(`extracting ${
|
|
3308
|
+
throw new Error(`extracting ${basename3(tarballPath)} failed (tar exit ${exitCode}): ${detail.trim()}`);
|
|
3226
3309
|
}
|
|
3227
|
-
await
|
|
3310
|
+
await rm5(tarballPath, { force: true });
|
|
3228
3311
|
}
|
|
3229
3312
|
async function defaultQueueRestart(home, binDir, trigger) {
|
|
3230
3313
|
const { receipt, supervisorPid } = await launchRestartStack({ home, binDir, trigger });
|
|
@@ -3253,7 +3336,7 @@ var COMMANDS = [
|
|
|
3253
3336
|
"update",
|
|
3254
3337
|
"setup"
|
|
3255
3338
|
];
|
|
3256
|
-
var CLI_USAGE = "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";
|
|
3339
|
+
var CLI_USAGE = "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 [--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";
|
|
3257
3340
|
var USAGE_EXIT_CODE = 2;
|
|
3258
3341
|
function usageFor(command) {
|
|
3259
3342
|
return command !== undefined && COMMANDS.includes(command) ? undefined : CLI_USAGE;
|
|
@@ -3421,7 +3504,7 @@ unknown argument: ${flag}`);
|
|
|
3421
3504
|
}
|
|
3422
3505
|
var TERMINAL_MONITOR_STAGES = new Set(["delivered", "authored_no_delivery", "failed", "failed_no_retry", "skipped"]);
|
|
3423
3506
|
function waitForMonitorStage(client, eventId, timeoutSeconds) {
|
|
3424
|
-
return new Promise((
|
|
3507
|
+
return new Promise((resolve2) => {
|
|
3425
3508
|
let stage = "admitted";
|
|
3426
3509
|
let settled = false;
|
|
3427
3510
|
let timer;
|
|
@@ -3433,7 +3516,7 @@ function waitForMonitorStage(client, eventId, timeoutSeconds) {
|
|
|
3433
3516
|
if (timer !== undefined)
|
|
3434
3517
|
clearTimeout(timer);
|
|
3435
3518
|
unsubscribe?.();
|
|
3436
|
-
|
|
3519
|
+
resolve2(stage);
|
|
3437
3520
|
};
|
|
3438
3521
|
unsubscribe = client.on("monitor.event", (payload) => {
|
|
3439
3522
|
if (typeof payload !== "object" || payload === null)
|
|
@@ -3594,7 +3677,7 @@ function renderDeliveries(result) {
|
|
|
3594
3677
|
return ["deliveries: none"];
|
|
3595
3678
|
return [
|
|
3596
3679
|
`deliveries: ${result.rows.length}`,
|
|
3597
|
-
...result.rows.map((row) => `${row.createdAt} ${row.state} delivery=${row.deliveryId} turn=${row.turnId} origin=${row.originKey} conversation=${row.conversationId} text=${JSON.stringify(row.textPrefix)}`)
|
|
3680
|
+
...result.rows.map((row) => `${row.createdAt} ${row.state} delivery=${row.deliveryId} turn=${row.turnId} origin=${row.originKey} conversation=${row.conversationId} lastError=${row.lastError ?? "-"} text=${JSON.stringify(row.textPrefix)}`)
|
|
3598
3681
|
];
|
|
3599
3682
|
}
|
|
3600
3683
|
var CHAT_TURN_TIMEOUT_MS = 30 * 60000;
|
|
@@ -3619,16 +3702,16 @@ async function chat(socket) {
|
|
|
3619
3702
|
console.error("(message was not engaged)");
|
|
3620
3703
|
return;
|
|
3621
3704
|
}
|
|
3622
|
-
await new Promise((
|
|
3705
|
+
await new Promise((resolve2) => {
|
|
3623
3706
|
const timer = setTimeout(() => {
|
|
3624
3707
|
turnWaiters.delete(turnId);
|
|
3625
3708
|
console.error(`(turn timed out after ${CHAT_TURN_TIMEOUT_MS / 60000}m)`);
|
|
3626
|
-
|
|
3709
|
+
resolve2();
|
|
3627
3710
|
}, CHAT_TURN_TIMEOUT_MS);
|
|
3628
3711
|
turnWaiters.set(turnId, () => {
|
|
3629
3712
|
clearTimeout(timer);
|
|
3630
3713
|
turnWaiters.delete(turnId);
|
|
3631
|
-
|
|
3714
|
+
resolve2();
|
|
3632
3715
|
});
|
|
3633
3716
|
});
|
|
3634
3717
|
};
|
|
@@ -3668,7 +3751,7 @@ async function pollMemoryOp(client, opRef, maxWaitMs = 300000, pollIntervalMs =
|
|
|
3668
3751
|
if (status.status === "failed") {
|
|
3669
3752
|
return { status: "failed", elapsedMs: status.elapsedMs, error: status.error };
|
|
3670
3753
|
}
|
|
3671
|
-
await new Promise((
|
|
3754
|
+
await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
|
|
3672
3755
|
}
|
|
3673
3756
|
const waitedMs = Date.now() - startTime;
|
|
3674
3757
|
console.error(`memory operation still running (${Math.round(operationElapsedMs / 1000)}s operation elapsed; CLI wait ended after ${Math.round(waitedMs / 1000)}s).
|
|
@@ -3949,7 +4032,7 @@ ${OPS_USAGE}`);
|
|
|
3949
4032
|
}
|
|
3950
4033
|
case "work": {
|
|
3951
4034
|
const [command, ...args2] = parsed.rest;
|
|
3952
|
-
const usage2 = 'usage: gajaeway work run|start <name> [--cwd DIR] [--resume] [--model ID|--preset NAME] "<task text>"|status <name>|steer <name> <text>|retire <name>|jobs';
|
|
4035
|
+
const usage2 = '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';
|
|
3953
4036
|
if (command === "status" || command === "steer") {
|
|
3954
4037
|
const name2 = args2[0];
|
|
3955
4038
|
const text2 = args2.slice(1).join(" ").trim();
|
|
@@ -4055,7 +4138,7 @@ ${OPS_USAGE}`);
|
|
|
4055
4138
|
} else if (arg === "--repo") {
|
|
4056
4139
|
if (repo !== undefined)
|
|
4057
4140
|
throw new Error(usage2);
|
|
4058
|
-
repo = value;
|
|
4141
|
+
repo = value.includes("://") || /^[^/@\s]+@[^:/\s]+:/.test(value) ? value : resolve(value);
|
|
4059
4142
|
} else if (arg === "--base") {
|
|
4060
4143
|
if (base !== undefined)
|
|
4061
4144
|
throw new Error(usage2);
|
|
@@ -4076,6 +4159,8 @@ ${OPS_USAGE}`);
|
|
|
4076
4159
|
const text = textParts.join(" ").trim();
|
|
4077
4160
|
if (!name || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name) || !text)
|
|
4078
4161
|
throw new Error(usage2);
|
|
4162
|
+
if (base !== undefined && repo === undefined)
|
|
4163
|
+
throw new Error(usage2);
|
|
4079
4164
|
const client = await connectGatewaySocket(parsed.socket, {
|
|
4080
4165
|
requestTimeoutMs: command === "run" ? 3600000 : 120000
|
|
4081
4166
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restart-stack.d.ts","sourceRoot":"","sources":["../src/restart-stack.ts"],"names":[],"mappings":"AAcA,OAAO,
|
|
1
|
+
{"version":3,"file":"restart-stack.d.ts","sourceRoot":"","sources":["../src/restart-stack.ts"],"names":[],"mappings":"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"}
|
package/dist/services.d.ts
CHANGED
|
@@ -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
|
*
|
package/dist/services.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,aAAa,EAAsB,MAAM,yBAAyB,CAAC;AAIrG,eAAO,MAAM,kBAAkB,uEAAwE,CAAC;AAGxG,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;AAC3F,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;AAEvF,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;CAC3C;AAED,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,CAAC;
|
|
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
|
|
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;
|
package/dist/update.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,gBAAgB,EAAoB,MAAM,eAAe,CAAC;AAExE,OAAO,EACN,KAAK,sBAAsB,
|
|
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.
|
|
3
|
+
"version": "0.3.0",
|
|
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.
|
|
45
|
-
"@gajae-gateway/protocol": "0.
|
|
44
|
+
"@gajae-gateway/sdk": "0.3.0",
|
|
45
|
+
"@gajae-gateway/protocol": "0.3.0"
|
|
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, join, resolve } from "node:path";
|
|
4
4
|
|
|
5
5
|
import type {
|
|
6
6
|
MonitorEventOperatorResult,
|
|
@@ -85,7 +85,7 @@ export const COMMANDS = [
|
|
|
85
85
|
] as const;
|
|
86
86
|
|
|
87
87
|
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";
|
|
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] [--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 [--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
89
|
|
|
90
90
|
/** Usage errors exit 2, as `gajaeway-gateway` does; 1 stays a runtime failure. */
|
|
91
91
|
export const USAGE_EXIT_CODE = 2;
|
|
@@ -486,7 +486,7 @@ export function renderDeliveries(result: OpsDeliveriesResult): string[] {
|
|
|
486
486
|
`deliveries: ${result.rows.length}`,
|
|
487
487
|
...result.rows.map(
|
|
488
488
|
(row) =>
|
|
489
|
-
`${row.createdAt} ${row.state} delivery=${row.deliveryId} turn=${row.turnId} origin=${row.originKey} conversation=${row.conversationId} text=${JSON.stringify(row.textPrefix)}`,
|
|
489
|
+
`${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
490
|
),
|
|
491
491
|
];
|
|
492
492
|
}
|
|
@@ -898,7 +898,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
|
|
|
898
898
|
case "work": {
|
|
899
899
|
const [command, ...args] = parsed.rest;
|
|
900
900
|
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';
|
|
901
|
+
'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
902
|
if (command === "status" || command === "steer") {
|
|
903
903
|
const name = args[0];
|
|
904
904
|
const text = args.slice(1).join(" ").trim();
|
|
@@ -1020,7 +1020,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
|
|
|
1020
1020
|
cwd = value;
|
|
1021
1021
|
} else if (arg === "--repo") {
|
|
1022
1022
|
if (repo !== undefined) throw new Error(usage);
|
|
1023
|
-
repo = value;
|
|
1023
|
+
repo = value.includes("://") || /^[^/@\s]+@[^:/\s]+:/.test(value) ? value : resolve(value);
|
|
1024
1024
|
} else if (arg === "--base") {
|
|
1025
1025
|
if (base !== undefined) throw new Error(usage);
|
|
1026
1026
|
base = value;
|
|
@@ -1034,6 +1034,7 @@ export async function main(args = process.argv.slice(2), options: MainOptions =
|
|
|
1034
1034
|
}
|
|
1035
1035
|
const text = textParts.join(" ").trim();
|
|
1036
1036
|
if (!name || !/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(name) || !text) throw new Error(usage);
|
|
1037
|
+
if (base !== undefined && repo === undefined) throw new Error(usage);
|
|
1037
1038
|
// This is a caller response-wait budget, never an attempt deadline.
|
|
1038
1039
|
// Timeout/disconnect leaves the attempt observable via work.status.
|
|
1039
1040
|
const client = await connectGatewaySocket(parsed.socket, {
|
package/src/restart-stack.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { access, mkdir, readFile,
|
|
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
|
|
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 (
|
|
379
|
-
|
|
380
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|