@langchain/langgraph 1.3.6 → 1.4.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 (221) hide show
  1. package/dist/channels/base.cjs +78 -2
  2. package/dist/channels/base.cjs.map +1 -1
  3. package/dist/channels/base.d.cts +35 -2
  4. package/dist/channels/base.d.cts.map +1 -1
  5. package/dist/channels/base.d.ts +35 -2
  6. package/dist/channels/base.d.ts.map +1 -1
  7. package/dist/channels/base.js +77 -4
  8. package/dist/channels/base.js.map +1 -1
  9. package/dist/channels/delta.cjs +136 -0
  10. package/dist/channels/delta.cjs.map +1 -0
  11. package/dist/channels/delta.d.cts +99 -0
  12. package/dist/channels/delta.d.cts.map +1 -0
  13. package/dist/channels/delta.d.ts +99 -0
  14. package/dist/channels/delta.d.ts.map +1 -0
  15. package/dist/channels/delta.js +136 -0
  16. package/dist/channels/delta.js.map +1 -0
  17. package/dist/channels/index.cjs +5 -0
  18. package/dist/channels/index.d.cts +3 -2
  19. package/dist/channels/index.d.ts +3 -2
  20. package/dist/channels/index.js +3 -2
  21. package/dist/constants.cjs +62 -4
  22. package/dist/constants.cjs.map +1 -1
  23. package/dist/constants.d.cts +33 -2
  24. package/dist/constants.d.cts.map +1 -1
  25. package/dist/constants.d.ts +33 -2
  26. package/dist/constants.d.ts.map +1 -1
  27. package/dist/constants.js +59 -5
  28. package/dist/constants.js.map +1 -1
  29. package/dist/errors.cjs +128 -0
  30. package/dist/errors.cjs.map +1 -1
  31. package/dist/errors.d.cts +86 -1
  32. package/dist/errors.d.cts.map +1 -1
  33. package/dist/errors.d.ts +86 -1
  34. package/dist/errors.d.ts.map +1 -1
  35. package/dist/errors.js +123 -1
  36. package/dist/errors.js.map +1 -1
  37. package/dist/func/index.cjs +9 -2
  38. package/dist/func/index.cjs.map +1 -1
  39. package/dist/func/index.d.cts +14 -0
  40. package/dist/func/index.d.cts.map +1 -1
  41. package/dist/func/index.d.ts +14 -0
  42. package/dist/func/index.d.ts.map +1 -1
  43. package/dist/func/index.js +9 -2
  44. package/dist/func/index.js.map +1 -1
  45. package/dist/graph/graph.cjs +44 -7
  46. package/dist/graph/graph.cjs.map +1 -1
  47. package/dist/graph/graph.d.cts +24 -2
  48. package/dist/graph/graph.d.cts.map +1 -1
  49. package/dist/graph/graph.d.ts +24 -2
  50. package/dist/graph/graph.d.ts.map +1 -1
  51. package/dist/graph/graph.js +44 -7
  52. package/dist/graph/graph.js.map +1 -1
  53. package/dist/graph/index.d.ts +3 -3
  54. package/dist/graph/messages_reducer.cjs +55 -0
  55. package/dist/graph/messages_reducer.cjs.map +1 -1
  56. package/dist/graph/messages_reducer.d.cts +28 -1
  57. package/dist/graph/messages_reducer.d.cts.map +1 -1
  58. package/dist/graph/messages_reducer.d.ts +28 -1
  59. package/dist/graph/messages_reducer.d.ts.map +1 -1
  60. package/dist/graph/messages_reducer.js +56 -2
  61. package/dist/graph/messages_reducer.js.map +1 -1
  62. package/dist/graph/state.cjs +174 -7
  63. package/dist/graph/state.cjs.map +1 -1
  64. package/dist/graph/state.d.cts +193 -17
  65. package/dist/graph/state.d.cts.map +1 -1
  66. package/dist/graph/state.d.ts +193 -17
  67. package/dist/graph/state.d.ts.map +1 -1
  68. package/dist/graph/state.js +175 -8
  69. package/dist/graph/state.js.map +1 -1
  70. package/dist/graph/zod/schema.cjs +5 -0
  71. package/dist/graph/zod/schema.cjs.map +1 -1
  72. package/dist/graph/zod/schema.d.cts.map +1 -1
  73. package/dist/graph/zod/schema.d.ts.map +1 -1
  74. package/dist/graph/zod/schema.js +5 -0
  75. package/dist/graph/zod/schema.js.map +1 -1
  76. package/dist/index.cjs +11 -0
  77. package/dist/index.cjs.map +1 -1
  78. package/dist/index.d.cts +11 -8
  79. package/dist/index.d.ts +11 -8
  80. package/dist/index.js +5 -3
  81. package/dist/index.js.map +1 -1
  82. package/dist/prebuilt/react_agent_executor.d.cts +1 -1
  83. package/dist/pregel/algo.cjs +182 -21
  84. package/dist/pregel/algo.cjs.map +1 -1
  85. package/dist/pregel/algo.d.cts +1 -1
  86. package/dist/pregel/algo.d.cts.map +1 -1
  87. package/dist/pregel/algo.d.ts +1 -1
  88. package/dist/pregel/algo.d.ts.map +1 -1
  89. package/dist/pregel/algo.js +185 -25
  90. package/dist/pregel/algo.js.map +1 -1
  91. package/dist/pregel/call.cjs +2 -1
  92. package/dist/pregel/call.cjs.map +1 -1
  93. package/dist/pregel/call.js +2 -1
  94. package/dist/pregel/call.js.map +1 -1
  95. package/dist/pregel/index.cjs +15 -3
  96. package/dist/pregel/index.cjs.map +1 -1
  97. package/dist/pregel/index.d.cts.map +1 -1
  98. package/dist/pregel/index.d.ts.map +1 -1
  99. package/dist/pregel/index.js +17 -5
  100. package/dist/pregel/index.js.map +1 -1
  101. package/dist/pregel/loop.cjs +362 -41
  102. package/dist/pregel/loop.cjs.map +1 -1
  103. package/dist/pregel/loop.js +365 -44
  104. package/dist/pregel/loop.js.map +1 -1
  105. package/dist/pregel/messages-v2.cjs +1 -1
  106. package/dist/pregel/messages-v2.js +1 -1
  107. package/dist/pregel/messages.cjs +1 -1
  108. package/dist/pregel/messages.js +1 -1
  109. package/dist/pregel/read.cjs +15 -5
  110. package/dist/pregel/read.cjs.map +1 -1
  111. package/dist/pregel/read.d.cts +9 -0
  112. package/dist/pregel/read.d.cts.map +1 -1
  113. package/dist/pregel/read.d.ts +9 -0
  114. package/dist/pregel/read.d.ts.map +1 -1
  115. package/dist/pregel/read.js +15 -5
  116. package/dist/pregel/read.js.map +1 -1
  117. package/dist/pregel/remote-run-stream.cjs +107 -0
  118. package/dist/pregel/remote-run-stream.cjs.map +1 -0
  119. package/dist/pregel/remote-run-stream.d.cts +33 -0
  120. package/dist/pregel/remote-run-stream.d.cts.map +1 -0
  121. package/dist/pregel/remote-run-stream.d.ts +33 -0
  122. package/dist/pregel/remote-run-stream.d.ts.map +1 -0
  123. package/dist/pregel/remote-run-stream.js +107 -0
  124. package/dist/pregel/remote-run-stream.js.map +1 -0
  125. package/dist/pregel/remote.cjs +61 -1
  126. package/dist/pregel/remote.cjs.map +1 -1
  127. package/dist/pregel/remote.d.cts +17 -0
  128. package/dist/pregel/remote.d.cts.map +1 -1
  129. package/dist/pregel/remote.d.ts +17 -0
  130. package/dist/pregel/remote.d.ts.map +1 -1
  131. package/dist/pregel/remote.js +61 -1
  132. package/dist/pregel/remote.js.map +1 -1
  133. package/dist/pregel/replay.cjs +62 -0
  134. package/dist/pregel/replay.cjs.map +1 -0
  135. package/dist/pregel/replay.js +62 -0
  136. package/dist/pregel/replay.js.map +1 -0
  137. package/dist/pregel/retry.cjs +8 -6
  138. package/dist/pregel/retry.cjs.map +1 -1
  139. package/dist/pregel/retry.js +8 -6
  140. package/dist/pregel/retry.js.map +1 -1
  141. package/dist/pregel/runnable_types.d.cts +20 -0
  142. package/dist/pregel/runnable_types.d.cts.map +1 -1
  143. package/dist/pregel/runnable_types.d.ts +20 -0
  144. package/dist/pregel/runnable_types.d.ts.map +1 -1
  145. package/dist/pregel/runner.cjs +48 -7
  146. package/dist/pregel/runner.cjs.map +1 -1
  147. package/dist/pregel/runner.js +50 -9
  148. package/dist/pregel/runner.js.map +1 -1
  149. package/dist/pregel/runtime.cjs +64 -0
  150. package/dist/pregel/runtime.cjs.map +1 -0
  151. package/dist/pregel/runtime.d.cts +57 -0
  152. package/dist/pregel/runtime.d.cts.map +1 -0
  153. package/dist/pregel/runtime.d.ts +57 -0
  154. package/dist/pregel/runtime.d.ts.map +1 -0
  155. package/dist/pregel/runtime.js +64 -0
  156. package/dist/pregel/runtime.js.map +1 -0
  157. package/dist/pregel/stream.cjs +2 -0
  158. package/dist/pregel/stream.cjs.map +1 -1
  159. package/dist/pregel/stream.js +2 -0
  160. package/dist/pregel/stream.js.map +1 -1
  161. package/dist/pregel/timeout.cjs +216 -0
  162. package/dist/pregel/timeout.cjs.map +1 -0
  163. package/dist/pregel/timeout.js +216 -0
  164. package/dist/pregel/timeout.js.map +1 -0
  165. package/dist/pregel/types.cjs +3 -1
  166. package/dist/pregel/types.cjs.map +1 -1
  167. package/dist/pregel/types.d.cts +13 -0
  168. package/dist/pregel/types.d.cts.map +1 -1
  169. package/dist/pregel/types.d.ts +14 -1
  170. package/dist/pregel/types.d.ts.map +1 -1
  171. package/dist/pregel/types.js +3 -1
  172. package/dist/pregel/types.js.map +1 -1
  173. package/dist/pregel/utils/config.cjs +3 -1
  174. package/dist/pregel/utils/config.cjs.map +1 -1
  175. package/dist/pregel/utils/config.d.cts.map +1 -1
  176. package/dist/pregel/utils/config.d.ts.map +1 -1
  177. package/dist/pregel/utils/config.js +3 -1
  178. package/dist/pregel/utils/config.js.map +1 -1
  179. package/dist/pregel/utils/index.cjs +1 -0
  180. package/dist/pregel/utils/index.cjs.map +1 -1
  181. package/dist/pregel/utils/index.d.cts +6 -1
  182. package/dist/pregel/utils/index.d.cts.map +1 -1
  183. package/dist/pregel/utils/index.d.ts +6 -1
  184. package/dist/pregel/utils/index.d.ts.map +1 -1
  185. package/dist/pregel/utils/index.js +1 -0
  186. package/dist/pregel/utils/index.js.map +1 -1
  187. package/dist/pregel/utils/timeout.cjs +34 -0
  188. package/dist/pregel/utils/timeout.cjs.map +1 -0
  189. package/dist/pregel/utils/timeout.d.cts +45 -0
  190. package/dist/pregel/utils/timeout.d.cts.map +1 -0
  191. package/dist/pregel/utils/timeout.d.ts +45 -0
  192. package/dist/pregel/utils/timeout.d.ts.map +1 -0
  193. package/dist/pregel/utils/timeout.js +34 -0
  194. package/dist/pregel/utils/timeout.js.map +1 -0
  195. package/dist/stream/index.cjs +1 -0
  196. package/dist/stream/index.d.cts +2 -1
  197. package/dist/stream/index.d.ts +2 -1
  198. package/dist/stream/index.js +1 -0
  199. package/dist/stream/stream-channel.d.cts +9 -1
  200. package/dist/stream/stream-channel.d.cts.map +1 -1
  201. package/dist/stream/stream-channel.d.ts +9 -1
  202. package/dist/stream/stream-channel.d.ts.map +1 -1
  203. package/dist/stream/subscription.cjs +136 -0
  204. package/dist/stream/subscription.cjs.map +1 -0
  205. package/dist/stream/subscription.d.cts +94 -0
  206. package/dist/stream/subscription.d.cts.map +1 -0
  207. package/dist/stream/subscription.d.ts +94 -0
  208. package/dist/stream/subscription.d.ts.map +1 -0
  209. package/dist/stream/subscription.js +131 -0
  210. package/dist/stream/subscription.js.map +1 -0
  211. package/dist/stream/types.d.cts +1 -1
  212. package/dist/stream/types.d.ts +1 -1
  213. package/dist/stream.cjs +16 -0
  214. package/dist/stream.d.cts +5 -0
  215. package/dist/stream.d.ts +5 -0
  216. package/dist/stream.js +4 -0
  217. package/dist/web.cjs +11 -0
  218. package/dist/web.d.cts +11 -8
  219. package/dist/web.d.ts +11 -8
  220. package/dist/web.js +5 -3
  221. package/package.json +18 -6
