@langchain/langgraph 1.2.8 → 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.
Files changed (166) hide show
  1. package/dist/graph/graph.cjs +6 -2
  2. package/dist/graph/graph.cjs.map +1 -1
  3. package/dist/graph/graph.d.cts +58 -7
  4. package/dist/graph/graph.d.cts.map +1 -1
  5. package/dist/graph/graph.d.ts +58 -7
  6. package/dist/graph/graph.d.ts.map +1 -1
  7. package/dist/graph/graph.js +6 -2
  8. package/dist/graph/graph.js.map +1 -1
  9. package/dist/graph/index.d.ts +3 -3
  10. package/dist/graph/state.cjs +3 -2
  11. package/dist/graph/state.cjs.map +1 -1
  12. package/dist/graph/state.d.cts +14 -6
  13. package/dist/graph/state.d.cts.map +1 -1
  14. package/dist/graph/state.d.ts +14 -6
  15. package/dist/graph/state.d.ts.map +1 -1
  16. package/dist/graph/state.js +3 -2
  17. package/dist/graph/state.js.map +1 -1
  18. package/dist/index.cjs +34 -5
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +16 -6
  21. package/dist/index.d.ts +16 -6
  22. package/dist/index.js +10 -1
  23. package/dist/index.js.map +1 -1
  24. package/dist/prebuilt/agent_executor.d.cts +1 -1
  25. package/dist/prebuilt/agent_executor.d.ts +1 -1
  26. package/dist/pregel/algo.cjs +6 -3
  27. package/dist/pregel/algo.cjs.map +1 -1
  28. package/dist/pregel/algo.js +6 -3
  29. package/dist/pregel/algo.js.map +1 -1
  30. package/dist/pregel/index.cjs +96 -25
  31. package/dist/pregel/index.cjs.map +1 -1
  32. package/dist/pregel/index.d.cts +25 -3
  33. package/dist/pregel/index.d.cts.map +1 -1
  34. package/dist/pregel/index.d.ts +25 -3
  35. package/dist/pregel/index.d.ts.map +1 -1
  36. package/dist/pregel/index.js +97 -26
  37. package/dist/pregel/index.js.map +1 -1
  38. package/dist/pregel/loop.cjs +51 -10
  39. package/dist/pregel/loop.cjs.map +1 -1
  40. package/dist/pregel/loop.js +51 -10
  41. package/dist/pregel/loop.js.map +1 -1
  42. package/dist/pregel/messages-v2.cjs +231 -0
  43. package/dist/pregel/messages-v2.cjs.map +1 -0
  44. package/dist/pregel/messages-v2.js +231 -0
  45. package/dist/pregel/messages-v2.js.map +1 -0
  46. package/dist/pregel/messages.cjs +14 -10
  47. package/dist/pregel/messages.cjs.map +1 -1
  48. package/dist/pregel/messages.js +14 -10
  49. package/dist/pregel/messages.js.map +1 -1
  50. package/dist/pregel/remote.cjs +15 -0
  51. package/dist/pregel/remote.cjs.map +1 -1
  52. package/dist/pregel/remote.d.cts.map +1 -1
  53. package/dist/pregel/remote.d.ts.map +1 -1
  54. package/dist/pregel/remote.js +15 -0
  55. package/dist/pregel/remote.js.map +1 -1
  56. package/dist/pregel/stream.cjs.map +1 -1
  57. package/dist/pregel/stream.d.cts +30 -0
  58. package/dist/pregel/stream.d.cts.map +1 -0
  59. package/dist/pregel/stream.d.ts +30 -1
  60. package/dist/pregel/stream.d.ts.map +1 -0
  61. package/dist/pregel/stream.js.map +1 -1
  62. package/dist/pregel/types.cjs.map +1 -1
  63. package/dist/pregel/types.d.cts +8 -1
  64. package/dist/pregel/types.d.cts.map +1 -1
  65. package/dist/pregel/types.d.ts +8 -1
  66. package/dist/pregel/types.d.ts.map +1 -1
  67. package/dist/pregel/types.js.map +1 -1
  68. package/dist/pregel/utils/config.cjs +21 -4
  69. package/dist/pregel/utils/config.cjs.map +1 -1
  70. package/dist/pregel/utils/config.d.cts.map +1 -1
  71. package/dist/pregel/utils/config.d.ts.map +1 -1
  72. package/dist/pregel/utils/config.js +21 -5
  73. package/dist/pregel/utils/config.js.map +1 -1
  74. package/dist/pregel/utils/index.d.ts +0 -1
  75. package/dist/pregel/utils/index.d.ts.map +1 -1
  76. package/dist/state/index.d.ts +1 -1
  77. package/dist/state/schema.d.cts +1 -1
  78. package/dist/state/schema.d.ts +1 -1
  79. package/dist/stream/convert.cjs +207 -0
  80. package/dist/stream/convert.cjs.map +1 -0
  81. package/dist/stream/convert.d.cts +69 -0
  82. package/dist/stream/convert.d.cts.map +1 -0
  83. package/dist/stream/convert.d.ts +69 -0
  84. package/dist/stream/convert.d.ts.map +1 -0
  85. package/dist/stream/convert.js +206 -0
  86. package/dist/stream/convert.js.map +1 -0
  87. package/dist/stream/index.cjs +11 -0
  88. package/dist/stream/index.d.cts +12 -0
  89. package/dist/stream/index.d.ts +12 -0
  90. package/dist/stream/index.js +12 -0
  91. package/dist/stream/mux.cjs +350 -0
  92. package/dist/stream/mux.cjs.map +1 -0
  93. package/dist/stream/mux.d.cts +160 -0
  94. package/dist/stream/mux.d.cts.map +1 -0
  95. package/dist/stream/mux.d.ts +160 -0
  96. package/dist/stream/mux.d.ts.map +1 -0
  97. package/dist/stream/mux.js +345 -0
  98. package/dist/stream/mux.js.map +1 -0
  99. package/dist/stream/run-stream.cjs +439 -0
  100. package/dist/stream/run-stream.cjs.map +1 -0
  101. package/dist/stream/run-stream.d.cts +286 -0
  102. package/dist/stream/run-stream.d.cts.map +1 -0
  103. package/dist/stream/run-stream.d.ts +285 -0
  104. package/dist/stream/run-stream.d.ts.map +1 -0
  105. package/dist/stream/run-stream.js +434 -0
  106. package/dist/stream/run-stream.js.map +1 -0
  107. package/dist/stream/stream-channel.cjs +208 -0
  108. package/dist/stream/stream-channel.cjs.map +1 -0
  109. package/dist/stream/stream-channel.d.cts +129 -0
  110. package/dist/stream/stream-channel.d.cts.map +1 -0
  111. package/dist/stream/stream-channel.d.ts +129 -0
  112. package/dist/stream/stream-channel.d.ts.map +1 -0
  113. package/dist/stream/stream-channel.js +207 -0
  114. package/dist/stream/stream-channel.js.map +1 -0
  115. package/dist/stream/transformers/index.cjs +4 -0
  116. package/dist/stream/transformers/index.d.ts +5 -0
  117. package/dist/stream/transformers/index.js +5 -0
  118. package/dist/stream/transformers/lifecycle.cjs +326 -0
  119. package/dist/stream/transformers/lifecycle.cjs.map +1 -0
  120. package/dist/stream/transformers/lifecycle.d.cts +53 -0
  121. package/dist/stream/transformers/lifecycle.d.cts.map +1 -0
  122. package/dist/stream/transformers/lifecycle.d.ts +53 -0
  123. package/dist/stream/transformers/lifecycle.d.ts.map +1 -0
  124. package/dist/stream/transformers/lifecycle.js +325 -0
  125. package/dist/stream/transformers/lifecycle.js.map +1 -0
  126. package/dist/stream/transformers/messages.cjs +94 -0
  127. package/dist/stream/transformers/messages.cjs.map +1 -0
  128. package/dist/stream/transformers/messages.d.cts +23 -0
  129. package/dist/stream/transformers/messages.d.cts.map +1 -0
  130. package/dist/stream/transformers/messages.d.ts +23 -0
  131. package/dist/stream/transformers/messages.d.ts.map +1 -0
  132. package/dist/stream/transformers/messages.js +94 -0
  133. package/dist/stream/transformers/messages.js.map +1 -0
  134. package/dist/stream/transformers/subgraphs.cjs +125 -0
  135. package/dist/stream/transformers/subgraphs.cjs.map +1 -0
  136. package/dist/stream/transformers/subgraphs.d.cts +95 -0
  137. package/dist/stream/transformers/subgraphs.d.cts.map +1 -0
  138. package/dist/stream/transformers/subgraphs.d.ts +95 -0
  139. package/dist/stream/transformers/subgraphs.d.ts.map +1 -0
  140. package/dist/stream/transformers/subgraphs.js +124 -0
  141. package/dist/stream/transformers/subgraphs.js.map +1 -0
  142. package/dist/stream/transformers/types.d.cts +89 -0
  143. package/dist/stream/transformers/types.d.cts.map +1 -0
  144. package/dist/stream/transformers/types.d.ts +89 -0
  145. package/dist/stream/transformers/types.d.ts.map +1 -0
  146. package/dist/stream/transformers/values.cjs +39 -0
  147. package/dist/stream/transformers/values.cjs.map +1 -0
  148. package/dist/stream/transformers/values.d.cts +21 -0
  149. package/dist/stream/transformers/values.d.cts.map +1 -0
  150. package/dist/stream/transformers/values.d.ts +21 -0
  151. package/dist/stream/transformers/values.d.ts.map +1 -0
  152. package/dist/stream/transformers/values.js +39 -0
  153. package/dist/stream/transformers/values.js.map +1 -0
  154. package/dist/stream/types.cjs +11 -0
  155. package/dist/stream/types.cjs.map +1 -0
  156. package/dist/stream/types.d.cts +255 -0
  157. package/dist/stream/types.d.cts.map +1 -0
  158. package/dist/stream/types.d.ts +255 -0
  159. package/dist/stream/types.d.ts.map +1 -0
  160. package/dist/stream/types.js +11 -0
  161. package/dist/stream/types.js.map +1 -0
  162. package/dist/web.cjs +39 -9
  163. package/dist/web.d.cts +16 -6
  164. package/dist/web.d.ts +16 -6
  165. package/dist/web.js +10 -1
  166. 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"}