@interactive-inc/claude-funnel 0.65.0 → 0.67.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 (87) hide show
  1. package/README.md +8 -4
  2. package/dist/bin.js +275 -372
  3. package/dist/channel.d.ts +185 -0
  4. package/dist/channel.js +238 -0
  5. package/dist/{channels-CRGb6B5_.d.ts → channels-BBA3GTAa.d.ts} +5 -5
  6. package/dist/claude.d.ts +11 -8
  7. package/dist/claude.js +31 -15
  8. package/dist/{connector-descriptor-BFIhyTfa.d.ts → connector-descriptor-F75ZI8Fh.d.ts} +27 -39
  9. package/dist/{connector-diagnostics-recorder-COtNEmUp.js → connector-diagnostics-recorder-BmOijU1p.js} +1 -0
  10. package/dist/connectors/discord.d.ts +10 -7
  11. package/dist/connectors/discord.js +2 -2
  12. package/dist/connectors/gh.d.ts +6 -5
  13. package/dist/connectors/gh.js +2 -2
  14. package/dist/connectors/schedule.d.ts +10 -7
  15. package/dist/connectors/schedule.js +2 -2
  16. package/dist/connectors/slack.d.ts +14 -9
  17. package/dist/connectors/slack.js +3 -3
  18. package/dist/diagnostics.d.ts +1 -1
  19. package/dist/diagnostics.js +1 -1
  20. package/dist/{discord-connector-DXARcO6w.js → discord-connector-CdjwPoty.js} +6 -6
  21. package/dist/{discord-connector-schema-D-bOVAKt.d.ts → discord-connector-schema-BaBZYHxK.d.ts} +0 -1
  22. package/dist/docs.d.ts +1 -1
  23. package/dist/docs.js +1 -1
  24. package/dist/doctor.d.ts +1 -1
  25. package/dist/doctor.js +1 -1
  26. package/dist/{file-process-guard-tVcgckH6.d.ts → file-process-guard-DAYe9Ndt.d.ts} +22 -17
  27. package/dist/{file-system-VhwwXZbm.d.ts → file-system-BNtl997T.d.ts} +2 -1
  28. package/dist/{flume-source-listener-BNyAII7N.d.ts → flume-source-listener-CLtsdcT2.d.ts} +8 -5
  29. package/dist/{funnel-diagnostics-Cvk6Sk4x.js → funnel-diagnostics-B-PCuv_E.js} +4 -3
  30. package/dist/{funnel-diagnostics-b9ar0Ing.d.ts → funnel-diagnostics-CnKus3Jg.d.ts} +8 -5
  31. package/dist/{funnel-docs-C-ge0MuB.js → funnel-docs-BFcqITFA.js} +4 -0
  32. package/dist/{funnel-doctor-XrI2GBH8.js → funnel-doctor-Csw5qjcH.js} +1 -0
  33. package/dist/{funnel-doctor-CnRQi4kM.d.ts → funnel-doctor-CviUTINw.d.ts} +20 -9
  34. package/dist/{funnel-error-0t1MK1R6.js → funnel-error-DoSBCogD.js} +13 -0
  35. package/dist/{funnel-log-sqlite-sink-DLYkY0pZ.js → funnel-log-sqlite-sink-CXbs3qQp.js} +1 -1
  36. package/dist/{funnel-recovery-CMhY8Jfk.d.ts → funnel-recovery-BwcSNNSN.d.ts} +1 -2
  37. package/dist/{funnel-recovery-DKnEutUS.js → funnel-recovery-DYbSYGWC.js} +1 -0
  38. package/dist/gateway/daemon.js +66 -125
  39. package/dist/gateway.d.ts +2 -2
  40. package/dist/gateway.js +2 -2
  41. package/dist/{gh-connector-BUGCOEWS.js → gh-connector-D-iyjl-d.js} +5 -5
  42. package/dist/{gh-connector-schema-DWQaB6gX.d.ts → gh-connector-schema-BrNsCl1T.d.ts} +0 -1
  43. package/dist/{index-Ds6sHhA-.d.ts → index-B4RvEaW-.d.ts} +78 -46
  44. package/dist/index.d.ts +115 -107
  45. package/dist/index.js +123 -32
  46. package/dist/{local-config-json-schema-DexV8vX3.js → local-config-json-schema-_-YVHX4c.js} +4 -4
  47. package/dist/local-config.d.ts +2 -3
  48. package/dist/local-config.js +1 -1
  49. package/dist/logger-mMZvblTx.d.ts +25 -0
  50. package/dist/logger.d.ts +29 -13
  51. package/dist/logger.js +1 -1
  52. package/dist/{memory-token-prompter-BoV8Hf-n.d.ts → memory-token-prompter-D3R_kgM_.d.ts} +2 -3
  53. package/dist/{node-file-system-BOXIHW_Q.js → node-file-system-xJx7dymE.js} +11 -3
  54. package/dist/{profiles-cVZQkM69.d.ts → profiles-CePRnv3F.d.ts} +3 -4
  55. package/dist/{profiles-ZHLONml4.js → profiles-KpN7_gBw.js} +19 -5
  56. package/dist/profiles.d.ts +1 -1
  57. package/dist/profiles.js +1 -1
  58. package/dist/recovery.d.ts +1 -1
  59. package/dist/recovery.js +1 -1
  60. package/dist/{schedule-connector-schema-Z0RXLgPI.d.ts → schedule-connector-schema-DBko_Bf7.d.ts} +0 -1
  61. package/dist/{schedule-connector-9k3gOIgl.js → schedule-connector-teeDMHUe.js} +5 -5
  62. package/dist/{settings-reader-BNxjsxCB.d.ts → settings-reader-CyTpbAre.d.ts} +1 -2
  63. package/dist/{settings-schema-BL_c2Udm.d.ts → settings-schema-B-CKLuST.d.ts} +0 -1
  64. package/dist/{settings-store-ccv291GV.js → settings-store-ZFWBhOnp.js} +12 -3
  65. package/dist/{slack-connector-CxpWagbT.js → slack-connector-BE0KAjCs.js} +10 -9
  66. package/dist/{slack-event-processor-xFDG3US0.js → slack-event-processor-Cs_YuI3w.js} +2 -2
  67. package/dist/{slack-event-processor-BhCf5Wiy.d.ts → slack-event-processor-DmAlq4cV.d.ts} +0 -1
  68. package/dist/{slot-fields-D-pvMgTK.js → slot-fields-5ERhytIA.js} +3 -3
  69. package/dist/{sqlite-diagnostic-log-CwhXE9Qh.js → sqlite-diagnostic-log-BDxfXGZy.js} +42 -19
  70. package/dist/{yaml-render-DVEtYuF1.js → yaml-render-DxxRQT-V.js} +3 -3
  71. package/package.json +15 -10
  72. package/dist/file-system-Wvzc2ePY.js +0 -9
  73. package/dist/logger-B6iyNbxM.js +0 -9
  74. package/dist/settings-reader-9FcX3qS1.js +0 -11
  75. /package/dist/{connector-adapter-Dvs8N7ew.js → connector-adapter-BL2ehMej.js} +0 -0
  76. /package/dist/{connector-listener-mPGZYa8e.js → connector-listener-BcQMzY6Q.js} +0 -0
  77. /package/dist/{diagnostic-sql-reader-oXZnWFf_.js → diagnostic-sql-reader-CoBk_EFF.js} +0 -0
  78. /package/dist/{discord-connector-schema-B4YpWpR3.js → discord-connector-schema-saAGuPmJ.js} +0 -0
  79. /package/dist/{error-message-of-ColuYmAk.js → error-message-of-BG4ezZ_s.js} +0 -0
  80. /package/dist/{funnel-docs-CNklHvbt.d.ts → funnel-docs-BJWawfWI.d.ts} +0 -0
  81. /package/dist/{gh-connector-schema-CAqIhzGr.js → gh-connector-schema-DmZTrzUu.js} +0 -0
  82. /package/dist/{loopback-fetch-CVNuN3YZ.js → loopback-fetch-HP-bo9Kv.js} +0 -0
  83. /package/dist/{node-http-client-u00atiKx.js → node-http-client-SX3xFh4h.js} +0 -0
  84. /package/dist/{node-process-runner-DxTvycoK.js → node-process-runner-D4rzPl8Q.js} +0 -0
  85. /package/dist/{resolve-connector-token-DxDG9mhf.js → resolve-connector-token-BwiJCu82.js} +0 -0
  86. /package/dist/{schedule-connector-schema-DKEPZnVv.js → schedule-connector-schema-C2AChpwX.js} +0 -0
  87. /package/dist/{slack-connector-schema-Dem8to4P.js → slack-connector-schema-EGVuuqSX.js} +0 -0