@@ -7,12 +7,72 @@ const require_io = require("./io.cjs");
7
7
  const require_index = require("./utils/index.cjs");
8
8
  const require_algo = require("./algo.cjs");
9
9
  const require_debug = require("./debug.cjs");
10
+ const require_replay = require("./replay.cjs");
10
11
  const require_stream = require("./stream.cjs");
11
12
  let _langchain_langgraph_checkpoint = require("@langchain/langgraph-checkpoint");
13
+ let uuid = require("uuid");
14
+ let _langchain_core_messages = require("@langchain/core/messages");
12
15
  //#region src/pregel/loop.ts
13
16
  const INPUT_DONE = Symbol.for("INPUT_DONE");
14
17
  const INPUT_RESUMING = Symbol.for("INPUT_RESUMING");
15
18
  const DEFAULT_LOOP_LIMIT = 25;
19
+ /**
20
+ * Recursively assign a stable UUID to any {@link BaseMessage} (in a value, an
21
+ * array, or an object's values) that is missing an `id`. Used so DeltaChannel
22
+ * writes — replayed on every read — reconstruct identical message identities.
23
+ */
24
+ function ensureMessageIds(value) {
25
+ if (value == null || typeof value !== "object") return;
26
+ if (_langchain_core_messages.BaseMessage.isInstance(value)) {
27
+ const msg = value;
28
+ if (msg.id == null) {
29
+ msg.id = (0, uuid.v4)();
30
+ if (msg.lc_kwargs != null) msg.lc_kwargs.id = msg.id;
31
+ }
32
+ return;
33
+ }
34
+ if (Array.isArray(value)) {
35
+ for (const item of value) ensureMessageIds(item);
36
+ return;
37
+ }
38
+ }
39
+ /**
40
+ * Split a serialized checkpoint namespace into its path segments.
41
+ *
42
+ * Checkpoint namespaces are stored as a single string whose nested levels are
43
+ * joined by {@link CHECKPOINT_NAMESPACE_SEPARATOR} (e.g. `"parent|child"`).
44
+ * The root namespace — represented as `undefined` or the empty string — maps
45
+ * to an empty array.
46
+ *
47
+ * @param ns - The serialized checkpoint namespace, or `undefined`.
48
+ * @returns The namespace as an array of path segments (`[]` for the root).
49
+ */
50
+ function checkpointNamespaceFromNs(ns) {
51
+ if (ns === void 0 || ns === "") return [];
52
+ return ns.split("|");
53
+ }
54
+ /**
55
+ * Find the most deeply nested namespace recorded in a checkpoint map.
56
+ *
57
+ * The checkpoint map ({@link CONFIG_KEY_CHECKPOINT_MAP}) associates every
58
+ * namespace seen on a thread with its checkpoint id. Because nested namespaces
59
+ * are built by appending segments to their parent, a deeper namespace always
60
+ * yields a longer key — so the longest non-empty key is the deepest one.
61
+ *
62
+ * Used by the loop's `#interruptStreamNamespace()` during subgraph
63
+ * time-travel: interrupt events must be emitted against the active (deepest)
64
+ * subgraph namespace rather than the root graph.
65
+ *
66
+ * @param map - The checkpoint map (namespace -> checkpoint id), or `undefined`.
67
+ * @returns The deepest namespace as path segments, or `[]` when the map is
68
+ * absent, empty, or only contains the root namespace.
69
+ */
70
+ function deepestCheckpointMapNamespace(map) {
71
+ if (!map) return [];
72
+ let deepest = "";
73
+ for (const key of Object.keys(map)) if (key !== "" && key.length > deepest.length) deepest = key;
74
+ return checkpointNamespaceFromNs(deepest);
75
+ }
16
76
  var AsyncBatchedCache = class extends _langchain_langgraph_checkpoint.BaseCache {
17
77
  cache;
18
78
  queue = Promise.resolve();
@@ -49,6 +109,15 @@ var PregelLoop = class PregelLoop {
49
109
  channels;
50
110
  checkpoint;
51
111
  checkpointIdSaved;
112
+ /**
113
+ * Exit-mode accumulator of DeltaChannel writes across the whole run, as
114
+ * `[step, taskId, channel, value]`. `undefined` outside "exit" durability.
115
+ */
116
+ _exitDeltaWrites;
117
+ /** Whether a real checkpoint was loaded from the saver at initialization. */
118
+ _hasPersistedParent = false;
119
+ /** The checkpointConfig as captured at initialization (anchor for exit writes). */
120
+ _initialCheckpointConfig;
52
121
  checkpointConfig;
53
122
  checkpointMetadata;
54
123
  checkpointNamespace;
@@ -64,10 +133,18 @@ var PregelLoop = class PregelLoop {
64
133
  prevCheckpointConfig;
65
134
  updatedChannels;
66
135
  status = "pending";
136
+ /**
137
+ * Run-scoped control surface for cooperative draining. Populated from the
138
+ * run config. When `control.drainRequested` is true, the loop stops at the
139
+ * next superstep boundary instead of dispatching more tasks.
140
+ */
141
+ control;
67
142
  tasks = {};
68
143
  stream;
69
144
  checkpointerPromises = /* @__PURE__ */ new Set();
70
145
  isNested;
146
+ /** True when an explicit checkpoint_id targets the latest saved checkpoint. */
147
+ resumeAtHead;
71
148
  _checkpointerChainedPromise = Promise.resolve();
72
149
  /**
73
150
  * Track a checkpointer promise, removing it from the set on success.
@@ -107,6 +184,9 @@ var PregelLoop = class PregelLoop {
107
184
  const runIdMatchesPrevious = !this.isNested && this.config.metadata?.run_id !== void 0 && this.checkpointMetadata?.run_id !== void 0 && this.config.metadata.run_id === this.checkpointMetadata?.run_id;
108
185
  return hasChannelVersions && (configIsResuming || inputIsNullOrUndefined || inputIsCommandResuming || inputIsResuming || runIdMatchesPrevious);
109
186
  }
187
+ get isReplaying() {
188
+ return !this.skipDoneTasks;
189
+ }
110
190
  constructor(params) {
111
191
  this.input = params.input;
112
192
  this.checkpointer = params.checkpointer;
@@ -122,6 +202,7 @@ var PregelLoop = class PregelLoop {
122
202
  this.config = params.config;
123
203
  this.checkpointConfig = params.checkpointConfig;
124
204
  this.isNested = params.isNested;
205
+ this.resumeAtHead = params.resumeAtHead;
125
206
  this.manager = params.manager;
126
207
  this.outputKeys = params.outputKeys;
127
208
  this.streamKeys = params.streamKeys;
@@ -137,6 +218,11 @@ var PregelLoop = class PregelLoop {
137
218
  this.durability = params.durability;
138
219
  this.debug = params.debug;
139
220
  this.triggerToNodes = params.triggerToNodes;
221
+ this.control = this.config.control;
222
+ this._exitDeltaWrites = this.durability === "exit" && this.checkpointer != null ? [] : void 0;
223
+ this._hasPersistedParent = params.hasPersistedParent ?? false;
224
+ this._initialCheckpointConfig = params.checkpointConfig;
225
+ this.checkpointIdSaved = params.checkpoint.id;
140
226
  }
141
227
  static async initialize(params) {
142
228
  let { config, stream } = params;
@@ -147,15 +233,24 @@ var PregelLoop = class PregelLoop {
147
233
  if (scratchpad.subgraphCounter > 0) config = require_index.patchConfigurable(config, { [require_constants.CONFIG_KEY_CHECKPOINT_NS]: [config.configurable[require_constants.CONFIG_KEY_CHECKPOINT_NS], scratchpad.subgraphCounter.toString()].join("|") });
148
234
  scratchpad.subgraphCounter += 1;
149
235
  }
236
+ const requestedCheckpointId = config.configurable?.checkpoint_id;
150
237
  const isNested = require_constants.CONFIG_KEY_READ in (config.configurable ?? {});
151
238
  if (!isNested && config.configurable?.checkpoint_ns !== void 0 && config.configurable?.checkpoint_ns !== "") config = require_index.patchConfigurable(config, {
152
239
  checkpoint_ns: "",
153
240
  checkpoint_id: void 0
154
241
  });
155
242
  let checkpointConfig = config;
156
- if (config.configurable?.["checkpoint_map"] !== void 0 && config.configurable?.["checkpoint_map"]?.[config.configurable?.checkpoint_ns]) checkpointConfig = require_index.patchConfigurable(config, { checkpoint_id: config.configurable[require_constants.CONFIG_KEY_CHECKPOINT_MAP][config.configurable?.checkpoint_ns] });
157
- const checkpointNamespace = config.configurable?.checkpoint_ns?.split("|") ?? [];
158
- const saved = await params.checkpointer?.getTuple(checkpointConfig) ?? {
243
+ if (config.configurable?.checkpoint_id === void 0 && config.configurable?.["checkpoint_map"] !== void 0 && config.configurable?.["checkpoint_map"]?.[config.configurable?.checkpoint_ns]) checkpointConfig = require_index.patchConfigurable(config, { checkpoint_id: config.configurable[require_constants.CONFIG_KEY_CHECKPOINT_MAP][config.configurable?.checkpoint_ns] });
244
+ const checkpointNamespace = checkpointNamespaceFromNs(config.configurable?.checkpoint_ns);
245
+ let saved;
246
+ if (!params.checkpointer) saved = void 0;
247
+ else if (checkpointConfig.configurable?.["checkpoint_id"]) saved = await params.checkpointer.getTuple(checkpointConfig);
248
+ else if (config.configurable?.["__pregel_replay_state"]) {
249
+ saved = await config.configurable[require_constants.CONFIG_KEY_REPLAY_STATE].getCheckpoint(config.configurable?.["checkpoint_ns"] ?? "", params.checkpointer, checkpointConfig);
250
+ if (config.configurable) delete config.configurable[require_constants.CONFIG_KEY_RESUMING];
251
+ } else saved = await params.checkpointer.getTuple(checkpointConfig);
252
+ const hasPersistedParent = saved !== void 0;
253
+ if (!saved) saved = {
159
254
  config,
160
255
  checkpoint: (0, _langchain_langgraph_checkpoint.emptyCheckpoint)(),
161
256
  metadata: {
@@ -177,8 +272,21 @@ var PregelLoop = class PregelLoop {
177
272
  const prevCheckpointConfig = saved.parentConfig;
178
273
  const checkpoint = (0, _langchain_langgraph_checkpoint.copyCheckpoint)(saved.checkpoint);
179
274
  const checkpointMetadata = { ...saved.metadata };
180
- const checkpointPendingWrites = saved.pendingWrites ?? [];
181
- const channels = require_base.emptyChannels(params.channelSpecs, checkpoint);
275
+ let checkpointPendingWrites = saved.pendingWrites ?? [];
276
+ const currentCheckpointNamespace = config.configurable?.checkpoint_ns;
277
+ const checkpointMap = config.configurable?.[require_constants.CONFIG_KEY_CHECKPOINT_MAP];
278
+ if (typeof currentCheckpointNamespace === "string" && currentCheckpointNamespace !== "" && typeof checkpointMap === "object" && checkpointMap !== null && currentCheckpointNamespace in checkpointMap && checkpointPendingWrites.length > 0) checkpointPendingWrites = checkpointPendingWrites.filter(([, channel]) => channel !== require_constants.RESUME);
279
+ let resumeAtHead = false;
280
+ const threadId = checkpointConfig.configurable?.thread_id;
281
+ const checkpointNs = checkpointConfig.configurable?.checkpoint_ns ?? "";
282
+ if (params.checkpointer && requestedCheckpointId && typeof threadId === "string") resumeAtHead = (await params.checkpointer.getTuple({ configurable: {
283
+ thread_id: threadId,
284
+ checkpoint_ns: checkpointNs
285
+ } }))?.config.configurable?.checkpoint_id === requestedCheckpointId && checkpointMetadata.source !== "update" && checkpointMetadata.source !== "fork";
286
+ const channels = await require_base.channelsFromCheckpoint(params.channelSpecs, checkpoint, {
287
+ saver: params.checkpointer,
288
+ config: checkpointConfig
289
+ });
182
290
  const step = (checkpointMetadata.step ?? 0) + 1;
183
291
  const stop = step + (config.recursionLimit ?? DEFAULT_LOOP_LIMIT) + 1;
184
292
  const checkpointPreviousVersions = { ...checkpoint.channel_versions };
@@ -195,6 +303,7 @@ var PregelLoop = class PregelLoop {
195
303
  checkpointNamespace,
196
304
  channels,
197
305
  isNested,
306
+ resumeAtHead,
198
307
  manager: params.manager,
199
308
  skipDoneTasks,
200
309
  step,
@@ -211,7 +320,8 @@ var PregelLoop = class PregelLoop {
211
320
  interruptBefore: params.interruptBefore,
212
321
  durability: params.durability,
213
322
  debug: params.debug,
214
- triggerToNodes: params.triggerToNodes
323
+ triggerToNodes: params.triggerToNodes,
324
+ hasPersistedParent
215
325
  });
216
326
  }
217
327
  _checkpointerPutAfterPrevious(input) {
@@ -250,6 +360,10 @@ var PregelLoop = class PregelLoop {
250
360
  c,
251
361
  v
252
362
  ]);
363
+ for (const [c, v] of writesToSave) {
364
+ const channel = this.channels[c];
365
+ if (channel != null && require_base.isDeltaChannel(channel)) ensureMessageIds(v);
366
+ }
253
367
  const config = require_index.patchConfigurable(this.checkpointConfig, {
254
368
  [require_constants.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
255
369
  [require_constants.CONFIG_KEY_CHECKPOINT_ID]: this.checkpoint.id
@@ -309,7 +423,8 @@ var PregelLoop = class PregelLoop {
309
423
  /**
310
424
  * Execute a single iteration of the Pregel loop.
311
425
  * Returns true if more iterations are needed.
312
- * @param params
426
+ * @param params - The input keys to use for the tick.
427
+ * @returns True if more iterations are needed, false otherwise.
313
428
  */
314
429
  async tick(params) {
315
430
  if (this.store && !this.store.isRunning) await this.store?.start();
@@ -320,13 +435,23 @@ var PregelLoop = class PregelLoop {
320
435
  this.status = "interrupt_before";
321
436
  throw new require_errors.GraphInterrupt();
322
437
  } else if (Object.values(this.tasks).every((task) => task.writes.length > 0)) {
323
- const writes = Object.values(this.tasks).flatMap((t) => t.writes);
324
- this.updatedChannels = require_algo._applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
438
+ const finishTaskList = Object.values(this.tasks);
439
+ const writes = finishTaskList.flatMap((t) => t.writes);
440
+ this.updatedChannels = require_algo._applyWrites(this.checkpoint, this.channels, finishTaskList, this.checkpointerGetNextVersion, this.triggerToNodes);
325
441
  const valuesOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_io.mapOutputValues(this.outputKeys, writes, this.channels), "values"));
442
+ if (this._exitDeltaWrites !== void 0) for (const [tid, ch, v] of this.checkpointPendingWrites) {
443
+ const channel = this.channels[ch];
444
+ if (channel != null && require_base.isDeltaChannel(channel)) this._exitDeltaWrites.push([
445
+ this.step,
446
+ tid,
447
+ ch,
448
+ v
449
+ ]);
450
+ }
326
451
  this.checkpointPendingWrites = [];
327
452
  await this._putCheckpoint({ source: "loop" });
328
453
  this._emitValuesWithCheckpointMeta(valuesOutput);
329
- if (require_algo.shouldInterrupt(this.checkpoint, this.interruptAfter, Object.values(this.tasks))) {
454
+ if (require_algo.shouldInterrupt(this.checkpoint, this.interruptAfter, finishTaskList)) {
330
455
  this.status = "interrupt_after";
331
456
  throw new require_errors.GraphInterrupt();
332
457
  }
@@ -346,30 +471,40 @@ var PregelLoop = class PregelLoop {
346
471
  triggerToNodes: this.triggerToNodes,
347
472
  updatedChannels: this.updatedChannels
348
473
  });
349
- if (this.checkpointer) this._emit(await require_utils.gatherIterator(require_utils.prefixGenerator(require_debug.mapDebugCheckpoint(this.checkpointConfig, this.channels, this.streamKeys, this.checkpointMetadata, Object.values(this.tasks), this.checkpointPendingWrites, this.prevCheckpointConfig, this.outputKeys), "checkpoints")));
350
- if (Object.values(this.tasks).length === 0) {
474
+ let taskList = Object.values(this.tasks);
475
+ if (this.checkpointer && (this.stream.modes.has("checkpoints") || this.stream.modes.has("debug"))) this._emit(await require_utils.gatherIterator(require_utils.prefixGenerator(require_debug.mapDebugCheckpoint(this.checkpointConfig, this.channels, this.streamKeys, this.checkpointMetadata, taskList, this.checkpointPendingWrites, this.prevCheckpointConfig, this.outputKeys), "checkpoints")));
476
+ if (taskList.length === 0) {
351
477
  this.status = "done";
352
478
  return false;
353
479
  }
480
+ if (this.control != null && this.control.drainRequested) {
481
+ this.status = "draining";
482
+ return false;
483
+ }
354
484
  if (this.skipDoneTasks && this.checkpointPendingWrites.length > 0) {
355
485
  for (const [tid, k, v] of this.checkpointPendingWrites) {
356
- if (k === "__error__" || k === "__interrupt__" || k === "__resume__") continue;
357
- const task = Object.values(this.tasks).find((t) => t.id === tid);
486
+ if (k === "__error__" || k === "__error_source_node__" || k === "__interrupt__" || k === "__resume__") continue;
487
+ const task = taskList.find((t) => t.id === tid);
358
488
  if (task) task.writes.push([k, v]);
359
489
  }
360
- for (const task of Object.values(this.tasks)) if (task.writes.length > 0) this._outputWrites(task.id, task.writes, true);
490
+ this._resumeErrorHandlersIfApplicable();
491
+ taskList = Object.values(this.tasks);
492
+ for (const task of taskList) if (task.writes.length > 0) this._outputWrites(task.id, task.writes, true);
361
493
  }
362
- if (Object.values(this.tasks).every((task) => task.writes.length > 0)) return this.tick({ inputKeys });
363
- if (require_algo.shouldInterrupt(this.checkpoint, this.interruptBefore, Object.values(this.tasks))) {
494
+ if (taskList.every((task) => task.writes.length > 0)) return this.tick({ inputKeys });
495
+ if (require_algo.shouldInterrupt(this.checkpoint, this.interruptBefore, taskList)) {
364
496
  this.status = "interrupt_before";
365
497
  throw new require_errors.GraphInterrupt();
366
498
  }
367
- const debugOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_debug.mapDebugTasks(Object.values(this.tasks)), "tasks"));
368
- this._emit(debugOutput);
499
+ if (this.stream.modes.has("tasks") || this.stream.modes.has("debug")) {
500
+ const debugOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_debug.mapDebugTasks(taskList), "tasks"));
501
+ this._emit(debugOutput);
502
+ }
369
503
  return true;
370
504
  }
