@langchain/langgraph 0.3.12 → 0.4.1

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 (76) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/channels/base.cjs +1 -2
  3. package/dist/channels/base.js +1 -2
  4. package/dist/channels/base.js.map +1 -1
  5. package/dist/channels/topic.cjs +5 -5
  6. package/dist/channels/topic.js +5 -5
  7. package/dist/channels/topic.js.map +1 -1
  8. package/dist/constants.cjs +3 -3
  9. package/dist/constants.d.ts +2 -5
  10. package/dist/constants.js +2 -2
  11. package/dist/constants.js.map +1 -1
  12. package/dist/errors.cjs +1 -1
  13. package/dist/errors.js +1 -1
  14. package/dist/errors.js.map +1 -1
  15. package/dist/graph/annotation.cjs +1 -5
  16. package/dist/graph/annotation.d.ts +4 -5
  17. package/dist/graph/annotation.js +1 -5
  18. package/dist/graph/annotation.js.map +1 -1
  19. package/dist/graph/graph.cjs +1 -3
  20. package/dist/graph/graph.d.ts +3 -3
  21. package/dist/graph/graph.js +1 -3
  22. package/dist/graph/graph.js.map +1 -1
  23. package/dist/graph/state.cjs +6 -10
  24. package/dist/graph/state.d.ts +8 -8
  25. package/dist/graph/state.js +7 -11
  26. package/dist/graph/state.js.map +1 -1
  27. package/dist/interrupt.cjs +2 -13
  28. package/dist/interrupt.js +2 -13
  29. package/dist/interrupt.js.map +1 -1
  30. package/dist/prebuilt/agent_executor.d.ts +22 -1
  31. package/dist/prebuilt/agent_executor.js.map +1 -1
  32. package/dist/pregel/algo.cjs +42 -71
  33. package/dist/pregel/algo.d.ts +9 -10
  34. package/dist/pregel/algo.js +42 -71
  35. package/dist/pregel/algo.js.map +1 -1
  36. package/dist/pregel/index.cjs +56 -92
  37. package/dist/pregel/index.d.ts +12 -30
  38. package/dist/pregel/index.js +57 -93
  39. package/dist/pregel/index.js.map +1 -1
  40. package/dist/pregel/loop.cjs +25 -86
  41. package/dist/pregel/loop.d.ts +5 -11
  42. package/dist/pregel/loop.js +25 -86
  43. package/dist/pregel/loop.js.map +1 -1
  44. package/dist/pregel/remote.cjs +13 -11
  45. package/dist/pregel/remote.d.ts +13 -16
  46. package/dist/pregel/remote.js +13 -11
  47. package/dist/pregel/remote.js.map +1 -1
  48. package/dist/pregel/runnable_types.d.ts +15 -2
  49. package/dist/pregel/types.d.ts +23 -10
  50. package/dist/pregel/types.js.map +1 -1
  51. package/dist/pregel/utils/config.cjs +2 -0
  52. package/dist/pregel/utils/config.js +2 -0
  53. package/dist/pregel/utils/config.js.map +1 -1
  54. package/dist/pregel/validate.d.ts +2 -3
  55. package/dist/pregel/validate.js.map +1 -1
  56. package/dist/web.cjs +0 -1
  57. package/dist/web.d.ts +1 -2
  58. package/dist/web.js +0 -1
  59. package/dist/web.js.map +1 -1
  60. package/package.json +7 -6
  61. package/dist/managed/base.cjs +0 -177
  62. package/dist/managed/base.d.ts +0 -38
  63. package/dist/managed/base.js +0 -168
  64. package/dist/managed/base.js.map +0 -1
  65. package/dist/managed/index.cjs +0 -20
  66. package/dist/managed/index.d.ts +0 -3
  67. package/dist/managed/index.js +0 -4
  68. package/dist/managed/index.js.map +0 -1
  69. package/dist/managed/is_last_step.cjs +0 -12
  70. package/dist/managed/is_last_step.d.ts +0 -4
  71. package/dist/managed/is_last_step.js +0 -8
  72. package/dist/managed/is_last_step.js.map +0 -1
  73. package/dist/managed/shared_value.cjs +0 -112
  74. package/dist/managed/shared_value.d.ts +0 -24
  75. package/dist/managed/shared_value.js +0 -108
  76. package/dist/managed/shared_value.js.map +0 -1
@@ -41,8 +41,7 @@ function shouldInterrupt(checkpoint, interruptNodes, tasks) {
41
41
  : interruptNodes.includes(task.name));