@@ -1,6 +1,6 @@
1
- import { t as errorMessageOf } from "./error-message-of-ColuYmAk.js";
2
- import { t as FunnelConnectorListener } from "./connector-listener-mPGZYa8e.js";
3
- import { t as FunnelConnectorDiagnosticsRecorder } from "./connector-diagnostics-recorder-COtNEmUp.js";
1
+ import { t as errorMessageOf } from "./error-message-of-BG4ezZ_s.js";
2
+ import { t as FunnelConnectorListener } from "./connector-listener-BcQMzY6Q.js";
3
+ import { t as FunnelConnectorDiagnosticsRecorder } from "./connector-diagnostics-recorder-BmOijU1p.js";
4
4
  import { Flume, createFlumeDefaultDeps } from "@interactive-inc/flume";
5
5
  //#region lib/engine/connectors/flume-deps.ts
6
6
  /**
@@ -1,15 +1,15 @@
1
- import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-CVNuN3YZ.js";
2
- import { t as NodeFunnelFileSystem } from "./node-file-system-BOXIHW_Q.js";
3
- import { t as NodeFunnelProcessRunner } from "./node-process-runner-DxTvycoK.js";
4
- import { n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ccv291GV.js";
5
- import { t as FunnelAuthFailedError } from "./funnel-error-0t1MK1R6.js";
6
- import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-oXZnWFf_.js";
7
- import { t as FunnelLogSqliteSink } from "./funnel-log-sqlite-sink-DLYkY0pZ.js";
1
+ import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-HP-bo9Kv.js";
2
+ import { t as NodeFunnelFileSystem } from "./node-file-system-xJx7dymE.js";
3
+ import { t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js";
4
+ import { n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ZFWBhOnp.js";
5
+ import { t as FunnelAuthFailedError } from "./funnel-error-DoSBCogD.js";
6
+ import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-CoBk_EFF.js";
7
+ import { t as FunnelLogSqliteSink } from "./funnel-log-sqlite-sink-CXbs3qQp.js";
8
8
  import { dirname, join } from "node:path";
9
9
  import { chmodSync, existsSync, mkdirSync } from "node:fs";
10
10
  import { homedir, tmpdir } from "node:os";
11
11
  import { z } from "zod";
12
- import { timingSafeEqual } from "node:crypto";
12
+ import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
13
13
  import { createFactory } from "hono/factory";
14
14
  import { HTTPException } from "hono/http-exception";
15
15
  import { zValidator } from "@hono/zod-validator";
@@ -128,6 +128,7 @@ var ConnectorDiagnosticLog = class {};
128
128
  * rejecting a malformed payload.
129
129
  */
