@gajae-gateway/cli 0.1.8 → 0.2.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.
- package/dist/discord-setup.d.ts +41 -0
- package/dist/discord-setup.d.ts.map +1 -0
- package/dist/gjc-install.d.ts +13 -0
- package/dist/gjc-install.d.ts.map +1 -0
- package/dist/main.d.ts +17 -30
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +1318 -582
- package/dist/migrate/hermes.d.ts.map +1 -1
- package/dist/migrate.d.ts.map +1 -1
- package/dist/restart-stack.d.ts +27 -13
- package/dist/restart-stack.d.ts.map +1 -1
- package/dist/services.d.ts +9 -6
- package/dist/services.d.ts.map +1 -1
- package/dist/setup.d.ts +14 -3
- package/dist/setup.d.ts.map +1 -1
- package/dist/up.d.ts +20 -0
- package/dist/up.d.ts.map +1 -0
- package/dist/update.d.ts +10 -6
- package/dist/update.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/discord-setup.ts +103 -0
- package/src/gjc-install.ts +148 -0
- package/src/main.ts +296 -151
- package/src/migrate/hermes.ts +0 -2
- package/src/migrate.ts +36 -4
- package/src/restart-stack.ts +309 -92
- package/src/services.ts +75 -23
- package/src/setup.ts +85 -10
- package/src/up.ts +133 -0
- package/src/update.ts +175 -98
- package/dist/upgrade.d.ts +0 -40
- package/dist/upgrade.d.ts.map +0 -1
- package/src/upgrade.ts +0 -205
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hermes.d.ts","sourceRoot":"","sources":["../../src/migrate/hermes.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"hermes.d.ts","sourceRoot":"","sources":["../../src/migrate/hermes.ts"],"names":[],"mappings":"AAEA,OAAO,EAUN,KAAK,aAAa,EAClB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAMN,KAAK,UAAU,EAGf,MAAM,aAAa,CAAC;AAErB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,eAAU,CAAC;AAE9C,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMjE;AAiBD,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAkHvF;AAED,2GAA2G;AAC3G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAMpE;AAuMD,wBAAsB,SAAS,CAC9B,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GACf,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,qFAAqF;AACrF,wBAAsB,eAAe,CACpC,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,aAAa,EACtB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC9B,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
package/dist/migrate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBpE;AAyHD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,cAAc,CAsBxE"}
|
package/dist/restart-stack.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export type RestartStepResult = "pending" | "ok" | "stale" | "failed" | "skipped
|
|
|
14
14
|
export type RestartState = "queued" | "running" | "ok" | "stale" | "failed";
|
|
15
15
|
export interface RestartStep {
|
|
16
16
|
readonly label: string;
|
|
17
|
-
/**
|
|
17
|
+
/** The final service-manager command; update broker receipts separately record agent sync. */
|
|
18
18
|
command?: readonly string[];
|
|
19
19
|
exitStatus?: number;
|
|
20
20
|
result: RestartStepResult;
|
|
@@ -22,30 +22,37 @@ export interface RestartStep {
|
|
|
22
22
|
processStartedAt?: string;
|
|
23
23
|
binary?: string;
|
|
24
24
|
binaryModifiedAt?: string;
|
|
25
|
+
agentSync?: {
|
|
26
|
+
readonly command: readonly string[];
|
|
27
|
+
readonly exitStatus: number;
|
|
28
|
+
readonly error?: string;
|
|
29
|
+
};
|
|
25
30
|
detail?: string;
|
|
26
31
|
}
|
|
27
32
|
export interface RestartReceipt {
|
|
28
33
|
readonly id: string;
|
|
34
|
+
readonly trigger: "update" | "manual";
|
|
29
35
|
state: RestartState;
|
|
30
36
|
readonly platform: ServicePlatform;
|
|
31
37
|
readonly requestedAt: string;
|
|
32
38
|
supervisorPid?: number;
|
|
33
39
|
finishedAt?: string;
|
|
40
|
+
/** Why the sequence never ran, e.g. the supervisor could not be started. */
|
|
41
|
+
detail?: string;
|
|
34
42
|
readonly steps: RestartStep[];
|
|
35
43
|
}
|
|
36
|
-
/**
|
|
44
|
+
/** The main PID reported by the service manager. */
|
|
37
45
|
export interface ServiceProcess {
|
|
38
46
|
readonly pid: number;
|
|
39
|
-
/** Epoch ms; `ps` reports whole seconds. */
|
|
40
|
-
readonly startedAt: number;
|
|
41
|
-
readonly binary: string;
|
|
42
47
|
}
|
|
43
48
|
export type CommandRunner = (command: readonly string[]) => number | PromiseLike<number>;
|
|
44
49
|
export type ServiceProbe = (label: string) => Promise<ServiceProcess | undefined>;
|
|
45
50
|
export type IsServiceInstalled = (label: string) => Promise<boolean>;
|
|
51
|
+
/** The trigger is explicit so only update receipts synchronize provisioned agent state. */
|
|
46
52
|
export interface RunRestartOptions {
|
|
47
53
|
readonly home: string;
|
|
48
54
|
readonly id: string;
|
|
55
|
+
readonly trigger?: "update" | "manual";
|
|
49
56
|
readonly platform?: ServicePlatform;
|
|
50
57
|
readonly uid?: number;
|
|
51
58
|
readonly runner?: CommandRunner;
|
|
@@ -63,13 +70,13 @@ export interface RunRestartOptions {
|
|
|
63
70
|
readonly env?: NodeJS.ProcessEnv;
|
|
64
71
|
/** LaunchAgents directory on darwin. Defaults to ~/Library/LaunchAgents. */
|
|
65
72
|
readonly launchAgentsDir?: string;
|
|
66
|
-
|
|
73
|
+
readonly binDir?: string;
|
|
67
74
|
readonly unitDir?: string;
|
|
68
75
|
}
|
|
69
76
|
export declare function restartReceiptPath(home: string): string;
|
|
70
77
|
export declare function readRestartReceipt(home: string): Promise<RestartReceipt | undefined>;
|
|
71
|
-
/** Reads the
|
|
72
|
-
export declare function defaultServiceProbe(platform: ServicePlatform): ServiceProbe;
|
|
78
|
+
/** Reads the current main PID directly from launchd or systemd. */
|
|
79
|
+
export declare function defaultServiceProbe(platform: ServicePlatform, uid?: number): ServiceProbe;
|
|
73
80
|
/**
|
|
74
81
|
* Runs the ordered restart, verifying each service before the next command,
|
|
75
82
|
* and persists the receipt after every transition. The first service that is
|
|
@@ -78,17 +85,24 @@ export declare function defaultServiceProbe(platform: ServicePlatform): ServiceP
|
|
|
78
85
|
export declare function runRestartStack(options: RunRestartOptions): Promise<RestartReceipt>;
|
|
79
86
|
export interface LaunchRestartOptions {
|
|
80
87
|
readonly home: string;
|
|
88
|
+
readonly trigger?: "update" | "manual";
|
|
81
89
|
readonly platform?: ServicePlatform;
|
|
82
90
|
readonly uid?: number;
|
|
91
|
+
/** Installed service binary directory used for lease verification. */
|
|
92
|
+
readonly binDir?: string;
|
|
83
93
|
/** Argv that re-enters the CLI; `--run <id>` is appended. */
|
|
84
94
|
readonly worker?: readonly string[];
|
|
85
95
|
readonly env?: NodeJS.ProcessEnv;
|
|
96
|
+
/** Starts systemd-run; injectable for launcher-result handling. */
|
|
97
|
+
readonly systemdRun?: (command: readonly string[]) => Bun.Subprocess;
|
|
98
|
+
/** Maximum time to wait for systemd-run to acknowledge the worker exec. */
|
|
99
|
+
readonly systemdRunTimeoutMs?: number;
|
|
86
100
|
}
|
|
87
101
|
/** The argv that runs this CLI again, whether compiled or run from source. */
|
|
88
102
|
export declare function cliCommand(): string[];
|
|
89
103
|
/**
|
|
90
|
-
* Queues a restart and hands it to a detached supervisor, returning
|
|
91
|
-
*
|
|
104
|
+
* Queues a restart and hands it to a detached supervisor, returning once the
|
|
105
|
+
* platform launcher acknowledges it so the caller may be killed by the restart.
|
|
92
106
|
*/
|
|
93
107
|
export declare function launchRestartStack(options: LaunchRestartOptions): Promise<{
|
|
94
108
|
readonly receipt: RestartReceipt;
|
|
@@ -100,11 +114,11 @@ export declare function launchRestartStack(options: LaunchRestartOptions): Promi
|
|
|
100
114
|
* restart it requests may stop, so the supervisor is started as its own
|
|
101
115
|
* transient user unit instead.
|
|
102
116
|
*/
|
|
103
|
-
export declare function supervisorArgv(platform: ServicePlatform, worker: readonly string[], home: string, id: string): string[];
|
|
117
|
+
export declare function supervisorArgv(platform: ServicePlatform, worker: readonly string[], home: string, id: string, binDir?: string): string[];
|
|
104
118
|
/**
|
|
105
119
|
* The receipt's state, except that an unfinished sequence whose supervisor is
|
|
106
120
|
* gone is reported as interrupted rather than left looking in progress.
|
|
107
121
|
*/
|
|
108
|
-
export declare function effectiveRestartState(receipt: RestartReceipt): RestartState | "interrupted"
|
|
109
|
-
export declare function renderRestartReceipt(receipt: RestartReceipt): string[];
|
|
122
|
+
export declare function effectiveRestartState(receipt: RestartReceipt, home: string): Promise<RestartState | "interrupted">;
|
|
123
|
+
export declare function renderRestartReceipt(receipt: RestartReceipt, state?: RestartState | "interrupted"): string[];
|
|
110
124
|
//# sourceMappingURL=restart-stack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restart-stack.d.ts","sourceRoot":"","sources":["../src/restart-stack.ts"],"names":[],"mappings":"
|
|
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
|
@@ -23,6 +23,10 @@ export interface InstallServicesOptions {
|
|
|
23
23
|
/** Service manager to generate for; defaults to the running platform. */
|
|
24
24
|
readonly platform?: ServicePlatform;
|
|
25
25
|
readonly env?: NodeJS.ProcessEnv;
|
|
26
|
+
/** Render adapter units only when their adapter-<platform>.json exists. */
|
|
27
|
+
readonly configuredAdaptersOnly?: boolean;
|
|
28
|
+
/** Leave unchanged unit files untouched. */
|
|
29
|
+
readonly compareAndWrite?: boolean;
|
|
26
30
|
/** Test seam for the `${SHELL} -lc` invocation used by the default path. */
|
|
27
31
|
readonly loginPathRunner?: LoginPathRunner;
|
|
28
32
|
/** Test seam for counting or inspecting the definition writes. */
|
|
@@ -42,6 +46,7 @@ interface ServiceSpec {
|
|
|
42
46
|
*/
|
|
43
47
|
readonly dependsOnGateway: boolean;
|
|
44
48
|
}
|
|
49
|
+
export declare const BROKER_UNIT = "gajaeway-broker.service";
|
|
45
50
|
export declare const GATEWAY_UNIT = "gajaeway-gateway.service";
|
|
46
51
|
export declare function serviceSpecs(): readonly ServiceSpec[];
|
|
47
52
|
export declare function mergePathEntries(binDir: string, userHome: string, loginPath: string): string[];
|
|
@@ -60,14 +65,12 @@ export declare function systemdUnitPath(spec: ServiceSpec, unitDir: string): str
|
|
|
60
65
|
/**
|
|
61
66
|
* The ordered commands that realign the whole stack.
|
|
62
67
|
*
|
|
63
|
-
* systemd
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* explicit here instead — and `bootout` never appears, because removing a job
|
|
67
|
-
* leaves it with no automatic recovery.
|
|
68
|
+
* systemd restarts the broker before the gateway; gateway dependencies restart
|
|
69
|
+
* their adapters. launchd has no dependency propagation, so every job is
|
|
70
|
+
* kicked explicitly in the same order.
|
|
68
71
|
*/
|
|
69
72
|
export declare function restartStackCommands(platform: ServicePlatform, uid?: number): readonly (readonly string[])[];
|
|
70
|
-
/**
|
|
73
|
+
/** Broker, gateway, then every job that holds a connection to the gateway. */
|
|
71
74
|
export declare function restartOrder(): readonly ServiceSpec[];
|
|
72
75
|
export declare function currentPlatform(): ServicePlatform;
|
|
73
76
|
export declare function installServices(options: InstallServicesOptions): Promise<readonly string[]>;
|
package/dist/services.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../src/services.ts"],"names":[],"mappings":"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"}
|
package/dist/setup.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export declare const SETUP_ENV: {
|
|
|
22
22
|
readonly telegramToken: "GAJAEWAY_TELEGRAM_TOKEN";
|
|
23
23
|
readonly ownerIds: "GAJAEWAY_OWNER_IDS";
|
|
24
24
|
};
|
|
25
|
-
export declare const SETUP_USAGE = "usage: gajaeway setup [--from-env] [--adapters discord,slack,telegram] [--owner ID[,ID...]] [--discord-app-id ID] | setup --status";
|
|
25
|
+
export declare const SETUP_USAGE = "usage: gajaeway setup [--from-env] [--adapters discord,slack,telegram] [--owner ID[,ID...]] [--discord-app-id ID] | setup --status | setup --broker-agent [--from DIR]";
|
|
26
26
|
/** Secret file names under `$GAJAEWAY_HOME/secrets`, matching docs/deployment.md. */
|
|
27
27
|
export declare const SECRET_FILES: {
|
|
28
28
|
readonly discord: "discord-token";
|
|
@@ -38,11 +38,12 @@ export declare const REDACTED = "[redacted]";
|
|
|
38
38
|
/** Replaces every occurrence of every secret. Short strings are skipped so a stray "a" cannot shred output. */
|
|
39
39
|
export declare function redact(text: string, secrets: Iterable<string>): string;
|
|
40
40
|
export interface ParsedSetupArgs {
|
|
41
|
-
readonly mode: "setup" | "status";
|
|
41
|
+
readonly mode: "setup" | "status" | "broker-agent";
|
|
42
42
|
readonly fromEnv: boolean;
|
|
43
43
|
readonly adapters?: readonly SetupPlatform[];
|
|
44
44
|
readonly owners: readonly string[];
|
|
45
45
|
readonly discordAppId?: string;
|
|
46
|
+
readonly from?: string;
|
|
46
47
|
}
|
|
47
48
|
export declare function parseSetupArgs(args: readonly string[]): ParsedSetupArgs;
|
|
48
49
|
export declare function parseAdapterList(value: string): SetupPlatform[];
|
|
@@ -73,6 +74,8 @@ export interface ValidatedIdentity {
|
|
|
73
74
|
readonly summary: string;
|
|
74
75
|
/** A user id the platform names as the app owner, when it names one. */
|
|
75
76
|
readonly ownerId?: string;
|
|
77
|
+
/** Application ID (Discord only). */
|
|
78
|
+
readonly appId?: string;
|
|
76
79
|
}
|
|
77
80
|
/** Discord: the bot token must authenticate `/users/@me` as a bot and, when given, belong to the expected application. */
|
|
78
81
|
export declare function validateDiscord(credentials: NonNullable<SetupTokens["discord"]>, fetcher: FetchLike): Promise<ValidatedIdentity>;
|
|
@@ -112,18 +115,26 @@ export interface Prompter {
|
|
|
112
115
|
close(): void;
|
|
113
116
|
}
|
|
114
117
|
/** Interactive collection. Tokens are read without echo and never repeated back. */
|
|
115
|
-
export declare function tokensFromPrompts(prompter: Prompter, parsed: ParsedSetupArgs): Promise<{
|
|
118
|
+
export declare function tokensFromPrompts(prompter: Prompter, parsed: ParsedSetupArgs, log?: (line: string) => void): Promise<{
|
|
116
119
|
tokens: SetupTokens;
|
|
117
120
|
owners: string[];
|
|
118
121
|
}>;
|
|
119
122
|
/** Terminal prompter: raw-mode, no-echo secret entry. Requires a TTY. */
|
|
120
123
|
export declare function terminalPrompter(): Prompter;
|
|
124
|
+
export interface BrokerAgentRunResult {
|
|
125
|
+
readonly exitCode: number;
|
|
126
|
+
readonly stdout: string;
|
|
127
|
+
readonly stderr: string;
|
|
128
|
+
}
|
|
129
|
+
export type BrokerAgentRunner = (command: readonly string[]) => Promise<BrokerAgentRunResult>;
|
|
121
130
|
export interface RunSetupOptions {
|
|
122
131
|
readonly home: string;
|
|
132
|
+
readonly binDir?: string;
|
|
123
133
|
readonly env?: NodeJS.ProcessEnv;
|
|
124
134
|
readonly fetch?: FetchLike;
|
|
125
135
|
readonly prompter?: () => Prompter;
|
|
126
136
|
readonly log?: (line: string) => void;
|
|
137
|
+
readonly runBrokerAgent?: BrokerAgentRunner;
|
|
127
138
|
}
|
|
128
139
|
/** The whole command. Returns the lines it printed so tests can assert nothing secret escaped. */
|
|
129
140
|
export declare function runSetup(args: readonly string[], options: RunSetupOptions): Promise<void>;
|
package/dist/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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"}
|
package/dist/up.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RunSetupOptions } from "./setup";
|
|
2
|
+
export interface UpOptions extends Omit<RunSetupOptions, "home"> {
|
|
3
|
+
readonly home: string;
|
|
4
|
+
readonly socket?: string;
|
|
5
|
+
/** Skip the setup check and assume config exists. */
|
|
6
|
+
readonly skipSetup?: boolean;
|
|
7
|
+
/** Spawn runner for tests; defaults to Bun.spawn */
|
|
8
|
+
readonly spawn?: (cmd: string, args: string[], opts?: {
|
|
9
|
+
cwd?: string;
|
|
10
|
+
}) => unknown;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* `gajaeway up`: One-command setup and start for first-time users.
|
|
14
|
+
*
|
|
15
|
+
* Checks for existing config.json; if missing, runs interactive setup.
|
|
16
|
+
* Then starts the gateway daemon and enabled adapters in the background.
|
|
17
|
+
* Reports the gateway status and how to stop it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runUp(options: UpOptions): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=up.d.ts.map
|
package/dist/up.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"up.d.ts","sourceRoot":"","sources":["../src/up.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAG/C,MAAM,WAAW,SAAU,SAAQ,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,oDAAoD;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC;CACnF;AAED;;;;;;GAMG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA8G7D"}
|
package/dist/update.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type GjcInstallRunner } from "./gjc-install";
|
|
2
|
+
import { type InstallServicesOptions } from "./services";
|
|
1
3
|
/**
|
|
2
4
|
* `gajaeway update`: self-update a binary install from the project's GitHub
|
|
3
5
|
* releases, the way `gjc update` does for gajae-code. Production hosts run
|
|
@@ -59,6 +61,7 @@ export interface UpdateResult {
|
|
|
59
61
|
readonly installed: readonly string[];
|
|
60
62
|
readonly backupDir?: string;
|
|
61
63
|
readonly restartQueued?: string;
|
|
64
|
+
readonly brokerNotEnabled?: boolean;
|
|
62
65
|
readonly restartSkipped?: boolean;
|
|
63
66
|
}
|
|
64
67
|
export declare function renderUpdate(result: UpdateResult): string[];
|
|
@@ -69,7 +72,9 @@ export interface RestartQueueReceipt {
|
|
|
69
72
|
export type ReleaseFetcher = (repo: string) => Promise<ReleaseInfo>;
|
|
70
73
|
export type AssetDownloader = (asset: ReleaseAsset) => Promise<Uint8Array>;
|
|
71
74
|
export type TarballExtractor = (tarball: Uint8Array, intoDir: string) => Promise<void>;
|
|
72
|
-
export type RestartQueuer = (home: string) => Promise<RestartQueueReceipt>;
|
|
75
|
+
export type RestartQueuer = (home: string, binDir: string, trigger: "update") => Promise<RestartQueueReceipt>;
|
|
76
|
+
export type UpdateCommandRunner = (command: readonly string[]) => Promise<number>;
|
|
77
|
+
type UpdateServiceOptions = Pick<InstallServicesOptions, "launchAgentsDir" | "unitDir" | "loginPathRunner" | "writeFile">;
|
|
73
78
|
export interface UpdateDeps {
|
|
74
79
|
readonly fetchLatestRelease?: ReleaseFetcher;
|
|
75
80
|
readonly downloadAsset?: AssetDownloader;
|
|
@@ -80,6 +85,9 @@ export interface UpdateDeps {
|
|
|
80
85
|
readonly env?: NodeJS.ProcessEnv;
|
|
81
86
|
readonly execPath?: string;
|
|
82
87
|
readonly now?: () => number;
|
|
88
|
+
readonly gjcInstallRunner?: GjcInstallRunner;
|
|
89
|
+
readonly serviceRunner?: UpdateCommandRunner;
|
|
90
|
+
readonly serviceOptions?: UpdateServiceOptions;
|
|
83
91
|
}
|
|
84
92
|
export interface RunUpdateOptions {
|
|
85
93
|
readonly args: ParsedUpdateArgs;
|
|
@@ -87,9 +95,5 @@ export interface RunUpdateOptions {
|
|
|
87
95
|
readonly deps?: UpdateDeps;
|
|
88
96
|
}
|
|
89
97
|
export declare function runUpdate(options: RunUpdateOptions): Promise<UpdateResult>;
|
|
90
|
-
|
|
91
|
-
* One update at a time per bin dir. A lock naming a live pid refuses; a lock
|
|
92
|
-
* naming a dead one is stale and taken over.
|
|
93
|
-
*/
|
|
94
|
-
export declare function acquireUpdateLock(binDir: string): Promise<() => Promise<void>>;
|
|
98
|
+
export {};
|
|
95
99
|
//# sourceMappingURL=update.d.ts.map
|
package/dist/update.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"
|
|
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.1
|
|
3
|
+
"version": "0.2.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,10 +41,13 @@
|
|
|
41
41
|
"prepublishOnly": "bun run build"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@gajae-gateway/sdk": "0.1
|
|
45
|
-
"@gajae-gateway/protocol": "0.1
|
|
44
|
+
"@gajae-gateway/sdk": "0.2.1",
|
|
45
|
+
"@gajae-gateway/protocol": "0.2.1"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"bun": ">=1.4.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@gajae-gateway/home": "0.1.0"
|
|
49
52
|
}
|
|
50
53
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord setup helpers: guided bot token acquisition and invite URL generation.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const DEVELOPER_PORTAL_URL = "https://discord.com/developers/applications";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Discord OAuth2 scopes needed for the adapter.
|
|
9
|
+
* `bot` allows the bot to join servers.
|
|
10
|
+
* `applications.commands` allows slash commands (future feature).
|
|
11
|
+
*/
|
|
12
|
+
export const DISCORD_BOT_SCOPES = ["bot", "applications.commands"];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Discord permissions needed for the bot to function.
|
|
16
|
+
* Calculated as the bitwise OR of individual permission bits.
|
|
17
|
+
*
|
|
18
|
+
* - SEND_MESSAGES (2048): Send messages in channels
|
|
19
|
+
* - EMBED_LINKS (16384): Embed links in messages
|
|
20
|
+
* - ATTACH_FILES (33554432): Attach files to messages
|
|
21
|
+
* - READ_MESSAGE_HISTORY (65536): Read past messages
|
|
22
|
+
* - MENTION_EVERYONE (131072): Mention @everyone, @here
|
|
23
|
+
* - MANAGE_MESSAGES (8192): Manage messages (delete, etc.)
|
|
24
|
+
* - ADD_REACTIONS (64): React to messages
|
|
25
|
+
*/
|
|
26
|
+
export const DISCORD_BOT_PERMISSIONS = 2048 | 16384 | 33554432 | 65536 | 131072 | 8192 | 64;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Prints step-by-step guidance for getting a Discord bot token.
|
|
30
|
+
* Called before asking the user to paste the token.
|
|
31
|
+
*/
|
|
32
|
+
export function printDiscordSetupGuide(log: (line: string) => void): void {
|
|
33
|
+
log("");
|
|
34
|
+
log("═══════════════════════════════════════════════════════════════════════════════════");
|
|
35
|
+
log(" Getting your Discord bot token");
|
|
36
|
+
log("═══════════════════════════════════════════════════════════════════════════════════");
|
|
37
|
+
log("");
|
|
38
|
+
log("1. Open the Discord Developer Portal:");
|
|
39
|
+
log(` ${DEVELOPER_PORTAL_URL}`);
|
|
40
|
+
log("");
|
|
41
|
+
log("2. Click 'New Application' and choose a name (e.g., 'My gajae-way agent')");
|
|
42
|
+
log("");
|
|
43
|
+
log("3. In the left menu, click 'Bot' → 'Add Bot'");
|
|
44
|
+
log("");
|
|
45
|
+
log("4. Under 'TOKEN', click 'Reset Token' → 'Yes, do it!'");
|
|
46
|
+
log("");
|
|
47
|
+
log("5. Click 'Copy' to copy your bot token (it starts with 'MTI...')");
|
|
48
|
+
log("");
|
|
49
|
+
log("6. (Important) Scroll down to 'GATEWAY INTENTS' and enable 'MESSAGE CONTENT INTENT'");
|
|
50
|
+
log(" This allows the bot to read message text, not just usernames.");
|
|
51
|
+
log("");
|
|
52
|
+
log("7. Click 'Save Changes'");
|
|
53
|
+
log("");
|
|
54
|
+
log("8. Come back here and paste your token below");
|
|
55
|
+
log("");
|
|
56
|
+
log("═══════════════════════════════════════════════════════════════════════════════════");
|
|
57
|
+
log("");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generates an OAuth2 invite URL for the Discord bot.
|
|
62
|
+
* The URL allows server owners to authorize the bot with the required permissions.
|
|
63
|
+
*
|
|
64
|
+
* @param appId - The Discord application ID (obtained from the API)
|
|
65
|
+
* @returns A clickable invite URL
|
|
66
|
+
*/
|
|
67
|
+
export function generateDiscordInviteUrl(appId: string): string {
|
|
68
|
+
const scopeParam = DISCORD_BOT_SCOPES.join("+");
|
|
69
|
+
const permissionsParam = String(DISCORD_BOT_PERMISSIONS);
|
|
70
|
+
return `https://discord.com/oauth2/authorize?client_id=${appId}&scope=${scopeParam}&permissions=${permissionsParam}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Formats the Discord bot setup success message with the invite URL.
|
|
75
|
+
* Includes clear instructions for the user to authorize the bot in their server.
|
|
76
|
+
*/
|
|
77
|
+
export function printDiscordBotReady(log: (line: string) => void, appId: string, botName?: string): void {
|
|
78
|
+
const inviteUrl = generateDiscordInviteUrl(appId);
|
|
79
|
+
|
|
80
|
+
log("");
|
|
81
|
+
log("═══════════════════════════════════════════════════════════════════════════════════");
|
|
82
|
+
log(" ✓ Discord bot token validated");
|
|
83
|
+
log("═══════════════════════════════════════════════════════════════════════════════════");
|
|
84
|
+
log("");
|
|
85
|
+
log(`Application ID: ${appId}`);
|
|
86
|
+
if (botName) {
|
|
87
|
+
log(`Bot name: ${botName}`);
|
|
88
|
+
}
|
|
89
|
+
log("");
|
|
90
|
+
log("To invite your bot to your Discord server, click this link:");
|
|
91
|
+
log("");
|
|
92
|
+
log(` ${inviteUrl}`);
|
|
93
|
+
log("");
|
|
94
|
+
log("Then:");
|
|
95
|
+
log(" 1. Choose the server where you want to add the bot");
|
|
96
|
+
log(" 2. Click 'Authorize'");
|
|
97
|
+
log(" 3. Complete the CAPTCHA");
|
|
98
|
+
log("");
|
|
99
|
+
log("Once authorized, send the bot a DM and start chatting!");
|
|
100
|
+
log("");
|
|
101
|
+
log("═══════════════════════════════════════════════════════════════════════════════════");
|
|
102
|
+
log("");
|
|
103
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import {
|
|
3
|
+
access,
|
|
4
|
+
chmod,
|
|
5
|
+
lstat,
|
|
6
|
+
mkdir,
|
|
7
|
+
mkdtemp,
|
|
8
|
+
readdir,
|
|
9
|
+
readlink,
|
|
10
|
+
rename,
|
|
11
|
+
rm,
|
|
12
|
+
symlink,
|
|
13
|
+
writeFile,
|
|
14
|
+
} from "node:fs/promises";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { homeLayout } from "@gajae-gateway/home";
|
|
17
|
+
|
|
18
|
+
export interface GjcInstallRunResult {
|
|
19
|
+
readonly exitCode: number;
|
|
20
|
+
readonly stdout: string;
|
|
21
|
+
readonly stderr: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type GjcInstallRunner = (command: readonly string[], cwd: string) => Promise<GjcInstallRunResult>;
|
|
25
|
+
|
|
26
|
+
const VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
27
|
+
|
|
28
|
+
async function defaultRunner(command: readonly string[], cwd: string): Promise<GjcInstallRunResult> {
|
|
29
|
+
const child = Bun.spawn([...command], { cwd, stdin: "ignore", stdout: "pipe", stderr: "pipe" });
|
|
30
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
31
|
+
new Response(child.stdout).text(),
|
|
32
|
+
new Response(child.stderr).text(),
|
|
33
|
+
child.exited,
|
|
34
|
+
]);
|
|
35
|
+
return { exitCode, stdout, stderr };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function assertSuccessful(command: readonly string[], result: GjcInstallRunResult): void {
|
|
39
|
+
if (result.exitCode !== 0) {
|
|
40
|
+
const detail = result.stderr.trim();
|
|
41
|
+
throw new Error(
|
|
42
|
+
`${command.join(" ")} exited with status ${result.exitCode}${detail.length === 0 ? "" : `: ${detail}`}`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function versionFromOutput(output: string): string | undefined {
|
|
48
|
+
return output.match(/\b\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?\b/)?.[0];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function verifyGjc(path: string, cwd: string, version: string, runner: GjcInstallRunner): Promise<void> {
|
|
52
|
+
await access(path);
|
|
53
|
+
const command = [path, "--version"];
|
|
54
|
+
const result = await runner(command, cwd);
|
|
55
|
+
assertSuccessful(command, result);
|
|
56
|
+
const reported = versionFromOutput(`${result.stdout}\n${result.stderr}`);
|
|
57
|
+
if (reported !== version)
|
|
58
|
+
throw new Error(`gjc version verification failed: expected ${version}, got ${reported ?? "unknown"}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function currentVersion(prefix: string, current: string): Promise<string | undefined> {
|
|
62
|
+
try {
|
|
63
|
+
const target = await readlink(current);
|
|
64
|
+
if (target.includes("/") || !VERSION_PATTERN.test(target)) return undefined;
|
|
65
|
+
const targetPath = join(prefix, target);
|
|
66
|
+
if (!(await lstat(targetPath)).isDirectory()) return undefined;
|
|
67
|
+
return target;
|
|
68
|
+
} catch {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function pruneVersions(prefix: string, keep: readonly string[]): Promise<void> {
|
|
74
|
+
const retained = new Set(keep);
|
|
75
|
+
const entries = await readdir(prefix, { withFileTypes: true });
|
|
76
|
+
const versions = entries
|
|
77
|
+
.filter((entry) => entry.isDirectory() && VERSION_PATTERN.test(entry.name))
|
|
78
|
+
.map((entry) => entry.name)
|
|
79
|
+
.sort((left, right) => Bun.semver.order(right, left));
|
|
80
|
+
for (const version of versions) {
|
|
81
|
+
if (retained.size >= 2) break;
|
|
82
|
+
retained.add(version);
|
|
83
|
+
}
|
|
84
|
+
for (const version of versions)
|
|
85
|
+
if (!retained.has(version)) await rm(join(prefix, version), { recursive: true, force: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Install the gateway-pinned gjc into its versioned private prefix. */
|
|
89
|
+
export async function installPinnedGjc(options: {
|
|
90
|
+
readonly home: string;
|
|
91
|
+
readonly version: string;
|
|
92
|
+
readonly runner?: GjcInstallRunner;
|
|
93
|
+
}): Promise<string> {
|
|
94
|
+
const { home, version } = options;
|
|
95
|
+
if (!VERSION_PATTERN.test(version)) throw new Error(`invalid pinned gjc version: ${version}`);
|
|
96
|
+
const layout = homeLayout(home);
|
|
97
|
+
const runner = options.runner ?? defaultRunner;
|
|
98
|
+
await mkdir(layout.gjcPrefix, { recursive: true, mode: 0o700 });
|
|
99
|
+
await chmod(layout.gjcPrefix, 0o700);
|
|
100
|
+
|
|
101
|
+
const versionDir = join(layout.gjcPrefix, version);
|
|
102
|
+
const previousVersion = await currentVersion(layout.gjcPrefix, layout.gjcCurrent);
|
|
103
|
+
let staging: string | undefined;
|
|
104
|
+
try {
|
|
105
|
+
let installed = false;
|
|
106
|
+
try {
|
|
107
|
+
const info = await lstat(versionDir);
|
|
108
|
+
if (!info.isDirectory()) throw new Error(`gjc version path is not a directory: ${versionDir}`);
|
|
109
|
+
installed = true;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (!installed) {
|
|
115
|
+
staging = await mkdtemp(join(layout.gjcPrefix, ".staging-"));
|
|
116
|
+
await chmod(staging, 0o700);
|
|
117
|
+
await writeFile(
|
|
118
|
+
join(staging, "package.json"),
|
|
119
|
+
`${JSON.stringify({ private: true, dependencies: { "gajae-code": version } }, null, 2)}\n`,
|
|
120
|
+
{ mode: 0o600 },
|
|
121
|
+
);
|
|
122
|
+
const installCommand = ["bun", "install", "--production"];
|
|
123
|
+
assertSuccessful(installCommand, await runner(installCommand, staging));
|
|
124
|
+
const installedBin = join(staging, "node_modules", ".bin", "gjc");
|
|
125
|
+
await access(installedBin);
|
|
126
|
+
const binDir = join(staging, "bin");
|
|
127
|
+
await mkdir(binDir, { mode: 0o700 });
|
|
128
|
+
await symlink("../node_modules/.bin/gjc", join(binDir, "gjc"), "file");
|
|
129
|
+
await verifyGjc(join(binDir, "gjc"), staging, version, runner);
|
|
130
|
+
await rename(staging, versionDir);
|
|
131
|
+
staging = undefined;
|
|
132
|
+
} else {
|
|
133
|
+
await verifyGjc(join(versionDir, "bin", "gjc"), versionDir, version, runner);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await pruneVersions(layout.gjcPrefix, [version, ...(previousVersion === undefined ? [] : [previousVersion])]);
|
|
137
|
+
const temporaryLink = join(layout.gjcPrefix, `.current-${randomUUID()}`);
|
|
138
|
+
try {
|
|
139
|
+
await symlink(version, temporaryLink, "dir");
|
|
140
|
+
await rename(temporaryLink, layout.gjcCurrent);
|
|
141
|
+
} finally {
|
|
142
|
+
await rm(temporaryLink, { force: true });
|
|
143
|
+
}
|
|
144
|
+
return layout.gjcExecutable();
|
|
145
|
+
} finally {
|
|
146
|
+
if (staging !== undefined) await rm(staging, { recursive: true, force: true });
|
|
147
|
+
}
|
|
148
|
+
}
|