@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,53 @@
1
+ import { Namespace, NativeStreamTransformer } from "../types.cjs";
2
+ import { StreamChannel } from "../stream-channel.cjs";
3
+ import { LifecycleEntry, LifecycleTransformerOptions } from "./types.cjs";
4
+
5
+ //#region src/stream/transformers/lifecycle.d.ts
6
+ /**
7
+ * Projection returned from the lifecycle transformer's `init()`.
8
+ *
9
+ * The local `StreamChannel` is closed automatically when the transformer
10
+ * finalizes or fails. `_lifecycleLog` is intentionally underscore-prefixed to
11
+ * signal that it is consumed by the run stream wiring
12
+ * (see `run-stream.ts`) and not meant for direct user access -
13
+ * consumers should read `run.lifecycle` instead.
14
+ *
15
+ * The `lifecycle` iterable is the root-scoped projection (prefix
16
+ * `[]`, starting at offset `0`) mirroring the pattern used by the
17
+ * subgraph discovery transformer. Root stream wiring consumes it
18
+ * via `SET_LIFECYCLE_ITERABLE`; child streams are wired with their
19
+ * own path-scoped iterable produced by `filterLifecycleEntries`.
20
+ */
21
+ interface LifecycleProjection {
22
+ _lifecycleLog: StreamChannel<LifecycleEntry>;
23
+ lifecycle: AsyncIterable<LifecycleEntry>;
24
+ }
25
+ /**
26
+ * Filter a lifecycle {@link StreamChannel} to only the entries whose
27
+ * namespace lies within the subtree rooted at {@link path}.
28
+ *
29
+ * Returns an `AsyncIterable` whose iterator yields every entry whose
30
+ * namespace either equals {@link path} or is a descendant of it.
31
+ * Iteration begins at {@link startAt}, so callers can capture the
32
+ * log's current size at construction time to skip entries emitted
33
+ * before the caller existed (e.g. a subgraph stream discovered
34
+ * mid-run shouldn't replay the root's `started`).
35
+ *
36
+ * @param log - The shared lifecycle log owned by the transformer.
37
+ * @param path - Namespace prefix to scope entries by (use `[]` for
38
+ * the root subtree, i.e. everything).
39
+ * @param startAt - Zero-based index into the log to begin from.
40
+ * @returns An async iterable of matching lifecycle entries.
41
+ */
42
+ declare function filterLifecycleEntries(log: StreamChannel<LifecycleEntry>, path: Namespace, startAt?: number): AsyncIterable<LifecycleEntry>;
43
+ /**
44
+ * Create the built-in lifecycle transformer.
45
+ *
46
+ * Marked as a {@link NativeStreamTransformer} so the run stream
47
+ * factory can expose `_lifecycleLog` via a dedicated getter
48
+ * (`run.lifecycle`) rather than through `run.extensions`.
49
+ */
50
+ declare function createLifecycleTransformer(options?: LifecycleTransformerOptions): NativeStreamTransformer<LifecycleProjection>;
51
+ //#endregion
52
+ export { LifecycleProjection, createLifecycleTransformer, filterLifecycleEntries };
53
+ //# sourceMappingURL=lifecycle.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.cts","names":[],"sources":["../../../src/stream/transformers/lifecycle.ts"],"mappings":";;;;;;;;AAsEA;;;;;;;;;;;;UAtBiB,mBAAA;EACf,aAAA,EAAe,aAAA,CAAc,cAAA;EAC7B,SAAA,EAAW,aAAA,CAAc,cAAA;AAAA;;;;;AAiI3B;;;;;;;;;;;;;iBA7GgB,sBAAA,CACd,GAAA,EAAK,aAAA,CAAc,cAAA,GACnB,IAAA,EAAM,SAAA,EACN,OAAA,YACC,aAAA,CAAc,cAAA;;;;;;;;iBAyGD,0BAAA,CACd,OAAA,GAAS,2BAAA,GACR,uBAAA,CAAwB,mBAAA"}
@@ -0,0 +1,53 @@
1
+ import { Namespace, NativeStreamTransformer } from "../types.js";
2
+ import { StreamChannel } from "../stream-channel.js";
3
+ import { LifecycleEntry, LifecycleTransformerOptions } from "./types.js";
4
+
5
+ //#region src/stream/transformers/lifecycle.d.ts
6
+ /**
7
+ * Projection returned from the lifecycle transformer's `init()`.
8
+ *
9
+ * The local `StreamChannel` is closed automatically when the transformer
10
+ * finalizes or fails. `_lifecycleLog` is intentionally underscore-prefixed to
11
+ * signal that it is consumed by the run stream wiring
12
+ * (see `run-stream.ts`) and not meant for direct user access -
13
+ * consumers should read `run.lifecycle` instead.
14
+ *
15
+ * The `lifecycle` iterable is the root-scoped projection (prefix
16
+ * `[]`, starting at offset `0`) mirroring the pattern used by the
17
+ * subgraph discovery transformer. Root stream wiring consumes it
18
+ * via `SET_LIFECYCLE_ITERABLE`; child streams are wired with their
19
+ * own path-scoped iterable produced by `filterLifecycleEntries`.
20
+ */
21
+ interface LifecycleProjection {
22
+ _lifecycleLog: StreamChannel<LifecycleEntry>;
23
+ lifecycle: AsyncIterable<LifecycleEntry>;
24
+ }
25
+ /**
26
+ * Filter a lifecycle {@link StreamChannel} to only the entries whose
27
+ * namespace lies within the subtree rooted at {@link path}.
28
+ *
29
+ * Returns an `AsyncIterable` whose iterator yields every entry whose
30
+ * namespace either equals {@link path} or is a descendant of it.
31
+ * Iteration begins at {@link startAt}, so callers can capture the
32
+ * log's current size at construction time to skip entries emitted
33
+ * before the caller existed (e.g. a subgraph stream discovered
34
+ * mid-run shouldn't replay the root's `started`).
35
+ *
36
+ * @param log - The shared lifecycle log owned by the transformer.
37
+ * @param path - Namespace prefix to scope entries by (use `[]` for
38
+ * the root subtree, i.e. everything).
39
+ * @param startAt - Zero-based index into the log to begin from.
40
+ * @returns An async iterable of matching lifecycle entries.
41
+ */
42
+ declare function filterLifecycleEntries(log: StreamChannel<LifecycleEntry>, path: Namespace, startAt?: number): AsyncIterable<LifecycleEntry>;
43
+ /**
44
+ * Create the built-in lifecycle transformer.
45
+ *
46
+ * Marked as a {@link NativeStreamTransformer} so the run stream
47
+ * factory can expose `_lifecycleLog` via a dedicated getter
48
+ * (`run.lifecycle`) rather than through `run.extensions`.
49
+ */
50
+ declare function createLifecycleTransformer(options?: LifecycleTransformerOptions): NativeStreamTransformer<LifecycleProjection>;
51
+ //#endregion
52
+ export { LifecycleProjection, createLifecycleTransformer, filterLifecycleEntries };
53
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","names":[],"sources":["../../../src/stream/transformers/lifecycle.ts"],"mappings":";;;;;;;;AAsEA;;;;;;;;;;;;UAtBiB,mBAAA;EACf,aAAA,EAAe,aAAA,CAAc,cAAA;EAC7B,SAAA,EAAW,aAAA,CAAc,cAAA;AAAA;;;;;AAiI3B;;;;;;;;;;;;;iBA7GgB,sBAAA,CACd,GAAA,EAAK,aAAA,CAAc,cAAA,GACnB,IAAA,EAAM,SAAA,EACN,OAAA,YACC,aAAA,CAAc,cAAA;;;;;;;;iBAyGD,0BAAA,CACd,OAAA,GAAS,2BAAA,GACR,uBAAA,CAAwB,mBAAA"}
@@ -0,0 +1,325 @@
1
+ import { StreamChannel } from "../stream-channel.js";
2
+ import { hasPrefix, nsKey } from "../mux.js";
3
+ //#region src/stream/transformers/lifecycle.ts
4
+ /**
5
+ * Filter a lifecycle {@link StreamChannel} to only the entries whose
6
+ * namespace lies within the subtree rooted at {@link path}.
7
+ *
8
+ * Returns an `AsyncIterable` whose iterator yields every entry whose
9
+ * namespace either equals {@link path} or is a descendant of it.
10
+ * Iteration begins at {@link startAt}, so callers can capture the
11
+ * log's current size at construction time to skip entries emitted
12
+ * before the caller existed (e.g. a subgraph stream discovered
13
+ * mid-run shouldn't replay the root's `started`).
14
+ *
15
+ * @param log - The shared lifecycle log owned by the transformer.
16
+ * @param path - Namespace prefix to scope entries by (use `[]` for
17
+ * the root subtree, i.e. everything).
18
+ * @param startAt - Zero-based index into the log to begin from.
19
+ * @returns An async iterable of matching lifecycle entries.
20
+ */
21
+ function filterLifecycleEntries(log, path, startAt = 0) {
22
+ return { [Symbol.asyncIterator]() {
23
+ const base = log.iterate(startAt);
24
+ return { async next() {
25
+ while (true) {
26
+ const result = await base.next();
27
+ if (result.done) return {
28
+ value: void 0,
29
+ done: true
30
+ };
31
+ if (hasPrefix(result.value.namespace, path)) return {
32
+ value: result.value,
33
+ done: false
34
+ };
35
+ }
36
+ } };
37
+ } };
38
+ }
39
+ const DEFAULT_ROOT_GRAPH_NAME = "root";
40
+ function defaultGuessGraphName(ns) {
41
+ if (ns.length === 0) return DEFAULT_ROOT_GRAPH_NAME;
42
+ const last = ns[ns.length - 1];
43
+ const colon = last.indexOf(":");
44
+ return colon === -1 ? last : last.slice(0, colon);
45
+ }
46
+ function defaultSerializeError(err) {
47
+ if (err instanceof Error) return err.message;
48
+ if (typeof err === "string") return err;
49
+ try {
50
+ return JSON.stringify(err);
51
+ } catch {
52
+ return String(err);
53
+ }
54
+ }
55
+ function isRecord(value) {
56
+ return typeof value === "object" && value !== null && !Array.isArray(value);
57
+ }
58
+ /**
59
+ * Extract an upstream `cause` from a `lifecycle.started` payload, if
60
+ * the shape matches one of the known variants. Shape validation is
61
+ * intentionally loose: any object with a string `type` is accepted, so
62
+ * future protocol variants flow through unchanged.
63
+ */
64
+ function extractCause(data) {
65
+ if (!isRecord(data)) return void 0;
66
+ if (data.event !== "started") return void 0;
67
+ const cause = data.cause;
68
+ if (!isRecord(cause)) return void 0;
69
+ if (typeof cause.type !== "string") return void 0;
70
+ return cause;
71
+ }
72
+ function extractTaskResultCompletion(data) {
73
+ if (!isRecord(data)) return void 0;
74
+ if (!("result" in data)) return void 0;
75
+ if (typeof data.name !== "string") return void 0;
76
+ if (typeof data.id !== "string") return void 0;
77
+ if (data.name.startsWith("__")) return void 0;
78
+ return {
79
+ name: data.name,
80
+ id: data.id
81
+ };
82
+ }
83
+ /**
84
+ * Create the built-in lifecycle transformer.
85
+ *
86
+ * Marked as a {@link NativeStreamTransformer} so the run stream
87
+ * factory can expose `_lifecycleLog` via a dedicated getter
88
+ * (`run.lifecycle`) rather than through `run.extensions`.
89
+ */
90
+ function createLifecycleTransformer(options = {}) {
91
+ const rootGraphName = options.rootGraphName ?? DEFAULT_ROOT_GRAPH_NAME;
92
+ const initialStatus = options.initialStatus ?? "running";
93
+ const emitRootOnRegister = options.emitRootOnRegister ?? true;
94
+ const getGraphName = options.getGraphName ?? defaultGuessGraphName;
95
+ const serializeError = options.serializeError ?? defaultSerializeError;
96
+ const getTerminalStatusOverride = options.getTerminalStatusOverride;
97
+ const log = StreamChannel.local();
98
+ const namespaces = /* @__PURE__ */ new Map();
99
+ const namespaceCause = /* @__PURE__ */ new Map();
100
+ const pendingInterruptIds = /* @__PURE__ */ new Set();
101
+ /**
102
+ * Child namespaces whose parent just saw an `updates` event with a
103
+ * `node` attribution. We defer the `lifecycle.completed` emission
104
+ * until the *next* inbound event (or `finalize`) so the parent's
105
+ * `updates` lands on the wire before its child is marked complete -
106
+ * matching the previous session behavior.
107
+ */
108
+ const pendingCompletions = [];
109
+ let emitter;
110
+ let inSelfEmit = 0;
111
+ let finalized = false;
112
+ const resolveGraphName = (ns) => ns.length === 0 ? rootGraphName : getGraphName(ns);
113
+ const emit = (ns, status, extras) => {
114
+ const key = nsKey(ns);
115
+ let current = namespaces.get(key);
116
+ const graphName = current?.graphName ?? resolveGraphName(ns);
117
+ if (current != null && current.status === status && current.graphName === graphName && extras?.error == null) return;
118
+ if (current == null) {
119
+ current = {
120
+ namespace: ns,
121
+ graphName,
122
+ status
123
+ };
124
+ namespaces.set(key, current);
125
+ } else current.status = status;
126
+ const data = {
127
+ event: status,
128
+ graph_name: graphName,
129
+ ...extras?.cause != null ? { cause: extras.cause } : {},
130
+ ...extras?.error != null ? { error: extras.error } : {}
131
+ };
132
+ const timestamp = Date.now();
133
+ log.push({
134
+ namespace: ns,
135
+ timestamp,
136
+ ...data
137
+ });
138
+ if (ns.length === 0 && !emitRootOnRegister) return;
139
+ if (emitter == null) return;
140
+ inSelfEmit += 1;
141
+ try {
142
+ emitter.push(ns, {
143
+ type: "event",
144
+ seq: 0,
145
+ method: "lifecycle",
146
+ params: {
147
+ namespace: ns,
148
+ timestamp,
149
+ data
150
+ }
151
+ });
152
+ } finally {
153
+ inSelfEmit -= 1;
154
+ }
155
+ };
156
+ /**
157
+ * Ensures a record exists for `ns` without mutating its status. Used
158
+ * by hooks that need a canonical `graphName` for lookups before emit
159
+ * writes the first status. Status remains `undefined` until `emit`
160
+ * fires.
161
+ */
162
+ const trackNamespace = (ns) => {
163
+ const key = nsKey(ns);
164
+ let rec = namespaces.get(key);
165
+ if (rec == null) {
166
+ rec = {
167
+ namespace: ns,
168
+ graphName: resolveGraphName(ns),
169
+ status: void 0
170
+ };
171
+ namespaces.set(key, rec);
172
+ }
173
+ return rec;
174
+ };
175
+ const flushPendingCompletions = () => {
176
+ if (pendingCompletions.length === 0) return;
177
+ const toFlush = pendingCompletions.splice(0, pendingCompletions.length);
178
+ for (const completion of toFlush) {
179
+ const key = nsKey(completion.namespace);
180
+ const rec = namespaces.get(key);
181
+ if (rec == null || rec.status !== "started") continue;
182
+ emit(completion.namespace, "completed");
183
+ }
184
+ };
185
+ const enqueueCompletion = (completion) => {
186
+ const key = nsKey(completion.namespace);
187
+ const rec = namespaces.get(key);
188
+ if (rec == null || rec.status !== "started") return;
189
+ if (pendingCompletions.some((pending) => nsKey(pending.namespace) === key)) return;
190
+ pendingCompletions.push(completion);
191
+ };
192
+ const removePendingNodeCompletions = (parent, node) => {
193
+ for (let index = pendingCompletions.length - 1; index >= 0; index -= 1) {
194
+ const pending = pendingCompletions[index];
195
+ if (pending.source.type !== "node") continue;
196
+ if (pending.source.node !== node) continue;
197
+ if (nsKey(pending.source.parent) !== nsKey(parent)) continue;
198
+ pendingCompletions.splice(index, 1);
199
+ }
200
+ };
201
+ const ensureStarted = (ns) => {
202
+ for (let length = 1; length <= ns.length; length += 1) {
203
+ const prefix = ns.slice(0, length);
204
+ const key = nsKey(prefix);
205
+ if (namespaces.has(key)) continue;
206
+ trackNamespace(prefix);
207
+ const cause = namespaceCause.get(key);
208
+ emit(prefix, "started", cause != null ? { cause } : void 0);
209
+ }
210
+ };
211
+ const defaultTerminalStatus = () => pendingInterruptIds.size > 0 ? "interrupted" : "completed";
212
+ const cascadeTerminalStatus = (status) => {
213
+ for (const rec of namespaces.values()) {
214
+ if (rec.namespace.length === 0) continue;
215
+ if (rec.status !== "started") continue;
216
+ emit(rec.namespace, status);
217
+ }
218
+ emit([], status);
219
+ log.close();
220
+ };
221
+ const resolveTerminalStatusOverride = async () => {
222
+ if (getTerminalStatusOverride == null) return defaultTerminalStatus();
223
+ try {
224
+ return await getTerminalStatusOverride() ?? defaultTerminalStatus();
225
+ } catch {
226
+ return defaultTerminalStatus();
227
+ }
228
+ };
229
+ const findStartedChildForNode = (parentNamespace, node) => {
230
+ const prefix = `${node}:`;
231
+ for (const rec of namespaces.values()) {
232
+ if (rec.namespace.length !== parentNamespace.length + 1) continue;
233
+ if (rec.status !== "started") continue;
234
+ if (!hasPrefix(rec.namespace, parentNamespace)) continue;
235
+ const last = rec.namespace[rec.namespace.length - 1];
236
+ if (last === node || last.startsWith(prefix)) return rec.namespace;
237
+ }
238
+ };
239
+ const findStartedChildForTask = (parentNamespace, task) => {
240
+ const namespace = [...parentNamespace, `${task.name}:${task.id}`];
241
+ return namespaces.get(nsKey(namespace))?.status === "started" ? namespace : void 0;
242
+ };
243
+ return {
244
+ __native: true,
245
+ init() {
246
+ return {
247
+ _lifecycleLog: log,
248
+ lifecycle: filterLifecycleEntries(log, [], 0)
249
+ };
250
+ },
251
+ onRegister(handle) {
252
+ emitter = handle;
253
+ trackNamespace([]);
254
+ if (emitRootOnRegister) emit([], initialStatus);
255
+ },
256
+ process(event) {
257
+ const ns = event.params.namespace;
258
+ if (inSelfEmit > 0) return true;
259
+ const taskCompletion = event.method === "tasks" ? extractTaskResultCompletion(event.params.data) : void 0;
260
+ if (taskCompletion != null) removePendingNodeCompletions(ns, taskCompletion.name);
261
+ flushPendingCompletions();
262
+ if (event.method === "lifecycle") {
263
+ const cause = extractCause(event.params.data);
264
+ if (cause != null) namespaceCause.set(nsKey(ns), cause);
265
+ ensureStarted(ns);
266
+ return false;
267
+ }
268
+ ensureStarted(ns);
269
+ if (event.method === "input" && isRecord(event.params.data) && event.params.data.event === "requested") {
270
+ const id = event.params.data.id;
271
+ if (typeof id === "string") pendingInterruptIds.add(id);
272
+ }
273
+ if (taskCompletion != null) {
274
+ const childNamespace = findStartedChildForTask(ns, taskCompletion);
275
+ if (childNamespace != null) enqueueCompletion({
276
+ namespace: childNamespace,
277
+ source: { type: "task" }
278
+ });
279
+ }
280
+ if (event.method === "updates") {
281
+ const node = event.params.node;
282
+ if (typeof node === "string" && !node.startsWith("__")) {
283
+ const childNamespace = findStartedChildForNode(ns, node);
284
+ if (childNamespace != null) enqueueCompletion({
285
+ namespace: childNamespace,
286
+ source: {
287
+ type: "node",
288
+ parent: ns,
289
+ node
290
+ }
291
+ });
292
+ }
293
+ }
294
+ return true;
295
+ },
296
+ finalize() {
297
+ if (finalized) return;
298
+ finalized = true;
299
+ flushPendingCompletions();
300
+ if (getTerminalStatusOverride == null) {
301
+ cascadeTerminalStatus(defaultTerminalStatus());
302
+ return;
303
+ }
304
+ return resolveTerminalStatusOverride().then(cascadeTerminalStatus).catch((err) => {
305
+ log.fail(err);
306
+ });
307
+ },
308
+ fail(err) {
309
+ if (finalized) return;
310
+ finalized = true;
311
+ const errorMessage = serializeError(err);
312
+ for (const rec of namespaces.values()) {
313
+ if (rec.namespace.length === 0) continue;
314
+ if (rec.status !== "started") continue;
315
+ emit(rec.namespace, "failed");
316
+ }
317
+ emit([], "failed", { error: errorMessage });
318
+ log.fail(err);
319
+ }
320
+ };
321
+ }
322
+ //#endregion
323
+ export { createLifecycleTransformer, filterLifecycleEntries };
324
+
325
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","names":[],"sources":["../../../src/stream/transformers/lifecycle.ts"],"sourcesContent":["/**\n * LifecycleTransformer - synthesizes `lifecycle` channel events that\n * track the status of the root run and every subgraph it spawns.\n *\n * The transformer is registered first in `createGraphRunStream` so that\n * every other transformer / consumer sees a coherent, authoritative\n * lifecycle stream. It is product-agnostic: deeper semantics (e.g.\n * DeepAgents' `SubagentTransformer` tool-call causation) reach the wire\n * by way of the re-entrant {@link StreamEmitter} - the transformer\n * stashes any `cause` attached upstream and re-emits its own\n * authoritative `lifecycle.started` with the correlation in place.\n *\n * Events are also pushed to a local {@link StreamChannel} so in-process\n * consumers can iterate `run.lifecycle` without filtering the main\n * event stream.\n */\n\nimport type {\n AgentStatus,\n LifecycleCause,\n LifecycleData,\n} from \"@langchain/protocol\";\n\nimport { hasPrefix, nsKey } from \"../mux.js\";\nimport { StreamChannel } from \"../stream-channel.js\";\nimport type {\n NativeStreamTransformer,\n Namespace,\n ProtocolEvent,\n StreamEmitter,\n} from \"../types.js\";\nimport type { LifecycleEntry, LifecycleTransformerOptions } from \"./types.js\";\n\n/**\n * Projection returned from the lifecycle transformer's `init()`.\n *\n * The local `StreamChannel` is closed automatically when the transformer\n * finalizes or fails. `_lifecycleLog` is intentionally underscore-prefixed to\n * signal that it is consumed by the run stream wiring\n * (see `run-stream.ts`) and not meant for direct user access -\n * consumers should read `run.lifecycle` instead.\n *\n * The `lifecycle` iterable is the root-scoped projection (prefix\n * `[]`, starting at offset `0`) mirroring the pattern used by the\n * subgraph discovery transformer. Root stream wiring consumes it\n * via `SET_LIFECYCLE_ITERABLE`; child streams are wired with their\n * own path-scoped iterable produced by `filterLifecycleEntries`.\n */\nexport interface LifecycleProjection {\n _lifecycleLog: StreamChannel<LifecycleEntry>;\n lifecycle: AsyncIterable<LifecycleEntry>;\n}\n\n/**\n * Filter a lifecycle {@link StreamChannel} to only the entries whose\n * namespace lies within the subtree rooted at {@link path}.\n *\n * Returns an `AsyncIterable` whose iterator yields every entry whose\n * namespace either equals {@link path} or is a descendant of it.\n * Iteration begins at {@link startAt}, so callers can capture the\n * log's current size at construction time to skip entries emitted\n * before the caller existed (e.g. a subgraph stream discovered\n * mid-run shouldn't replay the root's `started`).\n *\n * @param log - The shared lifecycle log owned by the transformer.\n * @param path - Namespace prefix to scope entries by (use `[]` for\n * the root subtree, i.e. everything).\n * @param startAt - Zero-based index into the log to begin from.\n * @returns An async iterable of matching lifecycle entries.\n */\nexport function filterLifecycleEntries(\n log: StreamChannel<LifecycleEntry>,\n path: Namespace,\n startAt = 0\n): AsyncIterable<LifecycleEntry> {\n return {\n [Symbol.asyncIterator](): AsyncIterator<LifecycleEntry> {\n const base = log.iterate(startAt);\n return {\n async next(): Promise<IteratorResult<LifecycleEntry>> {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const result = await base.next();\n if (result.done) {\n return {\n value: undefined as unknown as LifecycleEntry,\n done: true,\n };\n }\n if (hasPrefix(result.value.namespace, path)) {\n return { value: result.value, done: false };\n }\n }\n },\n };\n },\n };\n}\n\nconst DEFAULT_ROOT_GRAPH_NAME = \"root\";\n\nfunction defaultGuessGraphName(ns: Namespace): string {\n if (ns.length === 0) return DEFAULT_ROOT_GRAPH_NAME;\n const last = ns[ns.length - 1];\n const colon = last.indexOf(\":\");\n return colon === -1 ? last : last.slice(0, colon);\n}\n\nfunction defaultSerializeError(err: unknown): string {\n // oxlint-disable-next-line no-instanceof/no-instanceof\n if (err instanceof Error) return err.message;\n if (typeof err === \"string\") return err;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Extract an upstream `cause` from a `lifecycle.started` payload, if\n * the shape matches one of the known variants. Shape validation is\n * intentionally loose: any object with a string `type` is accepted, so\n * future protocol variants flow through unchanged.\n */\nfunction extractCause(data: unknown): LifecycleCause | undefined {\n if (!isRecord(data)) return undefined;\n if (data.event !== \"started\") return undefined;\n const cause = data.cause;\n if (!isRecord(cause)) return undefined;\n if (typeof cause.type !== \"string\") return undefined;\n return cause as unknown as LifecycleCause;\n}\n\nfunction extractTaskResultCompletion(\n data: unknown\n): TaskResultCompletion | undefined {\n if (!isRecord(data)) return undefined;\n if (!(\"result\" in data)) return undefined;\n if (typeof data.name !== \"string\") return undefined;\n if (typeof data.id !== \"string\") return undefined;\n if (data.name.startsWith(\"__\")) return undefined;\n return { name: data.name, id: data.id };\n}\n\ninterface NamespaceRecord {\n readonly namespace: Namespace;\n readonly graphName: string;\n /** Last emitted status; `undefined` until `emit` fires for this namespace. */\n status: AgentStatus | undefined;\n}\n\ninterface TaskResultCompletion {\n readonly name: string;\n readonly id: string;\n}\n\ninterface PendingCompletion {\n readonly namespace: Namespace;\n readonly source:\n | { readonly type: \"task\" }\n | {\n readonly type: \"node\";\n readonly parent: Namespace;\n readonly node: string;\n };\n}\n\n/**\n * Create the built-in lifecycle transformer.\n *\n * Marked as a {@link NativeStreamTransformer} so the run stream\n * factory can expose `_lifecycleLog` via a dedicated getter\n * (`run.lifecycle`) rather than through `run.extensions`.\n */\nexport function createLifecycleTransformer(\n options: LifecycleTransformerOptions = {}\n): NativeStreamTransformer<LifecycleProjection> {\n const rootGraphName = options.rootGraphName ?? DEFAULT_ROOT_GRAPH_NAME;\n const initialStatus: AgentStatus = options.initialStatus ?? \"running\";\n const emitRootOnRegister = options.emitRootOnRegister ?? true;\n const getGraphName = options.getGraphName ?? defaultGuessGraphName;\n const serializeError = options.serializeError ?? defaultSerializeError;\n const getTerminalStatusOverride = options.getTerminalStatusOverride;\n\n const log = StreamChannel.local<LifecycleEntry>();\n const namespaces = new Map<string, NamespaceRecord>();\n const namespaceCause = new Map<string, LifecycleCause>();\n const pendingInterruptIds = new Set<string>();\n /**\n * Child namespaces whose parent just saw an `updates` event with a\n * `node` attribution. We defer the `lifecycle.completed` emission\n * until the *next* inbound event (or `finalize`) so the parent's\n * `updates` lands on the wire before its child is marked complete -\n * matching the previous session behavior.\n */\n const pendingCompletions: PendingCompletion[] = [];\n\n let emitter: StreamEmitter | undefined;\n let inSelfEmit = 0;\n let finalized = false;\n\n const resolveGraphName = (ns: Namespace): string =>\n ns.length === 0 ? rootGraphName : getGraphName(ns);\n\n const emit = (\n ns: Namespace,\n status: AgentStatus,\n extras?: { cause?: LifecycleCause; error?: string }\n ): void => {\n const key = nsKey(ns);\n let current = namespaces.get(key);\n const graphName = current?.graphName ?? resolveGraphName(ns);\n\n // Dedup: identical status + graph name + no error override => skip.\n if (\n current != null &&\n current.status === status &&\n current.graphName === graphName &&\n extras?.error == null\n ) {\n return;\n }\n\n if (current == null) {\n current = { namespace: ns, graphName, status };\n namespaces.set(key, current);\n } else {\n current.status = status;\n }\n\n const data: LifecycleData = {\n event: status,\n graph_name: graphName,\n ...(extras?.cause != null ? { cause: extras.cause } : {}),\n ...(extras?.error != null ? { error: extras.error } : {}),\n };\n\n const timestamp = Date.now();\n\n log.push({ namespace: ns, timestamp, ...data });\n\n if (ns.length === 0 && !emitRootOnRegister) return;\n\n if (emitter == null) return;\n\n inSelfEmit += 1;\n try {\n emitter.push(ns, {\n type: \"event\",\n seq: 0,\n method: \"lifecycle\",\n params: { namespace: ns, timestamp, data },\n });\n } finally {\n inSelfEmit -= 1;\n }\n };\n\n /**\n * Ensures a record exists for `ns` without mutating its status. Used\n * by hooks that need a canonical `graphName` for lookups before emit\n * writes the first status. Status remains `undefined` until `emit`\n * fires.\n */\n const trackNamespace = (ns: Namespace): NamespaceRecord => {\n const key = nsKey(ns);\n let rec = namespaces.get(key);\n if (rec == null) {\n rec = {\n namespace: ns,\n graphName: resolveGraphName(ns),\n status: undefined,\n };\n namespaces.set(key, rec);\n }\n return rec;\n };\n\n const flushPendingCompletions = (): void => {\n if (pendingCompletions.length === 0) return;\n const toFlush = pendingCompletions.splice(0, pendingCompletions.length);\n for (const completion of toFlush) {\n const key = nsKey(completion.namespace);\n const rec = namespaces.get(key);\n if (rec == null || rec.status !== \"started\") continue;\n emit(completion.namespace, \"completed\");\n }\n };\n\n const enqueueCompletion = (completion: PendingCompletion): void => {\n const key = nsKey(completion.namespace);\n const rec = namespaces.get(key);\n if (rec == null || rec.status !== \"started\") return;\n if (\n pendingCompletions.some((pending) => nsKey(pending.namespace) === key)\n ) {\n return;\n }\n pendingCompletions.push(completion);\n };\n\n const removePendingNodeCompletions = (\n parent: Namespace,\n node: string\n ): void => {\n for (let index = pendingCompletions.length - 1; index >= 0; index -= 1) {\n const pending = pendingCompletions[index];\n if (pending.source.type !== \"node\") continue;\n if (pending.source.node !== node) continue;\n if (nsKey(pending.source.parent) !== nsKey(parent)) continue;\n pendingCompletions.splice(index, 1);\n }\n };\n\n const ensureStarted = (ns: Namespace): void => {\n // Synthesize `lifecycle.started` for each unseen prefix of `ns`,\n // outermost first. Deepest-first would force consumers to see a\n // child's started before its parent, which is wrong.\n for (let length = 1; length <= ns.length; length += 1) {\n const prefix = ns.slice(0, length);\n const key = nsKey(prefix);\n if (namespaces.has(key)) continue;\n trackNamespace(prefix);\n const cause = namespaceCause.get(key);\n emit(prefix, \"started\", cause != null ? { cause } : undefined);\n }\n };\n\n const defaultTerminalStatus = (): AgentStatus =>\n pendingInterruptIds.size > 0 ? \"interrupted\" : \"completed\";\n\n const cascadeTerminalStatus = (status: AgentStatus): void => {\n for (const rec of namespaces.values()) {\n if (rec.namespace.length === 0) continue;\n if (rec.status !== \"started\") continue;\n emit(rec.namespace, status);\n }\n emit([], status);\n log.close();\n };\n\n const resolveTerminalStatusOverride = async (): Promise<AgentStatus> => {\n if (getTerminalStatusOverride == null) return defaultTerminalStatus();\n try {\n return (await getTerminalStatusOverride()) ?? defaultTerminalStatus();\n } catch {\n return defaultTerminalStatus();\n }\n };\n\n const findStartedChildForNode = (\n parentNamespace: Namespace,\n node: string\n ): Namespace | undefined => {\n const prefix = `${node}:`;\n for (const rec of namespaces.values()) {\n if (rec.namespace.length !== parentNamespace.length + 1) continue;\n if (rec.status !== \"started\") continue;\n if (!hasPrefix(rec.namespace, parentNamespace)) continue;\n const last = rec.namespace[rec.namespace.length - 1];\n if (last === node || last.startsWith(prefix)) return rec.namespace;\n }\n return undefined;\n };\n\n const findStartedChildForTask = (\n parentNamespace: Namespace,\n task: TaskResultCompletion\n ): Namespace | undefined => {\n const namespace = [...parentNamespace, `${task.name}:${task.id}`];\n const rec = namespaces.get(nsKey(namespace));\n return rec?.status === \"started\" ? namespace : undefined;\n };\n\n const transformer: NativeStreamTransformer<LifecycleProjection> = {\n __native: true,\n\n init() {\n return {\n _lifecycleLog: log,\n lifecycle: filterLifecycleEntries(log, [], 0),\n };\n },\n\n onRegister(handle: StreamEmitter) {\n emitter = handle;\n // Seed root record so cascade logic can see it, even when the\n // outer authority owns root emission.\n trackNamespace([]);\n if (emitRootOnRegister) {\n emit([], initialStatus);\n }\n },\n\n process(event: ProtocolEvent): boolean {\n const ns = event.params.namespace;\n\n // Re-entrant loopback: an event we emitted via `emitter.push`\n // is being routed back through this transformer by the mux.\n // Allow it through the wire unchanged.\n if (inSelfEmit > 0) return true;\n\n const taskCompletion =\n event.method === \"tasks\"\n ? extractTaskResultCompletion(event.params.data)\n : undefined;\n if (taskCompletion != null) {\n // Prefer exact task-result attribution over any ambiguous\n // `updates.node` completion deferred from the previous event.\n removePendingNodeCompletions(ns, taskCompletion.name);\n }\n\n // Flush any completions deferred by the previous event so the\n // wire order is [triggering event] -> [deferred completed].\n flushPendingCompletions();\n\n // Upstream `lifecycle` events: stash any `cause` attached by a\n // product-specific transformer (e.g. deepagents' SubagentTransformer),\n // synthesize our authoritative started/... for the namespace, and\n // suppress the original so we are the single source of truth.\n if (event.method === \"lifecycle\") {\n const cause = extractCause(event.params.data);\n if (cause != null) {\n namespaceCause.set(nsKey(ns), cause);\n }\n ensureStarted(ns);\n return false;\n }\n\n // Lifecycle for parent + any unseen prefix => synthesize started.\n ensureStarted(ns);\n\n // Track interrupt ids so `finalize` can decide between\n // `completed` and `interrupted`.\n if (\n event.method === \"input\" &&\n isRecord(event.params.data) &&\n event.params.data.event === \"requested\"\n ) {\n const id = (event.params.data as { id?: unknown }).id;\n if (typeof id === \"string\") {\n pendingInterruptIds.add(id);\n }\n }\n\n if (taskCompletion != null) {\n const childNamespace = findStartedChildForTask(ns, taskCompletion);\n if (childNamespace != null) {\n enqueueCompletion({\n namespace: childNamespace,\n source: { type: \"task\" },\n });\n }\n }\n\n // Defer child-node completion: the `updates` event carries the\n // node attribution; the corresponding child namespace is\n // `[...ns, \"<node>:<uuid>\"]`. We pick the oldest still-started\n // matching child (LangGraph emits one updates per completed task\n // so repeated calls drain parallel fan-outs in order).\n if (event.method === \"updates\") {\n const node = event.params.node;\n if (typeof node === \"string\" && !node.startsWith(\"__\")) {\n const childNamespace = findStartedChildForNode(ns, node);\n if (childNamespace != null) {\n enqueueCompletion({\n namespace: childNamespace,\n source: { type: \"node\", parent: ns, node },\n });\n }\n }\n }\n\n return true;\n },\n\n finalize(): void | PromiseLike<void> {\n if (finalized) return;\n finalized = true;\n flushPendingCompletions();\n\n if (getTerminalStatusOverride == null) {\n cascadeTerminalStatus(defaultTerminalStatus());\n return;\n }\n\n return resolveTerminalStatusOverride()\n .then(cascadeTerminalStatus)\n .catch((err) => {\n log.fail(err);\n });\n },\n\n fail(err: unknown) {\n if (finalized) return;\n finalized = true;\n const errorMessage = serializeError(err);\n\n // Cascade `failed` to every still-started namespace. Children\n // that had already entered a terminal state are left untouched\n // by the dedup guard in `emit`.\n for (const rec of namespaces.values()) {\n if (rec.namespace.length === 0) continue;\n if (rec.status !== \"started\") continue;\n emit(rec.namespace, \"failed\");\n }\n\n emit([], \"failed\", { error: errorMessage });\n log.fail(err);\n },\n };\n\n return transformer;\n}\n"],"mappings":"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"}
@@ -0,0 +1,94 @@
1
+ const require_stream_channel = require("../stream-channel.cjs");
2
+ const require_mux = require("../mux.cjs");
3
+ let _langchain_core_language_models_stream = require("@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 = require_stream_channel.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 (!require_mux.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 = require_stream_channel.StreamChannel.local();
41
+ const stream = Object.assign(new _langchain_core_language_models_stream.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
+ exports.createMessagesTransformer = createMessagesTransformer;
93
+
94
+ //# sourceMappingURL=messages.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.cjs","names":["StreamChannel","hasPrefix","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,MAAMA,uBAAAA,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,CAACC,YAAAA,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,SAASD,uBAAAA,cAAc,OAA6B;KAC1D,MAAM,SAAS,OAAO,OACpB,IAAIE,uCAAAA,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,23 @@
1
+ import { Namespace, StreamTransformer } from "../types.cjs";
2
+ import { MessagesTransformerProjection } from "./types.cjs";
3
+
4
+ //#region src/stream/transformers/messages.d.ts
5
+ /**
6
+ * Creates a {@link StreamTransformer} that groups `messages` channel events into
7
+ * per-message {@link ChatModelStream} instances.
8
+ *
9
+ * A new `ChatModelStream` is created on `message-start` and closed on
10
+ * `message-finish`. Content-block events in between are forwarded to the
11
+ * active stream. Only events whose namespace exactly matches {@link path}
12
+ * are processed; child namespaces are ignored.
13
+ *
14
+ * @param path - Namespace prefix to match against incoming events.
15
+ * @param nodeFilter - If provided, only events emitted by this graph node
16
+ * are processed; all others are skipped.
17
+ * @returns A `StreamTransformer` whose projection contains the `messages`
18
+ * async iterable.
19
+ */
20
+ declare function createMessagesTransformer(path: Namespace, nodeFilter?: string): StreamTransformer<MessagesTransformerProjection>;
21
+ //#endregion
22
+ export { createMessagesTransformer };
23
+ //# sourceMappingURL=messages.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.cts","names":[],"sources":["../../../src/stream/transformers/messages.ts"],"mappings":";;;;;;AA0CA;;;;;;;;;;;;;iBAAgB,yBAAA,CACd,IAAA,EAAM,SAAA,EACN,UAAA,YACC,iBAAA,CAAkB,6BAAA"}
@@ -0,0 +1,23 @@
1
+ import { Namespace, StreamTransformer } from "../types.js";
2
+ import { MessagesTransformerProjection } from "./types.js";
3
+
4
+ //#region src/stream/transformers/messages.d.ts
5
+ /**
6
+ * Creates a {@link StreamTransformer} that groups `messages` channel events into
7
+ * per-message {@link ChatModelStream} instances.
8
+ *
9
+ * A new `ChatModelStream` is created on `message-start` and closed on
10
+ * `message-finish`. Content-block events in between are forwarded to the
11
+ * active stream. Only events whose namespace exactly matches {@link path}
12
+ * are processed; child namespaces are ignored.
13
+ *
14
+ * @param path - Namespace prefix to match against incoming events.
15
+ * @param nodeFilter - If provided, only events emitted by this graph node
16
+ * are processed; all others are skipped.
17
+ * @returns A `StreamTransformer` whose projection contains the `messages`
18
+ * async iterable.
19
+ */
20
+ declare function createMessagesTransformer(path: Namespace, nodeFilter?: string): StreamTransformer<MessagesTransformerProjection>;
21
+ //#endregion
22
+ export { createMessagesTransformer };
23
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","names":[],"sources":["../../../src/stream/transformers/messages.ts"],"mappings":";;;;;;AA0CA;;;;;;;;;;;;;iBAAgB,yBAAA,CACd,IAAA,EAAM,SAAA,EACN,UAAA,YACC,iBAAA,CAAkB,6BAAA"}