@interactive-inc/claude-funnel 0.38.0 → 0.39.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/dist/bin.js +118 -118
- package/dist/gateway/daemon.js +44 -44
- package/dist/index.d.ts +20 -2
- package/dist/index.js +22 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -407,6 +407,14 @@ type ClientData = {
|
|
|
407
407
|
connectors: string[];
|
|
408
408
|
tapAll?: boolean; /** Routing mode resolved from channel config at upgrade time. Defaults to fanout. */
|
|
409
409
|
delivery?: "fanout" | "exclusive";
|
|
410
|
+
/**
|
|
411
|
+
* Opaque per-client id declared at upgrade time (`?id=<subscriberId>`). When an
|
|
412
|
+
* event carries `meta.target`, only the client whose `subscriberId` equals it
|
|
413
|
+
* receives the event among that channel's regular subscribers. Targeted delivery
|
|
414
|
+
* is how a publisher addresses one specific instance (e.g. a single agent
|
|
415
|
+
* session) without every subscriber having to receive and discard it.
|
|
416
|
+
*/
|
|
417
|
+
subscriberId?: string;
|
|
410
418
|
};
|
|
411
419
|
type BroadcastEvent = {
|
|
412
420
|
content: string;
|
|
@@ -498,6 +506,11 @@ declare class FunnelBroadcaster {
|
|
|
498
506
|
* receive (passive observation). For each per-channel group:
|
|
499
507
|
* - fanout → every matching client receives
|
|
500
508
|
* - exclusive → exactly one client receives, picked round-robin per channel
|
|
509
|
+
*
|
|
510
|
+
* `meta.target` narrows the regular (non-tap) recipient set first via
|
|
511
|
+
* `matchesClient`: only the subscriber whose `subscriberId` equals `target`
|
|
512
|
+
* stays in the running, so a targeted event reaches one named instance while
|
|
513
|
+
* still being observable by tap=all clients.
|
|
501
514
|
*/
|
|
502
515
|
private pickRecipients;
|
|
503
516
|
addClient(ws: ServerWebSocket<unknown>, data: ClientData): void;
|
|
@@ -892,6 +905,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env$1, {
|
|
|
892
905
|
content: string;
|
|
893
906
|
meta?: Record<string, string> | undefined;
|
|
894
907
|
connector?: string | undefined;
|
|
908
|
+
target?: string | undefined;
|
|
895
909
|
};
|
|
896
910
|
};
|
|
897
911
|
output: {
|
|
@@ -910,6 +924,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env$1, {
|
|
|
910
924
|
content: string;
|
|
911
925
|
meta?: Record<string, string> | undefined;
|
|
912
926
|
connector?: string | undefined;
|
|
927
|
+
target?: string | undefined;
|
|
913
928
|
};
|
|
914
929
|
};
|
|
915
930
|
output: {
|
|
@@ -928,6 +943,7 @@ declare function buildGatewayRoutes(): _$hono_hono_base0.HonoBase<Env$1, {
|
|
|
928
943
|
content: string;
|
|
929
944
|
meta?: Record<string, string> | undefined;
|
|
930
945
|
connector?: string | undefined;
|
|
946
|
+
target?: string | undefined;
|
|
931
947
|
};
|
|
932
948
|
};
|
|
933
949
|
output: {
|
|
@@ -1303,6 +1319,7 @@ declare const publishRequestSchema: z.ZodObject<{
|
|
|
1303
1319
|
content: z.ZodString;
|
|
1304
1320
|
meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
1305
1321
|
connector: z.ZodOptional<z.ZodString>;
|
|
1322
|
+
target: z.ZodOptional<z.ZodString>;
|
|
1306
1323
|
}, z.core.$strip>;
|
|
1307
1324
|
type PublishRequest = z.infer<typeof publishRequestSchema>;
|
|
1308
1325
|
declare const publishResponseSchema: z.ZodObject<{
|
|
@@ -1472,7 +1489,8 @@ type WsData = {
|
|
|
1472
1489
|
channelName: string | null; /** Connector names belonging to that channel; used by tap-all replay filtering. */
|
|
1473
1490
|
connectors: string[];
|
|
1474
1491
|
tapAll?: boolean; /** Routing mode for this channel; resolved at upgrade time from settings. */
|
|
1475
|
-
delivery: "fanout" | "exclusive"; /**
|
|
1492
|
+
delivery: "fanout" | "exclusive"; /** Opaque client id from `?id=<subscriberId>`; lets publishers target this client via `meta.target`. */
|
|
1493
|
+
subscriberId?: string; /** Replay any events with offset strictly greater than this on open, then resume the live stream. */
|
|
1476
1494
|
since?: number;
|
|
1477
1495
|
};
|
|
1478
1496
|
/**
|
|
@@ -2354,7 +2372,7 @@ declare const routes: _$hono_hono_base0.HonoBase<Env, {
|
|
|
2354
2372
|
connectors: {
|
|
2355
2373
|
id: string;
|
|
2356
2374
|
name: string;
|
|
2357
|
-
type: "
|
|
2375
|
+
type: "discord" | "gh" | "slack" | "schedule";
|
|
2358
2376
|
}[];
|
|
2359
2377
|
}[];
|
|
2360
2378
|
outputFormat: "json";
|
package/dist/index.js
CHANGED
|
@@ -1740,7 +1740,14 @@ var MemoryFunnelClock = class extends FunnelClock {
|
|
|
1740
1740
|
const publishRequestSchema = z.object({
|
|
1741
1741
|
content: z.string().min(1),
|
|
1742
1742
|
meta: z.record(z.string(), z.string()).optional(),
|
|
1743
|
-
connector: z.string().min(1).optional()
|
|
1743
|
+
connector: z.string().min(1).optional(),
|
|
1744
|
+
/**
|
|
1745
|
+
* Address the event to a single subscriber. When set, only the WS client that
|
|
1746
|
+
* declared this id at upgrade time (`?id=<subscriberId>`) receives it among the
|
|
1747
|
+
* channel's regular subscribers; tap=all observers still see it. Omit for the
|
|
1748
|
+
* default fanout. The route surfaces it to subscribers as `meta.target`.
|
|
1749
|
+
*/
|
|
1750
|
+
target: z.string().min(1).optional()
|
|
1744
1751
|
});
|
|
1745
1752
|
const publishResponseSchema = z.object({
|
|
1746
1753
|
ok: z.literal(true),
|
|
@@ -2101,6 +2108,8 @@ var FunnelBroadcaster = class {
|
|
|
2101
2108
|
}
|
|
2102
2109
|
matchesClient(event, data) {
|
|
2103
2110
|
if (data.tapAll) return true;
|
|
2111
|
+
const target = event.meta?.target;
|
|
2112
|
+
if (target && target !== data.subscriberId) return false;
|
|
2104
2113
|
const channelId = event.meta?.channelId;
|
|
2105
2114
|
if (channelId && channelId !== data.channel) return false;
|
|
2106
2115
|
const connector = event.meta?.connector;
|
|
@@ -2112,6 +2121,11 @@ var FunnelBroadcaster = class {
|
|
|
2112
2121
|
* receive (passive observation). For each per-channel group:
|
|
2113
2122
|
* - fanout → every matching client receives
|
|
2114
2123
|
* - exclusive → exactly one client receives, picked round-robin per channel
|
|
2124
|
+
*
|
|
2125
|
+
* `meta.target` narrows the regular (non-tap) recipient set first via
|
|
2126
|
+
* `matchesClient`: only the subscriber whose `subscriberId` equals `target`
|
|
2127
|
+
* stays in the running, so a targeted event reaches one named instance while
|
|
2128
|
+
* still being observable by tap=all clients.
|
|
2115
2129
|
*/
|
|
2116
2130
|
pickRecipients(event) {
|
|
2117
2131
|
const exclusiveByChannel = /* @__PURE__ */ new Map();
|
|
@@ -2983,13 +2997,17 @@ const channelsPublishHandler$1 = factory$1.createHandlers(zParam(z.object({ chan
|
|
|
2983
2997
|
}), (c) => {
|
|
2984
2998
|
const param = c.req.valid("param");
|
|
2985
2999
|
const body = c.req.valid("json");
|
|
3000
|
+
const meta = body.target ? {
|
|
3001
|
+
...body.meta,
|
|
3002
|
+
target: body.target
|
|
3003
|
+
} : body.meta;
|
|
2986
3004
|
const response = {
|
|
2987
3005
|
ok: true,
|
|
2988
3006
|
offset: c.var.deps.emit({
|
|
2989
3007
|
channel: param.channel,
|
|
2990
3008
|
connector: body.connector,
|
|
2991
3009
|
content: body.content,
|
|
2992
|
-
meta
|
|
3010
|
+
meta
|
|
2993
3011
|
}).offset
|
|
2994
3012
|
};
|
|
2995
3013
|
return c.json(response);
|
|
@@ -3453,12 +3471,14 @@ var FunnelGatewayServer = class {
|
|
|
3453
3471
|
const sinceRaw = url.searchParams.get("since");
|
|
3454
3472
|
const sinceParsed = sinceRaw === null ? NaN : Number.parseInt(sinceRaw, 10);
|
|
3455
3473
|
const since = Number.isFinite(sinceParsed) && sinceParsed >= 0 ? sinceParsed : void 0;
|
|
3474
|
+
const subscriberId = url.searchParams.get("id") ?? void 0;
|
|
3456
3475
|
if (server.upgrade(request, { data: {
|
|
3457
3476
|
channel: channelId,
|
|
3458
3477
|
channelName,
|
|
3459
3478
|
connectors,
|
|
3460
3479
|
tapAll,
|
|
3461
3480
|
delivery,
|
|
3481
|
+
subscriberId,
|
|
3462
3482
|
since
|
|
3463
3483
|
} })) return void 0;
|
|
3464
3484
|
return new Response("WebSocket upgrade failed", { status: 400 });
|
package/package.json
CHANGED