@interactive-inc/claude-funnel 0.66.0 → 0.67.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.
Files changed (88) hide show
  1. package/README.md +8 -4
  2. package/dist/bin.js +275 -372
  3. package/dist/channel.d.ts +76 -52
  4. package/dist/channel.js +82 -47
  5. package/dist/{channels-DR90RmUP.d.ts → channels-BBA3GTAa.d.ts} +5 -6
  6. package/dist/claude.d.ts +11 -8
  7. package/dist/claude.js +31 -15
  8. package/dist/{connector-descriptor-CmyHlEiT.d.ts → connector-descriptor-F75ZI8Fh.d.ts} +26 -15
  9. package/dist/{connector-diagnostics-recorder-COtNEmUp.js → connector-diagnostics-recorder-BmOijU1p.js} +1 -0
  10. package/dist/connectors/discord.d.ts +10 -8
  11. package/dist/connectors/discord.js +2 -2
  12. package/dist/connectors/gh.d.ts +6 -6
  13. package/dist/connectors/gh.js +2 -2
  14. package/dist/connectors/schedule.d.ts +10 -8
  15. package/dist/connectors/schedule.js +2 -2
  16. package/dist/connectors/slack.d.ts +14 -10
  17. package/dist/connectors/slack.js +3 -3
  18. package/dist/diagnostics.d.ts +1 -1
  19. package/dist/diagnostics.js +1 -1
  20. package/dist/{discord-connector-DXARcO6w.js → discord-connector-CdjwPoty.js} +6 -6
  21. package/dist/{discord-connector-schema-D1dyxhXk.d.ts → discord-connector-schema-BaBZYHxK.d.ts} +0 -1
  22. package/dist/docs.d.ts +1 -1
  23. package/dist/docs.js +1 -1
  24. package/dist/doctor.d.ts +1 -1
  25. package/dist/doctor.js +1 -1
  26. package/dist/{file-process-guard-CiBwXjzm.d.ts → file-process-guard-DAYe9Ndt.d.ts} +22 -18
  27. package/dist/{file-system-DHgbuTFb.d.ts → file-system-BNtl997T.d.ts} +2 -1
  28. package/dist/{flume-source-listener-FzR5lGpL.d.ts → flume-source-listener-CLtsdcT2.d.ts} +8 -6
  29. package/dist/{funnel-diagnostics-Cvk6Sk4x.js → funnel-diagnostics-B-PCuv_E.js} +4 -3
  30. package/dist/{funnel-diagnostics-kbd27d7I.d.ts → funnel-diagnostics-CnKus3Jg.d.ts} +8 -5
  31. package/dist/{funnel-docs-C-ge0MuB.js → funnel-docs-BFcqITFA.js} +4 -0
  32. package/dist/{funnel-doctor-XrI2GBH8.js → funnel-doctor-Csw5qjcH.js} +1 -0
  33. package/dist/{funnel-doctor-CVTNUtDn.d.ts → funnel-doctor-CviUTINw.d.ts} +20 -9
  34. package/dist/{funnel-error-0t1MK1R6.js → funnel-error-DoSBCogD.js} +13 -0
  35. package/dist/{funnel-log-sqlite-sink-DLYkY0pZ.js → funnel-log-sqlite-sink-CXbs3qQp.js} +1 -1
  36. package/dist/{funnel-recovery-D8MkiTpk.d.ts → funnel-recovery-BwcSNNSN.d.ts} +1 -2
  37. package/dist/{funnel-recovery-DKnEutUS.js → funnel-recovery-DYbSYGWC.js} +1 -0
  38. package/dist/gateway/daemon.js +66 -125
  39. package/dist/gateway.d.ts +2 -3
  40. package/dist/gateway.js +2 -2
  41. package/dist/{gh-connector-BUGCOEWS.js → gh-connector-D-iyjl-d.js} +5 -5
  42. package/dist/{gh-connector-schema-BCHEqpUg.d.ts → gh-connector-schema-BrNsCl1T.d.ts} +0 -1
  43. package/dist/{index-BU1TtuFy.d.ts → index-B4RvEaW-.d.ts} +205 -40
  44. package/dist/index.d.ts +115 -109
  45. package/dist/index.js +123 -32
  46. package/dist/{local-config-json-schema-DexV8vX3.js → local-config-json-schema-_-YVHX4c.js} +4 -4
  47. package/dist/local-config.d.ts +2 -3
  48. package/dist/local-config.js +1 -1
  49. package/dist/logger.d.ts +29 -13
  50. package/dist/logger.js +1 -1
  51. package/dist/{memory-token-prompter-D0kIdhar.d.ts → memory-token-prompter-D3R_kgM_.d.ts} +2 -3
  52. package/dist/{node-file-system-BOXIHW_Q.js → node-file-system-xJx7dymE.js} +11 -3
  53. package/dist/{profiles-M24JrcOh.d.ts → profiles-CePRnv3F.d.ts} +3 -4
  54. package/dist/{profiles-ZHLONml4.js → profiles-KpN7_gBw.js} +19 -5
  55. package/dist/profiles.d.ts +1 -1
  56. package/dist/profiles.js +1 -1
  57. package/dist/recovery.d.ts +1 -1
  58. package/dist/recovery.js +1 -1
  59. package/dist/{schedule-connector-schema-D7ZEKvit.d.ts → schedule-connector-schema-DBko_Bf7.d.ts} +0 -1
  60. package/dist/{schedule-connector-9k3gOIgl.js → schedule-connector-teeDMHUe.js} +5 -5
  61. package/dist/{settings-reader-BnKIbmsD.d.ts → settings-reader-CyTpbAre.d.ts} +1 -2
  62. package/dist/{settings-schema-IShSMm5G.d.ts → settings-schema-B-CKLuST.d.ts} +0 -1
  63. package/dist/{settings-store-ccv291GV.js → settings-store-ZFWBhOnp.js} +12 -3
  64. package/dist/{slack-connector-CxpWagbT.js → slack-connector-BE0KAjCs.js} +10 -9
  65. package/dist/{slack-event-processor-xFDG3US0.js → slack-event-processor-Cs_YuI3w.js} +2 -2
  66. package/dist/{slack-event-processor-BDTr62cN.d.ts → slack-event-processor-DmAlq4cV.d.ts} +0 -1
  67. package/dist/{slot-fields-D-pvMgTK.js → slot-fields-5ERhytIA.js} +3 -3
  68. package/dist/{sqlite-diagnostic-log-CwhXE9Qh.js → sqlite-diagnostic-log-BDxfXGZy.js} +42 -19
  69. package/dist/{yaml-render-DVEtYuF1.js → yaml-render-DxxRQT-V.js} +3 -3
  70. package/package.json +10 -10
  71. package/dist/broadcaster-DVNcw00K.d.ts +0 -138
  72. package/dist/file-system-Wvzc2ePY.js +0 -9
  73. package/dist/logger-B6iyNbxM.js +0 -9
  74. package/dist/settings-reader-9FcX3qS1.js +0 -11
  75. /package/dist/{connector-adapter-Dvs8N7ew.js → connector-adapter-BL2ehMej.js} +0 -0
  76. /package/dist/{connector-listener-mPGZYa8e.js → connector-listener-BcQMzY6Q.js} +0 -0
  77. /package/dist/{diagnostic-sql-reader-oXZnWFf_.js → diagnostic-sql-reader-CoBk_EFF.js} +0 -0
  78. /package/dist/{discord-connector-schema-B4YpWpR3.js → discord-connector-schema-saAGuPmJ.js} +0 -0
  79. /package/dist/{error-message-of-ColuYmAk.js → error-message-of-BG4ezZ_s.js} +0 -0
  80. /package/dist/{funnel-docs-Cd66sKyV.d.ts → funnel-docs-BJWawfWI.d.ts} +0 -0
  81. /package/dist/{gh-connector-schema-CAqIhzGr.js → gh-connector-schema-DmZTrzUu.js} +0 -0
  82. /package/dist/{logger-Bc_Ooypb.d.ts → logger-mMZvblTx.d.ts} +0 -0
  83. /package/dist/{loopback-fetch-CVNuN3YZ.js → loopback-fetch-HP-bo9Kv.js} +0 -0
  84. /package/dist/{node-http-client-u00atiKx.js → node-http-client-SX3xFh4h.js} +0 -0
  85. /package/dist/{node-process-runner-DxTvycoK.js → node-process-runner-D4rzPl8Q.js} +0 -0
  86. /package/dist/{resolve-connector-token-DxDG9mhf.js → resolve-connector-token-BwiJCu82.js} +0 -0
  87. /package/dist/{schedule-connector-schema-DKEPZnVv.js → schedule-connector-schema-C2AChpwX.js} +0 -0
  88. /package/dist/{slack-connector-schema-Dem8to4P.js → slack-connector-schema-EGVuuqSX.js} +0 -0