371
505
  async finishAndHandleError(error) {
372
506
  if (this.durability === "exit" && (!this.isNested || typeof error !== "undefined" || this.checkpointNamespace.every((part) => !part.includes(":")))) {
507
+ await this._putExitDeltaWrites();
373
508
  this._putCheckpoint(this.checkpointMetadata);
374
509
  this._flushPendingWrites();
375
510
  }
@@ -380,7 +515,7 @@ var PregelLoop = class PregelLoop {
380
515
  this.updatedChannels = require_algo._applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
381
516
  this._emitValuesWithCheckpointMeta(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_io.mapOutputValues(this.outputKeys, Object.values(this.tasks).flatMap((t) => t.writes), this.channels), "values")));
382
517
  }
383
- if (require_errors.isGraphInterrupt(error) && !error.interrupts.length) this._emit([["updates", { [require_constants.INTERRUPT]: [] }], ["values", { [require_constants.INTERRUPT]: [] }]]);
518
+ if (require_errors.isGraphInterrupt(error) && !error.interrupts.length) this._emit([["updates", { [require_constants.INTERRUPT]: [] }], ["values", { [require_constants.INTERRUPT]: [] }]], this.#interruptStreamNamespace());
384
519
  }
385
520
  return suppress;
386
521
  }
@@ -407,7 +542,7 @@ var PregelLoop = class PregelLoop {
407
542
  this.toInterrupt.push(pushed);
408
543
  return;
409
544
  }
