@interactive-inc/claude-funnel 0.60.1 → 0.63.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 +2 -2
  2. package/dist/bin.js +428 -761
  3. package/dist/{channels-2g_BU1N0.d.ts → channels-B8RQPrVq.d.ts} +17 -16
  4. package/dist/claude.d.ts +5 -7
  5. package/dist/claude.js +143 -36
  6. package/dist/{connector-descriptor-6SXJoszo.d.ts → connector-descriptor-ClEEbuW3.d.ts} +50 -11
  7. package/dist/connector-diagnostics-recorder-COtNEmUp.js +42 -0
  8. package/dist/connectors/discord.d.ts +31 -37
  9. package/dist/connectors/discord.js +3 -3
  10. package/dist/connectors/gh.d.ts +37 -33
  11. package/dist/connectors/gh.js +3 -3
  12. package/dist/connectors/schedule.d.ts +9 -57
  13. package/dist/connectors/schedule.js +3 -3
  14. package/dist/connectors/slack.d.ts +71 -131
  15. package/dist/connectors/slack.js +4 -3
  16. package/dist/diagnostics.d.ts +1 -1
  17. package/dist/diagnostics.js +1 -1
  18. package/dist/discord-connector-DIFkYBbi.js +250 -0
  19. package/dist/discord-connector-schema-D-bOVAKt.d.ts +22 -0
  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/{file-process-guard-C_PLxfUX.d.ts → file-process-guard-DGHxALfI.d.ts} +6 -6
  24. package/dist/{file-system-o51IsM0W.d.ts → file-system-VhwwXZbm.d.ts} +8 -0
  25. package/dist/flume-source-listener-Dim5szHG.d.ts +133 -0
  26. package/dist/{funnel-diagnostics-CSiJmPlZ.js → funnel-diagnostics-Cvk6Sk4x.js} +193 -43
  27. package/dist/{funnel-diagnostics-DpXOsCty.d.ts → funnel-diagnostics-b9ar0Ing.d.ts} +67 -5
  28. package/dist/{funnel-docs-BxXZ9Ksx.js → funnel-docs-C-ge0MuB.js} +42 -6
  29. package/dist/{funnel-doctor-CZf_0Luq.d.ts → funnel-doctor-CnRQi4kM.d.ts} +2 -2
  30. package/dist/{funnel-doctor-DiJCjHsg.js → funnel-doctor-XrI2GBH8.js} +1 -1
  31. package/dist/funnel-error-0t1MK1R6.js +75 -0
  32. package/dist/{funnel-recovery-DnLrdWO9.d.ts → funnel-recovery-CMhY8Jfk.d.ts} +1 -1
  33. package/dist/gateway/daemon.js +167 -527
  34. package/dist/gateway.d.ts +3 -3
  35. package/dist/gateway.js +3 -3
  36. package/dist/gh-connector-BUGCOEWS.js +187 -0
  37. package/dist/{gh-connector-schema-Rzwc1c1N.js → gh-connector-schema-CAqIhzGr.js} +7 -0
  38. package/dist/gh-connector-schema-DWQaB6gX.d.ts +16 -0
  39. package/dist/{index-CgY8NdMz.d.ts → index-DxRikYmu.d.ts} +37 -19
  40. package/dist/index.d.ts +182 -22
  41. package/dist/index.js +363 -173
  42. package/dist/{local-config-json-schema-JyLqOQNX.js → local-config-json-schema-DexV8vX3.js} +24 -4
  43. package/dist/local-config.d.ts +39 -2
  44. package/dist/local-config.js +53 -2
  45. package/dist/logger.js +1 -1
  46. package/dist/loopback-fetch-CVNuN3YZ.js +40 -0
  47. package/dist/{local-config-sync-Dh1Croqe.d.ts → memory-token-prompter-DP_YV9xX.d.ts} +30 -3
  48. package/dist/node-file-system-BOXIHW_Q.js +174 -0
  49. package/dist/{profiles-DSzTeKQw.js → profiles-ZHLONml4.js} +49 -49
  50. package/dist/{profiles-Cy5wXQ0L.d.ts → profiles-cVZQkM69.d.ts} +3 -3
  51. package/dist/profiles.d.ts +1 -1
  52. package/dist/profiles.js +1 -1
  53. package/dist/recovery.d.ts +1 -1
  54. package/dist/recovery.js +1 -1
  55. package/dist/resolve-connector-token-DxDG9mhf.js +22 -0
  56. package/dist/{schedule-connector-L4uzg5M8.js → schedule-connector-9k3gOIgl.js} +54 -55
  57. package/dist/schedule-connector-schema-Z0RXLgPI.d.ts +49 -0
  58. package/dist/settings-reader-BNxjsxCB.d.ts +27 -0
  59. package/dist/{settings-store-CUKSeTXC.js → settings-store-C2QdOH-t.js} +23 -4
  60. package/dist/slack-connector-BU86fIge.js +359 -0
  61. package/dist/slack-event-processor-BhCf5Wiy.d.ts +95 -0
  62. package/dist/slack-event-processor-xFDG3US0.js +176 -0
  63. package/dist/slot-fields-D-pvMgTK.js +249 -0
  64. package/dist/{memory-diagnostic-log-CI60kNfB.js → sqlite-diagnostic-log-DOTPW-tG.js} +373 -249
  65. package/dist/{yaml-render-93pX7EF7.js → yaml-render--J1_3BSA.js} +25 -21
  66. package/package.json +2 -4
  67. package/dist/discord-connector-BL36yvbL.js +0 -250
  68. package/dist/gateway-base-url-Dy4Ykuoh.js +0 -14
  69. package/dist/gh-connector-DpiixfQZ.js +0 -226
  70. package/dist/http-client-oICicjuO.d.ts +0 -18
  71. package/dist/memory-token-prompter-B4sjyaAq.d.ts +0 -57
  72. package/dist/memory-token-prompter-CZde7e6y.js +0 -61
  73. package/dist/node-file-system-Blr8pAir.js +0 -48
  74. package/dist/settings-reader-BIFB_j2f.d.ts +0 -18
  75. package/dist/slack-connector-DQIFPdBF.js +0 -484
  76. package/dist/slot-fields-CMoRpwuy.js +0 -45
  77. /package/dist/{connector-adapter-DU9Rvyec.js → connector-adapter-Dvs8N7ew.js} +0 -0
  78. /package/dist/{connector-listener-DR3aKOuK.js → connector-listener-mPGZYa8e.js} +0 -0
  79. /package/dist/{diagnostic-sql-reader-C9zR-Csp.js → diagnostic-sql-reader-oXZnWFf_.js} +0 -0
  80. /package/dist/{discord-connector-schema-B_N6IXLz.js → discord-connector-schema-B4YpWpR3.js} +0 -0
  81. /package/dist/{error-message-of-Byi4y0Uf.js → error-message-of-ColuYmAk.js} +0 -0
  82. /package/dist/{funnel-log-sqlite-sink-kqJbx2H7.js → funnel-log-sqlite-sink-DLYkY0pZ.js} +0 -0
  83. /package/dist/{funnel-recovery-BFdPjL6Z.js → funnel-recovery-DKnEutUS.js} +0 -0
  84. /package/dist/{node-http-client-lowp60Oa.js → node-http-client-u00atiKx.js} +0 -0
  85. /package/dist/{schedule-connector-schema-CfyuMCMh.js → schedule-connector-schema-DKEPZnVv.js} +0 -0
  86. /package/dist/{settings-reader-CtQ-Ix8_.js → settings-reader-9FcX3qS1.js} +0 -0
  87. /package/dist/{settings-schema-D1xcOqRu.d.ts → settings-schema-BL_c2Udm.d.ts} +0 -0
  88. /package/dist/{slack-connector-schema-C1zEf4TG.js → slack-connector-schema-Dem8to4P.js} +0 -0