130
130
  var MemoryConnectorDiagnosticLog = class extends ConnectorDiagnosticLog {
131
+ now;
131
132
  raws = [];
132
133
  processeds = [];
133
134
  connections = [];
@@ -158,21 +159,24 @@ var MemoryConnectorDiagnosticLog = class extends ConnectorDiagnosticLog {
158
159
  });
159
160
  }
160
161
  queryRaw(query) {
161
- return takeRecent(this.raws.filter((event) => matches(event, query)), query.limit);
162
+ const matched = this.raws.filter((event) => matches(event, query));
163
+ return takeRecent(matched, query.limit);
162
164
  }
163
165
  queryProcessed(query) {
164
- return takeRecent(this.processeds.filter((event) => {
166
+ const matched = this.processeds.filter((event) => {
165
167
  if (!matches(event, query)) return false;
166
168
  if (query.outcome !== void 0 && event.outcome !== query.outcome) return false;
167
169
  return true;
168
- }), query.limit);
170
+ });
171
+ return takeRecent(matched, query.limit);
169
172
  }
170
173
  queryConnection(query) {
171
- return takeRecent(this.connections.filter((event) => {
174
+ const matched = this.connections.filter((event) => {
172
175
  if (!matches(event, query)) return false;
173
176
  if (query.status !== void 0 && event.status !== query.status) return false;
174
177
  return true;
175
- }), query.limit);
178
+ });
179
+ return takeRecent(matched, query.limit);
176
180
  }
