@interactive-inc/claude-funnel 0.59.1 → 0.60.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 (85) hide show
  1. package/README.md +9 -3
  2. package/dist/bin.js +549 -487
  3. package/dist/channels-2g_BU1N0.d.ts +174 -0
  4. package/dist/claude.d.ts +9 -5
  5. package/dist/claude.js +54 -17
  6. package/dist/{diagnostic-log-Cb3v8P7p.d.ts → connector-descriptor-6SXJoszo.d.ts} +158 -2
  7. package/dist/connectors/discord.d.ts +30 -4
  8. package/dist/connectors/discord.js +2 -2
  9. package/dist/connectors/gh.d.ts +21 -5
  10. package/dist/connectors/gh.js +3 -3
  11. package/dist/connectors/schedule.d.ts +124 -2
  12. package/dist/connectors/schedule.js +3 -3
  13. package/dist/connectors/slack.d.ts +149 -5
  14. package/dist/connectors/slack.js +2 -2
  15. package/dist/{diagnostic-sql-reader-CzYgZpq2.js → diagnostic-sql-reader-C9zR-Csp.js} +5 -5
  16. package/dist/diagnostics.d.ts +1 -1
  17. package/dist/diagnostics.js +1 -1
  18. package/dist/{discord-listener-CKsZGTnH.js → discord-connector-BL36yvbL.js} +60 -37
  19. package/dist/docs.d.ts +1 -1
  20. package/dist/docs.js +1 -1
  21. package/dist/doctor.d.ts +1 -1
  22. package/dist/doctor.js +1 -1
  23. package/dist/error-message-of-Byi4y0Uf.js +9 -0
  24. package/dist/{file-process-guard-JhFpmHYo.d.ts → file-process-guard-DOlCr4GF.d.ts} +4 -5
  25. package/dist/{funnel-diagnostics-BpKYrMSu.js → funnel-diagnostics-CSiJmPlZ.js} +19 -2
  26. package/dist/{funnel-diagnostics-K-wON25Y.d.ts → funnel-diagnostics-DpXOsCty.d.ts} +3 -3
  27. package/dist/{funnel-docs-ng5K8w4j.js → funnel-docs-BxXZ9Ksx.js} +76 -3
  28. package/dist/{funnel-docs-DYBs1-H_.d.ts → funnel-docs-CNklHvbt.d.ts} +1 -1
  29. package/dist/{funnel-doctor-vxO96TCA.d.ts → funnel-doctor-CZf_0Luq.d.ts} +2 -2
  30. package/dist/{funnel-recovery-COExL9MD.d.ts → funnel-recovery-DnLrdWO9.d.ts} +1 -1
  31. package/dist/gateway/daemon.js +326 -266
  32. package/dist/gateway-base-url-Dy4Ykuoh.js +14 -0
  33. package/dist/gateway.d.ts +2 -2
  34. package/dist/gateway.js +2 -2
  35. package/dist/{gh-listener-B2I4s8qh.js → gh-connector-DpiixfQZ.js} +53 -5
  36. package/dist/gh-connector-schema-Rzwc1c1N.js +12 -0
  37. package/dist/http-client-oICicjuO.d.ts +18 -0
  38. package/dist/index-CgY8NdMz.d.ts +1057 -0
  39. package/dist/index.d.ts +1558 -17
  40. package/dist/index.js +374 -342
  41. package/dist/{local-config-json-schema-DE1zkMcb.js → local-config-json-schema-JyLqOQNX.js} +9 -5
  42. package/dist/local-config-sync-Dh1Croqe.d.ts +169 -0
  43. package/dist/local-config.d.ts +2 -2
  44. package/dist/local-config.js +2 -2
  45. package/dist/logger.js +1 -1
  46. package/dist/{memory-diagnostic-log-B9Us7X05.js → memory-diagnostic-log-CI60kNfB.js} +33 -18
  47. package/dist/{memory-token-prompter-CcShtF8B.d.ts → memory-token-prompter-B4sjyaAq.d.ts} +2 -2
  48. package/dist/{memory-token-prompter-C7vREzCL.js → memory-token-prompter-CZde7e6y.js} +1 -1
  49. package/dist/{node-file-system-BcrmWN9I.js → node-file-system-Blr8pAir.js} +1 -1
  50. package/dist/node-http-client-lowp60Oa.js +25 -0
  51. package/dist/{gh-connector-schema-ClPLSYD9.js → node-process-runner-DxTvycoK.js} +1 -12
  52. package/dist/{profiles-g2qGVOWv.d.ts → profiles-Cy5wXQ0L.d.ts} +3 -3
  53. package/dist/{profiles-MnXvYfZF.js → profiles-DSzTeKQw.js} +1 -1
  54. package/dist/profiles.d.ts +1 -1
  55. package/dist/profiles.js +1 -1
  56. package/dist/recovery.d.ts +1 -1
  57. package/dist/recovery.js +1 -1
  58. package/dist/{schedule-listener-DP9Jhc6U.js → schedule-connector-L4uzg5M8.js} +109 -9
  59. package/dist/{settings-reader-DPwqOVUm.d.ts → settings-reader-BIFB_j2f.d.ts} +1 -1
  60. package/dist/settings-schema-D1xcOqRu.d.ts +78 -0
  61. package/dist/{gateway-base-url-DxVjjDoW.js → settings-store-CUKSeTXC.js} +27 -29
  62. package/dist/{slack-listener-C4wlZaOq.js → slack-connector-DQIFPdBF.js} +67 -12
  63. package/dist/slot-fields-CMoRpwuy.js +45 -0
  64. package/dist/{yaml-render-cZu6CxkE.js → yaml-render-qW34NlYz.js} +4 -4
  65. package/package.json +1 -1
  66. package/dist/connector-adapter-DGacCppE.d.ts +0 -25
  67. package/dist/discord-connector-schema-CQyfDkLD.d.ts +0 -39
  68. package/dist/gh-connector-schema-CZzwzvqY.d.ts +0 -14
  69. package/dist/index-D7mjirUL.d.ts +0 -3602
  70. package/dist/local-config-sync-BGPAS9Be.d.ts +0 -401
  71. package/dist/process-runner-DIm1cy95.d.ts +0 -52
  72. package/dist/resolve-connector-token-CczqG_Ig.js +0 -22
  73. package/dist/schedule-listener-DoMPjHZj.d.ts +0 -112
  74. package/dist/settings-schema-1hh11jnN.d.ts +0 -152
  75. package/dist/slack-listener-Dj9NFbAJ.d.ts +0 -136
  76. /package/dist/{connector-adapter-qwXLjQId.js → connector-adapter-DU9Rvyec.js} +0 -0
  77. /package/dist/{connector-listener-CpHBecCj.js → connector-listener-DR3aKOuK.js} +0 -0
  78. /package/dist/{file-system-PWKKU7lA.js → file-system-Wvzc2ePY.js} +0 -0
  79. /package/dist/{file-system-DxpnnUVb.d.ts → file-system-o51IsM0W.d.ts} +0 -0
  80. /package/dist/{funnel-doctor-CApCezTq.js → funnel-doctor-DiJCjHsg.js} +0 -0
  81. /package/dist/{funnel-log-sqlite-sink-B_5_4ybn.js → funnel-log-sqlite-sink-kqJbx2H7.js} +0 -0
  82. /package/dist/{funnel-recovery-D9CxD5Zs.js → funnel-recovery-BFdPjL6Z.js} +0 -0
  83. /package/dist/{logger-BP6SisKt.js → logger-B6iyNbxM.js} +0 -0
  84. /package/dist/{schedule-connector-schema-B_xO5z5B.js → schedule-connector-schema-CfyuMCMh.js} +0 -0
  85. /package/dist/{settings-reader-DPqrpV7s.js → settings-reader-CtQ-Ix8_.js} +0 -0
