@interactive-inc/claude-funnel 0.67.0 → 0.68.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 (54) hide show
  1. package/README.md +24 -3
  2. package/dist/bin.js +276 -270
  3. package/dist/{channels-BBA3GTAa.d.ts → channels-B0cifCfw.d.ts} +2 -1
  4. package/dist/claude.d.ts +2 -2
  5. package/dist/claude.js +5 -5
  6. package/dist/connector-descriptor-D4XtEsH8.d.ts +215 -0
  7. package/dist/connectors/discord.d.ts +3 -2
  8. package/dist/connectors/discord.js +1 -1
  9. package/dist/connectors/gh.d.ts +3 -2
  10. package/dist/connectors/gh.js +1 -1
  11. package/dist/connectors/schedule.d.ts +13 -11
  12. package/dist/connectors/schedule.js +3 -3
  13. package/dist/connectors/slack.d.ts +3 -2
  14. package/dist/connectors/slack.js +1 -1
  15. package/dist/diagnostic-event-CxMM5Bl2.js +78 -0
  16. package/dist/diagnostic-log-BsAg5qZK.d.ts +186 -0
  17. package/dist/diagnostics.d.ts +2 -2
  18. package/dist/diagnostics.js +3 -2
  19. package/dist/{discord-connector-CdjwPoty.js → discord-connector-CAcWifJn.js} +1 -1
  20. package/dist/docs.js +1 -1
  21. package/dist/doctor.d.ts +1 -1
  22. package/dist/event-log.d.ts +2 -0
  23. package/dist/event-log.js +3 -0
  24. package/dist/{file-process-guard-DAYe9Ndt.d.ts → file-process-guard-D-QatrwL.d.ts} +1 -1
  25. package/dist/{flume-source-listener-CLtsdcT2.d.ts → flume-source-listener-Ba8_1Mg-.d.ts} +2 -1
  26. package/dist/{funnel-diagnostics-B-PCuv_E.js → funnel-diagnostics-CAG7hJP0.js} +82 -139
  27. package/dist/{funnel-diagnostics-CnKus3Jg.d.ts → funnel-diagnostics-CDrZznTB.d.ts} +10 -13
  28. package/dist/{funnel-docs-BFcqITFA.js → funnel-docs-CI4hMkhq.js} +8 -3
  29. package/dist/{funnel-doctor-CviUTINw.d.ts → funnel-doctor-CY4S5cnz.d.ts} +1 -1
  30. package/dist/gateway/daemon.js +59 -79
  31. package/dist/gateway.d.ts +2 -2
  32. package/dist/gateway.js +1 -1
  33. package/dist/{gh-connector-D-iyjl-d.js → gh-connector-DMwI6zJA.js} +1 -1
  34. package/dist/{index-B4RvEaW-.d.ts → index-fHrKn4jm.d.ts} +7 -2
  35. package/dist/index.d.ts +18 -14
  36. package/dist/index.js +124 -30
  37. package/dist/local-config.d.ts +1 -1
  38. package/dist/logger.d.ts +6 -270
  39. package/dist/logger.js +6 -141
  40. package/dist/memory-event-log-BY8XjFzi.js +147 -0
  41. package/dist/{memory-token-prompter-D3R_kgM_.d.ts → memory-token-prompter-B20tl_aU.d.ts} +1 -1
  42. package/dist/{schedule-connector-teeDMHUe.js → schedule-connector-BXUOYgwZ.js} +59 -95
  43. package/dist/schedule-connector-schema-CNV8PgWX.js +137 -0
  44. package/dist/schedule-connector-schema-Tq5kJul-.d.ts +127 -0
  45. package/dist/{slack-connector-BE0KAjCs.js → slack-connector-CC3V2VXQ.js} +1 -1
  46. package/dist/{slot-fields-5ERhytIA.js → slot-fields-eCWizJqS.js} +1 -1
  47. package/dist/{sqlite-diagnostic-log-BDxfXGZy.js → sqlite-diagnostic-log-Qs4cf9I_.js} +53 -84
  48. package/dist/sqlite-event-log-BYgCFMxC.d.ts +284 -0
  49. package/dist/{funnel-log-sqlite-sink-CXbs3qQp.js → sqlite-event-log-eZuXKszJ.js} +52 -11
  50. package/package.json +16 -1
  51. package/dist/connector-descriptor-F75ZI8Fh.d.ts +0 -391
  52. package/dist/diagnostic-sql-reader-CoBk_EFF.js +0 -83
  53. package/dist/schedule-connector-schema-C2AChpwX.js +0 -31
  54. package/dist/schedule-connector-schema-DBko_Bf7.d.ts +0 -48