177
181
  clear() {
178
182
  this.raws.length = 0;
@@ -279,7 +283,8 @@ var FunnelChannelPublisher = class {
279
283
  */
280
284
  const requireBearerToken = (deps) => {
281
285
  return async (c, next) => {
282
- if (!constantTimeEqual((c.req.header("authorization") ?? "").match(/^Bearer\s+(.+)$/i)?.[1] ?? "", deps.expected)) return c.text("unauthorized", 401);
286
+ const presented = (c.req.header("authorization") ?? "").match(/^Bearer\s+(.+)$/i)?.[1] ?? "";
287
+ if (!constantTimeEqual(presented, deps.expected)) return c.text("unauthorized", 401);
283
288
  return await next();
284
289
  };
285
290
  };
@@ -626,7 +631,10 @@ var SqliteFunnelEventLog = class extends FunnelEventLog {
626
631
  * so this returns the full slice and lets the caller filter.
627
632
  */
628
633
  loadSince(since) {
629
- const records = this.sink.query({ sinceSeq: since });
634
+ const records = this.sink.query({
635
+ sinceSeq: since,
636
+ limit: Number.MAX_SAFE_INTEGER
637
+ });
630
638
  const out = [];
631
639
  for (const record of records) out.push({
632
640
  content: record.event.content,
@@ -1410,15 +1418,26 @@ function buildGatewayRoutes() {
1410
1418
  }
1411
1419
  const gatewayRoutes = buildGatewayRoutes();
1412
1420
  //#endregion
1421
+ //#region lib/gateway/default-event-db-path.ts
1422
+ /**
1423
+ * Gives each durable gateway endpoint its own replay database. Port zero is
1424
+ * ephemeral, so each construction receives a fresh scope instead of pretending
1425
+ * that replay can survive a restart onto a different assigned port.
1426
+ */
1427
+ function defaultEventDbPath(props) {
1428
+ const endpoint = props.port === 0 ? randomUUID() : String(props.port);
1429
+ const scope = createHash("sha256").update(`${props.funnelDir}\0${endpoint}`).digest("hex").slice(0, 20);
1430
+ return join(props.tmpDir, "events", `${scope}.db`);
1431
+ }
1432
+ //#endregion
1413
1433
  //#region lib/gateway/gateway-server.ts
1414
1434
  const DEFAULT_HOST = "127.0.0.1";
1415
- const LOOPBACK_HOSTS = new Set([
1435
+ const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
1416
1436
  "127.0.0.1",
1417
1437
  "localhost",
1418
1438
  "::1",
1419
1439
  "::ffff:127.0.0.1"
1420
1440
  ]);
1421
- const defaultDbPath = () => join(funnelTmpDir(), "events.db");
1422
1441
  const defaultOnError = () => {};
1423
1442
  /**
1424
1443
  * In-process gateway: runs `Bun.serve` (HTTP + WebSocket /ws), boots connector
@@ -1456,12 +1475,16 @@ var FunnelGatewayServer = class {
1456
1475
  this.channels = deps.channels;
1457
1476
  this.configuredPort = deps.port ?? resolveFunnelPort();
1458
1477
  this.configuredHostname = deps.hostname ?? DEFAULT_HOST;
1459
- this.dbPath = deps.dbPath ?? defaultDbPath();
1478
+ this.dir = deps.dir ?? FUNNEL_DIR;
1479
+ this.dbPath = deps.dbPath ?? defaultEventDbPath({
1480
+ tmpDir: deps.tmpDir ?? funnelTmpDir(),
1481
+ funnelDir: this.dir,
1482
+ port: this.configuredPort
1483
+ });
1460
1484
  this.process = deps.process;
1461
1485
  this.logger = deps.logger;
1462
1486
  this.onError = deps.onError ?? defaultOnError;
1463
1487
  this.selfPid = deps.selfPid ?? globalThis.process.pid;
1464
- this.dir = deps.dir ?? FUNNEL_DIR;
1465
1488
  this.killCompetingSlack = deps.killCompetingSlack ?? true;
1466
1489
  this.token = deps.token ?? "";
1467
1490
  this.allowInsecureHost = deps.allowInsecureHost ?? false;
@@ -1,6 +1,6 @@
1
- import { t as NodeFunnelFileSystem } from "./node-file-system-BOXIHW_Q.js";
2
- import { t as NodeFunnelProcessRunner } from "./node-process-runner-DxTvycoK.js";
3
- import { m as NodeFunnelIdGenerator, n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ccv291GV.js";
1
+ import { t as NodeFunnelFileSystem } from "./node-file-system-xJx7dymE.js";
2
+ import { t as NodeFunnelProcessRunner } from "./node-process-runner-D4rzPl8Q.js";
3
+ import { h as NodeFunnelIdGenerator, n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-ZFWBhOnp.js";
4
4
  import { join } from "node:path";
5
5
  import { stringify } from "yaml";
6
6
  //#region lib/engine/claude/claude.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interactive-inc/claude-funnel",
3
- "version": "0.65.0",
3
+ "version": "0.67.0",
4
4
  "description": "Hub CLI that routes external events (Slack / GitHub / Discord) to Claude Code agents through subscription channels over MCP.",
5
5
  "keywords": [
6
6
  "bun",
@@ -23,8 +23,8 @@
23
23
  "url": "git+https://github.com/interactive-inc/open-claude-funnel.git"
24
24
  },
25
25
  "bin": {
26
- "fnl": "./dist/bin.js",
27
- "funnel": "./dist/bin.js"
26
+ "fnl": "dist/bin.js",
27
+ "funnel": "dist/bin.js"
28
28
  },
29
29
  "files": [
30
30
  "dist/**/*",
@@ -107,6 +107,11 @@
107
107
  "import": "./dist/logger.js",
108
108
  "default": "./dist/logger.js"
109
109
  },
110
+ "./channel": {
111
+ "types": "./dist/channel.d.ts",
112
+ "import": "./dist/channel.js",
113
+ "default": "./dist/channel.js"
114
+ },
110
115
  "./bin": "./dist/bin.js",
111
116
  "./package.json": "./package.json"
112
117
  },
@@ -117,18 +122,18 @@
117
122
  "prepack": "make build"
118
123
  },
119
124
  "dependencies": {
120
- "@hono/zod-validator": "0.8.0",
121
- "@interactive-inc/flume": "^0.9.2",
122
- "@modelcontextprotocol/sdk": "^1.29.0",
123
- "hono": "^4.12.19",
125
+ "@hono/zod-validator": "0.9.0",
126
+ "@interactive-inc/flume": "^0.10.1",
127
+ "@modelcontextprotocol/sdk": "^1.30.0",
128
+ "hono": "^4.12.32",
124
129
  "yaml": "^2.9.0",
125
130
  "zod": "^4.4.3"
126
131
  },
127
132
  "devDependencies": {
128
133
  "@types/bun": "^1.3.14",
129
- "@typescript/native-preview": "^7.0.0-dev.20260516.1",
130
- "vite-plus": "^0.1.21",
131
- "vitest": "^4.1.8"
134
+ "@typescript/native-preview": "^7.0.0-dev.20260707.2",
135
+ "vite-plus": "^0.2.6",
136
+ "vitest": "^4.1.10"
132
137
  },
133
138
  "engines": {
134
139
  "bun": ">=1.3.0"
@@ -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 };
@@ -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,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 };