@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.
Files changed (141) 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 +1 -1
  10. package/dist/graph/state.cjs +3 -2
  11. package/dist/graph/state.cjs.map +1 -1
  12. package/dist/graph/state.d.cts +13 -5
  13. package/dist/graph/state.d.cts.map +1 -1
  14. package/dist/graph/state.d.ts +13 -5
  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 +12 -2
  21. package/dist/index.d.ts +12 -2
  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/index.cjs +69 -25
  27. package/dist/pregel/index.cjs.map +1 -1
  28. package/dist/pregel/index.d.cts +25 -3
  29. package/dist/pregel/index.d.cts.map +1 -1
  30. package/dist/pregel/index.d.ts +25 -3
  31. package/dist/pregel/index.d.ts.map +1 -1
  32. package/dist/pregel/index.js +69 -25
  33. package/dist/pregel/index.js.map +1 -1
  34. package/dist/pregel/loop.cjs +51 -10
  35. package/dist/pregel/loop.cjs.map +1 -1
  36. package/dist/pregel/loop.js +51 -10
  37. package/dist/pregel/loop.js.map +1 -1
  38. package/dist/pregel/messages-v2.cjs +231 -0
  39. package/dist/pregel/messages-v2.cjs.map +1 -0
  40. package/dist/pregel/messages-v2.js +231 -0
  41. package/dist/pregel/messages-v2.js.map +1 -0
  42. package/dist/pregel/stream.cjs.map +1 -1
  43. package/dist/pregel/stream.d.cts +30 -0
  44. package/dist/pregel/stream.d.cts.map +1 -0
  45. package/dist/pregel/stream.d.ts +30 -1
  46. package/dist/pregel/stream.d.ts.map +1 -0
  47. package/dist/pregel/stream.js.map +1 -1
  48. package/dist/pregel/types.cjs.map +1 -1
  49. package/dist/pregel/types.d.cts +8 -1
  50. package/dist/pregel/types.d.cts.map +1 -1
  51. package/dist/pregel/types.d.ts +8 -1
  52. package/dist/pregel/types.d.ts.map +1 -1
  53. package/dist/pregel/types.js.map +1 -1
  54. package/dist/stream/convert.cjs +207 -0
  55. package/dist/stream/convert.cjs.map +1 -0
  56. package/dist/stream/convert.d.cts +69 -0
  57. package/dist/stream/convert.d.cts.map +1 -0
  58. package/dist/stream/convert.d.ts +69 -0
  59. package/dist/stream/convert.d.ts.map +1 -0
  60. package/dist/stream/convert.js +206 -0
  61. package/dist/stream/convert.js.map +1 -0
  62. package/dist/stream/index.cjs +11 -0
  63. package/dist/stream/index.d.cts +12 -0
  64. package/dist/stream/index.d.ts +12 -0
  65. package/dist/stream/index.js +12 -0
  66. package/dist/stream/mux.cjs +350 -0
  67. package/dist/stream/mux.cjs.map +1 -0
  68. package/dist/stream/mux.d.cts +160 -0
  69. package/dist/stream/mux.d.cts.map +1 -0
  70. package/dist/stream/mux.d.ts +160 -0
  71. package/dist/stream/mux.d.ts.map +1 -0
  72. package/dist/stream/mux.js +345 -0
  73. package/dist/stream/mux.js.map +1 -0
  74. package/dist/stream/run-stream.cjs +439 -0
  75. package/dist/stream/run-stream.cjs.map +1 -0
  76. package/dist/stream/run-stream.d.cts +286 -0
  77. package/dist/stream/run-stream.d.cts.map +1 -0
  78. package/dist/stream/run-stream.d.ts +285 -0
  79. package/dist/stream/run-stream.d.ts.map +1 -0
  80. package/dist/stream/run-stream.js +434 -0
  81. package/dist/stream/run-stream.js.map +1 -0
  82. package/dist/stream/stream-channel.cjs +208 -0
  83. package/dist/stream/stream-channel.cjs.map +1 -0
  84. package/dist/stream/stream-channel.d.cts +129 -0
  85. package/dist/stream/stream-channel.d.cts.map +1 -0
  86. package/dist/stream/stream-channel.d.ts +129 -0
  87. package/dist/stream/stream-channel.d.ts.map +1 -0
  88. package/dist/stream/stream-channel.js +207 -0
  89. package/dist/stream/stream-channel.js.map +1 -0
  90. package/dist/stream/transformers/index.cjs +4 -0
  91. package/dist/stream/transformers/index.d.ts +5 -0
  92. package/dist/stream/transformers/index.js +5 -0
  93. package/dist/stream/transformers/lifecycle.cjs +326 -0
  94. package/dist/stream/transformers/lifecycle.cjs.map +1 -0
  95. package/dist/stream/transformers/lifecycle.d.cts +53 -0
  96. package/dist/stream/transformers/lifecycle.d.cts.map +1 -0
  97. package/dist/stream/transformers/lifecycle.d.ts +53 -0
  98. package/dist/stream/transformers/lifecycle.d.ts.map +1 -0
  99. package/dist/stream/transformers/lifecycle.js +325 -0
  100. package/dist/stream/transformers/lifecycle.js.map +1 -0
  101. package/dist/stream/transformers/messages.cjs +94 -0
  102. package/dist/stream/transformers/messages.cjs.map +1 -0
  103. package/dist/stream/transformers/messages.d.cts +23 -0
  104. package/dist/stream/transformers/messages.d.cts.map +1 -0
  105. package/dist/stream/transformers/messages.d.ts +23 -0
  106. package/dist/stream/transformers/messages.d.ts.map +1 -0
  107. package/dist/stream/transformers/messages.js +94 -0
  108. package/dist/stream/transformers/messages.js.map +1 -0
  109. package/dist/stream/transformers/subgraphs.cjs +125 -0
  110. package/dist/stream/transformers/subgraphs.cjs.map +1 -0
  111. package/dist/stream/transformers/subgraphs.d.cts +95 -0
  112. package/dist/stream/transformers/subgraphs.d.cts.map +1 -0
  113. package/dist/stream/transformers/subgraphs.d.ts +95 -0
  114. package/dist/stream/transformers/subgraphs.d.ts.map +1 -0
  115. package/dist/stream/transformers/subgraphs.js +124 -0
  116. package/dist/stream/transformers/subgraphs.js.map +1 -0
  117. package/dist/stream/transformers/types.d.cts +89 -0
  118. package/dist/stream/transformers/types.d.cts.map +1 -0
  119. package/dist/stream/transformers/types.d.ts +89 -0
  120. package/dist/stream/transformers/types.d.ts.map +1 -0
  121. package/dist/stream/transformers/values.cjs +39 -0
  122. package/dist/stream/transformers/values.cjs.map +1 -0
  123. package/dist/stream/transformers/values.d.cts +21 -0
  124. package/dist/stream/transformers/values.d.cts.map +1 -0
  125. package/dist/stream/transformers/values.d.ts +21 -0
  126. package/dist/stream/transformers/values.d.ts.map +1 -0
  127. package/dist/stream/transformers/values.js +39 -0
  128. package/dist/stream/transformers/values.js.map +1 -0
  129. package/dist/stream/types.cjs +11 -0
  130. package/dist/stream/types.cjs.map +1 -0
  131. package/dist/stream/types.d.cts +255 -0
  132. package/dist/stream/types.d.cts.map +1 -0
  133. package/dist/stream/types.d.ts +255 -0
  134. package/dist/stream/types.d.ts.map +1 -0
  135. package/dist/stream/types.js +11 -0
  136. package/dist/stream/types.js.map +1 -0
  137. package/dist/web.cjs +39 -9
  138. package/dist/web.d.cts +12 -2
  139. package/dist/web.d.ts +12 -2
  140. package/dist/web.js +10 -1
  141. package/package.json +9 -8