@@ -1,15 +1,15 @@
1
- import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-CVNuN3YZ.js";
2
- import { t as NodeFunnelFileSystem } from "./node-file-system-BOXIHW_Q.js";
3
- import { t as NodeFunnelProcessRunner } from "./node-process-runner-DxTvycoK.js";
4
- import { n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ccv291GV.js";
5
- import { t as FunnelAuthFailedError } from "./funnel-error-0t1MK1R6.js";
6
- import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-oXZnWFf_.js";
7
- import { t as FunnelLogSqliteSink } from "./funnel-log-sqlite-sink-DLYkY0pZ.js";
1
+ import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-HP-bo9Kv.js";
2
+ import { t as NodeFunnelFileSystem } from "./node-file-system-xJx7dymE.js";
3
+ import { t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js";
4
+ import { n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ZFWBhOnp.js";
5
+ import { t as FunnelAuthFailedError } from "./funnel-error-DoSBCogD.js";
6
+ import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-CoBk_EFF.js";
7
+ import { t as FunnelLogSqliteSink } from "./funnel-log-sqlite-sink-CXbs3qQp.js";
8
8
  import { dirname, join } from "node:path";
9
9
  import { chmodSync, existsSync, mkdirSync } from "node:fs";
10
10
  import { homedir, tmpdir } from "node:os";
11
11
  import { z } from "zod";
12
- import { timingSafeEqual } from "node:crypto";
12
+ import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
13
13
  import { createFactory } from "hono/factory";
14
14
  import { HTTPException } from "hono/http-exception";
15
15
  import { zValidator } from "@hono/zod-validator";
@@ -128,6 +128,7 @@ var ConnectorDiagnosticLog = class {};
128
128
  * rejecting a malformed payload.
129
129
  */
130
130
  var MemoryConnectorDiagnosticLog = class extends ConnectorDiagnosticLog {
131
+ now;
131
132
  raws = [];
132
133
  processeds = [];
133
134
  connections = [];
@@ -158,21 +159,24 @@ var MemoryConnectorDiagnosticLog = class extends ConnectorDiagnosticLog {
158
159
  });
159
160
  }
160
161
  queryRaw(query) {
161
- return takeRecent(this.raws.filter((event) => matches(event, query)), query.limit);
162
+ const matched = this.raws.filter((event) => matches(event, query));
163
+ return takeRecent(matched, query.limit);
162
164
  }
163
165
  queryProcessed(query) {
164
- return takeRecent(this.processeds.filter((event) => {
166
+ const matched = this.processeds.filter((event) => {
165
167
  if (!matches(event, query)) return false;
166
168
  if (query.outcome !== void 0 && event.outcome !== query.outcome) return false;
167
169
  return true;
168
- }), query.limit);
170
+ });
171
+ return takeRecent(matched, query.limit);
169
172
  }
170
173
  queryConnection(query) {
171
- return takeRecent(this.connections.filter((event) => {
174
+ const matched = this.connections.filter((event) => {
172
175
  if (!matches(event, query)) return false;
173
176
  if (query.status !== void 0 && event.status !== query.status) return false;
174
177
  return true;
175
- }), query.limit);
178
+ });
179
+ return takeRecent(matched, query.limit);
176
180
  }
177
181
  clear() {
178
182
  this.raws.length = 0;
@@ -279,7 +283,8 @@ var FunnelChannelPublisher = class {
279
283
  */
280
284
  const requireBearerToken = (deps) => {
281
285
  return async (c, next) => {
282
- if (!constantTimeEqual((c.req.header("authorization") ?? "").match(/^Bearer\s+(.+)$/i)?.[1] ?? "", deps.expected)) return c.text("unauthorized", 401);
286
+ const presented = (c.req.header("authorization") ?? "").match(/^Bearer\s+(.+)$/i)?.[1] ?? "";
287
+ if (!constantTimeEqual(presented, deps.expected)) return c.text("unauthorized", 401);
283
288
  return await next();
284
289
  };
285
290
  };
@@ -626,7 +631,10 @@ var SqliteFunnelEventLog = class extends FunnelEventLog {
626
631
  * so this returns the full slice and lets the caller filter.
627
632
  */
628
633
  loadSince(since) {
629
- const records = this.sink.query({ sinceSeq: since });
634
+ const records = this.sink.query({
635
+ sinceSeq: since,
636
+ limit: Number.MAX_SAFE_INTEGER
637
+ });
630
638
  const out = [];
631
639
  for (const record of records) out.push({
632
640
  content: record.event.content,
@@ -1410,15 +1418,26 @@ function buildGatewayRoutes() {
1410
1418
  }
1411
1419
  const gatewayRoutes = buildGatewayRoutes();
1412
1420
  //#endregion
1421
+ //#region lib/gateway/default-event-db-path.ts
1422
+ /**
1423
+ * Gives each durable gateway endpoint its own replay database. Port zero is
1424
+ * ephemeral, so each construction receives a fresh scope instead of pretending
1425
+ * that replay can survive a restart onto a different assigned port.
1426
+ */
1427
+ function defaultEventDbPath(props) {
1428
+ const endpoint = props.port === 0 ? randomUUID() : String(props.port);
1429
+ const scope = createHash("sha256").update(`${props.funnelDir}\0${endpoint}`).digest("hex").slice(0, 20);
1430
+ return join(props.tmpDir, "events", `${scope}.db`);
1431
+ }
1432
+ //#endregion
1413
1433
  //#region lib/gateway/gateway-server.ts
1414
1434
  const DEFAULT_HOST = "127.0.0.1";
1415
- const LOOPBACK_HOSTS = new Set([
1435
+ const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
1416
1436
  "127.0.0.1",
1417
1437
  "localhost",
1418
1438
  "::1",
1419
1439
  "::ffff:127.0.0.1"
1420
1440
  ]);
1421
- const defaultDbPath = () => join(funnelTmpDir(), "events.db");
1422
1441
  const defaultOnError = () => {};
1423
1442
  /**
1424
1443
  * In-process gateway: runs `Bun.serve` (HTTP + WebSocket /ws), boots connector
@@ -1456,12 +1475,16 @@ var FunnelGatewayServer = class {
1456
1475
  this.channels = deps.channels;
1457
1476
  this.configuredPort = deps.port ?? resolveFunnelPort();
1458
1477
  this.configuredHostname = deps.hostname ?? DEFAULT_HOST;
1459
- this.dbPath = deps.dbPath ?? defaultDbPath();
1478
+ this.dir = deps.dir ?? FUNNEL_DIR;
1479
+ this.dbPath = deps.dbPath ?? defaultEventDbPath({
1480
+ tmpDir: deps.tmpDir ?? funnelTmpDir(),
1481
+ funnelDir: this.dir,
1482
+ port: this.configuredPort
1483
+ });
1460
1484
  this.process = deps.process;
1461
1485
  this.logger = deps.logger;
1462
1486
  this.onError = deps.onError ?? defaultOnError;
1463
1487
  this.selfPid = deps.selfPid ?? globalThis.process.pid;
1464
- this.dir = deps.dir ?? FUNNEL_DIR;
1465
1488
  this.killCompetingSlack = deps.killCompetingSlack ?? true;
1466
1489
  this.token = deps.token ?? "";
1467
1490
  this.allowInsecureHost = deps.allowInsecureHost ?? false;
@@ -1,6 +1,6 @@
1
- import { t as NodeFunnelFileSystem } from "./node-file-system-BOXIHW_Q.js";
2
- import { t as NodeFunnelProcessRunner } from "./node-process-runner-DxTvycoK.js";
3
- import { m as NodeFunnelIdGenerator, n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ccv291GV.js";
1
+ import { t as NodeFunnelFileSystem } from "./node-file-system-xJx7dymE.js";
2
+ import { t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js";
3
+ import { h as NodeFunnelIdGenerator, n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ZFWBhOnp.js";
4
4
  import { join } from "node:path";
5
5
  import { stringify } from "yaml";
6
6
  //#region lib/engine/claude/claude.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.66.0",
3
+ "version": "0.67.0",
4
4
  "description": "Hub CLI that routes external events (Slack / GitHub / Discord) to Claude Code agents through subscription channels over MCP.",
5
5
  "keywords": [
6
6
  "bun",
@@ -23,8 +23,8 @@
23
23
  "url": "git+https://github.com/interactive-inc/open-claude-funnel.git"
24
24
  },
25
25
  "bin": {
26
- "fnl": "./dist/bin.js",
27
- "funnel": "./dist/bin.js"
26
+ "fnl": "dist/bin.js",
27
+ "funnel": "dist/bin.js"
28
28
  },
29
29
  "files": [
30
30
  "dist/**/*",
@@ -122,18 +122,18 @@
122
122
  "prepack": "make build"
123
123
  },
124
124
  "dependencies": {
125
- "@hono/zod-validator": "0.8.0",
126
- "@interactive-inc/flume": "^0.10.0",
127
- "@modelcontextprotocol/sdk": "^1.29.0",
128
- "hono": "^4.12.19",
125
+ "@hono/zod-validator": "0.9.0",
126
+ "@interactive-inc/flume": "^0.10.1",
127
+ "@modelcontextprotocol/sdk": "^1.30.0",
128
+ "hono": "^4.12.32",
129
129
  "yaml": "^2.9.0",
130
130
  "zod": "^4.4.3"
131
131
  },
132
132
  "devDependencies": {
133
133
  "@types/bun": "^1.3.14",
134
- "@typescript/native-preview": "^7.0.0-dev.20260516.1",
135
- "vite-plus": "^0.1.21",
136
- "vitest": "^4.1.8"
134
+ "@typescript/native-preview": "^7.0.0-dev.20260707.2",
135
+ "vite-plus": "^0.2.6",
136
+ "vitest": "^4.1.10"
137
137
  },
138
138
  "engines": {
139
139
  "bun": ">=1.3.0"
@@ -1,138 +0,0 @@
1
- import { t as FunnelLogger } from "./logger-Bc_Ooypb.js";
2
- import { ServerWebSocket } from "bun";
3
-
4
- //#region lib/engine/error/on-funnel-error.d.ts
5
- /**
6
- * Host integration hook called when Funnel catches an exception that would
7
- * otherwise be silently swallowed (subscriber throw, listener start failure,
8
- * MCP forward failure, etc.). Pass `Sentry.captureException` from the host to
9
- * pipe these into your error reporter. Defaults to a no-op when omitted.
10
- *
11
- * `context` carries the component name and any extra metadata the caller had
12
- * at the catch site (channel / connector / subscriber id when available).
13
- */
14
- type OnFunnelError = (error: Error, context?: Record<string, unknown>) => void;
15
- //#endregion
16
- //#region lib/gateway/broadcaster.d.ts
17
- type ClientData = {
18
- /** Stable channel id (uuid) that the WS client subscribed to. */channel: string; /** Human-facing channel name resolved at upgrade time, kept for log readability. */
19
- channelName?: string | null; /** Connector names belonging to that channel. */
20
- connectors: string[]; /** Routing mode resolved from channel config at upgrade time. Defaults to fanout. */
21
- delivery?: "fanout" | "exclusive";
22
- /**
23
- * Opaque per-client id declared at upgrade time (`?id=<subscriberId>`). When an
24
- * event carries `meta.target`, only the client whose `subscriberId` equals it
25
- * receives the event among that channel's regular subscribers. Targeted delivery
26
- * is how a publisher addresses one specific instance (e.g. a single agent
27
- * session) without every subscriber having to receive and discard it.
28
- */
29
- subscriberId?: string;
30
- };
31
- type BroadcastEvent = {
32
- content: string;
33
- meta?: Record<string, string>;
34
- };
35
- type ReplayableEvent = BroadcastEvent & {
36
- offset: number;
37
- };
38
- type BroadcastSubscriber = (event: ReplayableEvent) => void;
39
- /**
40
- * Optional persistent replay source. Wired in by the gateway-server with a
41
- * `FunnelEventLog` (SQLite-backed by default) so reconnects across daemon
42
- * restarts can recover events older than the in-memory buffer via an indexed
43
- * `seq > since` range scan.
44
- */
45
- type ReplaySource = {
46
- loadSince(since: number): ReplayableEvent[];
47
- };
48
- type Deps = {
49
- logger?: FunnelLogger; /** Host hook for surfacing subscriber-throw exceptions. Defaults to no-op. */
50
- onError?: OnFunnelError;
51
- maxBufferedBytes?: number;
52
- now?: () => number; /** Number of recent events kept in the in-memory replay buffer. */
53
- replayBufferSize?: number; /** Hard byte cap on replay buffer payloads. Older events are evicted FIFO until under this cap. */
54
- replayBufferMaxBytes?: number; /** Persistent replay source consulted when the in-memory buffer cannot satisfy `since`. */
55
- persistentReplay?: ReplaySource;
56
- };
57
- type BroadcasterMetrics = {
58
- clients: number;
59
- subscribers: number;
60
- eventsBroadcast: number;
61
- droppedSlowClients: number;
62
- lastBroadcastAt: string | null; /** Latest emitted offset. Clients can `?since=<offset>` to ask for events strictly after this point. */
63
- latestOffset: number; /** Oldest offset still held in the replay buffer. Older values cannot be replayed and trigger a full resync. */
64
- oldestReplayableOffset: number | null;
65
- };
66
- /**
67
- * In-process pub/sub for connector events.
68
- *
69
- * Two outbound paths:
70
- * - WS clients connected via the gateway's `/ws` endpoint, scoped per channel
71
- * - In-process subscribers registered via `subscribe()` (programmable API)
72
- *
73
- * Backpressure: if a WS client's `bufferedAmount` exceeds `maxBufferedBytes`
74
- * (default 1 MiB), the client is closed with code 1009 and dropped from the
75
- * registry to keep one slow consumer from blocking the daemon.
76
- *
77
- * Replay: every emitted event gets a strictly increasing `offset`. The latest
78
- * `replayBufferSize` events are kept in memory; reconnecting WS clients can
79
- * pass `?since=<offset>` and the broadcaster resends matching events before
80
- * resuming the live stream. The in-memory ring covers short reconnects;
81
- * older history is served from the event log wired in as `persistentReplay`.
82
- */
83
- declare class FunnelBroadcaster {
84
- private readonly clients;
85
- private readonly subscribers;
86
- private readonly logger;
87
- private readonly onError;
88
- private readonly maxBufferedBytes;
89
- private readonly now;
90
- private readonly replayBufferSize;
91
- private readonly replayBufferMaxBytes;
92
- private readonly replayBuffer;
93
- private readonly persistentReplay;
94
- private readonly exclusiveCursor;
95
- private replayBufferBytes;
96
- private eventsBroadcast;
97
- private droppedSlowClients;
98
- private lastBroadcastAt;
99
- private latestOffset;
100
- constructor(deps?: Deps);
101
- getMetrics(): BroadcasterMetrics;
102
- /**
103
- * Returns events with offset > since, filtered by the connector subscription
104
- * rules of `data`. Used at WS upgrade time when the client passes `?since=<offset>`.
105
- *
106
- * Two-tier lookup:
107
- * 1. The in-memory ring buffer (covers short reconnects, last `replayBufferSize` events).
108
- * 2. If `since` predates the oldest in-memory entry and a persistent replay source
109
- * is wired in (SQLite by default), the gap is filled from it. This covers reconnects
110
- * across daemon restarts where the in-memory buffer was lost.
111
- *
112
- * Result is sorted ascending by offset and de-duplicated against the in-memory buffer.
113
- */
114
- replaySince(since: number, data: ClientData): ReplayableEvent[];
115
- private matchesClient;
116
- /**
117
- * Returns the list of WS clients that should receive `event`. For each per-channel group:
118
- * - fanout → every matching client receives
119
- * - exclusive → exactly one client receives, picked round-robin per channel
120
- *
121
- * `meta.target` narrows the recipient set via `matchesClient`: only the subscriber
122
- * whose `subscriberId` equals `target` receives a targeted event.
123
- */
124
- private pickRecipients;
125
- addClient(ws: ServerWebSocket<unknown>, data: ClientData): void;
126
- removeClient(ws: ServerWebSocket<unknown>): void;
127
- getClientCount(): number;
128
- listChannels(): {
129
- channel: string;
130
- connectors: string[];
131
- }[];
132
- subscribe(handler: BroadcastSubscriber): () => void;
133
- broadcast(content: string, meta?: Record<string, string>): ReplayableEvent;
134
- /** Forward-seed the offset counter (used at startup from the persisted event store). */
135
- seedLatestOffset(offset: number): void;
136
- }
137
- //#endregion
138
- export { OnFunnelError as a, ReplayableEvent as i, BroadcastSubscriber as n, FunnelBroadcaster as r, BroadcastEvent as t };
@@ -1,9 +0,0 @@
1
- //#region lib/engine/fs/file-system.ts
2
- /**
3
- * Filesystem boundary used everywhere funnel reads or writes.
4
- * Default is NodeFunnelFileSystem (real `node:fs`); MemoryFunnelFileSystem
5
- * provides a sandbox for tests and embedded use.
6
- */
7
- var FunnelFileSystem = class {};
8
- //#endregion
9
- export { FunnelFileSystem as t };
@@ -1,9 +0,0 @@
1
- //#region lib/engine/logger/logger.ts
2
- /**
3
- * Structured logger with three levels and an optional log-file path.
4
- * Defaults to NodeFunnelLogger (appends to `<os.tmpdir()>/funnel/funnel.log`);
5
- * MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
6
- */
7
- var FunnelLogger = class {};
8
- //#endregion
9
- export { FunnelLogger as t };
@@ -1,11 +0,0 @@
1
- //#region lib/engine/id/id-generator.ts
2
- /**
3
- * ID generator boundary. Default NodeFunnelIdGenerator wraps `crypto.randomUUID()`;
4
- * MemoryFunnelIdGenerator emits `<prefix>-1, <prefix>-2, ...` for deterministic tests.
5
- */
6
- var FunnelIdGenerator = class {};
7
- //#endregion
8
- //#region lib/engine/settings/settings-reader.ts
9
- var FunnelSettingsReader = class {};
10
- //#endregion
11
- export { FunnelIdGenerator as n, FunnelSettingsReader as t };