@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
package/dist/gateway.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { i as ReplayableEvent, n as BroadcastSubscriber, r as FunnelBroadcaster, t as BroadcastEvent } from "./broadcaster-DVNcw00K.js";
2
- import { C as ConnectorRawRecord, D as connectorConnectionEventSchema, E as StoredRawEvent, O as connectorProcessedEventSchema, S as ConnectorRawQuery, T as StoredProcessedEvent, _ as ConnectorProcessedEvent, b as ConnectorQuery, d as CONNECTOR_CONNECTION_STATUSES, f as ConnectorConnectionEvent, g as ConnectorDiagnosticLog, h as ConnectorConnectionStatus, k as connectorRawEventSchema, m as ConnectorConnectionRecord, p as ConnectorConnectionQuery, v as ConnectorProcessedQuery, w as StoredConnectionEvent, x as ConnectorRawEvent, y as ConnectorProcessedRecord } from "./connector-descriptor-CmyHlEiT.js";
3
- import { C as funnelEventSchema, D as FunnelListenerRegistry, E as GatewayRouteDeps, S as FunnelEventRecord, T as GatewayEmitInput, _ as channelWsUrl, a as SqliteFunnelEventLog, b as FunnelEvent, c as PublishResponse, d as publishResponseSchema, f as DEFAULT_GATEWAY_TOKEN_PATH, g as channelWsProtocols, h as ChannelWsUrlInput, i as MemoryFunnelEventLog, l as PublishResult, m as gatewayLoopbackUrl, n as MemoryConnectorDiagnosticLog, o as FunnelChannelPublisher, p as FunnelGatewayToken, r as SqliteConnectorDiagnosticLog, s as PublishRequest, t as GatewayApp, u as publishRequestSchema, v as FunnelGatewayServer, w as Env, x as FunnelEventLog, y as GatewayEventStore } from "./index-BU1TtuFy.js";
1
+ import { C as ConnectorRawRecord, D as connectorConnectionEventSchema, E as StoredRawEvent, O as connectorProcessedEventSchema, S as ConnectorRawQuery, T as StoredProcessedEvent, _ as ConnectorProcessedEvent, b as ConnectorQuery, d as CONNECTOR_CONNECTION_STATUSES, f as ConnectorConnectionEvent, g as ConnectorDiagnosticLog, h as ConnectorConnectionStatus, k as connectorRawEventSchema, m as ConnectorConnectionRecord, p as ConnectorConnectionQuery, v as ConnectorProcessedQuery, w as StoredConnectionEvent, x as ConnectorRawEvent, y as ConnectorProcessedRecord } from "./connector-descriptor-F75ZI8Fh.js";
2
+ import { A as FunnelBroadcaster, C as funnelEventSchema, D as FunnelListenerRegistry, E as GatewayRouteDeps, O as BroadcastEvent, S as FunnelEventRecord, T as GatewayEmitInput, _ as channelWsUrl, a as SqliteFunnelEventLog, b as FunnelEvent, c as PublishResponse, d as publishResponseSchema, f as DEFAULT_GATEWAY_TOKEN_PATH, g as channelWsProtocols, h as ChannelWsUrlInput, i as MemoryFunnelEventLog, j as ReplayableEvent, k as BroadcastSubscriber, l as PublishResult, m as gatewayLoopbackUrl, n as MemoryConnectorDiagnosticLog, o as FunnelChannelPublisher, p as FunnelGatewayToken, r as SqliteConnectorDiagnosticLog, s as PublishRequest, t as GatewayApp, u as publishRequestSchema, v as FunnelGatewayServer, w as Env, x as FunnelEventLog, y as GatewayEventStore } from "./index-B4RvEaW-.js";
4
3
  export { BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, ChannelWsUrlInput, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDiagnosticLog, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, DEFAULT_GATEWAY_TOKEN_PATH, FunnelBroadcaster, FunnelChannelPublisher, FunnelEvent, FunnelEventLog, FunnelEventRecord, FunnelGatewayServer, FunnelGatewayToken, FunnelListenerRegistry, type GatewayApp, type GatewayEmitInput, GatewayEventStore, type GatewayRouteDeps, type Env as GatewayServerEnv, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, PublishRequest, PublishResponse, PublishResult, ReplayableEvent, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, channelWsProtocols, channelWsUrl, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, gatewayLoopbackUrl, publishRequestSchema, publishResponseSchema };