410
- this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_debug.mapDebugTasks([pushed]), "tasks")));
545
+ if (this.stream.modes.has("tasks") || this.stream.modes.has("debug")) this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_debug.mapDebugTasks([pushed]), "tasks")));
411
546
  if (this.debug) require_debug.printStepTasks(this.step, [pushed]);
412
547
  this.tasks[pushed.id] = pushed;
413
548
  if (this.skipDoneTasks) this._matchWrites({ [pushed.id]: pushed });
@@ -415,6 +550,74 @@ var PregelLoop = class PregelLoop {
415
550
  for (const { task } of tasks) this._outputWrites(task.id, task.writes, true);
416
551
  return pushed;
417
552
  }
553
+ /**
554
+ * Returns the name of the error handler node registered for `nodeName`, or
555
+ * `undefined` if none is configured.
556
+ */
557
+ getErrorHandlerNode(nodeName) {
558
+ return this.nodes[nodeName]?.errorHandlerNode;
559
+ }
560
+ /**
561
+ * Whether `nodeName` is itself an auto-generated error handler node.
562
+ */
563
+ isErrorHandlerNode(nodeName) {
564
+ return this.nodes[nodeName]?.isErrorHandler === true;
565
+ }
566
+ /**
567
+ * Schedule a node-level error handler task for a task that failed after its
568
+ * retry policy was exhausted. Prepares the handler task (injecting a
569
+ * {@link NodeError}), registers it so the runner executes it within the
570
+ * current step, and returns it (or `undefined` if no handler applies).
571
+ *
572
+ * The failure provenance (`ERROR` + `ERROR_SOURCE_NODE`) is checkpointed by
573
+ * the runner via {@link PregelLoop#putWrites} so handlers observe the same
574
+ * context after a resume.
575
+ */
576
+ scheduleErrorHandler(failedTask, error) {
577
+ const handlerNode = this.getErrorHandlerNode(String(failedTask.name));
578
+ if (!handlerNode) return void 0;
579
+ const handlerTask = require_algo._prepareNodeErrorHandlerTask(failedTask, handlerNode, error, this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, failedTask.config ?? this.config, {
580
+ step: this.step,
581
+ checkpointer: this.checkpointer,
582
+ manager: this.manager,
583
+ store: this.store,
584
+ stream: this.stream
585
+ });
586
+ if (handlerTask === void 0) return void 0;
587
+ this.tasks[handlerTask.id] = handlerTask;
588
+ this._emit(require_utils.gatherIteratorSync(require_utils.prefixGenerator(require_debug.mapDebugTasks([handlerTask]), "tasks")));
589
+ if (this.debug) require_debug.printStepTasks(this.step, [handlerTask]);
590
+ return handlerTask;
591
+ }
592
+ /**
593
+ * On resume, re-schedule error handlers for tasks that failed in a prior run
594
+ * but had not finished being handled. Scans pending writes for
595
+ * `ERROR_SOURCE_NODE` markers (paired with `ERROR`), marks the originating
596
+ * task as done (so the runner won't re-run it), and prepares a fresh handler
597
+ * task so the runner picks it up.
598
+ */
599
+ _resumeErrorHandlersIfApplicable() {
600
+ const failed = /* @__PURE__ */ new Map();
601
+ for (const [tid, chan] of this.checkpointPendingWrites) {
602
+ if (chan !== "__error_source_node__") continue;
603
+ const errorWrite = this.checkpointPendingWrites.find(([t, c]) => t === tid && c === "__error__");
604
+ if (errorWrite === void 0) continue;
605
+ const value = errorWrite[2];
606
+ const error = new Error(value?.message ?? String(value));
607
+ if (value?.name) error.name = value.name;
608
+ failed.set(tid, error);
609
+ }
610
+ for (const [tid, error] of failed) {
611
+ const task = this.tasks[tid];
612
+ if (task === void 0) continue;
613
+ if (!this.getErrorHandlerNode(String(task.name))) continue;
614
+ if (task.writes.length === 0) task.writes.push([require_constants.ERROR, {
615
+ message: error.message,
616
+ name: error.name
617
+ }]);
618
+ this.scheduleErrorHandler(task, error);
619
+ }
620
+ }
418
621
  _suppressInterrupt(e) {
419
622
  return require_errors.isGraphInterrupt(e) && !this.isNested;
420
623
  }
