@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
package/dist/index.js
CHANGED
|
@@ -1,37 +1,43 @@
|
|
|
1
|
-
import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import { t as
|
|
5
|
-
import { n as
|
|
6
|
-
import { n as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { a as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { t as
|
|
13
|
-
import { t as
|
|
14
|
-
import { t as
|
|
15
|
-
import {
|
|
16
|
-
import { t as
|
|
17
|
-
import { t as
|
|
18
|
-
import { t as
|
|
19
|
-
import { t as
|
|
20
|
-
import { t as
|
|
21
|
-
import {
|
|
22
|
-
import { t as
|
|
23
|
-
import { t as FunnelConnectorListener } from "./connector-listener-mPGZYa8e.js";
|
|
24
|
-
import { t as FunnelSlackEventProcessor } from "./slack-event-processor-xFDG3US0.js";
|
|
25
|
-
import { n as scheduleConnectorSchema, r as scheduleEntrySchema, t as scheduleCatchupPolicySchema } from "./schedule-connector-schema-DKEPZnVv.js";
|
|
1
|
+
import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-HP-bo9Kv.js";
|
|
2
|
+
import { n as FunnelFileSystem, t as NodeFunnelFileSystem } from "./node-file-system-xJx7dymE.js";
|
|
3
|
+
import { n as FunnelProcessRunner, t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js";
|
|
4
|
+
import { n as FunnelHttpClient, t as NodeFunnelHttpClient } from "./node-http-client-SX3xFh4h.js";
|
|
5
|
+
import { a as expandHomeDir, c as SETTINGS_VERSION, d as profileConfigSchema, f as settingsSchema, g as FunnelIdGenerator, h as NodeFunnelIdGenerator, i as SETTINGS_PATH, l as channelConfigSchema, m as FunnelSettingsReader, n as FUNNEL_DIR, o as resolveFunnelDir, p as baseConnectorConfigSchema, r as FunnelSettingsStore, s as resolveFunnelPort, t as DEFAULT_GATEWAY_PORT, u as channelDeliveryModeSchema } from "./settings-store-ZFWBhOnp.js";
|
|
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
|
+
import { a as FunnelMcp, o as FunnelFileProcessGuard, s as FunnelClaude, t as renderYaml } from "./yaml-render-DxxRQT-V.js";
|
|
8
|
+
import { n as sessionFileExists, t as FunnelProfiles } from "./profiles-KpN7_gBw.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
|
+
import { t as FunnelDoctor } from "./funnel-doctor-Csw5qjcH.js";
|
|
12
|
+
import { t as FunnelDocs } from "./funnel-docs-CI4hMkhq.js";
|
|
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
|
+
import { t as discordConnectorSchema } from "./discord-connector-schema-saAGuPmJ.js";
|
|
15
|
+
import { t as ghConnectorSchema } from "./gh-connector-schema-DmZTrzUu.js";
|
|
16
|
+
import { t as slackConnectorSchema } from "./slack-connector-schema-EGVuuqSX.js";
|
|
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-Qs4cf9I_.js";
|
|
19
|
+
import { t as FunnelConnectorAdapter } from "./connector-adapter-BL2ehMej.js";
|
|
20
|
+
import { t as FunnelConnectorListener } from "./connector-listener-BcQMzY6Q.js";
|
|
21
|
+
import { t as FunnelSlackEventProcessor } from "./slack-event-processor-Cs_YuI3w.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";
|
|
26
23
|
import { dirname, join, resolve } from "node:path";
|
|
27
24
|
import { hc } from "hono/client";
|
|
28
25
|
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
29
26
|
import { z } from "zod";
|
|
30
27
|
import { fileURLToPath } from "node:url";
|
|
31
28
|
import { createFactory } from "hono/factory";
|
|
29
|
+
import { Database } from "bun:sqlite";
|
|
32
30
|
import { HTTPException } from "hono/http-exception";
|
|
33
31
|
import { zValidator } from "@hono/zod-validator";
|
|
34
32
|
import { Hono } from "hono";
|
|
33
|
+
//#region lib/engine/logger/logger.ts
|
|
34
|
+
/**
|
|
35
|
+
* Structured logger with three levels and an optional log-file path.
|
|
36
|
+
* Defaults to NodeFunnelLogger (appends to `<os.tmpdir()>/funnel/funnel.log`);
|
|
37
|
+
* MemoryFunnelLogger captures entries in memory and NoopFunnelLogger silences output.
|
|
38
|
+
*/
|
|
39
|
+
var FunnelLogger = class {};
|
|
40
|
+
//#endregion
|
|
35
41
|
//#region lib/engine/time/clock.ts
|
|
36
42
|
/**
|
|
37
43
|
* Time boundary. Default NodeFunnelClock returns `new Date()`; MemoryFunnelClock
|
|
@@ -371,6 +377,76 @@ var FunnelChannels = class {
|
|
|
371
377
|
}
|
|
372
378
|
};
|
|
373
379
|
//#endregion
|
|
380
|
+
//#region lib/engine/claude/file-session-store.ts
|
|
381
|
+
const sessionIdsSchema = z.record(z.string(), z.string());
|
|
382
|
+
/**
|
|
383
|
+
* Session-id store for repo-local funnel.json profiles, isolated from the
|
|
384
|
+
* global profile list while remaining stable across launches.
|
|
385
|
+
*/
|
|
386
|
+
var FunnelFileSessionStore = class {
|
|
387
|
+
fs;
|
|
388
|
+
path;
|
|
389
|
+
constructor(deps) {
|
|
390
|
+
this.fs = deps.fs;
|
|
391
|
+
this.path = join(deps.dir, "claude", "local-sessions.json");
|
|
392
|
+
Object.freeze(this);
|
|
393
|
+
}
|
|
394
|
+
getSessionId(profileId) {
|
|
395
|
+
this.fs.mkdirSync(dirname(this.path), { recursive: true });
|
|
396
|
+
return this.fs.withFileLock(`${this.path}.lock`, () => this.read()[profileId] ?? null);
|
|
397
|
+
}
|
|
398
|
+
setSessionId(profileId, sessionId) {
|
|
399
|
+
this.fs.mkdirSync(dirname(this.path), { recursive: true });
|
|
400
|
+
this.fs.withFileLock(`${this.path}.lock`, () => {
|
|
401
|
+
const sessionIds = this.read();
|
|
402
|
+
sessionIds[profileId] = sessionId;
|
|
403
|
+
this.fs.writeFileSync(this.path, `${JSON.stringify(sessionIds, null, 2)}\n`);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
sessionFileExists(cwd, sessionId, env) {
|
|
407
|
+
return sessionFileExists({
|
|
408
|
+
fs: this.fs,
|
|
409
|
+
cwd,
|
|
410
|
+
sessionId,
|
|
411
|
+
env
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
read() {
|
|
415
|
+
if (!this.fs.existsSync(this.path)) return {};
|
|
416
|
+
const parsed = JSON.parse(this.fs.readFileSync(this.path));
|
|
417
|
+
const sessionIds = sessionIdsSchema.safeParse(parsed);
|
|
418
|
+
if (!sessionIds.success) throw new Error(`invalid local profile session store (${this.path})`);
|
|
419
|
+
return sessionIds.data;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
//#endregion
|
|
423
|
+
//#region lib/engine/claude/routed-session-store.ts
|
|
424
|
+
/**
|
|
425
|
+
* Keeps repo-local profile execution state out of the global profile store.
|
|
426
|
+
* Local ids carry a reserved prefix generated by localProfileId().
|
|
427
|
+
*/
|
|
428
|
+
var FunnelRoutedSessionStore = class {
|
|
429
|
+
global;
|
|
430
|
+
local;
|
|
431
|
+
constructor(deps) {
|
|
432
|
+
this.global = deps.global;
|
|
433
|
+
this.local = deps.local;
|
|
434
|
+
Object.freeze(this);
|
|
435
|
+
}
|
|
436
|
+
getSessionId(profileId) {
|
|
437
|
+
return this.storeFor(profileId).getSessionId(profileId);
|
|
438
|
+
}
|
|
439
|
+
setSessionId(profileId, sessionId) {
|
|
440
|
+
this.storeFor(profileId).setSessionId(profileId, sessionId);
|
|
441
|
+
}
|
|
442
|
+
sessionFileExists(cwd, sessionId, env) {
|
|
443
|
+
return this.global.sessionFileExists(cwd, sessionId, env);
|
|
444
|
+
}
|
|
445
|
+
storeFor(profileId) {
|
|
446
|
+
return profileId.startsWith("local-") ? this.local : this.global;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
//#endregion
|
|
374
450
|
//#region lib/engine/fs/memory-file-system.ts
|
|
375
451
|
const SECRET_MODE = 384;
|
|
376
452
|
var MemoryFunnelFileSystem = class extends FunnelFileSystem {
|
|
@@ -752,7 +828,11 @@ var FunnelGateway = class {
|
|
|
752
828
|
const gatewayScript = resolveDaemonScript();
|
|
753
829
|
const command = this.buildStartCommand(gatewayScript, options);
|
|
754
830
|
this.process.detach(command, {
|
|
755
|
-
env: {
|
|
831
|
+
env: {
|
|
832
|
+
FUNNEL_DIR: this.dir,
|
|
833
|
+
FUNNEL_PORT: String(this.port),
|
|
834
|
+
FUNNEL_TMP_DIR: this.tmpDir
|
|
835
|
+
},
|
|
756
836
|
stdoutFile: this.gatewayLog,
|
|
757
837
|
stderrFile: this.gatewayLog
|
|
758
838
|
});
|
|
@@ -998,6 +1078,7 @@ var Funnel = class Funnel {
|
|
|
998
1078
|
clock;
|
|
999
1079
|
http;
|
|
1000
1080
|
onError;
|
|
1081
|
+
diagnosticLog;
|
|
1001
1082
|
constructor(props = {}) {
|
|
1002
1083
|
const dir = props.dir ?? resolveFunnelDir();
|
|
1003
1084
|
const tmpDir = props.tmpDir ?? funnelTmpDir();
|
|
@@ -1017,6 +1098,7 @@ var Funnel = class Funnel {
|
|
|
1017
1098
|
this.clock = clock;
|
|
1018
1099
|
this.http = http;
|
|
1019
1100
|
this.onError = props.onError ?? noopOnError;
|
|
1101
|
+
this.diagnosticLog = props.diagnosticLog;
|
|
1020
1102
|
const store = props.store ?? new FunnelSettingsStore({
|
|
1021
1103
|
path: this.paths.settings,
|
|
1022
1104
|
fs,
|
|
@@ -1029,7 +1111,7 @@ var Funnel = class Funnel {
|
|
|
1029
1111
|
http,
|
|
1030
1112
|
clock,
|
|
1031
1113
|
logger: this.logger,
|
|
1032
|
-
diagnosticLog:
|
|
1114
|
+
diagnosticLog: this.diagnosticLog,
|
|
1033
1115
|
signal: props.signal,
|
|
1034
1116
|
dir
|
|
1035
1117
|
});
|
|
@@ -1073,11 +1155,18 @@ var Funnel = class Funnel {
|
|
|
1073
1155
|
channels: this.channels,
|
|
1074
1156
|
prompter: props.tokenPrompter ?? new NodeFunnelTokenPrompter()
|
|
1075
1157
|
});
|
|
1158
|
+
const sessions = new FunnelRoutedSessionStore({
|
|
1159
|
+
global: this.profiles,
|
|
1160
|
+
local: new FunnelFileSessionStore({
|
|
1161
|
+
fs,
|
|
1162
|
+
dir
|
|
1163
|
+
})
|
|
1164
|
+
});
|
|
1076
1165
|
this.claude = new FunnelClaude({
|
|
1077
1166
|
channels: this.channels,
|
|
1078
1167
|
mcp,
|
|
1079
1168
|
gateway: this.gateway,
|
|
1080
|
-
sessions
|
|
1169
|
+
sessions,
|
|
1081
1170
|
guard: new FunnelFileProcessGuard({
|
|
1082
1171
|
fs,
|
|
1083
1172
|
process,
|
|
@@ -1092,6 +1181,7 @@ var Funnel = class Funnel {
|
|
|
1092
1181
|
gatewayToken: this.gatewayToken,
|
|
1093
1182
|
channels: this.channels,
|
|
1094
1183
|
publisher: this.publisher,
|
|
1184
|
+
diagnosticLog: this.diagnosticLog,
|
|
1095
1185
|
tmpDir
|
|
1096
1186
|
});
|
|
1097
1187
|
this.recovery = new FunnelRecovery({
|
|
@@ -1154,10 +1244,12 @@ var Funnel = class Funnel {
|
|
|
1154
1244
|
logger: this.logger,
|
|
1155
1245
|
onError: this.onError,
|
|
1156
1246
|
dir: this.paths.dir,
|
|
1247
|
+
tmpDir: this.paths.tmpDir,
|
|
1157
1248
|
killCompetingSlack: options.killCompetingSlack,
|
|
1158
1249
|
token: options.token ?? this.gatewayToken.ensure(),
|
|
1159
1250
|
allowInsecureHost: options.allowInsecureHost,
|
|
1160
|
-
extraRoutes: options.extraRoutes
|
|
1251
|
+
extraRoutes: options.extraRoutes,
|
|
1252
|
+
diagnosticLog: this.diagnosticLog
|
|
1161
1253
|
});
|
|
1162
1254
|
}
|
|
1163
1255
|
/**
|
|
@@ -1184,7 +1276,11 @@ var Funnel = class Funnel {
|
|
|
1184
1276
|
"bun",
|
|
1185
1277
|
gatewayScript
|
|
1186
1278
|
] : ["bun", gatewayScript];
|
|
1187
|
-
return this.process.attach(command
|
|
1279
|
+
return this.process.attach(command, { env: {
|
|
1280
|
+
FUNNEL_DIR: this.paths.dir,
|
|
1281
|
+
FUNNEL_PORT: String(this.gateway.getPort()),
|
|
1282
|
+
FUNNEL_TMP_DIR: this.paths.tmpDir
|
|
1283
|
+
} });
|
|
1188
1284
|
}
|
|
1189
1285
|
gatewayClient() {
|
|
1190
1286
|
const { port } = this.gateway.getStatus();
|
|
@@ -1254,6 +1350,87 @@ var NoopFunnelLogger = class extends FunnelLogger {
|
|
|
1254
1350
|
error() {}
|
|
1255
1351
|
};
|
|
1256
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
|
|
1257
1434
|
//#region lib/gateway/service-routes.ts
|
|
1258
1435
|
/**
|
|
1259
1436
|
* Mountable Hono app that exposes the service layer (`FunnelDiagnostics` +
|
|
@@ -1374,7 +1551,7 @@ const SHORT_FLAGS = {
|
|
|
1374
1551
|
n: "name",
|
|
1375
1552
|
p: "profile"
|
|
1376
1553
|
};
|
|
1377
|
-
const METHOD_KEYWORDS = new Set([
|
|
1554
|
+
const METHOD_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1378
1555
|
"add",
|
|
1379
1556
|
"set",
|
|
1380
1557
|
"remove",
|
|
@@ -1383,7 +1560,7 @@ const METHOD_KEYWORDS = new Set([
|
|
|
1383
1560
|
"request",
|
|
1384
1561
|
"publish"
|
|
1385
1562
|
]);
|
|
1386
|
-
const API_CALL_METHODS = new Set([
|
|
1563
|
+
const API_CALL_METHODS = /* @__PURE__ */ new Set([
|
|
1387
1564
|
"get",
|
|
1388
1565
|
"post",
|
|
1389
1566
|
"put",
|
|
@@ -1474,9 +1651,9 @@ const toRequest = (args) => {
|
|
|
1474
1651
|
};
|
|
1475
1652
|
//#endregion
|
|
1476
1653
|
//#region lib/cli/router/query-to-cli-args.ts
|
|
1477
|
-
const BUILTIN_SKIP = new Set(["help"]);
|
|
1654
|
+
const BUILTIN_SKIP = /* @__PURE__ */ new Set(["help"]);
|
|
1478
1655
|
const queryToCliArgs = (url, reservedKeys = []) => {
|
|
1479
|
-
const skipped = new Set([...BUILTIN_SKIP, ...reservedKeys]);
|
|
1656
|
+
const skipped = /* @__PURE__ */ new Set([...BUILTIN_SKIP, ...reservedKeys]);
|
|
1480
1657
|
const args = [];
|
|
1481
1658
|
const searchParams = new URL(url).searchParams;
|
|
1482
1659
|
for (const entry of searchParams.entries()) {
|
|
@@ -1842,22 +2019,26 @@ usage: funnel channels <ch> connectors <conn> schedules [subcommand]
|
|
|
1842
2019
|
|
|
1843
2020
|
subcommands:
|
|
1844
2021
|
(none) / list schedule entries
|
|
1845
|
-
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
|
|
1846
2023
|
remove <id> / remove entry`), (c) => {
|
|
1847
2024
|
const param = c.req.valid("param");
|
|
1848
2025
|
const funnel = c.env.funnel;
|
|
1849
2026
|
const entries = z.array(scheduleEntrySchema).parse(funnel.channels.connectorOp(param.channel, param.connector, "listEntries", void 0));
|
|
1850
2027
|
if (entries.length === 0) return c.text("no schedule entries");
|
|
1851
|
-
return c.text(entries.map((
|
|
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"));
|
|
1852
2032
|
});
|
|
1853
2033
|
//#endregion
|
|
1854
2034
|
//#region lib/cli/routes/channels.$channel.connectors.$connector.schedules.add.ts
|
|
1855
2035
|
const help$9 = `funnel channels <ch> connectors <conn> schedules add <id> — add a schedule entry
|
|
1856
2036
|
|
|
1857
|
-
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]
|
|
1858
2038
|
|
|
1859
2039
|
options:
|
|
1860
|
-
--cron <expr> / 5-field cron expression (
|
|
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)
|
|
1861
2042
|
--prompt <text> / prompt delivered on each fire (required)
|
|
1862
2043
|
--enabled / fire on schedule (default: true; --enabled=false stores it disabled)
|
|
1863
2044
|
--catchup-policy latest|all|skip / how missed fires are replayed after downtime (default: latest)`;
|
|
@@ -1885,17 +2066,23 @@ const channelsConnectorsSchedulesAddHandler = factory.createHandlers(zValidator$
|
|
|
1885
2066
|
connector: z.string(),
|
|
1886
2067
|
id: z.string()
|
|
1887
2068
|
})), zValidator$1("query", z.object({
|
|
1888
|
-
cron:
|
|
2069
|
+
cron: cronExpressionSchema.optional(),
|
|
2070
|
+
"run-at": z.string().datetime({ offset: true }).optional(),
|
|
1889
2071
|
prompt: z.string(),
|
|
1890
2072
|
enabled: booleanFlag,
|
|
1891
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
|
+
});
|
|
1892
2079
|
})), async (c) => {
|
|
1893
2080
|
const param = c.req.valid("param");
|
|
1894
2081
|
const query = c.req.valid("query");
|
|
1895
2082
|
const funnel = c.env.funnel;
|
|
1896
2083
|
const entry = scheduleEntrySchema.parse(funnel.channels.connectorOp(param.channel, param.connector, "addEntry", {
|
|
1897
2084
|
id: param.id,
|
|
1898
|
-
cron: query.cron,
|
|
2085
|
+
...query.cron !== void 0 ? { cron: query.cron } : { runAt: query["run-at"] },
|
|
1899
2086
|
prompt: query.prompt,
|
|
1900
2087
|
...query.enabled !== void 0 ? { enabled: query.enabled } : {},
|
|
1901
2088
|
...query["catchup-policy"] !== void 0 ? { catchupPolicy: query["catchup-policy"] } : {}
|
|
@@ -2780,6 +2967,14 @@ const gatewayLogsHandler = factory.createHandlers(helpGuard(logsHelp), zValidato
|
|
|
2780
2967
|
process.exit(0);
|
|
2781
2968
|
});
|
|
2782
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
|
|
2783
2978
|
//#region lib/cli/routes/gateway.sql.ts
|
|
2784
2979
|
const PRESETS = {
|
|
2785
2980
|
recent: "SELECT seq, ts, type, outcome FROM processed ORDER BY seq DESC LIMIT 20",
|
|
@@ -2864,10 +3059,7 @@ const gatewaySqlHandler = factory.createHandlers(helpGuard(sqlHelp), zValidator$
|
|
|
2864
3059
|
params = resolvedChannelId ? [resolvedChannelId] : [];
|
|
2865
3060
|
} else if (query.query) sql = query.query;
|
|
2866
3061
|
if (!sql) return c.text(sqlHelp);
|
|
2867
|
-
const
|
|
2868
|
-
const rawPath = join(tmpDir, "connector-raw.db");
|
|
2869
|
-
const processedPath = join(tmpDir, "connector-processed.db");
|
|
2870
|
-
const connectionPath = join(tmpDir, "connector-connection.db");
|
|
3062
|
+
const { rawPath, processedPath, connectionPath } = connectorDiagnosticLogPaths(funnelTmpDir());
|
|
2871
3063
|
if (!existsSync(rawPath) || !existsSync(processedPath) || !existsSync(connectionPath)) return c.text("no diagnostic store yet (the gateway has not initialized it)");
|
|
2872
3064
|
const reader = new ConnectorDiagnosticSqlReader({
|
|
2873
3065
|
rawPath,
|
|
@@ -3057,7 +3249,7 @@ const profilesAddHandler = factory.createHandlers(zValidator$1("param", z.object
|
|
|
3057
3249
|
const param = c.req.valid("param");
|
|
3058
3250
|
const query = c.req.valid("query");
|
|
3059
3251
|
const funnel = c.env.funnel;
|
|
3060
|
-
const
|
|
3252
|
+
const profiles = c.env.profiles;
|
|
3061
3253
|
const channel = funnel.channels.get(query.channel);
|
|
3062
3254
|
if (!channel) throw new HTTPException(400, { message: notFoundMessage({
|
|
3063
3255
|
kind: "channel",
|
|
@@ -3082,9 +3274,7 @@ usage: funnel profiles <name> as-default
|
|
|
3082
3274
|
|
|
3083
3275
|
the first profile in the list is treated as the default for fnl claude.`), (c) => {
|
|
3084
3276
|
const param = c.req.valid("param");
|
|
3085
|
-
c.env.
|
|
3086
|
-
const { profiles, claude } = c.env;
|
|
3087
|
-
profiles.asDefault(param.profile);
|
|
3277
|
+
c.env.profiles.asDefault(param.profile);
|
|
3088
3278
|
return c.text(`profile "${param.profile}" is now the default`);
|
|
3089
3279
|
});
|
|
3090
3280
|
//#endregion
|
|
@@ -3110,9 +3300,7 @@ const profilesRenameHandler = factory.createHandlers(zValidator$1("param", z.obj
|
|
|
3110
3300
|
newName: z.string()
|
|
3111
3301
|
})), zValidator$1("query", z.object({})), (c) => {
|
|
3112
3302
|
const param = c.req.valid("param");
|
|
3113
|
-
c.env.
|
|
3114
|
-
const { profiles, claude } = c.env;
|
|
3115
|
-
profiles.rename(param.profile, param.newName);
|
|
3303
|
+
c.env.profiles.rename(param.profile, param.newName);
|
|
3116
3304
|
return c.text(`renamed profile "${param.profile}" to "${param.newName}"`);
|
|
3117
3305
|
});
|
|
3118
3306
|
//#endregion
|
|
@@ -3124,7 +3312,6 @@ usage: funnel profiles <name> run [additional claude args...]
|
|
|
3124
3312
|
const RESERVED_KEYS = [];
|
|
3125
3313
|
const profilesLaunchHandler = factory.createHandlers(zValidator$1("param", z.object({ profile: z.string() })), helpGuard(launchHelp), zValidator$1("query", z.object({}).loose()), async (c) => {
|
|
3126
3314
|
const param = c.req.valid("param");
|
|
3127
|
-
c.env.funnel;
|
|
3128
3315
|
const { profiles, claude } = c.env;
|
|
3129
3316
|
const profile = profiles.get(param.profile);
|
|
3130
3317
|
if (!profile) throw new HTTPException(404, { message: notFoundMessage({
|
|
@@ -3154,9 +3341,7 @@ const profilesRemoveHelpHandler = factory.createHandlers((c) => c.text(help$1));
|
|
|
3154
3341
|
//#region lib/cli/routes/profiles.remove.$profile.ts
|
|
3155
3342
|
const profilesRemoveHandler = factory.createHandlers(zValidator$1("param", z.object({ profile: z.string() })), zValidator$1("query", z.object({})), (c) => {
|
|
3156
3343
|
const param = c.req.valid("param");
|
|
3157
|
-
c.env.
|
|
3158
|
-
const { profiles, claude } = c.env;
|
|
3159
|
-
profiles.remove(param.profile);
|
|
3344
|
+
c.env.profiles.remove(param.profile);
|
|
3160
3345
|
return c.text(`removed profile "${param.profile}"`);
|
|
3161
3346
|
});
|
|
3162
3347
|
//#endregion
|
|
@@ -3190,7 +3375,7 @@ const profilesSetHandler = factory.createHandlers(zValidator$1("param", z.object
|
|
|
3190
3375
|
const param = c.req.valid("param");
|
|
3191
3376
|
const query = c.req.valid("query");
|
|
3192
3377
|
const funnel = c.env.funnel;
|
|
3193
|
-
const
|
|
3378
|
+
const profiles = c.env.profiles;
|
|
3194
3379
|
const channel = query.channel !== void 0 ? funnel.channels.get(query.channel) : null;
|
|
3195
3380
|
if (query.channel !== void 0 && !channel) throw new HTTPException(400, { message: notFoundMessage({
|
|
3196
3381
|
kind: "channel",
|
|
@@ -3408,4 +3593,4 @@ const routes = factory.createApp().onError((error, c) => {
|
|
|
3408
3593
|
return c.text(`error: ${error instanceof Error ? error.message : String(error)}`, 400);
|
|
3409
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);
|
|
3410
3595
|
//#endregion
|
|
3411
|
-
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,6 +1,6 @@
|
|
|
1
|
-
import { t as discordConnectorSchema } from "./discord-connector-schema-
|
|
2
|
-
import { t as ghConnectorSchema } from "./gh-connector-schema-
|
|
3
|
-
import { t as slackConnectorSchema } from "./slack-connector-schema-
|
|
1
|
+
import { t as discordConnectorSchema } from "./discord-connector-schema-saAGuPmJ.js";
|
|
2
|
+
import { t as ghConnectorSchema } from "./gh-connector-schema-DmZTrzUu.js";
|
|
3
|
+
import { t as slackConnectorSchema } from "./slack-connector-schema-EGVuuqSX.js";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { stderr, stdin } from "node:process";
|
|
@@ -60,7 +60,7 @@ const profileSpecSchema = z.object({
|
|
|
60
60
|
/** Env vars layered under the launched claude process. process.env wins on collision. */
|
|
61
61
|
env: z.record(z.string(), z.string()).optional(),
|
|
62
62
|
/**
|
|
63
|
-
* When true
|
|
63
|
+
* When true, funnel injects `--session-id <uuid>` so that
|
|
64
64
|
* relaunching from the same cwd resumes the previous claude session
|
|
65
65
|
* without bleeding into other channels or workspaces. Set to false for
|
|
66
66
|
* profiles that should always start a fresh session.
|
package/dist/local-config.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { n as FunnelFileSystem } from "./file-system-
|
|
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-
|
|
3
|
-
|
|
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-B20tl_aU.js";
|
|
4
3
|
//#region lib/services/local-config/local-config-json-schema.d.ts
|
|
5
4
|
/**
|
|
6
5
|
* Generates the JSON Schema (draft 2020-12) for `funnel.json`. Useful for
|
package/dist/local-config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as FunnelTokenPrompter, c as channelSpecSchema, d as profileSpecSchema, i as FunnelLocalConfigSync, l as connectorSpecSchema, n as MemoryFunnelTokenPrompter, o as FunnelLocalConfig, r as NodeFunnelTokenPrompter, s as LOCAL_CONFIG_FILENAME, t as funnelJsonSchema, u as localConfigSchema } from "./local-config-json-schema-
|
|
1
|
+
import { a as FunnelTokenPrompter, c as channelSpecSchema, d as profileSpecSchema, i as FunnelLocalConfigSync, l as connectorSpecSchema, n as MemoryFunnelTokenPrompter, o as FunnelLocalConfig, r as NodeFunnelTokenPrompter, s as LOCAL_CONFIG_FILENAME, t as funnelJsonSchema, u as localConfigSchema } from "./local-config-json-schema-_-YVHX4c.js";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
//#region lib/services/local-config/local-config-writer.ts
|
|
4
4
|
const isRecord = (value) => {
|