@@ -0,0 +1,206 @@
1
+ //#region src/stream/convert.ts
2
+ /**
3
+ * The set of stream modes requested by
4
+ * `streamEvents(..., { version: "v3" })` — every mode the protocol maps
5
+ * to a channel.
6
+ *
7
+ * The verbose `"debug"` mode is intentionally excluded: it was a thin
8
+ * re-wrap of `checkpoints` + `tasks` carrying no new information.
9
+ *
10
+ * The `"checkpoints"` mode is likewise excluded from the stream-mode
11
+ * request because the protocol's `checkpoints` channel carries only a
12
+ * lightweight envelope (`id`, `parent_id`, `step`, `source`) derived from
13
+ * {@link StreamChunkMeta.checkpoint} on the adjacent `values` chunk — not
14
+ * the full-state shape that Pregel's `checkpoints` stream mode produces.
15
+ * `convertToProtocolEvent` emits a companion `checkpoints` protocol event
16
+ * next to each `values` event when meta is present, so clients can build
17
+ * branching/time-travel UIs without a full-state `checkpoints` subscription.
18
+ */
19
+ const STREAM_EVENTS_V3_MODES = [
20
+ "values",
21
+ "updates",
22
+ "messages",
23
+ "tools",
24
+ "custom",
25
+ "tasks"
26
+ ];
27
+ function unwrapMessagesPayload(payload) {
28
+ if (!Array.isArray(payload) || payload.length !== 2) return { data: payload };
29
+ const [data, metadata] = payload;
30
+ if (metadata == null || typeof metadata !== "object") return { data: payload };
31
+ const record = metadata;
32
+ const node = typeof record.langgraph_node === "string" ? record.langgraph_node : void 0;
33
+ const runId = typeof record.run_id === "string" ? record.run_id : void 0;
34
+ return {
35
+ data: runId != null && data != null && typeof data === "object" ? {
36
+ ...data,
37
+ run_id: runId
38
+ } : data,
39
+ node
40
+ };
41
+ }
42
+ function convertToProtocolEvent({ namespace: ns, mode, payload, seq, meta }) {
43
+ const timestamp = Date.now();
44
+ const base = { type: "event" };
45
+ switch (mode) {
46
+ case "messages": {
47
+ const { data, node } = unwrapMessagesPayload(payload);
48
+ return [{
49
+ ...base,
50
+ seq,
51
+ method: "messages",
52
+ params: {
53
+ namespace: ns,
54
+ timestamp,
55
+ ...node ? { node } : {},
56
+ data
57
+ }
58
+ }];
59
+ }
60
+ case "tools": return [{
61
+ ...base,
62
+ seq,
63
+ method: "tools",
64
+ params: {
65
+ namespace: ns,
66
+ timestamp,
67
+ data: convertToolsPayload(payload)
68
+ }
69
+ }];
70
+ case "values": {
71
+ const events = [];
72
+ if (meta?.checkpoint != null) events.push({
73
+ ...base,
74
+ seq,
75
+ method: "checkpoints",
76
+ params: {
77
+ namespace: ns,
78
+ timestamp,
79
+ data: meta.checkpoint
80
+ }
81
+ });
82
+ events.push({
83
+ ...base,
84
+ seq: meta?.checkpoint != null ? seq + 1 : seq,
85
+ method: "values",
86
+ params: {
87
+ namespace: ns,
88
+ timestamp,
89
+ data: payload
90
+ }
91
+ });
92
+ return events;
93
+ }
94
+ case "updates": {
95
+ const data = convertUpdatesPayload(payload);
96
+ return [{
97
+ ...base,
98
+ seq,
99
+ method: "updates",
100
+ params: {
101
+ namespace: ns,
102
+ timestamp,
103
+ ...typeof data.node === "string" ? { node: data.node } : {},
104
+ data
105
+ }
106
+ }];
107
+ }
108
+ case "custom": {
109
+ const data = typeof payload === "object" && payload !== null && !Array.isArray(payload) && "name" in payload ? payload : { payload };
110
+ return [{
111
+ ...base,
112
+ seq,
113
+ method: "custom",
114
+ params: {
115
+ namespace: ns,
116
+ timestamp,
117
+ data
118
+ }
119
+ }];
120
+ }
121
+ case "tasks": return [{
122
+ ...base,
123
+ seq,
124
+ method: "tasks",
125
+ params: {
126
+ namespace: ns,
127
+ timestamp,
128
+ data: payload
129
+ }
130
+ }];
131
+ default: return [];
132
+ }
133
+ }
134
+ /**
135
+ * Normalises a raw tools-mode payload into a typed {@link ToolsEventData}
136
+ * discriminated union, mapping internal lifecycle events (`on_tool_start`,
137
+ * `on_tool_end`, etc.) to their protocol counterparts.
138
+ *
139
+ * @param payload - The raw payload from a `"tools"` stream chunk.
140
+ * @returns A {@link ToolsEventData} object with the appropriate `event`
141
+ * discriminant and associated fields.
142
+ */
143
+ function convertToolsPayload(payload) {
144
+ if (typeof payload !== "object" || payload === null) return {
145
+ event: "tool-error",
146
+ tool_call_id: "",
147
+ message: "Unexpected tools payload shape"
148
+ };
149
+ const p = payload;
150
+ const tool_call_id = String(p.toolCallId ?? "");
151
+ switch (p.event) {
152
+ case "on_tool_start": return {
153
+ event: "tool-started",
154
+ tool_call_id,
155
+ tool_name: String(p.name ?? "unknown"),
156
+ input: p.input
157
+ };
158
+ case "on_tool_event": return {
159
+ event: "tool-output-delta",
160
+ tool_call_id,
161
+ delta: typeof p.data === "string" ? p.data : JSON.stringify(p.data ?? "")
162
+ };
163
+ case "on_tool_end": return {
164
+ event: "tool-finished",
165
+ tool_call_id,
166
+ output: p.output
167
+ };
168
+ case "on_tool_error": {
169
+ const err = p.error;
170
+ return {
171
+ event: "tool-error",
172
+ tool_call_id,
173
+ message: typeof err === "object" && err !== null && "message" in err && typeof err.message === "string" ? err.message : String(err ?? "unknown error")
174
+ };
175
+ }
176
+ default: return {
177
+ event: "tool-error",
178
+ tool_call_id: "",
179
+ message: `Unknown tool event: ${String(p.event)}`
180
+ };
181
+ }
182
+ }
183
+ /**
184
+ * Extracts the first `{node: delta}` entry from an updates-mode payload and
185
+ * reshapes it into an {@link UpdatesEventData} with explicit `node` and
186
+ * `values` fields. Non-object payloads are coerced to `{ values: {} }`.
187
+ *
188
+ * @param payload - The raw payload from an `"updates"` stream chunk,
189
+ * expected to be a `Record<string, unknown>` keyed by node name.
190
+ * @returns An {@link UpdatesEventData} containing the extracted node name
191
+ * and its associated delta values.
192
+ */
193
+ function convertUpdatesPayload(payload) {
194
+ if (typeof payload !== "object" || payload === null) return { values: {} };
195
+ const entries = Object.entries(payload);
196
+ if (entries.length === 0) return { values: {} };
197
+ const [node, values] = entries[0];
198
+ return {
199
+ node,
200
+ values: typeof values === "object" && values !== null ? values : { value: values }
201
+ };
202
+ }
203
+ //#endregion
204
+ export { STREAM_EVENTS_V3_MODES, convertToProtocolEvent };
205
+
206
+ //# sourceMappingURL=convert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.js","names":[],"sources":["../../src/stream/convert.ts"],"sourcesContent":["/**\n * Protocol event conversion — maps raw `[ns, mode, payload, meta?]` stream\n * chunks from graph.stream() to CDDL-aligned ProtocolEvents.\n */\n\nimport type { StreamMode } from \"../pregel/types.js\";\nimport type { StreamChunkMeta } from \"../pregel/stream.js\";\nimport type {\n Namespace,\n ProtocolEvent,\n ToolsEventData,\n UpdatesEventData,\n} from \"./types.js\";\n\n/**\n * The set of stream modes requested by\n * `streamEvents(..., { version: \"v3\" })` — every mode the protocol maps\n * to a channel.\n *\n * The verbose `\"debug\"` mode is intentionally excluded: it was a thin\n * re-wrap of `checkpoints` + `tasks` carrying no new information.\n *\n * The `\"checkpoints\"` mode is likewise excluded from the stream-mode\n * request because the protocol's `checkpoints` channel carries only a\n * lightweight envelope (`id`, `parent_id`, `step`, `source`) derived from\n * {@link StreamChunkMeta.checkpoint} on the adjacent `values` chunk — not\n * the full-state shape that Pregel's `checkpoints` stream mode produces.\n * `convertToProtocolEvent` emits a companion `checkpoints` protocol event\n * next to each `values` event when meta is present, so clients can build\n * branching/time-travel UIs without a full-state `checkpoints` subscription.\n */\nexport const STREAM_EVENTS_V3_MODES: StreamMode[] = [\n \"values\",\n \"updates\",\n \"messages\",\n \"tools\",\n \"custom\",\n \"tasks\",\n];\n\n/**\n * Converts a raw `[ns, mode, payload, meta?]` stream chunk emitted by\n * `graph.stream()` into one or more CDDL-aligned {@link ProtocolEvent}s.\n *\n * Most modes produce a single event. `values` chunks carrying\n * {@link StreamChunkMeta.checkpoint} additionally produce a companion\n * `checkpoints` event immediately after the `values` event, so clients\n * that subscribe only to `checkpoints` can build a branching timeline\n * without also paying for full-state `values` payloads, and clients that\n * subscribe to both can correlate the pair by `(namespace, step)` or by\n * adjacent `seq` numbers.\n *\n * Returns an empty array for stream modes that have no protocol mapping.\n *\n * @param options - Conversion inputs for a single raw stream chunk.\n * @param options.namespace - Hierarchical namespace path identifying the\n * source in the agent tree.\n * @param options.mode - The stream mode that produced this chunk (e.g.\n * `\"messages\"`, `\"tools\"`).\n * @param options.payload - The raw payload emitted by the stream for this\n * mode.\n * @param options.seq - Monotonically increasing sequence number assigned to\n * the first returned event; the companion `checkpoints` event (when\n * emitted) uses `seq + 1`.\n * @param options.meta - Optional chunk-level metadata (e.g. the checkpoint\n * envelope paired with a `values` chunk).\n * @returns An ordered list of {@link ProtocolEvent}s ready for downstream\n * reducers. Callers advance their `seq` counter by `result.length`.\n */\nexport interface ConvertToProtocolEventOptions {\n namespace: Namespace;\n mode: StreamMode;\n payload: unknown;\n seq: number;\n meta?: StreamChunkMeta;\n}\n\nfunction unwrapMessagesPayload(payload: unknown) {\n if (!Array.isArray(payload) || payload.length !== 2) {\n return { data: payload };\n }\n\n const [data, metadata] = payload;\n if (metadata == null || typeof metadata !== \"object\") {\n return { data: payload };\n }\n\n const record = metadata as Record<string, unknown>;\n const node =\n typeof record.langgraph_node === \"string\"\n ? record.langgraph_node\n : undefined;\n const runId = typeof record.run_id === \"string\" ? record.run_id : undefined;\n const dataWithRunId =\n runId != null && data != null && typeof data === \"object\"\n ? { ...(data as Record<string, unknown>), run_id: runId }\n : data;\n\n return { data: dataWithRunId, node };\n}\n\nexport function convertToProtocolEvent({\n namespace: ns,\n mode,\n payload,\n seq,\n meta,\n}: ConvertToProtocolEventOptions): ProtocolEvent[] {\n const timestamp = Date.now();\n const base = { type: \"event\" as const };\n\n switch (mode) {\n case \"messages\": {\n const { data, node } = unwrapMessagesPayload(payload);\n return [\n {\n ...base,\n seq,\n method: \"messages\",\n params: { namespace: ns, timestamp, ...(node ? { node } : {}), data },\n },\n ];\n }\n\n case \"tools\":\n return [\n {\n ...base,\n seq,\n method: \"tools\",\n params: {\n namespace: ns,\n timestamp,\n data: convertToolsPayload(payload),\n },\n },\n ];\n\n case \"values\": {\n // Emit the `checkpoints` event immediately BEFORE its companion\n // `values` event so clients subscribed to both channels have the\n // envelope buffered by the time the values payload arrives. This\n // lets the SDK attach `parentCheckpointId` to messages extracted\n // from the values snapshot without waiting for a second pass.\n const events: ProtocolEvent[] = [];\n if (meta?.checkpoint != null) {\n events.push({\n ...base,\n seq,\n method: \"checkpoints\",\n params: { namespace: ns, timestamp, data: meta.checkpoint },\n });\n }\n events.push({\n ...base,\n seq: meta?.checkpoint != null ? seq + 1 : seq,\n method: \"values\",\n params: { namespace: ns, timestamp, data: payload },\n });\n return events;\n }\n\n case \"updates\": {\n const data = convertUpdatesPayload(payload);\n return [\n {\n ...base,\n seq,\n method: \"updates\",\n params: {\n namespace: ns,\n timestamp,\n // Surface the completed node at the top level of `params` so\n // transformers (notably `LifecycleTransformer`) can attribute\n // a finished task to its child namespace without re-parsing\n // the payload. The same value is retained inside `data` for\n // downstream consumers that inspect the event body.\n ...(typeof data.node === \"string\" ? { node: data.node } : {}),\n data,\n },\n },\n ];\n }\n\n case \"custom\": {\n const data =\n typeof payload === \"object\" &&\n payload !== null &&\n !Array.isArray(payload) &&\n \"name\" in payload\n ? payload\n : { payload };\n return [\n {\n ...base,\n seq,\n method: \"custom\",\n params: { namespace: ns, timestamp, data },\n },\n ];\n }\n\n case \"tasks\":\n return [\n {\n ...base,\n seq,\n method: \"tasks\",\n params: { namespace: ns, timestamp, data: payload },\n },\n ];\n\n default:\n return [];\n }\n}\n\n/**\n * Normalises a raw tools-mode payload into a typed {@link ToolsEventData}\n * discriminated union, mapping internal lifecycle events (`on_tool_start`,\n * `on_tool_end`, etc.) to their protocol counterparts.\n *\n * @param payload - The raw payload from a `\"tools\"` stream chunk.\n * @returns A {@link ToolsEventData} object with the appropriate `event`\n * discriminant and associated fields.\n */\nfunction convertToolsPayload(payload: unknown): ToolsEventData {\n if (typeof payload !== \"object\" || payload === null) {\n return {\n event: \"tool-error\",\n tool_call_id: \"\",\n message: \"Unexpected tools payload shape\",\n };\n }\n\n const p = payload as Record<string, unknown>;\n const tool_call_id = String(p.toolCallId ?? \"\");\n\n switch (p.event) {\n case \"on_tool_start\":\n return {\n event: \"tool-started\",\n tool_call_id,\n tool_name: String(p.name ?? \"unknown\"),\n input: p.input,\n };\n\n case \"on_tool_event\": {\n const delta =\n typeof p.data === \"string\" ? p.data : JSON.stringify(p.data ?? \"\");\n return {\n event: \"tool-output-delta\",\n tool_call_id,\n delta,\n };\n }\n\n case \"on_tool_end\":\n return {\n event: \"tool-finished\",\n tool_call_id,\n output: p.output,\n };\n\n case \"on_tool_error\": {\n const err = p.error;\n const errMessage =\n typeof err === \"object\" &&\n err !== null &&\n \"message\" in err &&\n typeof (err as { message: unknown }).message === \"string\"\n ? (err as { message: string }).message\n : String(err ?? \"unknown error\");\n return {\n event: \"tool-error\",\n tool_call_id,\n message: errMessage,\n };\n }\n\n default:\n return {\n event: \"tool-error\",\n tool_call_id: \"\",\n message: `Unknown tool event: ${String(p.event)}`,\n };\n }\n}\n\n/**\n * Extracts the first `{node: delta}` entry from an updates-mode payload and\n * reshapes it into an {@link UpdatesEventData} with explicit `node` and\n * `values` fields. Non-object payloads are coerced to `{ values: {} }`.\n *\n * @param payload - The raw payload from an `\"updates\"` stream chunk,\n * expected to be a `Record<string, unknown>` keyed by node name.\n * @returns An {@link UpdatesEventData} containing the extracted node name\n * and its associated delta values.\n */\nfunction convertUpdatesPayload(payload: unknown): UpdatesEventData {\n if (typeof payload !== \"object\" || payload === null) {\n return { values: {} };\n }\n\n const entries = Object.entries(payload as Record<string, unknown>);\n if (entries.length === 0) {\n return { values: {} };\n }\n\n const [node, values] = entries[0];\n return {\n node,\n values: (typeof values === \"object\" && values !== null\n ? values\n : { value: values }) as Record<string, unknown>,\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ require("./stream-channel.cjs");
2
+ require("./convert.cjs");
3
+ require("./mux.cjs");
4
+ require("./transformers/lifecycle.cjs");
5
+ require("./transformers/messages.cjs");
6
+ require("./transformers/subgraphs.cjs");
7
+ require("./transformers/values.cjs");
8
+ require("./transformers/index.cjs");
9
+ require("./types.cjs");
10
+ require("./run-stream.cjs");
11
+ require("@langchain/core/language_models/stream");
@@ -0,0 +1,12 @@
1
+ import { AgentStatus, ChatModelStream as ChatModelStream$1, InferExtensions, InterruptPayload, LifecycleCause, LifecycleData, MessagesEventData, Namespace, NativeStreamTransformer, ProtocolEvent, StreamEmitter, StreamTransformer, ToolCallStatus, ToolCallStream, ToolsEventData, UpdatesEventData, UsageInfo, isNativeTransformer } from "./types.cjs";
2
+ import { StreamChannel } from "./stream-channel.cjs";
3
+ import { ConvertToProtocolEventOptions, STREAM_EVENTS_V3_MODES, convertToProtocolEvent } from "./convert.cjs";
4
+ import { REJECT_VALUES, RESOLVE_VALUES, StreamHandle, StreamMux, SubgraphDiscovery } from "./mux.cjs";
5
+ import { LifecycleEntry, LifecycleTransformerOptions } from "./transformers/types.cjs";
6
+ import { LifecycleProjection, createLifecycleTransformer, filterLifecycleEntries } from "./transformers/lifecycle.cjs";
7
+ import { createMessagesTransformer } from "./transformers/messages.cjs";
8
+ import { SubgraphDiscoveryProjection, SubgraphDiscoveryTransformerOptions, createSubgraphDiscoveryTransformer, filterSubgraphHandles } from "./transformers/subgraphs.cjs";
9
+ import { createValuesTransformer } from "./transformers/values.cjs";
10
+ import { CreateGraphRunStreamOptions, GraphRunStream, SET_LIFECYCLE_ITERABLE, SET_MESSAGES_ITERABLE, SET_VALUES_LOG, SubgraphRunStream, createGraphRunStream } from "./run-stream.cjs";
11
+ import { ChatModelStream as ChatModelStreamImpl } from "@langchain/core/language_models/stream";
12
+ export { ChatModelStreamImpl };
@@ -0,0 +1,12 @@
1
+ import { AgentStatus, ChatModelStream as ChatModelStream$1, InferExtensions, InterruptPayload, LifecycleCause, LifecycleData, MessagesEventData, Namespace, NativeStreamTransformer, ProtocolEvent, StreamEmitter, StreamTransformer, ToolCallStatus, ToolCallStream, ToolsEventData, UpdatesEventData, UsageInfo, isNativeTransformer } from "./types.js";
2
+ import { StreamChannel } from "./stream-channel.js";
3
+ import { ConvertToProtocolEventOptions, STREAM_EVENTS_V3_MODES, convertToProtocolEvent } from "./convert.js";
4
+ import { REJECT_VALUES, RESOLVE_VALUES, StreamHandle, StreamMux, SubgraphDiscovery } from "./mux.js";
5
+ import { LifecycleEntry, LifecycleTransformerOptions } from "./transformers/types.js";
6
+ import { LifecycleProjection, createLifecycleTransformer, filterLifecycleEntries } from "./transformers/lifecycle.js";
7
+ import { createMessagesTransformer } from "./transformers/messages.js";
8
+ import { SubgraphDiscoveryProjection, SubgraphDiscoveryTransformerOptions, createSubgraphDiscoveryTransformer, filterSubgraphHandles } from "./transformers/subgraphs.js";
9
+ import { createValuesTransformer } from "./transformers/values.js";
10
+ import { CreateGraphRunStreamOptions, GraphRunStream, SET_LIFECYCLE_ITERABLE, SET_MESSAGES_ITERABLE, SET_VALUES_LOG, SubgraphRunStream, createGraphRunStream } from "./run-stream.js";
11
+ import { ChatModelStream as ChatModelStreamImpl } from "@langchain/core/language_models/stream";
12
+ export { ChatModelStreamImpl };
@@ -0,0 +1,12 @@
1
+ import "./stream-channel.js";
2
+ import "./convert.js";
3
+ import "./mux.js";
4
+ import "./transformers/lifecycle.js";
5
+ import "./transformers/messages.js";
6
+ import "./transformers/subgraphs.js";
7
+ import "./transformers/values.js";
8
+ import "./transformers/index.js";
9
+ import "./types.js";
10
+ import "./run-stream.js";
11
+ import { ChatModelStream as ChatModelStreamImpl } from "@langchain/core/language_models/stream";
12
+ export { ChatModelStreamImpl };
@@ -0,0 +1,350 @@
1
+ const require_constants = require("../constants.cjs");
2
+ const require_stream_channel = require("./stream-channel.cjs");
3
+ const require_convert = require("./convert.cjs");
4
+ //#region src/stream/mux.ts
5
+ /**
6
+ * Structural `PromiseLike<T>` predicate — true for thenables including
7
+ * native promises, user-constructed `{ then }` objects, and helper
8
+ * wrappers. Used by {@link StreamMux.wireChannels} to detect final-value
9
+ * projections distinctly from streaming `StreamChannel` values.
10
+ */
11
+ function isPromiseLike(value) {
12
+ return value != null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
13
+ }
14
+ /**
15
+ * Symbol key used by {@link StreamMux} to resolve the values promise on a
16
+ * stream handle. Using a symbol keeps this off the public autocomplete surface.
17
+ */
18
+ const RESOLVE_VALUES = Symbol("resolveValues");
19
+ /**
20
+ * Symbol key used by {@link StreamMux} to reject the values promise on a
21
+ * stream handle. Using a symbol keeps this off the public autocomplete surface.
22
+ */
23
+ const REJECT_VALUES = Symbol("rejectValues");
24
+ /**
25
+ * Central event dispatcher that routes {@link ProtocolEvent}s through a
26
+ * pipeline of {@link StreamTransformer}s, manages namespace discovery for
27
+ * subgraph streams, and exposes async iteration over filtered event
28
+ * sequences.
29
+ *
30
+ * One `StreamMux` instance exists per top-level
31
+ * `streamEvents(..., { version: "v3" })` invocation.
32
+ */
33
+ var StreamMux = class {
34
+ /** @internal All protocol events in arrival order (after reducer pipeline). */
35
+ _events = require_stream_channel.StreamChannel.local();
36
+ /** @internal New-namespace discovery notifications. */
37
+ _discoveries = require_stream_channel.StreamChannel.local();
38
+ /** Monotonic counter for auto-forwarded channel events. */
39
+ #nextEmitSeq = 0;
40
+ /** Whether the mux has been closed or failed. */
41
+ #closed = false;
42
+ /** The error passed to {@link fail}, if any. */
43
+ #error;
44
+ /** Whether the run was interrupted. */
45
+ #interrupted = false;
46
+ /**
47
+ * Namespace of the event currently being processed by
48
+ * {@link push}. Read by {@link StreamChannel} wiring callbacks so
49
+ * auto-forwarded events inherit the triggering event's namespace.
50
+ */
51
+ #currentNamespace = [];
52
+ #transformers = [];
53
+ #channels = [];
54
+ #streamMap = /* @__PURE__ */ new Map();
55
+ #latestValues = /* @__PURE__ */ new Map();
56
+ #interrupts = [];
57
+ /**
58
+ * Final-value projection keys tracked for remote surfacing. Populated
59
+ * by {@link wireChannels} when a transformer's projection contains a
60
+ * `PromiseLike` value. Each entry is flushed as a `custom:<name>`
61
+ * protocol event during {@link close} so that remote clients can
62
+ * observe final-value transformers via `thread.extensions.<name>`.
63
+ */
64
+ #finalValues = [];
65
+ /**
66
+ * Associates a pre-existing stream handle with a namespace so that
67
+ * {@link close} can resolve its values promise later.
68
+ *
69
+ * @param path - The namespace path to register.
70
+ * @param stream - The run stream handle for that namespace.
71
+ */
72
+ register(path, stream) {
73
+ this.#streamMap.set(nsKey(path), stream);
74
+ }
75
+ /**
76
+ * Registers a transformer and replays all buffered events through it so
77
+ * it catches up with events already processed by the mux. When the event
78
+ * log is empty (typical at construction time) the replay is a no-op.
79
+ *
80
+ * The transformer must already have been initialised (i.e. `init()` called
81
+ * and any projection wired). The sequence is:
82
+ *
83
+ * 1. Snapshot the current event log length.
84
+ * 2. Append the transformer so future {@link push} calls reach it.
85
+ * 3. Replay events `[0, snapshot)` through `process()`.
86
+ * 4. If the mux is already closed, call `finalize()` (or `fail()`)
87
+ * immediately so the transformer's log/channel terminates cleanly.
88
+ *
89
+ * @param transformer - An already-initialised transformer to register.
90
+ */
91
+ addTransformer(transformer) {
92
+ const snapshot = this._events.size;
93
+ this.#transformers.push(transformer);
94
+ if (transformer.onRegister) transformer.onRegister({ push: (ns, event) => this.push(ns, event) });
95
+ for (let i = 0; i < snapshot; i += 1) transformer.process(this._events.get(i));
96
+ if (this.#closed) if (this.#error !== void 0) transformer.fail?.(this.#error);
97
+ else transformer.finalize?.();
98
+ }
99
+ /**
100
+ * Scans a transformer projection for streaming and final-value primitives.
101
+ * Remote stream channels are wired to auto-forward to the protocol event
102
+ * stream; local stream channels are tracked for lifecycle only.
103
+ *
104
+ * Two projection shapes are recognised:
105
+ *
106
+ * - {@link StreamChannel} values — named channels forward each `push()`
107
+ * immediately as a protocol event on the channel's declared
108
+ * `channelName` method. Unnamed channels remain in-process-only.
109
+ *
110
+ * - `PromiseLike<unknown>` values — tracked as final-value
111
+ * projections and flushed on {@link close} as a single
112
+ * `custom:<key>` event, where `<key>` is the projection key.
113
+ * This mirrors the in-process `await run.extensions.<key>`
114
+ * ergonomics on remote clients via
115
+ * `await thread.extensions.<key>`.
116
+ *
117
+ * Plain values that are neither are ignored — they remain in-process-only,
118
+ * matching prior behaviour.
119
+ *
120
+ * @param projection - The object returned by `transformer.init()`.
121
+ */
122
+ wireChannels(projection) {
123
+ for (const [key, value] of Object.entries(projection)) {
124
+ if (require_stream_channel.isStreamChannel(value)) {
125
+ this.#channels.push(value);
126
+ if (typeof value.channelName !== "string") continue;
127
+ value._wire((item) => {
128
+ this._events.push({
129
+ type: "event",
130
+ seq: this.#nextEmitSeq++,
131
+ method: value.channelName,
132
+ params: {
133
+ namespace: this.#currentNamespace,
134
+ timestamp: Date.now(),
135
+ data: item
136
+ }
137
+ });
138
+ });
139
+ continue;
140
+ }
141
+ if (isPromiseLike(value)) this.#finalValues.push({
142
+ name: key,
143
+ promise: Promise.resolve(value)
144
+ });
145
+ }
146
+ }
147
+ /**
148
+ * Distributes an event through the transformer pipeline, then appends it to
149
+ * the main event log.
150
+ *
151
+ * Subgraph discovery (materializing a {@link StreamHandle} for each
152
+ * newly observed top-level namespace) is handled by the
153
+ * {@link createSubgraphDiscoveryTransformer} when installed, not here.
154
+ *
155
+ * @param ns - The namespace path that produced the event.
156
+ * @param event - The protocol event to process and store.
157
+ */
158
+ push(ns, event) {
159
+ if (event.method === "values") this.#latestValues.set(nsKey(ns), event.params.data);
160
+ const outerNamespace = this.#currentNamespace;
161
+ this.#currentNamespace = ns;
162
+ let keep = true;
163
+ for (const transformer of this.#transformers) if (!transformer.process(event)) keep = false;
164
+ this.#currentNamespace = outerNamespace;
165
+ if (keep) this._events.push({
166
+ ...event,
167
+ seq: this.#nextEmitSeq++
168
+ });
169
+ }
170
+ /**
171
+ * Gracefully ends the stream: resolves values promises on all known
172
+ * streams, finalizes every transformer, auto-closes streaming
173
+ * channels, flushes any final-value projections as `custom:<name>`
174
+ * events, and closes both event logs.
175
+ *
176
+ * When final-value projections are present, `_events.close()` is
177
+ * deferred until every tracked projection promise has settled so
178
+ * remote consumers observe the flushed values before their event
179
+ * stream ends. Callers do not need to await — `close()` returns
180
+ * synchronously and any downstream consumer iterating
181
+ * {@link _events} naturally waits for the final events.
182
+ */
183
+ close() {
184
+ this.#closed = true;
185
+ for (const [key, values] of this.#latestValues.entries()) {
186
+ const ns = key ? key.split("\0") : [];
187
+ this.#streamMap.get(nsKey(ns))?.[RESOLVE_VALUES](values);
188
+ }
189
+ const finalizePromises = [];
190
+ for (const transformer of this.#transformers) {
191
+ const result = transformer.finalize?.();
192
+ if (result != null && typeof result.then === "function") finalizePromises.push(result);
193
+ }
194
+ for (const channel of this.#channels) channel._close();
195
+ const finalValues = this.#finalValues;
196
+ if (finalValues.length === 0 && finalizePromises.length === 0) {
197
+ this._events.close();
198
+ this._discoveries.close();
199
+ } else Promise.allSettled([...finalizePromises, ...finalValues.map(async ({ name, promise }) => {
200
+ try {
201
+ const resolved = await promise;
202
+ if (!this._events.done) this._events.push({
203
+ type: "event",
204
+ seq: this.#nextEmitSeq++,
205
+ method: "custom",
206
+ params: {
207
+ namespace: [],
208
+ timestamp: Date.now(),
209
+ data: {
210
+ name,
211
+ payload: resolved
212
+ }
213
+ }
214
+ });
215
+ } catch {}
216
+ })]).then(() => {
217
+ this._events.close();
218
+ this._discoveries.close();
219
+ });
220
+ for (const stream of this.#streamMap.values()) stream[RESOLVE_VALUES](void 0);
221
+ }
222
+ /**
223
+ * Propagates a failure to all transformers, channels, event logs, and
224
+ * stream handles.
225
+ *
226
+ * @param err - The error that caused the run to fail.
227
+ */
228
+ fail(err) {
229
+ this.#closed = true;
230
+ this.#error = err;
231
+ for (const transformer of this.#transformers) transformer.fail?.(err);
232
+ for (const channel of this.#channels) channel._fail(err);
233
+ this._events.fail(err);
234
+ this._discoveries.fail(err);
235
+ for (const stream of this.#streamMap.values()) stream[REJECT_VALUES](err);
236
+ }
237
+ /**
238
+ * Records that the run was interrupted, appending the supplied payloads
239
+ * for later retrieval.
240
+ *
241
+ * @param interrupts - The interrupt payloads to store.
242
+ */
243
+ markInterrupted(interrupts) {
244
+ this.#interrupted = true;
245
+ this.#interrupts.push(...interrupts);
246
+ }
247
+ /**
248
+ * Whether the run ended due to an interrupt.
249
+ *
250
+ * @returns `true` if {@link markInterrupted} was called.
251
+ */
252
+ get interrupted() {
253
+ return this.#interrupted;
254
+ }
255
+ /**
256
+ * All interrupt payloads collected during the run.
257
+ *
258
+ * @returns A readonly view of the accumulated interrupt payloads.
259
+ */
260
+ get interrupts() {
261
+ return this.#interrupts;
262
+ }
263
+ /**
264
+ * Returns an async iterator that yields only events whose namespace
265
+ * starts with {@link path}.
266
+ *
267
+ * @param path - Namespace prefix to filter on.
268
+ * @param startAt - Zero-based index into the event log to begin from.
269
+ * @returns An async iterator over matching {@link ProtocolEvent}s.
270
+ */
271
+ subscribeEvents(path, startAt = 0) {
272
+ const base = this._events.iterate(startAt);
273
+ return { async next() {
274
+ while (true) {
275
+ const result = await base.next();
276
+ if (result.done) return result;
277
+ if (hasPrefix(result.value.params.namespace, path)) return result;
278
+ }
279
+ } };
280
+ }
281
+ };
282
+ /**
283
+ * Background consumer that drains a raw `graph.stream()` source into a
284
+ * {@link StreamMux}. Converts each chunk to a {@link ProtocolEvent} and
285
+ * pushes it; calls {@link StreamMux.close} on normal completion or
286
+ * {@link StreamMux.fail} on error.
287
+ *
288
+ * @param source - The async iterable of raw stream chunks from the engine.
289
+ * @param mux - The mux instance to feed.
290
+ * @returns A promise that resolves when the source is fully consumed.
291
+ */
292
+ async function pump(source, mux) {
293
+ let seq = 0;
294
+ try {
295
+ for await (const chunk of source) {
296
+ const [ns, mode, payload, meta] = chunk;
297
+ if (mode === "values" && require_constants.isInterrupted(payload)) {
298
+ const interrupts = payload[require_constants.INTERRUPT];
299
+ mux.markInterrupted(interrupts.map((i) => ({
300
+ interruptId: i.id ?? "",
301
+ payload: i.value
302
+ })));
303
+ }
304
+ const events = require_convert.convertToProtocolEvent({
305
+ namespace: ns,
306
+ mode,
307
+ payload,
308
+ seq,
309
+ meta
310
+ });
311
+ seq += events.length;
312
+ for (const event of events) mux.push(ns, event);
313
+ }
314
+ } catch (err) {
315
+ mux.fail(err);
316
+ return;
317
+ }
318
+ mux.close();
319
+ }
320
+ /**
321
+ * Serialises a {@link Namespace} array into a single string key using the
322
+ * null byte (`\x00`) as separator, suitable for `Map`/`Set` lookups.
323
+ *
324
+ * @param ns - The namespace segments to join.
325
+ * @returns A null-byte-joined string key.
326
+ */
327
+ function nsKey(ns) {
328
+ return ns.join("\0");
329
+ }
330
+ /**
331
+ * Tests whether {@link ns} starts with every segment in {@link prefix}.
332
+ *
333
+ * @param ns - The full namespace to check.
334
+ * @param prefix - The prefix to match against.
335
+ * @returns `true` if `ns` begins with `prefix` segment-by-segment.
336
+ */
337
+ function hasPrefix(ns, prefix) {
338
+ if (prefix.length > ns.length) return false;
339
+ for (let i = 0; i < prefix.length; i += 1) if (ns[i] !== prefix[i]) return false;
340
+ return true;
341
+ }
342
+ //#endregion
343
+ exports.REJECT_VALUES = REJECT_VALUES;
344
+ exports.RESOLVE_VALUES = RESOLVE_VALUES;
345
+ exports.StreamMux = StreamMux;
346
+ exports.hasPrefix = hasPrefix;
347
+ exports.nsKey = nsKey;
348
+ exports.pump = pump;
349
+
350
+ //# sourceMappingURL=mux.cjs.map