@interactive-inc/claude-funnel 0.66.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.
- package/README.md +31 -6
- package/dist/bin.js +292 -383
- package/dist/channel.d.ts +76 -52
- package/dist/channel.js +82 -47
- package/dist/{channels-DR90RmUP.d.ts → channels-B0cifCfw.d.ts} +6 -6
- package/dist/claude.d.ts +11 -8
- package/dist/claude.js +31 -15
- package/dist/connector-descriptor-D4XtEsH8.d.ts +215 -0
- package/dist/{connector-diagnostics-recorder-COtNEmUp.js → connector-diagnostics-recorder-BmOijU1p.js} +1 -0
- package/dist/connectors/discord.d.ts +11 -8
- package/dist/connectors/discord.js +2 -2
- package/dist/connectors/gh.d.ts +7 -6
- package/dist/connectors/gh.js +2 -2
- package/dist/connectors/schedule.d.ts +21 -17
- package/dist/connectors/schedule.js +3 -3
- package/dist/connectors/slack.d.ts +15 -10
- package/dist/connectors/slack.js +3 -3
- package/dist/diagnostic-event-CxMM5Bl2.js +78 -0
- package/dist/diagnostic-log-BsAg5qZK.d.ts +186 -0
- package/dist/diagnostics.d.ts +2 -2
- package/dist/diagnostics.js +3 -2
- package/dist/{discord-connector-DXARcO6w.js → discord-connector-CAcWifJn.js} +6 -6
- package/dist/{discord-connector-schema-D1dyxhXk.d.ts → discord-connector-schema-BaBZYHxK.d.ts} +0 -1
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +1 -1
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.js +1 -1
- package/dist/event-log.d.ts +2 -0
- package/dist/event-log.js +3 -0
- package/dist/{file-process-guard-CiBwXjzm.d.ts → file-process-guard-D-QatrwL.d.ts} +22 -18
- package/dist/{file-system-DHgbuTFb.d.ts → file-system-BNtl997T.d.ts} +2 -1
- package/dist/{flume-source-listener-FzR5lGpL.d.ts → flume-source-listener-Ba8_1Mg-.d.ts} +9 -6
- package/dist/{funnel-diagnostics-Cvk6Sk4x.js → funnel-diagnostics-CAG7hJP0.js} +85 -141
- package/dist/{funnel-diagnostics-kbd27d7I.d.ts → funnel-diagnostics-CDrZznTB.d.ts} +18 -18
- package/dist/{funnel-docs-C-ge0MuB.js → funnel-docs-CI4hMkhq.js} +12 -3
- package/dist/{funnel-doctor-CVTNUtDn.d.ts → funnel-doctor-CY4S5cnz.d.ts} +20 -9
- package/dist/{funnel-doctor-XrI2GBH8.js → funnel-doctor-Csw5qjcH.js} +1 -0
- package/dist/{funnel-error-0t1MK1R6.js → funnel-error-DoSBCogD.js} +13 -0
- package/dist/{funnel-recovery-D8MkiTpk.d.ts → funnel-recovery-BwcSNNSN.d.ts} +1 -2
- package/dist/{funnel-recovery-DKnEutUS.js → funnel-recovery-DYbSYGWC.js} +1 -0
- package/dist/gateway/daemon.js +60 -139
- package/dist/gateway.d.ts +2 -3
- package/dist/gateway.js +2 -2
- package/dist/{gh-connector-BUGCOEWS.js → gh-connector-DMwI6zJA.js} +5 -5
- package/dist/{gh-connector-schema-BCHEqpUg.d.ts → gh-connector-schema-BrNsCl1T.d.ts} +0 -1
- package/dist/{index-BU1TtuFy.d.ts → index-fHrKn4jm.d.ts} +210 -40
- package/dist/index.d.ts +125 -115
- package/dist/index.js +242 -57
- package/dist/{local-config-json-schema-DexV8vX3.js → local-config-json-schema-_-YVHX4c.js} +4 -4
- package/dist/local-config.d.ts +2 -3
- package/dist/local-config.js +1 -1
- package/dist/logger.d.ts +17 -265
- package/dist/logger.js +6 -141
- package/dist/memory-event-log-BY8XjFzi.js +147 -0
- package/dist/{memory-token-prompter-D0kIdhar.d.ts → memory-token-prompter-B20tl_aU.d.ts} +2 -3
- package/dist/{node-file-system-BOXIHW_Q.js → node-file-system-xJx7dymE.js} +11 -3
- package/dist/{profiles-M24JrcOh.d.ts → profiles-CePRnv3F.d.ts} +3 -4
- package/dist/{profiles-ZHLONml4.js → profiles-KpN7_gBw.js} +19 -5
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +1 -1
- package/dist/recovery.d.ts +1 -1
- package/dist/recovery.js +1 -1
- package/dist/{schedule-connector-9k3gOIgl.js → schedule-connector-BXUOYgwZ.js} +63 -99
- package/dist/schedule-connector-schema-CNV8PgWX.js +137 -0
- package/dist/schedule-connector-schema-Tq5kJul-.d.ts +127 -0
- package/dist/{settings-reader-BnKIbmsD.d.ts → settings-reader-CyTpbAre.d.ts} +1 -2
- package/dist/{settings-schema-IShSMm5G.d.ts → settings-schema-B-CKLuST.d.ts} +0 -1
- package/dist/{settings-store-ccv291GV.js → settings-store-ZFWBhOnp.js} +12 -3
- package/dist/{slack-connector-CxpWagbT.js → slack-connector-CC3V2VXQ.js} +10 -9
- package/dist/{slack-event-processor-xFDG3US0.js → slack-event-processor-Cs_YuI3w.js} +2 -2
- package/dist/{slack-event-processor-BDTr62cN.d.ts → slack-event-processor-DmAlq4cV.d.ts} +0 -1
- package/dist/{slot-fields-D-pvMgTK.js → slot-fields-eCWizJqS.js} +4 -4
- package/dist/{sqlite-diagnostic-log-CwhXE9Qh.js → sqlite-diagnostic-log-Qs4cf9I_.js} +92 -100
- package/dist/sqlite-event-log-BYgCFMxC.d.ts +284 -0
- package/dist/{funnel-log-sqlite-sink-DLYkY0pZ.js → sqlite-event-log-eZuXKszJ.js} +53 -12
- package/dist/{yaml-render-DVEtYuF1.js → yaml-render-DxxRQT-V.js} +3 -3
- package/package.json +25 -10
- package/dist/broadcaster-DVNcw00K.d.ts +0 -138
- package/dist/connector-descriptor-CmyHlEiT.d.ts +0 -380
- package/dist/diagnostic-sql-reader-oXZnWFf_.js +0 -83
- package/dist/file-system-Wvzc2ePY.js +0 -9
- package/dist/logger-B6iyNbxM.js +0 -9
- package/dist/schedule-connector-schema-D7ZEKvit.d.ts +0 -49
- package/dist/schedule-connector-schema-DKEPZnVv.js +0 -31
- package/dist/settings-reader-9FcX3qS1.js +0 -11
- /package/dist/{connector-adapter-Dvs8N7ew.js → connector-adapter-BL2ehMej.js} +0 -0
- /package/dist/{connector-listener-mPGZYa8e.js → connector-listener-BcQMzY6Q.js} +0 -0
- /package/dist/{discord-connector-schema-B4YpWpR3.js → discord-connector-schema-saAGuPmJ.js} +0 -0
- /package/dist/{error-message-of-ColuYmAk.js → error-message-of-BG4ezZ_s.js} +0 -0
- /package/dist/{funnel-docs-Cd66sKyV.d.ts → funnel-docs-BJWawfWI.d.ts} +0 -0
- /package/dist/{gh-connector-schema-CAqIhzGr.js → gh-connector-schema-DmZTrzUu.js} +0 -0
- /package/dist/{logger-Bc_Ooypb.d.ts → logger-mMZvblTx.d.ts} +0 -0
- /package/dist/{loopback-fetch-CVNuN3YZ.js → loopback-fetch-HP-bo9Kv.js} +0 -0
- /package/dist/{node-http-client-u00atiKx.js → node-http-client-SX3xFh4h.js} +0 -0
- /package/dist/{node-process-runner-DxTvycoK.js → node-process-runner-D4rzPl8Q.js} +0 -0
- /package/dist/{resolve-connector-token-DxDG9mhf.js → resolve-connector-token-BwiJCu82.js} +0 -0
- /package/dist/{slack-connector-schema-Dem8to4P.js → slack-connector-schema-EGVuuqSX.js} +0 -0
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { n as FunnelClock, t as FunnelLogger } from "./logger-Bc_Ooypb.js";
|
|
2
|
-
import { n as FunnelFileSystem } from "./file-system-DHgbuTFb.js";
|
|
3
|
-
import { z } from "zod";
|
|
4
|
-
|
|
5
|
-
//#region lib/engine/process/process-runner.d.ts
|
|
6
|
-
type RunOptions = {
|
|
7
|
-
cwd?: string;
|
|
8
|
-
env?: Record<string, string>;
|
|
9
|
-
input?: string;
|
|
10
|
-
};
|
|
11
|
-
type RunResult = {
|
|
12
|
-
exitCode: number;
|
|
13
|
-
stdout: string;
|
|
14
|
-
stderr: string;
|
|
15
|
-
};
|
|
16
|
-
type AttachOptions = {
|
|
17
|
-
cwd?: string;
|
|
18
|
-
env?: Record<string, string>;
|
|
19
|
-
/** Invoked synchronously after the child process has been spawned, with its PID.
|
|
20
|
-
* Useful for hosts that need to register the spawned process before it exits. */
|
|
21
|
-
onSpawned?: (pid: number) => void;
|
|
22
|
-
};
|
|
23
|
-
type DetachOptions = {
|
|
24
|
-
env?: Record<string, string>; /** Append stdout to this file. Parent dir is the caller's responsibility. */
|
|
25
|
-
stdoutFile?: string; /** Append stderr to this file. Parent dir is the caller's responsibility. */
|
|
26
|
-
stderrFile?: string;
|
|
27
|
-
};
|
|
28
|
-
type ProcessSnapshot = {
|
|
29
|
-
pid: number;
|
|
30
|
-
command: string;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* Process boundary covering one-shot runs, sync runs, foreground attach, and
|
|
34
|
-
* detached background spawns. Default is NodeFunnelProcessRunner (Bun.spawn);
|
|
35
|
-
* MemoryFunnelProcessRunner records calls and lets tests stub responses.
|
|
36
|
-
*
|
|
37
|
-
* Liveness and process-listing helpers absorb POSIX/Windows differences so
|
|
38
|
-
* callers do not branch on `process.platform`. `isAlive` checks whether a PID
|
|
39
|
-
* names a live (non-zombie) process; `listProcessesContaining` enumerates
|
|
40
|
-
* processes whose command line includes `marker`, used for funnel-gateway tag
|
|
41
|
-
* matching across daemons that share a home dir. `getStartTime` returns a
|
|
42
|
-
* stable string identifying when a PID was started, used to detect PID reuse
|
|
43
|
-
* after the original process died abnormally (no exit hook fired).
|
|
44
|
-
*/
|
|
45
|
-
declare abstract class FunnelProcessRunner {
|
|
46
|
-
abstract run(command: string[], options?: RunOptions): Promise<RunResult>;
|
|
47
|
-
abstract runSync(command: string[]): RunResult;
|
|
48
|
-
abstract attach(command: string[], options?: AttachOptions): Promise<number>;
|
|
49
|
-
abstract detach(command: string[], options?: DetachOptions): void;
|
|
50
|
-
abstract kill(pid: number, signal?: string): void;
|
|
51
|
-
abstract isAlive(pid: number): boolean;
|
|
52
|
-
abstract listProcessesContaining(marker: string): ProcessSnapshot[];
|
|
53
|
-
abstract getStartTime(pid: number): string | null;
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
//#region lib/engine/connectors/base-connector-config.d.ts
|
|
57
|
-
/**
|
|
58
|
-
* Fields every connector config carries, regardless of type. The discriminated
|
|
59
|
-
* union of concrete connector configs no longer lives in core: each connector
|
|
60
|
-
* type owns its full schema inside its descriptor, and core handles connectors
|
|
61
|
-
* through this base shape plus the injected registry. `type` is an open string
|
|
62
|
-
* here on purpose — core does not enumerate the known connector types.
|
|
63
|
-
*/
|
|
64
|
-
declare const baseConnectorConfigSchema: z.ZodObject<{
|
|
65
|
-
id: z.ZodString;
|
|
66
|
-
name: z.ZodString;
|
|
67
|
-
type: z.ZodString;
|
|
68
|
-
createdAt: z.ZodOptional<z.ZodString>;
|
|
69
|
-
updatedAt: z.ZodOptional<z.ZodString>;
|
|
70
|
-
}, z.core.$strip>;
|
|
71
|
-
type BaseConnectorConfig = z.infer<typeof baseConnectorConfigSchema>;
|
|
72
|
-
//#endregion
|
|
73
|
-
//#region lib/engine/connectors/connector-adapter.d.ts
|
|
74
|
-
/**
|
|
75
|
-
* A JSON-serializable value. Connector call bodies are sent to external APIs as
|
|
76
|
-
* JSON, so the body must be representable as JSON — `JsonValue` says exactly
|
|
77
|
-
* that, replacing a bare `unknown` that let non-serializable values (functions,
|
|
78
|
-
* symbols, class instances) slip through to `JSON.stringify`.
|
|
79
|
-
*/
|
|
80
|
-
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
81
|
-
[key: string]: JsonValue;
|
|
82
|
-
};
|
|
83
|
-
type CallInput = {
|
|
84
|
-
method: string;
|
|
85
|
-
path: string; /** JSON request body. Omit for GET-like calls. */
|
|
86
|
-
body?: JsonValue;
|
|
87
|
-
};
|
|
88
|
-
declare abstract class FunnelConnectorAdapter {
|
|
89
|
-
/**
|
|
90
|
-
* Dispatches one Claude → external call. The response is the external API's
|
|
91
|
-
* raw payload, typed `unknown` because its shape is the provider's concern —
|
|
92
|
-
* the caller (Claude, via MCP) interprets it.
|
|
93
|
-
*/
|
|
94
|
-
abstract call(input: CallInput): Promise<unknown>;
|
|
95
|
-
}
|
|
96
|
-
//#endregion
|
|
97
|
-
//#region lib/engine/connectors/connector-listener.d.ts
|
|
98
|
-
type NotifyFn = (content: string, meta?: Record<string, string>) => Promise<void>;
|
|
99
|
-
/**
|
|
100
|
-
* Long-lived event source for one connector.
|
|
101
|
-
*
|
|
102
|
-
* `start()` opens the underlying connection (Slack Socket Mode, Discord
|
|
103
|
-
* Gateway, GH polling, schedule tick) and pushes events through `notify`.
|
|
104
|
-
* `stop()` releases the resources so the supervisor can recreate the listener
|
|
105
|
-
* with new config without restarting the whole gateway. `isAlive()` lets the
|
|
106
|
-
* supervisor periodically health-check and auto-restart dead listeners; the
|
|
107
|
-
* default optimistic implementation is fine for poll/tick-based listeners
|
|
108
|
-
* that self-heal.
|
|
109
|
-
*/
|
|
110
|
-
declare abstract class FunnelConnectorListener {
|
|
111
|
-
abstract start(notify: NotifyFn): Promise<void>;
|
|
112
|
-
abstract stop(): Promise<void>;
|
|
113
|
-
isAlive(): boolean;
|
|
114
|
-
}
|
|
115
|
-
//#endregion
|
|
116
|
-
//#region lib/engine/diagnostic-log/diagnostic-log.d.ts
|
|
117
|
-
/**
|
|
118
|
-
* Points in the listener's connection lifecycle. The single source of truth
|
|
119
|
-
* for the value set: the `status` column schema, the `ConnectorConnectionStatus`
|
|
120
|
-
* union, and the runtime Set used to narrow on read-back all derive from this
|
|
121
|
-
* array, so adding a status is a one-line change that cannot drift out of sync.
|
|
122
|
-
*
|
|
123
|
-
* started start() was called
|
|
124
|
-
* connected the socket opened and events can flow
|
|
125
|
-
* disconnected the socket was closed by a stop() call (a clean teardown)
|
|
126
|
-
* auth-failed the token was rejected before the socket opened
|
|
127
|
-
* stopped the listener was fully torn down (always follows a stop(),
|
|
128
|
-
* paired with the disconnected/error that preceded it)
|
|
129
|
-
* error start/stop threw, or Bolt surfaced an error frame — this is
|
|
130
|
-
* also where an unsolicited socket drop shows up when Bolt
|
|
131
|
-
* reports it (an `error` with no following `stopped` means the
|
|
132
|
-
* supervisor recycled the listener, not a clean stop)
|
|
133
|
-
*
|
|
134
|
-
* A connection row is independent of any single inbound event, so it carries
|
|
135
|
-
* no `eventId`. This is how "no notification arrived because the listener
|
|
136
|
-
* never connected (or dropped, or failed auth)" becomes visible: the
|
|
137
|
-
* raw/processed tables only hold events that *did* arrive.
|
|
138
|
-
*/
|
|
139
|
-
declare const CONNECTOR_CONNECTION_STATUSES: readonly ["started", "connected", "disconnected", "auth-failed", "stopped", "error"];
|
|
140
|
-
type ConnectorConnectionStatus = (typeof CONNECTOR_CONNECTION_STATUSES)[number];
|
|
141
|
-
/**
|
|
142
|
-
* Rows stored in the diagnostic tables. Connector-agnostic on purpose: `type`
|
|
143
|
-
* carries the listener kind ("slack" | "discord" | "gh" | "schedule") so new
|
|
144
|
-
* connectors land in the same tables without a schema change. `event_id` is
|
|
145
|
-
* the correlation key the listener mints once per inbound event and stamps
|
|
146
|
-
* onto both the raw and processed rows, so the two are joinable even though
|
|
147
|
-
* they live in separate tables with independent `seq` counters.
|
|
148
|
-
*
|
|
149
|
-
* These schemas mirror the stored shape (snake_case columns) the way
|
|
150
|
-
* `FunnelEvent` does for the replay log; they exist for `z.infer` and to
|
|
151
|
-
* document the column set, not as a parse boundary.
|
|
152
|
-
*/
|
|
153
|
-
declare const connectorRawEventSchema: z.ZodObject<{
|
|
154
|
-
event_id: z.ZodString;
|
|
155
|
-
type: z.ZodString;
|
|
156
|
-
connector_id: z.ZodNullable<z.ZodString>;
|
|
157
|
-
channel_id: z.ZodNullable<z.ZodString>;
|
|
158
|
-
payload: z.ZodString;
|
|
159
|
-
}, z.core.$strip>;
|
|
160
|
-
type ConnectorRawEvent = z.infer<typeof connectorRawEventSchema>;
|
|
161
|
-
declare const connectorProcessedEventSchema: z.ZodObject<{
|
|
162
|
-
event_id: z.ZodString;
|
|
163
|
-
type: z.ZodString;
|
|
164
|
-
connector_id: z.ZodNullable<z.ZodString>;
|
|
165
|
-
channel_id: z.ZodNullable<z.ZodString>;
|
|
166
|
-
outcome: z.ZodString;
|
|
167
|
-
payload: z.ZodString;
|
|
168
|
-
}, z.core.$strip>;
|
|
169
|
-
type ConnectorProcessedEvent = z.infer<typeof connectorProcessedEventSchema>;
|
|
170
|
-
declare const connectorConnectionEventSchema: z.ZodObject<{
|
|
171
|
-
type: z.ZodString;
|
|
172
|
-
connector_id: z.ZodNullable<z.ZodString>;
|
|
173
|
-
channel_id: z.ZodNullable<z.ZodString>;
|
|
174
|
-
status: z.ZodEnum<{
|
|
175
|
-
error: "error";
|
|
176
|
-
started: "started";
|
|
177
|
-
connected: "connected";
|
|
178
|
-
disconnected: "disconnected";
|
|
179
|
-
"auth-failed": "auth-failed";
|
|
180
|
-
stopped: "stopped";
|
|
181
|
-
}>;
|
|
182
|
-
detail: z.ZodString;
|
|
183
|
-
}, z.core.$strip>;
|
|
184
|
-
type ConnectorConnectionEvent = z.infer<typeof connectorConnectionEventSchema>;
|
|
185
|
-
/** The connector a row belongs to — the axis every diagnostic table shares. */
|
|
186
|
-
type ConnectorRef = {
|
|
187
|
-
type: string;
|
|
188
|
-
connectorId: string | null;
|
|
189
|
-
channelId: string | null;
|
|
190
|
-
};
|
|
191
|
-
/** A row tied to one inbound event, joinable to its twin by `eventId`. */
|
|
192
|
-
type ConnectorEventKeys = ConnectorRef & {
|
|
193
|
-
/** Correlation id shared by the raw and processed rows of the same inbound event. */eventId: string;
|
|
194
|
-
};
|
|
195
|
-
/** One untouched inbound event to persist, before any processing. */
|
|
196
|
-
type ConnectorRawRecord = ConnectorEventKeys & {
|
|
197
|
-
/** The listener's untouched payload, already JSON-stringified by the caller. */payload: string;
|
|
198
|
-
};
|
|
199
|
-
/** The processor's verdict for one inbound event. */
|
|
200
|
-
type ConnectorProcessedRecord = ConnectorEventKeys & {
|
|
201
|
-
/**
|
|
202
|
-
* "emitted" on successful delivery, "emitted:delivery-failed" when the
|
|
203
|
-
* downstream notify threw, or "skip:<reason>" when the processor dropped it.
|
|
204
|
-
*/
|
|
205
|
-
outcome: string;
|
|
206
|
-
/**
|
|
207
|
-
* The delivered body (content + meta) for an emitted event. For a skipped
|
|
208
|
-
* event there is no body, so the listener records the event JSON here
|
|
209
|
-
* instead — keeping a skipped row self-describing rather than blank.
|
|
210
|
-
*/
|
|
211
|
-
payload: string;
|
|
212
|
-
};
|
|
213
|
-
type ConnectorConnectionRecord = ConnectorRef & {
|
|
214
|
-
status: ConnectorConnectionStatus; /** Free-form context (an error message, a reason) or "" when none. */
|
|
215
|
-
detail: string;
|
|
216
|
-
};
|
|
217
|
-
/**
|
|
218
|
-
* Filters every table query accepts — the read-side mirror of `ConnectorRef`.
|
|
219
|
-
* Each per-table query extends this with its own table's column, the same way
|
|
220
|
-
* each record extends `ConnectorRef`, so neither half of the file treats one
|
|
221
|
-
* table's shape as the base for the others.
|
|
222
|
-
*/
|
|
223
|
-
type ConnectorQuery = {
|
|
224
|
-
type?: string;
|
|
225
|
-
connectorId?: string | null;
|
|
226
|
-
channelId?: string | null; /** Cap on returned rows. The most recent matching rows are returned, oldest first. */
|
|
227
|
-
limit?: number;
|
|
228
|
-
};
|
|
229
|
-
type ConnectorRawQuery = ConnectorQuery;
|
|
230
|
-
type ConnectorProcessedQuery = ConnectorQuery & {
|
|
231
|
-
outcome?: string;
|
|
232
|
-
};
|
|
233
|
-
type ConnectorConnectionQuery = ConnectorQuery & {
|
|
234
|
-
status?: ConnectorConnectionStatus;
|
|
235
|
-
};
|
|
236
|
-
/**
|
|
237
|
-
* A stored row, ascending by `seq`. `seq` is per-table (each table counts
|
|
238
|
-
* independently) and is for ordering within one table, not for correlating
|
|
239
|
-
* across them — use `eventId` to join raw and processed.
|
|
240
|
-
*/
|
|
241
|
-
type StoredRawEvent = ConnectorRawRecord & {
|
|
242
|
-
seq: number;
|
|
243
|
-
ts: number;
|
|
244
|
-
};
|
|
245
|
-
type StoredProcessedEvent = ConnectorProcessedRecord & {
|
|
246
|
-
seq: number;
|
|
247
|
-
ts: number;
|
|
248
|
-
};
|
|
249
|
-
type StoredConnectionEvent = ConnectorConnectionRecord & {
|
|
250
|
-
seq: number;
|
|
251
|
-
ts: number;
|
|
252
|
-
};
|
|
253
|
-
/**
|
|
254
|
-
* Three-table diagnostic log of everything a connector listener does, so
|
|
255
|
-
* "why was there no notification?" is answerable whichever way it failed:
|
|
256
|
-
* - `raw` — every inbound event, before any filtering, with the listener's
|
|
257
|
-
* untouched payload (the Slack Bolt event, the GH webhook, …)
|
|
258
|
-
* - `processed` — the verdict for that event: `outcome` (emitted, or the
|
|
259
|
-
* reason it was dropped) and, when emitted, the body that was delivered.
|
|
260
|
-
* Shares an `eventId` with its raw row, so the two join into one story.
|
|
261
|
-
* - `connection` — the listener's lifecycle (started, connected, dropped,
|
|
262
|
-
* auth-failed, stopped, errored). This is the half the event tables can't
|
|
263
|
-
* show: an event that never arrived leaves no raw row, but a listener that
|
|
264
|
-
* never connected leaves a `connection` trail that says so.
|
|
265
|
-
*
|
|
266
|
-
* The three are physically separate (independent retention and payload-size
|
|
267
|
-
* policy) so a query never crosses them by accident and a huge raw payload
|
|
268
|
-
* never bloats the verdict or lifecycle trails. None flow to WS clients or the
|
|
269
|
-
* MCP channel — this is a separate store from `FunnelEventLog` (replay) and
|
|
270
|
-
* exists solely for debugging.
|
|
271
|
-
*
|
|
272
|
-
* Implementations:
|
|
273
|
-
* - `SqliteConnectorDiagnosticLog` — the default; survives daemon restarts,
|
|
274
|
-
* bounded by per-table row/age caps.
|
|
275
|
-
* - `MemoryConnectorDiagnosticLog` — an in-process double for tests.
|
|
276
|
-
*/
|
|
277
|
-
declare abstract class ConnectorDiagnosticLog {
|
|
278
|
-
abstract recordRaw(record: ConnectorRawRecord): void;
|
|
279
|
-
abstract recordProcessed(record: ConnectorProcessedRecord): void;
|
|
280
|
-
abstract recordConnection(record: ConnectorConnectionRecord): void;
|
|
281
|
-
abstract queryRaw(query: ConnectorRawQuery): StoredRawEvent[];
|
|
282
|
-
abstract queryProcessed(query: ConnectorProcessedQuery): StoredProcessedEvent[];
|
|
283
|
-
abstract queryConnection(query: ConnectorConnectionQuery): StoredConnectionEvent[];
|
|
284
|
-
/** Drop every diagnostic row across all three tables and reclaim the files. */
|
|
285
|
-
abstract clear(): void;
|
|
286
|
-
abstract close(): void;
|
|
287
|
-
}
|
|
288
|
-
//#endregion
|
|
289
|
-
//#region lib/engine/http/http-client.d.ts
|
|
290
|
-
type HttpRequest = {
|
|
291
|
-
method: string;
|
|
292
|
-
url: string;
|
|
293
|
-
headers?: Record<string, string>;
|
|
294
|
-
body?: string;
|
|
295
|
-
};
|
|
296
|
-
type HttpResponse = {
|
|
297
|
-
status: number;
|
|
298
|
-
ok: boolean;
|
|
299
|
-
text(): Promise<string>;
|
|
300
|
-
json(): Promise<unknown>;
|
|
301
|
-
};
|
|
302
|
-
declare abstract class FunnelHttpClient {
|
|
303
|
-
abstract fetch(request: HttpRequest): Promise<HttpResponse>;
|
|
304
|
-
}
|
|
305
|
-
//#endregion
|
|
306
|
-
//#region lib/engine/connectors/connector-descriptor.d.ts
|
|
307
|
-
/** Boundaries a listener needs, supplied by the registry at build time. */
|
|
308
|
-
type ConnectorListenerDeps = {
|
|
309
|
-
channelId: string;
|
|
310
|
-
fs: FunnelFileSystem;
|
|
311
|
-
process: FunnelProcessRunner; /** HTTP client for self-detection (Slack auth.test), reactions, and other listener-side REST calls. */
|
|
312
|
-
http: FunnelHttpClient; /** Wall clock — listeners that own a timer (schedule) read it from here so tests can inject a fake. */
|
|
313
|
-
clock: FunnelClock;
|
|
314
|
-
logger?: FunnelLogger;
|
|
315
|
-
diagnosticLog?: ConnectorDiagnosticLog;
|
|
316
|
-
/**
|
|
317
|
-
* Optional shutdown signal forwarded to flume-backed listeners. When the
|
|
318
|
-
* host aborts the signal, the listener's Flume tears down its WebSocket /
|
|
319
|
-
* fetch loop without waiting for the supervisor's `stop()`. Hosts that want
|
|
320
|
-
* a clean SIGTERM story wire `controller.signal` here and call
|
|
321
|
-
* `controller.abort()` in their shutdown handler.
|
|
322
|
-
*/
|
|
323
|
-
signal?: AbortSignal; /** Resolves the per-connector state directory (`<dir>/channels/<id>/connectors/<id>`). */
|
|
324
|
-
connectorDir: (channelId: string, connectorId: string) => string;
|
|
325
|
-
};
|
|
326
|
-
/** Boundaries an adapter needs. Adapters are channel-agnostic. */
|
|
327
|
-
type ConnectorAdapterDeps = {
|
|
328
|
-
fs: FunnelFileSystem;
|
|
329
|
-
process: FunnelProcessRunner; /** HTTP client for outbound calls. Used by the Slack adapter, future REST adapters. */
|
|
330
|
-
http: FunnelHttpClient;
|
|
331
|
-
logger?: FunnelLogger;
|
|
332
|
-
};
|
|
333
|
-
type ConnectorBuildContext = {
|
|
334
|
-
id: string;
|
|
335
|
-
now: string;
|
|
336
|
-
};
|
|
337
|
-
type ConnectorUpdateContext = {
|
|
338
|
-
now: string;
|
|
339
|
-
};
|
|
340
|
-
type ConnectorOperationContext = {
|
|
341
|
-
generateId: () => string;
|
|
342
|
-
now: string;
|
|
343
|
-
};
|
|
344
|
-
/**
|
|
345
|
-
* One named operation a connector type exposes beyond plain CRUD (e.g. schedule
|
|
346
|
-
* entry add/remove/list). Returns the next config and an arbitrary result; when
|
|
347
|
-
* the returned config is reference-equal to the input, the channels layer treats
|
|
348
|
-
* the call as a read and skips persistence.
|
|
349
|
-
*/
|
|
350
|
-
type ConnectorOperation = (props: {
|
|
351
|
-
config: BaseConnectorConfig;
|
|
352
|
-
args: unknown;
|
|
353
|
-
context: ConnectorOperationContext;
|
|
354
|
-
}) => {
|
|
355
|
-
config: BaseConnectorConfig;
|
|
356
|
-
result: unknown;
|
|
357
|
-
};
|
|
358
|
-
/**
|
|
359
|
-
* Everything core needs to handle one connector type, without importing it. A
|
|
360
|
-
* descriptor accepts/returns `BaseConnectorConfig` at every boundary and parses
|
|
361
|
-
* to its concrete config internally (via `schema`), so the registry can hold a
|
|
362
|
-
* homogeneous `ConnectorDescriptor[]` with no variance gymnastics. Type-specific
|
|
363
|
-
* launch hooks (e.g. Schedule `onFired`) are closed over by the descriptor
|
|
364
|
-
* factory, not threaded through here. Each descriptor parses configs to its
|
|
365
|
-
* concrete shape internally (it owns its zod schema), so no schema is exposed
|
|
366
|
-
* here — that also sidesteps the variance trap of a `ZodType<Slack>` field
|
|
367
|
-
* declared as `ZodType<BaseConnectorConfig>`.
|
|
368
|
-
*/
|
|
369
|
-
type ConnectorDescriptor = {
|
|
370
|
-
type: string;
|
|
371
|
-
createListener: (config: BaseConnectorConfig, deps: ConnectorListenerDeps) => FunnelConnectorListener;
|
|
372
|
-
createAdapter: ((config: BaseConnectorConfig, deps: ConnectorAdapterDeps) => FunnelConnectorAdapter) | null; /** Whether the MCP channel server exposes this type as a callable tool. */
|
|
373
|
-
toolExposed: boolean;
|
|
374
|
-
secretTokens: (config: BaseConnectorConfig) => string[];
|
|
375
|
-
buildConfig: (input: Record<string, unknown>, context: ConnectorBuildContext) => BaseConnectorConfig;
|
|
376
|
-
applyUpdate: (config: BaseConnectorConfig, fields: Record<string, unknown>, context: ConnectorUpdateContext) => BaseConnectorConfig;
|
|
377
|
-
operations: Record<string, ConnectorOperation>;
|
|
378
|
-
};
|
|
379
|
-
//#endregion
|
|
380
|
-
export { FunnelConnectorListener as A, ProcessSnapshot as B, ConnectorRawRecord as C, connectorConnectionEventSchema as D, StoredRawEvent as E, BaseConnectorConfig as F, RunResult as H, baseConnectorConfigSchema as I, AttachOptions as L, CallInput as M, FunnelConnectorAdapter as N, connectorProcessedEventSchema as O, JsonValue as P, DetachOptions as R, ConnectorRawQuery as S, StoredProcessedEvent as T, RunOptions as V, ConnectorProcessedEvent as _, ConnectorOperation as a, ConnectorQuery as b, FunnelHttpClient as c, CONNECTOR_CONNECTION_STATUSES as d, ConnectorConnectionEvent as f, ConnectorDiagnosticLog as g, ConnectorConnectionStatus as h, ConnectorListenerDeps as i, NotifyFn as j, connectorRawEventSchema as k, HttpRequest as l, ConnectorConnectionRecord as m, ConnectorBuildContext as n, ConnectorOperationContext as o, ConnectorConnectionQuery as p, ConnectorDescriptor as r, ConnectorUpdateContext as s, ConnectorAdapterDeps as t, HttpResponse as u, ConnectorProcessedQuery as v, StoredConnectionEvent as w, ConnectorRawEvent as x, ConnectorProcessedRecord as y, FunnelProcessRunner as z };
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { Database } from "bun:sqlite";
|
|
2
|
-
//#region lib/engine/diagnostic-log/diagnostic-sql-reader.ts
|
|
3
|
-
/**
|
|
4
|
-
* Read-only SQL surface over the three diagnostic tables, for Claude to query
|
|
5
|
-
* the log with arbitrary `SELECT`s. It opens all files read-only and exposes
|
|
6
|
-
* three views — `raw`, `processed`, `connection` — that hide the storage
|
|
7
|
-
* details (the physical table is `logs` and each row's columns live
|
|
8
|
-
* inside a JSON `event` blob): the views surface the columns as plain fields,
|
|
9
|
-
* with `payload` already pulled out of the nested JSON.
|
|
10
|
-
*
|
|
11
|
-
* The tables are separate files. `raw` and `processed` share an `event_id`,
|
|
12
|
-
* so a `JOIN` answers "the event arrived, but what verdict did it get?";
|
|
13
|
-
* `connection` answers the other half — "did the listener ever connect at
|
|
14
|
-
* all?". Writes are impossible: the connection is read-only and `query`
|
|
15
|
-
* rejects anything but a single `SELECT`.
|
|
16
|
-
*/
|
|
17
|
-
var ConnectorDiagnosticSqlReader = class {
|
|
18
|
-
db;
|
|
19
|
-
constructor(props) {
|
|
20
|
-
const db = new Database(props.rawPath, { readonly: true });
|
|
21
|
-
try {
|
|
22
|
-
db.run("PRAGMA busy_timeout = 500");
|
|
23
|
-
db.prepare("ATTACH DATABASE ? AS processeddb").run(props.processedPath);
|
|
24
|
-
db.prepare("ATTACH DATABASE ? AS connectiondb").run(props.connectionPath);
|
|
25
|
-
db.run(rawViewSql);
|
|
26
|
-
db.run(processedViewSql);
|
|
27
|
-
db.run(connectionViewSql);
|
|
28
|
-
} catch (error) {
|
|
29
|
-
db.close();
|
|
30
|
-
throw error;
|
|
31
|
-
}
|
|
32
|
-
this.db = db;
|
|
33
|
-
Object.freeze(this);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Run one read-only `SELECT` and return the rows. Returns an `Error` (rather
|
|
37
|
-
* than throwing) for a non-SELECT statement or a SQL error, so the caller
|
|
38
|
-
* can surface the message without a stack trace.
|
|
39
|
-
*/
|
|
40
|
-
query(sql, params = []) {
|
|
41
|
-
const trimmed = sql.trim().replace(/;$/, "").trim();
|
|
42
|
-
if (!/^select\b/i.test(trimmed)) return /* @__PURE__ */ new Error("only a single SELECT statement is allowed");
|
|
43
|
-
if (trimmed.includes(";")) return /* @__PURE__ */ new Error("only a single statement is allowed (remove the ';')");
|
|
44
|
-
try {
|
|
45
|
-
return this.db.prepare(trimmed).all(...params);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
close() {
|
|
51
|
-
this.db.close();
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
const rawViewSql = `CREATE TEMP VIEW raw AS SELECT
|
|
55
|
-
seq,
|
|
56
|
-
ts,
|
|
57
|
-
json_extract(event, '$.event_id') AS event_id,
|
|
58
|
-
json_extract(event, '$.type') AS type,
|
|
59
|
-
json_extract(event, '$.connector_id') AS connector_id,
|
|
60
|
-
json_extract(event, '$.channel_id') AS channel_id,
|
|
61
|
-
json_extract(event, '$.payload') AS payload
|
|
62
|
-
FROM main.logs`;
|
|
63
|
-
const processedViewSql = `CREATE TEMP VIEW processed AS SELECT
|
|
64
|
-
seq,
|
|
65
|
-
ts,
|
|
66
|
-
json_extract(event, '$.event_id') AS event_id,
|
|
67
|
-
json_extract(event, '$.type') AS type,
|
|
68
|
-
json_extract(event, '$.connector_id') AS connector_id,
|
|
69
|
-
json_extract(event, '$.channel_id') AS channel_id,
|
|
70
|
-
json_extract(event, '$.outcome') AS outcome,
|
|
71
|
-
json_extract(event, '$.payload') AS payload
|
|
72
|
-
FROM processeddb.logs`;
|
|
73
|
-
const connectionViewSql = `CREATE TEMP VIEW connection AS SELECT
|
|
74
|
-
seq,
|
|
75
|
-
ts,
|
|
76
|
-
json_extract(event, '$.type') AS type,
|
|
77
|
-
json_extract(event, '$.connector_id') AS connector_id,
|
|
78
|
-
json_extract(event, '$.channel_id') AS channel_id,
|
|
79
|
-
json_extract(event, '$.status') AS status,
|
|
80
|
-
json_extract(event, '$.detail') AS detail
|
|
81
|
-
FROM connectiondb.logs`;
|
|
82
|
-
//#endregion
|
|
83
|
-
export { ConnectorDiagnosticSqlReader as t };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region lib/engine/fs/file-system.ts
|
|
2
|
-
/**
|
|
3
|
-
* Filesystem boundary used everywhere funnel reads or writes.
|
|
4
|
-
* Default is NodeFunnelFileSystem (real `node:fs`); MemoryFunnelFileSystem
|
|
5
|
-
* provides a sandbox for tests and embedded use.
|
|
6
|
-
*/
|
|
7
|
-
var FunnelFileSystem = class {};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { FunnelFileSystem as t };
|
package/dist/logger-B6iyNbxM.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region lib/engine/logger/logger.ts
|
|
2
|
-
/**
|
|
3
|
-
* Structured logger with three levels and an optional log-file path.
|
|
4
|
-
* Defaults to NodeFunnelLogger (appends to `<os.tmpdir()>/funnel/funnel.log`);
|
|
5
|
-
* MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
|
|
6
|
-
*/
|
|
7
|
-
var FunnelLogger = class {};
|
|
8
|
-
//#endregion
|
|
9
|
-
export { FunnelLogger as t };
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
|
|
3
|
-
//#region lib/engine/connectors/schedule-connector-schema.d.ts
|
|
4
|
-
/**
|
|
5
|
-
* Catch-up behavior when the daemon was down past one or more matching minutes.
|
|
6
|
-
*
|
|
7
|
-
* - `latest`: fire once with the most recent missed match (default; preserves prior behavior).
|
|
8
|
-
* - `all`: fire once per missed minute, oldest first (capped at 24 h).
|
|
9
|
-
* - `skip`: never fire missed matches; only fire when the current minute matches.
|
|
10
|
-
*/
|
|
11
|
-
declare const scheduleCatchupPolicySchema: z.ZodEnum<{
|
|
12
|
-
latest: "latest";
|
|
13
|
-
all: "all";
|
|
14
|
-
skip: "skip";
|
|
15
|
-
}>;
|
|
16
|
-
type ScheduleCatchupPolicy = z.infer<typeof scheduleCatchupPolicySchema>;
|
|
17
|
-
declare const scheduleEntrySchema: z.ZodObject<{
|
|
18
|
-
id: z.ZodString;
|
|
19
|
-
cron: z.ZodString;
|
|
20
|
-
prompt: z.ZodString;
|
|
21
|
-
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
22
|
-
catchupPolicy: z.ZodDefault<z.ZodEnum<{
|
|
23
|
-
latest: "latest";
|
|
24
|
-
all: "all";
|
|
25
|
-
skip: "skip";
|
|
26
|
-
}>>;
|
|
27
|
-
}, z.core.$strip>;
|
|
28
|
-
type ScheduleEntry = z.infer<typeof scheduleEntrySchema>;
|
|
29
|
-
declare const scheduleConnectorSchema: z.ZodObject<{
|
|
30
|
-
id: z.ZodString;
|
|
31
|
-
name: z.ZodString;
|
|
32
|
-
type: z.ZodLiteral<"schedule">;
|
|
33
|
-
entries: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
34
|
-
id: z.ZodString;
|
|
35
|
-
cron: z.ZodString;
|
|
36
|
-
prompt: z.ZodString;
|
|
37
|
-
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
38
|
-
catchupPolicy: z.ZodDefault<z.ZodEnum<{
|
|
39
|
-
latest: "latest";
|
|
40
|
-
all: "all";
|
|
41
|
-
skip: "skip";
|
|
42
|
-
}>>;
|
|
43
|
-
}, z.core.$strip>>>;
|
|
44
|
-
createdAt: z.ZodOptional<z.ZodString>;
|
|
45
|
-
updatedAt: z.ZodOptional<z.ZodString>;
|
|
46
|
-
}, z.core.$strip>;
|
|
47
|
-
type ScheduleConnectorConfig = z.infer<typeof scheduleConnectorSchema>;
|
|
48
|
-
//#endregion
|
|
49
|
-
export { scheduleConnectorSchema as a, scheduleCatchupPolicySchema as i, ScheduleConnectorConfig as n, scheduleEntrySchema as o, ScheduleEntry as r, ScheduleCatchupPolicy as t };
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
//#region lib/engine/connectors/schedule-connector-schema.ts
|
|
3
|
-
/**
|
|
4
|
-
* Catch-up behavior when the daemon was down past one or more matching minutes.
|
|
5
|
-
*
|
|
6
|
-
* - `latest`: fire once with the most recent missed match (default; preserves prior behavior).
|
|
7
|
-
* - `all`: fire once per missed minute, oldest first (capped at 24 h).
|
|
8
|
-
* - `skip`: never fire missed matches; only fire when the current minute matches.
|
|
9
|
-
*/
|
|
10
|
-
const scheduleCatchupPolicySchema = z.enum([
|
|
11
|
-
"latest",
|
|
12
|
-
"all",
|
|
13
|
-
"skip"
|
|
14
|
-
]);
|
|
15
|
-
const scheduleEntrySchema = z.object({
|
|
16
|
-
id: z.string(),
|
|
17
|
-
cron: z.string(),
|
|
18
|
-
prompt: z.string(),
|
|
19
|
-
enabled: z.boolean().default(true),
|
|
20
|
-
catchupPolicy: scheduleCatchupPolicySchema.default("latest")
|
|
21
|
-
});
|
|
22
|
-
const scheduleConnectorSchema = z.object({
|
|
23
|
-
id: z.string(),
|
|
24
|
-
name: z.string(),
|
|
25
|
-
type: z.literal("schedule"),
|
|
26
|
-
entries: z.array(scheduleEntrySchema).default([]),
|
|
27
|
-
createdAt: z.string().datetime().optional(),
|
|
28
|
-
updatedAt: z.string().datetime().optional()
|
|
29
|
-
});
|
|
30
|
-
//#endregion
|
|
31
|
-
export { scheduleConnectorSchema as n, scheduleEntrySchema as r, scheduleCatchupPolicySchema as t };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region lib/engine/id/id-generator.ts
|
|
2
|
-
/**
|
|
3
|
-
* ID generator boundary. Default NodeFunnelIdGenerator wraps `crypto.randomUUID()`;
|
|
4
|
-
* MemoryFunnelIdGenerator emits `<prefix>-1, <prefix>-2, ...` for deterministic tests.
|
|
5
|
-
*/
|
|
6
|
-
var FunnelIdGenerator = class {};
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region lib/engine/settings/settings-reader.ts
|
|
9
|
-
var FunnelSettingsReader = class {};
|
|
10
|
-
//#endregion
|
|
11
|
-
export { FunnelIdGenerator as n, FunnelSettingsReader as t };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|