package/dist/gateway.js CHANGED
@@ -1,3 +1,3 @@
1
- import { n as gatewayLoopbackUrl } from "./loopback-fetch-CVNuN3YZ.js";
2
- import { S as connectorRawEventSchema, _ as MemoryConnectorDiagnosticLog, a as DEFAULT_GATEWAY_TOKEN_PATH, b as connectorConnectionEventSchema, c as FunnelListenerRegistry, d as funnelEventSchema, f as FunnelBroadcaster, g as publishResponseSchema, h as publishRequestSchema, i as channelWsUrl, l as SqliteFunnelEventLog, m as FunnelChannelPublisher, n as MemoryFunnelEventLog, o as FunnelGatewayToken, r as channelWsProtocols, s as FunnelGatewayServer, t as SqliteConnectorDiagnosticLog, u as FunnelEventLog, v as CONNECTOR_CONNECTION_STATUSES, x as connectorProcessedEventSchema, y as ConnectorDiagnosticLog } from "./sqlite-diagnostic-log-CwhXE9Qh.js";
1
+ import { n as gatewayLoopbackUrl } from "./loopback-fetch-HP-bo9Kv.js";
2
+ import { S as connectorRawEventSchema, _ as MemoryConnectorDiagnosticLog, a as DEFAULT_GATEWAY_TOKEN_PATH, b as connectorConnectionEventSchema, c as FunnelListenerRegistry, d as funnelEventSchema, f as FunnelBroadcaster, g as publishResponseSchema, h as publishRequestSchema, i as channelWsUrl, l as SqliteFunnelEventLog, m as FunnelChannelPublisher, n as MemoryFunnelEventLog, o as FunnelGatewayToken, r as channelWsProtocols, s as FunnelGatewayServer, t as SqliteConnectorDiagnosticLog, u as FunnelEventLog, v as CONNECTOR_CONNECTION_STATUSES, x as connectorProcessedEventSchema, y as ConnectorDiagnosticLog } from "./sqlite-diagnostic-log-BDxfXGZy.js";
3
3
  export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, DEFAULT_GATEWAY_TOKEN_PATH, FunnelBroadcaster, FunnelChannelPublisher, FunnelEventLog, FunnelGatewayServer, FunnelGatewayToken, FunnelListenerRegistry, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, channelWsProtocols, channelWsUrl, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, gatewayLoopbackUrl, publishRequestSchema, publishResponseSchema };
