@alfe.ai/gateway 0.4.0 → 0.5.0
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 +1 -1
- package/dist/health.js +228 -81
- package/dist/src/index.d.ts +23 -1
- package/dist/src/index.js +2 -2
- package/package.json +4 -4
package/dist/bin/gateway.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { a as installService, c as uninstallService, i as checkExistingDaemon, n as queryDaemonHealth, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport, w as SOCKET_PATH } from "../health.js";
|
|
3
3
|
import { t as LOG_FILE } from "../logger.js";
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
//#region bin/gateway.ts
|
package/dist/health.js
CHANGED
|
@@ -5266,7 +5266,7 @@ function isIPCResponse(msg) {
|
|
|
5266
5266
|
const PROTOCOL_VERSION = 1;
|
|
5267
5267
|
//#endregion
|
|
5268
5268
|
//#region src/runtime-gate.ts
|
|
5269
|
-
const log$
|
|
5269
|
+
const log$4 = logger$1.child({ component: "RuntimeGate" });
|
|
5270
5270
|
var RuntimeGate = class {
|
|
5271
5271
|
depth = 0;
|
|
5272
5272
|
wasRunning = false;
|
|
@@ -5284,7 +5284,7 @@ var RuntimeGate = class {
|
|
|
5284
5284
|
const rp = this.getRuntime();
|
|
5285
5285
|
this.wasRunning = rp?.isRunning ?? false;
|
|
5286
5286
|
if (rp && this.wasRunning) {
|
|
5287
|
-
log$
|
|
5287
|
+
log$4.info("Suspending runtime for mutating reconcile (avoid concurrent SQLite writers)");
|
|
5288
5288
|
await rp.stop();
|
|
5289
5289
|
}
|
|
5290
5290
|
}
|
|
@@ -5299,7 +5299,7 @@ var RuntimeGate = class {
|
|
|
5299
5299
|
if (this.depth < 0) this.depth = 0;
|
|
5300
5300
|
const rp = this.getRuntime();
|
|
5301
5301
|
if (rp && this.wasRunning) {
|
|
5302
|
-
log$
|
|
5302
|
+
log$4.info("Resuming runtime after mutating reconcile");
|
|
5303
5303
|
rp.resume();
|
|
5304
5304
|
}
|
|
5305
5305
|
this.wasRunning = false;
|
|
@@ -5314,12 +5314,12 @@ var RuntimeGate = class {
|
|
|
5314
5314
|
*/
|
|
5315
5315
|
requestRestart() {
|
|
5316
5316
|
if (this.depth > 0) {
|
|
5317
|
-
log$
|
|
5317
|
+
log$4.info("Runtime restart requested while suspended — deferring to pending resume");
|
|
5318
5318
|
return;
|
|
5319
5319
|
}
|
|
5320
5320
|
const rp = this.getRuntime();
|
|
5321
5321
|
if (rp) rp.restart().catch((err) => {
|
|
5322
|
-
log$
|
|
5322
|
+
log$4.error({ err: err instanceof Error ? err.message : String(err) }, "Failed to restart runtime");
|
|
5323
5323
|
});
|
|
5324
5324
|
}
|
|
5325
5325
|
};
|
|
@@ -5374,6 +5374,13 @@ const CLI_SENTRY_DSN = "https://82dde4631336561f2fcc89d7531623de@o45110082394521
|
|
|
5374
5374
|
* Mirrors `SENTRY_DSNS.agentRuntime` in `config/config.ts`.
|
|
5375
5375
|
*/
|
|
5376
5376
|
const AGENT_RUNTIME_SENTRY_DSN = "https://feb7fb2e3b8e723aec518e74715bfa6d@o4511008239452160.ingest.us.sentry.io/4511683667558400";
|
|
5377
|
+
/**
|
|
5378
|
+
* MCP tool/server failures on agent VMs — reported by the daemon-hosted MCP
|
|
5379
|
+
* bundler (tool errors, child crashes, stderr output). This is the SAME
|
|
5380
|
+
* project as the cloud MCP Fly service (`SENTRY_DSNS.mcp`); agent-side events
|
|
5381
|
+
* are distinguished by `source: agent-daemon` + `agentId` tags.
|
|
5382
|
+
*/
|
|
5383
|
+
const AGENT_MCP_SENTRY_DSN = "https://638309eac96146a945f46b578f10c806@o4511008239452160.ingest.us.sentry.io/4511146364174336";
|
|
5377
5384
|
/** Surface → Sentry project: `cli` and `agent-daemon` respectively. */
|
|
5378
5385
|
const SURFACE_DSNS = {
|
|
5379
5386
|
cli: CLI_SENTRY_DSN,
|
|
@@ -5382,13 +5389,16 @@ const SURFACE_DSNS = {
|
|
|
5382
5389
|
/** Held after a successful init so the capture helpers can run synchronously. */
|
|
5383
5390
|
let sentry = null;
|
|
5384
5391
|
/**
|
|
5385
|
-
*
|
|
5386
|
-
*
|
|
5387
|
-
*
|
|
5388
|
-
* pattern. `null` until `initAgentSentry({ surface: "daemon" })`
|
|
5392
|
+
* Additional bound clients (daemon surface only). The default client keeps the
|
|
5393
|
+
* daemon's own DSN; runtime child-process events and MCP failures are routed
|
|
5394
|
+
* to their own projects via explicitly-bound Scopes — the documented
|
|
5395
|
+
* multi-client pattern. `null` until `initAgentSentry({ surface: "daemon" })`
|
|
5396
|
+
* succeeds.
|
|
5389
5397
|
*/
|
|
5390
5398
|
let runtimeClient = null;
|
|
5391
5399
|
let runtimeScope = null;
|
|
5400
|
+
let mcpClient = null;
|
|
5401
|
+
let mcpScope = null;
|
|
5392
5402
|
/**
|
|
5393
5403
|
* Map the configured API URL to a coarse environment tag. Best-effort — returns
|
|
5394
5404
|
* `"unknown"` when no config is present yet (e.g. `alfe login` pre-setup).
|
|
@@ -5470,32 +5480,46 @@ async function initAgentSentry(options) {
|
|
|
5470
5480
|
const dsn = SURFACE_DSNS[options.surface].trim();
|
|
5471
5481
|
if (!dsn) return;
|
|
5472
5482
|
const mod = await import("@sentry/node");
|
|
5473
|
-
if (options.surface === "daemon"
|
|
5474
|
-
const
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5483
|
+
if (options.surface === "daemon") {
|
|
5484
|
+
const buildBoundScope = (dsn, extraTags) => {
|
|
5485
|
+
try {
|
|
5486
|
+
if (!dsn.trim()) return null;
|
|
5487
|
+
const client = new mod.NodeClient({
|
|
5488
|
+
dsn: dsn.trim(),
|
|
5489
|
+
environment: deriveEnvironment(),
|
|
5490
|
+
...options.release ? { release: options.release } : {},
|
|
5491
|
+
sampleRate: 1,
|
|
5492
|
+
tracesSampleRate: 0,
|
|
5493
|
+
sendDefaultPii: false,
|
|
5494
|
+
transport: mod.makeNodeTransport,
|
|
5495
|
+
stackParser: mod.defaultStackParser,
|
|
5496
|
+
integrations: [],
|
|
5497
|
+
beforeSend: (event) => scrubEvent(event)
|
|
5498
|
+
});
|
|
5499
|
+
client.init();
|
|
5500
|
+
const scope = new mod.Scope();
|
|
5501
|
+
scope.setClient(client);
|
|
5502
|
+
const runtime = deriveRuntime();
|
|
5503
|
+
if (runtime) scope.setTag("runtime", runtime);
|
|
5504
|
+
for (const [k, v] of Object.entries(extraTags)) scope.setTag(k, v);
|
|
5505
|
+
return {
|
|
5506
|
+
client,
|
|
5507
|
+
scope
|
|
5508
|
+
};
|
|
5509
|
+
} catch {
|
|
5510
|
+
return null;
|
|
5511
|
+
}
|
|
5512
|
+
};
|
|
5513
|
+
if (!runtimeScope) {
|
|
5514
|
+
const bound = buildBoundScope(AGENT_RUNTIME_SENTRY_DSN, {});
|
|
5515
|
+
runtimeClient = bound?.client ?? null;
|
|
5516
|
+
runtimeScope = bound?.scope ?? null;
|
|
5517
|
+
}
|
|
5518
|
+
if (!mcpScope) {
|
|
5519
|
+
const bound = buildBoundScope(AGENT_MCP_SENTRY_DSN, { source: "agent-daemon" });
|
|
5520
|
+
mcpClient = bound?.client ?? null;
|
|
5521
|
+
mcpScope = bound?.scope ?? null;
|
|
5495
5522
|
}
|
|
5496
|
-
} catch {
|
|
5497
|
-
runtimeClient = null;
|
|
5498
|
-
runtimeScope = null;
|
|
5499
5523
|
}
|
|
5500
5524
|
if (mod.getClient()) {
|
|
5501
5525
|
sentry = mod;
|
|
@@ -5527,11 +5551,14 @@ async function initAgentSentry(options) {
|
|
|
5527
5551
|
function setAgentContext(context) {
|
|
5528
5552
|
if (!sentry) return;
|
|
5529
5553
|
try {
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5554
|
+
for (const scope of [
|
|
5555
|
+
sentry,
|
|
5556
|
+
runtimeScope,
|
|
5557
|
+
mcpScope
|
|
5558
|
+
]) {
|
|
5559
|
+
if (!scope) continue;
|
|
5560
|
+
if (context.agentId) scope.setTag("agentId", context.agentId);
|
|
5561
|
+
if (context.runtime) scope.setTag("runtime", context.runtime);
|
|
5535
5562
|
}
|
|
5536
5563
|
} catch {}
|
|
5537
5564
|
}
|
|
@@ -5641,10 +5668,40 @@ function captureRuntimeErrorOutput(opts) {
|
|
|
5641
5668
|
scope.captureMessage(opts.lines[0].slice(0, 300), "error");
|
|
5642
5669
|
} catch {}
|
|
5643
5670
|
}
|
|
5671
|
+
/**
|
|
5672
|
+
* Capture an MCP failure (tool error, server crash, or error-looking stderr
|
|
5673
|
+
* output) into the `mcp` project via the daemon's bound MCP client. Throttling
|
|
5674
|
+
* is the caller's job (`mcp-error-capture.ts`). No-op when the MCP client is
|
|
5675
|
+
* not initialised. Never throws.
|
|
5676
|
+
*/
|
|
5677
|
+
function captureMcpFailure(opts) {
|
|
5678
|
+
if (!mcpScope) return;
|
|
5679
|
+
try {
|
|
5680
|
+
const scope = mcpScope.clone();
|
|
5681
|
+
for (const line of opts.lines ?? []) scope.addBreadcrumb({
|
|
5682
|
+
category: `mcp.${opts.server}`,
|
|
5683
|
+
level: "error",
|
|
5684
|
+
message: line
|
|
5685
|
+
});
|
|
5686
|
+
scope.setFingerprint([
|
|
5687
|
+
"agent-mcp",
|
|
5688
|
+
opts.server,
|
|
5689
|
+
opts.kind,
|
|
5690
|
+
...opts.tool ? [opts.tool] : []
|
|
5691
|
+
]);
|
|
5692
|
+
scope.setTags({
|
|
5693
|
+
server: opts.server,
|
|
5694
|
+
kind: opts.kind,
|
|
5695
|
+
...opts.tool ? { tool: opts.tool } : {},
|
|
5696
|
+
suppressedCount: String(opts.suppressedCount ?? 0)
|
|
5697
|
+
});
|
|
5698
|
+
scope.captureMessage(`MCP ${opts.server}${opts.tool ? `.${opts.tool}` : ""} ${opts.kind}: ${opts.message.slice(0, 300)}`, "error");
|
|
5699
|
+
} catch {}
|
|
5700
|
+
}
|
|
5644
5701
|
/** Flush queued events (small timeout) so short-lived commands deliver them. */
|
|
5645
5702
|
async function flushSentry(timeoutMs = 2e3) {
|
|
5646
|
-
try {
|
|
5647
|
-
if (
|
|
5703
|
+
for (const client of [runtimeClient, mcpClient]) try {
|
|
5704
|
+
if (client) await client.flush(timeoutMs);
|
|
5648
5705
|
} catch {}
|
|
5649
5706
|
if (!sentry) return;
|
|
5650
5707
|
try {
|
|
@@ -5664,7 +5721,7 @@ function captureFatal(cause) {
|
|
|
5664
5721
|
}
|
|
5665
5722
|
//#endregion
|
|
5666
5723
|
//#region src/reconciliation.ts
|
|
5667
|
-
const log$
|
|
5724
|
+
const log$3 = logger$1.child({ component: "Reconciliation" });
|
|
5668
5725
|
/**
|
|
5669
5726
|
* How many times reconcile will re-attempt activation of an intact integration
|
|
5670
5727
|
* stuck in `error` (with no reinstall requested) before giving up and waiting
|
|
@@ -5734,7 +5791,7 @@ var ReconciliationEngine = class {
|
|
|
5734
5791
|
try {
|
|
5735
5792
|
localIntegrations = await this.manager.getInstalledIntegrations();
|
|
5736
5793
|
} catch (err) {
|
|
5737
|
-
log$
|
|
5794
|
+
log$3.error({ err }, "Failed to get local integrations");
|
|
5738
5795
|
localIntegrations = [];
|
|
5739
5796
|
}
|
|
5740
5797
|
const localMap = new Map(localIntegrations.map((i) => [i.id, i]));
|
|
@@ -5753,10 +5810,10 @@ var ReconciliationEngine = class {
|
|
|
5753
5810
|
try {
|
|
5754
5811
|
if (!local) {
|
|
5755
5812
|
await this.ensureSuspended();
|
|
5756
|
-
log$
|
|
5813
|
+
log$3.info(`Installing ${id}@${desired.version}`);
|
|
5757
5814
|
await this.manager.install(id, desired.version, desired.config, desired.customSource);
|
|
5758
5815
|
report.installed.push(id);
|
|
5759
|
-
log$
|
|
5816
|
+
log$3.info(`Activating ${id}`);
|
|
5760
5817
|
if ((await this.manager.activate(id)).configApplied) report.configApplied = true;
|
|
5761
5818
|
report.activated.push(id);
|
|
5762
5819
|
report.results.push({
|
|
@@ -5768,7 +5825,7 @@ var ReconciliationEngine = class {
|
|
|
5768
5825
|
}
|
|
5769
5826
|
if (local.version !== desired.version && desired.version !== "" && local.version !== "unknown") {
|
|
5770
5827
|
await this.ensureSuspended();
|
|
5771
|
-
log$
|
|
5828
|
+
log$3.info(`Upgrading ${id}: ${local.version} → ${desired.version}`);
|
|
5772
5829
|
if ((await this.manager.reinstall(id, desired.version, desired.config, desired.customSource)).configApplied) report.configApplied = true;
|
|
5773
5830
|
report.installed.push(id);
|
|
5774
5831
|
report.activated.push(id);
|
|
@@ -5782,7 +5839,7 @@ var ReconciliationEngine = class {
|
|
|
5782
5839
|
if (local.status === "error") {
|
|
5783
5840
|
if (desired.reinstallRequestedAt && local.installedAt && desired.reinstallRequestedAt > local.installedAt) {
|
|
5784
5841
|
await this.ensureSuspended();
|
|
5785
|
-
log$
|
|
5842
|
+
log$3.info(`Reinstalling ${id} from error state (requested: ${desired.reinstallRequestedAt}, installed: ${local.installedAt})`);
|
|
5786
5843
|
this.manager.resetReinstallAttempts(id);
|
|
5787
5844
|
this.activateAttempts.delete(id);
|
|
5788
5845
|
if ((await this.manager.reinstall(id, desired.version, desired.config, desired.customSource)).configApplied) report.configApplied = true;
|
|
@@ -5798,7 +5855,7 @@ var ReconciliationEngine = class {
|
|
|
5798
5855
|
if (!await this.manager.isInstallIntact(id)) {
|
|
5799
5856
|
const attempts = this.manager.getReinstallAttempts(id);
|
|
5800
5857
|
if (attempts >= 3) {
|
|
5801
|
-
log$
|
|
5858
|
+
log$3.error(`Auto-reinstall blocked for ${id} — ${String(attempts)} consecutive failures. Manual reinstall required.`);
|
|
5802
5859
|
captureIntegrationFailure(id, "reinstall", `Max auto-reinstall attempts (${String(attempts)}) reached — manual reinstall required`);
|
|
5803
5860
|
report.errors.push({
|
|
5804
5861
|
integrationId: id,
|
|
@@ -5813,7 +5870,7 @@ var ReconciliationEngine = class {
|
|
|
5813
5870
|
return;
|
|
5814
5871
|
}
|
|
5815
5872
|
await this.ensureSuspended();
|
|
5816
|
-
log$
|
|
5873
|
+
log$3.info(`Auto-reinstalling ${id} — install directory is corrupted or missing (attempt ${String(attempts + 1)}/3)`);
|
|
5817
5874
|
this.manager.incrementReinstallAttempts(id);
|
|
5818
5875
|
try {
|
|
5819
5876
|
if ((await this.manager.reinstall(id, desired.version, desired.config, desired.customSource)).configApplied) report.configApplied = true;
|
|
@@ -5828,7 +5885,7 @@ var ReconciliationEngine = class {
|
|
|
5828
5885
|
});
|
|
5829
5886
|
} catch (reinstallErr) {
|
|
5830
5887
|
const reinstallMsg = reinstallErr instanceof Error ? reinstallErr.message : String(reinstallErr);
|
|
5831
|
-
log$
|
|
5888
|
+
log$3.error({ err: reinstallErr }, `Auto-reinstall failed for ${id}`);
|
|
5832
5889
|
captureIntegrationFailure(id, "reinstall", reinstallErr);
|
|
5833
5890
|
report.errors.push({
|
|
5834
5891
|
integrationId: id,
|
|
@@ -5847,7 +5904,7 @@ var ReconciliationEngine = class {
|
|
|
5847
5904
|
if (activateAttempts < MAX_ERROR_ACTIVATE_ATTEMPTS) {
|
|
5848
5905
|
this.activateAttempts.set(id, activateAttempts + 1);
|
|
5849
5906
|
await this.ensureSuspended();
|
|
5850
|
-
log$
|
|
5907
|
+
log$3.info(`Re-activating ${id} from error state (attempt ${String(activateAttempts + 1)}/${String(MAX_ERROR_ACTIVATE_ATTEMPTS)})`);
|
|
5851
5908
|
try {
|
|
5852
5909
|
if ((await this.manager.activate(id)).configApplied) report.configApplied = true;
|
|
5853
5910
|
this.activateAttempts.delete(id);
|
|
@@ -5860,7 +5917,7 @@ var ReconciliationEngine = class {
|
|
|
5860
5917
|
return;
|
|
5861
5918
|
} catch (reactivateErr) {
|
|
5862
5919
|
const reactivateMsg = reactivateErr instanceof Error ? reactivateErr.message : String(reactivateErr);
|
|
5863
|
-
log$
|
|
5920
|
+
log$3.warn(`Re-activation of ${id} from error state failed (attempt ${String(activateAttempts + 1)}/${String(MAX_ERROR_ACTIVATE_ATTEMPTS)}): ${reactivateMsg}`);
|
|
5864
5921
|
captureIntegrationFailure(id, "reactivate", reactivateErr);
|
|
5865
5922
|
report.errors.push({
|
|
5866
5923
|
integrationId: id,
|
|
@@ -5875,7 +5932,7 @@ var ReconciliationEngine = class {
|
|
|
5875
5932
|
return;
|
|
5876
5933
|
}
|
|
5877
5934
|
}
|
|
5878
|
-
log$
|
|
5935
|
+
log$3.warn(`Integration ${id} is in error state — re-activation exhausted, waiting for reinstall request`);
|
|
5879
5936
|
captureIntegrationFailure(id, "reactivate", `Integration ${id} stuck in error state — re-activation attempts exhausted`);
|
|
5880
5937
|
report.errors.push({
|
|
5881
5938
|
integrationId: id,
|
|
@@ -5891,7 +5948,7 @@ var ReconciliationEngine = class {
|
|
|
5891
5948
|
}
|
|
5892
5949
|
if (local.status !== "active") {
|
|
5893
5950
|
await this.ensureSuspended();
|
|
5894
|
-
log$
|
|
5951
|
+
log$3.info(`Activating ${id}`);
|
|
5895
5952
|
if ((await this.manager.activate(id)).configApplied) report.configApplied = true;
|
|
5896
5953
|
report.activated.push(id);
|
|
5897
5954
|
report.results.push({
|
|
@@ -5903,7 +5960,7 @@ var ReconciliationEngine = class {
|
|
|
5903
5960
|
}
|
|
5904
5961
|
if (desired.reinstallRequestedAt && local.installedAt && desired.reinstallRequestedAt > local.installedAt) {
|
|
5905
5962
|
await this.ensureSuspended();
|
|
5906
|
-
log$
|
|
5963
|
+
log$3.info(`Reinstall requested for ${id} (requested: ${desired.reinstallRequestedAt}, installed: ${local.installedAt})`);
|
|
5907
5964
|
this.manager.resetReinstallAttempts(id);
|
|
5908
5965
|
this.activateAttempts.delete(id);
|
|
5909
5966
|
if ((await this.manager.reinstall(id, desired.version, desired.config, desired.customSource)).configApplied) report.configApplied = true;
|
|
@@ -5924,7 +5981,7 @@ var ReconciliationEngine = class {
|
|
|
5924
5981
|
});
|
|
5925
5982
|
} catch (err) {
|
|
5926
5983
|
const message = err instanceof Error ? err.message : String(err);
|
|
5927
|
-
log$
|
|
5984
|
+
log$3.error({ err }, `Error reconciling ${id}`);
|
|
5928
5985
|
captureIntegrationFailure(id, "reconcile_active", err);
|
|
5929
5986
|
report.errors.push({
|
|
5930
5987
|
integrationId: id,
|
|
@@ -5949,7 +6006,7 @@ var ReconciliationEngine = class {
|
|
|
5949
6006
|
}
|
|
5950
6007
|
try {
|
|
5951
6008
|
await this.ensureSuspended();
|
|
5952
|
-
log$
|
|
6009
|
+
log$3.info(`Removing ${id}`);
|
|
5953
6010
|
if (local.status === "active") {
|
|
5954
6011
|
await this.manager.deactivate(id);
|
|
5955
6012
|
report.deactivated.push(id);
|
|
@@ -5963,7 +6020,7 @@ var ReconciliationEngine = class {
|
|
|
5963
6020
|
});
|
|
5964
6021
|
} catch (err) {
|
|
5965
6022
|
const message = err instanceof Error ? err.message : String(err);
|
|
5966
|
-
log$
|
|
6023
|
+
log$3.error({ err }, `Error removing ${id}`);
|
|
5967
6024
|
captureIntegrationFailure(id, "reconcile_removed", err);
|
|
5968
6025
|
report.errors.push({
|
|
5969
6026
|
integrationId: id,
|
|
@@ -22275,7 +22332,7 @@ var CaptureThrottle = class {
|
|
|
22275
22332
|
* Spawns the runtime binary, pipes stdout/stderr to the daemon logger,
|
|
22276
22333
|
* and restarts on crash with exponential backoff.
|
|
22277
22334
|
*/
|
|
22278
|
-
const log$
|
|
22335
|
+
const log$2 = createLogger("RuntimeProcess");
|
|
22279
22336
|
/** Quiet-period flush for a pending multi-line error block (e.g. a traceback
|
|
22280
22337
|
* followed by silence — no closing line ever arrives to complete it). */
|
|
22281
22338
|
const DETECTOR_FLUSH_DEBOUNCE_MS = 1500;
|
|
@@ -22322,7 +22379,7 @@ var RuntimeProcess = class {
|
|
|
22322
22379
|
if (this.stopped) return;
|
|
22323
22380
|
const { command, args } = this.resolveCommand();
|
|
22324
22381
|
this.lastStartTime = Date.now();
|
|
22325
|
-
log$
|
|
22382
|
+
log$2.info({
|
|
22326
22383
|
runtime: this.options.runtime,
|
|
22327
22384
|
command,
|
|
22328
22385
|
args,
|
|
@@ -22343,7 +22400,7 @@ var RuntimeProcess = class {
|
|
|
22343
22400
|
this.child.stdout?.on("data", (data) => {
|
|
22344
22401
|
const lines = data.toString().trim().split("\n");
|
|
22345
22402
|
for (const line of lines) {
|
|
22346
|
-
log$
|
|
22403
|
+
log$2.info({
|
|
22347
22404
|
runtime: this.options.runtime,
|
|
22348
22405
|
stream: "stdout"
|
|
22349
22406
|
}, line);
|
|
@@ -22353,7 +22410,7 @@ var RuntimeProcess = class {
|
|
|
22353
22410
|
this.child.stderr?.on("data", (data) => {
|
|
22354
22411
|
const lines = data.toString().trim().split("\n");
|
|
22355
22412
|
for (const line of lines) {
|
|
22356
|
-
log$
|
|
22413
|
+
log$2.warn({
|
|
22357
22414
|
runtime: this.options.runtime,
|
|
22358
22415
|
stream: "stderr"
|
|
22359
22416
|
}, line);
|
|
@@ -22363,7 +22420,7 @@ var RuntimeProcess = class {
|
|
|
22363
22420
|
this.child.on("exit", (code, signal) => {
|
|
22364
22421
|
this.child = null;
|
|
22365
22422
|
if (this.stopped) {
|
|
22366
|
-
log$
|
|
22423
|
+
log$2.info({
|
|
22367
22424
|
runtime: this.options.runtime,
|
|
22368
22425
|
code,
|
|
22369
22426
|
signal
|
|
@@ -22371,7 +22428,7 @@ var RuntimeProcess = class {
|
|
|
22371
22428
|
return;
|
|
22372
22429
|
}
|
|
22373
22430
|
if (code === 0 && signal == null) {
|
|
22374
|
-
log$
|
|
22431
|
+
log$2.info({
|
|
22375
22432
|
runtime: this.options.runtime,
|
|
22376
22433
|
code
|
|
22377
22434
|
}, "Runtime exited gracefully — restarting");
|
|
@@ -22381,7 +22438,7 @@ var RuntimeProcess = class {
|
|
|
22381
22438
|
}, 500);
|
|
22382
22439
|
return;
|
|
22383
22440
|
}
|
|
22384
|
-
log$
|
|
22441
|
+
log$2.warn({
|
|
22385
22442
|
runtime: this.options.runtime,
|
|
22386
22443
|
code,
|
|
22387
22444
|
signal,
|
|
@@ -22402,7 +22459,7 @@ var RuntimeProcess = class {
|
|
|
22402
22459
|
recentOutput: this.ringBuffer.snapshot(),
|
|
22403
22460
|
crashesSuppressed: crash.suppressedCount
|
|
22404
22461
|
});
|
|
22405
|
-
else log$
|
|
22462
|
+
else log$2.debug({
|
|
22406
22463
|
runtime: this.options.runtime,
|
|
22407
22464
|
suppressed: crash.suppressedCount
|
|
22408
22465
|
}, "Crash capture suppressed by throttle");
|
|
@@ -22414,7 +22471,7 @@ var RuntimeProcess = class {
|
|
|
22414
22471
|
this.backoffMs = Math.min(this.backoffMs * 2, BACKOFF_MAX_MS);
|
|
22415
22472
|
});
|
|
22416
22473
|
this.child.on("error", (err) => {
|
|
22417
|
-
log$
|
|
22474
|
+
log$2.error({
|
|
22418
22475
|
runtime: this.options.runtime,
|
|
22419
22476
|
err: err.message
|
|
22420
22477
|
}, "Runtime process error");
|
|
@@ -22453,7 +22510,7 @@ var RuntimeProcess = class {
|
|
|
22453
22510
|
this.emitErrorBlock(this.detector.flush());
|
|
22454
22511
|
}, DETECTOR_FLUSH_DEBOUNCE_MS);
|
|
22455
22512
|
} catch (err) {
|
|
22456
|
-
log$
|
|
22513
|
+
log$2.debug({
|
|
22457
22514
|
runtime: this.options.runtime,
|
|
22458
22515
|
err: err instanceof Error ? err.message : String(err)
|
|
22459
22516
|
}, "Runtime output observation failed");
|
|
@@ -22464,7 +22521,7 @@ var RuntimeProcess = class {
|
|
|
22464
22521
|
if (!block) return;
|
|
22465
22522
|
const { allow, suppressedCount } = this.throttle.allowErrorCapture(block.fingerprintKey);
|
|
22466
22523
|
if (!allow) {
|
|
22467
|
-
log$
|
|
22524
|
+
log$2.debug({
|
|
22468
22525
|
runtime: this.options.runtime,
|
|
22469
22526
|
kind: block.kind,
|
|
22470
22527
|
suppressed: suppressedCount
|
|
@@ -22498,7 +22555,7 @@ var RuntimeProcess = class {
|
|
|
22498
22555
|
if (!child) return;
|
|
22499
22556
|
return new Promise((resolve) => {
|
|
22500
22557
|
const killTimer = setTimeout(() => {
|
|
22501
|
-
log$
|
|
22558
|
+
log$2.warn({ runtime: this.options.runtime }, "Runtime did not exit in time — sending SIGKILL");
|
|
22502
22559
|
child.kill("SIGKILL");
|
|
22503
22560
|
}, 5e3);
|
|
22504
22561
|
child.on("exit", () => {
|
|
@@ -22523,7 +22580,7 @@ var RuntimeProcess = class {
|
|
|
22523
22580
|
* Restart the runtime process (stop then start with fresh backoff).
|
|
22524
22581
|
*/
|
|
22525
22582
|
async restart() {
|
|
22526
|
-
log$
|
|
22583
|
+
log$2.info({ runtime: this.options.runtime }, "Restarting runtime...");
|
|
22527
22584
|
await this.stop();
|
|
22528
22585
|
this.stopped = false;
|
|
22529
22586
|
this.backoffMs = BACKOFF_INITIAL_MS;
|
|
@@ -22545,7 +22602,7 @@ var RuntimeProcess = class {
|
|
|
22545
22602
|
* this registry from active integration manifests. Handler files are loaded
|
|
22546
22603
|
* via ESM dynamic import on first use and cached until the registry is cleared.
|
|
22547
22604
|
*/
|
|
22548
|
-
const log = createLogger("CommandRegistry");
|
|
22605
|
+
const log$1 = createLogger("CommandRegistry");
|
|
22549
22606
|
var CommandRegistry = class {
|
|
22550
22607
|
commands = /* @__PURE__ */ new Map();
|
|
22551
22608
|
version = 0;
|
|
@@ -22556,7 +22613,7 @@ var CommandRegistry = class {
|
|
|
22556
22613
|
register(integrationId, name, handlerPath, method = "handle", timeoutMs = 3e4) {
|
|
22557
22614
|
const existing = this.commands.get(name);
|
|
22558
22615
|
if (existing) {
|
|
22559
|
-
log.warn({
|
|
22616
|
+
log$1.warn({
|
|
22560
22617
|
command: name,
|
|
22561
22618
|
existing: existing.integrationId,
|
|
22562
22619
|
attempted: integrationId
|
|
@@ -22564,7 +22621,7 @@ var CommandRegistry = class {
|
|
|
22564
22621
|
return;
|
|
22565
22622
|
}
|
|
22566
22623
|
if (!existsSync(handlerPath)) {
|
|
22567
|
-
log.warn({
|
|
22624
|
+
log$1.warn({
|
|
22568
22625
|
command: name,
|
|
22569
22626
|
handlerPath,
|
|
22570
22627
|
integrationId
|
|
@@ -22579,7 +22636,7 @@ var CommandRegistry = class {
|
|
|
22579
22636
|
timeoutMs,
|
|
22580
22637
|
handler: null
|
|
22581
22638
|
});
|
|
22582
|
-
log.info({
|
|
22639
|
+
log$1.info({
|
|
22583
22640
|
command: name,
|
|
22584
22641
|
integrationId,
|
|
22585
22642
|
handlerPath,
|
|
@@ -22593,7 +22650,7 @@ var CommandRegistry = class {
|
|
|
22593
22650
|
unregisterAll(integrationId) {
|
|
22594
22651
|
for (const [name, entry] of this.commands) if (entry.integrationId === integrationId) {
|
|
22595
22652
|
this.commands.delete(name);
|
|
22596
|
-
log.info({
|
|
22653
|
+
log$1.info({
|
|
22597
22654
|
command: name,
|
|
22598
22655
|
integrationId
|
|
22599
22656
|
}, "Unregistered command");
|
|
@@ -22631,7 +22688,7 @@ var CommandRegistry = class {
|
|
|
22631
22688
|
entry.handler = fn;
|
|
22632
22689
|
} catch (err) {
|
|
22633
22690
|
const message = err instanceof Error ? err.message : String(err);
|
|
22634
|
-
log.error({
|
|
22691
|
+
log$1.error({
|
|
22635
22692
|
err: message,
|
|
22636
22693
|
command: name,
|
|
22637
22694
|
handlerPath: entry.handlerPath
|
|
@@ -22652,7 +22709,7 @@ var CommandRegistry = class {
|
|
|
22652
22709
|
})]);
|
|
22653
22710
|
} catch (err) {
|
|
22654
22711
|
const message = err instanceof Error ? err.message : String(err);
|
|
22655
|
-
log.error({
|
|
22712
|
+
log$1.error({
|
|
22656
22713
|
err: message,
|
|
22657
22714
|
command: name
|
|
22658
22715
|
}, "Command execution failed");
|
|
@@ -22681,7 +22738,7 @@ var CommandRegistry = class {
|
|
|
22681
22738
|
clear() {
|
|
22682
22739
|
this.commands.clear();
|
|
22683
22740
|
this.version++;
|
|
22684
|
-
log.info({ version: this.version }, "Command registry cleared");
|
|
22741
|
+
log$1.info({ version: this.version }, "Command registry cleared");
|
|
22685
22742
|
}
|
|
22686
22743
|
};
|
|
22687
22744
|
//#endregion
|
|
@@ -22970,6 +23027,93 @@ function writeSentinel(path) {
|
|
|
22970
23027
|
} catch {}
|
|
22971
23028
|
}
|
|
22972
23029
|
//#endregion
|
|
23030
|
+
//#region src/mcp-error-capture.ts
|
|
23031
|
+
const log = createLogger("McpErrorCapture");
|
|
23032
|
+
/** Quiet-period flush for a pending multi-line stderr block. */
|
|
23033
|
+
const MCP_STDERR_FLUSH_DEBOUNCE_MS = 1500;
|
|
23034
|
+
function createMcpErrorHooks() {
|
|
23035
|
+
const resultErrorThrottle = new CaptureThrottle(6e4);
|
|
23036
|
+
const errorThrottle = new CaptureThrottle(6e4);
|
|
23037
|
+
const crashThrottle = new CaptureThrottle(6e4);
|
|
23038
|
+
const throttleFor = (kind) => kind === "tool-result-error" ? resultErrorThrottle : kind === "server-crash" ? crashThrottle : errorThrottle;
|
|
23039
|
+
const detectors = /* @__PURE__ */ new Map();
|
|
23040
|
+
const flushTimers = /* @__PURE__ */ new Map();
|
|
23041
|
+
const capture = (opts) => {
|
|
23042
|
+
const { allow, suppressedCount } = throttleFor(opts.kind).allowErrorCapture(opts.fingerprintKey);
|
|
23043
|
+
if (!allow) {
|
|
23044
|
+
log.debug({
|
|
23045
|
+
server: opts.server,
|
|
23046
|
+
kind: opts.kind,
|
|
23047
|
+
suppressed: suppressedCount
|
|
23048
|
+
}, "MCP failure capture suppressed by throttle");
|
|
23049
|
+
return;
|
|
23050
|
+
}
|
|
23051
|
+
captureMcpFailure({
|
|
23052
|
+
...opts,
|
|
23053
|
+
suppressedCount
|
|
23054
|
+
});
|
|
23055
|
+
};
|
|
23056
|
+
const emitBlock = (server, block) => {
|
|
23057
|
+
if (!block) return;
|
|
23058
|
+
capture({
|
|
23059
|
+
server,
|
|
23060
|
+
kind: "stderr-output",
|
|
23061
|
+
message: block.lines[0],
|
|
23062
|
+
lines: block.lines,
|
|
23063
|
+
fingerprintKey: `stderr:${server}:${block.fingerprintKey}`
|
|
23064
|
+
});
|
|
23065
|
+
};
|
|
23066
|
+
return {
|
|
23067
|
+
onToolError: (info) => {
|
|
23068
|
+
capture({
|
|
23069
|
+
server: info.server,
|
|
23070
|
+
tool: info.tool,
|
|
23071
|
+
kind: info.kind === "thrown" ? "tool-thrown" : "tool-result-error",
|
|
23072
|
+
message: info.message,
|
|
23073
|
+
fingerprintKey: `tool:${info.server}:${info.tool}:${toFingerprintKey(info.message)}`
|
|
23074
|
+
});
|
|
23075
|
+
},
|
|
23076
|
+
onServerCrash: (server) => {
|
|
23077
|
+
const timer = flushTimers.get(server);
|
|
23078
|
+
if (timer) {
|
|
23079
|
+
clearTimeout(timer);
|
|
23080
|
+
flushTimers.delete(server);
|
|
23081
|
+
}
|
|
23082
|
+
emitBlock(server, detectors.get(server)?.flush() ?? null);
|
|
23083
|
+
capture({
|
|
23084
|
+
server,
|
|
23085
|
+
kind: "server-crash",
|
|
23086
|
+
message: "MCP server connection closed unexpectedly",
|
|
23087
|
+
fingerprintKey: `crash:${server}`
|
|
23088
|
+
});
|
|
23089
|
+
},
|
|
23090
|
+
onServerStderr: (server, line) => {
|
|
23091
|
+
let detector = detectors.get(server);
|
|
23092
|
+
if (!detector) {
|
|
23093
|
+
detector = new ErrorLineDetector();
|
|
23094
|
+
detectors.set(server, detector);
|
|
23095
|
+
}
|
|
23096
|
+
for (const block of detector.feed("stderr", line)) emitBlock(server, block);
|
|
23097
|
+
const existing = flushTimers.get(server);
|
|
23098
|
+
if (existing) {
|
|
23099
|
+
clearTimeout(existing);
|
|
23100
|
+
flushTimers.delete(server);
|
|
23101
|
+
}
|
|
23102
|
+
if (detector.isCollecting) {
|
|
23103
|
+
const target = detector;
|
|
23104
|
+
flushTimers.set(server, setTimeout(() => {
|
|
23105
|
+
flushTimers.delete(server);
|
|
23106
|
+
emitBlock(server, target.flush());
|
|
23107
|
+
}, MCP_STDERR_FLUSH_DEBOUNCE_MS));
|
|
23108
|
+
}
|
|
23109
|
+
},
|
|
23110
|
+
dispose: () => {
|
|
23111
|
+
for (const timer of flushTimers.values()) clearTimeout(timer);
|
|
23112
|
+
flushTimers.clear();
|
|
23113
|
+
}
|
|
23114
|
+
};
|
|
23115
|
+
}
|
|
23116
|
+
//#endregion
|
|
22973
23117
|
//#region src/daemon.ts
|
|
22974
23118
|
/**
|
|
22975
23119
|
* Alfe Gateway Daemon — main entry point.
|
|
@@ -23354,9 +23498,11 @@ async function startDaemon() {
|
|
|
23354
23498
|
});
|
|
23355
23499
|
const mcpManager = new Manager({ logger: logger$1 });
|
|
23356
23500
|
mcpManagerRef = mcpManager;
|
|
23501
|
+
const mcpErrorHooks = createMcpErrorHooks();
|
|
23357
23502
|
mcpBundler = new McpBundler({
|
|
23358
23503
|
logger: logger$1,
|
|
23359
|
-
idleTtlMs: 0
|
|
23504
|
+
idleTtlMs: 0,
|
|
23505
|
+
...mcpErrorHooks
|
|
23360
23506
|
}, { connect: defaultConnect });
|
|
23361
23507
|
if (config.runtime === "hermes") logger$1.info("Hermes runtime — daemon MCP bundler left idle (store mirrored to config.yaml by HermesMcpSync)");
|
|
23362
23508
|
else {
|
|
@@ -23483,6 +23629,7 @@ async function startDaemon() {
|
|
|
23483
23629
|
mcpBundler = null;
|
|
23484
23630
|
logger$1.debug("MCP bundler stopped");
|
|
23485
23631
|
}
|
|
23632
|
+
mcpErrorHooks.dispose();
|
|
23486
23633
|
logger$1.debug("Stopping MCP bundler manager...");
|
|
23487
23634
|
await mcpManager.dispose();
|
|
23488
23635
|
mcpManagerRef = null;
|
|
@@ -24207,4 +24354,4 @@ function formatDuration(ms) {
|
|
|
24207
24354
|
return `${String(Math.round(seconds / 3600))}h`;
|
|
24208
24355
|
}
|
|
24209
24356
|
//#endregion
|
|
24210
|
-
export {
|
|
24357
|
+
export { PID_PATH as C, resolveAgentIdentity as D, loadDaemonConfig as E, PINNED_OPENCLAW_VERSION as O, ALFE_DIR as S, fetchAgentConfig as T, captureRuntimeErrorOutput as _, installService as a, setAgentContext as b, uninstallService as c, AGENT_RUNTIME_SENTRY_DSN as d, captureCliFailure as f, captureRuntimeCrash as g, captureMcpFailure as h, checkExistingDaemon as i, AGENT_DAEMON_SENTRY_DSN as l, captureIntegrationFailure as m, queryDaemonHealth as n, startService as o, captureFatal as p, startDaemon as r, stopExistingDaemon as s, formatHealthReport as t, AGENT_MCP_SENTRY_DSN as u, flushSentry as v, SOCKET_PATH as w, PROTOCOL_VERSION as x, initAgentSentry as y };
|
package/dist/src/index.d.ts
CHANGED
|
@@ -81,6 +81,13 @@ declare const AGENT_DAEMON_SENTRY_DSN = "https://a47f010d8d39fb4350f913492189f28
|
|
|
81
81
|
* Mirrors `SENTRY_DSNS.agentRuntime` in `config/config.ts`.
|
|
82
82
|
*/
|
|
83
83
|
declare const AGENT_RUNTIME_SENTRY_DSN = "https://feb7fb2e3b8e723aec518e74715bfa6d@o4511008239452160.ingest.us.sentry.io/4511683667558400";
|
|
84
|
+
/**
|
|
85
|
+
* MCP tool/server failures on agent VMs — reported by the daemon-hosted MCP
|
|
86
|
+
* bundler (tool errors, child crashes, stderr output). This is the SAME
|
|
87
|
+
* project as the cloud MCP Fly service (`SENTRY_DSNS.mcp`); agent-side events
|
|
88
|
+
* are distinguished by `source: agent-daemon` + `agentId` tags.
|
|
89
|
+
*/
|
|
90
|
+
declare const AGENT_MCP_SENTRY_DSN = "https://638309eac96146a945f46b578f10c806@o4511008239452160.ingest.us.sentry.io/4511146364174336";
|
|
84
91
|
/** Which surface initialised Sentry — tagged on every event. */
|
|
85
92
|
type SentrySurface = "cli" | "daemon";
|
|
86
93
|
interface InitAgentSentryOptions {
|
|
@@ -157,6 +164,21 @@ declare function captureRuntimeErrorOutput(opts: {
|
|
|
157
164
|
fingerprintKey: string;
|
|
158
165
|
suppressedCount?: number;
|
|
159
166
|
}): void;
|
|
167
|
+
/**
|
|
168
|
+
* Capture an MCP failure (tool error, server crash, or error-looking stderr
|
|
169
|
+
* output) into the `mcp` project via the daemon's bound MCP client. Throttling
|
|
170
|
+
* is the caller's job (`mcp-error-capture.ts`). No-op when the MCP client is
|
|
171
|
+
* not initialised. Never throws.
|
|
172
|
+
*/
|
|
173
|
+
declare function captureMcpFailure(opts: {
|
|
174
|
+
server: string;
|
|
175
|
+
tool?: string;
|
|
176
|
+
kind: "tool-thrown" | "tool-result-error" | "server-crash" | "stderr-output";
|
|
177
|
+
message: string;
|
|
178
|
+
/** Optional context lines (stderr block) — attached as breadcrumbs. */
|
|
179
|
+
lines?: readonly string[];
|
|
180
|
+
suppressedCount?: number;
|
|
181
|
+
}): void;
|
|
160
182
|
/** Flush queued events (small timeout) so short-lived commands deliver them. */
|
|
161
183
|
declare function flushSentry(timeoutMs?: number): Promise<void>;
|
|
162
184
|
/**
|
|
@@ -338,4 +360,4 @@ declare function checkExistingDaemon(): Promise<number | null>;
|
|
|
338
360
|
*/
|
|
339
361
|
declare function stopExistingDaemon(): Promise<boolean>;
|
|
340
362
|
//#endregion
|
|
341
|
-
export { AGENT_DAEMON_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, type InitAgentSentryOptions, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, type RuntimeOutputLine, SOCKET_PATH, type SentrySurface, captureCliFailure, captureFatal, captureIntegrationFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, setAgentContext, startDaemon, startService, stopExistingDaemon, uninstallService };
|
|
363
|
+
export { AGENT_DAEMON_SENTRY_DSN, AGENT_MCP_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, type InitAgentSentryOptions, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, type RuntimeOutputLine, SOCKET_PATH, type SentrySurface, captureCliFailure, captureFatal, captureIntegrationFailure, captureMcpFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, setAgentContext, startDaemon, startService, stopExistingDaemon, uninstallService };
|
package/dist/src/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { C as PID_PATH, D as resolveAgentIdentity, E as loadDaemonConfig, O as PINNED_OPENCLAW_VERSION, S as ALFE_DIR, T as fetchAgentConfig, _ as captureRuntimeErrorOutput, a as installService, b as setAgentContext, c as uninstallService, d as AGENT_RUNTIME_SENTRY_DSN, f as captureCliFailure, g as captureRuntimeCrash, h as captureMcpFailure, i as checkExistingDaemon, l as AGENT_DAEMON_SENTRY_DSN, m as captureIntegrationFailure, n as queryDaemonHealth, o as startService, p as captureFatal, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport, u as AGENT_MCP_SENTRY_DSN, v as flushSentry, w as SOCKET_PATH, x as PROTOCOL_VERSION, y as initAgentSentry } from "../health.js";
|
|
2
2
|
import { n as logger } from "../logger.js";
|
|
3
|
-
export { AGENT_DAEMON_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, captureCliFailure, captureFatal, captureIntegrationFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, setAgentContext, startDaemon, startService, stopExistingDaemon, uninstallService };
|
|
3
|
+
export { AGENT_DAEMON_SENTRY_DSN, AGENT_MCP_SENTRY_DSN, AGENT_RUNTIME_SENTRY_DSN, ALFE_DIR, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, captureCliFailure, captureFatal, captureIntegrationFailure, captureMcpFailure, captureRuntimeCrash, captureRuntimeErrorOutput, checkExistingDaemon, fetchAgentConfig, flushSentry, formatHealthReport, initAgentSentry, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, setAgentContext, startDaemon, startService, stopExistingDaemon, uninstallService };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfe.ai/gateway",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Alfe local gateway daemon — persistent control plane for agent integrations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,12 +23,12 @@
|
|
|
23
23
|
"pino-roll": "^1.2.0",
|
|
24
24
|
"smol-toml": ">=1.6.1",
|
|
25
25
|
"ws": "^8.18.0",
|
|
26
|
-
"@alfe.ai/agent-api-client": "^0.
|
|
26
|
+
"@alfe.ai/agent-api-client": "^0.8.0",
|
|
27
27
|
"@alfe.ai/ai-proxy-local": "^0.0.13",
|
|
28
28
|
"@alfe.ai/config": "^0.3.0",
|
|
29
29
|
"@alfe.ai/integration-manifest": "^0.3.1",
|
|
30
|
-
"@alfe.ai/integrations": "^0.2.
|
|
31
|
-
"@alfe.ai/mcp-bundler": "^0.
|
|
30
|
+
"@alfe.ai/integrations": "^0.2.10",
|
|
31
|
+
"@alfe.ai/mcp-bundler": "^0.3.0"
|
|
32
32
|
},
|
|
33
33
|
"license": "UNLICENSED",
|
|
34
34
|
"homepage": "https://alfe.ai",
|