package/dist/gateway.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import { C as StoredRawEvent, E as connectorRawEventSchema, S as StoredProcessedEvent, T as connectorProcessedEventSchema, _ as ConnectorQuery, b as ConnectorRawRecord, c as CONNECTOR_CONNECTION_STATUSES, d as ConnectorConnectionRecord, f as ConnectorConnectionStatus, g as ConnectorProcessedRecord, h as ConnectorProcessedQuery, l as ConnectorConnectionEvent, m as ConnectorProcessedEvent, p as ConnectorDiagnosticLog, u as ConnectorConnectionQuery, v as ConnectorRawEvent, w as connectorConnectionEventSchema, x as StoredConnectionEvent, y as ConnectorRawQuery } from "./connector-descriptor-6SXJoszo.js";
2
- import { A as FunnelBroadcaster, C as funnelEventSchema, D as FunnelListenerSupervisor, 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-CgY8NdMz.js";
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, FunnelListenerSupervisor, 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 };
1
+ import { A as connectorRawEventSchema, C as ConnectorRawQuery, D as StoredRawEvent, E as StoredProcessedEvent, O as connectorConnectionEventSchema, S as ConnectorRawEvent, T as StoredConnectionEvent, _ as ConnectorDiagnosticLog, b as ConnectorProcessedRecord, f as CONNECTOR_CONNECTION_STATUSES, g as ConnectorConnectionStatus, h as ConnectorConnectionRecord, k as connectorProcessedEventSchema, m as ConnectorConnectionQuery, p as ConnectorConnectionEvent, v as ConnectorProcessedEvent, w as ConnectorRawRecord, x as ConnectorQuery, y as ConnectorProcessedQuery } from "./connector-descriptor-ClEEbuW3.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-DxRikYmu.js";
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 { t as gatewayLoopbackUrl } from "./gateway-base-url-Dy4Ykuoh.js";
2
- import { S as publishResponseSchema, _ as funnelEventSchema, a as connectorConnectionEventSchema, b as FunnelChannelPublisher, c as MemoryFunnelEventLog, d as DEFAULT_GATEWAY_TOKEN_PATH, f as FunnelGatewayToken, g as FunnelEventLog, h as SqliteFunnelEventLog, i as ConnectorDiagnosticLog, l as channelWsProtocols, m as FunnelListenerSupervisor, n as SqliteConnectorDiagnosticLog, o as connectorProcessedEventSchema, p as FunnelGatewayServer, r as CONNECTOR_CONNECTION_STATUSES, s as connectorRawEventSchema, t as MemoryConnectorDiagnosticLog, u as channelWsUrl, v as FunnelBroadcaster, x as publishRequestSchema } from "./memory-diagnostic-log-CI60kNfB.js";
3
- export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, DEFAULT_GATEWAY_TOKEN_PATH, FunnelBroadcaster, FunnelChannelPublisher, FunnelEventLog, FunnelGatewayServer, FunnelGatewayToken, FunnelListenerSupervisor, MemoryConnectorDiagnosticLog, MemoryFunnelEventLog, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, channelWsProtocols, channelWsUrl, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, funnelEventSchema, gatewayLoopbackUrl, publishRequestSchema, publishResponseSchema };
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-DOTPW-tG.js";
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 };
@@ -0,0 +1,187 @@
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";
6
+ import { FlumeGitHubSource } from "@interactive-inc/flume/github";
7
+ //#region lib/engine/connectors/gh-adapter.ts
8
+ const defaultProcess$1 = new NodeFunnelProcessRunner();
9
+ var FunnelGhAdapter = class extends FunnelConnectorAdapter {
10
+ process;
11
+ constructor(deps = {}) {
12
+ super();
13
+ this.process = deps.process ?? defaultProcess$1;
14
+ Object.freeze(this);
15
+ }
16
+ async call(input) {
17
+ const args = ["api", input.path];
18
+ if (input.method && input.method.toLowerCase() !== "get") args.push("-X", input.method.toUpperCase());
19
+ const hasBody = input.body && typeof input.body === "object" && Object.keys(input.body).length > 0;
20
+ if (hasBody) args.push("--input", "-");
21
+ const result = await this.process.run(["gh", ...args], { input: hasBody ? JSON.stringify(input.body) : void 0 });
22
+ if (result.exitCode !== 0) throw new Error(`gh api failed: ${result.stderr.trim() || result.stdout.trim()}`);
23
+ try {
24
+ return JSON.parse(result.stdout);
25
+ } catch {
26
+ return result.stdout;
27
+ }
28
+ }
29
+ };
30
+ //#endregion
31
+ //#region lib/engine/connectors/gh-flume-listener.ts
32
+ const defaultProcess = new NodeFunnelProcessRunner();
33
+ /**
34
+ * GitHub listener backed by `@interactive-inc/flume`'s `FlumeGitHubSource`
35
+ * (raw REST polling of `/notifications` + Zod).
36
+ *
37
+ * Token resolution order mirrors the other connectors' literal-or-env-ref
38
+ * slot, with a `gh auth token` fallback as the convenience path:
39
+ *
40
+ * 1. `config.token` (literal)
41
+ * 2. `config.tokenEnv` (env var name → value)
42
+ * 3. `gh auth token` (reuses the `gh` CLI's authenticated session)
43
+ *
44
+ * The adapter still uses `gh api` for outbound calls, so when the fallback
45
+ * is in use the auth model is unchanged end-to-end.
46
+ */
47
+ var FunnelFlumeGhListener = class extends FunnelFlumeSourceListener {
48
+ config;
49
+ env;
50
+ process;
51
+ flumeDeps;
52
+ signal;
53
+ constructor(deps) {
54
+ super({
55
+ type: "gh",
56
+ connectorId: deps.config.id,
57
+ channelId: deps.channelId ?? null,
58
+ logger: deps.logger,
59
+ diagnosticLog: deps.diagnosticLog
60
+ });
61
+ this.config = deps.config;
62
+ this.env = deps.env ?? process.env;
63
+ this.process = deps.process ?? defaultProcess;
64
+ this.flumeDeps = deps.flumeDeps ?? {};
65
+ this.signal = deps.signal;
66
+ }
67
+ async start(notify) {
68
+ this.diagnostics.recordConnection("started", "");
69
+ let token;
70
+ try {
71
+ token = await this.resolveToken();
72
+ } catch (error) {
73
+ this.diagnostics.recordConnection("auth-failed", errorMessageOf(error));
74
+ throw error;
75
+ }
76
+ const source = new FlumeGitHubSource({
77
+ token,
78
+ pollInterval: this.config.pollInterval ?? 60
79
+ });
80
+ await this.runStart({
81
+ source,
82
+ onLog: flumeLogHandler(this.logger),
83
+ deps: resolveFlumeDeps(this.flumeDeps),
84
+ signal: this.signal,
85
+ onEvent: (event) => {
86
+ if (event.source !== "github") return Promise.resolve();
87
+ return this.handleEvent(event, notify);
88
+ }
89
+ });
90
+ }
91
+ async resolveToken() {
92
+ if (this.config.token) return this.config.token;
93
+ if (this.config.tokenEnv) {
94
+ const fromEnv = this.env[this.config.tokenEnv];
95
+ if (typeof fromEnv === "string" && fromEnv !== "") return fromEnv;
96
+ throw new Error(`${this.config.name}.token references env var "${this.config.tokenEnv}" but it is not set`);
97
+ }
98
+ const result = await this.process.run([
99
+ "gh",
100
+ "auth",
101
+ "token"
102
+ ]);
103
+ if (result.exitCode !== 0) throw new Error(`gh auth token failed: ${result.stderr.trim() || result.stdout.trim()}`);
104
+ return result.stdout.trim();
105
+ }
106
+ async handleEvent(event, notify) {
107
+ const eventId = event.data.id;
108
+ const rawJson = JSON.stringify(event.data);
109
+ this.diagnostics.recordRaw(eventId, rawJson);
110
+ const meta = {
111
+ ...event.meta,
112
+ event_type: "gh",
113
+ subject_url: event.data.subject.url ?? "",
114
+ updated_at: event.data.updated_at
115
+ };
116
+ await this.deliver(notify, eventId, rawJson, meta);
117
+ }
118
+ async deliver(notify, eventId, content, meta) {
119
+ try {
120
+ await notify(content, meta);
121
+ } catch (error) {
122
+ this.diagnostics.recordProcessed(eventId, "emitted:delivery-failed", content);
123
+ this.logger?.error("gh notify error", { error: errorMessageOf(error) });
124
+ return;
125
+ }
126
+ this.diagnostics.recordProcessed(eventId, "emitted", content);
127
+ }
128
+ };
129
+ //#endregion
130
+ //#region lib/engine/connectors/gh-connector.ts
131
+ /**
132
+ * GitHub connector descriptor. Pass `ghConnector()` to
133
+ * `new Funnel({ connectors: [...] })` to enable the type.
134
+ *
135
+ * The listener is backed by `@interactive-inc/flume`'s `FlumeGitHubSource`
136
+ * (raw REST polling + Zod), authenticating with a token resolved from the
137
+ * environment or `gh auth token`. The adapter still uses `gh api` for
138
+ * outbound calls, so the auth model is unchanged end-to-end.
139
+ */
140
+ const ghConnector = () => ({
141
+ type: "gh",
142
+ toolExposed: true,
143
+ createListener(config, deps) {
144
+ return new FunnelFlumeGhListener({
145
+ config: ghConnectorSchema.parse(config),
146
+ channelId: deps.channelId,
147
+ process: deps.process,
148
+ logger: deps.logger,
149
+ diagnosticLog: deps.diagnosticLog,
150
+ signal: deps.signal
151
+ });
152
+ },
153
+ createAdapter(config, deps) {
154
+ ghConnectorSchema.parse(config);
155
+ return new FunnelGhAdapter({ process: deps.process });
156
+ },
157
+ secretTokens(config) {
158
+ return [ghConnectorSchema.parse(config).token].filter((token) => token !== void 0);
159
+ },
160
+ buildConfig(input, context) {
161
+ return ghConnectorSchema.parse({
162
+ id: context.id,
163
+ type: "gh",
164
+ name: input.name,
165
+ ...typeof input.pollInterval === "number" ? { pollInterval: input.pollInterval } : {},
166
+ ...typeof input.token === "string" ? { token: input.token } : {},
167
+ ...typeof input.tokenEnv === "string" ? { tokenEnv: input.tokenEnv } : {},
168
+ createdAt: context.now,
169
+ updatedAt: context.now
170
+ });
171
+ },
172
+ applyUpdate(config, fields, context) {
173
+ const current = ghConnectorSchema.parse(config);
174
+ return ghConnectorSchema.parse({
175
+ id: current.id,
176
+ name: current.name,
177
+ type: "gh",
178
+ pollInterval: typeof fields.pollInterval === "number" ? fields.pollInterval : current.pollInterval,
179
+ createdAt: current.createdAt,
180
+ updatedAt: context.now,
181
+ ...slotFields("token", "tokenEnv", fields, current)
182
+ });
183
+ },
184
+ operations: {}
185
+ });
186
+ //#endregion
187
+ export { FunnelFlumeGhListener as n, FunnelGhAdapter as r, ghConnector as t };
@@ -5,6 +5,13 @@ const ghConnectorSchema = z.object({
5
5
  name: z.string(),
6
6
  type: z.literal("gh"),
7
7
  pollInterval: z.number().int().positive().optional(),
8
+ /**
9
+ * Explicit PAT/OAuth token. When neither this nor `tokenEnv` is set, the
10
+ * listener falls back to `gh auth token`, reusing the `gh` CLI's session.
11
+ */
12
+ token: z.string().optional(),
13
+ /** Name of an env var to read the token from at start time. */
14
+ tokenEnv: z.string().optional(),
8
15
  createdAt: z.string().datetime().optional(),
9
16
  updatedAt: z.string().datetime().optional()
10
17
  });
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+
3
+ //#region lib/engine/connectors/gh-connector-schema.d.ts
4
+ declare const ghConnectorSchema: z.ZodObject<{
5
+ id: z.ZodString;
6
+ name: z.ZodString;
7
+ type: z.ZodLiteral<"gh">;
8
+ pollInterval: z.ZodOptional<z.ZodNumber>;
9
+ token: z.ZodOptional<z.ZodString>;
10
+ tokenEnv: z.ZodOptional<z.ZodString>;
11
+ createdAt: z.ZodOptional<z.ZodString>;
12
+ updatedAt: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>;
14
+ type GhConnectorConfig = z.infer<typeof ghConnectorSchema>;
15
+ //#endregion
16
+ export { ghConnectorSchema as n, GhConnectorConfig as t };
@@ -1,6 +1,6 @@
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";
1
+ import { B as FunnelProcessRunner, C as ConnectorRawQuery, D as StoredRawEvent, E as StoredProcessedEvent, I as BaseConnectorConfig, T as StoredConnectionEvent, W as FunnelLogger, _ as ConnectorDiagnosticLog, b as ConnectorProcessedRecord, c as FunnelClock, h as ConnectorConnectionRecord, j as FunnelConnectorListener, m as ConnectorConnectionQuery, w as ConnectorRawRecord, y as ConnectorProcessedQuery } from "./connector-descriptor-ClEEbuW3.js";
2
+ import { n as FunnelFileSystem } from "./file-system-VhwwXZbm.js";
3
+ import { n as ChannelConnectorView, r as FunnelChannels } from "./channels-B8RQPrVq.js";
4
4
  import { z } from "zod";
5
5
  import { Hono } from "hono";
6
6
  import { ServerWebSocket } from "bun";
@@ -142,7 +142,7 @@ declare class FunnelBroadcaster {
142
142
  seedLatestOffset(offset: number): void;
143
143
  }
144
144
  //#endregion
145
- //#region lib/gateway/listener-supervisor.d.ts
145
+ //#region lib/gateway/listener-registry.d.ts
146
146
  type ConnectorRegistry = {
147
147
  listAllConnectors(): ChannelConnectorView[];
148
148
  createListener(channelName: string, connectorName: string): {
@@ -151,10 +151,10 @@ type ConnectorRegistry = {
151
151
  listener: FunnelConnectorListener;
152
152
  } | null;
153
153
  };
154
- type SupervisorNotify = (channelName: string, connectorName: string, content: string, meta?: Record<string, string>) => Promise<void>;
154
+ type ListenerRegistryNotify = (channelName: string, connectorName: string, content: string, meta?: Record<string, string>) => Promise<void>;
155
155
  type Deps$3 = {
156
156
  channels: ConnectorRegistry;
157
- notify: SupervisorNotify;
157
+ notify: ListenerRegistryNotify;
158
158
  logger?: FunnelLogger; /** Host hook for surfacing listener lifecycle exceptions. Defaults to no-op. */
159
159
  onError?: OnFunnelError;
160
160
  healthCheckIntervalMs?: number;
@@ -189,13 +189,14 @@ type ListenerEntryStatus = {
189
189
  * dead listeners with exponential backoff (1s, 2s, 4s, ... capped). Resets
190
190
  * the backoff counter on successful restart.
191
191
  */
192
- declare class FunnelListenerSupervisor {
192
+ declare class FunnelListenerRegistry {
193
193
  private readonly channels;
194
194
  private readonly notify;
195
195
  private readonly logger;
196
196
  private readonly onError;
197
197
  private readonly running;
198
198
  private readonly failureCounts;
199
+ private readonly starting;
199
200
  private readonly stats;
200
201
  private readonly healthCheckIntervalMs;
201
202
  private readonly maxBackoffMs;
@@ -213,14 +214,18 @@ declare class FunnelListenerSupervisor {
213
214
  start(channelName: string, connectorName: string): Promise<{
214
215
  ok: boolean;
215
216
  reason?: string;
217
+ retriable?: boolean;
216
218
  }>;
219
+ private startLocked;
217
220
  stop(channelName: string, connectorName: string): Promise<{
218
221
  ok: boolean;
219
222
  reason?: string;
223
+ retriable?: boolean;
220
224
  }>;
221
225
  restart(channelName: string, connectorName: string): Promise<{
222
226
  ok: boolean;
223
227
  reason?: string;
228
+ retriable?: boolean;
224
229
  }>;
225
230
  startAll(): Promise<void>;
226
231
  stopAll(): Promise<void>;
@@ -232,6 +237,7 @@ declare class FunnelListenerSupervisor {
232
237
  /** Run one health-check pass synchronously. Test-only seam. */
233
238
  runHealthCheckForTest(): Promise<void>;
234
239
  private runHealthCheck;
240
+ private attemptRetry;
235
241
  private recoverDead;
236
242
  }
237
243
  //#endregion
@@ -248,7 +254,7 @@ type GatewayRouteDeps = {
248
254
  * daemon answering on a shared port belongs to the expected repo/scope. */
249
255
  dir: string;
250
256
  broadcaster: FunnelBroadcaster;
251
- supervisor: FunnelListenerSupervisor;
257
+ registry: FunnelListenerRegistry;
252
258
  channels: FunnelChannels;
253
259
  uptimeMs: () => number;
254
260
  emit: (input: GatewayEmitInput) => {
@@ -357,7 +363,7 @@ type Deps$2 = GatewayEventStore & {
357
363
  };
358
364
  /**
359
365
  * In-process gateway: runs `Bun.serve` (HTTP + WebSocket /ws), boots connector
360
- * listeners through `FunnelListenerSupervisor`, fans events out via
366
+ * listeners through `FunnelListenerRegistry`, fans events out via
361
367
  * `FunnelBroadcaster`, and persists them via a `FunnelEventLog` (SQLite by default).
362
368
  * System events (gateway lifecycle, connect/disconnect) flow to `FunnelLogger`
363
369
  * instead — keeping the SQLite seq space exclusive to broadcaster traffic so
@@ -380,11 +386,13 @@ declare class FunnelGatewayServer {
380
386
  private readonly allowInsecureHost;
381
387
  private readonly broadcaster;
382
388
  private readonly eventLog;
383
- private readonly supervisor;
389
+ private readonly registry;
384
390
  private readonly nowMs;
385
391
  private readonly extraRoutes;
392
+ private readonly ownsEventLog;
386
393
  private startedAt;
387
394
  private server;
395
+ private disposed;
388
396
  constructor(deps: Deps$2);
389
397
  /**
390
398
  * The resolved listen port: the live Bun server's port once started (so
@@ -403,7 +411,7 @@ declare class FunnelGatewayServer {
403
411
  }[];
404
412
  };
405
413
  getBroadcaster(): FunnelBroadcaster;
406
- getSupervisor(): FunnelListenerSupervisor;
414
+ getRegistry(): FunnelListenerRegistry;
407
415
  getEventLog(): FunnelEventLog;
408
416
  /**
409
417
  * Register an in-process observer for every broadcast event. Fires after
@@ -517,12 +525,12 @@ declare class FunnelGatewayToken {
517
525
  constructor(deps?: Deps$1);
518
526
  read(): string | null;
519
527
  /**
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.
528
+ * Returns the existing token or, if missing, generates one and writes it
529
+ * with mode 0600. Read+write runs inside an exclusive lock so two
530
+ * concurrent `ensure()` calls (a daemon spawn racing a CLI helper that
531
+ * reads the token before the gateway PID lock is acquired) cannot each
532
+ * persist a different token and leave one side authenticating against a
533
+ * value the other never sees.
526
534
  */
527
535
  ensure(): string;
528
536
  getPath(): string;
@@ -582,7 +590,13 @@ declare class FunnelChannelPublisher {
582
590
  type Props$1 = {
583
591
  /** SQLite database file path. Created on first write. ":memory:" for tests. */path: string; /** Override for tests. Defaults to `Date.now`. */
584
592
  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. */
593
+ logger?: FunnelLogger;
594
+ /**
595
+ * Host-supplied error sink. Routed alongside the logger when a write
596
+ * fails, so Sentry / Datadog / a custom alert pipeline sees the durable
597
+ * replay loss too — not just the local log file. Silent if absent.
598
+ */
599
+ onError?: OnFunnelError; /** Optional row cap. Pruned on every insert. */
586
600
  maxRows?: number; /** Optional age cap in ms. Pruned on every insert. */
587
601
  maxAgeMs?: number; /** Optional on-disk byte cap. Checked periodically; on overflow the oldest rows are dropped toward targetBytes and the file is VACUUMed. */
588
602
  maxBytes?: number; /** Shrink target when maxBytes is exceeded. Defaults to maxBytes/4. */
@@ -609,6 +623,7 @@ declare class SqliteFunnelEventLog extends FunnelEventLog {
609
623
  private readonly sink;
610
624
  private readonly now;
611
625
  private readonly logger;
626
+ private readonly onError;
612
627
  constructor(props: Props$1);
613
628
  /**
614
629
  * Persist a broadcaster-driven event with its assigned offset. Caller
@@ -896,6 +911,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
896
911
  output: {
897
912
  ok: boolean;
898
913
  reason?: string | undefined;
914
+ retriable?: boolean | undefined;
899
915
  };
900
916
  outputFormat: "json";
901
917
  status: 200 | 400;
@@ -926,6 +942,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
926
942
  output: {
927
943
  ok: boolean;
928
944
  reason?: string | undefined;
945
+ retriable?: boolean | undefined;
929
946
  };
930
947
  outputFormat: "json";
931
948
  status: 200 | 400;
@@ -956,6 +973,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
956
973
  output: {
957
974
  ok: boolean;
958
975
  reason?: string | undefined;
976
+ retriable?: boolean | undefined;
959
977
  };
960
978
  outputFormat: "json";
961
979
  status: 200 | 400;
@@ -1054,4 +1072,4 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env, {
1054
1072
  };
1055
1073
  }, "/", "/channels/:channel/publish">;
1056
1074
  //#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 };
1075
+ 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 };