@alfe.ai/gateway 0.0.8 → 0.0.10
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/bin/gateway.js +2 -1
- package/dist/health.js +167 -50
- package/dist/logger.js +46 -0
- package/dist/src/index.js +2 -1
- package/dist/upgrade.js +62 -0
- package/package.json +3 -3
package/dist/bin/gateway.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as installService, c as uninstallService, f as SOCKET_PATH,
|
|
2
|
+
import { a as installService, c as uninstallService, f as SOCKET_PATH, i as checkExistingDaemon, n as queryDaemonHealth, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport } from "../health.js";
|
|
3
|
+
import { t as LOG_FILE } from "../logger.js";
|
|
3
4
|
import { spawn } from "node:child_process";
|
|
4
5
|
//#region bin/gateway.ts
|
|
5
6
|
/**
|
package/dist/health.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { n as logger$1 } from "./logger.js";
|
|
1
2
|
import { createRequire } from "node:module";
|
|
2
3
|
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { homedir } from "node:os";
|
|
5
6
|
import pino from "pino";
|
|
6
|
-
import { chmodSync, existsSync,
|
|
7
|
+
import { chmodSync, existsSync, unlinkSync } from "node:fs";
|
|
7
8
|
import { getEndpointFromToken, readConfig } from "@alfe.ai/config";
|
|
8
9
|
import crypto from "crypto";
|
|
9
10
|
import { parse } from "smol-toml";
|
|
@@ -53,47 +54,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
53
54
|
}) : target, mod));
|
|
54
55
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
55
56
|
//#endregion
|
|
56
|
-
//#region src/logger.ts
|
|
57
|
-
/**
|
|
58
|
-
* Daemon logger — pino with rolling file output.
|
|
59
|
-
*
|
|
60
|
-
* Writes to ~/.alfe/logs/gateway.log with 10MB rotation, keep 5 files.
|
|
61
|
-
* In managed mode (ECS Fargate): always stdout for CloudWatch capture.
|
|
62
|
-
* In development: stdout.
|
|
63
|
-
*/
|
|
64
|
-
const LOG_DIR = join(homedir(), ".alfe", "logs");
|
|
65
|
-
const LOG_FILE = join(LOG_DIR, "gateway.log");
|
|
66
|
-
const isDev = process.env.NODE_ENV !== "production";
|
|
67
|
-
const isManaged = process.env.ALFE_MANAGED === "true";
|
|
68
|
-
if (!isManaged) try {
|
|
69
|
-
mkdirSync(LOG_DIR, { recursive: true });
|
|
70
|
-
} catch {}
|
|
71
|
-
/**
|
|
72
|
-
* Create the daemon logger.
|
|
73
|
-
* Managed mode (ECS): JSON to stdout (CloudWatch captures via awslogs driver).
|
|
74
|
-
* Development: JSON to stdout.
|
|
75
|
-
* Production (local): JSON to rolling file.
|
|
76
|
-
*/
|
|
77
|
-
function createLogger$1() {
|
|
78
|
-
if (isDev || isManaged) return pino({
|
|
79
|
-
level: process.env.LOG_LEVEL ?? (isDev ? "debug" : "info"),
|
|
80
|
-
transport: {
|
|
81
|
-
target: "pino/file",
|
|
82
|
-
options: { destination: 1 }
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
const transport = pino.transport({
|
|
86
|
-
target: "pino-roll",
|
|
87
|
-
options: {
|
|
88
|
-
file: LOG_FILE,
|
|
89
|
-
size: "10m",
|
|
90
|
-
limit: { count: 5 }
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
return pino({ level: process.env.LOG_LEVEL ?? "info" }, transport);
|
|
94
|
-
}
|
|
95
|
-
const logger$1 = createLogger$1();
|
|
96
|
-
//#endregion
|
|
97
57
|
//#region ../../packages-internal/ids/dist/prefixes.js
|
|
98
58
|
const ID_PREFIXES = {
|
|
99
59
|
agent: "agt",
|
|
@@ -407,6 +367,95 @@ var AuthService = class {
|
|
|
407
367
|
}
|
|
408
368
|
};
|
|
409
369
|
//#endregion
|
|
370
|
+
//#region ../../packages-internal/api-client/dist/services/integrations.js
|
|
371
|
+
var IntegrationsService = class {
|
|
372
|
+
client;
|
|
373
|
+
voiceClient;
|
|
374
|
+
constructor(client, voiceClient) {
|
|
375
|
+
this.client = client;
|
|
376
|
+
this.voiceClient = voiceClient;
|
|
377
|
+
}
|
|
378
|
+
listIntegrations(agentId) {
|
|
379
|
+
return this.client.request(`/integrations/agents/${agentId}`);
|
|
380
|
+
}
|
|
381
|
+
installIntegration(agentId, data) {
|
|
382
|
+
return this.client.request(`/integrations/agents/${agentId}`, {
|
|
383
|
+
method: "POST",
|
|
384
|
+
body: JSON.stringify(data)
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
getIntegrationConfig(agentId, integrationId) {
|
|
388
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}/config`);
|
|
389
|
+
}
|
|
390
|
+
updateIntegration(agentId, integrationId, data) {
|
|
391
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}`, {
|
|
392
|
+
method: "PATCH",
|
|
393
|
+
body: JSON.stringify(data)
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
removeIntegration(agentId, integrationId) {
|
|
397
|
+
return this.client.request(`/integrations/agents/${agentId}/${integrationId}`, { method: "DELETE" });
|
|
398
|
+
}
|
|
399
|
+
getRegistry() {
|
|
400
|
+
return this.client.request("/integrations/registry");
|
|
401
|
+
}
|
|
402
|
+
triggerSync(agentId) {
|
|
403
|
+
return this.client.request("/integrations/sync/trigger", {
|
|
404
|
+
method: "POST",
|
|
405
|
+
body: JSON.stringify({ agentId })
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
listVoices() {
|
|
409
|
+
if (this.voiceClient) return this.voiceClient.request("/api/voices");
|
|
410
|
+
return this.client.request("/integrations/voices");
|
|
411
|
+
}
|
|
412
|
+
getDiscordGuildChannels(guildId) {
|
|
413
|
+
return this.client.request(`/discord/guilds/${encodeURIComponent(guildId)}/channels`);
|
|
414
|
+
}
|
|
415
|
+
listMobileNumbers() {
|
|
416
|
+
return this.client.request("/mobile/numbers");
|
|
417
|
+
}
|
|
418
|
+
assignMobileNumber(agentId, phoneNumber) {
|
|
419
|
+
return this.client.request("/mobile/numbers/assign", {
|
|
420
|
+
method: "POST",
|
|
421
|
+
body: JSON.stringify({
|
|
422
|
+
agentId,
|
|
423
|
+
phoneNumber
|
|
424
|
+
})
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
recallJoinMeeting(agentId, meetingUrl, botName) {
|
|
428
|
+
if (this.voiceClient) return this.voiceClient.request("/api/join", {
|
|
429
|
+
method: "POST",
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
agentId,
|
|
432
|
+
meetingUrl,
|
|
433
|
+
botName
|
|
434
|
+
})
|
|
435
|
+
});
|
|
436
|
+
return this.client.request("/integrations/recall/join", {
|
|
437
|
+
method: "POST",
|
|
438
|
+
body: JSON.stringify({
|
|
439
|
+
agentId,
|
|
440
|
+
meetingUrl,
|
|
441
|
+
botName
|
|
442
|
+
})
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
listSlackChannels(agentId) {
|
|
446
|
+
return this.client.request(`/slack/agents/${encodeURIComponent(agentId)}/channels`);
|
|
447
|
+
}
|
|
448
|
+
sendSlackMessage(agentId, channel, text) {
|
|
449
|
+
return this.client.request(`/slack/agents/${encodeURIComponent(agentId)}/send`, {
|
|
450
|
+
method: "POST",
|
|
451
|
+
body: JSON.stringify({
|
|
452
|
+
channel,
|
|
453
|
+
text
|
|
454
|
+
})
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
//#endregion
|
|
410
459
|
//#region ../../packages-internal/types/dist/lib/enum-values.js
|
|
411
460
|
/**
|
|
412
461
|
* Converts a const enum object into a non-empty readonly tuple.
|
|
@@ -3550,13 +3599,15 @@ function createServiceRegister(agentId, capabilities = [
|
|
|
3550
3599
|
"integrations",
|
|
3551
3600
|
"lifecycle",
|
|
3552
3601
|
"health"
|
|
3553
|
-
]) {
|
|
3554
|
-
|
|
3602
|
+
], cliVersion) {
|
|
3603
|
+
const msg = {
|
|
3555
3604
|
type: "SERVICE_REGISTER",
|
|
3556
3605
|
serviceId: `gateway-daemon-${agentId}`,
|
|
3557
3606
|
agentIds: [agentId],
|
|
3558
3607
|
capabilities
|
|
3559
3608
|
};
|
|
3609
|
+
if (cliVersion) msg.cliVersion = cliVersion;
|
|
3610
|
+
return msg;
|
|
3560
3611
|
}
|
|
3561
3612
|
/**
|
|
3562
3613
|
* Create an IPC success response.
|
|
@@ -3943,10 +3994,11 @@ var CloudClient = class {
|
|
|
3943
3994
|
});
|
|
3944
3995
|
}
|
|
3945
3996
|
sendRegister() {
|
|
3946
|
-
const msg = createServiceRegister(this.config.agentId);
|
|
3997
|
+
const msg = createServiceRegister(this.config.agentId, void 0, this.config.cliVersion);
|
|
3947
3998
|
logger$1.debug({
|
|
3948
3999
|
serviceId: msg.serviceId,
|
|
3949
|
-
agentIds: msg.agentIds
|
|
4000
|
+
agentIds: msg.agentIds,
|
|
4001
|
+
cliVersion: msg.cliVersion
|
|
3950
4002
|
}, "Cloud: sending SERVICE_REGISTER");
|
|
3951
4003
|
this.send(msg);
|
|
3952
4004
|
logger$1.info({ serviceId: msg.serviceId }, "Sent SERVICE_REGISTER");
|
|
@@ -20048,6 +20100,22 @@ let aiProxyUrl = null;
|
|
|
20048
20100
|
let aiProxyRunning = false;
|
|
20049
20101
|
let cloudConnected = false;
|
|
20050
20102
|
let shuttingDown = false;
|
|
20103
|
+
let resolvedCliVersion;
|
|
20104
|
+
/**
|
|
20105
|
+
* Resolve the installed @alfe.ai/cli version.
|
|
20106
|
+
* Prefers ALFE_CLI_VERSION env var (set by the CLI entry point),
|
|
20107
|
+
* falls back to resolving @alfe.ai/cli/package.json directly.
|
|
20108
|
+
*/
|
|
20109
|
+
async function getCliVersion() {
|
|
20110
|
+
if (process.env.ALFE_CLI_VERSION) return process.env.ALFE_CLI_VERSION;
|
|
20111
|
+
try {
|
|
20112
|
+
const raw = await readFile(createRequire(import.meta.url).resolve("@alfe.ai/cli/package.json"), "utf-8");
|
|
20113
|
+
return JSON.parse(raw).version;
|
|
20114
|
+
} catch {
|
|
20115
|
+
logger$1.debug("Could not resolve @alfe.ai/cli version — daemon may not be running from CLI");
|
|
20116
|
+
return;
|
|
20117
|
+
}
|
|
20118
|
+
}
|
|
20051
20119
|
/**
|
|
20052
20120
|
* Flush pino's async transport and exit.
|
|
20053
20121
|
* process.exit() can drop buffered log lines — this ensures they're written first.
|
|
@@ -20140,6 +20208,8 @@ async function startDaemon() {
|
|
|
20140
20208
|
}, "Failed to start IPC server");
|
|
20141
20209
|
await flushAndExit(1);
|
|
20142
20210
|
}
|
|
20211
|
+
resolvedCliVersion = await getCliVersion();
|
|
20212
|
+
logger$1.info({ cliVersion: resolvedCliVersion }, "Resolved CLI version");
|
|
20143
20213
|
logger$1.debug({
|
|
20144
20214
|
wsUrl: config.gatewayWsUrl,
|
|
20145
20215
|
agentId: config.agentId
|
|
@@ -20147,7 +20217,8 @@ async function startDaemon() {
|
|
|
20147
20217
|
cloudClient = new CloudClient({
|
|
20148
20218
|
wsUrl: config.gatewayWsUrl,
|
|
20149
20219
|
apiKey: config.apiKey,
|
|
20150
|
-
agentId: config.agentId
|
|
20220
|
+
agentId: config.agentId,
|
|
20221
|
+
cliVersion: resolvedCliVersion
|
|
20151
20222
|
});
|
|
20152
20223
|
cloudClient.setCommandHandler(handleCloudCommand);
|
|
20153
20224
|
cloudClient.setConnectionChangeHandler((connected) => {
|
|
@@ -20163,9 +20234,17 @@ async function startDaemon() {
|
|
|
20163
20234
|
workspace: runtimeCfg.workspace
|
|
20164
20235
|
}, "Registered OpenClaw runtime applier");
|
|
20165
20236
|
} else logger$1.warn({ runtime: name }, "Unknown runtime type — skipping");
|
|
20237
|
+
const integrationsService = new IntegrationsService(new AlfeApiClient({
|
|
20238
|
+
apiBaseUrl: config.apiEndpoint,
|
|
20239
|
+
getToken: () => Promise.resolve(config.apiKey)
|
|
20240
|
+
}));
|
|
20166
20241
|
integrationManager = new IntegrationManager({
|
|
20167
|
-
|
|
20168
|
-
|
|
20242
|
+
runtimeAppliers,
|
|
20243
|
+
registryFetcher: async () => {
|
|
20244
|
+
const result = await integrationsService.getRegistry();
|
|
20245
|
+
if (!result.ok) throw new Error(result.error);
|
|
20246
|
+
return result.data.integrations;
|
|
20247
|
+
}
|
|
20169
20248
|
});
|
|
20170
20249
|
const integrationAdapter = new IntegrationManagerAdapter(integrationManager);
|
|
20171
20250
|
cloudClient.setIntegrationManager(integrationAdapter);
|
|
@@ -20314,6 +20393,44 @@ async function handleCloudCommand(command) {
|
|
|
20314
20393
|
};
|
|
20315
20394
|
}
|
|
20316
20395
|
}
|
|
20396
|
+
if (command.command === "daemon.update") {
|
|
20397
|
+
const version = command.payload?.version ?? "latest";
|
|
20398
|
+
if (!isManagedMode()) return {
|
|
20399
|
+
type: "COMMAND_ACK",
|
|
20400
|
+
commandId: command.commandId,
|
|
20401
|
+
status: "error",
|
|
20402
|
+
result: {
|
|
20403
|
+
code: "NOT_MANAGED",
|
|
20404
|
+
message: "daemon.update is only supported in managed mode"
|
|
20405
|
+
}
|
|
20406
|
+
};
|
|
20407
|
+
try {
|
|
20408
|
+
const { spawnUpgradeScript } = await import("./upgrade.js");
|
|
20409
|
+
await spawnUpgradeScript(version);
|
|
20410
|
+
logger$1.info({ version }, "Upgrade script spawned — daemon will restart shortly");
|
|
20411
|
+
return {
|
|
20412
|
+
type: "COMMAND_ACK",
|
|
20413
|
+
commandId: command.commandId,
|
|
20414
|
+
status: "ok",
|
|
20415
|
+
result: {
|
|
20416
|
+
upgrading: true,
|
|
20417
|
+
version
|
|
20418
|
+
}
|
|
20419
|
+
};
|
|
20420
|
+
} catch (err) {
|
|
20421
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
20422
|
+
logger$1.error({ err: message }, "Failed to spawn upgrade script");
|
|
20423
|
+
return {
|
|
20424
|
+
type: "COMMAND_ACK",
|
|
20425
|
+
commandId: command.commandId,
|
|
20426
|
+
status: "error",
|
|
20427
|
+
result: {
|
|
20428
|
+
code: "UPGRADE_FAILED",
|
|
20429
|
+
message
|
|
20430
|
+
}
|
|
20431
|
+
};
|
|
20432
|
+
}
|
|
20433
|
+
}
|
|
20317
20434
|
if (command.command === "integration.status") {
|
|
20318
20435
|
const payload = command.payload;
|
|
20319
20436
|
try {
|
|
@@ -20568,4 +20685,4 @@ function formatDuration(ms) {
|
|
|
20568
20685
|
return `${String(Math.round(seconds / 3600))}h`;
|
|
20569
20686
|
}
|
|
20570
20687
|
//#endregion
|
|
20571
|
-
export {
|
|
20688
|
+
export { installService as a, uninstallService as c, PID_PATH as d, SOCKET_PATH as f, resolveAgentIdentity as h, checkExistingDaemon as i, PROTOCOL_VERSION as l, loadDaemonConfig as m, queryDaemonHealth as n, startService as o, fetchAgentConfig as p, startDaemon as r, stopExistingDaemon as s, formatHealthReport as t, ALFE_DIR as u };
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import pino from "pino";
|
|
4
|
+
import { mkdirSync } from "node:fs";
|
|
5
|
+
//#region src/logger.ts
|
|
6
|
+
/**
|
|
7
|
+
* Daemon logger — pino with rolling file output.
|
|
8
|
+
*
|
|
9
|
+
* Writes to ~/.alfe/logs/gateway.log with 10MB rotation, keep 5 files.
|
|
10
|
+
* In managed mode (ECS Fargate): always stdout for CloudWatch capture.
|
|
11
|
+
* In development: stdout.
|
|
12
|
+
*/
|
|
13
|
+
const LOG_DIR = join(homedir(), ".alfe", "logs");
|
|
14
|
+
const LOG_FILE = join(LOG_DIR, "gateway.log");
|
|
15
|
+
const isDev = process.env.NODE_ENV !== "production";
|
|
16
|
+
const isManaged = process.env.ALFE_MANAGED === "true";
|
|
17
|
+
if (!isManaged) try {
|
|
18
|
+
mkdirSync(LOG_DIR, { recursive: true });
|
|
19
|
+
} catch {}
|
|
20
|
+
/**
|
|
21
|
+
* Create the daemon logger.
|
|
22
|
+
* Managed mode (ECS): JSON to stdout (CloudWatch captures via awslogs driver).
|
|
23
|
+
* Development: JSON to stdout.
|
|
24
|
+
* Production (local): JSON to rolling file.
|
|
25
|
+
*/
|
|
26
|
+
function createLogger() {
|
|
27
|
+
if (isDev || isManaged) return pino({
|
|
28
|
+
level: process.env.LOG_LEVEL ?? (isDev ? "debug" : "info"),
|
|
29
|
+
transport: {
|
|
30
|
+
target: "pino/file",
|
|
31
|
+
options: { destination: 1 }
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const transport = pino.transport({
|
|
35
|
+
target: "pino-roll",
|
|
36
|
+
options: {
|
|
37
|
+
file: LOG_FILE,
|
|
38
|
+
size: "10m",
|
|
39
|
+
limit: { count: 5 }
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return pino({ level: process.env.LOG_LEVEL ?? "info" }, transport);
|
|
43
|
+
}
|
|
44
|
+
const logger = createLogger();
|
|
45
|
+
//#endregion
|
|
46
|
+
export { logger as n, LOG_FILE as t };
|
package/dist/src/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as installService, c as uninstallService, d as PID_PATH, f as SOCKET_PATH, h as resolveAgentIdentity, i as checkExistingDaemon, l as PROTOCOL_VERSION, m as loadDaemonConfig, n as queryDaemonHealth, o as startService, p as fetchAgentConfig, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport, u as ALFE_DIR } from "../health.js";
|
|
2
|
+
import { n as logger } from "../logger.js";
|
|
2
3
|
export { ALFE_DIR, PID_PATH, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, startService, stopExistingDaemon, uninstallService };
|
package/dist/upgrade.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { n as logger } from "./logger.js";
|
|
2
|
+
import { chmod, writeFile } from "node:fs/promises";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
//#region src/upgrade.ts
|
|
5
|
+
/**
|
|
6
|
+
* CLI upgrade — spawns a detached shell script to upgrade @alfe.ai/cli.
|
|
7
|
+
*
|
|
8
|
+
* The daemon process IS the service being upgraded, so it cannot manage the
|
|
9
|
+
* upgrade itself. Instead we:
|
|
10
|
+
* 1. Write a bash script to /tmp
|
|
11
|
+
* 2. Spawn it detached (survives parent death)
|
|
12
|
+
* 3. The script stops the service, upgrades, re-runs setup, and restarts
|
|
13
|
+
*
|
|
14
|
+
* The daemon ACKs the COMMAND before the script runs, so the cloud gets
|
|
15
|
+
* confirmation. After restart the daemon reconnects with the new version.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Spawn a detached upgrade script that will:
|
|
19
|
+
* 1. Wait briefly for the daemon to finish sending its ACK
|
|
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
|
|
25
|
+
*/
|
|
26
|
+
async function spawnUpgradeScript(version) {
|
|
27
|
+
const scriptPath = `/tmp/alfe-upgrade-${String(Date.now())}.sh`;
|
|
28
|
+
await writeFile(scriptPath, `#!/bin/bash
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
|
|
31
|
+
# Wait for daemon to finish sending COMMAND_ACK
|
|
32
|
+
sleep 2
|
|
33
|
+
|
|
34
|
+
# Stop the gateway service
|
|
35
|
+
systemctl stop alfe-gateway
|
|
36
|
+
|
|
37
|
+
# Upgrade CLI to target version
|
|
38
|
+
npm install -g @alfe.ai/cli@${version}
|
|
39
|
+
|
|
40
|
+
# Re-run setup to regenerate systemd unit with new binary path
|
|
41
|
+
alfe setup --managed
|
|
42
|
+
|
|
43
|
+
# Start the service — daemon will reconnect with new version
|
|
44
|
+
systemctl start alfe-gateway
|
|
45
|
+
|
|
46
|
+
# Clean up
|
|
47
|
+
rm -f "$0"
|
|
48
|
+
`, "utf-8");
|
|
49
|
+
await chmod(scriptPath, 493);
|
|
50
|
+
const child = spawn("bash", [scriptPath], {
|
|
51
|
+
detached: true,
|
|
52
|
+
stdio: "ignore"
|
|
53
|
+
});
|
|
54
|
+
child.unref();
|
|
55
|
+
logger.info({
|
|
56
|
+
scriptPath,
|
|
57
|
+
version,
|
|
58
|
+
pid: child.pid
|
|
59
|
+
}, "Spawned detached upgrade script");
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
export { spawnUpgradeScript };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/gateway",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Alfe local gateway daemon — persistent control plane for agent integrations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -25,12 +25,12 @@
|
|
|
25
25
|
"@alfe.ai/ai-proxy-local": "^0.0.2",
|
|
26
26
|
"@alfe.ai/config": "^0.0.2",
|
|
27
27
|
"@alfe.ai/doctor": "^0.0.2",
|
|
28
|
-
"@alfe.ai/integrations": "^0.0.
|
|
28
|
+
"@alfe.ai/integrations": "^0.0.3"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/ws": "^8.5.13",
|
|
32
32
|
"tsx": "^4.19.0",
|
|
33
|
-
"@alfe/api-client": "0.1.
|
|
33
|
+
"@alfe/api-client": "0.1.1",
|
|
34
34
|
"@alfe/ids": "0.1.0"
|
|
35
35
|
},
|
|
36
36
|
"license": "UNLICENSED",
|