@@ -1,8 +1,8 @@
1
- import { t as NodeFunnelProcessRunner } from "./node-process-runner-DxTvycoK.js";
2
- import { t as errorMessageOf } from "./error-message-of-ColuYmAk.js";
3
- import { t as ghConnectorSchema } from "./gh-connector-schema-CAqIhzGr.js";
4
- import { t as FunnelConnectorAdapter } from "./connector-adapter-Dvs8N7ew.js";
5
- import { i as resolveFlumeDeps, n as FunnelFlumeSourceListener, r as flumeLogHandler, t as slotFields } from "./slot-fields-D-pvMgTK.js";
1
+ import { t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js";
2
+ import { t as errorMessageOf } from "./error-message-of-BG4ezZ_s.js";
3
+ import { t as ghConnectorSchema } from "./gh-connector-schema-DmZTrzUu.js";
4
+ import { t as FunnelConnectorAdapter } from "./connector-adapter-BL2ehMej.js";
5
+ import { i as resolveFlumeDeps, n as FunnelFlumeSourceListener, r as flumeLogHandler, t as slotFields } from "./slot-fields-5ERhytIA.js";
6
6
  import { FlumeGitHubSource } from "@interactive-inc/flume/github";
7
7
  //#region lib/engine/connectors/gh-adapter.ts
8
8
  const defaultProcess$1 = new NodeFunnelProcessRunner();
@@ -1,5 +1,4 @@
1
1
  import { z } from "zod";
2
-
3
2
  //#region lib/engine/connectors/gh-connector-schema.d.ts
4
3
  declare const ghConnectorSchema: z.ZodObject<{
5
4
  id: z.ZodString;
@@ -1,14 +1,154 @@
1
- import { n as FunnelClock, t as FunnelLogger } from "./logger-Bc_Ooypb.js";
2
- import { n as FunnelFileSystem } from "./file-system-DHgbuTFb.js";
3
- import { a as OnFunnelError, i as ReplayableEvent, n as BroadcastSubscriber, r as FunnelBroadcaster } from "./broadcaster-DVNcw00K.js";
4
- import { A as FunnelConnectorListener, C as ConnectorRawRecord, E as StoredRawEvent, F as BaseConnectorConfig, S as ConnectorRawQuery, T as StoredProcessedEvent, g as ConnectorDiagnosticLog, m as ConnectorConnectionRecord, p as ConnectorConnectionQuery, v as ConnectorProcessedQuery, w as StoredConnectionEvent, y as ConnectorProcessedRecord, z as FunnelProcessRunner } from "./connector-descriptor-CmyHlEiT.js";
5
- import { n as ChannelConnectorView, r as FunnelChannels } from "./channels-DR90RmUP.js";
1
+ import { n as FunnelClock, t as FunnelLogger } from "./logger-mMZvblTx.js";
2
+ import { n as FunnelFileSystem } from "./file-system-BNtl997T.js";
3
+ import { A as FunnelConnectorListener, C as ConnectorRawRecord, E as StoredRawEvent, F as BaseConnectorConfig, S as ConnectorRawQuery, T as StoredProcessedEvent, g as ConnectorDiagnosticLog, m as ConnectorConnectionRecord, p as ConnectorConnectionQuery, v as ConnectorProcessedQuery, w as StoredConnectionEvent, y as ConnectorProcessedRecord, z as FunnelProcessRunner } from "./connector-descriptor-F75ZI8Fh.js";
4
+ import { n as ChannelConnectorView, r as FunnelChannels } from "./channels-BBA3GTAa.js";
6
5
  import { z } from "zod";
7
6
  import { Hono } from "hono";
8
- import * as _$hono_utils_http_status0 from "hono/utils/http-status";
9
- import * as _$hono_utils_types0 from "hono/utils/types";
10
- import * as _$hono_hono_base0 from "hono/hono-base";
11
-
7
+ import { ServerWebSocket } from "bun";
8
+ //#region lib/engine/error/on-funnel-error.d.ts
9
+ /**
10
+ * Host integration hook called when Funnel catches an exception that would
11
+ * otherwise be silently swallowed (subscriber throw, listener start failure,
12
+ * MCP forward failure, etc.). Pass `Sentry.captureException` from the host to
13
+ * pipe these into your error reporter. Defaults to a no-op when omitted.
14
+ *
15
+ * `context` carries the component name and any extra metadata the caller had
16
+ * at the catch site (channel / connector / subscriber id when available).
17
+ */
18
+ type OnFunnelError = (error: Error, context?: Record<string, unknown>) => void;
19
+ //#endregion
20
+ //#region lib/gateway/broadcaster.d.ts
21
+ type ClientData = {
22
+ /** Stable channel id (uuid) that the WS client subscribed to. */
23
+ channel: string;
24
+ /** Human-facing channel name resolved at upgrade time, kept for log readability. */
25
+ channelName?: string | null;
26
+ /** Connector names belonging to that channel. */
27
+ connectors: string[];
28
+ /** Routing mode resolved from channel config at upgrade time. Defaults to fanout. */
29
+ delivery?: "fanout" | "exclusive";
30
+ /**
31
+ * Opaque per-client id declared at upgrade time (`?id=<subscriberId>`). When an
32
+ * event carries `meta.target`, only the client whose `subscriberId` equals it
33
+ * receives the event among that channel's regular subscribers. Targeted delivery
34
+ * is how a publisher addresses one specific instance (e.g. a single agent
35
+ * session) without every subscriber having to receive and discard it.
36
+ */
37
+ subscriberId?: string;
38
+ };
39
+ type BroadcastEvent = {
40
+ content: string;
41
+ meta?: Record<string, string>;
42
+ };
43
+ type ReplayableEvent = BroadcastEvent & {
44
+ offset: number;
45
+ };
46
+ type BroadcastSubscriber = (event: ReplayableEvent) => void;
47
+ /**
48
+ * Optional persistent replay source. Wired in by the gateway-server with a
49
+ * `FunnelEventLog` (SQLite-backed by default) so reconnects across daemon
50
+ * restarts can recover events older than the in-memory buffer via an indexed
51
+ * `seq > since` range scan.
52
+ */
53
+ type ReplaySource = {
54
+ loadSince(since: number): ReplayableEvent[];
55
+ };
56
+ type Deps$4 = {
57
+ logger?: FunnelLogger;
58
+ /** Host hook for surfacing subscriber-throw exceptions. Defaults to no-op. */
59
+ onError?: OnFunnelError;
60
+ maxBufferedBytes?: number;
61
+ now?: () => number;
62
+ /** Number of recent events kept in the in-memory replay buffer. */
63
+ replayBufferSize?: number;
64
+ /** Hard byte cap on replay buffer payloads. Older events are evicted FIFO until under this cap. */
65
+ replayBufferMaxBytes?: number;
66
+ /** Persistent replay source consulted when the in-memory buffer cannot satisfy `since`. */
67
+ persistentReplay?: ReplaySource;
68
+ };
69
+ type BroadcasterMetrics = {
70
+ clients: number;
71
+ subscribers: number;
72
+ eventsBroadcast: number;
73
+ droppedSlowClients: number;
74
+ lastBroadcastAt: string | null;
75
+ /** Latest emitted offset. Clients can `?since=<offset>` to ask for events strictly after this point. */
76
+ latestOffset: number;
77
+ /** Oldest offset still held in the replay buffer. Older values cannot be replayed and trigger a full resync. */
78
+ oldestReplayableOffset: number | null;
79
+ };
80
+ /**
81
+ * In-process pub/sub for connector events.
82
+ *
83
+ * Two outbound paths:
84
+ * - WS clients connected via the gateway's `/ws` endpoint, scoped per channel
85
+ * - In-process subscribers registered via `subscribe()` (programmable API)
86
+ *
87
+ * Backpressure: if a WS client's `bufferedAmount` exceeds `maxBufferedBytes`
88
+ * (default 1 MiB), the client is closed with code 1009 and dropped from the
89
+ * registry to keep one slow consumer from blocking the daemon.
90
+ *
91
+ * Replay: every emitted event gets a strictly increasing `offset`. The latest
92
+ * `replayBufferSize` events are kept in memory; reconnecting WS clients can
93
+ * pass `?since=<offset>` and the broadcaster resends matching events before
94
+ * resuming the live stream. The in-memory ring covers short reconnects;
95
+ * older history is served from the event log wired in as `persistentReplay`.
96
+ */
97
+ declare class FunnelBroadcaster {
98
+ private readonly clients;
99
+ private readonly subscribers;
100
+ private readonly logger;
101
+ private readonly onError;
102
+ private readonly maxBufferedBytes;
103
+ private readonly now;
104
+ private readonly replayBufferSize;
105
+ private readonly replayBufferMaxBytes;
106
+ private readonly replayBuffer;
107
+ private readonly persistentReplay;
108
+ private readonly exclusiveCursor;
109
+ private replayBufferBytes;
110
+ private eventsBroadcast;
111
+ private droppedSlowClients;
112
+ private lastBroadcastAt;
113
+ private latestOffset;
114
+ constructor(deps?: Deps$4);
115
+ getMetrics(): BroadcasterMetrics;
116
+ /**
117
+ * Returns events with offset > since, filtered by the connector subscription
118
+ * rules of `data`. Used at WS upgrade time when the client passes `?since=<offset>`.
119
+ *
120
+ * Two-tier lookup:
121
+ * 1. The in-memory ring buffer (covers short reconnects, last `replayBufferSize` events).
122
+ * 2. If `since` predates the oldest in-memory entry and a persistent replay source
123
+ * is wired in (SQLite by default), the gap is filled from it. This covers reconnects
124
+ * across daemon restarts where the in-memory buffer was lost.
125
+ *
126
+ * Result is sorted ascending by offset and de-duplicated against the in-memory buffer.
127
+ */
128
+ replaySince(since: number, data: ClientData): ReplayableEvent[];
129
+ private matchesClient;
130
+ /**
131
+ * Returns the list of WS clients that should receive `event`. For each per-channel group:
132
+ * - fanout → every matching client receives
133
+ * - exclusive → exactly one client receives, picked round-robin per channel
134
+ *
135
+ * `meta.target` narrows the recipient set via `matchesClient`: only the subscriber
136
+ * whose `subscriberId` equals `target` receives a targeted event.
137
+ */
138
+ private pickRecipients;
139
+ addClient(ws: ServerWebSocket<unknown>, data: ClientData): void;
140
+ removeClient(ws: ServerWebSocket<unknown>): void;
141
+ getClientCount(): number;
142
+ listChannels(): {
143
+ channel: string;
144
+ connectors: string[];
145
+ }[];
146
+ subscribe(handler: BroadcastSubscriber): () => void;
147
+ broadcast(content: string, meta?: Record<string, string>): ReplayableEvent;
148
+ /** Forward-seed the offset counter (used at startup from the persisted event store). */
149
+ seedLatestOffset(offset: number): void;
150
+ }
151
+ //#endregion
12
152
  //#region lib/gateway/listener-registry.d.ts
13
153
  type ConnectorRegistry = {
14
154
  listAllConnectors(): ChannelConnectorView[];
@@ -22,7 +162,8 @@ type ListenerRegistryNotify = (channelName: string, connectorName: string, conte
22
162
  type Deps$3 = {
23
163
  channels: ConnectorRegistry;
24
164
  notify: ListenerRegistryNotify;
25
- logger?: FunnelLogger; /** Host hook for surfacing listener lifecycle exceptions. Defaults to no-op. */
165
+ logger?: FunnelLogger;
166
+ /** Host hook for surfacing listener lifecycle exceptions. Defaults to no-op. */
26
167
  onError?: OnFunnelError;
27
168
  healthCheckIntervalMs?: number;
28
169
  maxBackoffMs?: number;
@@ -190,7 +331,7 @@ declare abstract class FunnelEventLog {
190
331
  * mutually exclusive — modeled as a union so you can't pass both (the old shape
191
332
  * silently ignored `dbPath` when `eventLog` was also given).
192
333
  *
193
- * - omit both → SQLite at the default path (`<os.tmpdir()>/funnel/events.db`)
334
+ * - omit both → SQLite under `<tmpDir>/events/`, isolated by funnel dir + port
194
335
  * - `dbPath` → SQLite at a custom path (parent dir created on demand)
195
336
  * - `eventLog` → bring your own `FunnelEventLog` (e.g. `MemoryFunnelEventLog`)
196
337
  */
@@ -203,15 +344,21 @@ type GatewayEventStore = {
203
344
  };
204
345
  type Deps$2 = GatewayEventStore & {
205
346
  channels: FunnelChannels;
206
- port?: number; /** Bind address for `Bun.serve`. Defaults to `127.0.0.1` (loopback only). Set to `0.0.0.0` to expose on the network. */
347
+ port?: number;
348
+ /** Bind address for `Bun.serve`. Defaults to `127.0.0.1` (loopback only). Set to `0.0.0.0` to expose on the network. */
207
349
  hostname?: string;
208
350
  process?: FunnelProcessRunner;
209
351
  clock?: FunnelClock;
210
- logger?: FunnelLogger; /** Host hook for surfacing internal exceptions (broadcaster / supervisor). Defaults to no-op. */
352
+ logger?: FunnelLogger;
353
+ /** Host hook for surfacing internal exceptions (broadcaster / supervisor). Defaults to no-op. */
211
354
  onError?: OnFunnelError;
212
- selfPid?: number; /** Funnel home dir, used to scope kill-competing to daemons rooted at the same dir. Defaults to FUNNEL_DIR. */
355
+ selfPid?: number;
356
+ /** Funnel home dir, used to scope kill-competing to daemons rooted at the same dir. Defaults to FUNNEL_DIR. */
213
357
  dir?: string;
214
- killCompetingSlack?: boolean; /** Bearer token required for `/listeners*`, `/status`, and `/ws`. Empty string disables auth (tests only). */
358
+ /** Runtime directory used by the default replay database. Defaults to `funnelTmpDir()`. */
359
+ tmpDir?: string;
360
+ killCompetingSlack?: boolean;
361
+ /** Bearer token required for `/listeners*`, `/status`, and `/ws`. Empty string disables auth (tests only). */
215
362
  token?: string;
216
363
  /**
217
364
  * Permit binding a non-loopback hostname without a token. Off by default:
@@ -344,9 +491,13 @@ declare class FunnelGatewayServer {
344
491
  * gateway requires a token.
345
492
  */
346
493
  type ChannelWsUrlInput = {
347
- /** Base WS endpoint, e.g. `ws://localhost:9743/ws`. Existing query is preserved. */base: string; /** Channel name to subscribe to. Required — the broadcaster filters by it. */
348
- channel: string; /** Opaque subscriber id for targeted delivery (`meta.target=<id>`). Omit for fanout. */
349
- subscriberId?: string; /** Replay from this event offset (inclusive). Omit to receive only new events. */
494
+ /** Base WS endpoint, e.g. `ws://localhost:9743/ws`. Existing query is preserved. */
495
+ base: string;
496
+ /** Channel name to subscribe to. Required the broadcaster filters by it. */
497
+ channel: string;
498
+ /** Opaque subscriber id for targeted delivery (`meta.target=<id>`). Omit for fanout. */
499
+ subscriberId?: string;
500
+ /** Replay from this event offset (inclusive). Omit to receive only new events. */
350
501
  since?: number;
351
502
  };
352
503
  declare function channelWsUrl(input: ChannelWsUrlInput): string;
@@ -436,7 +587,8 @@ type PublishResult = {
436
587
  //#region lib/gateway/channel-publisher.d.ts
437
588
  type Deps = {
438
589
  port: number;
439
- isDaemonRunning: () => boolean; /** Returns the daemon's gateway token, or null if unavailable. Sent as `Authorization: Bearer`. */
590
+ isDaemonRunning: () => boolean;
591
+ /** Returns the daemon's gateway token, or null if unavailable. Sent as `Authorization: Bearer`. */
440
592
  getToken?: () => string | null;
441
593
  };
442
594
  /**
@@ -455,18 +607,25 @@ declare class FunnelChannelPublisher {
455
607
  //#endregion
456
608
  //#region lib/gateway/event-log/sqlite-event-log.d.ts
457
609
  type Props$1 = {
458
- /** SQLite database file path. Created on first write. ":memory:" for tests. */path: string; /** Override for tests. Defaults to `Date.now`. */
459
- now?: () => number; /** Surfaces a failed persist (PK collision, disk-full, locked WAL). Silent if absent. */
610
+ /** SQLite database file path. Created on first write. ":memory:" for tests. */
611
+ path: string;
612
+ /** Override for tests. Defaults to `Date.now`. */
613
+ now?: () => number;
614
+ /** Surfaces a failed persist (PK collision, disk-full, locked WAL). Silent if absent. */
460
615
  logger?: FunnelLogger;
461
616
  /**
462
617
  * Host-supplied error sink. Routed alongside the logger when a write
463
618
  * fails, so Sentry / Datadog / a custom alert pipeline sees the durable
464
619
  * replay loss too — not just the local log file. Silent if absent.
465
620
  */
466
- onError?: OnFunnelError; /** Optional row cap. Pruned on every insert. */
467
- maxRows?: number; /** Optional age cap in ms. Pruned on every insert. */
468
- maxAgeMs?: number; /** Optional on-disk byte cap. Checked periodically; on overflow the oldest rows are dropped toward targetBytes and the file is VACUUMed. */
469
- maxBytes?: number; /** Shrink target when maxBytes is exceeded. Defaults to maxBytes/4. */
621
+ onError?: OnFunnelError;
622
+ /** Optional row cap. Pruned on every insert. */
623
+ maxRows?: number;
624
+ /** Optional age cap in ms. Pruned on every insert. */
625
+ maxAgeMs?: number;
626
+ /** Optional on-disk byte cap. Checked periodically; on overflow the oldest rows are dropped toward targetBytes and the file is VACUUMed. */
627
+ maxBytes?: number;
628
+ /** Shrink target when maxBytes is exceeded. Defaults to maxBytes/4. */
470
629
  targetBytes?: number;
471
630
  };
472
631
  /**
@@ -540,18 +699,24 @@ declare class MemoryFunnelEventLog extends FunnelEventLog {
540
699
  //#endregion
541
700
  //#region lib/engine/diagnostic-log/sqlite-diagnostic-log.d.ts
542
701
  type Props = {
543
- /** SQLite file for the raw (pre-filter) table. ":memory:" for tests. */rawPath: string; /** SQLite file for the processed (verdict) table. ":memory:" for tests. */
544
- processedPath: string; /** SQLite file for the connection (lifecycle) table. ":memory:" for tests. */
702
+ /** SQLite file for the raw (pre-filter) table. ":memory:" for tests. */
703
+ rawPath: string;
704
+ /** SQLite file for the processed (verdict) table. ":memory:" for tests. */
705
+ processedPath: string;
706
+ /** SQLite file for the connection (lifecycle) table. ":memory:" for tests. */
545
707
  connectionPath: string;
546
- now?: () => number; /** Row cap for the processed and connection tables. Pruned on every insert. */
708
+ now?: () => number;
709
+ /** Row cap for the processed and connection tables. Pruned on every insert. */
547
710
  maxRows?: number;
548
711
  /**
549
712
  * Row cap for the raw table specifically. Raw rows can each hold up to
550
713
  * `RAW_PAYLOAD_CAP` bytes, so they want a tighter cap than the small
551
714
  * processed/connection verdict rows. Defaults to `maxRows` when unset.
552
715
  */
553
- rawMaxRows?: number; /** Age cap in ms for all tables — bounds how long untouched payloads (with PII) live. Pruned on every insert. */
554
- maxAgeMs?: number; /** When set, `insert()` errors (disk full, WAL lock) are logged instead of silently dropped. */
716
+ rawMaxRows?: number;
717
+ /** Age cap in ms for all tables bounds how long untouched payloads (with PII) live. Pruned on every insert. */
718
+ maxAgeMs?: number;
719
+ /** When set, `insert()` errors (disk full, WAL lock) are logged instead of silently dropped. */
555
720
  logger?: FunnelLogger;
556
721
  };
557
722
  /**
@@ -621,7 +786,7 @@ declare class MemoryConnectorDiagnosticLog extends ConnectorDiagnosticLog {
621
786
  * shape as CLI's `c.var.funnel`.
622
787
  */
623
788
  type GatewayApp = ReturnType<typeof buildGatewayRoutes>;
624
- declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
789
+ declare function buildGatewayRoutes(): import("hono/hono-base").HonoBase<Env, {
625
790
  "/health": {
626
791
  $get: {
627
792
  input: {};
@@ -643,7 +808,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
643
808
  }[];
644
809
  };
645
810
  outputFormat: "json";
646
- status: _$hono_utils_http_status0.ContentfulStatusCode;
811
+ status: import("hono/utils/http-status").ContentfulStatusCode;
647
812
  };
648
813
  };
649
814
  } & {
@@ -681,7 +846,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
681
846
  };
682
847
  };
683
848
  outputFormat: "json";
684
- status: _$hono_utils_http_status0.ContentfulStatusCode;
849
+ status: import("hono/utils/http-status").ContentfulStatusCode;
685
850
  };
686
851
  };