package/dist/gateway.d.ts CHANGED
@@ -1,3 +1,3 @@
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";
1
+ import { _ as connectorConnectionEventSchema, a as ConnectorConnectionStatus, c as ConnectorProcessedQuery, d as ConnectorRawEvent, f as ConnectorRawQuery, g as StoredRawEvent, h as StoredProcessedEvent, i as ConnectorConnectionRecord, l as ConnectorProcessedRecord, m as StoredConnectionEvent, n as ConnectorConnectionEvent, o as ConnectorDiagnosticLog, p as ConnectorRawRecord, r as ConnectorConnectionQuery, s as ConnectorProcessedEvent, t as CONNECTOR_CONNECTION_STATUSES, u as ConnectorQuery, v as connectorProcessedEventSchema, y as connectorRawEventSchema } from "./diagnostic-log-BsAg5qZK.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-fHrKn4jm.js";
3
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
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";
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-Qs4cf9I_.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 };
@@ -2,7 +2,7 @@ import { t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js"
2
2
  import { t as errorMessageOf } from "./error-message-of-BG4ezZ_s.js";
3
3
  import { t as ghConnectorSchema } from "./gh-connector-schema-DmZTrzUu.js";
4
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";
5
+ import { i as resolveFlumeDeps, n as FunnelFlumeSourceListener, r as flumeLogHandler, t as slotFields } from "./slot-fields-eCWizJqS.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,7 +1,8 @@
1
1
  import { n as FunnelClock, t as FunnelLogger } from "./logger-mMZvblTx.js";
2
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";
3
+ import { b as FunnelProcessRunner, d as FunnelConnectorListener, g as BaseConnectorConfig } from "./connector-descriptor-D4XtEsH8.js";
4
+ import { c as ConnectorProcessedQuery, f as ConnectorRawQuery, g as StoredRawEvent, h as StoredProcessedEvent, i as ConnectorConnectionRecord, l as ConnectorProcessedRecord, m as StoredConnectionEvent, o as ConnectorDiagnosticLog, p as ConnectorRawRecord, r as ConnectorConnectionQuery } from "./diagnostic-log-BsAg5qZK.js";
5
+ import { n as ChannelConnectorView, r as FunnelChannels } from "./channels-B0cifCfw.js";
5
6
  import { z } from "zod";
6
7
  import { Hono } from "hono";
7
8
  import { ServerWebSocket } from "bun";
@@ -268,6 +269,7 @@ type GatewayRouteDeps = {
268
269
  emit: (input: GatewayEmitInput) => {
269
270
  offset: number;
270
271
  };
272
+ diagnosticLog?: ConnectorDiagnosticLog;
271
273
  };
272
274
  //#endregion
273
275
  //#region lib/gateway/factory.d.ts
@@ -374,6 +376,8 @@ type Deps$2 = GatewayEventStore & {
374
376
  * `/channels`, `/health` are mounted after and take precedence on conflict.
375
377
  */
376
378
  extraRoutes?: Hono<Env>;
379
+ /** Read-side diagnostic source exposed to the built-in debug route. */
380
+ diagnosticLog?: ConnectorDiagnosticLog;
377
381
  };
378
382
  /**
379
383
  * In-process gateway: runs `Bun.serve` (HTTP + WebSocket /ws), boots connector
@@ -404,6 +408,7 @@ declare class FunnelGatewayServer {
404
408
  private readonly nowMs;
405
409
  private readonly extraRoutes;
406
410
  private readonly ownsEventLog;
411
+ private readonly diagnosticLog;
407
412
  private startedAt;
408
413
  private server;
409
414
  private disposed;
package/dist/index.d.ts CHANGED
@@ -1,21 +1,22 @@
1
1
  import { n as FunnelClock, t as FunnelLogger } from "./logger-mMZvblTx.js";
2
2
  import { n as FunnelFileSystem, t as FileStat } from "./file-system-BNtl997T.js";
3
3
  import { a as Settings, c as profileConfigSchema, i as SETTINGS_VERSION, l as settingsSchema, n as ChannelDeliveryMode, o as channelConfigSchema, r as ProfileConfig, s as channelDeliveryModeSchema, t as ChannelConfig } from "./settings-schema-B-CKLuST.js";
4
- import { n as FunnelClaude, t as FunnelFileProcessGuard } from "./file-process-guard-DAYe9Ndt.js";
4
+ import { n as FunnelClaude, t as FunnelFileProcessGuard } from "./file-process-guard-D-QatrwL.js";
5
5
  import { n as FunnelIdGenerator, t as FunnelSettingsReader } from "./settings-reader-CyTpbAre.js";
6
- import { A as FunnelConnectorListener, B as ProcessSnapshot, C as ConnectorRawRecord, D as connectorConnectionEventSchema, E as StoredRawEvent, F as BaseConnectorConfig, H as RunResult, I as baseConnectorConfigSchema, L as AttachOptions, M as CallInput, N as FunnelConnectorAdapter, O as connectorProcessedEventSchema, P as JsonValue, R as DetachOptions, S as ConnectorRawQuery, T as StoredProcessedEvent, V as RunOptions, _ as ConnectorProcessedEvent, a as ConnectorOperation, b as ConnectorQuery, c as FunnelHttpClient, d as CONNECTOR_CONNECTION_STATUSES, f as ConnectorConnectionEvent, g as ConnectorDiagnosticLog, h as ConnectorConnectionStatus, i as ConnectorListenerDeps, j as NotifyFn, k as connectorRawEventSchema, l as HttpRequest, m as ConnectorConnectionRecord, n as ConnectorBuildContext, o as ConnectorOperationContext, p as ConnectorConnectionQuery, r as ConnectorDescriptor, s as ConnectorUpdateContext, t as ConnectorAdapterDeps, u as HttpResponse, v as ConnectorProcessedQuery, w as StoredConnectionEvent, x as ConnectorRawEvent, y as ConnectorProcessedRecord, z as FunnelProcessRunner } from "./connector-descriptor-F75ZI8Fh.js";
6
+ import { C as RunResult, S as RunOptions, _ as baseConnectorConfigSchema, a as ConnectorOperation, b as FunnelProcessRunner, c as FunnelHttpClient, d as FunnelConnectorListener, f as NotifyFn, g as BaseConnectorConfig, h as JsonValue, i as ConnectorListenerDeps, l as HttpRequest, m as FunnelConnectorAdapter, n as ConnectorBuildContext, o as ConnectorOperationContext, p as CallInput, r as ConnectorDescriptor, s as ConnectorUpdateContext, t as ConnectorAdapterDeps, u as HttpResponse, v as AttachOptions, x as ProcessSnapshot, y as DetachOptions } from "./connector-descriptor-D4XtEsH8.js";
7
+ import { _ as connectorConnectionEventSchema, a as ConnectorConnectionStatus, c as ConnectorProcessedQuery, d as ConnectorRawEvent, f as ConnectorRawQuery, g as StoredRawEvent, h as StoredProcessedEvent, i as ConnectorConnectionRecord, l as ConnectorProcessedRecord, m as StoredConnectionEvent, n as ConnectorConnectionEvent, o as ConnectorDiagnosticLog, p as ConnectorRawRecord, r as ConnectorConnectionQuery, s as ConnectorProcessedEvent, t as CONNECTOR_CONNECTION_STATUSES, u as ConnectorQuery, v as connectorProcessedEventSchema, y as connectorRawEventSchema } from "./diagnostic-log-BsAg5qZK.js";
7
8
  import { t as FunnelProfiles } from "./profiles-CePRnv3F.js";
8
- import { a as DiagnosticsGatewayProbe, c as FunnelDiagnostics, d as DiagnosticEvent, f as previewOf, g as ConnectorDiagnosticSqlReader, h as toDiagnosticEvent, i as DiagnosticsChannelSource, l as ReplayResult, m as toDiagnosticConnectionError, n as DiagnoseAllReport, o as DiagnosticsPublisher, p as queryRows, r as DiagnosisStatus, s as DiagnosticsTokenReader, t as ChannelDiagnosis, u as DiagnosticConnectionError } from "./funnel-diagnostics-CnKus3Jg.js";
9
+ import { _ as toDiagnosticConnectionError, a as DiagnosticsGatewayProbe, c as FunnelDiagnostics, d as DiagnosticEvent, f as diagnosticConnectionEventOf, g as queryRows, h as previewOf, i as DiagnosticsChannelSource, l as ReplayResult, m as diagnosticEventOfRaw, n as DiagnoseAllReport, o as DiagnosticsPublisher, p as diagnosticEventOfProcessed, r as DiagnosisStatus, s as DiagnosticsTokenReader, t as ChannelDiagnosis, u as DiagnosticConnectionError, v as toDiagnosticEvent, y as ConnectorDiagnosticSqlReader } from "./funnel-diagnostics-CDrZznTB.js";
9
10
  import { n as FunnelDocs, t as DocsTopicListing } from "./funnel-docs-BJWawfWI.js";
10
11
  import { a as RecoveryListenerControl, i as RecoveryGatewayControl, n as RecoveryAction, o as RecoveryResult, r as RecoveryChannelSource, t as FunnelRecovery } from "./funnel-recovery-BwcSNNSN.js";
11
- import { n as DoctorReport, r as FunnelDoctor, t as DoctorFixMode } from "./funnel-doctor-CviUTINw.js";
12
+ import { n as DoctorReport, r as FunnelDoctor, t as DoctorFixMode } from "./funnel-doctor-CY4S5cnz.js";
12
13
  import { n as discordConnectorSchema, t as DiscordConnectorConfig } from "./discord-connector-schema-BaBZYHxK.js";
13
14
  import { n as ghConnectorSchema, t as GhConnectorConfig } from "./gh-connector-schema-BrNsCl1T.js";
14
- import { a as scheduleConnectorSchema, i as scheduleCatchupPolicySchema, n as ScheduleConnectorConfig, o as scheduleEntrySchema, r as ScheduleEntry, t as ScheduleCatchupPolicy } from "./schedule-connector-schema-DBko_Bf7.js";
15
+ import { a as ScheduleEntry, c as cronScheduleEntrySchema, d as scheduleConnectorSchema, f as scheduleEntryInputSchema, i as ScheduleConnectorConfig, l as onceScheduleEntrySchema, n as OnceScheduleEntry, o as ScheduleEntryInput, p as scheduleEntrySchema, r as ScheduleCatchupPolicy, s as cronExpressionSchema, t as CronScheduleEntry, u as scheduleCatchupPolicySchema } from "./schedule-connector-schema-Tq5kJul-.js";
15
16
  import { a as SlackRawEvent, c as SlackMessageEvent, d as slackConnectorSchema, i as SlackProcessedSkip, l as SlackReactionEvent, n as SlackProcessed, o as SlackSkipReason, r as SlackProcessedEmit, s as SlackEvent, t as FunnelSlackEventProcessor, u as SlackConnectorConfig } from "./slack-event-processor-DmAlq4cV.js";
16
- import { i as FunnelConnectorRegistry, n as ChannelConnectorView, r as FunnelChannels, t as AddConnectorInput } from "./channels-BBA3GTAa.js";
17
- import { A as FunnelBroadcaster, C as funnelEventSchema, D as FunnelListenerRegistry, E as GatewayRouteDeps, M as OnFunnelError, 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$1, x as FunnelEventLog, y as GatewayEventStore } from "./index-B4RvEaW-.js";
18
- import { i as FunnelLocalConfigSync, n as NodeFunnelTokenPrompter, o as FunnelTokenPrompter, s as FunnelLocalConfig, t as MemoryFunnelTokenPrompter } from "./memory-token-prompter-D3R_kgM_.js";
17
+ import { i as FunnelConnectorRegistry, n as ChannelConnectorView, r as FunnelChannels, t as AddConnectorInput } from "./channels-B0cifCfw.js";
18
+ import { A as FunnelBroadcaster, C as funnelEventSchema, D as FunnelListenerRegistry, E as GatewayRouteDeps, M as OnFunnelError, 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$1, x as FunnelEventLog, y as GatewayEventStore } from "./index-fHrKn4jm.js";
19
+ import { i as FunnelLocalConfigSync, n as NodeFunnelTokenPrompter, o as FunnelTokenPrompter, s as FunnelLocalConfig, t as MemoryFunnelTokenPrompter } from "./memory-token-prompter-B20tl_aU.js";
19
20
  import { hc } from "hono/client";
20
21
  import { z } from "zod";
21
22
  import { Hono } from "hono";
@@ -157,9 +158,10 @@ type Props$4 = {
157
158
  connectors?: ConnectorDescriptor[];
158
159
  /**
159
160
  * Diagnostic log of inbound connector traffic (raw events before filtering
160
- * and the processor's verdict after). Threaded into listeners that record
161
- * it. Only the gateway daemon injects a `SqliteConnectorDiagnosticLog`; everywhere
162
- * else this stays absent and recording is a no-op.
161
+ * and the processor's verdict after). The same instance is threaded into
162
+ * listeners for writes and `funnel.diagnostics` for reads, so custom storage
163
+ * paths remain opaque to the service layer. Omit it to disable event
164
+ * diagnostics for this facade.
163
165
  */
164
166
  diagnosticLog?: ConnectorDiagnosticLog;
165
167
  /**
@@ -251,6 +253,7 @@ declare class Funnel {
251
253
  private readonly clock;
252
254
  private readonly http;
253
255
  private readonly onError;
256
+ private readonly diagnosticLog;
254
257
  constructor(props?: Props$4);
255
258
  /**
256
259
  * Sandboxed Funnel wired with in-memory implementations for every IO
@@ -1214,7 +1217,7 @@ declare const routes: import("hono/hono-base").HonoBase<Env, {
1214
1217
  connector: string;
1215
1218
  };
1216
1219
  };
1217
- output: "funnel channels <ch> connectors <conn> schedules add <id> — add a schedule entry\n\nusage: funnel channels <ch> connectors <conn> schedules add <id> --cron=\"*/5 * * * *\" --prompt=\"...\" [--enabled|--enabled=false] [--catchup-policy=latest|all|skip]\n\noptions:\n --cron <expr> / 5-field cron expression (required)\n --prompt <text> / prompt delivered on each fire (required)\n --enabled / fire on schedule (default: true; --enabled=false stores it disabled)\n --catchup-policy latest|all|skip / how missed fires are replayed after downtime (default: latest)";
1220
+ output: "funnel channels <ch> connectors <conn> schedules add <id> — add a schedule entry\n\nusage: funnel channels <ch> connectors <conn> schedules add <id> (--cron=\"*/5 * * * *\" | --run-at=\"2026-08-01T09:00:00+09:00\") --prompt=\"...\" [--enabled|--enabled=false] [--catchup-policy=latest|all|skip]\n\noptions:\n --cron <expr> / 5-field cron expression (exclusive with --run-at)\n --run-at <ISO datetime> / fire once at or after this instant (exclusive with --cron)\n --prompt <text> / prompt delivered on each fire (required)\n --enabled / fire on schedule (default: true; --enabled=false stores it disabled)\n --catchup-policy latest|all|skip / how missed fires are replayed after downtime (default: latest)";
1218
1221
  outputFormat: "text";
1219
1222
  status: import("hono/utils/http-status").ContentfulStatusCode;
1220
1223
  };