@@ -443,20 +646,24 @@ var PregelLoop = class PregelLoop {
443
646
  writes: nullWrites,
444
647
  triggers: []
445
648
  }], this.checkpointerGetNextVersion, this.triggerToNodes);
446
- const isCommandUpdateOrGoto = require_constants.isCommand(this.input) && nullWrites.length > 0;
447
- if (this.isResuming || isCommandUpdateOrGoto) {
649
+ const inputIsCommand = require_constants.isCommand(this.input);
650
+ const isCommandUpdateOrGoto = inputIsCommand && nullWrites.length > 0;
651
+ const isTimeTraveling = this.isReplaying && (this.isNested && configurable?.["checkpoint_ns"] !== void 0 && configurable?.["checkpoint_ns"] !== "" && configurable?.["checkpoint_map"] !== void 0 && configurable["checkpoint_ns"] in configurable["checkpoint_map"] || !(inputIsCommand && this.input.resume != null || configurable?.["__pregel_resuming"] === true || this.resumeAtHead));
652
+ if (isTimeTraveling) this.checkpointPendingWrites = this.checkpointPendingWrites.filter((w) => w[1] !== require_constants.RESUME);
653
+ const cachedIsResuming = this.isResuming;
654
+ if (cachedIsResuming || isCommandUpdateOrGoto) {
655
+ const interruptSeen = { ...this.checkpoint.versions_seen[require_constants.INTERRUPT] };
448
656
  for (const channelName in this.channels) {
449
657
  if (!Object.prototype.hasOwnProperty.call(this.channels, channelName)) continue;
450
- if (this.checkpoint.channel_versions[channelName] !== void 0) {
451
- const version = this.checkpoint.channel_versions[channelName];
452
- this.checkpoint.versions_seen[require_constants.INTERRUPT] = {
453
- ...this.checkpoint.versions_seen[require_constants.INTERRUPT],
454
- [channelName]: version
455
- };
456
- }
658
+ if (this.checkpoint.channel_versions[channelName] !== void 0) interruptSeen[channelName] = this.checkpoint.channel_versions[channelName];
659
+ }
660
+ this.checkpoint.versions_seen[require_constants.INTERRUPT] = interruptSeen;
661
+ if (isTimeTraveling && this.checkpointMetadata.source !== "update" && this.checkpointMetadata.source !== "fork") {
662
+ this.checkpointPendingWrites = this.checkpointPendingWrites.filter((w) => w[1] !== require_constants.INTERRUPT);
663
+ await this._putCheckpoint({ source: "fork" });
457
664
  }
458
665
  const valuesOutput = await require_utils.gatherIterator(require_utils.prefixGenerator(require_io.mapOutputValues(this.outputKeys, true, this.channels), "values"));
459
- if (this.isResuming) this.input = INPUT_RESUMING;
666
+ if (cachedIsResuming) this.input = INPUT_RESUMING;
460
667
  else if (isCommandUpdateOrGoto) {
461
668
  await this._putCheckpoint({ source: "input" });
462
669
  this.input = INPUT_DONE;
@@ -471,17 +678,47 @@ var PregelLoop = class PregelLoop {
471
678
  writes: inputWrites,
472
679
  triggers: []
473
680
  }]), this.checkpointerGetNextVersion, this.triggerToNodes);