687
852
  } & {
@@ -710,7 +875,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
710
875
  outcome: string;
711
876
  payload: string | null;
712
877
  payloadParsed: {
713
- [x: string]: _$hono_utils_types0.JSONValue;
878
+ [x: string]: import("hono/utils/types").JSONValue;
714
879
  } | null;
715
880
  preview: string | null;
716
881
  }[];
@@ -729,7 +894,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
729
894
  }[];
730
895
  };
731
896
  outputFormat: "json";
732
- status: _$hono_utils_http_status0.ContentfulStatusCode;
897
+ status: import("hono/utils/http-status").ContentfulStatusCode;
733
898
  };
734
899
  };
735
900
  } & {
@@ -750,7 +915,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
750
915
  }[];
751
916
  };
752
917
  outputFormat: "json";
753
- status: _$hono_utils_http_status0.ContentfulStatusCode;
918
+ status: import("hono/utils/http-status").ContentfulStatusCode;
754
919
  };
755
920
  };
756
921
  } & {
@@ -870,10 +1035,10 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
870
1035
  };
871
1036
  output: {
872
1037
  ok: true;
873
- result: _$hono_utils_types0.JSONValue;
1038
+ result: import("hono/utils/types").JSONValue;
874
1039
  };
875
1040
  outputFormat: "json";
