@alfe.ai/gateway 0.2.5 → 0.3.1

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
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";
2
+ import { a as installService, c as uninstallService, i as checkExistingDaemon, n as queryDaemonHealth, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport, y 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
@@ -7,7 +7,7 @@ import { dirname, join } from "node:path";
7
7
  import { homedir } from "node:os";
8
8
  import pino from "pino";
9
9
  import { chmodSync, existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
10
- import { getEndpointFromToken, readConfig } from "@alfe.ai/config";
10
+ import { getEndpointFromToken, readConfig, resolveConfig } from "@alfe.ai/config";
11
11
  import crypto from "crypto";
12
12
  import { parse } from "smol-toml";
13
13
  import WebSocket from "ws";
@@ -5330,6 +5330,215 @@ var NoopRuntimeGate = class {
5330
5330
  requestRestart() {}
5331
5331
  };
5332
5332
  //#endregion
5333
+ //#region src/sentry.ts
5334
+ /**
5335
+ * Agent-side error reporting (Sentry) for the Alfe CLI + gateway daemon.
5336
+ *
5337
+ * This module is the single Sentry bootstrap shared by both published
5338
+ * agent-side packages — `@alfe.ai/gateway` (the daemon) and `@alfe.ai/cli`
5339
+ * (which re-imports these helpers from `@alfe.ai/gateway`). It exists so
5340
+ * integration-installation failures on customer/managed VMs surface centrally
5341
+ * instead of silently rotting until someone SSHes into the box.
5342
+ *
5343
+ * Design constraints (see packages/gateway/DEVELOPING.md → "Error reporting"):
5344
+ * - Errors only. No tracing/profiling (`tracesSampleRate: 0`, `sampleRate: 1`).
5345
+ * - `@sentry/node` is lazy-imported so `alfe --version` doesn't pay for it.
5346
+ * - Sentry can NEVER break the CLI/daemon — every entry point is try/catch'd.
5347
+ * - The DSNs are baked as constants: published tarballs run on agent VMs and
5348
+ * cannot read the repo's `config/config.ts`. That file's `SENTRY_DSNS`
5349
+ * registry (keys `agentDaemon` + `cli`) mirrors them as the human reference.
5350
+ * - Secrets are scrubbed in `beforeSend`; request/env payloads are dropped.
5351
+ * - Opt-out via `ALFE_ERROR_REPORTING=0|false` or `errorReporting = false`
5352
+ * in `~/.alfe/config.toml`. Default ON.
5353
+ */
5354
+ /**
5355
+ * Baked per-surface Sentry DSNs (org `alfe-ai`). DSNs are public by design
5356
+ * (they only permit event ingestion). Mirrors of `config/config.ts` →
5357
+ * `SENTRY_DSNS.agentDaemon` / `SENTRY_DSNS.cli`. If you rotate a DSN, update
5358
+ * both places.
5359
+ */
5360
+ const AGENT_DAEMON_SENTRY_DSN = "https://a47f010d8d39fb4350f913492189f283@o4511008239452160.ingest.us.sentry.io/4511679448547328";
5361
+ /** Surface → Sentry project: `cli` and `agent-daemon` respectively. */
5362
+ const SURFACE_DSNS = {
5363
+ cli: "https://82dde4631336561f2fcc89d7531623de@o4511008239452160.ingest.us.sentry.io/4511679411191808",
5364
+ daemon: AGENT_DAEMON_SENTRY_DSN
5365
+ };
5366
+ /** Held after a successful init so the capture helpers can run synchronously. */
5367
+ let sentry = null;
5368
+ /**
5369
+ * Map the configured API URL to a coarse environment tag. Best-effort — returns
5370
+ * `"unknown"` when no config is present yet (e.g. `alfe login` pre-setup).
5371
+ */
5372
+ function deriveEnvironment() {
5373
+ try {
5374
+ const { apiUrl } = resolveConfig();
5375
+ if (apiUrl.includes("api.dev.alfe.ai") || apiUrl.includes("dev.alfe.ai")) return "dev";
5376
+ if (apiUrl.includes("api.test.alfe.ai")) return "test";
5377
+ if (apiUrl.includes("api.demo.alfe.ai")) return "demo";
5378
+ if (apiUrl.includes("api.alfe.ai")) return "prod";
5379
+ } catch {}
5380
+ return "unknown";
5381
+ }
5382
+ /** Active runtime (`openclaw`/`hermes`) from config, or undefined if unknown. */
5383
+ function deriveRuntime() {
5384
+ try {
5385
+ return resolveConfig().runtime;
5386
+ } catch {
5387
+ return;
5388
+ }
5389
+ }
5390
+ /** True when the operator has opted out of error reporting. */
5391
+ function errorReportingDisabled() {
5392
+ const env = process.env.ALFE_ERROR_REPORTING?.trim().toLowerCase();
5393
+ if (env === "0" || env === "false") return true;
5394
+ try {
5395
+ if (readConfig().errorReporting === false) return true;
5396
+ } catch {}
5397
+ return false;
5398
+ }
5399
+ const KV_SECRET_RE = /\b(authorization|api[_-]?key|apikey|token|secret|password|passwd|bearer)\b(\s*[:=]\s*|\s+)("?)([^\s"']+)\3/gi;
5400
+ const MIN_BARE_SECRET_LEN = 16;
5401
+ const ALFE_TOKEN_RE = /alfe_(?:dev|test|demo|live)_[A-Za-z0-9._-]+/g;
5402
+ const BEARER_RE = /\bbearer\s+[A-Za-z0-9._\-+/=]+/gi;
5403
+ function scrubString(value) {
5404
+ return value.replace(BEARER_RE, "Bearer [REDACTED]").replace(KV_SECRET_RE, (match, label, sep, _q, secret) => {
5405
+ if (!/[:=]/.test(sep) && secret.length < MIN_BARE_SECRET_LEN) return match;
5406
+ return `${label}${sep}[REDACTED]`;
5407
+ }).replace(ALFE_TOKEN_RE, "alfe_[REDACTED]");
5408
+ }
5409
+ /** Scrub secrets from a breadcrumb's message + string data values in place. */
5410
+ function scrubBreadcrumb(b) {
5411
+ if (typeof b.message === "string") b.message = scrubString(b.message);
5412
+ const data = b.data;
5413
+ if (data) for (const k of Object.keys(data)) {
5414
+ const dv = data[k];
5415
+ if (typeof dv === "string") data[k] = scrubString(dv);
5416
+ }
5417
+ return b;
5418
+ }
5419
+ /**
5420
+ * Scrub secrets and drop request/env payloads before an event is sent.
5421
+ * Generic so it preserves the caller's exact event subtype (`beforeSend`
5422
+ * receives — and must return — an `ErrorEvent`, not a widened `Event`).
5423
+ */
5424
+ function scrubEvent(event) {
5425
+ delete event.request;
5426
+ if (event.contexts) delete event.contexts.runtime;
5427
+ delete event.extra;
5428
+ delete event.server_name;
5429
+ if (typeof event.message === "string") event.message = scrubString(event.message);
5430
+ const values = event.exception?.values;
5431
+ if (values) {
5432
+ for (const v of values) if (typeof v.value === "string") v.value = scrubString(v.value);
5433
+ }
5434
+ if (event.breadcrumbs) for (const b of event.breadcrumbs) scrubBreadcrumb(b);
5435
+ return event;
5436
+ }
5437
+ /**
5438
+ * Initialise Sentry for the agent-side CLI/daemon. Idempotent, best-effort, and
5439
+ * a no-op when opted out or when the baked DSN is empty. Never throws.
5440
+ */
5441
+ async function initAgentSentry(options) {
5442
+ try {
5443
+ if (sentry) return;
5444
+ if (errorReportingDisabled()) return;
5445
+ const dsn = SURFACE_DSNS[options.surface].trim();
5446
+ if (!dsn) return;
5447
+ const mod = await import("@sentry/node");
5448
+ if (mod.getClient()) {
5449
+ sentry = mod;
5450
+ return;
5451
+ }
5452
+ mod.init({
5453
+ dsn,
5454
+ environment: deriveEnvironment(),
5455
+ ...options.release ? { release: options.release } : {},
5456
+ sampleRate: 1,
5457
+ tracesSampleRate: 0,
5458
+ sendDefaultPii: false,
5459
+ beforeSend: (event) => scrubEvent(event),
5460
+ beforeBreadcrumb: (breadcrumb) => scrubBreadcrumb(breadcrumb)
5461
+ });
5462
+ sentry = mod;
5463
+ mod.setTag("surface", options.surface);
5464
+ const runtime = deriveRuntime();
5465
+ if (runtime) mod.setTag("runtime", runtime);
5466
+ } catch {
5467
+ sentry = null;
5468
+ }
5469
+ }
5470
+ /**
5471
+ * Attach the resolved agent identity to all subsequent events. Called by the
5472
+ * daemon once `loadDaemonConfig()` has resolved `agentId`/`runtime`.
5473
+ */
5474
+ function setAgentContext(context) {
5475
+ if (!sentry) return;
5476
+ try {
5477
+ if (context.agentId) sentry.setTag("agentId", context.agentId);
5478
+ if (context.runtime) sentry.setTag("runtime", context.runtime);
5479
+ } catch {}
5480
+ }
5481
+ /**
5482
+ * Capture an integration lifecycle failure (install/activate/reinstall/remove)
5483
+ * with `{ integration, phase }` tags. Accepts an `Error` (captured with stack)
5484
+ * or a plain message string (captured as an error-level message). No-op when
5485
+ * Sentry is not initialised.
5486
+ */
5487
+ function captureIntegrationFailure(integration, phase, cause) {
5488
+ if (!sentry) return;
5489
+ try {
5490
+ if (cause instanceof Error) sentry.captureException(cause, { tags: {
5491
+ integration,
5492
+ phase
5493
+ } });
5494
+ else sentry.captureMessage(String(cause), {
5495
+ level: "error",
5496
+ tags: {
5497
+ integration,
5498
+ phase
5499
+ }
5500
+ });
5501
+ } catch {}
5502
+ }
5503
+ /**
5504
+ * Capture a generic CLI failure with a `{ context }` tag. The CLI counterpart
5505
+ * to `captureIntegrationFailure` — used by `exitWithError` at the handled-error
5506
+ * `process.exit()` sites in `@alfe.ai/cli`'s commands, which otherwise report
5507
+ * nothing (the error was caught, never thrown). Accepts an `Error` (captured
5508
+ * with stack), a defined non-Error value (captured as an error-level message),
5509
+ * or nothing (the `context` string itself becomes the message). No-op when
5510
+ * Sentry is not initialised. Never throws.
5511
+ */
5512
+ function captureCliFailure(context, cause) {
5513
+ if (!sentry) return;
5514
+ try {
5515
+ if (cause instanceof Error) sentry.captureException(cause, { tags: { context } });
5516
+ else if (cause === void 0) sentry.captureMessage(context, { level: "error" });
5517
+ else sentry.captureMessage(String(cause), {
5518
+ level: "error",
5519
+ tags: { context }
5520
+ });
5521
+ } catch {}
5522
+ }
5523
+ /** Flush queued events (small timeout) so short-lived commands deliver them. */
5524
+ async function flushSentry(timeoutMs = 2e3) {
5525
+ if (!sentry) return;
5526
+ try {
5527
+ await sentry.flush(timeoutMs);
5528
+ } catch {}
5529
+ }
5530
+ /**
5531
+ * Capture a fatal error — for the CLI's top-level catch. Does NOT flush: the
5532
+ * caller's `finally { await flushSentry() }` delivers it (flushing here too
5533
+ * doubled the worst-case exit delay on a failing command).
5534
+ */
5535
+ function captureFatal(cause) {
5536
+ if (!sentry) return;
5537
+ try {
5538
+ sentry.captureException(cause);
5539
+ } catch {}
5540
+ }
5541
+ //#endregion
5333
5542
  //#region src/reconciliation.ts
5334
5543
  const log$2 = logger$1.child({ component: "Reconciliation" });
5335
5544
  /**
@@ -5466,6 +5675,7 @@ var ReconciliationEngine = class {
5466
5675
  const attempts = this.manager.getReinstallAttempts(id);
5467
5676
  if (attempts >= 3) {
5468
5677
  log$2.error(`Auto-reinstall blocked for ${id} — ${String(attempts)} consecutive failures. Manual reinstall required.`);
5678
+ captureIntegrationFailure(id, "reinstall", `Max auto-reinstall attempts (${String(attempts)}) reached — manual reinstall required`);
5469
5679
  report.errors.push({
5470
5680
  integrationId: id,
5471
5681
  error: `Max auto-reinstall attempts (${String(attempts)}) reached`
@@ -5495,6 +5705,7 @@ var ReconciliationEngine = class {
5495
5705
  } catch (reinstallErr) {
5496
5706
  const reinstallMsg = reinstallErr instanceof Error ? reinstallErr.message : String(reinstallErr);
5497
5707
  log$2.error({ err: reinstallErr }, `Auto-reinstall failed for ${id}`);
5708
+ captureIntegrationFailure(id, "reinstall", reinstallErr);
5498
5709
  report.errors.push({
5499
5710
  integrationId: id,
5500
5711
  error: reinstallMsg
@@ -5526,6 +5737,7 @@ var ReconciliationEngine = class {
5526
5737
  } catch (reactivateErr) {
5527
5738
  const reactivateMsg = reactivateErr instanceof Error ? reactivateErr.message : String(reactivateErr);
5528
5739
  log$2.warn(`Re-activation of ${id} from error state failed (attempt ${String(activateAttempts + 1)}/${String(MAX_ERROR_ACTIVATE_ATTEMPTS)}): ${reactivateMsg}`);
5740
+ captureIntegrationFailure(id, "reactivate", reactivateErr);
5529
5741
  report.errors.push({
5530
5742
  integrationId: id,
5531
5743
  error: reactivateMsg
@@ -5540,6 +5752,7 @@ var ReconciliationEngine = class {
5540
5752
  }
5541
5753
  }
5542
5754
  log$2.warn(`Integration ${id} is in error state — re-activation exhausted, waiting for reinstall request`);
5755
+ captureIntegrationFailure(id, "reactivate", `Integration ${id} stuck in error state — re-activation attempts exhausted`);
5543
5756
  report.errors.push({
5544
5757
  integrationId: id,
5545
5758
  error: "Integration is in error state"
@@ -5588,6 +5801,7 @@ var ReconciliationEngine = class {
5588
5801
  } catch (err) {
5589
5802
  const message = err instanceof Error ? err.message : String(err);
5590
5803
  log$2.error({ err }, `Error reconciling ${id}`);
5804
+ captureIntegrationFailure(id, "reconcile_active", err);
5591
5805
  report.errors.push({
5592
5806
  integrationId: id,
5593
5807
  error: message
@@ -5626,6 +5840,7 @@ var ReconciliationEngine = class {
5626
5840
  } catch (err) {
5627
5841
  const message = err instanceof Error ? err.message : String(err);
5628
5842
  log$2.error({ err }, `Error removing ${id}`);
5843
+ captureIntegrationFailure(id, "reconcile_removed", err);
5629
5844
  report.errors.push({
5630
5845
  integrationId: id,
5631
5846
  error: message
@@ -22530,6 +22745,7 @@ async function getRuntimeVersion(runtime) {
22530
22745
  * process.exit() can drop buffered log lines — this ensures they're written first.
22531
22746
  */
22532
22747
  async function flushAndExit(code) {
22748
+ await flushSentry();
22533
22749
  await new Promise((resolve) => {
22534
22750
  logger$1.flush();
22535
22751
  setTimeout(resolve, 500);
@@ -22592,6 +22808,10 @@ async function startDaemon() {
22592
22808
  managed,
22593
22809
  pid: process.pid
22594
22810
  }, "Starting Alfe Gateway Daemon...");
22811
+ await initAgentSentry({
22812
+ surface: "daemon",
22813
+ release: await getCliVersion()
22814
+ });
22595
22815
  if (!managed) {
22596
22816
  await mkdir(join(homedir(), ".alfe"), { recursive: true });
22597
22817
  const existingPid = await checkExistingDaemon();
@@ -22608,6 +22828,10 @@ async function startDaemon() {
22608
22828
  orgId: config.orgId,
22609
22829
  wsUrl: config.gatewayWsUrl
22610
22830
  }, "Config loaded, identity resolved");
22831
+ setAgentContext({
22832
+ agentId: config.agentId,
22833
+ runtime: config.runtime
22834
+ });
22611
22835
  } catch (err) {
22612
22836
  const message = err instanceof Error ? err.message : String(err);
22613
22837
  const stack = err instanceof Error ? err.stack : void 0;
@@ -23575,4 +23799,4 @@ function formatDuration(ms) {
23575
23799
  return `${String(Math.round(seconds / 3600))}h`;
23576
23800
  }
23577
23801
  //#endregion
23578
- export { installService as a, uninstallService as c, PID_PATH as d, SOCKET_PATH as f, PINNED_OPENCLAW_VERSION as g, 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 };
23802
+ export { PINNED_OPENCLAW_VERSION as C, resolveAgentIdentity as S, ALFE_DIR as _, installService as a, fetchAgentConfig as b, uninstallService as c, captureFatal as d, captureIntegrationFailure as f, PROTOCOL_VERSION as g, setAgentContext as h, checkExistingDaemon as i, AGENT_DAEMON_SENTRY_DSN as l, initAgentSentry as m, queryDaemonHealth as n, startService as o, flushSentry as p, startDaemon as r, stopExistingDaemon as s, formatHealthReport as t, captureCliFailure as u, PID_PATH as v, loadDaemonConfig as x, SOCKET_PATH as y };
@@ -46,6 +46,81 @@ declare function startDaemon(): Promise<void>;
46
46
  */
47
47
  declare const PINNED_OPENCLAW_VERSION = "2026.6.8";
48
48
  //#endregion
49
+ //#region src/sentry.d.ts
50
+ /**
51
+ * Agent-side error reporting (Sentry) for the Alfe CLI + gateway daemon.
52
+ *
53
+ * This module is the single Sentry bootstrap shared by both published
54
+ * agent-side packages — `@alfe.ai/gateway` (the daemon) and `@alfe.ai/cli`
55
+ * (which re-imports these helpers from `@alfe.ai/gateway`). It exists so
56
+ * integration-installation failures on customer/managed VMs surface centrally
57
+ * instead of silently rotting until someone SSHes into the box.
58
+ *
59
+ * Design constraints (see packages/gateway/DEVELOPING.md → "Error reporting"):
60
+ * - Errors only. No tracing/profiling (`tracesSampleRate: 0`, `sampleRate: 1`).
61
+ * - `@sentry/node` is lazy-imported so `alfe --version` doesn't pay for it.
62
+ * - Sentry can NEVER break the CLI/daemon — every entry point is try/catch'd.
63
+ * - The DSNs are baked as constants: published tarballs run on agent VMs and
64
+ * cannot read the repo's `config/config.ts`. That file's `SENTRY_DSNS`
65
+ * registry (keys `agentDaemon` + `cli`) mirrors them as the human reference.
66
+ * - Secrets are scrubbed in `beforeSend`; request/env payloads are dropped.
67
+ * - Opt-out via `ALFE_ERROR_REPORTING=0|false` or `errorReporting = false`
68
+ * in `~/.alfe/config.toml`. Default ON.
69
+ */
70
+ /**
71
+ * Baked per-surface Sentry DSNs (org `alfe-ai`). DSNs are public by design
72
+ * (they only permit event ingestion). Mirrors of `config/config.ts` →
73
+ * `SENTRY_DSNS.agentDaemon` / `SENTRY_DSNS.cli`. If you rotate a DSN, update
74
+ * both places.
75
+ */
76
+ declare const AGENT_DAEMON_SENTRY_DSN = "https://a47f010d8d39fb4350f913492189f283@o4511008239452160.ingest.us.sentry.io/4511679448547328";
77
+ /** Which surface initialised Sentry — tagged on every event. */
78
+ type SentrySurface = "cli" | "daemon";
79
+ interface InitAgentSentryOptions {
80
+ /** `"cli"` or `"daemon"` — tagged as `surface`. */
81
+ surface: SentrySurface;
82
+ /** Release identifier — the package version. */
83
+ release?: string;
84
+ }
85
+ /**
86
+ * Initialise Sentry for the agent-side CLI/daemon. Idempotent, best-effort, and
87
+ * a no-op when opted out or when the baked DSN is empty. Never throws.
88
+ */
89
+ declare function initAgentSentry(options: InitAgentSentryOptions): Promise<void>;
90
+ /**
91
+ * Attach the resolved agent identity to all subsequent events. Called by the
92
+ * daemon once `loadDaemonConfig()` has resolved `agentId`/`runtime`.
93
+ */
94
+ declare function setAgentContext(context: {
95
+ agentId?: string;
96
+ runtime?: string;
97
+ }): void;
98
+ /**
99
+ * Capture an integration lifecycle failure (install/activate/reinstall/remove)
100
+ * with `{ integration, phase }` tags. Accepts an `Error` (captured with stack)
101
+ * or a plain message string (captured as an error-level message). No-op when
102
+ * Sentry is not initialised.
103
+ */
104
+ declare function captureIntegrationFailure(integration: string, phase: string, cause: unknown): void;
105
+ /**
106
+ * Capture a generic CLI failure with a `{ context }` tag. The CLI counterpart
107
+ * to `captureIntegrationFailure` — used by `exitWithError` at the handled-error
108
+ * `process.exit()` sites in `@alfe.ai/cli`'s commands, which otherwise report
109
+ * nothing (the error was caught, never thrown). Accepts an `Error` (captured
110
+ * with stack), a defined non-Error value (captured as an error-level message),
111
+ * or nothing (the `context` string itself becomes the message). No-op when
112
+ * Sentry is not initialised. Never throws.
113
+ */
114
+ declare function captureCliFailure(context: string, cause?: unknown): void;
115
+ /** Flush queued events (small timeout) so short-lived commands deliver them. */
116
+ declare function flushSentry(timeoutMs?: number): Promise<void>;
117
+ /**
118
+ * Capture a fatal error — for the CLI's top-level catch. Does NOT flush: the
119
+ * caller's `finally { await flushSentry() }` delivers it (flushing here too
120
+ * doubled the worst-case exit delay on a failing command).
121
+ */
122
+ declare function captureFatal(cause: unknown): void;
123
+ //#endregion
49
124
  //#region src/config.d.ts
50
125
  /**
51
126
  * Daemon configuration — reads ~/.alfe/config.toml and resolves agent identity.
@@ -218,4 +293,4 @@ declare function checkExistingDaemon(): Promise<number | null>;
218
293
  */
219
294
  declare function stopExistingDaemon(): Promise<boolean>;
220
295
  //#endregion
221
- export { ALFE_DIR, type AgentIdentity, type AgentWorkspaceConfig, type DaemonConfig, type DaemonHealth, type IPCEvent, type IPCRequest, type IPCResponse, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, startService, stopExistingDaemon, uninstallService };
296
+ export { AGENT_DAEMON_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, SOCKET_PATH, type SentrySurface, captureCliFailure, captureFatal, captureIntegrationFailure, 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 { a as installService, c as uninstallService, d as PID_PATH, f as SOCKET_PATH, g as PINNED_OPENCLAW_VERSION, 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";
1
+ import { C as PINNED_OPENCLAW_VERSION, S as resolveAgentIdentity, _ as ALFE_DIR, a as installService, b as fetchAgentConfig, c as uninstallService, d as captureFatal, f as captureIntegrationFailure, g as PROTOCOL_VERSION, h as setAgentContext, i as checkExistingDaemon, l as AGENT_DAEMON_SENTRY_DSN, m as initAgentSentry, n as queryDaemonHealth, o as startService, p as flushSentry, r as startDaemon, s as stopExistingDaemon, t as formatHealthReport, u as captureCliFailure, v as PID_PATH, x as loadDaemonConfig, y as SOCKET_PATH } from "../health.js";
2
2
  import { n as logger } from "../logger.js";
3
- export { ALFE_DIR, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, checkExistingDaemon, fetchAgentConfig, formatHealthReport, installService, loadDaemonConfig, logger, queryDaemonHealth, resolveAgentIdentity, startDaemon, startService, stopExistingDaemon, uninstallService };
3
+ export { AGENT_DAEMON_SENTRY_DSN, ALFE_DIR, PID_PATH, PINNED_OPENCLAW_VERSION, PROTOCOL_VERSION, SOCKET_PATH, captureCliFailure, captureFatal, captureIntegrationFailure, 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.2.5",
3
+ "version": "0.3.1",
4
4
  "description": "Alfe local gateway daemon — persistent control plane for agent integrations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,6 +18,7 @@
18
18
  "dist"
19
19
  ],
20
20
  "dependencies": {
21
+ "@sentry/node": "^10.42.0",
21
22
  "pino": "^9.6.0",
22
23
  "pino-roll": "^1.2.0",
23
24
  "smol-toml": ">=1.6.1",
@@ -26,7 +27,7 @@
26
27
  "@alfe.ai/ai-proxy-local": "^0.0.13",
27
28
  "@alfe.ai/config": "^0.3.0",
28
29
  "@alfe.ai/integration-manifest": "^0.3.1",
29
- "@alfe.ai/integrations": "^0.2.6",
30
+ "@alfe.ai/integrations": "^0.2.7",
30
31
  "@alfe.ai/mcp-bundler": "^0.2.2"
31
32
  },
32
33
  "license": "UNLICENSED",