@langchain/langgraph 1.2.9 → 1.3.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/graph/graph.cjs +6 -2
- package/dist/graph/graph.cjs.map +1 -1
- package/dist/graph/graph.d.cts +58 -7
- package/dist/graph/graph.d.cts.map +1 -1
- package/dist/graph/graph.d.ts +58 -7
- package/dist/graph/graph.d.ts.map +1 -1
- package/dist/graph/graph.js +6 -2
- package/dist/graph/graph.js.map +1 -1
- package/dist/graph/index.d.ts +1 -1
- package/dist/graph/state.cjs +3 -2
- package/dist/graph/state.cjs.map +1 -1
- package/dist/graph/state.d.cts +13 -5
- package/dist/graph/state.d.cts.map +1 -1
- package/dist/graph/state.d.ts +13 -5
- package/dist/graph/state.d.ts.map +1 -1
- package/dist/graph/state.js +3 -2
- package/dist/graph/state.js.map +1 -1
- package/dist/index.cjs +34 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/prebuilt/agent_executor.d.cts +1 -1
- package/dist/prebuilt/agent_executor.d.ts +1 -1
- package/dist/pregel/index.cjs +69 -25
- package/dist/pregel/index.cjs.map +1 -1
- package/dist/pregel/index.d.cts +25 -3
- package/dist/pregel/index.d.cts.map +1 -1
- package/dist/pregel/index.d.ts +25 -3
- package/dist/pregel/index.d.ts.map +1 -1
- package/dist/pregel/index.js +69 -25
- package/dist/pregel/index.js.map +1 -1
- package/dist/pregel/loop.cjs +51 -10
- package/dist/pregel/loop.cjs.map +1 -1
- package/dist/pregel/loop.js +51 -10
- package/dist/pregel/loop.js.map +1 -1
- package/dist/pregel/messages-v2.cjs +231 -0
- package/dist/pregel/messages-v2.cjs.map +1 -0
- package/dist/pregel/messages-v2.js +231 -0
- package/dist/pregel/messages-v2.js.map +1 -0
- package/dist/pregel/stream.cjs.map +1 -1
- package/dist/pregel/stream.d.cts +30 -0
- package/dist/pregel/stream.d.cts.map +1 -0
- package/dist/pregel/stream.d.ts +30 -1
- package/dist/pregel/stream.d.ts.map +1 -0
- package/dist/pregel/stream.js.map +1 -1
- package/dist/pregel/types.cjs.map +1 -1
- package/dist/pregel/types.d.cts +8 -1
- package/dist/pregel/types.d.cts.map +1 -1
- package/dist/pregel/types.d.ts +8 -1
- package/dist/pregel/types.d.ts.map +1 -1
- package/dist/pregel/types.js.map +1 -1
- package/dist/stream/convert.cjs +207 -0
- package/dist/stream/convert.cjs.map +1 -0
- package/dist/stream/convert.d.cts +69 -0
- package/dist/stream/convert.d.cts.map +1 -0
- package/dist/stream/convert.d.ts +69 -0
- package/dist/stream/convert.d.ts.map +1 -0
- package/dist/stream/convert.js +206 -0
- package/dist/stream/convert.js.map +1 -0
- package/dist/stream/index.cjs +11 -0
- package/dist/stream/index.d.cts +12 -0
- package/dist/stream/index.d.ts +12 -0
- package/dist/stream/index.js +12 -0
- package/dist/stream/mux.cjs +350 -0
- package/dist/stream/mux.cjs.map +1 -0
- package/dist/stream/mux.d.cts +160 -0
- package/dist/stream/mux.d.cts.map +1 -0
- package/dist/stream/mux.d.ts +160 -0
- package/dist/stream/mux.d.ts.map +1 -0
- package/dist/stream/mux.js +345 -0
- package/dist/stream/mux.js.map +1 -0
- package/dist/stream/run-stream.cjs +439 -0
- package/dist/stream/run-stream.cjs.map +1 -0
- package/dist/stream/run-stream.d.cts +286 -0
- package/dist/stream/run-stream.d.cts.map +1 -0
- package/dist/stream/run-stream.d.ts +285 -0
- package/dist/stream/run-stream.d.ts.map +1 -0
- package/dist/stream/run-stream.js +434 -0
- package/dist/stream/run-stream.js.map +1 -0
- package/dist/stream/stream-channel.cjs +208 -0
- package/dist/stream/stream-channel.cjs.map +1 -0
- package/dist/stream/stream-channel.d.cts +129 -0
- package/dist/stream/stream-channel.d.cts.map +1 -0
- package/dist/stream/stream-channel.d.ts +129 -0
- package/dist/stream/stream-channel.d.ts.map +1 -0
- package/dist/stream/stream-channel.js +207 -0
- package/dist/stream/stream-channel.js.map +1 -0
- package/dist/stream/transformers/index.cjs +4 -0
- package/dist/stream/transformers/index.d.ts +5 -0
- package/dist/stream/transformers/index.js +5 -0
- package/dist/stream/transformers/lifecycle.cjs +326 -0
- package/dist/stream/transformers/lifecycle.cjs.map +1 -0
- package/dist/stream/transformers/lifecycle.d.cts +53 -0
- package/dist/stream/transformers/lifecycle.d.cts.map +1 -0
- package/dist/stream/transformers/lifecycle.d.ts +53 -0
- package/dist/stream/transformers/lifecycle.d.ts.map +1 -0
- package/dist/stream/transformers/lifecycle.js +325 -0
- package/dist/stream/transformers/lifecycle.js.map +1 -0
- package/dist/stream/transformers/messages.cjs +94 -0
- package/dist/stream/transformers/messages.cjs.map +1 -0
- package/dist/stream/transformers/messages.d.cts +23 -0
- package/dist/stream/transformers/messages.d.cts.map +1 -0
- package/dist/stream/transformers/messages.d.ts +23 -0
- package/dist/stream/transformers/messages.d.ts.map +1 -0
- package/dist/stream/transformers/messages.js +94 -0
- package/dist/stream/transformers/messages.js.map +1 -0
- package/dist/stream/transformers/subgraphs.cjs +125 -0
- package/dist/stream/transformers/subgraphs.cjs.map +1 -0
- package/dist/stream/transformers/subgraphs.d.cts +95 -0
- package/dist/stream/transformers/subgraphs.d.cts.map +1 -0
- package/dist/stream/transformers/subgraphs.d.ts +95 -0
- package/dist/stream/transformers/subgraphs.d.ts.map +1 -0
- package/dist/stream/transformers/subgraphs.js +124 -0
- package/dist/stream/transformers/subgraphs.js.map +1 -0
- package/dist/stream/transformers/types.d.cts +89 -0
- package/dist/stream/transformers/types.d.cts.map +1 -0
- package/dist/stream/transformers/types.d.ts +89 -0
- package/dist/stream/transformers/types.d.ts.map +1 -0
- package/dist/stream/transformers/values.cjs +39 -0
- package/dist/stream/transformers/values.cjs.map +1 -0
- package/dist/stream/transformers/values.d.cts +21 -0
- package/dist/stream/transformers/values.d.cts.map +1 -0
- package/dist/stream/transformers/values.d.ts +21 -0
- package/dist/stream/transformers/values.d.ts.map +1 -0
- package/dist/stream/transformers/values.js +39 -0
- package/dist/stream/transformers/values.js.map +1 -0
- package/dist/stream/types.cjs +11 -0
- package/dist/stream/types.cjs.map +1 -0
- package/dist/stream/types.d.cts +255 -0
- package/dist/stream/types.d.cts.map +1 -0
- package/dist/stream/types.d.ts +255 -0
- package/dist/stream/types.d.ts.map +1 -0
- package/dist/stream/types.js +11 -0
- package/dist/stream/types.js.map +1 -0
- package/dist/web.cjs +39 -9
- package/dist/web.d.cts +12 -2
- package/dist/web.d.ts +12 -2
- package/dist/web.js +10 -1
- package/package.json +9 -8
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { StreamChannel } from "../stream-channel.js";
|
|
2
|
+
import { hasPrefix } from "../mux.js";
|
|
3
|
+
import { ChatModelStream } from "@langchain/core/language_models/stream";
|
|
4
|
+
//#region src/stream/transformers/messages.ts
|
|
5
|
+
function getMessageStreamKey(data) {
|
|
6
|
+
const record = data;
|
|
7
|
+
if (typeof record.run_id === "string") return `run:${record.run_id}`;
|
|
8
|
+
if (data.event === "message-start" && typeof record.id === "string") return `message:${record.id}`;
|
|
9
|
+
return "__default__";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a {@link StreamTransformer} that groups `messages` channel events into
|
|
13
|
+
* per-message {@link ChatModelStream} instances.
|
|
14
|
+
*
|
|
15
|
+
* A new `ChatModelStream` is created on `message-start` and closed on
|
|
16
|
+
* `message-finish`. Content-block events in between are forwarded to the
|
|
17
|
+
* active stream. Only events whose namespace exactly matches {@link path}
|
|
18
|
+
* are processed; child namespaces are ignored.
|
|
19
|
+
*
|
|
20
|
+
* @param path - Namespace prefix to match against incoming events.
|
|
21
|
+
* @param nodeFilter - If provided, only events emitted by this graph node
|
|
22
|
+
* are processed; all others are skipped.
|
|
23
|
+
* @returns A `StreamTransformer` whose projection contains the `messages`
|
|
24
|
+
* async iterable.
|
|
25
|
+
*/
|
|
26
|
+
function createMessagesTransformer(path, nodeFilter) {
|
|
27
|
+
const log = StreamChannel.local();
|
|
28
|
+
const active = /* @__PURE__ */ new Map();
|
|
29
|
+
return {
|
|
30
|
+
init: () => ({ messages: log.toAsyncIterable() }),
|
|
31
|
+
process(event) {
|
|
32
|
+
if (event.method !== "messages") return true;
|
|
33
|
+
if (!hasPrefix(event.params.namespace, path)) return true;
|
|
34
|
+
if (event.params.namespace.length !== path.length + 1) return true;
|
|
35
|
+
if (nodeFilter !== void 0 && event.params.node !== nodeFilter) return true;
|
|
36
|
+
const data = event.params.data;
|
|
37
|
+
switch (data.event) {
|
|
38
|
+
case "message-start": {
|
|
39
|
+
const key = getMessageStreamKey(data);
|
|
40
|
+
const source = StreamChannel.local();
|
|
41
|
+
const stream = Object.assign(new ChatModelStream(source.toAsyncIterable()), {
|
|
42
|
+
namespace: event.params.namespace,
|
|
43
|
+
node: event.params.node
|
|
44
|
+
});
|
|
45
|
+
active.set(key, {
|
|
46
|
+
source,
|
|
47
|
+
stream
|
|
48
|
+
});
|
|
49
|
+
source.push(data);
|
|
50
|
+
log.push(stream);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "content-block-start":
|
|
54
|
+
case "content-block-delta":
|
|
55
|
+
case "content-block-finish":
|
|
56
|
+
active.get(getMessageStreamKey(data))?.source.push(data);
|
|
57
|
+
break;
|
|
58
|
+
case "message-finish": {
|
|
59
|
+
const key = getMessageStreamKey(data);
|
|
60
|
+
const stream = active.get(key);
|
|
61
|
+
if (stream) {
|
|
62
|
+
stream.source.push(data);
|
|
63
|
+
stream.source.close();
|
|
64
|
+
active.delete(key);
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
case "error":
|
|
69
|
+
active.get(getMessageStreamKey(data))?.source.push(data);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
},
|
|
74
|
+
finalize() {
|
|
75
|
+
for (const [key, stream] of active) {
|
|
76
|
+
stream.source.push({ event: "message-finish" });
|
|
77
|
+
stream.source.close();
|
|
78
|
+
active.delete(key);
|
|
79
|
+
}
|
|
80
|
+
log.close();
|
|
81
|
+
},
|
|
82
|
+
fail(err) {
|
|
83
|
+
for (const [key, stream] of active) {
|
|
84
|
+
stream.source.fail(err);
|
|
85
|
+
active.delete(key);
|
|
86
|
+
}
|
|
87
|
+
log.fail(err);
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
92
|
+
export { createMessagesTransformer };
|
|
93
|
+
|
|
94
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","names":["CoreChatModelStream"],"sources":["../../../src/stream/transformers/messages.ts"],"sourcesContent":["import type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport { ChatModelStream as CoreChatModelStream } from \"@langchain/core/language_models/stream\";\nimport { hasPrefix } from \"../mux.js\";\nimport { StreamChannel } from \"../stream-channel.js\";\nimport type {\n ChatModelStream,\n MessagesEventData,\n Namespace,\n ProtocolEvent,\n StreamTransformer,\n} from \"../types.js\";\nimport type { MessagesTransformerProjection } from \"./types.js\";\n\ntype ActiveMessageStream = {\n source: StreamChannel<ChatModelStreamEvent>;\n stream: ChatModelStream;\n};\n\nfunction getMessageStreamKey(data: MessagesEventData): string {\n const record = data as unknown as Record<string, unknown>;\n if (typeof record.run_id === \"string\") return `run:${record.run_id}`;\n if (data.event === \"message-start\" && typeof record.id === \"string\") {\n return `message:${record.id}`;\n }\n return \"__default__\";\n}\n\n/**\n * Creates a {@link StreamTransformer} that groups `messages` channel events into\n * per-message {@link ChatModelStream} instances.\n *\n * A new `ChatModelStream` is created on `message-start` and closed on\n * `message-finish`. Content-block events in between are forwarded to the\n * active stream. Only events whose namespace exactly matches {@link path}\n * are processed; child namespaces are ignored.\n *\n * @param path - Namespace prefix to match against incoming events.\n * @param nodeFilter - If provided, only events emitted by this graph node\n * are processed; all others are skipped.\n * @returns A `StreamTransformer` whose projection contains the `messages`\n * async iterable.\n */\nexport function createMessagesTransformer(\n path: Namespace,\n nodeFilter?: string\n): StreamTransformer<MessagesTransformerProjection> {\n const log = StreamChannel.local<ChatModelStream>();\n const active = new Map<string, ActiveMessageStream>();\n\n return {\n init: () => ({\n messages: log.toAsyncIterable(),\n }),\n\n process(event: ProtocolEvent): boolean {\n if (event.method !== \"messages\") return true;\n if (!hasPrefix(event.params.namespace, path)) return true;\n\n // Only capture messages from this graph's own node executions,\n // which sit exactly one namespace level deeper than `path`.\n // Events at `path` itself are chain-level replays from the\n // callback system (handleChainEnd re-emits finalized messages)\n // and would duplicate the streamed content already captured\n // at depth+1.\n const depth = event.params.namespace.length;\n if (depth !== path.length + 1) return true;\n\n if (nodeFilter !== undefined && event.params.node !== nodeFilter) {\n return true;\n }\n\n const data = event.params.data as MessagesEventData;\n\n switch (data.event) {\n case \"message-start\": {\n const key = getMessageStreamKey(data);\n const source = StreamChannel.local<ChatModelStreamEvent>();\n const stream = Object.assign(\n new CoreChatModelStream(source.toAsyncIterable()),\n {\n namespace: event.params.namespace,\n node: event.params.node,\n }\n ) as ChatModelStream;\n active.set(key, { source, stream });\n source.push(data as unknown as ChatModelStreamEvent);\n log.push(stream);\n break;\n }\n\n case \"content-block-start\":\n case \"content-block-delta\":\n case \"content-block-finish\":\n active\n .get(getMessageStreamKey(data))\n ?.source.push(data as unknown as ChatModelStreamEvent);\n break;\n\n case \"message-finish\": {\n const key = getMessageStreamKey(data);\n const stream = active.get(key);\n if (stream) {\n stream.source.push(data as unknown as ChatModelStreamEvent);\n stream.source.close();\n active.delete(key);\n }\n break;\n }\n\n case \"error\":\n active\n .get(getMessageStreamKey(data))\n ?.source.push(data as unknown as ChatModelStreamEvent);\n break;\n }\n\n return true;\n },\n\n finalize(): void {\n for (const [key, stream] of active) {\n stream.source.push({ event: \"message-finish\" });\n stream.source.close();\n active.delete(key);\n }\n log.close();\n },\n\n fail(err: unknown): void {\n for (const [key, stream] of active) {\n stream.source.fail(err);\n active.delete(key);\n }\n log.fail(err);\n },\n };\n}\n"],"mappings":";;;;AAkBA,SAAS,oBAAoB,MAAiC;CAC5D,MAAM,SAAS;AACf,KAAI,OAAO,OAAO,WAAW,SAAU,QAAO,OAAO,OAAO;AAC5D,KAAI,KAAK,UAAU,mBAAmB,OAAO,OAAO,OAAO,SACzD,QAAO,WAAW,OAAO;AAE3B,QAAO;;;;;;;;;;;;;;;;;AAkBT,SAAgB,0BACd,MACA,YACkD;CAClD,MAAM,MAAM,cAAc,OAAwB;CAClD,MAAM,yBAAS,IAAI,KAAkC;AAErD,QAAO;EACL,aAAa,EACX,UAAU,IAAI,iBAAiB,EAChC;EAED,QAAQ,OAA+B;AACrC,OAAI,MAAM,WAAW,WAAY,QAAO;AACxC,OAAI,CAAC,UAAU,MAAM,OAAO,WAAW,KAAK,CAAE,QAAO;AASrD,OADc,MAAM,OAAO,UAAU,WACvB,KAAK,SAAS,EAAG,QAAO;AAEtC,OAAI,eAAe,KAAA,KAAa,MAAM,OAAO,SAAS,WACpD,QAAO;GAGT,MAAM,OAAO,MAAM,OAAO;AAE1B,WAAQ,KAAK,OAAb;IACE,KAAK,iBAAiB;KACpB,MAAM,MAAM,oBAAoB,KAAK;KACrC,MAAM,SAAS,cAAc,OAA6B;KAC1D,MAAM,SAAS,OAAO,OACpB,IAAIA,gBAAoB,OAAO,iBAAiB,CAAC,EACjD;MACE,WAAW,MAAM,OAAO;MACxB,MAAM,MAAM,OAAO;MACpB,CACF;AACD,YAAO,IAAI,KAAK;MAAE;MAAQ;MAAQ,CAAC;AACnC,YAAO,KAAK,KAAwC;AACpD,SAAI,KAAK,OAAO;AAChB;;IAGF,KAAK;IACL,KAAK;IACL,KAAK;AACH,YACG,IAAI,oBAAoB,KAAK,CAAC,EAC7B,OAAO,KAAK,KAAwC;AACxD;IAEF,KAAK,kBAAkB;KACrB,MAAM,MAAM,oBAAoB,KAAK;KACrC,MAAM,SAAS,OAAO,IAAI,IAAI;AAC9B,SAAI,QAAQ;AACV,aAAO,OAAO,KAAK,KAAwC;AAC3D,aAAO,OAAO,OAAO;AACrB,aAAO,OAAO,IAAI;;AAEpB;;IAGF,KAAK;AACH,YACG,IAAI,oBAAoB,KAAK,CAAC,EAC7B,OAAO,KAAK,KAAwC;AACxD;;AAGJ,UAAO;;EAGT,WAAiB;AACf,QAAK,MAAM,CAAC,KAAK,WAAW,QAAQ;AAClC,WAAO,OAAO,KAAK,EAAE,OAAO,kBAAkB,CAAC;AAC/C,WAAO,OAAO,OAAO;AACrB,WAAO,OAAO,IAAI;;AAEpB,OAAI,OAAO;;EAGb,KAAK,KAAoB;AACvB,QAAK,MAAM,CAAC,KAAK,WAAW,QAAQ;AAClC,WAAO,OAAO,KAAK,IAAI;AACvB,WAAO,OAAO,IAAI;;AAEpB,OAAI,KAAK,IAAI;;EAEhB"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const require_mux = require("../mux.cjs");
|
|
2
|
+
//#region src/stream/transformers/subgraphs.ts
|
|
3
|
+
/**
|
|
4
|
+
* SubgraphDiscoveryTransformer - materializes a {@link StreamHandle} for
|
|
5
|
+
* each newly observed top-level subgraph namespace and announces it on
|
|
6
|
+
* the mux's shared {@link StreamMux._discoveries} channel.
|
|
7
|
+
*
|
|
8
|
+
* Previously this work was inlined in {@link StreamMux.push}. Extracting
|
|
9
|
+
* it into a transformer aligns discovery with the rest of the stream
|
|
10
|
+
* architecture (lifecycle, values, messages are all transformers),
|
|
11
|
+
* isolates the factory wiring, and makes discovery behavior
|
|
12
|
+
* independently testable.
|
|
13
|
+
*
|
|
14
|
+
* The transformer also owns the read-side of discovery: it exposes an
|
|
15
|
+
* `AsyncIterable<TStream>` projection (`subgraphs`) scoped to the root
|
|
16
|
+
* namespace, and a {@link filterSubgraphHandles} helper that callers
|
|
17
|
+
* can use to scope the same channel to any descendant namespace. This
|
|
18
|
+
* lets `GraphRunStream` drop its bespoke `subscribeSubgraphs`
|
|
19
|
+
* delegation and surface child streams via the standard native
|
|
20
|
+
* projection pattern.
|
|
21
|
+
*
|
|
22
|
+
* Only first-level namespace segments are announced. Deeper segments
|
|
23
|
+
* (e.g. `["researcher:uuid", "tools:uuid"]`) are internal Pregel
|
|
24
|
+
* checkpoint namespaces for nodes inside a subgraph and should not
|
|
25
|
+
* appear as user-facing `SubgraphRunStream` instances; the mux still
|
|
26
|
+
* resolves their values via its own `#streamMap` when registered
|
|
27
|
+
* elsewhere.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Filter a {@link SubgraphDiscovery} channel to only the direct children
|
|
31
|
+
* of a given namespace.
|
|
32
|
+
*
|
|
33
|
+
* Returns an `AsyncIterable` whose iterator yields stream handles for
|
|
34
|
+
* discoveries whose namespace is exactly one segment deeper than
|
|
35
|
+
* {@link path} and shares it as a prefix. Iteration begins at
|
|
36
|
+
* {@link startAt} (so each caller picks up only discoveries added
|
|
37
|
+
* after its construction) and terminates when the underlying log
|
|
38
|
+
* closes or fails.
|
|
39
|
+
*
|
|
40
|
+
* @typeParam TStream - Concrete stream type recorded in the log.
|
|
41
|
+
* Callers may cast if the log was populated by a specific factory.
|
|
42
|
+
* @param log - The shared discovery channel (`mux._discoveries`).
|
|
43
|
+
* @param path - Parent namespace whose direct children should be
|
|
44
|
+
* yielded.
|
|
45
|
+
* @param startAt - Zero-based index into the discovery log to begin
|
|
46
|
+
* from.
|
|
47
|
+
* @returns An async iterable of stream handles.
|
|
48
|
+
*/
|
|
49
|
+
function filterSubgraphHandles(log, path, startAt = 0) {
|
|
50
|
+
const targetDepth = path.length + 1;
|
|
51
|
+
return { [Symbol.asyncIterator]() {
|
|
52
|
+
const base = log.iterate(startAt);
|
|
53
|
+
return { async next() {
|
|
54
|
+
while (true) {
|
|
55
|
+
const result = await base.next();
|
|
56
|
+
if (result.done) return {
|
|
57
|
+
value: void 0,
|
|
58
|
+
done: true
|
|
59
|
+
};
|
|
60
|
+
const { ns, stream } = result.value;
|
|
61
|
+
if (ns.length === targetDepth && require_mux.hasPrefix(ns, path)) return {
|
|
62
|
+
value: stream,
|
|
63
|
+
done: false
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
} };
|
|
67
|
+
} };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create the subgraph discovery transformer.
|
|
71
|
+
*
|
|
72
|
+
* Registering this transformer against a mux replaces the legacy
|
|
73
|
+
* inline behavior that previously lived in {@link StreamMux.push}.
|
|
74
|
+
* The mux no longer knows about the subgraph factory: instead, this
|
|
75
|
+
* transformer is the single component that materializes stream
|
|
76
|
+
* handles and announces them on `_discoveries`.
|
|
77
|
+
*
|
|
78
|
+
* Marked as a {@link NativeStreamTransformer} so the projection is
|
|
79
|
+
* treated as internal wiring (not merged into `run.extensions` and
|
|
80
|
+
* not auto-forwarded via {@link StreamMux.wireChannels}).
|
|
81
|
+
*
|
|
82
|
+
* @typeParam TStream - Concrete stream handle type produced by
|
|
83
|
+
* {@link SubgraphDiscoveryTransformerOptions.createStream}.
|
|
84
|
+
* Defaults to the base {@link StreamHandle} interface.
|
|
85
|
+
* @param mux - The mux whose `_discoveries` log should receive
|
|
86
|
+
* discovery entries and whose `register` will be called for each
|
|
87
|
+
* new stream handle.
|
|
88
|
+
* @param options - Factory and related wiring.
|
|
89
|
+
* @returns A native transformer that populates
|
|
90
|
+
* {@link StreamMux._discoveries} and exposes a root-scoped
|
|
91
|
+
* `subgraphs` iterable via its projection.
|
|
92
|
+
*/
|
|
93
|
+
function createSubgraphDiscoveryTransformer(mux, options) {
|
|
94
|
+
const { createStream } = options;
|
|
95
|
+
const seen = /* @__PURE__ */ new Set();
|
|
96
|
+
return {
|
|
97
|
+
__native: true,
|
|
98
|
+
init() {
|
|
99
|
+
return {
|
|
100
|
+
_discoveries: mux._discoveries,
|
|
101
|
+
subgraphs: filterSubgraphHandles(mux._discoveries, [], 0)
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
process(event) {
|
|
105
|
+
const ns = event.params.namespace;
|
|
106
|
+
if (ns.length === 0) return true;
|
|
107
|
+
const topNs = ns.slice(0, 1);
|
|
108
|
+
const topKey = require_mux.nsKey(topNs);
|
|
109
|
+
if (seen.has(topKey)) return true;
|
|
110
|
+
seen.add(topKey);
|
|
111
|
+
const stream = createStream(topNs, mux._discoveries.size, mux._events.size);
|
|
112
|
+
mux.register(topNs, stream);
|
|
113
|
+
mux._discoveries.push({
|
|
114
|
+
ns: topNs,
|
|
115
|
+
stream
|
|
116
|
+
});
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
exports.createSubgraphDiscoveryTransformer = createSubgraphDiscoveryTransformer;
|
|
123
|
+
exports.filterSubgraphHandles = filterSubgraphHandles;
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=subgraphs.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgraphs.cjs","names":["hasPrefix","nsKey"],"sources":["../../../src/stream/transformers/subgraphs.ts"],"sourcesContent":["/**\n * SubgraphDiscoveryTransformer - materializes a {@link StreamHandle} for\n * each newly observed top-level subgraph namespace and announces it on\n * the mux's shared {@link StreamMux._discoveries} channel.\n *\n * Previously this work was inlined in {@link StreamMux.push}. Extracting\n * it into a transformer aligns discovery with the rest of the stream\n * architecture (lifecycle, values, messages are all transformers),\n * isolates the factory wiring, and makes discovery behavior\n * independently testable.\n *\n * The transformer also owns the read-side of discovery: it exposes an\n * `AsyncIterable<TStream>` projection (`subgraphs`) scoped to the root\n * namespace, and a {@link filterSubgraphHandles} helper that callers\n * can use to scope the same channel to any descendant namespace. This\n * lets `GraphRunStream` drop its bespoke `subscribeSubgraphs`\n * delegation and surface child streams via the standard native\n * projection pattern.\n *\n * Only first-level namespace segments are announced. Deeper segments\n * (e.g. `[\"researcher:uuid\", \"tools:uuid\"]`) are internal Pregel\n * checkpoint namespaces for nodes inside a subgraph and should not\n * appear as user-facing `SubgraphRunStream` instances; the mux still\n * resolves their values via its own `#streamMap` when registered\n * elsewhere.\n */\n\nimport { hasPrefix, nsKey } from \"../mux.js\";\nimport type { StreamHandle, StreamMux, SubgraphDiscovery } from \"../mux.js\";\nimport type {\n Namespace,\n NativeStreamTransformer,\n ProtocolEvent,\n} from \"../types.js\";\nimport type { StreamChannel } from \"../stream-channel.js\";\n\n/**\n * Projection returned by {@link createSubgraphDiscoveryTransformer}.\n *\n * @typeParam TStream - Concrete stream handle type produced by the\n * configured factory (e.g. `SubgraphRunStream`).\n */\nexport interface SubgraphDiscoveryProjection<\n TStream extends StreamHandle = StreamHandle,\n> {\n /**\n * Shared discovery channel on the mux. The transformer writes to it so\n * the channel's lifetime stays tied to the mux (closed on `mux.close()`\n * / failed on `mux.fail()`). The underscore prefix signals internal\n * wiring: consumers should iterate {@link subgraphs} instead.\n */\n _discoveries: StreamChannel<SubgraphDiscovery>;\n\n /**\n * Async iterable of direct child stream handles of the root\n * namespace. Wired onto `GraphRunStream.subgraphs` during root\n * stream construction. For descendant namespaces, use\n * {@link filterSubgraphHandles} to scope the same log.\n */\n subgraphs: AsyncIterable<TStream>;\n}\n\n/**\n * Configuration for {@link createSubgraphDiscoveryTransformer}.\n */\nexport interface SubgraphDiscoveryTransformerOptions<\n TStream extends StreamHandle = StreamHandle,\n> {\n /**\n * Factory invoked once per newly observed top-level namespace.\n *\n * Receives the discovery-channel and event-channel offsets so the resulting\n * stream can iterate only events arriving after the namespace was\n * first seen (no retroactive replay).\n *\n * @param path - The single-segment top-level namespace.\n * @param discoveryStart - Current size of the mux discovery log.\n * @param eventStart - Current size of the mux event log.\n * @returns A stream handle registered with the mux for values/error\n * resolution on close/fail.\n */\n createStream: (\n path: Namespace,\n discoveryStart: number,\n eventStart: number\n ) => TStream;\n}\n\n/**\n * Filter a {@link SubgraphDiscovery} channel to only the direct children\n * of a given namespace.\n *\n * Returns an `AsyncIterable` whose iterator yields stream handles for\n * discoveries whose namespace is exactly one segment deeper than\n * {@link path} and shares it as a prefix. Iteration begins at\n * {@link startAt} (so each caller picks up only discoveries added\n * after its construction) and terminates when the underlying log\n * closes or fails.\n *\n * @typeParam TStream - Concrete stream type recorded in the log.\n * Callers may cast if the log was populated by a specific factory.\n * @param log - The shared discovery channel (`mux._discoveries`).\n * @param path - Parent namespace whose direct children should be\n * yielded.\n * @param startAt - Zero-based index into the discovery log to begin\n * from.\n * @returns An async iterable of stream handles.\n */\nexport function filterSubgraphHandles<\n TStream extends StreamHandle = StreamHandle,\n>(\n log: StreamChannel<SubgraphDiscovery>,\n path: Namespace,\n startAt = 0\n): AsyncIterable<TStream> {\n const targetDepth = path.length + 1;\n return {\n [Symbol.asyncIterator](): AsyncIterator<TStream> {\n const base = log.iterate(startAt);\n return {\n async next(): Promise<IteratorResult<TStream>> {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const result = await base.next();\n if (result.done) {\n return { value: undefined as unknown as TStream, done: true };\n }\n const { ns, stream } = result.value;\n if (ns.length === targetDepth && hasPrefix(ns, path)) {\n return { value: stream as TStream, done: false };\n }\n }\n },\n };\n },\n };\n}\n\n/**\n * Create the subgraph discovery transformer.\n *\n * Registering this transformer against a mux replaces the legacy\n * inline behavior that previously lived in {@link StreamMux.push}.\n * The mux no longer knows about the subgraph factory: instead, this\n * transformer is the single component that materializes stream\n * handles and announces them on `_discoveries`.\n *\n * Marked as a {@link NativeStreamTransformer} so the projection is\n * treated as internal wiring (not merged into `run.extensions` and\n * not auto-forwarded via {@link StreamMux.wireChannels}).\n *\n * @typeParam TStream - Concrete stream handle type produced by\n * {@link SubgraphDiscoveryTransformerOptions.createStream}.\n * Defaults to the base {@link StreamHandle} interface.\n * @param mux - The mux whose `_discoveries` log should receive\n * discovery entries and whose `register` will be called for each\n * new stream handle.\n * @param options - Factory and related wiring.\n * @returns A native transformer that populates\n * {@link StreamMux._discoveries} and exposes a root-scoped\n * `subgraphs` iterable via its projection.\n */\nexport function createSubgraphDiscoveryTransformer<\n TStream extends StreamHandle = StreamHandle,\n>(\n mux: StreamMux,\n options: SubgraphDiscoveryTransformerOptions<TStream>\n): NativeStreamTransformer<SubgraphDiscoveryProjection<TStream>> {\n const { createStream } = options;\n const seen = new Set<string>();\n\n return {\n __native: true,\n\n init() {\n return {\n _discoveries: mux._discoveries,\n subgraphs: filterSubgraphHandles<TStream>(mux._discoveries, [], 0),\n };\n },\n\n process(event: ProtocolEvent): boolean {\n const ns = event.params.namespace;\n if (ns.length === 0) return true;\n\n const topNs = ns.slice(0, 1);\n const topKey = nsKey(topNs);\n if (seen.has(topKey)) return true;\n seen.add(topKey);\n\n const stream = createStream(\n topNs,\n mux._discoveries.size,\n mux._events.size\n );\n mux.register(topNs, stream);\n mux._discoveries.push({ ns: topNs, stream });\n return true;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,SAAgB,sBAGd,KACA,MACA,UAAU,GACc;CACxB,MAAM,cAAc,KAAK,SAAS;AAClC,QAAO,EACL,CAAC,OAAO,iBAAyC;EAC/C,MAAM,OAAO,IAAI,QAAQ,QAAQ;AACjC,SAAO,EACL,MAAM,OAAyC;AAE7C,UAAO,MAAM;IACX,MAAM,SAAS,MAAM,KAAK,MAAM;AAChC,QAAI,OAAO,KACT,QAAO;KAAE,OAAO,KAAA;KAAiC,MAAM;KAAM;IAE/D,MAAM,EAAE,IAAI,WAAW,OAAO;AAC9B,QAAI,GAAG,WAAW,eAAeA,YAAAA,UAAU,IAAI,KAAK,CAClD,QAAO;KAAE,OAAO;KAAmB,MAAM;KAAO;;KAIvD;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BH,SAAgB,mCAGd,KACA,SAC+D;CAC/D,MAAM,EAAE,iBAAiB;CACzB,MAAM,uBAAO,IAAI,KAAa;AAE9B,QAAO;EACL,UAAU;EAEV,OAAO;AACL,UAAO;IACL,cAAc,IAAI;IAClB,WAAW,sBAA+B,IAAI,cAAc,EAAE,EAAE,EAAE;IACnE;;EAGH,QAAQ,OAA+B;GACrC,MAAM,KAAK,MAAM,OAAO;AACxB,OAAI,GAAG,WAAW,EAAG,QAAO;GAE5B,MAAM,QAAQ,GAAG,MAAM,GAAG,EAAE;GAC5B,MAAM,SAASC,YAAAA,MAAM,MAAM;AAC3B,OAAI,KAAK,IAAI,OAAO,CAAE,QAAO;AAC7B,QAAK,IAAI,OAAO;GAEhB,MAAM,SAAS,aACb,OACA,IAAI,aAAa,MACjB,IAAI,QAAQ,KACb;AACD,OAAI,SAAS,OAAO,OAAO;AAC3B,OAAI,aAAa,KAAK;IAAE,IAAI;IAAO;IAAQ,CAAC;AAC5C,UAAO;;EAEV"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Namespace, NativeStreamTransformer } from "../types.cjs";
|
|
2
|
+
import { StreamChannel } from "../stream-channel.cjs";
|
|
3
|
+
import { StreamHandle, StreamMux, SubgraphDiscovery } from "../mux.cjs";
|
|
4
|
+
|
|
5
|
+
//#region src/stream/transformers/subgraphs.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Projection returned by {@link createSubgraphDiscoveryTransformer}.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam TStream - Concrete stream handle type produced by the
|
|
10
|
+
* configured factory (e.g. `SubgraphRunStream`).
|
|
11
|
+
*/
|
|
12
|
+
interface SubgraphDiscoveryProjection<TStream extends StreamHandle = StreamHandle> {
|
|
13
|
+
/**
|
|
14
|
+
* Shared discovery channel on the mux. The transformer writes to it so
|
|
15
|
+
* the channel's lifetime stays tied to the mux (closed on `mux.close()`
|
|
16
|
+
* / failed on `mux.fail()`). The underscore prefix signals internal
|
|
17
|
+
* wiring: consumers should iterate {@link subgraphs} instead.
|
|
18
|
+
*/
|
|
19
|
+
_discoveries: StreamChannel<SubgraphDiscovery>;
|
|
20
|
+
/**
|
|
21
|
+
* Async iterable of direct child stream handles of the root
|
|
22
|
+
* namespace. Wired onto `GraphRunStream.subgraphs` during root
|
|
23
|
+
* stream construction. For descendant namespaces, use
|
|
24
|
+
* {@link filterSubgraphHandles} to scope the same log.
|
|
25
|
+
*/
|
|
26
|
+
subgraphs: AsyncIterable<TStream>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for {@link createSubgraphDiscoveryTransformer}.
|
|
30
|
+
*/
|
|
31
|
+
interface SubgraphDiscoveryTransformerOptions<TStream extends StreamHandle = StreamHandle> {
|
|
32
|
+
/**
|
|
33
|
+
* Factory invoked once per newly observed top-level namespace.
|
|
34
|
+
*
|
|
35
|
+
* Receives the discovery-channel and event-channel offsets so the resulting
|
|
36
|
+
* stream can iterate only events arriving after the namespace was
|
|
37
|
+
* first seen (no retroactive replay).
|
|
38
|
+
*
|
|
39
|
+
* @param path - The single-segment top-level namespace.
|
|
40
|
+
* @param discoveryStart - Current size of the mux discovery log.
|
|
41
|
+
* @param eventStart - Current size of the mux event log.
|
|
42
|
+
* @returns A stream handle registered with the mux for values/error
|
|
43
|
+
* resolution on close/fail.
|
|
44
|
+
*/
|
|
45
|
+
createStream: (path: Namespace, discoveryStart: number, eventStart: number) => TStream;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Filter a {@link SubgraphDiscovery} channel to only the direct children
|
|
49
|
+
* of a given namespace.
|
|
50
|
+
*
|
|
51
|
+
* Returns an `AsyncIterable` whose iterator yields stream handles for
|
|
52
|
+
* discoveries whose namespace is exactly one segment deeper than
|
|
53
|
+
* {@link path} and shares it as a prefix. Iteration begins at
|
|
54
|
+
* {@link startAt} (so each caller picks up only discoveries added
|
|
55
|
+
* after its construction) and terminates when the underlying log
|
|
56
|
+
* closes or fails.
|
|
57
|
+
*
|
|
58
|
+
* @typeParam TStream - Concrete stream type recorded in the log.
|
|
59
|
+
* Callers may cast if the log was populated by a specific factory.
|
|
60
|
+
* @param log - The shared discovery channel (`mux._discoveries`).
|
|
61
|
+
* @param path - Parent namespace whose direct children should be
|
|
62
|
+
* yielded.
|
|
63
|
+
* @param startAt - Zero-based index into the discovery log to begin
|
|
64
|
+
* from.
|
|
65
|
+
* @returns An async iterable of stream handles.
|
|
66
|
+
*/
|
|
67
|
+
declare function filterSubgraphHandles<TStream extends StreamHandle = StreamHandle>(log: StreamChannel<SubgraphDiscovery>, path: Namespace, startAt?: number): AsyncIterable<TStream>;
|
|
68
|
+
/**
|
|
69
|
+
* Create the subgraph discovery transformer.
|
|
70
|
+
*
|
|
71
|
+
* Registering this transformer against a mux replaces the legacy
|
|
72
|
+
* inline behavior that previously lived in {@link StreamMux.push}.
|
|
73
|
+
* The mux no longer knows about the subgraph factory: instead, this
|
|
74
|
+
* transformer is the single component that materializes stream
|
|
75
|
+
* handles and announces them on `_discoveries`.
|
|
76
|
+
*
|
|
77
|
+
* Marked as a {@link NativeStreamTransformer} so the projection is
|
|
78
|
+
* treated as internal wiring (not merged into `run.extensions` and
|
|
79
|
+
* not auto-forwarded via {@link StreamMux.wireChannels}).
|
|
80
|
+
*
|
|
81
|
+
* @typeParam TStream - Concrete stream handle type produced by
|
|
82
|
+
* {@link SubgraphDiscoveryTransformerOptions.createStream}.
|
|
83
|
+
* Defaults to the base {@link StreamHandle} interface.
|
|
84
|
+
* @param mux - The mux whose `_discoveries` log should receive
|
|
85
|
+
* discovery entries and whose `register` will be called for each
|
|
86
|
+
* new stream handle.
|
|
87
|
+
* @param options - Factory and related wiring.
|
|
88
|
+
* @returns A native transformer that populates
|
|
89
|
+
* {@link StreamMux._discoveries} and exposes a root-scoped
|
|
90
|
+
* `subgraphs` iterable via its projection.
|
|
91
|
+
*/
|
|
92
|
+
declare function createSubgraphDiscoveryTransformer<TStream extends StreamHandle = StreamHandle>(mux: StreamMux, options: SubgraphDiscoveryTransformerOptions<TStream>): NativeStreamTransformer<SubgraphDiscoveryProjection<TStream>>;
|
|
93
|
+
//#endregion
|
|
94
|
+
export { SubgraphDiscoveryProjection, SubgraphDiscoveryTransformerOptions, createSubgraphDiscoveryTransformer, filterSubgraphHandles };
|
|
95
|
+
//# sourceMappingURL=subgraphs.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgraphs.d.cts","names":[],"sources":["../../../src/stream/transformers/subgraphs.ts"],"mappings":";;;;;;;;;;;UA0CiB,2BAAA,iBACC,YAAA,GAAe,YAAA;EAuB/B;;;;;;EAfA,YAAA,EAAc,aAAA,CAAc,iBAAA;EAiC1B;;;;AAwBJ;;EAjDE,SAAA,EAAW,aAAA,CAAc,OAAA;AAAA;;;;UAMV,mCAAA,iBACC,YAAA,GAAe,YAAA;EAgDhB;;;;;;;;;;;;;EAjCf,YAAA,GACE,IAAA,EAAM,SAAA,EACN,cAAA,UACA,UAAA,aACG,OAAA;AAAA;;;AA6EP;;;;;;;;;;;;;;;;;;iBAtDgB,qBAAA,iBACE,YAAA,GAAe,YAAA,CAAA,CAE/B,GAAA,EAAK,aAAA,CAAc,iBAAA,GACnB,IAAA,EAAM,SAAA,EACN,OAAA,YACC,aAAA,CAAc,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDD,kCAAA,iBACE,YAAA,GAAe,YAAA,CAAA,CAE/B,GAAA,EAAK,SAAA,EACL,OAAA,EAAS,mCAAA,CAAoC,OAAA,IAC5C,uBAAA,CAAwB,2BAAA,CAA4B,OAAA"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Namespace, NativeStreamTransformer } from "../types.js";
|
|
2
|
+
import { StreamChannel } from "../stream-channel.js";
|
|
3
|
+
import { StreamHandle, StreamMux, SubgraphDiscovery } from "../mux.js";
|
|
4
|
+
|
|
5
|
+
//#region src/stream/transformers/subgraphs.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Projection returned by {@link createSubgraphDiscoveryTransformer}.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam TStream - Concrete stream handle type produced by the
|
|
10
|
+
* configured factory (e.g. `SubgraphRunStream`).
|
|
11
|
+
*/
|
|
12
|
+
interface SubgraphDiscoveryProjection<TStream extends StreamHandle = StreamHandle> {
|
|
13
|
+
/**
|
|
14
|
+
* Shared discovery channel on the mux. The transformer writes to it so
|
|
15
|
+
* the channel's lifetime stays tied to the mux (closed on `mux.close()`
|
|
16
|
+
* / failed on `mux.fail()`). The underscore prefix signals internal
|
|
17
|
+
* wiring: consumers should iterate {@link subgraphs} instead.
|
|
18
|
+
*/
|
|
19
|
+
_discoveries: StreamChannel<SubgraphDiscovery>;
|
|
20
|
+
/**
|
|
21
|
+
* Async iterable of direct child stream handles of the root
|
|
22
|
+
* namespace. Wired onto `GraphRunStream.subgraphs` during root
|
|
23
|
+
* stream construction. For descendant namespaces, use
|
|
24
|
+
* {@link filterSubgraphHandles} to scope the same log.
|
|
25
|
+
*/
|
|
26
|
+
subgraphs: AsyncIterable<TStream>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for {@link createSubgraphDiscoveryTransformer}.
|
|
30
|
+
*/
|
|
31
|
+
interface SubgraphDiscoveryTransformerOptions<TStream extends StreamHandle = StreamHandle> {
|
|
32
|
+
/**
|
|
33
|
+
* Factory invoked once per newly observed top-level namespace.
|
|
34
|
+
*
|
|
35
|
+
* Receives the discovery-channel and event-channel offsets so the resulting
|
|
36
|
+
* stream can iterate only events arriving after the namespace was
|
|
37
|
+
* first seen (no retroactive replay).
|
|
38
|
+
*
|
|
39
|
+
* @param path - The single-segment top-level namespace.
|
|
40
|
+
* @param discoveryStart - Current size of the mux discovery log.
|
|
41
|
+
* @param eventStart - Current size of the mux event log.
|
|
42
|
+
* @returns A stream handle registered with the mux for values/error
|
|
43
|
+
* resolution on close/fail.
|
|
44
|
+
*/
|
|
45
|
+
createStream: (path: Namespace, discoveryStart: number, eventStart: number) => TStream;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Filter a {@link SubgraphDiscovery} channel to only the direct children
|
|
49
|
+
* of a given namespace.
|
|
50
|
+
*
|
|
51
|
+
* Returns an `AsyncIterable` whose iterator yields stream handles for
|
|
52
|
+
* discoveries whose namespace is exactly one segment deeper than
|
|
53
|
+
* {@link path} and shares it as a prefix. Iteration begins at
|
|
54
|
+
* {@link startAt} (so each caller picks up only discoveries added
|
|
55
|
+
* after its construction) and terminates when the underlying log
|
|
56
|
+
* closes or fails.
|
|
57
|
+
*
|
|
58
|
+
* @typeParam TStream - Concrete stream type recorded in the log.
|
|
59
|
+
* Callers may cast if the log was populated by a specific factory.
|
|
60
|
+
* @param log - The shared discovery channel (`mux._discoveries`).
|
|
61
|
+
* @param path - Parent namespace whose direct children should be
|
|
62
|
+
* yielded.
|
|
63
|
+
* @param startAt - Zero-based index into the discovery log to begin
|
|
64
|
+
* from.
|
|
65
|
+
* @returns An async iterable of stream handles.
|
|
66
|
+
*/
|
|
67
|
+
declare function filterSubgraphHandles<TStream extends StreamHandle = StreamHandle>(log: StreamChannel<SubgraphDiscovery>, path: Namespace, startAt?: number): AsyncIterable<TStream>;
|
|
68
|
+
/**
|
|
69
|
+
* Create the subgraph discovery transformer.
|
|
70
|
+
*
|
|
71
|
+
* Registering this transformer against a mux replaces the legacy
|
|
72
|
+
* inline behavior that previously lived in {@link StreamMux.push}.
|
|
73
|
+
* The mux no longer knows about the subgraph factory: instead, this
|
|
74
|
+
* transformer is the single component that materializes stream
|
|
75
|
+
* handles and announces them on `_discoveries`.
|
|
76
|
+
*
|
|
77
|
+
* Marked as a {@link NativeStreamTransformer} so the projection is
|
|
78
|
+
* treated as internal wiring (not merged into `run.extensions` and
|
|
79
|
+
* not auto-forwarded via {@link StreamMux.wireChannels}).
|
|
80
|
+
*
|
|
81
|
+
* @typeParam TStream - Concrete stream handle type produced by
|
|
82
|
+
* {@link SubgraphDiscoveryTransformerOptions.createStream}.
|
|
83
|
+
* Defaults to the base {@link StreamHandle} interface.
|
|
84
|
+
* @param mux - The mux whose `_discoveries` log should receive
|
|
85
|
+
* discovery entries and whose `register` will be called for each
|
|
86
|
+
* new stream handle.
|
|
87
|
+
* @param options - Factory and related wiring.
|
|
88
|
+
* @returns A native transformer that populates
|
|
89
|
+
* {@link StreamMux._discoveries} and exposes a root-scoped
|
|
90
|
+
* `subgraphs` iterable via its projection.
|
|
91
|
+
*/
|
|
92
|
+
declare function createSubgraphDiscoveryTransformer<TStream extends StreamHandle = StreamHandle>(mux: StreamMux, options: SubgraphDiscoveryTransformerOptions<TStream>): NativeStreamTransformer<SubgraphDiscoveryProjection<TStream>>;
|
|
93
|
+
//#endregion
|
|
94
|
+
export { SubgraphDiscoveryProjection, SubgraphDiscoveryTransformerOptions, createSubgraphDiscoveryTransformer, filterSubgraphHandles };
|
|
95
|
+
//# sourceMappingURL=subgraphs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgraphs.d.ts","names":[],"sources":["../../../src/stream/transformers/subgraphs.ts"],"mappings":";;;;;;;;;;;UA0CiB,2BAAA,iBACC,YAAA,GAAe,YAAA;EAuB/B;;;;;;EAfA,YAAA,EAAc,aAAA,CAAc,iBAAA;EAiC1B;;;;AAwBJ;;EAjDE,SAAA,EAAW,aAAA,CAAc,OAAA;AAAA;;;;UAMV,mCAAA,iBACC,YAAA,GAAe,YAAA;EAgDhB;;;;;;;;;;;;;EAjCf,YAAA,GACE,IAAA,EAAM,SAAA,EACN,cAAA,UACA,UAAA,aACG,OAAA;AAAA;;;AA6EP;;;;;;;;;;;;;;;;;;iBAtDgB,qBAAA,iBACE,YAAA,GAAe,YAAA,CAAA,CAE/B,GAAA,EAAK,aAAA,CAAc,iBAAA,GACnB,IAAA,EAAM,SAAA,EACN,OAAA,YACC,aAAA,CAAc,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDD,kCAAA,iBACE,YAAA,GAAe,YAAA,CAAA,CAE/B,GAAA,EAAK,SAAA,EACL,OAAA,EAAS,mCAAA,CAAoC,OAAA,IAC5C,uBAAA,CAAwB,2BAAA,CAA4B,OAAA"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { hasPrefix, nsKey } from "../mux.js";
|
|
2
|
+
//#region src/stream/transformers/subgraphs.ts
|
|
3
|
+
/**
|
|
4
|
+
* SubgraphDiscoveryTransformer - materializes a {@link StreamHandle} for
|
|
5
|
+
* each newly observed top-level subgraph namespace and announces it on
|
|
6
|
+
* the mux's shared {@link StreamMux._discoveries} channel.
|
|
7
|
+
*
|
|
8
|
+
* Previously this work was inlined in {@link StreamMux.push}. Extracting
|
|
9
|
+
* it into a transformer aligns discovery with the rest of the stream
|
|
10
|
+
* architecture (lifecycle, values, messages are all transformers),
|
|
11
|
+
* isolates the factory wiring, and makes discovery behavior
|
|
12
|
+
* independently testable.
|
|
13
|
+
*
|
|
14
|
+
* The transformer also owns the read-side of discovery: it exposes an
|
|
15
|
+
* `AsyncIterable<TStream>` projection (`subgraphs`) scoped to the root
|
|
16
|
+
* namespace, and a {@link filterSubgraphHandles} helper that callers
|
|
17
|
+
* can use to scope the same channel to any descendant namespace. This
|
|
18
|
+
* lets `GraphRunStream` drop its bespoke `subscribeSubgraphs`
|
|
19
|
+
* delegation and surface child streams via the standard native
|
|
20
|
+
* projection pattern.
|
|
21
|
+
*
|
|
22
|
+
* Only first-level namespace segments are announced. Deeper segments
|
|
23
|
+
* (e.g. `["researcher:uuid", "tools:uuid"]`) are internal Pregel
|
|
24
|
+
* checkpoint namespaces for nodes inside a subgraph and should not
|
|
25
|
+
* appear as user-facing `SubgraphRunStream` instances; the mux still
|
|
26
|
+
* resolves their values via its own `#streamMap` when registered
|
|
27
|
+
* elsewhere.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Filter a {@link SubgraphDiscovery} channel to only the direct children
|
|
31
|
+
* of a given namespace.
|
|
32
|
+
*
|
|
33
|
+
* Returns an `AsyncIterable` whose iterator yields stream handles for
|
|
34
|
+
* discoveries whose namespace is exactly one segment deeper than
|
|
35
|
+
* {@link path} and shares it as a prefix. Iteration begins at
|
|
36
|
+
* {@link startAt} (so each caller picks up only discoveries added
|
|
37
|
+
* after its construction) and terminates when the underlying log
|
|
38
|
+
* closes or fails.
|
|
39
|
+
*
|
|
40
|
+
* @typeParam TStream - Concrete stream type recorded in the log.
|
|
41
|
+
* Callers may cast if the log was populated by a specific factory.
|
|
42
|
+
* @param log - The shared discovery channel (`mux._discoveries`).
|
|
43
|
+
* @param path - Parent namespace whose direct children should be
|
|
44
|
+
* yielded.
|
|
45
|
+
* @param startAt - Zero-based index into the discovery log to begin
|
|
46
|
+
* from.
|
|
47
|
+
* @returns An async iterable of stream handles.
|
|
48
|
+
*/
|
|
49
|
+
function filterSubgraphHandles(log, path, startAt = 0) {
|
|
50
|
+
const targetDepth = path.length + 1;
|
|
51
|
+
return { [Symbol.asyncIterator]() {
|
|
52
|
+
const base = log.iterate(startAt);
|
|
53
|
+
return { async next() {
|
|
54
|
+
while (true) {
|
|
55
|
+
const result = await base.next();
|
|
56
|
+
if (result.done) return {
|
|
57
|
+
value: void 0,
|
|
58
|
+
done: true
|
|
59
|
+
};
|
|
60
|
+
const { ns, stream } = result.value;
|
|
61
|
+
if (ns.length === targetDepth && hasPrefix(ns, path)) return {
|
|
62
|
+
value: stream,
|
|
63
|
+
done: false
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
} };
|
|
67
|
+
} };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create the subgraph discovery transformer.
|
|
71
|
+
*
|
|
72
|
+
* Registering this transformer against a mux replaces the legacy
|
|
73
|
+
* inline behavior that previously lived in {@link StreamMux.push}.
|
|
74
|
+
* The mux no longer knows about the subgraph factory: instead, this
|
|
75
|
+
* transformer is the single component that materializes stream
|
|
76
|
+
* handles and announces them on `_discoveries`.
|
|
77
|
+
*
|
|
78
|
+
* Marked as a {@link NativeStreamTransformer} so the projection is
|
|
79
|
+
* treated as internal wiring (not merged into `run.extensions` and
|
|
80
|
+
* not auto-forwarded via {@link StreamMux.wireChannels}).
|
|
81
|
+
*
|
|
82
|
+
* @typeParam TStream - Concrete stream handle type produced by
|
|
83
|
+
* {@link SubgraphDiscoveryTransformerOptions.createStream}.
|
|
84
|
+
* Defaults to the base {@link StreamHandle} interface.
|
|
85
|
+
* @param mux - The mux whose `_discoveries` log should receive
|
|
86
|
+
* discovery entries and whose `register` will be called for each
|
|
87
|
+
* new stream handle.
|
|
88
|
+
* @param options - Factory and related wiring.
|
|
89
|
+
* @returns A native transformer that populates
|
|
90
|
+
* {@link StreamMux._discoveries} and exposes a root-scoped
|
|
91
|
+
* `subgraphs` iterable via its projection.
|
|
92
|
+
*/
|
|
93
|
+
function createSubgraphDiscoveryTransformer(mux, options) {
|
|
94
|
+
const { createStream } = options;
|
|
95
|
+
const seen = /* @__PURE__ */ new Set();
|
|
96
|
+
return {
|
|
97
|
+
__native: true,
|
|
98
|
+
init() {
|
|
99
|
+
return {
|
|
100
|
+
_discoveries: mux._discoveries,
|
|
101
|
+
subgraphs: filterSubgraphHandles(mux._discoveries, [], 0)
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
process(event) {
|
|
105
|
+
const ns = event.params.namespace;
|
|
106
|
+
if (ns.length === 0) return true;
|
|
107
|
+
const topNs = ns.slice(0, 1);
|
|
108
|
+
const topKey = nsKey(topNs);
|
|
109
|
+
if (seen.has(topKey)) return true;
|
|
110
|
+
seen.add(topKey);
|
|
111
|
+
const stream = createStream(topNs, mux._discoveries.size, mux._events.size);
|
|
112
|
+
mux.register(topNs, stream);
|
|
113
|
+
mux._discoveries.push({
|
|
114
|
+
ns: topNs,
|
|
115
|
+
stream
|
|
116
|
+
});
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//#endregion
|
|
122
|
+
export { createSubgraphDiscoveryTransformer, filterSubgraphHandles };
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=subgraphs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subgraphs.js","names":[],"sources":["../../../src/stream/transformers/subgraphs.ts"],"sourcesContent":["/**\n * SubgraphDiscoveryTransformer - materializes a {@link StreamHandle} for\n * each newly observed top-level subgraph namespace and announces it on\n * the mux's shared {@link StreamMux._discoveries} channel.\n *\n * Previously this work was inlined in {@link StreamMux.push}. Extracting\n * it into a transformer aligns discovery with the rest of the stream\n * architecture (lifecycle, values, messages are all transformers),\n * isolates the factory wiring, and makes discovery behavior\n * independently testable.\n *\n * The transformer also owns the read-side of discovery: it exposes an\n * `AsyncIterable<TStream>` projection (`subgraphs`) scoped to the root\n * namespace, and a {@link filterSubgraphHandles} helper that callers\n * can use to scope the same channel to any descendant namespace. This\n * lets `GraphRunStream` drop its bespoke `subscribeSubgraphs`\n * delegation and surface child streams via the standard native\n * projection pattern.\n *\n * Only first-level namespace segments are announced. Deeper segments\n * (e.g. `[\"researcher:uuid\", \"tools:uuid\"]`) are internal Pregel\n * checkpoint namespaces for nodes inside a subgraph and should not\n * appear as user-facing `SubgraphRunStream` instances; the mux still\n * resolves their values via its own `#streamMap` when registered\n * elsewhere.\n */\n\nimport { hasPrefix, nsKey } from \"../mux.js\";\nimport type { StreamHandle, StreamMux, SubgraphDiscovery } from \"../mux.js\";\nimport type {\n Namespace,\n NativeStreamTransformer,\n ProtocolEvent,\n} from \"../types.js\";\nimport type { StreamChannel } from \"../stream-channel.js\";\n\n/**\n * Projection returned by {@link createSubgraphDiscoveryTransformer}.\n *\n * @typeParam TStream - Concrete stream handle type produced by the\n * configured factory (e.g. `SubgraphRunStream`).\n */\nexport interface SubgraphDiscoveryProjection<\n TStream extends StreamHandle = StreamHandle,\n> {\n /**\n * Shared discovery channel on the mux. The transformer writes to it so\n * the channel's lifetime stays tied to the mux (closed on `mux.close()`\n * / failed on `mux.fail()`). The underscore prefix signals internal\n * wiring: consumers should iterate {@link subgraphs} instead.\n */\n _discoveries: StreamChannel<SubgraphDiscovery>;\n\n /**\n * Async iterable of direct child stream handles of the root\n * namespace. Wired onto `GraphRunStream.subgraphs` during root\n * stream construction. For descendant namespaces, use\n * {@link filterSubgraphHandles} to scope the same log.\n */\n subgraphs: AsyncIterable<TStream>;\n}\n\n/**\n * Configuration for {@link createSubgraphDiscoveryTransformer}.\n */\nexport interface SubgraphDiscoveryTransformerOptions<\n TStream extends StreamHandle = StreamHandle,\n> {\n /**\n * Factory invoked once per newly observed top-level namespace.\n *\n * Receives the discovery-channel and event-channel offsets so the resulting\n * stream can iterate only events arriving after the namespace was\n * first seen (no retroactive replay).\n *\n * @param path - The single-segment top-level namespace.\n * @param discoveryStart - Current size of the mux discovery log.\n * @param eventStart - Current size of the mux event log.\n * @returns A stream handle registered with the mux for values/error\n * resolution on close/fail.\n */\n createStream: (\n path: Namespace,\n discoveryStart: number,\n eventStart: number\n ) => TStream;\n}\n\n/**\n * Filter a {@link SubgraphDiscovery} channel to only the direct children\n * of a given namespace.\n *\n * Returns an `AsyncIterable` whose iterator yields stream handles for\n * discoveries whose namespace is exactly one segment deeper than\n * {@link path} and shares it as a prefix. Iteration begins at\n * {@link startAt} (so each caller picks up only discoveries added\n * after its construction) and terminates when the underlying log\n * closes or fails.\n *\n * @typeParam TStream - Concrete stream type recorded in the log.\n * Callers may cast if the log was populated by a specific factory.\n * @param log - The shared discovery channel (`mux._discoveries`).\n * @param path - Parent namespace whose direct children should be\n * yielded.\n * @param startAt - Zero-based index into the discovery log to begin\n * from.\n * @returns An async iterable of stream handles.\n */\nexport function filterSubgraphHandles<\n TStream extends StreamHandle = StreamHandle,\n>(\n log: StreamChannel<SubgraphDiscovery>,\n path: Namespace,\n startAt = 0\n): AsyncIterable<TStream> {\n const targetDepth = path.length + 1;\n return {\n [Symbol.asyncIterator](): AsyncIterator<TStream> {\n const base = log.iterate(startAt);\n return {\n async next(): Promise<IteratorResult<TStream>> {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const result = await base.next();\n if (result.done) {\n return { value: undefined as unknown as TStream, done: true };\n }\n const { ns, stream } = result.value;\n if (ns.length === targetDepth && hasPrefix(ns, path)) {\n return { value: stream as TStream, done: false };\n }\n }\n },\n };\n },\n };\n}\n\n/**\n * Create the subgraph discovery transformer.\n *\n * Registering this transformer against a mux replaces the legacy\n * inline behavior that previously lived in {@link StreamMux.push}.\n * The mux no longer knows about the subgraph factory: instead, this\n * transformer is the single component that materializes stream\n * handles and announces them on `_discoveries`.\n *\n * Marked as a {@link NativeStreamTransformer} so the projection is\n * treated as internal wiring (not merged into `run.extensions` and\n * not auto-forwarded via {@link StreamMux.wireChannels}).\n *\n * @typeParam TStream - Concrete stream handle type produced by\n * {@link SubgraphDiscoveryTransformerOptions.createStream}.\n * Defaults to the base {@link StreamHandle} interface.\n * @param mux - The mux whose `_discoveries` log should receive\n * discovery entries and whose `register` will be called for each\n * new stream handle.\n * @param options - Factory and related wiring.\n * @returns A native transformer that populates\n * {@link StreamMux._discoveries} and exposes a root-scoped\n * `subgraphs` iterable via its projection.\n */\nexport function createSubgraphDiscoveryTransformer<\n TStream extends StreamHandle = StreamHandle,\n>(\n mux: StreamMux,\n options: SubgraphDiscoveryTransformerOptions<TStream>\n): NativeStreamTransformer<SubgraphDiscoveryProjection<TStream>> {\n const { createStream } = options;\n const seen = new Set<string>();\n\n return {\n __native: true,\n\n init() {\n return {\n _discoveries: mux._discoveries,\n subgraphs: filterSubgraphHandles<TStream>(mux._discoveries, [], 0),\n };\n },\n\n process(event: ProtocolEvent): boolean {\n const ns = event.params.namespace;\n if (ns.length === 0) return true;\n\n const topNs = ns.slice(0, 1);\n const topKey = nsKey(topNs);\n if (seen.has(topKey)) return true;\n seen.add(topKey);\n\n const stream = createStream(\n topNs,\n mux._discoveries.size,\n mux._events.size\n );\n mux.register(topNs, stream);\n mux._discoveries.push({ ns: topNs, stream });\n return true;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4GA,SAAgB,sBAGd,KACA,MACA,UAAU,GACc;CACxB,MAAM,cAAc,KAAK,SAAS;AAClC,QAAO,EACL,CAAC,OAAO,iBAAyC;EAC/C,MAAM,OAAO,IAAI,QAAQ,QAAQ;AACjC,SAAO,EACL,MAAM,OAAyC;AAE7C,UAAO,MAAM;IACX,MAAM,SAAS,MAAM,KAAK,MAAM;AAChC,QAAI,OAAO,KACT,QAAO;KAAE,OAAO,KAAA;KAAiC,MAAM;KAAM;IAE/D,MAAM,EAAE,IAAI,WAAW,OAAO;AAC9B,QAAI,GAAG,WAAW,eAAe,UAAU,IAAI,KAAK,CAClD,QAAO;KAAE,OAAO;KAAmB,MAAM;KAAO;;KAIvD;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BH,SAAgB,mCAGd,KACA,SAC+D;CAC/D,MAAM,EAAE,iBAAiB;CACzB,MAAM,uBAAO,IAAI,KAAa;AAE9B,QAAO;EACL,UAAU;EAEV,OAAO;AACL,UAAO;IACL,cAAc,IAAI;IAClB,WAAW,sBAA+B,IAAI,cAAc,EAAE,EAAE,EAAE;IACnE;;EAGH,QAAQ,OAA+B;GACrC,MAAM,KAAK,MAAM,OAAO;AACxB,OAAI,GAAG,WAAW,EAAG,QAAO;GAE5B,MAAM,QAAQ,GAAG,MAAM,GAAG,EAAE;GAC5B,MAAM,SAAS,MAAM,MAAM;AAC3B,OAAI,KAAK,IAAI,OAAO,CAAE,QAAO;AAC7B,QAAK,IAAI,OAAO;GAEhB,MAAM,SAAS,aACb,OACA,IAAI,aAAa,MACjB,IAAI,QAAQ,KACb;AACD,OAAI,SAAS,OAAO,OAAO;AAC3B,OAAI,aAAa,KAAK;IAAE,IAAI;IAAO;IAAQ,CAAC;AAC5C,UAAO;;EAEV"}
|