@interactive-inc/claude-funnel 0.66.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.
- package/README.md +8 -4
- package/dist/bin.js +275 -372
- package/dist/channel.d.ts +76 -52
- package/dist/channel.js +82 -47
- package/dist/{channels-DR90RmUP.d.ts → channels-BBA3GTAa.d.ts} +5 -6
- package/dist/claude.d.ts +11 -8
- package/dist/claude.js +31 -15
- package/dist/{connector-descriptor-CmyHlEiT.d.ts → connector-descriptor-F75ZI8Fh.d.ts} +26 -15
- package/dist/{connector-diagnostics-recorder-COtNEmUp.js → connector-diagnostics-recorder-BmOijU1p.js} +1 -0
- package/dist/connectors/discord.d.ts +10 -8
- package/dist/connectors/discord.js +2 -2
- package/dist/connectors/gh.d.ts +6 -6
- package/dist/connectors/gh.js +2 -2
- package/dist/connectors/schedule.d.ts +10 -8
- package/dist/connectors/schedule.js +2 -2
- package/dist/connectors/slack.d.ts +14 -10
- package/dist/connectors/slack.js +3 -3
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.js +1 -1
- package/dist/{discord-connector-DXARcO6w.js → discord-connector-CdjwPoty.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/{file-process-guard-CiBwXjzm.d.ts → file-process-guard-DAYe9Ndt.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-CLtsdcT2.d.ts} +8 -6
- package/dist/{funnel-diagnostics-Cvk6Sk4x.js → funnel-diagnostics-B-PCuv_E.js} +4 -3
- package/dist/{funnel-diagnostics-kbd27d7I.d.ts → funnel-diagnostics-CnKus3Jg.d.ts} +8 -5
- package/dist/{funnel-docs-C-ge0MuB.js → funnel-docs-BFcqITFA.js} +4 -0
- package/dist/{funnel-doctor-XrI2GBH8.js → funnel-doctor-Csw5qjcH.js} +1 -0
- package/dist/{funnel-doctor-CVTNUtDn.d.ts → funnel-doctor-CviUTINw.d.ts} +20 -9
- package/dist/{funnel-error-0t1MK1R6.js → funnel-error-DoSBCogD.js} +13 -0
- package/dist/{funnel-log-sqlite-sink-DLYkY0pZ.js → funnel-log-sqlite-sink-CXbs3qQp.js} +1 -1
- 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 +66 -125
- package/dist/gateway.d.ts +2 -3
- package/dist/gateway.js +2 -2
- package/dist/{gh-connector-BUGCOEWS.js → gh-connector-D-iyjl-d.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-B4RvEaW-.d.ts} +205 -40
- package/dist/index.d.ts +115 -109
- package/dist/index.js +123 -32
- 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 +29 -13
- package/dist/logger.js +1 -1
- package/dist/{memory-token-prompter-D0kIdhar.d.ts → memory-token-prompter-D3R_kgM_.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-schema-D7ZEKvit.d.ts → schedule-connector-schema-DBko_Bf7.d.ts} +0 -1
- package/dist/{schedule-connector-9k3gOIgl.js → schedule-connector-teeDMHUe.js} +5 -5
- 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-BE0KAjCs.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-5ERhytIA.js} +3 -3
- package/dist/{sqlite-diagnostic-log-CwhXE9Qh.js → sqlite-diagnostic-log-BDxfXGZy.js} +42 -19
- package/dist/{yaml-render-DVEtYuF1.js → yaml-render-DxxRQT-V.js} +3 -3
- package/package.json +10 -10
- package/dist/broadcaster-DVNcw00K.d.ts +0 -138
- package/dist/file-system-Wvzc2ePY.js +0 -9
- package/dist/logger-B6iyNbxM.js +0 -9
- 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/{diagnostic-sql-reader-oXZnWFf_.js → diagnostic-sql-reader-CoBk_EFF.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/{schedule-connector-schema-DKEPZnVv.js → schedule-connector-schema-C2AChpwX.js} +0 -0
- /package/dist/{slack-connector-schema-Dem8to4P.js → slack-connector-schema-EGVuuqSX.js} +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { n as gatewayLoopbackUrl, t as loopbackFetch } from "./loopback-fetch-
|
|
2
|
-
import { t as NodeFunnelFileSystem } from "./node-file-system-
|
|
3
|
-
import { t as NodeFunnelProcessRunner } from "./node-process-runner-
|
|
4
|
-
import { n as FUNNEL_DIR, s as resolveFunnelPort } from "./settings-store-
|
|
5
|
-
import { t as FunnelAuthFailedError } from "./funnel-error-
|
|
6
|
-
import { t as ConnectorDiagnosticSqlReader } from "./diagnostic-sql-reader-
|
|
7
|
-
import { t as FunnelLogSqliteSink } from "./funnel-log-sqlite-sink-
|
|
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
|
-
|
|
162
|
+
const matched = this.raws.filter((event) => matches(event, query));
|
|
163
|
+
return takeRecent(matched, query.limit);
|
|
162
164
|
}
|
|
163
165
|
queryProcessed(query) {
|
|
164
|
-
|
|
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
|
-
})
|
|
170
|
+
});
|
|
171
|
+
return takeRecent(matched, query.limit);
|
|
169
172
|
}
|
|
170
173
|
queryConnection(query) {
|
|
171
|
-
|
|
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
|
-
})
|
|
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
|
-
|
|
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({
|
|
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.
|
|
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-
|
|
2
|
-
import { t as NodeFunnelProcessRunner } from "./node-process-runner-
|
|
3
|
-
import {
|
|
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.
|
|
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": "
|
|
27
|
-
"funnel": "
|
|
26
|
+
"fnl": "dist/bin.js",
|
|
27
|
+
"funnel": "dist/bin.js"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"dist/**/*",
|
|
@@ -122,18 +122,18 @@
|
|
|
122
122
|
"prepack": "make build"
|
|
123
123
|
},
|
|
124
124
|
"dependencies": {
|
|
125
|
-
"@hono/zod-validator": "0.
|
|
126
|
-
"@interactive-inc/flume": "^0.10.
|
|
127
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
128
|
-
"hono": "^4.12.
|
|
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",
|
|
129
129
|
"yaml": "^2.9.0",
|
|
130
130
|
"zod": "^4.4.3"
|
|
131
131
|
},
|
|
132
132
|
"devDependencies": {
|
|
133
133
|
"@types/bun": "^1.3.14",
|
|
134
|
-
"@typescript/native-preview": "^7.0.0-dev.
|
|
135
|
-
"vite-plus": "^0.
|
|
136
|
-
"vitest": "^4.1.
|
|
134
|
+
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
|
|
135
|
+
"vite-plus": "^0.2.6",
|
|
136
|
+
"vitest": "^4.1.10"
|
|
137
137
|
},
|
|
138
138
|
"engines": {
|
|
139
139
|
"bun": ">=1.3.0"
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { t as FunnelLogger } from "./logger-Bc_Ooypb.js";
|
|
2
|
-
import { ServerWebSocket } from "bun";
|
|
3
|
-
|
|
4
|
-
//#region lib/engine/error/on-funnel-error.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Host integration hook called when Funnel catches an exception that would
|
|
7
|
-
* otherwise be silently swallowed (subscriber throw, listener start failure,
|
|
8
|
-
* MCP forward failure, etc.). Pass `Sentry.captureException` from the host to
|
|
9
|
-
* pipe these into your error reporter. Defaults to a no-op when omitted.
|
|
10
|
-
*
|
|
11
|
-
* `context` carries the component name and any extra metadata the caller had
|
|
12
|
-
* at the catch site (channel / connector / subscriber id when available).
|
|
13
|
-
*/
|
|
14
|
-
type OnFunnelError = (error: Error, context?: Record<string, unknown>) => void;
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region lib/gateway/broadcaster.d.ts
|
|
17
|
-
type ClientData = {
|
|
18
|
-
/** Stable channel id (uuid) that the WS client subscribed to. */channel: string; /** Human-facing channel name resolved at upgrade time, kept for log readability. */
|
|
19
|
-
channelName?: string | null; /** Connector names belonging to that channel. */
|
|
20
|
-
connectors: string[]; /** Routing mode resolved from channel config at upgrade time. Defaults to fanout. */
|
|
21
|
-
delivery?: "fanout" | "exclusive";
|
|
22
|
-
/**
|
|
23
|
-
* Opaque per-client id declared at upgrade time (`?id=<subscriberId>`). When an
|
|
24
|
-
* event carries `meta.target`, only the client whose `subscriberId` equals it
|
|
25
|
-
* receives the event among that channel's regular subscribers. Targeted delivery
|
|
26
|
-
* is how a publisher addresses one specific instance (e.g. a single agent
|
|
27
|
-
* session) without every subscriber having to receive and discard it.
|
|
28
|
-
*/
|
|
29
|
-
subscriberId?: string;
|
|
30
|
-
};
|
|
31
|
-
type BroadcastEvent = {
|
|
32
|
-
content: string;
|
|
33
|
-
meta?: Record<string, string>;
|
|
34
|
-
};
|
|
35
|
-
type ReplayableEvent = BroadcastEvent & {
|
|
36
|
-
offset: number;
|
|
37
|
-
};
|
|
38
|
-
type BroadcastSubscriber = (event: ReplayableEvent) => void;
|
|
39
|
-
/**
|
|
40
|
-
* Optional persistent replay source. Wired in by the gateway-server with a
|
|
41
|
-
* `FunnelEventLog` (SQLite-backed by default) so reconnects across daemon
|
|
42
|
-
* restarts can recover events older than the in-memory buffer via an indexed
|
|
43
|
-
* `seq > since` range scan.
|
|
44
|
-
*/
|
|
45
|
-
type ReplaySource = {
|
|
46
|
-
loadSince(since: number): ReplayableEvent[];
|
|
47
|
-
};
|
|
48
|
-
type Deps = {
|
|
49
|
-
logger?: FunnelLogger; /** Host hook for surfacing subscriber-throw exceptions. Defaults to no-op. */
|
|
50
|
-
onError?: OnFunnelError;
|
|
51
|
-
maxBufferedBytes?: number;
|
|
52
|
-
now?: () => number; /** Number of recent events kept in the in-memory replay buffer. */
|
|
53
|
-
replayBufferSize?: number; /** Hard byte cap on replay buffer payloads. Older events are evicted FIFO until under this cap. */
|
|
54
|
-
replayBufferMaxBytes?: number; /** Persistent replay source consulted when the in-memory buffer cannot satisfy `since`. */
|
|
55
|
-
persistentReplay?: ReplaySource;
|
|
56
|
-
};
|
|
57
|
-
type BroadcasterMetrics = {
|
|
58
|
-
clients: number;
|
|
59
|
-
subscribers: number;
|
|
60
|
-
eventsBroadcast: number;
|
|
61
|
-
droppedSlowClients: number;
|
|
62
|
-
lastBroadcastAt: string | null; /** Latest emitted offset. Clients can `?since=<offset>` to ask for events strictly after this point. */
|
|
63
|
-
latestOffset: number; /** Oldest offset still held in the replay buffer. Older values cannot be replayed and trigger a full resync. */
|
|
64
|
-
oldestReplayableOffset: number | null;
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* In-process pub/sub for connector events.
|
|
68
|
-
*
|
|
69
|
-
* Two outbound paths:
|
|
70
|
-
* - WS clients connected via the gateway's `/ws` endpoint, scoped per channel
|
|
71
|
-
* - In-process subscribers registered via `subscribe()` (programmable API)
|
|
72
|
-
*
|
|
73
|
-
* Backpressure: if a WS client's `bufferedAmount` exceeds `maxBufferedBytes`
|
|
74
|
-
* (default 1 MiB), the client is closed with code 1009 and dropped from the
|
|
75
|
-
* registry to keep one slow consumer from blocking the daemon.
|
|
76
|
-
*
|
|
77
|
-
* Replay: every emitted event gets a strictly increasing `offset`. The latest
|
|
78
|
-
* `replayBufferSize` events are kept in memory; reconnecting WS clients can
|
|
79
|
-
* pass `?since=<offset>` and the broadcaster resends matching events before
|
|
80
|
-
* resuming the live stream. The in-memory ring covers short reconnects;
|
|
81
|
-
* older history is served from the event log wired in as `persistentReplay`.
|
|
82
|
-
*/
|
|
83
|
-
declare class FunnelBroadcaster {
|
|
84
|
-
private readonly clients;
|
|
85
|
-
private readonly subscribers;
|
|
86
|
-
private readonly logger;
|
|
87
|
-
private readonly onError;
|
|
88
|
-
private readonly maxBufferedBytes;
|
|
89
|
-
private readonly now;
|
|
90
|
-
private readonly replayBufferSize;
|
|
91
|
-
private readonly replayBufferMaxBytes;
|
|
92
|
-
private readonly replayBuffer;
|
|
93
|
-
private readonly persistentReplay;
|
|
94
|
-
private readonly exclusiveCursor;
|
|
95
|
-
private replayBufferBytes;
|
|
96
|
-
private eventsBroadcast;
|
|
97
|
-
private droppedSlowClients;
|
|
98
|
-
private lastBroadcastAt;
|
|
99
|
-
private latestOffset;
|
|
100
|
-
constructor(deps?: Deps);
|
|
101
|
-
getMetrics(): BroadcasterMetrics;
|
|
102
|
-
/**
|
|
103
|
-
* Returns events with offset > since, filtered by the connector subscription
|
|
104
|
-
* rules of `data`. Used at WS upgrade time when the client passes `?since=<offset>`.
|
|
105
|
-
*
|
|
106
|
-
* Two-tier lookup:
|
|
107
|
-
* 1. The in-memory ring buffer (covers short reconnects, last `replayBufferSize` events).
|
|
108
|
-
* 2. If `since` predates the oldest in-memory entry and a persistent replay source
|
|
109
|
-
* is wired in (SQLite by default), the gap is filled from it. This covers reconnects
|
|
110
|
-
* across daemon restarts where the in-memory buffer was lost.
|
|
111
|
-
*
|
|
112
|
-
* Result is sorted ascending by offset and de-duplicated against the in-memory buffer.
|
|
113
|
-
*/
|
|
114
|
-
replaySince(since: number, data: ClientData): ReplayableEvent[];
|
|
115
|
-
private matchesClient;
|
|
116
|
-
/**
|
|
117
|
-
* Returns the list of WS clients that should receive `event`. For each per-channel group:
|
|
118
|
-
* - fanout → every matching client receives
|
|
119
|
-
* - exclusive → exactly one client receives, picked round-robin per channel
|
|
120
|
-
*
|
|
121
|
-
* `meta.target` narrows the recipient set via `matchesClient`: only the subscriber
|
|
122
|
-
* whose `subscriberId` equals `target` receives a targeted event.
|
|
123
|
-
*/
|
|
124
|
-
private pickRecipients;
|
|
125
|
-
addClient(ws: ServerWebSocket<unknown>, data: ClientData): void;
|
|
126
|
-
removeClient(ws: ServerWebSocket<unknown>): void;
|
|
127
|
-
getClientCount(): number;
|
|
128
|
-
listChannels(): {
|
|
129
|
-
channel: string;
|
|
130
|
-
connectors: string[];
|
|
131
|
-
}[];
|
|
132
|
-
subscribe(handler: BroadcastSubscriber): () => void;
|
|
133
|
-
broadcast(content: string, meta?: Record<string, string>): ReplayableEvent;
|
|
134
|
-
/** Forward-seed the offset counter (used at startup from the persisted event store). */
|
|
135
|
-
seedLatestOffset(offset: number): void;
|
|
136
|
-
}
|
|
137
|
-
//#endregion
|
|
138
|
-
export { OnFunnelError as a, ReplayableEvent as i, BroadcastSubscriber as n, FunnelBroadcaster as r, BroadcastEvent 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,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
|
/package/dist/{schedule-connector-schema-DKEPZnVv.js → schedule-connector-schema-C2AChpwX.js}
RENAMED
|
File without changes
|
|
File without changes
|