@alfe.ai/gateway 0.0.12 → 0.0.13

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
@@ -3873,6 +3873,7 @@ var CloudClient = class {
3873
3873
  onCommand = null;
3874
3874
  onConnectionChange = null;
3875
3875
  onServiceRelay = null;
3876
+ onPluginsChanged = null;
3876
3877
  reconciliationEngine = null;
3877
3878
  constructor(config) {
3878
3879
  this.config = config;
@@ -3910,6 +3911,12 @@ var CloudClient = class {
3910
3911
  * Set the integration manager for reconciliation.
3911
3912
  * When set, the cloud client will handle DESIRED_STATE messages automatically.
3912
3913
  */
3914
+ /**
3915
+ * Set a callback for when plugins change (install/uninstall) — used to restart the runtime.
3916
+ */
3917
+ setPluginsChangedHandler(handler) {
3918
+ this.onPluginsChanged = handler;
3919
+ }
3913
3920
  setIntegrationManager(manager) {
3914
3921
  this.reconciliationEngine = new ReconciliationEngine(manager);
3915
3922
  }
@@ -4106,6 +4113,7 @@ var CloudClient = class {
4106
4113
  }, "Cloud: reconciliation complete");
4107
4114
  const reportMsg = createReconciliationReport(report.results);
4108
4115
  this.send(reportMsg);
4116
+ if ((report.installed.length > 0 || report.uninstalled.length > 0) && this.onPluginsChanged) this.onPluginsChanged();
4109
4117
  } catch (err) {
4110
4118
  const message = err instanceof Error ? err.message : String(err);
4111
4119
  logger$1.error({ err: message }, "Cloud: reconciliation failed");
@@ -4594,22 +4602,13 @@ function getSystemdServicePath() {
4594
4602
  return join(homedir(), ".config", "systemd", "user", `${SYSTEMD_SERVICE}.service`);
4595
4603
  }
4596
4604
  /**
4597
- * Resolve the path to the gateway binary.
4605
+ * Resolve the alfe CLI path. Globally installed via npm, always in PATH.
4598
4606
  */
4599
- function getGatewayBinPath() {
4600
- const globalBin = process.env.ALFE_GATEWAY_BIN;
4601
- if (globalBin) return globalBin;
4602
- for (const rel of ["../bin/gateway.js", "bin/gateway.js"]) {
4603
- const candidate = join(import.meta.dirname, rel);
4604
- if (existsSync(candidate)) return candidate;
4605
- }
4606
- return "alfe-gateway";
4607
- }
4608
- function getNodePath() {
4607
+ function getAlfeBinPath() {
4609
4608
  try {
4610
- return execSync("which node", { encoding: "utf-8" }).trim();
4609
+ return execSync("which alfe", { encoding: "utf-8" }).trim();
4611
4610
  } catch {
4612
- return "/usr/local/bin/node";
4611
+ return "alfe";
4613
4612
  }
4614
4613
  }
4615
4614
  /**
@@ -4624,8 +4623,8 @@ function generateLaunchdPlist() {
4624
4623
  <string>${LAUNCHD_LABEL}</string>
4625
4624
  <key>ProgramArguments</key>
4626
4625
  <array>
4627
- <string>${getNodePath()}</string>
4628
- <string>${getGatewayBinPath()}</string>
4626
+ <string>${getAlfeBinPath()}</string>
4627
+ <string>gateway</string>
4629
4628
  <string>daemon</string>
4630
4629
  </array>
4631
4630
  <key>RunAtLoad</key>
@@ -4653,8 +4652,7 @@ function generateLaunchdPlist() {
4653
4652
  * Root users get a system-level unit; non-root get a user-level unit.
4654
4653
  */
4655
4654
  function generateSystemdUnit() {
4656
- const nodePath = getNodePath();
4657
- const gatewayBin = getGatewayBinPath();
4655
+ const alfeBin = getAlfeBinPath();
4658
4656
  const root = isRootUser();
4659
4657
  const envLines = [
4660
4658
  "ALFE_MANAGED",
@@ -4668,7 +4666,7 @@ Wants=network-online.target
4668
4666
 
4669
4667
  [Service]
4670
4668
  Type=simple
4671
- ExecStart=${nodePath} ${gatewayBin} daemon
4669
+ ExecStart=${alfeBin} gateway daemon
4672
4670
  Restart=always
4673
4671
  RestartSec=10
4674
4672
  Environment=NODE_ENV=production${root ? "\nEnvironment=HOME=/root\nWorkingDirectory=/root" : ""}
@@ -19902,6 +19900,16 @@ var RuntimeProcess = class {
19902
19900
  });
19903
19901
  }
19904
19902
  /**
19903
+ * Restart the runtime process (stop then start with fresh backoff).
19904
+ */
19905
+ async restart() {
19906
+ log$1.info({ runtime: this.options.runtime }, "Restarting runtime...");
19907
+ await this.stop();
19908
+ this.stopped = false;
19909
+ this.backoffMs = BACKOFF_INITIAL_MS;
19910
+ this.start();
19911
+ }
19912
+ /**
19905
19913
  * Whether the runtime process is currently running.
19906
19914
  */
19907
19915
  get isRunning() {
@@ -20187,18 +20195,19 @@ async function startDaemon() {
20187
20195
  const { createProxyServer, DEFAULT_AI_PROXY_PORT } = await import("@alfe.ai/ai-proxy-local");
20188
20196
  const { getAiServiceUrlFromToken } = await import("@alfe.ai/config");
20189
20197
  const proxyUrl = getAiServiceUrlFromToken(config.apiKey);
20198
+ const port = DEFAULT_AI_PROXY_PORT ?? 18193;
20190
20199
  aiProxyServer = createProxyServer({
20191
- port: DEFAULT_AI_PROXY_PORT,
20200
+ port,
20192
20201
  apiKey: config.apiKey,
20193
20202
  proxyUrl
20194
20203
  });
20195
20204
  const server = aiProxyServer;
20196
20205
  await new Promise((resolve, reject) => {
20197
- server.listen(DEFAULT_AI_PROXY_PORT, "127.0.0.1", () => {
20206
+ server.listen(port, "127.0.0.1", () => {
20198
20207
  aiProxyRunning = true;
20199
- aiProxyUrl = `http://127.0.0.1:${String(DEFAULT_AI_PROXY_PORT)}`;
20208
+ aiProxyUrl = `http://127.0.0.1:${String(port)}`;
20200
20209
  logger$1.info({
20201
- port: DEFAULT_AI_PROXY_PORT,
20210
+ port,
20202
20211
  upstream: proxyUrl
20203
20212
  }, "AI proxy started");
20204
20213
  resolve();
@@ -20268,6 +20277,14 @@ async function startDaemon() {
20268
20277
  });
20269
20278
  const integrationAdapter = new IntegrationManagerAdapter(integrationManager);
20270
20279
  cloudClient.setIntegrationManager(integrationAdapter);
20280
+ cloudClient.setPluginsChangedHandler(() => {
20281
+ if (runtimeProcess) {
20282
+ logger$1.info("Plugins changed — restarting runtime to load new plugins");
20283
+ runtimeProcess.restart().catch((err) => {
20284
+ logger$1.error({ err: err instanceof Error ? err.message : String(err) }, "Failed to restart runtime");
20285
+ });
20286
+ }
20287
+ });
20271
20288
  cloudClient.start();
20272
20289
  logger$1.debug("Cloud client started");
20273
20290
  if (config.autoStartRuntime && config.runtime) {
package/dist/upgrade.js CHANGED
@@ -27,6 +27,7 @@ async function spawnUpgradeScript(version) {
27
27
  const scriptPath = `/tmp/alfe-upgrade-${String(Date.now())}.sh`;
28
28
  await writeFile(scriptPath, `#!/bin/bash
29
29
  set -euo pipefail
30
+ exec > /tmp/alfe-upgrade.log 2>&1
30
31
 
31
32
  # Wait for daemon to finish sending COMMAND_ACK
32
33
  sleep 2
@@ -37,10 +38,7 @@ systemctl stop alfe-gateway
37
38
  # Upgrade CLI to target version
38
39
  npm install -g @alfe.ai/cli@${version}
39
40
 
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
41
+ # Restart systemd ExecStart resolves the new binary automatically
44
42
  systemctl start alfe-gateway
45
43
 
46
44
  # Clean up
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/gateway",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
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.2",
26
- "@alfe.ai/config": "^0.0.2",
27
- "@alfe.ai/doctor": "^0.0.2",
28
- "@alfe.ai/integrations": "^0.0.5"
25
+ "@alfe.ai/ai-proxy-local": "^0.0.3",
26
+ "@alfe.ai/config": "^0.0.3",
27
+ "@alfe.ai/doctor": "^0.0.3",
28
+ "@alfe.ai/integrations": "^0.0.6"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/ws": "^8.5.13",