681
+ const deltaInput = inputWrites.filter(([c]) => {
682
+ const channel = this.channels[c];
683
+ return channel != null && require_base.isDeltaChannel(channel);
684
+ });
685
+ if (deltaInput.length > 0) {
686
+ if (this._exitDeltaWrites !== void 0) for (const [c, v] of deltaInput) this._exitDeltaWrites.push([
687
+ this.step,
688
+ require_constants.NULL_TASK_ID,
689
+ c,
690
+ v
691
+ ]);
692
+ else if (this.checkpointer != null) this.putWrites(require_constants.NULL_TASK_ID, deltaInput);
693
+ }
474
694
  await this._putCheckpoint({ source: "input" });
475
695
  this.input = INPUT_DONE;
476
696
  } else if (!("__pregel_resuming" in (this.config.configurable ?? {}))) throw new require_errors.EmptyInputError(`Received no input writes for ${JSON.stringify(inputKeys, null, 2)}`);
477
697
  else this.input = INPUT_DONE;
478
698
  }
479
- if (!this.isNested) this.config = require_index.patchConfigurable(this.config, { [require_constants.CONFIG_KEY_RESUMING]: this.isResuming });
699
+ if (!this.isNested) {
700
+ let replayState;
701
+ if (isTimeTraveling) {
702
+ let replayCheckpointId = this.checkpoint.id;
703
+ if ((this.checkpointMetadata.source === "update" || this.checkpointMetadata.source === "fork") && this.prevCheckpointConfig) replayCheckpointId = this.prevCheckpointConfig.configurable?.["checkpoint_id"] ?? replayCheckpointId;
704
+ replayState = new require_replay.ReplayState(replayCheckpointId);
705
+ }
706
+ this.config = require_index.patchConfigurable(this.config, {
707
+ [require_constants.CONFIG_KEY_RESUMING]: this.isResuming,
708
+ [require_constants.CONFIG_KEY_REPLAY_STATE]: replayState
709
+ });
710
+ }
711
+ }
712
+ #interruptStreamNamespace() {
713
+ const ns = this.checkpointNamespace;
714
+ if (!(ns.length === 0 || ns.length === 1 && ns[0] === "") || this.config.configurable?.["__pregel_stream"] === void 0) return ns;
715
+ const deepest = deepestCheckpointMapNamespace(this.config.configurable?.[require_constants.CONFIG_KEY_CHECKPOINT_MAP]);
716
+ return deepest.length > 0 ? deepest : ns;
480
717
  }