@@ -0,0 +1,1057 @@
1
+ import { B as FunnelLogger, C as StoredRawEvent, D as FunnelConnectorListener, I as FunnelProcessRunner, M as BaseConnectorConfig, S as StoredProcessedEvent, b as ConnectorRawRecord, d as ConnectorConnectionRecord, g as ConnectorProcessedRecord, h as ConnectorProcessedQuery, p as ConnectorDiagnosticLog, u as ConnectorConnectionQuery, x as StoredConnectionEvent, y as ConnectorRawQuery } from "./connector-descriptor-6SXJoszo.js";
2
+ import { n as FunnelFileSystem } from "./file-system-o51IsM0W.js";
3
+ import { i as FunnelClock, n as ChannelConnectorView, r as FunnelChannels } from "./channels-2g_BU1N0.js";
4
+ import { z } from "zod";
5
+ import { Hono } from "hono";
6
+ import { ServerWebSocket } from "bun";
7
+ import * as _$hono_utils_http_status0 from "hono/utils/http-status";
8
+ import * as _$hono_utils_types0 from "hono/utils/types";
9
+ import * as _$hono_hono_base0 from "hono/hono-base";
10
+
11
+ //#region lib/engine/error/on-funnel-error.d.ts
12
+ /**
13
+ * Host integration hook called when Funnel catches an exception that would
14
+ * otherwise be silently swallowed (subscriber throw, listener start failure,
15
+ * MCP forward failure, etc.). Pass `Sentry.captureException` from the host to
16
+ * pipe these into your error reporter. Defaults to a no-op when omitted.
17
+ *
18
+ * `context` carries the component name and any extra metadata the caller had
19
+ * at the catch site (channel / connector / subscriber id when available).
20
+ */
21
+ type OnFunnelError = (error: Error, context?: Record<string, unknown>) => void;
22
+ //#endregion
23
+ //#region lib/gateway/broadcaster.d.ts
24
+ type ClientData = {
25
+ /** Stable channel id (uuid) that the WS client subscribed to. */channel: string; /** Human-facing channel name resolved at upgrade time, kept for log readability. */
26
+ channelName?: string | null; /** Connector names belonging to that channel. */
27
+ connectors: string[]; /** Routing mode resolved from channel config at upgrade time. Defaults to fanout. */
28
+ delivery?: "fanout" | "exclusive";
29
+ /**
30
+ * Opaque per-client id declared at upgrade time (`?id=<subscriberId>`). When an
31
+ * event carries `meta.target`, only the client whose `subscriberId` equals it
32
+ * receives the event among that channel's regular subscribers. Targeted delivery
33
+ * is how a publisher addresses one specific instance (e.g. a single agent
34
+ * session) without every subscriber having to receive and discard it.
35
+ */
36
+ subscriberId?: string;
37
+ };
38
+ type BroadcastEvent = {
39
+ content: string;
40
+ meta?: Record<string, string>;
41
+ };
42
+ type ReplayableEvent = BroadcastEvent & {
43
+ offset: number;
44
+ };
45
+ type BroadcastSubscriber = (event: ReplayableEvent) => void;
46
+ /**
47
+ * Optional persistent replay source. Wired in by the gateway-server with a
48
+ * `FunnelEventLog` (SQLite-backed by default) so reconnects across daemon
49
+ * restarts can recover events older than the in-memory buffer via an indexed
50
+ * `seq > since` range scan.
51
+ */
52
+ type ReplaySource = {
53
+ loadSince(since: number): ReplayableEvent[];
54
+ };
55
+ type Deps$4 = {
56
+ logger?: FunnelLogger; /** Host hook for surfacing subscriber-throw exceptions. Defaults to no-op. */
57
+ onError?: OnFunnelError;
58
+ maxBufferedBytes?: number;
59
+ now?: () => number; /** Number of recent events kept in the in-memory replay buffer. */
60
+ replayBufferSize?: number; /** Hard byte cap on replay buffer payloads. Older events are evicted FIFO until under this cap. */
61
+ replayBufferMaxBytes?: number; /** Persistent replay source consulted when the in-memory buffer cannot satisfy `since`. */
62
+ persistentReplay?: ReplaySource;
63
+ };
64
+ type BroadcasterMetrics = {
65
+ clients: number;
66
+ subscribers: number;
67
+ eventsBroadcast: number;
68
+ droppedSlowClients: number;
69
+ lastBroadcastAt: string | null; /** Latest emitted offset. Clients can `?since=<offset>` to ask for events strictly after this point. */
70
+ latestOffset: number; /** Oldest offset still held in the replay buffer. Older values cannot be replayed and trigger a full resync. */
71
+ oldestReplayableOffset: number | null;
72
+ };
73
+ /**
74
+ * In-process pub/sub for connector events.
75
+ *
76
+ * Two outbound paths:
77
+ * - WS clients connected via the gateway's `/ws` endpoint, scoped per channel
78
+ * - In-process subscribers registered via `subscribe()` (programmable API)
79
+ *
80
+ * Backpressure: if a WS client's `bufferedAmount` exceeds `maxBufferedBytes`
81
+ * (default 1 MiB), the client is closed with code 1009 and dropped from the
82
+ * registry to keep one slow consumer from blocking the daemon.
83
+ *
84
+ * Replay: every emitted event gets a strictly increasing `offset`. The latest
85
+ * `replayBufferSize` events are kept in memory; reconnecting WS clients can
86
+ * pass `?since=<offset>` and the broadcaster resends matching events before
87
+ * resuming the live stream. The in-memory ring covers short reconnects;
88
+ * older history is served from the event log wired in as `persistentReplay`.
89
+ */
90
+ declare class FunnelBroadcaster {
91
+ private readonly clients;
92
+ private readonly subscribers;
93
+ private readonly logger;
94
+ private readonly onError;
95
+ private readonly maxBufferedBytes;
96
+ private readonly now;
97
+ private readonly replayBufferSize;
98
+ private readonly replayBufferMaxBytes;
99
+ private readonly replayBuffer;
100
+ private readonly persistentReplay;
101
+ private readonly exclusiveCursor;
102
+ private replayBufferBytes;
103
+ private eventsBroadcast;
104
+ private droppedSlowClients;
105
+ private lastBroadcastAt;
106
+ private latestOffset;
107
+ constructor(deps?: Deps$4);
108
+ getMetrics(): BroadcasterMetrics;
109
+ /**
110
+ * Returns events with offset > since, filtered by the connector subscription
111
+ * rules of `data`. Used at WS upgrade time when the client passes `?since=<offset>`.
112
+ *
113
+ * Two-tier lookup:
114
+ * 1. The in-memory ring buffer (covers short reconnects, last `replayBufferSize` events).
115
+ * 2. If `since` predates the oldest in-memory entry and a persistent replay source
116
+ * is wired in (SQLite by default), the gap is filled from it. This covers reconnects
117
+ * across daemon restarts where the in-memory buffer was lost.
118
+ *
119
+ * Result is sorted ascending by offset and de-duplicated against the in-memory buffer.
120
+ */
121
+ replaySince(since: number, data: ClientData): ReplayableEvent[];
122
+ private matchesClient;
123
+ /**
124
+ * Returns the list of WS clients that should receive `event`. For each per-channel group:
125
+ * - fanout → every matching client receives
126
+ * - exclusive → exactly one client receives, picked round-robin per channel
127
+ *
128
+ * `meta.target` narrows the recipient set via `matchesClient`: only the subscriber
129
+ * whose `subscriberId` equals `target` receives a targeted event.
130
+ */
131
+ private pickRecipients;
132
+ addClient(ws: ServerWebSocket<unknown>, data: ClientData): void;
133
+ removeClient(ws: ServerWebSocket<unknown>): void;
134
+ getClientCount(): number;
135
+ listChannels(): {
136
+ channel: string;
137
+ connectors: string[];
138
+ }[];
139
+ subscribe(handler: BroadcastSubscriber): () => void;
140
+ broadcast(content: string, meta?: Record<string, string>): ReplayableEvent;
141
+ /** Forward-seed the offset counter (used at startup from the persisted event store). */
142
+ seedLatestOffset(offset: number): void;
143
+ }
144
+ //#endregion
145
+ //#region lib/gateway/listener-supervisor.d.ts
146
+ type ConnectorRegistry = {
147
+ listAllConnectors(): ChannelConnectorView[];
148
+ createListener(channelName: string, connectorName: string): {
149
+ config: BaseConnectorConfig;
150
+ channelId: string;
151
+ listener: FunnelConnectorListener;
152
+ } | null;
153
+ };
154
+ type SupervisorNotify = (channelName: string, connectorName: string, content: string, meta?: Record<string, string>) => Promise<void>;
155
+ type Deps$3 = {
156
+ channels: ConnectorRegistry;
157
+ notify: SupervisorNotify;
158
+ logger?: FunnelLogger; /** Host hook for surfacing listener lifecycle exceptions. Defaults to no-op. */
159
+ onError?: OnFunnelError;
160
+ healthCheckIntervalMs?: number;
161
+ maxBackoffMs?: number;
162
+ /** Per-listener timeout for `start()`. A listener that hangs beyond this is
163
+ * treated as a startup failure — it won't block other listeners or the
164
+ * health-check loop. Defaults to 30 seconds. */
165
+ startTimeoutMs?: number;
166
+ sleep?: (ms: number) => Promise<void>;
167
+ now?: () => number;
168
+ };
169
+ type ListenerEntryStatus = {
170
+ channelName: string;
171
+ channelId: string;
172
+ name: string;
173
+ type: string;
174
+ alive: boolean;
175
+ events: number;
176
+ errors: number;
177
+ failureCount: number;
178
+ lastEventAt: string | null;
179
+ };
180
+ /**
181
+ * Owns the running listener instances and their lifecycle.
182
+ *
183
+ * Lives in the gateway process and is the only place that calls
184
+ * `listener.start()` / `listener.stop()`. Each entry is keyed by
185
+ * `${channelName}/${connectorName}` so the same connector name can exist in
186
+ * multiple channels without colliding.
187
+ *
188
+ * Periodically polls each running listener's `isAlive()` and auto-restarts
189
+ * dead listeners with exponential backoff (1s, 2s, 4s, ... capped). Resets
190
+ * the backoff counter on successful restart.
191
+ */
192
+ declare class FunnelListenerSupervisor {
193
+ private readonly channels;
194
+ private readonly notify;
195
+ private readonly logger;
196
+ private readonly onError;
197
+ private readonly running;
198
+ private readonly failureCounts;
199
+ private readonly stats;
200
+ private readonly healthCheckIntervalMs;
201
+ private readonly maxBackoffMs;
202
+ private readonly startTimeoutMs;
203
+ private readonly sleep;
204
+ private readonly now;
205
+ private healthCheckTimer;
206
+ private healthCheckInFlight;
207
+ /** Connectors that failed initial start — retried by the health check. */
208
+ private readonly pendingRetry;
209
+ constructor(deps: Deps$3);
210
+ static keyOf(channelName: string, connectorName: string): string;
211
+ isRunning(channelName: string, connectorName: string): boolean;
212
+ list(): ListenerEntryStatus[];
213
+ start(channelName: string, connectorName: string): Promise<{
214
+ ok: boolean;
215
+ reason?: string;
216
+ }>;
217
+ stop(channelName: string, connectorName: string): Promise<{
218
+ ok: boolean;
219
+ reason?: string;
220
+ }>;
221
+ restart(channelName: string, connectorName: string): Promise<{
222
+ ok: boolean;
223
+ reason?: string;
224
+ }>;
225
+ startAll(): Promise<void>;
226
+ stopAll(): Promise<void>;
227
+ private ensureStats;
228
+ private recordEvent;
229
+ private recordError;
230
+ private startHealthCheck;
231
+ private stopHealthCheck;
232
+ /** Run one health-check pass synchronously. Test-only seam. */
233
+ runHealthCheckForTest(): Promise<void>;
234
+ private runHealthCheck;
235
+ private recoverDead;
236
+ }
237
+ //#endregion
238
+ //#region lib/gateway/routes/route-deps.d.ts
239
+ type GatewayEmitInput = {
240
+ channel: string;
241
+ connector?: string;
242
+ content: string;
243
+ meta?: Record<string, string>;
244
+ };
245
+ type GatewayRouteDeps = {
246
+ selfPid: number;
247
+ /** Funnel home dir this daemon is rooted at. Lets a probe tell whether the
248
+ * daemon answering on a shared port belongs to the expected repo/scope. */
249
+ dir: string;
250
+ broadcaster: FunnelBroadcaster;
251
+ supervisor: FunnelListenerSupervisor;
252
+ channels: FunnelChannels;
253
+ uptimeMs: () => number;
254
+ emit: (input: GatewayEmitInput) => {
255
+ offset: number;
256
+ };
257
+ };
258
+ //#endregion
259
+ //#region lib/gateway/factory.d.ts
260
+ type Env = {
261
+ Variables: {
262
+ deps: GatewayRouteDeps;
263
+ };
264
+ };
265
+ //#endregion
266
+ //#region lib/gateway/event-log/event-log.d.ts
267
+ /**
268
+ * Replayable event payload persisted by the gateway. Domain events the
269
+ * broadcaster emits to WS clients land here so reconnects across daemon
270
+ * restarts can be served from disk. System events (gateway start, channel
271
+ * connected, etc.) are routed to `FunnelLogger` instead — they never go
272
+ * through this log, which keeps the offset space clean for replay.
273
+ */
274
+ declare const funnelEventSchema: z.ZodObject<{
275
+ type: z.ZodString;
276
+ content: z.ZodString;
277
+ channel_id: z.ZodNullable<z.ZodString>;
278
+ connector_id: z.ZodNullable<z.ZodString>;
279
+ meta: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodString>>;
280
+ }, z.core.$strip>;
281
+ type FunnelEvent = z.infer<typeof funnelEventSchema>;
282
+ /** One broadcast event to persist, carrying the offset the broadcaster assigned. */
283
+ type FunnelEventRecord = {
284
+ content: string;
285
+ channelId: string | null;
286
+ connectorId: string | null;
287
+ meta: Record<string, string> | null;
288
+ offset: number;
289
+ };
290
+ /**
291
+ * Durable, append-only log of broadcaster events keyed by the offset the
292
+ * broadcaster assigns. The gateway persists every domain event here, and
293
+ * across restarts it both seeds the broadcaster's offset counter
294
+ * (`findMaxOffset`) and serves reconnect replay (`loadSince`) from it.
295
+ *
296
+ * `loadSince` is the only method the broadcaster itself needs, which makes
297
+ * any implementation assignable to the broadcaster's narrow `ReplaySource`.
298
+ *
299
+ * Implementations:
300
+ * - `SqliteFunnelEventLog` — the default; durable across daemon restarts.
301
+ * - `MemoryFunnelEventLog` — an in-process double for tests and embedders
302
+ * that do not need durability (replay is lost when the process exits).
303
+ */
304
+ declare abstract class FunnelEventLog {
305
+ abstract record(record: FunnelEventRecord): void;
306
+ abstract loadSince(since: number): ReplayableEvent[];
307
+ abstract findMaxOffset(): number;
308
+ /** Drop every stored event and reclaim the file. The broadcaster's in-memory
309
+ * offset counter is unaffected, so offsets keep increasing after a clear. */
310
+ abstract clear(): void;
311
+ abstract close(): void;
312
+ }
313
+ //#endregion
314
+ //#region lib/gateway/gateway-server.d.ts
315
+ /**
316
+ * Where the gateway's durable replay log lives. The two ways to specify it are
317
+ * mutually exclusive — modeled as a union so you can't pass both (the old shape
318
+ * silently ignored `dbPath` when `eventLog` was also given).
319
+ *
320
+ * - omit both → SQLite at the default path (`<os.tmpdir()>/funnel/events.db`)
321
+ * - `dbPath` → SQLite at a custom path (parent dir created on demand)
322
+ * - `eventLog` → bring your own `FunnelEventLog` (e.g. `MemoryFunnelEventLog`)
323
+ */
324
+ type GatewayEventStore = {
325
+ dbPath?: string;
326
+ eventLog?: undefined;
327
+ } | {
328
+ dbPath?: undefined;
329
+ eventLog: FunnelEventLog;
330
+ };
331
+ type Deps$2 = GatewayEventStore & {
332
+ channels: FunnelChannels;
333
+ 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. */
334
+ hostname?: string;
335
+ process?: FunnelProcessRunner;
336
+ clock?: FunnelClock;
337
+ logger?: FunnelLogger; /** Host hook for surfacing internal exceptions (broadcaster / supervisor). Defaults to no-op. */
338
+ onError?: OnFunnelError;
339
+ selfPid?: number; /** Funnel home dir, used to scope kill-competing to daemons rooted at the same dir. Defaults to FUNNEL_DIR. */
340
+ dir?: string;
341
+ killCompetingSlack?: boolean; /** Bearer token required for `/listeners*`, `/status`, and `/ws`. Empty string disables auth (tests only). */
342
+ token?: string;
343
+ /**
344
+ * Permit binding a non-loopback hostname without a token. Off by default:
345
+ * `start()` throws when `hostname` is reachable off-box and `token` is empty,
346
+ * because every privileged endpoint would then be open to the network. Set
347
+ * this only when you've deliberately fronted the gateway with your own auth.
348
+ */
349
+ allowInsecureHost?: boolean;
350
+ /**
351
+ * Additional hono app mounted before the built-in gateway routes.
352
+ * Use to embed host-specific endpoints (e.g. an MCP route, custom `/api/*`).
353
+ * Host routes are mounted first; built-in `/listeners`, `/status`,
354
+ * `/channels`, `/health` are mounted after and take precedence on conflict.
355
+ */
356
+ extraRoutes?: Hono<Env>;
357
+ };
358
+ /**
359
+ * In-process gateway: runs `Bun.serve` (HTTP + WebSocket /ws), boots connector
360
+ * listeners through `FunnelListenerSupervisor`, fans events out via
361
+ * `FunnelBroadcaster`, and persists them via a `FunnelEventLog` (SQLite by default).
362
+ * System events (gateway lifecycle, connect/disconnect) flow to `FunnelLogger`
363
+ * instead — keeping the SQLite seq space exclusive to broadcaster traffic so
364
+ * the broadcaster's offset counter and `getMaxSeq()` stay aligned without
365
+ * per-event coordination. Exposes `/listeners` HTTP for runtime
366
+ * start/stop/restart of individual connectors.
367
+ */
368
+ declare class FunnelGatewayServer {
369
+ private readonly channels;
370
+ private readonly configuredPort;
371
+ private readonly configuredHostname;
372
+ private readonly dbPath;
373
+ private readonly process?;
374
+ private readonly logger;
375
+ private readonly onError;
376
+ private readonly selfPid;
377
+ private readonly dir;
378
+ private readonly killCompetingSlack;
379
+ private readonly token;
380
+ private readonly allowInsecureHost;
381
+ private readonly broadcaster;
382
+ private readonly eventLog;
383
+ private readonly supervisor;
384
+ private readonly nowMs;
385
+ private readonly extraRoutes;
386
+ private startedAt;
387
+ private server;
388
+ constructor(deps: Deps$2);
389
+ /**
390
+ * The resolved listen port: the live Bun server's port once started (so
391
+ * `port: 0` auto-assignment is visible), the configured value before that.
392
+ */
393
+ get port(): number;
394
+ /** The bind address: the live Bun server's hostname once started, the configured value before that. */
395
+ get hostname(): string;
396
+ start(): Promise<void>;
397
+ stop(): Promise<void>;
398
+ getStatus(): {
399
+ clients: number;
400
+ channels: {
401
+ channel: string;
402
+ connectors: string[];
403
+ }[];
404
+ };
405
+ getBroadcaster(): FunnelBroadcaster;
406
+ getSupervisor(): FunnelListenerSupervisor;
407
+ getEventLog(): FunnelEventLog;
408
+ /**
409
+ * Register an in-process observer for every broadcast event. Fires after
410
+ * the event is fanned out to WS clients and recorded in the event log.
411
+ * Returns an unsubscribe function. Only meaningful in-process (embedded
412
+ * hosts / `new Funnel(...)` running their own gateway-server); a separate
413
+ * daemon process cannot be observed this way — use a WS client for that.
414
+ */
415
+ onEvent(handler: BroadcastSubscriber): () => void;
416
+ private handleFetch;
417
+ private handleWsOpen;
418
+ private handleWsClose;
419
+ private logServerStarted;
420
+ private buildApp;
421
+ /**
422
+ * Reads the bearer token from the WebSocket upgrade request. Accepts:
423
+ * - `Sec-WebSocket-Protocol: funnel.token.<value>` (preferred — header, never logged in URLs)
424
+ * - `Authorization: Bearer <value>` (also header-based)
425
+ * Returns true on a constant-time match against the daemon token.
426
+ */
427
+ private tokenMatchesUpgrade;
428
+ private resolveChannel;
429
+ private killCompetingSlackIfNeeded;
430
+ private bootListeners;
431
+ /**
432
+ * Broadcast `content` to subscribers of `channel`, persisting the event in
433
+ * the SQLite store and stamping `meta.channel{,Id}` / `meta.connector{,Id}`
434
+ * when they resolve. Used by both the connector-listener path (via the
435
+ * supervisor's `notify` callback) and the public `/channels/:channel/publish`
436
+ * route. Returns the assigned event offset.
437
+ *
438
+ * Public SDK surface for hosts running this gateway in-process — the no-HTTP
439
+ * sibling of `funnel.publisher.publish()`, which targets a daemon instead
440
+ * (see fnl docs programmable-api).
441
+ */
442
+ emit(input: {
443
+ channel: string;
444
+ connector?: string;
445
+ content: string;
446
+ meta?: Record<string, string>;
447
+ }): {
448
+ offset: number;
449
+ };
450
+ private lookupChannelId;
451
+ private lookupConnectorId;
452
+ }
453
+ //#endregion
454
+ //#region lib/gateway/channel-ws-url.d.ts
455
+ /**
456
+ * Builds the WebSocket URL a client uses to subscribe to a gateway channel.
457
+ *
458
+ * The gateway's `/ws` upgrade handler reads three query params — `channel`
459
+ * (required), `id` (the subscriber id for targeted delivery), and `since`
460
+ * (replay offset). Forgetting `channel=` silently drops the subscription
461
+ * (the broadcaster never matches the client), which has caused outages when
462
+ * callers hand-built the URL with string concatenation. This builder makes
463
+ * `channel` a required field, so the mistake becomes a compile error.
464
+ *
465
+ * `subscriberId` enables targeted delivery: events carrying `meta.target=<id>`
466
+ * reach only this client. Omit it to receive the channel's fanout.
467
+ *
468
+ * Pair with `channelWsProtocols()` to authenticate the upgrade when the
469
+ * gateway requires a token.
470
+ */
471
+ type ChannelWsUrlInput = {
472
+ /** 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. */
473
+ channel: string; /** Opaque subscriber id for targeted delivery (`meta.target=<id>`). Omit for fanout. */
474
+ subscriberId?: string; /** Replay from this event offset (inclusive). Omit to receive only new events. */
475
+ since?: number;
476
+ };
477
+ declare function channelWsUrl(input: ChannelWsUrlInput): string;
478
+ /**
479
+ * Builds the `Sec-WebSocket-Protocol` values that authenticate a gateway WS
480
+ * upgrade. Browser `WebSocket` cannot set an `Authorization` header, so the
481
+ * gateway also accepts the token as a `funnel.token.<token>` subprotocol.
482
+ * Returns an empty array when no token is given (auth disabled / loopback).
483
+ *
484
+ * Usage: `new WebSocket(channelWsUrl({ base, channel }), channelWsProtocols(token))`
485
+ */
486
+ declare function channelWsProtocols(token?: string | null): string[];
487
+ //#endregion
488
+ //#region lib/engine/http/gateway-base-url.d.ts
489
+ /**
490
+ * The HTTP base URL of a gateway daemon on the loopback interface. The daemon
491
+ * always binds 127.0.0.1 for its management API (only the WS `/ws` endpoint is
492
+ * ever exposed off-box), so every in-process HTTP client — publisher, listeners
493
+ * client, MCP channel server — talks to it here. Centralizing the construction
494
+ * keeps the host/port shape in one place instead of re-spelling
495
+ * `http://127.0.0.1:${port}` at each call site.
496
+ */
497
+ declare function gatewayLoopbackUrl(port: number): string;
498
+ //#endregion
499
+ //#region lib/gateway/gateway-token.d.ts
500
+ type Deps$1 = {
501
+ fs?: FunnelFileSystem;
502
+ dir?: string;
503
+ generate?: () => string;
504
+ };
505
+ /**
506
+ * Reads / generates the gateway daemon token used to authenticate
507
+ * `/listeners*`, `/status`, and `/ws` connections.
508
+ *
509
+ * Token file: `<dir>/gateway.token` (default `~/.funnel/gateway.token`),
510
+ * written with mode 0600. Clients on the same machine as the daemon read
511
+ * the file directly; the token never leaves the user's home directory.
512
+ */
513
+ declare class FunnelGatewayToken {
514
+ private readonly fs;
515
+ private readonly path;
516
+ private readonly generate;
517
+ constructor(deps?: Deps$1);
518
+ read(): string | null;
519
+ /**
520
+ * Returns the existing token or, if missing, generates one and writes it with mode 0600.
521
+ *
522
+ * NOTE: not atomic — two concurrent `ensure()` calls (e.g., `fnl gateway start` racing
523
+ * itself before the PID lock is acquired) could each generate independent tokens. The
524
+ * gateway PID file makes this practically a non-issue; if you need stronger guarantees,
525
+ * take a file lock around this call externally.
526
+ */
527
+ ensure(): string;
528
+ getPath(): string;
529
+ }
530
+ declare const DEFAULT_GATEWAY_TOKEN_PATH: string;
531
+ //#endregion
532
+ //#region lib/gateway/publish-schema.d.ts
533
+ /**
534
+ * Shared schema for `POST /channels/:channel/publish` — used by both the
535
+ * gateway route handler (input validation) and the CLI / programmable client
536
+ * (request shape). The route resolves `channel` from the path; this body
537
+ * covers everything else.
538
+ */
539
+ declare const publishRequestSchema: z.ZodObject<{
540
+ content: z.ZodString;
541
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
542
+ connector: z.ZodOptional<z.ZodString>;
543
+ target: z.ZodOptional<z.ZodString>;
544
+ }, z.core.$strip>;
545
+ type PublishRequest = z.infer<typeof publishRequestSchema>;
546
+ declare const publishResponseSchema: z.ZodObject<{
547
+ ok: z.ZodLiteral<true>;
548
+ offset: z.ZodNumber;
549
+ }, z.core.$strip>;
550
+ type PublishResponse = z.infer<typeof publishResponseSchema>;
551
+ type PublishResult = {
552
+ state: "ok";
553
+ offset: number;
554
+ } | {
555
+ state: "offline";
556
+ } | {
557
+ state: "error";
558
+ reason: string;
559
+ };
560
+ //#endregion
561
+ //#region lib/gateway/channel-publisher.d.ts
562
+ type Deps = {
563
+ port: number;
564
+ isDaemonRunning: () => boolean; /** Returns the daemon's gateway token, or null if unavailable. Sent as `Authorization: Bearer`. */
565
+ getToken?: () => string | null;
566
+ };
567
+ /**
568
+ * HTTP client for `POST /channels/:channel/publish` on a running gateway
569
+ * daemon. Returns `{ state: "offline" }` when the daemon isn't up so callers
570
+ * can branch without exceptions, mirroring `FunnelListenersClient`.
571
+ */
572
+ declare class FunnelChannelPublisher {
573
+ private readonly port;
574
+ private readonly isDaemonRunning;
575
+ private readonly getToken;
576
+ constructor(deps: Deps);
577
+ publish(channelName: string, request: PublishRequest): Promise<PublishResult>;
578
+ private authHeaders;
579
+ }
580
+ //#endregion
581
+ //#region lib/gateway/event-log/sqlite-event-log.d.ts
582
+ type Props$1 = {
583
+ /** SQLite database file path. Created on first write. ":memory:" for tests. */path: string; /** Override for tests. Defaults to `Date.now`. */
584
+ now?: () => number; /** Surfaces a failed persist (PK collision, disk-full, locked WAL). Silent if absent. */
585
+ logger?: FunnelLogger; /** Optional row cap. Pruned on every insert. */
586
+ maxRows?: number; /** Optional age cap in ms. Pruned on every insert. */
587
+ maxAgeMs?: number; /** Optional on-disk byte cap. Checked periodically; on overflow the oldest rows are dropped toward targetBytes and the file is VACUUMed. */
588
+ maxBytes?: number; /** Shrink target when maxBytes is exceeded. Defaults to maxBytes/4. */
589
+ targetBytes?: number;
590
+ };
591
+ /**
592
+ * SQLite-backed `FunnelEventLog`. One indexed table holds every broadcaster
593
+ * event with `channel_id` and `connector_id` as dedicated columns, so
594
+ * per-channel and per-connector replay is an indexed range scan.
595
+ *
596
+ * Concurrency: `seq` is `INTEGER PRIMARY KEY`, so SQLite assigns it
597
+ * atomically. The broadcaster owns its own offset counter at runtime
598
+ * (seeded from `findMaxOffset()` at startup); each broadcaster event
599
+ * flows in here via `record()` with that pre-assigned offset, which the
600
+ * sink stores via `write()` — PK uniqueness catches double-emit bugs.
601
+ *
602
+ * System events (gateway lifecycle, channel connect/disconnect, etc.) do
603
+ * NOT go through this store. They are diagnostic only and live in
604
+ * `FunnelLogger`'s file so the seq space here stays exclusive to
605
+ * broadcaster traffic. This is what makes the broadcaster's seq seeding
606
+ * (`getMaxSeq()` at startup) correct without per-event coordination.
607
+ */
608
+ declare class SqliteFunnelEventLog extends FunnelEventLog {
609
+ private readonly sink;
610
+ private readonly now;
611
+ private readonly logger;
612
+ constructor(props: Props$1);
613
+ /**
614
+ * Persist a broadcaster-driven event with its assigned offset. Caller
615
+ * (the gateway-server) supplies the offset from `broadcaster.broadcast()`
616
+ * so this store and the broadcaster's in-memory ring stay aligned.
617
+ */
618
+ record(record: FunnelEventRecord): void;
619
+ /**
620
+ * Returns events with offset > since. Filtering by channel/connector is
621
+ * the broadcaster's responsibility (it knows the client's subscription),
622
+ * so this returns the full slice and lets the caller filter.
623
+ */
624
+ loadSince(since: number): ReplayableEvent[];
625
+ /**
626
+ * Returns events for one channel (and optionally one connector). Used
627
+ * by the gateway logs CLI for scoped queries. Channel/connector filters
628
+ * are indexed columns, so this is an indexed range scan.
629
+ */
630
+ loadForChannel(props: {
631
+ channelId: string;
632
+ connectorId?: string;
633
+ sinceSeq?: number;
634
+ limit?: number;
635
+ }): ReplayableEvent[];
636
+ findMaxOffset(): number;
637
+ clear(): void;
638
+ close(): void;
639
+ }
640
+ //#endregion
641
+ //#region lib/gateway/event-log/memory-event-log.d.ts
642
+ /**
643
+ * In-process `FunnelEventLog` backed by a plain array. Used by tests and by
644
+ * embedders that do not need durability — replay works within the process
645
+ * lifetime but is lost when the process exits. Unlike the SQLite log it does
646
+ * not truncate content or prune, so it is not meant for unbounded production
647
+ * traffic.
648
+ */
649
+ declare class MemoryFunnelEventLog extends FunnelEventLog {
650
+ private readonly events;
651
+ constructor();
652
+ record(record: FunnelEventRecord): void;
653
+ loadSince(since: number): ReplayableEvent[];
654
+ findMaxOffset(): number;
655
+ clear(): void;
656
+ close(): void;
657
+ }
658
+ //#endregion
659
+ //#region lib/engine/diagnostic-log/sqlite-diagnostic-log.d.ts
660
+ type Props = {
661
+ /** SQLite file for the raw (pre-filter) table. ":memory:" for tests. */rawPath: string; /** SQLite file for the processed (verdict) table. ":memory:" for tests. */
662
+ processedPath: string; /** SQLite file for the connection (lifecycle) table. ":memory:" for tests. */
663
+ connectionPath: string;
664
+ now?: () => number; /** Row cap for the processed and connection tables. Pruned on every insert. */
665
+ maxRows?: number;
666
+ /**
667
+ * Row cap for the raw table specifically. Raw rows can each hold up to
668
+ * `RAW_PAYLOAD_CAP` bytes, so they want a tighter cap than the small
669
+ * processed/connection verdict rows. Defaults to `maxRows` when unset.
670
+ */
671
+ rawMaxRows?: number; /** Age cap in ms for all tables — bounds how long untouched payloads (with PII) live. Pruned on every insert. */
672
+ maxAgeMs?: number; /** When set, `insert()` errors (disk full, WAL lock) are logged instead of silently dropped. */
673
+ logger?: FunnelLogger;
674
+ };
675
+ /**
676
+ * Default `ConnectorDiagnosticLog`: three independent `FunnelLogSqliteSink`s, one
677
+ * per table (raw / processed / connection), in separate files. Each sink
678
+ * indexes the columns its queries filter on — `event_id` / `connector_id` /
679
+ * `channel_id` for raw, plus `outcome` for processed and `status` for
680
+ * connection — so those lookups are indexed scans (`type` is a fixed column
681
+ * the sink extracts separately, not an index, so filtering by it is a scan).
682
+ *
683
+ * The raw table offloads any payload over `RAW_PAYLOAD_CAP`: rather than
684
+ * truncating mid-string (which yields unparseable JSON), it replaces the
685
+ * body with a small JSON object that keeps the diagnostic essentials and
686
+ * records the dropped size under `_funnel_oversized`. Every stored payload
687
+ * therefore stays valid JSON.
688
+ */
689
+ declare class SqliteConnectorDiagnosticLog extends ConnectorDiagnosticLog {
690
+ private readonly raw;
691
+ private readonly processed;
692
+ private readonly connection;
693
+ private readonly now;
694
+ private readonly logger;
695
+ constructor(props: Props);
696
+ recordRaw(record: ConnectorRawRecord): void;
697
+ recordProcessed(record: ConnectorProcessedRecord): void;
698
+ recordConnection(record: ConnectorConnectionRecord): void;
699
+ private report;
700
+ queryRaw(query: ConnectorRawQuery): StoredRawEvent[];
701
+ queryProcessed(query: ConnectorProcessedQuery): StoredProcessedEvent[];
702
+ queryConnection(query: ConnectorConnectionQuery): StoredConnectionEvent[];
703
+ clear(): void;
704
+ close(): void;
705
+ }
706
+ //#endregion
707
+ //#region lib/engine/diagnostic-log/memory-diagnostic-log.d.ts
708
+ /**
709
+ * In-process `ConnectorDiagnosticLog` backed by one array per table. Used by tests
710
+ * and embedders that do not need durability. Like the SQLite log it keeps
711
+ * `seq` per-table (each array's 1-based position) and returns the most recent
712
+ * `limit` rows oldest-first; unlike it, it never prunes and never offloads
713
+ * oversized payloads — it keeps whatever the caller hands it, which is fine
714
+ * for the bounded volumes a test produces. Payload-validity is therefore a
715
+ * SQLite-only guarantee; do not write a test that leans on this double
716
+ * rejecting a malformed payload.
717
+ */
718
+ declare class MemoryConnectorDiagnosticLog extends ConnectorDiagnosticLog {
719
+ private readonly now;
720
+ private readonly raws;
721
+ private readonly processeds;
722
+ private readonly connections;
723
+ constructor(now?: () => number);
724
+ recordRaw(record: ConnectorRawRecord): void;
725
+ recordProcessed(record: ConnectorProcessedRecord): void;
726
+ recordConnection(record: ConnectorConnectionRecord): void;
727
+ queryRaw(query: ConnectorRawQuery): StoredRawEvent[];
728
+ queryProcessed(query: ConnectorProcessedQuery): StoredProcessedEvent[];
729
+ queryConnection(query: ConnectorConnectionQuery): StoredConnectionEvent[];
730
+ clear(): void;
731
+ close(): void;
732
+ }
733
+ //#endregion
734
+ //#region lib/gateway/routes/index.d.ts
735
+ /**
736
+ * Top-level Hono app for the gateway daemon. Mounts every HTTP endpoint flat
737
+ * (the WebSocket /ws upgrade is handled directly by `Bun.serve`). Deps come
738
+ * from the `deps` variable set by `FunnelGatewayServer`'s middleware — same
739
+ * shape as CLI's `c.var.funnel`.
740
+ */
741
+ type GatewayApp = ReturnType<typeof buildGatewayRoutes>;
742
+ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
743
+ "/health": {
744
+ $get: {
745
+ input: {};
746
+ output: {
747
+ ok: true;
748
+ pid: number;
749
+ funnelDir: string;
750
+ clients: number;
751
+ listeners: {
752
+ channelName: string;
753
+ channelId: string;
754
+ name: string;
755
+ type: string;
756
+ alive: boolean;
757
+ events: number;
758
+ errors: number;
759
+ failureCount: number;
760
+ lastEventAt: string | null;
761
+ }[];
762
+ };
763
+ outputFormat: "json";
764
+ status: _$hono_utils_http_status0.ContentfulStatusCode;
765
+ };
766
+ };
767
+ } & {
768
+ "/status": {
769
+ $get: {
770
+ input: {};
771
+ output: {
772
+ ok: true;
773
+ pid: number;
774
+ funnelDir: string;
775
+ uptimeMs: number;
776
+ clients: {
777
+ channel: string;
778
+ connectors: string[];
779
+ }[];
780
+ listeners: {
781
+ channelName: string;
782
+ channelId: string;
783
+ name: string;
784
+ type: string;
785
+ alive: boolean;
786
+ events: number;
787
+ errors: number;
788
+ failureCount: number;
789
+ lastEventAt: string | null;
790
+ }[];
791
+ broadcaster: {
792
+ clients: number;
793
+ subscribers: number;
794
+ eventsBroadcast: number;
795
+ droppedSlowClients: number;
796
+ lastBroadcastAt: string | null;
797
+ latestOffset: number;
798
+ oldestReplayableOffset: number | null;
799
+ };
800
+ };
801
+ outputFormat: "json";
802
+ status: _$hono_utils_http_status0.ContentfulStatusCode;
803
+ };
804
+ };
805
+ } & {
806
+ "/debug": {
807
+ $get: {
808
+ input: {};
809
+ output: {
810
+ pid: number;
811
+ uptimeMs: number;
812
+ eventsBroadcast: number;
813
+ channels: {
814
+ id: string;
815
+ name: string;
816
+ connectors: string[];
817
+ listener: {
818
+ alive: boolean;
819
+ events: number;
820
+ errors: number;
821
+ lastEventAt: string | null;
822
+ } | null;
823
+ claudeClients: number;
824
+ recentEvents: {
825
+ seq: number | null;
826
+ ts: number | null;
827
+ type: string;
828
+ outcome: string;
829
+ payload: string | null;
830
+ payloadParsed: {
831
+ [x: string]: _$hono_utils_types0.JSONValue;
832
+ } | null;
833
+ preview: string | null;
834
+ }[];
835
+ connectionErrors: {
836
+ ts: number | null;
837
+ type: string;
838
+ status: string;
839
+ detail: string | null;
840
+ }[];
841
+ diagnosis: {
842
+ status: "ok" | "warn" | "error";
843
+ message: string;
844
+ nextActions: string[];
845
+ rootCause: string | null;
846
+ };
847
+ }[];
848
+ };
849
+ outputFormat: "json";
850
+ status: _$hono_utils_http_status0.ContentfulStatusCode;
851
+ };
852
+ };
853
+ } & {
854
+ "/listeners": {
855
+ $get: {
856
+ input: {};
857
+ output: {
858
+ listeners: {
859
+ channelName: string;
860
+ channelId: string;
861
+ name: string;
862
+ type: string;
863
+ alive: boolean;
864
+ events: number;
865
+ errors: number;
866
+ failureCount: number;
867
+ lastEventAt: string | null;
868
+ }[];
869
+ };
870
+ outputFormat: "json";
871
+ status: _$hono_utils_http_status0.ContentfulStatusCode;
872
+ };
873
+ };
874
+ } & {
875
+ "/listeners/:channel/:connector/start": {
876
+ $post: {
877
+ input: {
878
+ param: {
879
+ channel: string;
880
+ connector: string;
881
+ };
882
+ };
883
+ output: {
884
+ ok: boolean;
885
+ reason: string;
886
+ };
887
+ outputFormat: "json";
888
+ status: 400;
889
+ } | {
890
+ input: {
891
+ param: {
892
+ channel: string;
893
+ connector: string;
894
+ };
895
+ };
896
+ output: {
897
+ ok: boolean;
898
+ reason?: string | undefined;
899
+ };
900
+ outputFormat: "json";
901
+ status: 200 | 400;
902
+ };
903
+ };
904
+ } & {
905
+ "/listeners/:channel/:connector": {
906
+ $delete: {
907
+ input: {
908
+ param: {
909
+ channel: string;
910
+ connector: string;
911
+ };
912
+ };
913
+ output: {
914
+ ok: boolean;
915
+ reason: string;
916
+ };
917
+ outputFormat: "json";
918
+ status: 400;
919
+ } | {
920
+ input: {
921
+ param: {
922
+ channel: string;
923
+ connector: string;
924
+ };
925
+ };
926
+ output: {
927
+ ok: boolean;
928
+ reason?: string | undefined;
929
+ };
930
+ outputFormat: "json";
931
+ status: 200 | 400;
932
+ };
933
+ };
934
+ } & {
935
+ "/listeners/:channel/:connector/restart": {
936
+ $post: {
937
+ input: {
938
+ param: {
939
+ channel: string;
940
+ connector: string;
941
+ };
942
+ };
943
+ output: {
944
+ ok: boolean;
945
+ reason: string;
946
+ };
947
+ outputFormat: "json";
948
+ status: 400;
949
+ } | {
950
+ input: {
951
+ param: {
952
+ channel: string;
953
+ connector: string;
954
+ };
955
+ };
956
+ output: {
957
+ ok: boolean;
958
+ reason?: string | undefined;
959
+ };
960
+ outputFormat: "json";
961
+ status: 200 | 400;
962
+ };
963
+ };
964
+ } & {
965
+ "/channels/:channel/connectors/:connector/call": {
966
+ $post: {
967
+ input: {
968
+ param: {
969
+ channel: string;
970
+ connector: string;
971
+ };
972
+ };
973
+ output: {
974
+ ok: boolean;
975
+ reason: string;
976
+ };
977
+ outputFormat: "json";
978
+ status: 400;
979
+ } | {
980
+ input: {
981
+ param: {
982
+ channel: string;
983
+ connector: string;
984
+ };
985
+ };
986
+ output: {
987
+ ok: true;
988
+ result: _$hono_utils_types0.JSONValue;
989
+ };
990
+ outputFormat: "json";
991
+ status: _$hono_utils_http_status0.ContentfulStatusCode;
992
+ };
993
+ };
994
+ } & {
995
+ "/channels/:channel/publish": {
996
+ $post: {
997
+ input: {
998
+ param: {
999
+ channel: string;
1000
+ };
1001
+ } & {
1002
+ json: {
1003
+ content: string;
1004
+ meta?: Record<string, string> | undefined;
1005
+ connector?: string | undefined;
1006
+ target?: string | undefined;
1007
+ };
1008
+ };
1009
+ output: {
1010
+ ok: boolean;
1011
+ reason: string;
1012
+ };
1013
+ outputFormat: "json";
1014
+ status: 400;
1015
+ } | {
1016
+ input: {
1017
+ param: {
1018
+ channel: string;
1019
+ };
1020
+ } & {
1021
+ json: {
1022
+ content: string;
1023
+ meta?: Record<string, string> | undefined;
1024
+ connector?: string | undefined;
1025
+ target?: string | undefined;
1026
+ };
1027
+ };
1028
+ output: {
1029
+ ok: boolean;
1030
+ reason: string;
1031
+ };
1032
+ outputFormat: "json";
1033
+ status: 400;
1034
+ } | {
1035
+ input: {
1036
+ param: {
1037
+ channel: string;
1038
+ };
1039
+ } & {
1040
+ json: {
1041
+ content: string;
1042
+ meta?: Record<string, string> | undefined;
1043
+ connector?: string | undefined;
1044
+ target?: string | undefined;
1045
+ };
1046
+ };
1047
+ output: {
1048
+ ok: true;
1049
+ offset: number;
1050
+ };
1051
+ outputFormat: "json";
1052
+ status: _$hono_utils_http_status0.ContentfulStatusCode;
1053
+ };
1054
+ };
1055
+ }, "/", "/channels/:channel/publish">;
1056
+ //#endregion
1057
+ export { FunnelBroadcaster as A, funnelEventSchema as C, FunnelListenerSupervisor 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 };