@@ -1230,8 +1233,9 @@ declare const routes: import("hono/hono-base").HonoBase<Env, {
1230
1233
  };
1231
1234
  } & {
1232
1235
  query: {
1233
- cron: string;
1234
1236
  prompt: string;
1237
+ cron?: string | undefined;
1238
+ "run-at"?: string | undefined;
1235
1239
  enabled?: "" | "true" | "false" | undefined;
1236
1240
  "catchup-policy"?: "latest" | "all" | "skip" | undefined;
1237
1241
  };
@@ -1742,4 +1746,4 @@ declare const routes: import("hono/hono-base").HonoBase<Env, {
1742
1746
  }, "/", "/update">;
1743
1747
  type CliApp = typeof routes;
1744
1748
  //#endregion
1745
- export { AddConnectorInput, AliveStub, AttachOptions, BaseConnectorConfig, BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, CallInput, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelDiagnosis, ChannelWsUrlInput, type CliApp, ConnectorAdapterDeps, ConnectorBuildContext, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDescriptor, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, ConnectorListenerDeps, ConnectorOperation, ConnectorOperationContext, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, ConnectorUpdateContext, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiagnoseAllReport, DiagnosisStatus, DiagnosticConnectionError, DiagnosticEvent, DiagnosticsChannelSource, DiagnosticsGatewayProbe, DiagnosticsPublisher, DiagnosticsTokenReader, DiscordConnectorConfig, DocsTopicListing, DoctorFixMode, DoctorReport, Env, FUNNEL_DIR, FileStat, Funnel, FunnelAuthFailedError, FunnelBroadcaster, FunnelChannelAlreadyExistsError, FunnelChannelNotFoundError, FunnelChannelPublisher, FunnelChannels, FunnelClock, FunnelConnectorAdapter, FunnelConnectorListener, FunnelConnectorNotFoundError, FunnelConnectorRegistry, FunnelConnectorTypeMismatchError, FunnelDiagnostics, FunnelDocs, FunnelDoctor, FunnelError, FunnelEvent, FunnelEventLog, FunnelEventRecord, FunnelFileSystem, FunnelGateway, FunnelGatewayBindError, FunnelGatewayServer, FunnelGatewayToken, FunnelHttpClient, FunnelIdGenerator, FunnelListenerRegistry, FunnelListenersClient, FunnelLogger, FunnelProcessRunner, FunnelRecovery, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenCollisionError, FunnelTokenPrompter, type GatewayApp, type GatewayEmitInput, GatewayEventStore, type GatewayRouteDeps, type Env$1 as GatewayServerEnv, GatewayServerOptions, GhConnectorConfig, HttpRequest, HttpResponse, JsonValue, ListListenersResult, ListenerEntry, ListenerOpResult, LogEntry, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelHttpClient, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MemoryHttpHandler, MemoryHttpResponse, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelHttpClient, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, NotifyFn, OnFunnelError, ProcessListStub, ProcessSnapshot, ProfileConfig, PublishRequest, PublishResponse, PublishResult, RecoveryAction, RecoveryChannelSource, RecoveryGatewayControl, RecoveryListenerControl, RecoveryResult, ReplayResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, Settings, SlackConnectorConfig, SlackEvent, SlackMessageEvent, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, SlackReactionEvent, SlackSkipReason, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StartTimeStub, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, baseConnectorConfigSchema, buildServiceRoutes, channelConfigSchema, channelDeliveryModeSchema, channelWsProtocols, channelWsUrl, routes as cliRoutes, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, createSettings, discordConnectorSchema, expandHomeDir, factory, funnelEventSchema, gatewayLoopbackUrl, ghConnectorSchema, previewOf, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryRows, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, toDiagnosticConnectionError, toDiagnosticEvent, toRequest };
1749
+ export { AddConnectorInput, AliveStub, AttachOptions, BaseConnectorConfig, BroadcastEvent, BroadcastSubscriber, CONNECTOR_CONNECTION_STATUSES, CallInput, ChannelConfig, ChannelConnectorView, ChannelDeliveryMode, ChannelDiagnosis, ChannelWsUrlInput, type CliApp, ConnectorAdapterDeps, ConnectorBuildContext, ConnectorConnectionEvent, ConnectorConnectionQuery, ConnectorConnectionRecord, ConnectorConnectionStatus, ConnectorDescriptor, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, ConnectorListenerDeps, ConnectorOperation, ConnectorOperationContext, ConnectorProcessedEvent, ConnectorProcessedQuery, ConnectorProcessedRecord, ConnectorQuery, ConnectorRawEvent, ConnectorRawQuery, ConnectorRawRecord, ConnectorUpdateContext, CronScheduleEntry, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, DetachOptions, DiagnoseAllReport, DiagnosisStatus, DiagnosticConnectionError, DiagnosticEvent, DiagnosticsChannelSource, DiagnosticsGatewayProbe, DiagnosticsPublisher, DiagnosticsTokenReader, DiscordConnectorConfig, DocsTopicListing, DoctorFixMode, DoctorReport, Env, FUNNEL_DIR, FileStat, Funnel, FunnelAuthFailedError, FunnelBroadcaster, FunnelChannelAlreadyExistsError, FunnelChannelNotFoundError, FunnelChannelPublisher, FunnelChannels, FunnelClock, FunnelConnectorAdapter, FunnelConnectorListener, FunnelConnectorNotFoundError, FunnelConnectorRegistry, FunnelConnectorTypeMismatchError, FunnelDiagnostics, FunnelDocs, FunnelDoctor, FunnelError, FunnelEvent, FunnelEventLog, FunnelEventRecord, FunnelFileSystem, FunnelGateway, FunnelGatewayBindError, FunnelGatewayServer, FunnelGatewayToken, FunnelHttpClient, FunnelIdGenerator, FunnelListenerRegistry, FunnelListenersClient, FunnelLogger, FunnelProcessRunner, FunnelRecovery, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenCollisionError, FunnelTokenPrompter, type GatewayApp, type GatewayEmitInput, GatewayEventStore, type GatewayRouteDeps, type Env$1 as GatewayServerEnv, GatewayServerOptions, GhConnectorConfig, HttpRequest, HttpResponse, JsonValue, ListListenersResult, ListenerEntry, ListenerOpResult, LogEntry, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelHttpClient, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MemoryHttpHandler, MemoryHttpResponse, MemoryProcessCall, MemoryProcessHandler, MemoryProcessResponse, MemoryProcessSyncHandler, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelHttpClient, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, NotifyFn, OnFunnelError, OnceScheduleEntry, ProcessListStub, ProcessSnapshot, ProfileConfig, PublishRequest, PublishResponse, PublishResult, RecoveryAction, RecoveryChannelSource, RecoveryGatewayControl, RecoveryListenerControl, RecoveryResult, ReplayResult, ReplayableEvent, RunOptions, RunResult, SETTINGS_PATH, SETTINGS_VERSION, ScheduleCatchupPolicy, ScheduleConnectorConfig, ScheduleEntry, ScheduleEntryInput, Settings, SlackConnectorConfig, SlackEvent, SlackMessageEvent, SlackProcessed, SlackProcessedEmit, SlackProcessedSkip, SlackRawEvent, SlackReactionEvent, SlackSkipReason, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, StartTimeStub, StoredConnectionEvent, StoredProcessedEvent, StoredRawEvent, baseConnectorConfigSchema, buildServiceRoutes, channelConfigSchema, channelDeliveryModeSchema, channelWsProtocols, channelWsUrl, routes as cliRoutes, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, createSettings, cronExpressionSchema, cronScheduleEntrySchema, diagnosticConnectionEventOf, diagnosticEventOfProcessed, diagnosticEventOfRaw, discordConnectorSchema, expandHomeDir, factory, funnelEventSchema, gatewayLoopbackUrl, ghConnectorSchema, onceScheduleEntrySchema, previewOf, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryRows, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntryInputSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, toDiagnosticConnectionError, toDiagnosticEvent, toRequest };
package/dist/index.js CHANGED
@@ -6,26 +6,27 @@ import { a as expandHomeDir, c as SETTINGS_VERSION, d as profileConfigSchema, f
6
6
  import { a as FunnelConnectorTypeMismatchError, c as FunnelTokenCollisionError, i as FunnelConnectorNotFoundError, n as FunnelChannelAlreadyExistsError, o as FunnelError, r as FunnelChannelNotFoundError, s as FunnelGatewayBindError, t as FunnelAuthFailedError } from "./funnel-error-DoSBCogD.js";
7
7
  import { a as FunnelMcp, o as FunnelFileProcessGuard, s as FunnelClaude, t as renderYaml } from "./yaml-render-DxxRQT-V.js";
8
8
  import { n as sessionFileExists, t as FunnelProfiles } from "./profiles-KpN7_gBw.js";
9
- import { a as toDiagnosticEvent, i as toDiagnosticConnectionError, n as previewOf, r as queryRows, t as FunnelDiagnostics } from "./funnel-diagnostics-B-PCuv_E.js";
10
- import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-CoBk_EFF.js";
9
+ import { a as queryRows, i as previewOf, n as diagnosticEventOfProcessed, o as toDiagnosticConnectionError, r as diagnosticEventOfRaw, s as toDiagnosticEvent, t as diagnosticConnectionEventOf } from "./diagnostic-event-CxMM5Bl2.js";
10
+ import { t as FunnelDiagnostics } from "./funnel-diagnostics-CAG7hJP0.js";
11
11
  import { t as FunnelDoctor } from "./funnel-doctor-Csw5qjcH.js";
12
- import { t as FunnelDocs } from "./funnel-docs-BFcqITFA.js";
12
+ import { t as FunnelDocs } from "./funnel-docs-CI4hMkhq.js";
13
13
  import { a as FunnelTokenPrompter, i as FunnelLocalConfigSync, n as MemoryFunnelTokenPrompter, o as FunnelLocalConfig, r as NodeFunnelTokenPrompter, t as funnelJsonSchema } from "./local-config-json-schema-_-YVHX4c.js";
14
14
  import { t as discordConnectorSchema } from "./discord-connector-schema-saAGuPmJ.js";
15
15
  import { t as ghConnectorSchema } from "./gh-connector-schema-DmZTrzUu.js";
16
16
  import { t as slackConnectorSchema } from "./slack-connector-schema-EGVuuqSX.js";
17
17
  import { t as FunnelRecovery } from "./funnel-recovery-DYbSYGWC.js";
18
- import { C as funnelTmpDir, 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, p as requireBearerToken, 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";
18
+ import { C as funnelTmpDir, 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, p as requireBearerToken, 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-Qs4cf9I_.js";
19
19
  import { t as FunnelConnectorAdapter } from "./connector-adapter-BL2ehMej.js";
20
20
  import { t as FunnelConnectorListener } from "./connector-listener-BcQMzY6Q.js";
21
21
  import { t as FunnelSlackEventProcessor } from "./slack-event-processor-Cs_YuI3w.js";
22
- import { n as scheduleConnectorSchema, r as scheduleEntrySchema, t as scheduleCatchupPolicySchema } from "./schedule-connector-schema-C2AChpwX.js";
22
+ import { a as scheduleConnectorSchema, i as scheduleCatchupPolicySchema, n as cronScheduleEntrySchema, o as scheduleEntryInputSchema, r as onceScheduleEntrySchema, s as scheduleEntrySchema, t as cronExpressionSchema } from "./schedule-connector-schema-CNV8PgWX.js";
23
23
  import { dirname, join, resolve } from "node:path";
24
24
  import { hc } from "hono/client";
25
25
  import { appendFileSync, existsSync, mkdirSync } from "node:fs";
26
26
  import { z } from "zod";
27
27
  import { fileURLToPath } from "node:url";
28
28
  import { createFactory } from "hono/factory";
29
+ import { Database } from "bun:sqlite";
29
30
  import { HTTPException } from "hono/http-exception";
30
31
  import { zValidator } from "@hono/zod-validator";
31
32
  import { Hono } from "hono";
@@ -1077,6 +1078,7 @@ var Funnel = class Funnel {
1077
1078
  clock;
1078
1079
  http;
1079
1080
  onError;
1081
+ diagnosticLog;
1080
1082
  constructor(props = {}) {
1081
1083
  const dir = props.dir ?? resolveFunnelDir();
1082
1084
  const tmpDir = props.tmpDir ?? funnelTmpDir();
@@ -1096,6 +1098,7 @@ var Funnel = class Funnel {
1096
1098
  this.clock = clock;
1097
1099
  this.http = http;
1098
1100
  this.onError = props.onError ?? noopOnError;
1101
+ this.diagnosticLog = props.diagnosticLog;
1099
1102
  const store = props.store ?? new FunnelSettingsStore({
1100
1103
  path: this.paths.settings,
1101
1104
  fs,
@@ -1108,7 +1111,7 @@ var Funnel = class Funnel {
1108
1111
  http,
1109
1112
  clock,
1110
1113
  logger: this.logger,
1111
- diagnosticLog: props.diagnosticLog,
1114
+ diagnosticLog: this.diagnosticLog,
1112
1115
  signal: props.signal,
1113
1116
  dir
1114
1117
  });
@@ -1178,6 +1181,7 @@ var Funnel = class Funnel {
1178
1181
  gatewayToken: this.gatewayToken,
1179
1182
  channels: this.channels,
1180
1183
  publisher: this.publisher,
1184
+ diagnosticLog: this.diagnosticLog,
1181
1185
  tmpDir
1182
1186
  });
1183
1187
  this.recovery = new FunnelRecovery({
@@ -1244,7 +1248,8 @@ var Funnel = class Funnel {
1244
1248
  killCompetingSlack: options.killCompetingSlack,
1245
1249
  token: options.token ?? this.gatewayToken.ensure(),
1246
1250
  allowInsecureHost: options.allowInsecureHost,
1247
- extraRoutes: options.extraRoutes
1251
+ extraRoutes: options.extraRoutes,
1252
+ diagnosticLog: this.diagnosticLog
1248
1253
  });
1249
1254
  }
1250
1255
  /**
@@ -1345,6 +1350,87 @@ var NoopFunnelLogger = class extends FunnelLogger {
1345
1350
  error() {}
1346
1351
  };
1347
1352
  //#endregion
1353
+ //#region lib/engine/diagnostic-log/diagnostic-sql-reader.ts
1354
+ /**
1355
+ * Read-only SQL surface over the three diagnostic tables, for Claude to query
1356
+ * the log with arbitrary `SELECT`s. It opens all files read-only and exposes
1357
+ * three views — `raw`, `processed`, `connection` — that hide the storage
1358
+ * details (the physical table is `logs` and each row's columns live
1359
+ * inside a JSON `event` blob): the views surface the columns as plain fields,
1360
+ * with `payload` already pulled out of the nested JSON.
1361
+ *
1362
+ * The tables are separate files. `raw` and `processed` share an `event_id`,
1363
+ * so a `JOIN` answers "the event arrived, but what verdict did it get?";
1364
+ * `connection` answers the other half — "did the listener ever connect at
1365
+ * all?". Writes are impossible: the connection is read-only and `query`
1366
+ * rejects anything but a single `SELECT`.
1367
+ */
1368
+ var ConnectorDiagnosticSqlReader = class {
1369
+ db;
1370
+ constructor(props) {
1371
+ const db = new Database(props.rawPath, { readonly: true });
1372
+ try {
1373
+ db.run("PRAGMA busy_timeout = 500");
1374
+ db.prepare("ATTACH DATABASE ? AS processeddb").run(props.processedPath);
1375
+ db.prepare("ATTACH DATABASE ? AS connectiondb").run(props.connectionPath);
1376
+ db.run(rawViewSql);
1377
+ db.run(processedViewSql);
1378
+ db.run(connectionViewSql);
1379
+ } catch (error) {
1380
+ db.close();
1381
+ throw error;
1382
+ }
1383
+ this.db = db;
1384
+ Object.freeze(this);
1385
+ }
1386
+ /**
1387
+ * Run one read-only `SELECT` and return the rows. Returns an `Error` (rather
1388
+ * than throwing) for a non-SELECT statement or a SQL error, so the caller
1389
+ * can surface the message without a stack trace.
1390
+ */
1391
+ query(sql, params = []) {
1392
+ const trimmed = sql.trim().replace(/;$/, "").trim();
1393
+ if (!/^select\b/i.test(trimmed)) return /* @__PURE__ */ new Error("only a single SELECT statement is allowed");
1394
+ if (trimmed.includes(";")) return /* @__PURE__ */ new Error("only a single statement is allowed (remove the ';')");
1395
+ try {
1396
+ return this.db.prepare(trimmed).all(...params);
1397
+ } catch (error) {
1398
+ return error instanceof Error ? error : new Error(String(error));
1399
+ }
1400
+ }
1401
+ close() {
1402
+ this.db.close();
1403
+ }
1404
+ };
1405
+ const rawViewSql = `CREATE TEMP VIEW raw AS SELECT
1406
+ seq,
1407
+ ts,
1408
+ json_extract(event, '$.event_id') AS event_id,
1409
+ json_extract(event, '$.type') AS type,
1410
+ json_extract(event, '$.connector_id') AS connector_id,
1411
+ json_extract(event, '$.channel_id') AS channel_id,
1412
+ json_extract(event, '$.payload') AS payload
1413
+ FROM main.logs`;
1414
+ const processedViewSql = `CREATE TEMP VIEW processed AS SELECT
1415
+ seq,
1416
+ ts,
1417
+ json_extract(event, '$.event_id') AS event_id,
1418
+ json_extract(event, '$.type') AS type,
1419
+ json_extract(event, '$.connector_id') AS connector_id,
1420
+ json_extract(event, '$.channel_id') AS channel_id,
1421
+ json_extract(event, '$.outcome') AS outcome,
1422
+ json_extract(event, '$.payload') AS payload
1423
+ FROM processeddb.logs`;
1424
+ const connectionViewSql = `CREATE TEMP VIEW connection AS SELECT
1425
+ seq,
1426
+ ts,
1427
+ json_extract(event, '$.type') AS type,
1428
+ json_extract(event, '$.connector_id') AS connector_id,
1429
+ json_extract(event, '$.channel_id') AS channel_id,
1430
+ json_extract(event, '$.status') AS status,
1431
+ json_extract(event, '$.detail') AS detail
1432
+ FROM connectiondb.logs`;
1433
+ //#endregion
1348
1434
  //#region lib/gateway/service-routes.ts
1349
1435
  /**
1350
1436
  * Mountable Hono app that exposes the service layer (`FunnelDiagnostics` +
@@ -1933,22 +2019,26 @@ usage: funnel channels <ch> connectors <conn> schedules [subcommand]
1933
2019
 
1934
2020
  subcommands:
1935
2021
  (none) / list schedule entries
1936
- add <id> --cron=... --prompt=... [--enabled=true] [--catchup-policy=latest|all|skip] / add entry
2022
+ add <id> (--cron=... | --run-at=...) --prompt=... [--enabled=true] [--catchup-policy=latest|all|skip] / add entry
1937
2023
  remove <id> / remove entry`), (c) => {
1938
2024
  const param = c.req.valid("param");
1939
2025
  const funnel = c.env.funnel;
1940
2026
  const entries = z.array(scheduleEntrySchema).parse(funnel.channels.connectorOp(param.channel, param.connector, "listEntries", void 0));
1941
2027
  if (entries.length === 0) return c.text("no schedule entries");
1942
- return c.text(entries.map((e) => `${e.id}\t${e.cron}\t${e.enabled ? "on" : "off"}\t${e.prompt}`).join("\n"));
2028
+ return c.text(entries.map((entry) => {
2029
+ const schedule = entry.kind === "cron" ? entry.cron : `once:${entry.runAt}`;
2030
+ return `${entry.id}\t${schedule}\t${entry.enabled ? "on" : "off"}\t${entry.prompt}`;
2031
+ }).join("\n"));
1943
2032
  });
1944
2033
  //#endregion
1945
2034
  //#region lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.ts
1946
2035
  const help$9 = `funnel channels <ch> connectors <conn> schedules add <id> — add a schedule entry
1947
2036
 
1948
- usage: funnel channels <ch> connectors <conn> schedules add <id> --cron="*/5 * * * *" --prompt="..." [--enabled|--enabled=false] [--catchup-policy=latest|all|skip]
2037
+ usage: funnel channels <ch> connectors <conn> schedules add <id> (--cron="*/5 * * * *" | --run-at="2026-08-01T09:00:00+09:00") --prompt="..." [--enabled|--enabled=false] [--catchup-policy=latest|all|skip]
1949
2038
 
1950
2039
  options:
1951
- --cron <expr> / 5-field cron expression (required)
2040
+ --cron <expr> / 5-field cron expression (exclusive with --run-at)
2041
+ --run-at <ISO datetime> / fire once at or after this instant (exclusive with --cron)
1952
2042
  --prompt <text> / prompt delivered on each fire (required)
1953
2043
  --enabled / fire on schedule (default: true; --enabled=false stores it disabled)
1954
2044
  --catchup-policy latest|all|skip / how missed fires are replayed after downtime (default: latest)`;
@@ -1976,17 +2066,23 @@ const channelsConnectorsSchedulesAddHandler = factory.createHandlers(zValidator$
1976
2066
  connector: z.string(),
1977
2067
  id: z.string()
1978
2068
  })), zValidator$1("query", z.object({
1979
- cron: z.string(),
2069
+ cron: cronExpressionSchema.optional(),
2070
+ "run-at": z.string().datetime({ offset: true }).optional(),
1980
2071
  prompt: z.string(),
1981
2072
  enabled: booleanFlag,
1982
2073
  "catchup-policy": scheduleCatchupPolicySchema.optional()
2074
+ }).superRefine((query, context) => {
2075
+ if (query.cron === void 0 === (query["run-at"] === void 0)) context.addIssue({
2076
+ code: "custom",
2077
+ message: "exactly one of --cron or --run-at is required"
2078
+ });
1983
2079
  })), async (c) => {
1984
2080
  const param = c.req.valid("param");
1985
2081
  const query = c.req.valid("query");
1986
2082
  const funnel = c.env.funnel;
1987
2083
  const entry = scheduleEntrySchema.parse(funnel.channels.connectorOp(param.channel, param.connector, "addEntry", {
1988
2084
  id: param.id,
1989
- cron: query.cron,
2085
+ ...query.cron !== void 0 ? { cron: query.cron } : { runAt: query["run-at"] },
1990
2086
  prompt: query.prompt,
1991
2087
  ...query.enabled !== void 0 ? { enabled: query.enabled } : {},
1992
2088
  ...query["catchup-policy"] !== void 0 ? { catchupPolicy: query["catchup-policy"] } : {}
@@ -2871,6 +2967,14 @@ const gatewayLogsHandler = factory.createHandlers(helpGuard(logsHelp), zValidato
2871
2967
  process.exit(0);
2872
2968
  });
2873
2969
  //#endregion
2970
+ //#region lib/engine/diagnostic-log/diagnostic-log-paths.ts
2971
+ /** Default on-disk layout used by the bundled CLI and gateway daemon. */
2972
+ const connectorDiagnosticLogPaths = (tmpDir) => ({
2973
+ rawPath: join(tmpDir, "connector-raw.db"),
2974
+ processedPath: join(tmpDir, "connector-processed.db"),
2975
+ connectionPath: join(tmpDir, "connector-connection.db")
2976
+ });
2977
+ //#endregion
2874
2978
  //#region lib/cli/routes/gateway.sql.ts
2875
2979
  const PRESETS = {
2876
2980
  recent: "SELECT seq, ts, type, outcome FROM processed ORDER BY seq DESC LIMIT 20",
@@ -2955,10 +3059,7 @@ const gatewaySqlHandler = factory.createHandlers(helpGuard(sqlHelp), zValidator$
2955
3059
  params = resolvedChannelId ? [resolvedChannelId] : [];
2956
3060
  } else if (query.query) sql = query.query;
2957
3061
  if (!sql) return c.text(sqlHelp);
2958
- const tmpDir = funnelTmpDir();
2959
- const rawPath = join(tmpDir, "connector-raw.db");
2960
- const processedPath = join(tmpDir, "connector-processed.db");
2961
- const connectionPath = join(tmpDir, "connector-connection.db");
3062
+ const { rawPath, processedPath, connectionPath } = connectorDiagnosticLogPaths(funnelTmpDir());
2962
3063
  if (!existsSync(rawPath) || !existsSync(processedPath) || !existsSync(connectionPath)) return c.text("no diagnostic store yet (the gateway has not initialized it)");
2963
3064
  const reader = new ConnectorDiagnosticSqlReader({
2964
3065
  rawPath,
@@ -3148,7 +3249,7 @@ const profilesAddHandler = factory.createHandlers(zValidator$1("param", z.object
3148
3249
  const param = c.req.valid("param");
3149
3250
  const query = c.req.valid("query");
3150
3251
  const funnel = c.env.funnel;
3151
- const { profiles, claude } = c.env;
3252
+ const profiles = c.env.profiles;
3152
3253
  const channel = funnel.channels.get(query.channel);
3153
3254
  if (!channel) throw new HTTPException(400, { message: notFoundMessage({
3154
3255
  kind: "channel",
@@ -3173,9 +3274,7 @@ usage: funnel profiles <name> as-default
3173
3274
 
3174
3275
  the first profile in the list is treated as the default for fnl claude.`), (c) => {
3175
3276
  const param = c.req.valid("param");
3176
- c.env.funnel;
3177
- const { profiles, claude } = c.env;
3178
- profiles.asDefault(param.profile);
3277
+ c.env.profiles.asDefault(param.profile);
3179
3278
  return c.text(`profile "${param.profile}" is now the default`);
3180
3279
  });
3181
3280
  //#endregion
@@ -3201,9 +3300,7 @@ const profilesRenameHandler = factory.createHandlers(zValidator$1("param", z.obj
3201
3300
  newName: z.string()
3202
3301
  })), zValidator$1("query", z.object({})), (c) => {
3203
3302
  const param = c.req.valid("param");
3204
- c.env.funnel;
3205
- const { profiles, claude } = c.env;
3206
- profiles.rename(param.profile, param.newName);
3303
+ c.env.profiles.rename(param.profile, param.newName);
3207
3304
  return c.text(`renamed profile "${param.profile}" to "${param.newName}"`);
3208
3305
  });
3209
3306
  //#endregion
@@ -3215,7 +3312,6 @@ usage: funnel profiles <name> run [additional claude args...]
3215
3312
  const RESERVED_KEYS = [];
3216
3313
  const profilesLaunchHandler = factory.createHandlers(zValidator$1("param", z.object({ profile: z.string() })), helpGuard(launchHelp), zValidator$1("query", z.object({}).loose()), async (c) => {
3217
3314
  const param = c.req.valid("param");
3218
- c.env.funnel;
3219
3315
  const { profiles, claude } = c.env;
3220
3316
  const profile = profiles.get(param.profile);
3221
3317
  if (!profile) throw new HTTPException(404, { message: notFoundMessage({
@@ -3245,9 +3341,7 @@ const profilesRemoveHelpHandler = factory.createHandlers((c) => c.text(help$1));
3245
3341
  //#region lib/cli/routes/profiles.remove.$profile.ts
3246
3342
  const profilesRemoveHandler = factory.createHandlers(zValidator$1("param", z.object({ profile: z.string() })), zValidator$1("query", z.object({})), (c) => {
3247
3343
  const param = c.req.valid("param");
3248
- c.env.funnel;
3249
- const { profiles, claude } = c.env;
3250
- profiles.remove(param.profile);
3344
+ c.env.profiles.remove(param.profile);
3251
3345
  return c.text(`removed profile "${param.profile}"`);
3252
3346
  });
3253
3347
  //#endregion
@@ -3281,7 +3375,7 @@ const profilesSetHandler = factory.createHandlers(zValidator$1("param", z.object
3281
3375
  const param = c.req.valid("param");
3282
3376
  const query = c.req.valid("query");
3283
3377
  const funnel = c.env.funnel;
3284
- const { profiles, claude } = c.env;
3378
+ const profiles = c.env.profiles;
3285
3379
  const channel = query.channel !== void 0 ? funnel.channels.get(query.channel) : null;
3286
3380
  if (query.channel !== void 0 && !channel) throw new HTTPException(400, { message: notFoundMessage({
3287
3381
  kind: "channel",
@@ -3499,4 +3593,4 @@ const routes = factory.createApp().onError((error, c) => {
3499
3593
  return c.text(`error: ${error instanceof Error ? error.message : String(error)}`, 400);
3500
3594
  }).get("/claude", ...claudeHandler).get("/channels", ...channelsGroupHandler).post("/channels/add", ...channelsAddHelpHandler).post("/channels/add/:channel", ...channelsAddHandler).post("/channels/remove", ...channelsRemoveHelpHandler).post("/channels/remove/:channel", ...channelsRemoveHandler).post("/channels/rename/:channel/:newName", ...channelsRenameHandler).post("/channels/:channel/rename/:newName", ...channelsRenameHandler).post("/channels/rename", ...channelsRenameHelpHandler).post("/channels/:channel/rename", ...channelsChannelRenameHelpHandler).post("/channels/:channel/set/delivery/:mode", ...channelsSetDeliveryHandler).post("/channels/publish", ...channelsPublishHelpHandler).post("/channels/:channel/publish", ...channelsPublishHandler).get("/channels/:channel/validate", ...channelsValidateHandler).get("/channels/validate", ...channelsValidateHelpHandler).get("/channels/:channel", ...channelsShowHandler).get("/channels/:channel/connectors", ...channelsConnectorsGroupHandler).post("/channels/:channel/connectors/add", ...channelsConnectorsAddHelpHandler).post("/channels/:channel/connectors/add/:connector", ...channelsConnectorsAddHandler).post("/channels/:channel/connectors/remove", ...channelsConnectorsRemoveHelpHandler).post("/channels/:channel/connectors/remove/:connector", ...channelsConnectorsRemoveHandler).post("/channels/:channel/connectors/set", ...channelsConnectorsSetHelpHandler).post("/channels/:channel/connectors/set/:connector", ...channelsConnectorsSetHandler).post("/channels/:channel/connectors/rename/:connector/:newName", ...channelsConnectorsRenameHandler).post("/channels/:channel/connectors/:connector/rename/:newName", ...channelsConnectorsRenameHandler).post("/channels/:channel/connectors/rename", ...channelsConnectorsRenameHelpHandler).post("/channels/:channel/connectors/:connector/rename", ...channelsConnectorRenameHelpHandler).post("/channels/:channel/connectors/:connector/request", ...channelsConnectorsRequestHandler).get("/channels/:channel/connectors/:connector", ...channelsConnectorsShowHandler).get("/channels/:channel/connectors/:connector/schedules", ...channelsConnectorsSchedulesGroupHandler).post("/channels/:channel/connectors/:connector/schedules/add", ...channelsConnectorSchedulesAddHelpHandler).post("/channels/:channel/connectors/:connector/schedules/add/:id", ...channelsConnectorsSchedulesAddHandler).post("/channels/:channel/connectors/:connector/schedules/remove", ...channelsConnectorSchedulesRemoveHelpHandler).post("/channels/:channel/connectors/:connector/schedules/remove/:id", ...channelsConnectorsSchedulesRemoveHandler).get("/profiles", ...profilesGroupHandler).post("/profiles/add", ...profilesAddHelpHandler).post("/profiles/add/:profile", ...profilesAddHandler).post("/profiles/set", ...profilesSetHelpHandler).post("/profiles/set/:profile", ...profilesSetHandler).post("/profiles/remove", ...profilesRemoveHelpHandler).post("/profiles/remove/:profile", ...profilesRemoveHandler).post("/profiles/rename/:profile/:newName", ...profilesRenameHandler).post("/profiles/:profile/rename/:newName", ...profilesRenameHandler).post("/profiles/rename", ...profilesRenameHelpHandler).post("/profiles/:profile/rename", ...profilesProfileRenameHelpHandler).post("/profiles/:profile/as-default", ...profilesAsDefaultHandler).get("/profiles/:profile/run", ...profilesLaunchHandler).get("/profiles/:profile", ...profilesLaunchHandler).get("/gateway", ...gatewayGroupHandler).get("/gateway/status", ...gatewayStatusHandler).get("/gateway/start", ...gatewayStartHandler).get("/gateway/stop", ...gatewayStopHandler).get("/gateway/restart", ...gatewayRestartHandler).get("/gateway/run", ...gatewayRunHandler).get("/gateway/logs", ...gatewayLogsHandler).get("/gateway/sql", ...gatewaySqlHandler).get("/gateway/listeners", ...gatewayListenersHandler).get("/debug", ...debugHandler).get("/debug/events", ...debugEventsHandler).get("/debug/dropped", ...debugDroppedHandler).get("/debug/errors", ...debugErrorsHandler).get("/debug/replay", ...debugReplayHandler).get("/debug/raw", ...debugRawHandler).get("/debug/connection", ...debugConnectionHandler).get("/debug/logs", ...debugLogsHandler).get("/docs", ...docsIndexHandler).get("/docs/:topic", ...docsTopicHandler).get("/doctor", ...doctorHandler).get("/schema", ...schemaHandler).get("/status", ...statusHandler).get("/update", ...updateHandler);
3501
3595
  //#endregion
3502
- export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, FUNNEL_DIR, Funnel, FunnelAuthFailedError, FunnelBroadcaster, FunnelChannelAlreadyExistsError, FunnelChannelNotFoundError, FunnelChannelPublisher, FunnelChannels, FunnelClock, FunnelConnectorAdapter, FunnelConnectorListener, FunnelConnectorNotFoundError, FunnelConnectorRegistry, FunnelConnectorTypeMismatchError, FunnelDiagnostics, FunnelDocs, FunnelDoctor, FunnelError, FunnelEventLog, FunnelFileSystem, FunnelGateway, FunnelGatewayBindError, FunnelGatewayServer, FunnelGatewayToken, FunnelHttpClient, FunnelIdGenerator, FunnelListenerRegistry, FunnelListenersClient, FunnelLogger, FunnelProcessRunner, FunnelRecovery, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenCollisionError, FunnelTokenPrompter, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelHttpClient, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelHttpClient, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, SETTINGS_PATH, SETTINGS_VERSION, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, baseConnectorConfigSchema, buildServiceRoutes, channelConfigSchema, channelDeliveryModeSchema, channelWsProtocols, channelWsUrl, routes as cliRoutes, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, createSettings, discordConnectorSchema, expandHomeDir, factory, funnelEventSchema, gatewayLoopbackUrl, ghConnectorSchema, previewOf, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryRows, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, toDiagnosticConnectionError, toDiagnosticEvent, toRequest };
3596
+ export { CONNECTOR_CONNECTION_STATUSES, ConnectorDiagnosticLog, ConnectorDiagnosticSqlReader, DEFAULT_GATEWAY_PORT, DEFAULT_GATEWAY_TOKEN_PATH, FUNNEL_DIR, Funnel, FunnelAuthFailedError, FunnelBroadcaster, FunnelChannelAlreadyExistsError, FunnelChannelNotFoundError, FunnelChannelPublisher, FunnelChannels, FunnelClock, FunnelConnectorAdapter, FunnelConnectorListener, FunnelConnectorNotFoundError, FunnelConnectorRegistry, FunnelConnectorTypeMismatchError, FunnelDiagnostics, FunnelDocs, FunnelDoctor, FunnelError, FunnelEventLog, FunnelFileSystem, FunnelGateway, FunnelGatewayBindError, FunnelGatewayServer, FunnelGatewayToken, FunnelHttpClient, FunnelIdGenerator, FunnelListenerRegistry, FunnelListenersClient, FunnelLogger, FunnelProcessRunner, FunnelRecovery, FunnelSettingsReader, FunnelSettingsStore, FunnelSlackEventProcessor, FunnelTokenCollisionError, FunnelTokenPrompter, MemoryConnectorDiagnosticLog, MemoryFunnelClock, MemoryFunnelEventLog, MemoryFunnelFileSystem, MemoryFunnelHttpClient, MemoryFunnelIdGenerator, MemoryFunnelLogger, MemoryFunnelProcessRunner, MemoryFunnelTokenPrompter, MockFunnelSettingsReader, NodeFunnelClock, NodeFunnelFileSystem, NodeFunnelHttpClient, NodeFunnelIdGenerator, NodeFunnelLogger, NodeFunnelProcessRunner, NodeFunnelTokenPrompter, NoopFunnelLogger, SETTINGS_PATH, SETTINGS_VERSION, SqliteConnectorDiagnosticLog, SqliteFunnelEventLog, baseConnectorConfigSchema, buildServiceRoutes, channelConfigSchema, channelDeliveryModeSchema, channelWsProtocols, channelWsUrl, routes as cliRoutes, connectorConnectionEventSchema, connectorProcessedEventSchema, connectorRawEventSchema, createSettings, cronExpressionSchema, cronScheduleEntrySchema, diagnosticConnectionEventOf, diagnosticEventOfProcessed, diagnosticEventOfRaw, discordConnectorSchema, expandHomeDir, factory, funnelEventSchema, gatewayLoopbackUrl, ghConnectorSchema, onceScheduleEntrySchema, previewOf, profileConfigSchema, publishRequestSchema, publishResponseSchema, queryRows, queryToCliArgs, resolveFunnelDir, resolveFunnelPort, scheduleCatchupPolicySchema, scheduleConnectorSchema, scheduleEntryInputSchema, scheduleEntrySchema, settingsSchema, slackConnectorSchema, toDiagnosticConnectionError, toDiagnosticEvent, toRequest };
@@ -1,5 +1,5 @@
1
1
  import { n as FunnelFileSystem } from "./file-system-BNtl997T.js";
2
- import { a as LocalConfigSyncResult, c as ChannelSpec, d as LocalConfig, f as ProfileSpec, g as profileSpecSchema, h as localConfigSchema, i as FunnelLocalConfigSync, l as ConnectorSpec, m as connectorSpecSchema, n as NodeFunnelTokenPrompter, o as FunnelTokenPrompter, p as channelSpecSchema, r as ConnectorSyncOutcome, s as FunnelLocalConfig, t as MemoryFunnelTokenPrompter, u as LOCAL_CONFIG_FILENAME } from "./memory-token-prompter-D3R_kgM_.js";
2
+ import { a as LocalConfigSyncResult, c as ChannelSpec, d as LocalConfig, f as ProfileSpec, g as profileSpecSchema, h as localConfigSchema, i as FunnelLocalConfigSync, l as ConnectorSpec, m as connectorSpecSchema, n as NodeFunnelTokenPrompter, o as FunnelTokenPrompter, p as channelSpecSchema, r as ConnectorSyncOutcome, s as FunnelLocalConfig, t as MemoryFunnelTokenPrompter, u as LOCAL_CONFIG_FILENAME } from "./memory-token-prompter-B20tl_aU.js";
3
3
  //#region lib/services/local-config/local-config-json-schema.d.ts
4
4
  /**
5
5
  * Generates the JSON Schema (draft 2020-12) for `funnel.json`. Useful for