@alfe.ai/gateway 0.2.2 → 0.2.4

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.
Files changed (2) hide show
  1. package/dist/health.js +15 -6
  2. package/package.json +4 -4
package/dist/health.js CHANGED
@@ -12,7 +12,7 @@ import crypto from "crypto";
12
12
  import { parse } from "smol-toml";
13
13
  import WebSocket from "ws";
14
14
  import { createConnection, createServer } from "node:net";
15
- import { HermesApplier, HermesMcpSync, IntegrationManager, IntegrationManagerAdapter, McpApplier, OpenClawApplier } from "@alfe.ai/integrations";
15
+ import { HermesApplier, HermesMcpSync, IntegrationManager, IntegrationManagerAdapter, McpApplier, NoopOpenClawCliLock, OpenClawApplier, SerialOpenClawCliLock } from "@alfe.ai/integrations";
16
16
  import { AgentApiClient } from "@alfe.ai/agent-api-client";
17
17
  import { Manager, McpBundler, defaultConnect } from "@alfe.ai/mcp-bundler";
18
18
  import stream, { Readable } from "stream";
@@ -22194,13 +22194,15 @@ async function approvePendingScopeUpgrades(opts) {
22194
22194
  function startPairingApprovalPoller(opts) {
22195
22195
  const stateDir = resolveStateDir(opts.stateDir);
22196
22196
  const intervalMs = opts.intervalMs ?? 3e4;
22197
- const exec = opts.exec ?? (async (file, args, { timeout }) => {
22197
+ const cliLock = opts.cliLock ?? new NoopOpenClawCliLock();
22198
+ const rawExec = opts.exec ?? (async (file, args, { timeout }) => {
22198
22199
  const { stdout, stderr } = await execFileAsync$2(file, args, { timeout });
22199
22200
  return {
22200
22201
  stdout,
22201
22202
  stderr
22202
22203
  };
22203
22204
  });
22205
+ const exec = (file, args, execOpts) => cliLock.run(() => rawExec(file, args, execOpts));
22204
22206
  const pendingPath = join(stateDir, "devices", "pending.json");
22205
22207
  let lastSeenMtime = null;
22206
22208
  let stopped = false;
@@ -22305,6 +22307,7 @@ const defaultOpenclaw = {
22305
22307
  async function runOpenclawMcpCleanup(opts) {
22306
22308
  const sentinelPath = opts.sentinelPath ?? DEFAULT_SENTINEL_PATH;
22307
22309
  const openclaw = opts.openclaw ?? defaultOpenclaw;
22310
+ const cliLock = opts.cliLock ?? new NoopOpenClawCliLock();
22308
22311
  if (existsSync(sentinelPath)) {
22309
22312
  opts.logger.debug({ sentinel: sentinelPath }, "openclaw.json mcp.servers cleanup already ran — skipping");
22310
22313
  return;
@@ -22335,7 +22338,7 @@ async function runOpenclawMcpCleanup(opts) {
22335
22338
  return;
22336
22339
  }
22337
22340
  for (const key of toUnset) try {
22338
- await openclaw.unsetServer(key);
22341
+ await cliLock.run(() => openclaw.unsetServer(key));
22339
22342
  opts.logger.info({ key }, "Cleaned up stale openclaw.json#mcp.servers entry");
22340
22343
  } catch (err) {
22341
22344
  opts.logger.warn({
@@ -22688,11 +22691,13 @@ async function startDaemon() {
22688
22691
  logger$1.info({ connected }, "Cloud connection state changed");
22689
22692
  ipcServer?.broadcastEvent("cloud.status", { connected });
22690
22693
  });
22694
+ const openclawCliLock = new SerialOpenClawCliLock();
22691
22695
  const runtimeAppliers = /* @__PURE__ */ new Map();
22692
22696
  for (const [name, runtimeCfg] of Object.entries(config.runtimes)) if (name === "openclaw") {
22693
22697
  runtimeAppliers.set(name, new OpenClawApplier({
22694
22698
  home: runtimeCfg.workspace,
22695
- agentWorkspace: runtimeCfg.agentWorkspace
22699
+ agentWorkspace: runtimeCfg.agentWorkspace,
22700
+ cliLock: openclawCliLock
22696
22701
  }));
22697
22702
  logger$1.info({
22698
22703
  runtime: name,
@@ -22741,7 +22746,8 @@ async function startDaemon() {
22741
22746
  }
22742
22747
  if (config.runtime === "openclaw") await runOpenclawMcpCleanup({
22743
22748
  manager: mcpManager,
22744
- logger: logger$1
22749
+ logger: logger$1,
22750
+ cliLock: openclawCliLock
22745
22751
  }).catch((err) => {
22746
22752
  logger$1.warn({ err: err instanceof Error ? err.message : String(err) }, "openclaw.json mcp.servers cleanup threw — startup continues");
22747
22753
  });
@@ -22813,7 +22819,10 @@ async function startDaemon() {
22813
22819
  runtimeProcess.start();
22814
22820
  logger$1.debug("Runtime process started");
22815
22821
  if (config.runtime === "openclaw") {
22816
- stopPairingApprovalPoller = startPairingApprovalPoller({ log: logger$1 });
22822
+ stopPairingApprovalPoller = startPairingApprovalPoller({
22823
+ log: logger$1,
22824
+ cliLock: openclawCliLock
22825
+ });
22817
22826
  logger$1.debug("Pairing approval poller started");
22818
22827
  }
22819
22828
  } else logger$1.warn({ runtime: config.runtime }, "No runtime config found — skipping runtime start");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/gateway",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Alfe local gateway daemon — persistent control plane for agent integrations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,10 +23,10 @@
23
23
  "smol-toml": ">=1.6.1",
24
24
  "ws": "^8.18.0",
25
25
  "@alfe.ai/agent-api-client": "^0.4.0",
26
- "@alfe.ai/ai-proxy-local": "^0.0.12",
27
- "@alfe.ai/config": "^0.2.0",
26
+ "@alfe.ai/ai-proxy-local": "^0.0.13",
27
+ "@alfe.ai/config": "^0.3.0",
28
28
  "@alfe.ai/integration-manifest": "^0.3.1",
29
- "@alfe.ai/integrations": "^0.2.5",
29
+ "@alfe.ai/integrations": "^0.2.6",
30
30
  "@alfe.ai/mcp-bundler": "^0.2.2"
31
31
  },
32
32
  "license": "UNLICENSED",