42
42
  return anyChannelUpdated && anyTriggeredNodeInInterruptNodes;
43
43
  }
44
- function _localRead(step, checkpoint, channels, managed, task, select, fresh = false) {
45
- let managedKeys = [];
44
+ function _localRead(checkpoint, channels, task, select, fresh = false) {
46
45
  let updated = new Set();
47
46
  if (!Array.isArray(select)) {
48
47
  for (const [c] of task.writes) {
@@ -54,8 +53,6 @@ function _localRead(step, checkpoint, channels, managed, task, select, fresh = f
54
53
  updated = updated || new Set();
55
54
  }
56
55
  else {
57
- managedKeys = select.filter((k) => managed.get(k));
58
- select = select.filter((k) => !managed.get(k));
59
56
  updated = new Set(select.filter((c) => task.writes.some(([key, _]) => key === c)));
60
57
  }
61
58
  let values;
@@ -69,20 +66,11 @@ function _localRead(step, checkpoint, channels, managed, task, select, fresh = f
69
66
  else {
70
67
  values = (0, io_js_1.readChannels)(channels, select);
71
68
  }
72
- if (managedKeys.length > 0) {
73
- for (const k of managedKeys) {
74
- const managedValue = managed.get(k);
75
- if (managedValue) {
76
- const resultOfManagedCall = managedValue.call(step);
77
- values[k] = resultOfManagedCall;
78
- }
79
- }
80
- }
81
69
  return values;
82
70
  }
83
- function _localWrite(step,
71
+ function _localWrite(
84
72
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
- commit, processes, managed,
73
+ commit, processes,
86
74
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
75
  writes) {
88
76
  for (const [chan, value] of writes) {
@@ -93,8 +81,6 @@ writes) {
93
81
  if (!(value.node in processes)) {
94
82
  throw new errors_js_1.InvalidUpdateError(`Invalid node name "${value.node}" in Send packet`);
95
83
  }
96
- // replace any runtime values with placeholders
97
- managed.replaceRuntimeValues(step, value.args);
98
84
  }
99
85
  }
100
86
  commit(writes);
@@ -152,47 +138,32 @@ getNextVersion, triggerToNodes) {
152
138
  for (const chan of channelsToConsume) {
153
139
  if (chan in onlyChannels && onlyChannels[chan].consume()) {
154
140
  if (getNextVersion !== undefined) {
155
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
141
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
156
142
  }
157
143
  }
158
144
  }
159
- // Clear pending sends
160
- if (checkpoint.pending_sends?.length && bumpStep) {
161
- checkpoint.pending_sends = [];
162
- }
163
145
  // Group writes by channel
164
- const pendingWriteValuesByChannel = {};
165
- const pendingWritesByManaged = {};
146
+ const pendingWritesByChannel = {};
166
147
  for (const task of tasks) {
167
148
  for (const [chan, val] of task.writes) {
168
149
  if (IGNORE.has(chan)) {
169
150
  // do nothing
170
151
  }
171
- else if (chan === constants_js_1.TASKS) {
172
- // TODO: remove branch in 1.0
173
- checkpoint.pending_sends.push({
174
- node: val.node,
175
- args: val.args,
176
- });
177
- }
178
152
  else if (chan in onlyChannels) {
179
- pendingWriteValuesByChannel[chan] ??= [];
180
- pendingWriteValuesByChannel[chan].push(val);
181
- }
182
- else {
183
- pendingWritesByManaged[chan] ??= [];
184
- pendingWritesByManaged[chan].push(val);
153
+ pendingWritesByChannel[chan] ??= [];
154
+ pendingWritesByChannel[chan].push(val);
185
155
  }
186
156
  }
187
157
  }
188
- // find the highest version of all channels
158
+ // Find the highest version of all channels
159
+ // TODO: figure out why we need to do this twice (Python only does this once)
189
160
  maxVersion = undefined;
190
161
  if (Object.keys(checkpoint.channel_versions).length > 0) {
191
162
  maxVersion = (0, langgraph_checkpoint_1.maxChannelVersion)(...Object.values(checkpoint.channel_versions));
192
163
  }
193
164
  const updatedChannels = new Set();
194
165
  // Apply writes to channels
195
- for (const [chan, vals] of Object.entries(pendingWriteValuesByChannel)) {
166
+ for (const [chan, vals] of Object.entries(pendingWritesByChannel)) {
196
167
  if (chan in onlyChannels) {
197
168
  let updated;
198
169
  try {
@@ -210,7 +181,7 @@ getNextVersion, triggerToNodes) {
210
181
  }
211
182
  }
212
183
  if (updated && getNextVersion !== undefined) {
213
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
184
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
214
185
  // unavailable channels can't trigger tasks, so don't add them
215
186
  if (onlyChannels[chan].isAvailable()) {
216
187
  updatedChannels.add(chan);
@@ -224,7 +195,7 @@ getNextVersion, triggerToNodes) {
224
195
  if (onlyChannels[chan].isAvailable() && !updatedChannels.has(chan)) {
225
196
  const updated = onlyChannels[chan].update([]);
226
197
  if (updated && getNextVersion !== undefined) {
227
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
198
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
228
199
  // unavailable channels can't trigger tasks, so don't add them
229
200
  if (onlyChannels[chan].isAvailable()) {
230
201
  updatedChannels.add(chan);
@@ -235,11 +206,10 @@ getNextVersion, triggerToNodes) {
235
206
  }
236
207
  // If this is (tentatively) the last superstep, notify all channels of finish
237
208
  if (bumpStep &&
238
- checkpoint.pending_sends.length === 0 &&
239
209
  !Object.keys(triggerToNodes ?? {}).some((channel) => updatedChannels.has(channel))) {
240
210
  for (const chan of Object.keys(onlyChannels)) {
241
211
  if (onlyChannels[chan].finish() && getNextVersion !== undefined) {
242
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
212
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
243
213
  // unavailable channels can't trigger tasks, so don't add them
244
214
  if (onlyChannels[chan].isAvailable()) {
245
215
  updatedChannels.add(chan);
@@ -247,27 +217,29 @@ getNextVersion, triggerToNodes) {
247
217
  }
248
218
  }
249
219
  }
250
- // Return managed values writes to be applied externally
251
- return pendingWritesByManaged;
252
220
  }
253
221
  /**
254
222
  * Prepare the set of tasks that will make up the next Pregel step.
255
223
  * This is the union of all PUSH tasks (Sends) and PULL tasks (nodes triggered
256
224
  * by edges).
257
225
  */
258
- function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra) {
226
+ function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
259
227
  const tasks = {};
260
- // Consume pending packets
261
- for (let i = 0; i < checkpoint.pending_sends.length; i += 1) {
262
- const task = _prepareSingleTask([constants_js_1.PUSH, i], checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra);
263
- if (task !== undefined) {
264
- tasks[task.id] = task;
228
+ // Consume pending tasks
229
+ const tasksChannel = channels[constants_js_1.TASKS];
230
+ if (tasksChannel?.isAvailable()) {
231
+ const len = tasksChannel.get().length;
232
+ for (let i = 0; i < len; i += 1) {
233
+ const task = _prepareSingleTask([constants_js_1.PUSH, i], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
234
+ if (task !== undefined) {
235
+ tasks[task.id] = task;
236
+ }
265
237
  }
266
238
  }
267
239
  // Check if any processes should be run in next step
268
240
  // If so, prepare the values to be passed to them
269
241
  for (const name of Object.keys(processes)) {
270
- const task = _prepareSingleTask([constants_js_1.PULL, name], checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra);
242
+ const task = _prepareSingleTask([constants_js_1.PULL, name], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
271
243
  if (task !== undefined) {
272
244
  tasks[task.id] = task;
273
245
  }
@@ -278,7 +250,7 @@ function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, manag
278
250
  * Prepares a single task for the next Pregel step, given a task path, which
279
251
  * uniquely identifies a PUSH or PULL task within the graph.
280
252
  */
281
- function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra) {
253
+ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
282
254
  const { step, checkpointer, manager } = extra;
283
255
  const configurable = config.configurable ?? {};
284
256
  const parentNamespace = configurable.checkpoint_ns ?? "";
@@ -324,8 +296,8 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
324
296
  configurable: {
325
297
  [constants_js_1.CONFIG_KEY_TASK_ID]: id,
326
298
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
327
- [constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite(step, (items) => writes.push(...items), processes, managed, writes_),
328
- [constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(step, checkpoint, channels, managed, {
299
+ [constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
300
+ [constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
329
301
  name: call.name,
330
302
  writes: writes,
331
303
  triggers,
@@ -376,13 +348,16 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
376
348
  const index = typeof taskPath[1] === "number"
377
349
  ? taskPath[1]
378
350
  : parseInt(taskPath[1], 10);
379
- if (index >= checkpoint.pending_sends.length) {
351
+ if (!channels[constants_js_1.TASKS]?.isAvailable()) {
380
352
  return undefined;
381
353
  }
382
- const packet = (0, constants_js_1._isSendInterface)(checkpoint.pending_sends[index]) &&
383
- !(0, constants_js_1._isSend)(checkpoint.pending_sends[index])
384
- ? new constants_js_1.Send(checkpoint.pending_sends[index].node, checkpoint.pending_sends[index].args)
385
- : checkpoint.pending_sends[index];
354
+ const sends = channels[constants_js_1.TASKS].get();
355
+ if (index < 0 || index >= sends.length) {
356
+ return undefined;
357
+ }
358
+ const packet = (0, constants_js_1._isSendInterface)(sends[index]) && !(0, constants_js_1._isSend)(sends[index])
359
+ ? new constants_js_1.Send(sends[index].node, sends[index].args)
360
+ : sends[index];
386
361
  if (!(0, constants_js_1._isSendInterface)(packet)) {
387
362
  console.warn(`Ignoring invalid packet ${JSON.stringify(packet)} in pending sends.`);
388
363
  return undefined;
@@ -414,7 +389,6 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
414
389
  const proc = processes[packet.node];
415
390
  const node = proc.getNode();
416
391
  if (node !== undefined) {
417
- managed.replaceRuntimePlaceholders(step, packet.args);
418
392
  if (proc.metadata !== undefined) {
419
393
  metadata = { ...metadata, ...proc.metadata };
420
394
  }
@@ -435,8 +409,8 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
435
409
  configurable: {
436
410
  [constants_js_1.CONFIG_KEY_TASK_ID]: taskId,
437
411
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
438
- [constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite(step, (items) => writes.push(...items), processes, managed, writes_),
439
- [constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(step, checkpoint, channels, managed, {
412
+ [constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
413
+ [constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
440
414
  name: packet.node,
441
415
  writes: writes,
442
416
  triggers,
@@ -528,7 +502,7 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
528
502
  .sort();
529
503
  // If any of the channels read by this process were updated
530
504
  if (triggers.length > 0) {
531
- const val = _procInput(step, proc, managed, channels, forExecution);
505
+ const val = _procInput(proc, channels, forExecution);
532
506
  if (val === undefined) {
533
507
  return undefined;
534
508
  }
@@ -573,10 +547,10 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
573
547
  configurable: {
574
548
  [constants_js_1.CONFIG_KEY_TASK_ID]: taskId,
575
549
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
576
- [constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite(step, (items) => {
550
+ [constants_js_1.CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => {
577
551
  writes.push(...items);
578
- }, processes, managed, writes_),
579
- [constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(step, checkpoint, channels, managed, {
552
+ }, processes, writes_),
553
+ [constants_js_1.CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
580
554
  name,
581
555
  writes: writes,
582
556
  triggers,
@@ -633,7 +607,7 @@ function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, chan
633
607
  *
634
608
  * @internal
635
609
  */
636
- function _procInput(step, proc, managed, channels, forExecution) {
610
+ function _procInput(proc, channels, forExecution) {
637
611
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
638
612
  let val;
639
613
  if (typeof proc.channels === "object" && !Array.isArray(proc.channels)) {
@@ -667,9 +641,6 @@ function _procInput(step, proc, managed, channels, forExecution) {
667
641
  }
668
642
  }
669
643
  }
670
- else {
671
- val[k] = managed.get(k)?.call(step);
672
- }
673
644
  }
674
645
  }
675
646
  else if (Array.isArray(proc.channels)) {
@@ -1,10 +1,9 @@
1
1
  import { RunnableConfig } from "@langchain/core/runnables";
2
2
  import { CallbackManagerForChainRun } from "@langchain/core/callbacks/manager";
3
- import { All, BaseCheckpointSaver, Checkpoint, ReadonlyCheckpoint, type PendingWrite, type PendingWriteValue, BaseStore, CheckpointPendingWrite } from "@langchain/langgraph-checkpoint";
3
+ import { All, BaseCheckpointSaver, Checkpoint, ReadonlyCheckpoint, type PendingWrite, BaseStore, CheckpointPendingWrite } from "@langchain/langgraph-checkpoint";
4
4
  import { BaseChannel } from "../channels/base.js";
5
5
  import { PregelNode } from "./read.js";
6
6
  import { PregelExecutableTask, PregelTaskDescription, SimpleTaskPath, TaskPath } from "./types.js";
7
- import { ManagedValueMapping } from "../managed/base.js";
8
7
  import { IterableReadableWritableStream } from "./stream.js";
9
8
  /**
10
9
  * Construct a type with a set of properties K of type T
@@ -20,9 +19,9 @@ export type WritesProtocol<C = string> = {
20
19
  };
21
20
  export declare const increment: (current?: number) => number;
22
21
  export declare function shouldInterrupt<N extends PropertyKey, C extends PropertyKey>(checkpoint: Checkpoint, interruptNodes: All | N[], tasks: PregelExecutableTask<N, C>[]): boolean;
23
- export declare function _localRead<Cc extends Record<string, BaseChannel>>(step: number, checkpoint: ReadonlyCheckpoint, channels: Cc, managed: ManagedValueMapping, task: WritesProtocol<keyof Cc>, select: Array<keyof Cc> | keyof Cc, fresh?: boolean): Record<string, unknown> | unknown;
24
- export declare function _localWrite(step: number, commit: (writes: [string, any][]) => any, processes: Record<string, PregelNode>, managed: ManagedValueMapping, writes: [string, any][]): void;
25
- export declare function _applyWrites<Cc extends Record<string, BaseChannel>>(checkpoint: Checkpoint, channels: Cc, tasks: WritesProtocol<keyof Cc>[], getNextVersion: ((version: any, channel: BaseChannel) => any) | undefined, triggerToNodes: Record<string, string[]> | undefined): Record<string, PendingWriteValue[]>;
22
+ export declare function _localRead<Cc extends Record<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, channels: Cc, task: WritesProtocol<keyof Cc>, select: Array<keyof Cc> | keyof Cc, fresh?: boolean): Record<string, unknown> | unknown;
23
+ export declare function _localWrite(commit: (writes: [string, any][]) => any, processes: Record<string, PregelNode>, writes: [string, any][]): void;
24
+ export declare function _applyWrites<Cc extends Record<string, BaseChannel>>(checkpoint: Checkpoint, channels: Cc, tasks: WritesProtocol<keyof Cc>[], getNextVersion: ((version: any) => any) | undefined, triggerToNodes: Record<string, string[]> | undefined): void;
26
25
  export type NextTaskExtraFields = {
27
26
  step: number;
28
27
  isResuming?: boolean;
@@ -37,8 +36,8 @@ export type NextTaskExtraFieldsWithStore = NextTaskExtraFields & {
37
36
  export type NextTaskExtraFieldsWithoutStore = NextTaskExtraFields & {
38
37
  store?: never;
39
38
  };
40
- export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc, managed: ManagedValueMapping, config: RunnableConfig, forExecution: false, extra: NextTaskExtraFieldsWithoutStore): Record<string, PregelTaskDescription>;
41
- export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc, managed: ManagedValueMapping, config: RunnableConfig, forExecution: true, extra: NextTaskExtraFieldsWithStore): Record<string, PregelExecutableTask<keyof Nn, keyof Cc>>;
42
- export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: SimpleTaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, managed: ManagedValueMapping, config: RunnableConfig, forExecution: false, extra: NextTaskExtraFields): PregelTaskDescription | undefined;
43
- export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, managed: ManagedValueMapping, config: RunnableConfig, forExecution: true, extra: NextTaskExtraFields): PregelExecutableTask<keyof Nn, keyof Cc> | undefined;
44
- export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, managed: ManagedValueMapping, config: RunnableConfig, forExecution: boolean, extra: NextTaskExtraFieldsWithStore): PregelTaskDescription | PregelExecutableTask<keyof Nn, keyof Cc> | undefined;
39
+ export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: false, extra: NextTaskExtraFieldsWithoutStore): Record<string, PregelTaskDescription>;
40
+ export declare function _prepareNextTasks<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(checkpoint: ReadonlyCheckpoint, pendingWrites: [string, string, unknown][] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: true, extra: NextTaskExtraFieldsWithStore): Record<string, PregelExecutableTask<keyof Nn, keyof Cc>>;
41
+ export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: SimpleTaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: false, extra: NextTaskExtraFields): PregelTaskDescription | undefined;
42
+ export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: true, extra: NextTaskExtraFields): PregelExecutableTask<keyof Nn, keyof Cc> | undefined;
43
+ export declare function _prepareSingleTask<Nn extends StrRecord<string, PregelNode>, Cc extends StrRecord<string, BaseChannel>>(taskPath: TaskPath, checkpoint: ReadonlyCheckpoint, pendingWrites: CheckpointPendingWrite[] | undefined, processes: Nn, channels: Cc, config: RunnableConfig, forExecution: boolean, extra: NextTaskExtraFieldsWithStore): PregelTaskDescription | PregelExecutableTask<keyof Nn, keyof Cc> | undefined;
@@ -31,8 +31,7 @@ export function shouldInterrupt(checkpoint, interruptNodes, tasks) {
31
31
  : interruptNodes.includes(task.name));
32
32
  return anyChannelUpdated && anyTriggeredNodeInInterruptNodes;
33
33
  }
34
- export function _localRead(step, checkpoint, channels, managed, task, select, fresh = false) {
35
- let managedKeys = [];
34
+ export function _localRead(checkpoint, channels, task, select, fresh = false) {
36
35
  let updated = new Set();
37
36
  if (!Array.isArray(select)) {
38
37
  for (const [c] of task.writes) {
@@ -44,8 +43,6 @@ export function _localRead(step, checkpoint, channels, managed, task, select, fr
44
43
  updated = updated || new Set();
45
44
  }
46
45
  else {
47
- managedKeys = select.filter((k) => managed.get(k));
48
- select = select.filter((k) => !managed.get(k));
49
46
  updated = new Set(select.filter((c) => task.writes.some(([key, _]) => key === c)));
50
47
  }
51
48
  let values;
@@ -59,20 +56,11 @@ export function _localRead(step, checkpoint, channels, managed, task, select, fr
59
56
  else {
60
57
  values = readChannels(channels, select);
61
58
  }
62
- if (managedKeys.length > 0) {
63
- for (const k of managedKeys) {
64
- const managedValue = managed.get(k);
65
- if (managedValue) {
66
- const resultOfManagedCall = managedValue.call(step);
67
- values[k] = resultOfManagedCall;
68
- }
69
- }
70
- }
71
59
  return values;
72
60
  }
73
- export function _localWrite(step,
61
+ export function _localWrite(
74
62
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
- commit, processes, managed,
63
+ commit, processes,
76
64
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
65
  writes) {
78
66
  for (const [chan, value] of writes) {
@@ -83,8 +71,6 @@ writes) {
83
71
  if (!(value.node in processes)) {
84
72
  throw new InvalidUpdateError(`Invalid node name "${value.node}" in Send packet`);
85
73
  }
86
- // replace any runtime values with placeholders
87
- managed.replaceRuntimeValues(step, value.args);
88
74
  }
89
75
  }
90
76
  commit(writes);
@@ -142,47 +128,32 @@ getNextVersion, triggerToNodes) {
142
128
  for (const chan of channelsToConsume) {
143
129
  if (chan in onlyChannels && onlyChannels[chan].consume()) {
144
130
  if (getNextVersion !== undefined) {
145
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
131
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
146
132
  }
147
133
  }
148
134
  }
149
- // Clear pending sends
150
- if (checkpoint.pending_sends?.length && bumpStep) {
151
- checkpoint.pending_sends = [];
152
- }
153
135
  // Group writes by channel
154
- const pendingWriteValuesByChannel = {};
155
- const pendingWritesByManaged = {};
136
+ const pendingWritesByChannel = {};
156
137
  for (const task of tasks) {
157
138
  for (const [chan, val] of task.writes) {
158
139
  if (IGNORE.has(chan)) {
159
140
  // do nothing
160
141
  }
161
- else if (chan === TASKS) {
162
- // TODO: remove branch in 1.0
163
- checkpoint.pending_sends.push({
164
- node: val.node,
165
- args: val.args,
166
- });
167
- }
168
142
  else if (chan in onlyChannels) {
169
- pendingWriteValuesByChannel[chan] ??= [];
170
- pendingWriteValuesByChannel[chan].push(val);
171
- }
172
- else {
173
- pendingWritesByManaged[chan] ??= [];
174
- pendingWritesByManaged[chan].push(val);
143
+ pendingWritesByChannel[chan] ??= [];
144
+ pendingWritesByChannel[chan].push(val);
175
145
  }
176
146
  }
177
147
  }
178
- // find the highest version of all channels
148
+ // Find the highest version of all channels
149
+ // TODO: figure out why we need to do this twice (Python only does this once)
179
150
  maxVersion = undefined;
180
151
  if (Object.keys(checkpoint.channel_versions).length > 0) {
181
152
  maxVersion = maxChannelVersion(...Object.values(checkpoint.channel_versions));
182
153
  }
183
154
  const updatedChannels = new Set();
184
155
  // Apply writes to channels
185
- for (const [chan, vals] of Object.entries(pendingWriteValuesByChannel)) {
156
+ for (const [chan, vals] of Object.entries(pendingWritesByChannel)) {
186
157
  if (chan in onlyChannels) {
187
158
  let updated;
188
159
  try {
@@ -200,7 +171,7 @@ getNextVersion, triggerToNodes) {
200
171
  }
201
172
  }
202
173
  if (updated && getNextVersion !== undefined) {
203
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
174
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
204
175
  // unavailable channels can't trigger tasks, so don't add them
205
176
  if (onlyChannels[chan].isAvailable()) {
206
177
  updatedChannels.add(chan);
@@ -214,7 +185,7 @@ getNextVersion, triggerToNodes) {
214
185
  if (onlyChannels[chan].isAvailable() && !updatedChannels.has(chan)) {
215
186
  const updated = onlyChannels[chan].update([]);
216
187
  if (updated && getNextVersion !== undefined) {
217
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
188
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
218
189
  // unavailable channels can't trigger tasks, so don't add them
219
190
  if (onlyChannels[chan].isAvailable()) {
220
191
  updatedChannels.add(chan);
@@ -225,11 +196,10 @@ getNextVersion, triggerToNodes) {
225
196
  }
226
197
  // If this is (tentatively) the last superstep, notify all channels of finish
227
198
  if (bumpStep &&
228
- checkpoint.pending_sends.length === 0 &&
229
199
  !Object.keys(triggerToNodes ?? {}).some((channel) => updatedChannels.has(channel))) {
230
200
  for (const chan of Object.keys(onlyChannels)) {
231
201
  if (onlyChannels[chan].finish() && getNextVersion !== undefined) {
232
- checkpoint.channel_versions[chan] = getNextVersion(maxVersion, onlyChannels[chan]);
202
+ checkpoint.channel_versions[chan] = getNextVersion(maxVersion);
233
203
  // unavailable channels can't trigger tasks, so don't add them
234
204
  if (onlyChannels[chan].isAvailable()) {
235
205
  updatedChannels.add(chan);
@@ -237,27 +207,29 @@ getNextVersion, triggerToNodes) {
237
207
  }
238
208
  }
239
209
  }
240
- // Return managed values writes to be applied externally
241
- return pendingWritesByManaged;
242
210
  }
243
211
  /**
244
212
  * Prepare the set of tasks that will make up the next Pregel step.
245
213
  * This is the union of all PUSH tasks (Sends) and PULL tasks (nodes triggered
246
214
  * by edges).
247
215
  */
248
- export function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra) {
216
+ export function _prepareNextTasks(checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
249
217
  const tasks = {};
250
- // Consume pending packets
251
- for (let i = 0; i < checkpoint.pending_sends.length; i += 1) {
252
- const task = _prepareSingleTask([PUSH, i], checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra);
253
- if (task !== undefined) {
254
- tasks[task.id] = task;
218
+ // Consume pending tasks
219
+ const tasksChannel = channels[TASKS];
220
+ if (tasksChannel?.isAvailable()) {
221
+ const len = tasksChannel.get().length;
222
+ for (let i = 0; i < len; i += 1) {
223
+ const task = _prepareSingleTask([PUSH, i], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
224
+ if (task !== undefined) {
225
+ tasks[task.id] = task;
226
+ }
255
227
  }
256
228
  }
257
229
  // Check if any processes should be run in next step
258
230
  // If so, prepare the values to be passed to them
259
231
  for (const name of Object.keys(processes)) {
260
- const task = _prepareSingleTask([PULL, name], checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra);
232
+ const task = _prepareSingleTask([PULL, name], checkpoint, pendingWrites, processes, channels, config, forExecution, extra);
261
233
  if (task !== undefined) {
262
234
  tasks[task.id] = task;
263
235
  }
@@ -268,7 +240,7 @@ export function _prepareNextTasks(checkpoint, pendingWrites, processes, channels
268
240
  * Prepares a single task for the next Pregel step, given a task path, which
269
241
  * uniquely identifies a PUSH or PULL task within the graph.
270
242
  */
271
- export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels, managed, config, forExecution, extra) {
243
+ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processes, channels, config, forExecution, extra) {
272
244
  const { step, checkpointer, manager } = extra;
273
245
  const configurable = config.configurable ?? {};
274
246
  const parentNamespace = configurable.checkpoint_ns ?? "";
@@ -314,8 +286,8 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
314
286
  configurable: {
315
287
  [CONFIG_KEY_TASK_ID]: id,
316
288
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
317
- [CONFIG_KEY_SEND]: (writes_) => _localWrite(step, (items) => writes.push(...items), processes, managed, writes_),
318
- [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(step, checkpoint, channels, managed, {
289
+ [CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
290
+ [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
319
291
  name: call.name,
320
292
  writes: writes,
321
293
  triggers,
@@ -366,13 +338,16 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
366
338
  const index = typeof taskPath[1] === "number"
367
339
  ? taskPath[1]
368
340
  : parseInt(taskPath[1], 10);
369
- if (index >= checkpoint.pending_sends.length) {
341
+ if (!channels[TASKS]?.isAvailable()) {
370
342
  return undefined;
371
343
  }
372
- const packet = _isSendInterface(checkpoint.pending_sends[index]) &&
373
- !_isSend(checkpoint.pending_sends[index])
374
- ? new Send(checkpoint.pending_sends[index].node, checkpoint.pending_sends[index].args)
375
- : checkpoint.pending_sends[index];
344
+ const sends = channels[TASKS].get();
345
+ if (index < 0 || index >= sends.length) {
346
+ return undefined;
347
+ }
348
+ const packet = _isSendInterface(sends[index]) && !_isSend(sends[index])
349
+ ? new Send(sends[index].node, sends[index].args)
350
+ : sends[index];
376
351
  if (!_isSendInterface(packet)) {
377
352
  console.warn(`Ignoring invalid packet ${JSON.stringify(packet)} in pending sends.`);
378
353
  return undefined;
@@ -404,7 +379,6 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
404
379
  const proc = processes[packet.node];
405
380
  const node = proc.getNode();
406
381
  if (node !== undefined) {
407
- managed.replaceRuntimePlaceholders(step, packet.args);
408
382
  if (proc.metadata !== undefined) {
409
383
  metadata = { ...metadata, ...proc.metadata };
410
384
  }
@@ -425,8 +399,8 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
425
399
  configurable: {
426
400
  [CONFIG_KEY_TASK_ID]: taskId,
427
401
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
428
- [CONFIG_KEY_SEND]: (writes_) => _localWrite(step, (items) => writes.push(...items), processes, managed, writes_),
429
- [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(step, checkpoint, channels, managed, {
402
+ [CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => writes.push(...items), processes, writes_),
403
+ [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
430
404
  name: packet.node,
431
405
  writes: writes,
432
406
  triggers,
@@ -518,7 +492,7 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
518
492
  .sort();
519
493
  // If any of the channels read by this process were updated
520
494
  if (triggers.length > 0) {
521
- const val = _procInput(step, proc, managed, channels, forExecution);
495
+ const val = _procInput(proc, channels, forExecution);
522
496
  if (val === undefined) {
523
497
  return undefined;
524
498
  }
@@ -563,10 +537,10 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
563
537
  configurable: {
564
538
  [CONFIG_KEY_TASK_ID]: taskId,
565
539
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
566
- [CONFIG_KEY_SEND]: (writes_) => _localWrite(step, (items) => {
540
+ [CONFIG_KEY_SEND]: (writes_) => _localWrite((items) => {
567
541
  writes.push(...items);
568
- }, processes, managed, writes_),
569
- [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(step, checkpoint, channels, managed, {
542
+ }, processes, writes_),
543
+ [CONFIG_KEY_READ]: (select_, fresh_ = false) => _localRead(checkpoint, channels, {
570
544
  name,
571
545
  writes: writes,
572
546
  triggers,
@@ -623,7 +597,7 @@ export function _prepareSingleTask(taskPath, checkpoint, pendingWrites, processe
623
597
  *
624
598
  * @internal
625
599
  */
626
- function _procInput(step, proc, managed, channels, forExecution) {
600
+ function _procInput(proc, channels, forExecution) {
627
601
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
628
602
  let val;
629
603
  if (typeof proc.channels === "object" && !Array.isArray(proc.channels)) {
@@ -657,9 +631,6 @@ function _procInput(step, proc, managed, channels, forExecution) {
657
631
  }
658
632
  }
659
633
  }
660
- else {
661
- val[k] = managed.get(k)?.call(step);
662
- }
663
634
  }
664
635
  }
665
636
  else if (Array.isArray(proc.channels)) {