@alfe.ai/gateway 0.0.13 → 0.0.15
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/health.js +65 -27
- package/dist/upgrade.js +34 -50
- package/package.json +5 -5
package/dist/health.js
CHANGED
|
@@ -4,7 +4,7 @@ import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import pino from "pino";
|
|
7
|
-
import { chmodSync, existsSync, unlinkSync } from "node:fs";
|
|
7
|
+
import { chmodSync, existsSync, readFileSync, unlinkSync } from "node:fs";
|
|
8
8
|
import { getEndpointFromToken, readConfig } from "@alfe.ai/config";
|
|
9
9
|
import crypto from "crypto";
|
|
10
10
|
import { parse } from "smol-toml";
|
|
@@ -3152,7 +3152,16 @@ enumValues({
|
|
|
3152
3152
|
object({ gracePeriodDays: number().int().positive().optional() });
|
|
3153
3153
|
enumValues({
|
|
3154
3154
|
Active: "active",
|
|
3155
|
-
|
|
3155
|
+
Pending: "pending",
|
|
3156
|
+
Provisioning: "provisioning",
|
|
3157
|
+
Starting: "starting",
|
|
3158
|
+
Running: "running",
|
|
3159
|
+
Stopping: "stopping",
|
|
3160
|
+
Stopped: "stopped",
|
|
3161
|
+
Rebooting: "rebooting",
|
|
3162
|
+
Failing: "failing",
|
|
3163
|
+
Failed: "failed",
|
|
3164
|
+
BillingSuspended: "billing_suspended",
|
|
3156
3165
|
Deleted: "deleted"
|
|
3157
3166
|
});
|
|
3158
3167
|
enumValues({
|
|
@@ -3163,16 +3172,6 @@ enumValues({
|
|
|
3163
3172
|
OpenClaw: "openclaw",
|
|
3164
3173
|
NanoClaw: "nanoclaw"
|
|
3165
3174
|
});
|
|
3166
|
-
enumValues({
|
|
3167
|
-
None: "none",
|
|
3168
|
-
Pending: "pending",
|
|
3169
|
-
Provisioning: "provisioning",
|
|
3170
|
-
Running: "running",
|
|
3171
|
-
Stopped: "stopped",
|
|
3172
|
-
Failing: "failing",
|
|
3173
|
-
Failed: "failed",
|
|
3174
|
-
BillingSuspended: "billing_suspended"
|
|
3175
|
-
});
|
|
3176
3175
|
enumValues({
|
|
3177
3176
|
Active: "active",
|
|
3178
3177
|
Removed: "removed"
|
|
@@ -3437,7 +3436,12 @@ async function loadRuntimeConfigs() {
|
|
|
3437
3436
|
* of ~/.alfe/config.toml, and IPC/PID features are disabled.
|
|
3438
3437
|
*/
|
|
3439
3438
|
function isManagedMode() {
|
|
3440
|
-
|
|
3439
|
+
if (process.env.ALFE_MANAGED === "true") return true;
|
|
3440
|
+
try {
|
|
3441
|
+
return parse(readFileSync(join(homedir(), ".alfe", "config.toml"), "utf-8")).managed === true;
|
|
3442
|
+
} catch {
|
|
3443
|
+
return false;
|
|
3444
|
+
}
|
|
3441
3445
|
}
|
|
3442
3446
|
/**
|
|
3443
3447
|
* Load configuration for managed mode (ECS Fargate).
|
|
@@ -20432,44 +20436,78 @@ async function handleCloudCommand(command) {
|
|
|
20432
20436
|
};
|
|
20433
20437
|
}
|
|
20434
20438
|
}
|
|
20435
|
-
if (command.command === "
|
|
20436
|
-
const
|
|
20437
|
-
if (!
|
|
20439
|
+
if (command.command === "support.bash") {
|
|
20440
|
+
const payload = command.payload;
|
|
20441
|
+
if (!payload.cmd) return {
|
|
20438
20442
|
type: "COMMAND_ACK",
|
|
20439
20443
|
commandId: command.commandId,
|
|
20440
20444
|
status: "error",
|
|
20441
20445
|
result: {
|
|
20442
|
-
code: "
|
|
20443
|
-
message: "
|
|
20446
|
+
code: "MISSING_CMD",
|
|
20447
|
+
message: "No command provided"
|
|
20444
20448
|
}
|
|
20445
20449
|
};
|
|
20450
|
+
const workspacePath = Object.values(config.runtimes)[0]?.workspace ?? "~/.openclaw";
|
|
20446
20451
|
try {
|
|
20447
|
-
const {
|
|
20448
|
-
await
|
|
20449
|
-
|
|
20452
|
+
const { exec } = await import("child_process");
|
|
20453
|
+
const { promisify } = await import("util");
|
|
20454
|
+
const { stdout, stderr } = await promisify(exec)(payload.cmd, {
|
|
20455
|
+
cwd: workspacePath,
|
|
20456
|
+
timeout: 25e3,
|
|
20457
|
+
maxBuffer: 512 * 1024
|
|
20458
|
+
});
|
|
20450
20459
|
return {
|
|
20451
20460
|
type: "COMMAND_ACK",
|
|
20452
20461
|
commandId: command.commandId,
|
|
20453
20462
|
status: "ok",
|
|
20454
20463
|
result: {
|
|
20455
|
-
|
|
20456
|
-
|
|
20464
|
+
stdout: stdout.trim(),
|
|
20465
|
+
stderr: stderr.trim()
|
|
20457
20466
|
}
|
|
20458
20467
|
};
|
|
20459
20468
|
} catch (err) {
|
|
20460
|
-
const
|
|
20461
|
-
logger$1.error({ err: message }, "Failed to spawn upgrade script");
|
|
20469
|
+
const execErr = err;
|
|
20462
20470
|
return {
|
|
20463
20471
|
type: "COMMAND_ACK",
|
|
20464
20472
|
commandId: command.commandId,
|
|
20465
20473
|
status: "error",
|
|
20466
20474
|
result: {
|
|
20467
|
-
code: "
|
|
20468
|
-
|
|
20475
|
+
code: "EXEC_FAILED",
|
|
20476
|
+
stdout: execErr.stdout?.trim() ?? "",
|
|
20477
|
+
stderr: execErr.stderr?.trim() ?? "",
|
|
20478
|
+
message: execErr.message ?? String(err),
|
|
20479
|
+
exitCode: execErr.code
|
|
20469
20480
|
}
|
|
20470
20481
|
};
|
|
20471
20482
|
}
|
|
20472
20483
|
}
|
|
20484
|
+
if (command.command === "daemon.update") {
|
|
20485
|
+
const version = command.payload?.version ?? "latest";
|
|
20486
|
+
if (!isManagedMode()) return {
|
|
20487
|
+
type: "COMMAND_ACK",
|
|
20488
|
+
commandId: command.commandId,
|
|
20489
|
+
status: "error",
|
|
20490
|
+
result: {
|
|
20491
|
+
code: "NOT_MANAGED",
|
|
20492
|
+
message: "daemon.update is only supported in managed mode"
|
|
20493
|
+
}
|
|
20494
|
+
};
|
|
20495
|
+
setTimeout(() => {
|
|
20496
|
+
import("./upgrade.js").then(({ upgradeAndExit }) => upgradeAndExit(version)).catch((err) => {
|
|
20497
|
+
logger$1.error({ err: err instanceof Error ? err.message : String(err) }, "Upgrade failed");
|
|
20498
|
+
process.exit(1);
|
|
20499
|
+
});
|
|
20500
|
+
}, 500);
|
|
20501
|
+
return {
|
|
20502
|
+
type: "COMMAND_ACK",
|
|
20503
|
+
commandId: command.commandId,
|
|
20504
|
+
status: "ok",
|
|
20505
|
+
result: {
|
|
20506
|
+
upgrading: true,
|
|
20507
|
+
version
|
|
20508
|
+
}
|
|
20509
|
+
};
|
|
20510
|
+
}
|
|
20473
20511
|
if (command.command === "integration.status") {
|
|
20474
20512
|
const payload = command.payload;
|
|
20475
20513
|
try {
|
package/dist/upgrade.js
CHANGED
|
@@ -1,60 +1,44 @@
|
|
|
1
1
|
import { n as logger } from "./logger.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { execFile } from "node:child_process";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
4
|
//#region src/upgrade.ts
|
|
5
5
|
/**
|
|
6
|
-
* CLI upgrade —
|
|
6
|
+
* CLI upgrade — runs npm install inline then exits.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* 2. Spawn it detached (survives parent death)
|
|
12
|
-
* 3. The script stops the service, upgrades, re-runs setup, and restarts
|
|
8
|
+
* Systemd has Restart=always, so after the daemon exits the service
|
|
9
|
+
* restarts automatically with the new CLI version. No detached scripts,
|
|
10
|
+
* no race conditions.
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* Flow:
|
|
13
|
+
* 1. Daemon ACKs the COMMAND (caller handles this before calling upgrade)
|
|
14
|
+
* 2. npm install -g @alfe.ai/cli@{version} runs as a child process
|
|
15
|
+
* 3. Daemon exits with code 0
|
|
16
|
+
* 4. Systemd restarts the service → new version boots
|
|
16
17
|
*/
|
|
18
|
+
const execFileAsync = promisify(execFile);
|
|
17
19
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* 2. Stop the systemd service
|
|
21
|
-
* 3. Install the target CLI version globally
|
|
22
|
-
* 4. Re-run `alfe setup --managed` to regenerate the systemd unit
|
|
23
|
-
* 5. Start the service again
|
|
24
|
-
* 6. Clean up the script file
|
|
20
|
+
* Upgrade the CLI to a target version and exit.
|
|
21
|
+
* Systemd will restart the daemon with the new version.
|
|
25
22
|
*/
|
|
26
|
-
async function
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
rm -f "$0"
|
|
46
|
-
`, "utf-8");
|
|
47
|
-
await chmod(scriptPath, 493);
|
|
48
|
-
const child = spawn("bash", [scriptPath], {
|
|
49
|
-
detached: true,
|
|
50
|
-
stdio: "ignore"
|
|
51
|
-
});
|
|
52
|
-
child.unref();
|
|
53
|
-
logger.info({
|
|
54
|
-
scriptPath,
|
|
55
|
-
version,
|
|
56
|
-
pid: child.pid
|
|
57
|
-
}, "Spawned detached upgrade script");
|
|
23
|
+
async function upgradeAndExit(version) {
|
|
24
|
+
logger.info({ version }, "Upgrading CLI...");
|
|
25
|
+
try {
|
|
26
|
+
const { stdout, stderr } = await execFileAsync("npm", [
|
|
27
|
+
"install",
|
|
28
|
+
"-g",
|
|
29
|
+
`@alfe.ai/cli@${version}`
|
|
30
|
+
], { timeout: 12e4 });
|
|
31
|
+
if (stdout) logger.debug({ stdout: stdout.trim() }, "npm install stdout");
|
|
32
|
+
if (stderr) logger.debug({ stderr: stderr.trim() }, "npm install stderr");
|
|
33
|
+
logger.info({ version }, "CLI upgraded — exiting for systemd restart");
|
|
34
|
+
} catch (err) {
|
|
35
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
36
|
+
logger.error({
|
|
37
|
+
err: message,
|
|
38
|
+
version
|
|
39
|
+
}, "CLI upgrade failed");
|
|
40
|
+
}
|
|
41
|
+
process.exit(0);
|
|
58
42
|
}
|
|
59
43
|
//#endregion
|
|
60
|
-
export {
|
|
44
|
+
export { upgradeAndExit };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/gateway",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"description": "Alfe local gateway daemon — persistent control plane for agent integrations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"pino-roll": "^1.2.0",
|
|
23
23
|
"smol-toml": ">=1.6.1",
|
|
24
24
|
"ws": "^8.18.0",
|
|
25
|
-
"@alfe.ai/ai-proxy-local": "^0.0.
|
|
26
|
-
"@alfe.ai/config": "^0.0.
|
|
27
|
-
"@alfe.ai/doctor": "^0.0.
|
|
28
|
-
"@alfe.ai/integrations": "^0.0.
|
|
25
|
+
"@alfe.ai/ai-proxy-local": "^0.0.4",
|
|
26
|
+
"@alfe.ai/config": "^0.0.4",
|
|
27
|
+
"@alfe.ai/doctor": "^0.0.4",
|
|
28
|
+
"@alfe.ai/integrations": "^0.0.8"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/ws": "^8.5.13",
|