876
- status: _$hono_utils_http_status0.ContentfulStatusCode;
1041
+ status: import("hono/utils/http-status").ContentfulStatusCode;
877
1042
  };
878
1043
  };
879
1044
  } & {
@@ -934,9 +1099,9 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
934
1099
  offset: number;
935
1100
  };
936
1101
  outputFormat: "json";
937
- status: _$hono_utils_http_status0.ContentfulStatusCode;
1102
+ status: import("hono/utils/http-status").ContentfulStatusCode;
938
1103
  };
939
1104
  };
940
1105
  }, "/", "/channels/:channel/publish">;
941
1106
  //#endregion
942
- export { funnelEventSchema as C, FunnelListenerRegistry as D, GatewayRouteDeps as E, FunnelEventRecord as S, GatewayEmitInput as T, channelWsUrl as _, SqliteFunnelEventLog as a, FunnelEvent as b, PublishResponse as c, publishResponseSchema as d, DEFAULT_GATEWAY_TOKEN_PATH as f, channelWsProtocols as g, ChannelWsUrlInput as h, MemoryFunnelEventLog as i, PublishResult as l, gatewayLoopbackUrl as m, MemoryConnectorDiagnosticLog as n, FunnelChannelPublisher as o, FunnelGatewayToken as p, SqliteConnectorDiagnosticLog as r, PublishRequest as s, GatewayApp as t, publishRequestSchema as u, FunnelGatewayServer as v, Env as w, FunnelEventLog as x, GatewayEventStore as y };
1107
+ export { FunnelBroadcaster as A, funnelEventSchema as C, FunnelListenerRegistry as D, GatewayRouteDeps as E, OnFunnelError as M, BroadcastEvent as O, FunnelEventRecord as S, GatewayEmitInput as T, channelWsUrl as _, SqliteFunnelEventLog as a, FunnelEvent as b, PublishResponse as c, publishResponseSchema as d, DEFAULT_GATEWAY_TOKEN_PATH as f, channelWsProtocols as g, ChannelWsUrlInput as h, MemoryFunnelEventLog as i, ReplayableEvent as j, BroadcastSubscriber as k, PublishResult as l, gatewayLoopbackUrl as m, MemoryConnectorDiagnosticLog as n, FunnelChannelPublisher as o, FunnelGatewayToken as p, SqliteConnectorDiagnosticLog as r, PublishRequest as s, GatewayApp as t, publishRequestSchema as u, FunnelGatewayServer as v, Env as w, FunnelEventLog as x, GatewayEventStore as y };