@alfe.ai/gateway 0.0.39 → 0.0.40

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 CHANGED
@@ -87,6 +87,7 @@ const ID_PREFIXES = {
87
87
  identityNote: "ino",
88
88
  identityTag: "itg",
89
89
  identityAlias: "ial",
90
+ identityVerification: "ivf",
90
91
  attachment: "att",
91
92
  run: "run",
92
93
  request: "req",
@@ -521,8 +522,15 @@ var IntegrationsService = class {
521
522
  getMobileNumber(agentId) {
522
523
  return this.client.request(`/mobile/numbers?agentId=${encodeURIComponent(agentId)}`);
523
524
  }
524
- disconnectGoogle(agentId) {
525
- return this.client.request(`/google/agents/${encodeURIComponent(agentId)}/account`, { method: "DELETE" });
525
+ disconnectGoogle(agentId, email) {
526
+ const query = email ? `?email=${encodeURIComponent(email)}` : "";
527
+ return this.client.request(`/google/agents/${encodeURIComponent(agentId)}/account${query}`, { method: "DELETE" });
528
+ }
529
+ setDefaultGoogleAccount(agentId, email) {
530
+ return this.client.request(`/google/agents/${encodeURIComponent(agentId)}/account/default`, {
531
+ method: "PUT",
532
+ body: JSON.stringify({ email })
533
+ });
526
534
  }
527
535
  getAtlassianSites(agentId) {
528
536
  return this.client.request(`/atlassian/agents/${encodeURIComponent(agentId)}/sites`);
@@ -3288,7 +3296,6 @@ enumValues({
3288
3296
  });
3289
3297
  enumValues({
3290
3298
  Public: "public",
3291
- Dev: "dev",
3292
3299
  Hidden: "hidden"
3293
3300
  });
3294
3301
  enumValues({
@@ -3875,7 +3882,7 @@ function createServiceRegister(agentId, capabilities = [
3875
3882
  "integrations",
3876
3883
  "lifecycle",
3877
3884
  "health"
3878
- ], cliVersion) {
3885
+ ], cliVersion, runtimeVersion) {
3879
3886
  const msg = {
3880
3887
  type: "SERVICE_REGISTER",
3881
3888
  serviceId: `gateway-daemon-${agentId}`,
@@ -3883,6 +3890,7 @@ function createServiceRegister(agentId, capabilities = [
3883
3890
  capabilities
3884
3891
  };
3885
3892
  if (cliVersion) msg.cliVersion = cliVersion;
3893
+ if (runtimeVersion) msg.runtimeVersion = runtimeVersion;
3886
3894
  return msg;
3887
3895
  }
3888
3896
  /**
@@ -4279,6 +4287,14 @@ var CloudClient = class {
4279
4287
  if (this.lastPong === 0) return -1;
4280
4288
  return Date.now() - this.lastPong;
4281
4289
  }
4290
+ /**
4291
+ * Update the runtime version and re-send SERVICE_REGISTER.
4292
+ * Used after a runtime upgrade to immediately persist the new version.
4293
+ */
4294
+ updateRuntimeVersionAndReRegister(runtimeVersion) {
4295
+ this.config.runtimeVersion = runtimeVersion;
4296
+ if (this.ws?.readyState === WebSocket.OPEN) this.sendRegister();
4297
+ }
4282
4298
  doConnect() {
4283
4299
  if (this.closed) {
4284
4300
  logger$1.debug("Cloud: doConnect skipped — client is closed");
@@ -4330,11 +4346,12 @@ var CloudClient = class {
4330
4346
  });
4331
4347
  }
4332
4348
  sendRegister() {
4333
- const msg = createServiceRegister(this.config.agentId, void 0, this.config.cliVersion);
4349
+ const msg = createServiceRegister(this.config.agentId, void 0, this.config.cliVersion, this.config.runtimeVersion);
4334
4350
  logger$1.debug({
4335
4351
  serviceId: msg.serviceId,
4336
4352
  agentIds: msg.agentIds,
4337
- cliVersion: msg.cliVersion
4353
+ cliVersion: msg.cliVersion,
4354
+ runtimeVersion: msg.runtimeVersion
4338
4355
  }, "Cloud: sending SERVICE_REGISTER");
4339
4356
  this.send(msg);
4340
4357
  logger$1.info({ serviceId: msg.serviceId }, "Sent SERVICE_REGISTER");
@@ -20477,6 +20494,8 @@ let cloudConnected = false;
20477
20494
  let shuttingDown = false;
20478
20495
  let commandRegistry;
20479
20496
  let resolvedCliVersion;
20497
+ let resolvedRuntimeVersion;
20498
+ let upgradingRuntime = false;
20480
20499
  /**
20481
20500
  * Resolve the installed @alfe.ai/cli version.
20482
20501
  *
@@ -20507,6 +20526,19 @@ async function getCliVersion() {
20507
20526
  logger$1.debug("Could not resolve @alfe.ai/cli version");
20508
20527
  }
20509
20528
  /**
20529
+ * Resolve the installed runtime (OpenClaw) version.
20530
+ * Runs `openclaw --version` and returns the trimmed output.
20531
+ */
20532
+ async function getRuntimeVersion() {
20533
+ try {
20534
+ const { stdout } = await execFileAsync("openclaw", ["--version"]);
20535
+ return stdout.trim() || void 0;
20536
+ } catch {
20537
+ logger$1.debug("Could not resolve openclaw runtime version");
20538
+ return;
20539
+ }
20540
+ }
20541
+ /**
20510
20542
  * Flush pino's async transport and exit.
20511
20543
  * process.exit() can drop buffered log lines — this ensures they're written first.
20512
20544
  */
@@ -20601,7 +20633,11 @@ async function startDaemon() {
20601
20633
  await flushAndExit(1);
20602
20634
  }
20603
20635
  resolvedCliVersion = await getCliVersion();
20604
- logger$1.info({ cliVersion: resolvedCliVersion }, "Resolved CLI version");
20636
+ resolvedRuntimeVersion = await getRuntimeVersion();
20637
+ logger$1.info({
20638
+ cliVersion: resolvedCliVersion,
20639
+ runtimeVersion: resolvedRuntimeVersion
20640
+ }, "Resolved versions");
20605
20641
  logger$1.debug({
20606
20642
  wsUrl: config.gatewayWsUrl,
20607
20643
  agentId: config.agentId
@@ -20610,7 +20646,8 @@ async function startDaemon() {
20610
20646
  wsUrl: config.gatewayWsUrl,
20611
20647
  apiKey: config.apiKey,
20612
20648
  agentId: config.agentId,
20613
- cliVersion: resolvedCliVersion
20649
+ cliVersion: resolvedCliVersion,
20650
+ runtimeVersion: resolvedRuntimeVersion
20614
20651
  });
20615
20652
  cloudClient.setCommandHandler(handleCloudCommand);
20616
20653
  cloudClient.setConnectionChangeHandler((connected) => {
@@ -20748,6 +20785,45 @@ async function handleCloudCommand(command) {
20748
20785
  }
20749
20786
  };
20750
20787
  }
20788
+ if (command.command === "runtime.update") {
20789
+ if (upgradingRuntime) return {
20790
+ type: "COMMAND_ACK",
20791
+ commandId: command.commandId,
20792
+ status: "error",
20793
+ result: {
20794
+ code: "ALREADY_UPGRADING",
20795
+ message: "Runtime upgrade already in progress"
20796
+ }
20797
+ };
20798
+ const version = command.payload?.version ?? "latest";
20799
+ upgradingRuntime = true;
20800
+ setTimeout(() => {
20801
+ (async () => {
20802
+ try {
20803
+ const { upgradeRuntime } = await import("./runtime-upgrade.js");
20804
+ if ((await upgradeRuntime(version, runtimeProcess)).success) {
20805
+ resolvedRuntimeVersion = await getRuntimeVersion();
20806
+ if (!resolvedRuntimeVersion) logger$1.warn({ requestedVersion: version }, "Could not detect runtime version after upgrade — using requested version");
20807
+ logger$1.info({ runtimeVersion: resolvedRuntimeVersion ?? version }, "Runtime version updated after upgrade");
20808
+ cloudClient.updateRuntimeVersionAndReRegister(resolvedRuntimeVersion ?? version);
20809
+ }
20810
+ } catch (err) {
20811
+ logger$1.error({ err: err instanceof Error ? err.message : String(err) }, "Runtime upgrade failed");
20812
+ } finally {
20813
+ upgradingRuntime = false;
20814
+ }
20815
+ })();
20816
+ }, 100);
20817
+ return {
20818
+ type: "COMMAND_ACK",
20819
+ commandId: command.commandId,
20820
+ status: "ok",
20821
+ result: {
20822
+ upgrading: true,
20823
+ version
20824
+ }
20825
+ };
20826
+ }
20751
20827
  if (command.command === "integration.status") {
20752
20828
  const payload = command.payload;
20753
20829
  try {
@@ -20966,7 +21042,8 @@ function handleStatus() {
20966
21042
  status: "running",
20967
21043
  pid: process.pid,
20968
21044
  uptime: (Date.now() - startedAt) / 1e3,
20969
- version: "0.1.0"
21045
+ version: "0.1.0",
21046
+ runtimeVersion: resolvedRuntimeVersion
20970
21047
  },
20971
21048
  cloud: {
20972
21049
  status: cloudConnected ? "connected" : "disconnected",
@@ -21075,6 +21152,7 @@ function formatHealthReport(health) {
21075
21152
  const lines = [];
21076
21153
  const daemonIcon = health.daemon.status === "running" ? "✓" : "✗";
21077
21154
  lines.push(` Gateway daemon ${daemonIcon} ${health.daemon.status}` + (health.daemon.uptime ? ` (uptime: ${formatUptime(health.daemon.uptime)})` : "") + (health.daemon.version ? ` v${health.daemon.version}` : ""));
21155
+ if (health.daemon.runtimeVersion) lines.push(` Runtime version ✓ v${health.daemon.runtimeVersion}`);
21078
21156
  const cloudIcon = health.cloud.status === "connected" ? "✓" : "✗";
21079
21157
  lines.push(` Cloud connection ${cloudIcon} ${health.cloud.status}` + (health.cloud.latencyMs !== void 0 ? ` (latency: ${String(health.cloud.latencyMs)}ms)` : ""));
21080
21158
  const proxyIcon = health.aiProxy.status === "running" ? "✓" : "✗";
@@ -0,0 +1,63 @@
1
+ import { n as logger } from "./logger.js";
2
+ import { execFile } from "node:child_process";
3
+ import { promisify } from "node:util";
4
+ //#region src/runtime-upgrade.ts
5
+ /**
6
+ * Runtime upgrade — npm install then cycle the RuntimeProcess.
7
+ *
8
+ * Unlike CLI upgrade (which exits the daemon for systemd restart),
9
+ * runtime upgrade keeps the daemon running and just restarts the child process.
10
+ *
11
+ * Flow:
12
+ * 1. Stop the RuntimeProcess child (SIGTERM + grace period)
13
+ * 2. npm install -g openclaw@{version}
14
+ * 3. Restart the RuntimeProcess child
15
+ *
16
+ * On npm failure, the runtime is restarted on the old version.
17
+ */
18
+ const execFileAsync = promisify(execFile);
19
+ async function upgradeRuntime(version, runtimeProcess) {
20
+ logger.info({ version }, "Upgrading OpenClaw runtime...");
21
+ if (runtimeProcess) {
22
+ logger.info("Stopping runtime for upgrade...");
23
+ await runtimeProcess.stop();
24
+ }
25
+ try {
26
+ const { stdout, stderr } = await execFileAsync("npm", [
27
+ "install",
28
+ "-g",
29
+ `openclaw@${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 }, "OpenClaw runtime upgraded successfully");
34
+ } catch (err) {
35
+ const message = err instanceof Error ? err.message : String(err);
36
+ logger.error({
37
+ err: message,
38
+ version
39
+ }, "Runtime upgrade npm install failed");
40
+ if (runtimeProcess) try {
41
+ logger.info("Restarting runtime on previous version after failed upgrade...");
42
+ await runtimeProcess.restart();
43
+ } catch (restartErr) {
44
+ const restartMsg = restartErr instanceof Error ? restartErr.message : String(restartErr);
45
+ logger.error({ err: restartMsg }, "Failed to restart runtime after failed upgrade");
46
+ }
47
+ return {
48
+ success: false,
49
+ version,
50
+ error: message
51
+ };
52
+ }
53
+ if (runtimeProcess) {
54
+ logger.info("Restarting runtime after upgrade...");
55
+ await runtimeProcess.restart();
56
+ }
57
+ return {
58
+ success: true,
59
+ version
60
+ };
61
+ }
62
+ //#endregion
63
+ export { upgradeRuntime };
@@ -111,6 +111,7 @@ interface DaemonHealth {
111
111
  pid?: number;
112
112
  uptime?: number;
113
113
  version?: string;
114
+ runtimeVersion?: string;
114
115
  };
115
116
  cloud: {
116
117
  status: 'connected' | 'disconnected' | 'unknown';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/gateway",
3
- "version": "0.0.39",
3
+ "version": "0.0.40",
4
4
  "description": "Alfe local gateway daemon — persistent control plane for agent integrations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "@alfe.ai/ai-proxy-local": "^0.0.7",
26
26
  "@alfe.ai/config": "^0.0.7",
27
27
  "@alfe.ai/integration-manifest": "^0.0.9",
28
- "@alfe.ai/integrations": "^0.0.25"
28
+ "@alfe.ai/integrations": "^0.0.26"
29
29
  },
30
30
  "license": "UNLICENSED",
31
31
  "scripts": {