481
- _emit(values) {
718
+ _emit(values, namespace = this.checkpointNamespace) {
482
719
  for (const [mode, payload] of values) {
483
720
  if (this.stream.modes.has(mode)) this.stream.push([
484
- this.checkpointNamespace,
721
+ namespace,
485
722
  mode,
486
723
  payload
487
724
  ]);
@@ -494,7 +731,7 @@ var PregelLoop = class PregelLoop {
494
731
  else return "task";
495
732
  })();
496
733
  this.stream.push([
497
- this.checkpointNamespace,
734
+ namespace,
498
735
  "debug",
499
736
  {
500
737
  step,
@@ -564,15 +801,99 @@ var PregelLoop = class PregelLoop {
564
801
  }
565
802
  };
566
803
  };
567
- if (!exiting) this.checkpointMetadata = {
568
- ...inputMetadata,
569
- step: this.step,
570
- parents: this.config.configurable?.["checkpoint_map"] ?? {}
571
- };
572
- this.checkpoint = require_base.createCheckpoint(this.checkpoint, doCheckpoint ? this.channels : void 0, this.step, exiting ? { id: this.checkpoint.id } : void 0);
804
+ let newCounters;
805
+ if (!exiting) {
806
+ const prevCounters = this.checkpointMetadata.counters_since_delta_snapshot ?? {};
807
+ newCounters = {};
808
+ const updated = this.updatedChannels ?? /* @__PURE__ */ new Set();
809
+ for (const chName in this.channels) {
810
+ if (!Object.prototype.hasOwnProperty.call(this.channels, chName)) continue;
811
+ if (!require_base.isDeltaChannel(this.channels[chName])) continue;
812
+ const [u, s] = prevCounters[chName] ?? [0, 0];
813
+ newCounters[chName] = [updated.has(chName) ? u + 1 : u, s + 1];
814
+ }
815
+ this.checkpointMetadata = {
816
+ ...inputMetadata,
817
+ step: this.step,
818
+ parents: this.config.configurable?.["checkpoint_map"] ?? {}
819
+ };
820
+ } else newCounters = { ...this.checkpointMetadata.counters_since_delta_snapshot ?? {} };
821
+ const channelsToSnapshot = doCheckpoint ? require_base.deltaChannelsToSnapshot(this.channels, newCounters) : /* @__PURE__ */ new Set();
822
+ this.checkpoint = require_base.createCheckpoint(this.checkpoint, doCheckpoint ? this.channels : void 0, this.step, {
823
+ id: exiting ? this.checkpoint.id : void 0,
824
+ channelsToSnapshot,
825
+ updatedChannels: this.updatedChannels,
826
+ getNextVersion: doCheckpoint ? (current) => this.checkpointerGetNextVersion(current) : void 0
827
+ });
828
+ for (const k of channelsToSnapshot) newCounters[k] = [0, 0];
829
+ const nonZero = {};
830
+ for (const k in newCounters) {
831
+ if (!Object.prototype.hasOwnProperty.call(newCounters, k)) continue;
832
+ const [u, s] = newCounters[k];
833
+ if (u !== 0 || s !== 0) nonZero[k] = [u, s];
834
+ }
835
+ if (Object.keys(nonZero).length > 0) this.checkpointMetadata.counters_since_delta_snapshot = nonZero;
836
+ else delete this.checkpointMetadata.counters_since_delta_snapshot;
573
837
  if (doCheckpoint) storeCheckpoint(this.checkpoint);
574
838
  if (!exiting) this.step += 1;
575
839
  }
840
+ /**
841
+ * Stage the exit-mode accumulator of DeltaChannel writes so the final
842
+ * checkpoint can be reconstructed. In "exit" durability per-step writes are
843
+ * not persisted, so delta writes are accumulated across the run and anchored
844
+ * here — under the saved parent, or a freshly-created stub when this is a
845
+ * first run with no persisted parent. Channels that will snapshot in the
846
+ * final checkpoint are excluded (their full value lives in `channel_values`).
847
+ *
848
+ * Must run BEFORE the final `_putCheckpoint` so the stub branch can adjust
849
+ * `checkpointConfig` to anchor the final checkpoint on the stub.
850
+ */
851
+ async _putExitDeltaWrites() {
852
+ if (this._exitDeltaWrites === void 0 || this._exitDeltaWrites.length === 0 || this.checkpointer == null || this._initialCheckpointConfig === void 0) return;
853
+ const counters = this.checkpointMetadata.counters_since_delta_snapshot ?? {};
854
+ const channelsToSnapshot = require_base.deltaChannelsToSnapshot(this.channels, counters);
855
+ const pending = this._exitDeltaWrites.filter(([, , ch]) => !channelsToSnapshot.has(ch));
856
+ if (pending.length === 0) return;
857
+ let anchorConfig;
858
+ if (this._hasPersistedParent) anchorConfig = this._initialCheckpointConfig;
859
+ else {
860
+ const stubCp = (0, _langchain_langgraph_checkpoint.emptyCheckpoint)();
861
+ stubCp.id = this.checkpointIdSaved ?? stubCp.id;
862
+ stubCp.ts = (/* @__PURE__ */ new Date()).toISOString();
863
+ const stubPutConfig = require_index.patchConfigurable(this._initialCheckpointConfig, { [require_constants.CONFIG_KEY_CHECKPOINT_ID]: void 0 });
864
+ anchorConfig = require_index.patchConfigurable(this._initialCheckpointConfig, { [require_constants.CONFIG_KEY_CHECKPOINT_ID]: stubCp.id });
865
+ this._trackCheckpointerPromise(this.checkpointer.put(stubPutConfig, stubCp, {
866
+ source: "loop",
867
+ step: -2,
868
+ parents: {}
869
+ }, {}));
870
+ this.checkpointConfig = anchorConfig;
871
+ }
872
+ const anchorWriteConfig = require_index.patchConfigurable(anchorConfig, {
873
+ [require_constants.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
874
+ [require_constants.CONFIG_KEY_CHECKPOINT_ID]: anchorConfig.configurable?.[require_constants.CONFIG_KEY_CHECKPOINT_ID]
875
+ });
876
+ const grouped = /* @__PURE__ */ new Map();
877
+ const order = [];
878
+ for (const [step, tid, ch, v] of pending) {
879
+ const key = `${step}\u0000${tid}`;
880
+ let group = grouped.get(key);
881
+ if (group === void 0) {
882
+ group = [];
883
+ grouped.set(key, group);
884
+ order.push({
885
+ key,
886
+ step,
887
+ tid
888
+ });
889
+ }
890
+ group.push([ch, v]);
891
+ }
892
+ for (const { key, step, tid } of order) {
893
+ const synthTid = `${String(step).padStart(8, "0")}-${tid}`;
894
+ this._trackCheckpointerPromise(this.checkpointer.putWrites(anchorWriteConfig, grouped.get(key), synthTid));
895
+ }
896
+ }
576
897
  _flushPendingWrites() {
577
898
  if (this.checkpointer == null) return;
578
899
  if (this.checkpointPendingWrites.length === 0) return;