@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
@@ -124,12 +124,6 @@ class PregelLoop {
124
124
  writable: true,
125
125
  value: void 0
126
126
  });
127
- Object.defineProperty(this, "managed", {
128
- enumerable: true,
129
- configurable: true,
130
- writable: true,
131
- value: void 0
132
- });
133
127
  Object.defineProperty(this, "checkpoint", {
134
128
  enumerable: true,
135
129
  configurable: true,
@@ -184,7 +178,7 @@ class PregelLoop {
184
178
  writable: true,
185
179
  value: void 0
186
180
  });
187
- Object.defineProperty(this, "checkpointDuring", {
181
+ Object.defineProperty(this, "durability", {
188
182
  enumerable: true,
189
183
  configurable: true,
190
184
  writable: true,
@@ -220,12 +214,6 @@ class PregelLoop {
220
214
  writable: true,
221
215
  value: void 0
222
216
  });
223
- Object.defineProperty(this, "prevCheckpoint", {
224
- enumerable: true,
225
- configurable: true,
226
- writable: true,
227
- value: void 0
228
- });
229
217
  Object.defineProperty(this, "status", {
230
218
  enumerable: true,
231
219
  configurable: true,
@@ -326,7 +314,6 @@ class PregelLoop {
326
314
  this.checkpointMetadata = params.checkpointMetadata;
327
315
  this.checkpointPreviousVersions = params.checkpointPreviousVersions;
328
316
  this.channels = params.channels;
329
- this.managed = params.managed;
330
317
  this.checkpointPendingWrites = params.checkpointPendingWrites;
331
318
  this.step = params.step;
332
319
  this.stop = params.stop;
@@ -345,7 +332,7 @@ class PregelLoop {
345
332
  this.prevCheckpointConfig = params.prevCheckpointConfig;
346
333
  this.interruptAfter = params.interruptAfter;
347
334
  this.interruptBefore = params.interruptBefore;
348
- this.checkpointDuring = params.checkpointDuring;
335
+ this.durability = params.durability;
349
336
  this.debug = params.debug;
350
337
  this.triggerToNodes = params.triggerToNodes;
351
338
  }
@@ -390,12 +377,7 @@ class PregelLoop {
390
377
  const saved = (await params.checkpointer?.getTuple(checkpointConfig)) ?? {
391
378
  config,
392
379
  checkpoint: (0, langgraph_checkpoint_1.emptyCheckpoint)(),
393
- metadata: {
394
- source: "input",
395
- step: -2,
396
- writes: null,
397
- parents: {},
398
- },
380
+ metadata: { source: "input", step: -2, parents: {} },
399
381
  pendingWrites: [],
400
382
  };
401
383
  checkpointConfig = {
@@ -420,7 +402,7 @@ class PregelLoop {
420
402
  : undefined;
421
403
  if (store) {
422
404
  // Start the store. This is a batch store, so it will run continuously
423
- store.start();
405
+ await store.start();
424
406
  }
425
407
  return new PregelLoop({
426
408
  input: params.input,
@@ -432,7 +414,6 @@ class PregelLoop {
432
414
  prevCheckpointConfig,
433
415
  checkpointNamespace,
434
416
  channels,
435
- managed: params.managed,
436
417
  isNested,
437
418
  manager: params.manager,
438
419
  skipDoneTasks,
@@ -448,7 +429,7 @@ class PregelLoop {
448
429
  cache: params.cache,
449
430
  interruptAfter: params.interruptAfter,
450
431
  interruptBefore: params.interruptBefore,
451
- checkpointDuring: params.checkpointDuring,
432
+ durability: params.durability,
452
433
  debug: params.debug,
453
434
  triggerToNodes: params.triggerToNodes,
454
435
  });
@@ -459,13 +440,6 @@ class PregelLoop {
459
440
  });
460
441
  this.checkpointerPromises.push(this._checkpointerChainedPromise);
461
442
  }
462
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
463
- async updateManagedValues(key, values) {
464
- const mv = this.managed.get(key);
465
- if (mv && "update" in mv && typeof mv.update === "function") {
466
- await mv.update(values);
467
- }
468
- }
469
443
  /**
470
444
  * Put writes for a task, to be read by the next tick.
471
445
  * @param taskId
@@ -485,16 +459,12 @@ class PregelLoop {
485
459
  for (const [c, v] of writesCopy) {
486
460
  this.checkpointPendingWrites.push([taskId, c, v]);
487
461
  }
488
- const putWritePromise = this.checkpointer?.putWrites({
489
- ...this.checkpointConfig,
490
- configurable: {
491
- ...this.checkpointConfig.configurable,
492
- checkpoint_ns: this.config.configurable?.checkpoint_ns ?? "",
493
- checkpoint_id: this.checkpoint.id,
494
- },
495
- }, writesCopy, taskId);
496
- if (putWritePromise !== undefined) {
497
- this.checkpointerPromises.push(putWritePromise);
462
+ const config = (0, index_js_1.patchConfigurable)(this.checkpointConfig, {
463
+ [constants_js_1.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
464
+ [constants_js_1.CONFIG_KEY_CHECKPOINT_ID]: this.checkpoint.id,
465
+ });
466
+ if (this.durability !== "exit" && this.checkpointer != null) {
467
+ this.checkpointerPromises.push(this.checkpointer.putWrites(config, writesCopy, taskId));
498
468
  }
499
469
  if (this.tasks) {
500
470
  this._outputWrites(taskId, writesCopy);
@@ -585,7 +555,7 @@ class PregelLoop {
585
555
  */
586
556
  async tick(params) {
587
557
  if (this.store && !this.store.isRunning) {
588
- this.store?.start();
558
+ await this.store?.start();
589
559
  }
590
560
  const { inputKeys = [] } = params;
591
561
  if (this.status !== "pending") {
@@ -602,19 +572,13 @@ class PregelLoop {
602
572
  // finish superstep
603
573
  const writes = Object.values(this.tasks).flatMap((t) => t.writes);
604
574
  // All tasks have finished
605
- const managedValueWrites = (0, algo_js_1._applyWrites)(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
606
- for (const [key, values] of Object.entries(managedValueWrites)) {
607
- await this.updateManagedValues(key, values);
608
- }
575
+ (0, algo_js_1._applyWrites)(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
609
576
  // produce values output
610
577
  const valuesOutput = await (0, utils_js_1.gatherIterator)((0, utils_js_1.prefixGenerator)((0, io_js_1.mapOutputValues)(this.outputKeys, writes, this.channels), "values"));
611
578
  this._emit(valuesOutput);
612
579
  // clear pending writes
613
580
  this.checkpointPendingWrites = [];
614
- await this._putCheckpoint({
615
- source: "loop",
616
- writes: (0, io_js_1.mapOutputUpdates)(this.outputKeys, Object.values(this.tasks).map((task) => [task, task.writes])).next().value ?? null,
617
- });
581
+ await this._putCheckpoint({ source: "loop" });
618
582
  // after execution, check if we should interrupt
619
583
  if ((0, algo_js_1.shouldInterrupt)(this.checkpoint, this.interruptAfter, Object.values(this.tasks))) {
620
584
  this.status = "interrupt_after";
@@ -632,7 +596,7 @@ class PregelLoop {
632
596
  this.status = "out_of_steps";
633
597
  return false;
634
598
  }
635
- const nextTasks = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, this.config, true, {
599
+ const nextTasks = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.config, true, {
636
600
  step: this.step,
637
601
  checkpointer: this.checkpointer,
638
602
  isResuming: this.isResuming,
@@ -682,7 +646,7 @@ class PregelLoop {
682
646
  }
683
647
  async finishAndHandleError(error) {
684
648
  // persist current checkpoint and writes
685
- if (!this.checkpointDuring &&
649
+ if (this.durability === "exit" &&
686
650
  // if it's a top graph
687
651
  (!this.isNested ||
688
652
  // or a nested graph with error or interrupt
@@ -701,10 +665,7 @@ class PregelLoop {
701
665
  if (this.tasks !== undefined &&
702
666
  this.checkpointPendingWrites.length > 0 &&
703
667
  Object.values(this.tasks).some((task) => task.writes.length > 0)) {
704
- const managedValueWrites = (0, algo_js_1._applyWrites)(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
705
- for (const [key, values] of Object.entries(managedValueWrites)) {
706
- await this.updateManagedValues(key, values);
707
- }
668
+ (0, algo_js_1._applyWrites)(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
708
669
  this._emit((0, utils_js_1.gatherIteratorSync)((0, utils_js_1.prefixGenerator)((0, io_js_1.mapOutputValues)(this.outputKeys, Object.values(this.tasks).flatMap((t) => t.writes), this.channels), "values")));
709
670
  }
710
671
  // Emit INTERRUPT event
@@ -723,7 +684,7 @@ class PregelLoop {
723
684
  this.toInterrupt.push(task);
724
685
  return;
725
686
  }
726
- const pushed = (0, algo_js_1._prepareSingleTask)([constants_js_1.PUSH, task.path ?? [], writeIdx, task.id, call], this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, task.config ?? {}, true, {
687
+ const pushed = (0, algo_js_1._prepareSingleTask)([constants_js_1.PUSH, task.path ?? [], writeIdx, task.id, call], this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, task.config ?? {}, true, {
727
688
  step: this.step,
728
689
  checkpointer: this.checkpointer,
729
690
  manager: this.manager,
@@ -825,14 +786,14 @@ class PregelLoop {
825
786
  // we need to create a new checkpoint for Command(update=...) or Command(goto=...)
826
787
  // in case the result of Command(goto=...) is an interrupt.
827
788
  // If not done, the checkpoint containing the interrupt will be lost.
828
- await this._putCheckpoint({ source: "input", writes: {} });
789
+ await this._putCheckpoint({ source: "input" });
829
790
  this.input = INPUT_DONE;
830
791
  }
831
792
  else {
832
793
  // map inputs to channel updates
833
794
  const inputWrites = await (0, utils_js_1.gatherIterator)((0, io_js_1.mapInput)(inputKeys, this.input));
834
795
  if (inputWrites.length > 0) {
835
- const discardTasks = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, this.config, true, { step: this.step });
796
+ const discardTasks = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.config, true, { step: this.step });
836
797
  (0, algo_js_1._applyWrites)(this.checkpoint, this.channels, Object.values(discardTasks).concat([
837
798
  {
838
799
  name: constants_js_1.INPUT,
@@ -841,10 +802,7 @@ class PregelLoop {
841
802
  },
842
803
  ]), this.checkpointerGetNextVersion, this.triggerToNodes);
843
804
  // save input checkpoint
844
- await this._putCheckpoint({
845
- source: "input",
846
- writes: Object.fromEntries(inputWrites),
847
- });
805
+ await this._putCheckpoint({ source: "input" });
848
806
  this.input = INPUT_DONE;
849
807
  }
850
808
  else if (!(constants_js_1.CONFIG_KEY_RESUMING in (this.config.configurable ?? {}))) {
@@ -895,7 +853,7 @@ class PregelLoop {
895
853
  }
896
854
  _putCheckpoint(inputMetadata) {
897
855
  const exiting = this.checkpointMetadata === inputMetadata;
898
- const doCheckpoint = this.checkpointer != null && (this.checkpointDuring || exiting);
856
+ const doCheckpoint = this.checkpointer != null && (this.durability !== "exit" || exiting);
899
857
  const storeCheckpoint = (checkpoint) => {
900
858
  // store the previous checkpoint config for debug events
901
859
  this.prevCheckpointConfig = this.checkpointConfig?.configurable
@@ -906,13 +864,9 @@ class PregelLoop {
906
864
  // this is achieved by writing child checkpoints as progress is made
907
865
  // (so that error recovery / resuming from interrupt don't lose work)
908
866
  // but doing so always with an id equal to that of the parent checkpoint
909
- this.checkpointConfig = {
910
- ...this.checkpointConfig,
911
- configurable: {
912
- ...this.checkpointConfig.configurable,
913
- checkpoint_ns: this.config.configurable?.checkpoint_ns ?? "",
914
- },
915
- };
867
+ this.checkpointConfig = (0, index_js_1.patchConfigurable)(this.checkpointConfig, {
868
+ [constants_js_1.CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
869
+ });
916
870
  const channelVersions = { ...this.checkpoint.channel_versions };
917
871
  const newVersions = (0, index_js_1.getNewChannelVersions)(this.checkpointPreviousVersions, channelVersions);
918
872
  this.checkpointPreviousVersions = channelVersions;
@@ -933,16 +887,6 @@ class PregelLoop {
933
887
  },
934
888
  };
935
889
  };
936
- // We need to retroactively store the previous checkpoint
937
- // if it turns out that pending sends are scheduled.
938
- // TODO: remove when `pending_sends` is removed from checkpoints
939
- if (!exiting &&
940
- !this.checkpointDuring &&
941
- this.checkpointer != null &&
942
- this.prevCheckpoint != null &&
943
- this.checkpoint.pending_sends.length > 0) {
944
- storeCheckpoint(this.prevCheckpoint);
945
- }
946
890
  if (!exiting) {
947
891
  this.checkpointMetadata = {
948
892
  ...inputMetadata,
@@ -950,11 +894,6 @@ class PregelLoop {
950
894
  parents: this.config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINT_MAP] ?? {},
951
895
  };
952
896
  }
953
- // Store previous checkpoint in case pending_sends are scheduled
954
- // for next checkpoint.
955
- if (!this.checkpointDuring) {
956
- this.prevCheckpoint = this.checkpoint;
957
- }
958
897
  // create new checkpoint
959
898
  this.checkpoint = (0, base_js_1.createCheckpoint)(this.checkpoint, doCheckpoint ? this.channels : undefined, this.step, exiting ? { id: this.checkpoint.id } : undefined);
960
899
  // Bail if no checkpointer
@@ -2,10 +2,9 @@ import type { RunnableConfig } from "@langchain/core/runnables";
2
2
  import type { CallbackManagerForChainRun } from "@langchain/core/callbacks/manager";
3
3
  import { BaseCheckpointSaver, Checkpoint, PendingWrite, CheckpointPendingWrite, CheckpointMetadata, All, BaseStore, AsyncBatchedStore, BaseCache, CacheFullKey, CacheNamespace } from "@langchain/langgraph-checkpoint";
4
4
  import { BaseChannel } from "../channels/base.js";
5
- import { Call, PregelExecutableTask, StreamMode } from "./types.js";
5
+ import type { Call, Durability, PregelExecutableTask, StreamMode } from "./types.js";
6
6
  import { Command } from "../constants.js";
7
7
  import { PregelNode } from "./read.js";
8
- import { ManagedValueMapping } from "../managed/base.js";
9
8
  import { LangGraphRunnableConfig } from "./runnable_types.js";
10
9
  import { IterableReadableWritableStream } from "./stream.js";
11
10
  export type PregelLoopInitializeParams = {
@@ -16,13 +15,12 @@ export type PregelLoopInitializeParams = {
16
15
  streamKeys: string | string[];
17
16
  nodes: Record<string, PregelNode>;
18
17
  channelSpecs: Record<string, BaseChannel>;
19
- managed: ManagedValueMapping;
20
18
  stream: IterableReadableWritableStream;
21
19
  store?: BaseStore;
22
20
  cache?: BaseCache<PendingWrite<string>[]>;
23
21
  interruptAfter: string[] | All;
24
22
  interruptBefore: string[] | All;
25
- checkpointDuring: boolean;
23
+ durability: Durability;
26
24
  manager?: CallbackManagerForChainRun;
27
25
  debug: boolean;
28
26
  triggerToNodes: Record<string, string[]>;
@@ -37,7 +35,6 @@ type PregelLoopParams = {
37
35
  checkpointPendingWrites: CheckpointPendingWrite[];
38
36
  checkpointConfig: RunnableConfig;
39
37
  channels: Record<string, BaseChannel>;
40
- managed: ManagedValueMapping;
41
38
  step: number;
42
39
  stop: number;
43
40
  outputKeys: string | string[];
@@ -53,7 +50,7 @@ type PregelLoopParams = {
53
50
  prevCheckpointConfig: RunnableConfig | undefined;
54
51
  interruptAfter: string[] | All;
55
52
  interruptBefore: string[] | All;
56
- checkpointDuring: boolean;
53
+ durability: Durability;
57
54
  debug: boolean;
58
55
  triggerToNodes: Record<string, string[]>;
59
56
  };
@@ -79,9 +76,8 @@ export declare class PregelLoop {
79
76
  output: any;
80
77
  config: LangGraphRunnableConfig;
81
78
  protected checkpointer?: BaseCheckpointSaver;
82
- protected checkpointerGetNextVersion: (current: number | undefined, channel: BaseChannel) => number;
79
+ protected checkpointerGetNextVersion: (current: number | undefined) => number;
83
80
  channels: Record<string, BaseChannel>;
84
- managed: ManagedValueMapping;
85
81
  protected checkpoint: Checkpoint;
86
82
  protected checkpointIdSaved: string | undefined;
87
83
  protected checkpointConfig: RunnableConfig;
@@ -91,13 +87,12 @@ export declare class PregelLoop {
91
87
  protected checkpointPreviousVersions: Record<string, string | number>;
92
88
  step: number;
93
89
  protected stop: number;
94
- protected checkpointDuring: boolean;
90
+ protected durability: Durability;
95
91
  protected outputKeys: string | string[];
96
92
  protected streamKeys: string | string[];
97
93
  protected nodes: Record<string, PregelNode>;
98
94
  protected skipDoneTasks: boolean;
99
95
  protected prevCheckpointConfig: RunnableConfig | undefined;
100
- protected prevCheckpoint: Checkpoint | undefined;
101
96
  status: "pending" | "done" | "interrupt_before" | "interrupt_after" | "out_of_steps";
102
97
  tasks: Record<string, PregelExecutableTask<any, any>>;
103
98
  stream: IterableReadableWritableStream;
@@ -121,7 +116,6 @@ export declare class PregelLoop {
121
116
  metadata: CheckpointMetadata;
122
117
  newVersions: Record<string, string | number>;
123
118
  }): void;
124
- protected updateManagedValues(key: string, values: any[]): Promise<void>;
125
119
  /**
126
120
  * Put writes for a task, to be read by the next tick.
127
121
  * @param taskId
@@ -121,12 +121,6 @@ export class PregelLoop {
121
121
  writable: true,
122
122
  value: void 0
123
123
  });
124
- Object.defineProperty(this, "managed", {
125
- enumerable: true,
126
- configurable: true,
127
- writable: true,
128
- value: void 0
129
- });
130
124
  Object.defineProperty(this, "checkpoint", {
131
125
  enumerable: true,
132
126
  configurable: true,
@@ -181,7 +175,7 @@ export class PregelLoop {
181
175
  writable: true,
182
176
  value: void 0
183
177
  });
184
- Object.defineProperty(this, "checkpointDuring", {
178
+ Object.defineProperty(this, "durability", {
185
179
  enumerable: true,
186
180
  configurable: true,
187
181
  writable: true,
@@ -217,12 +211,6 @@ export class PregelLoop {
217
211
  writable: true,
218
212
  value: void 0
219
213
  });
220
- Object.defineProperty(this, "prevCheckpoint", {
221
- enumerable: true,
222
- configurable: true,
223
- writable: true,
224
- value: void 0
225
- });
226
214
  Object.defineProperty(this, "status", {
227
215
  enumerable: true,
228
216
  configurable: true,
@@ -323,7 +311,6 @@ export class PregelLoop {
323
311
  this.checkpointMetadata = params.checkpointMetadata;
324
312
  this.checkpointPreviousVersions = params.checkpointPreviousVersions;
325
313
  this.channels = params.channels;
326
- this.managed = params.managed;
327
314
  this.checkpointPendingWrites = params.checkpointPendingWrites;
328
315
  this.step = params.step;
329
316
  this.stop = params.stop;
@@ -342,7 +329,7 @@ export class PregelLoop {
342
329
  this.prevCheckpointConfig = params.prevCheckpointConfig;
343
330
  this.interruptAfter = params.interruptAfter;
344
331
  this.interruptBefore = params.interruptBefore;
345
- this.checkpointDuring = params.checkpointDuring;
332
+ this.durability = params.durability;
346
333
  this.debug = params.debug;
347
334
  this.triggerToNodes = params.triggerToNodes;
348
335
  }
@@ -387,12 +374,7 @@ export class PregelLoop {
387
374
  const saved = (await params.checkpointer?.getTuple(checkpointConfig)) ?? {
388
375
  config,
389
376
  checkpoint: emptyCheckpoint(),
390
- metadata: {
391
- source: "input",
392
- step: -2,
393
- writes: null,
394
- parents: {},
395
- },
377
+ metadata: { source: "input", step: -2, parents: {} },
396
378
  pendingWrites: [],
397
379
  };
398
380
  checkpointConfig = {
@@ -417,7 +399,7 @@ export class PregelLoop {
417
399
  : undefined;
418
400
  if (store) {
419
401
  // Start the store. This is a batch store, so it will run continuously
420
- store.start();
402
+ await store.start();
421
403
  }
422
404
  return new PregelLoop({
423
405
  input: params.input,
@@ -429,7 +411,6 @@ export class PregelLoop {
429
411
  prevCheckpointConfig,
430
412
  checkpointNamespace,
431
413
  channels,
432
- managed: params.managed,
433
414
  isNested,
434
415
  manager: params.manager,
435
416
  skipDoneTasks,
@@ -445,7 +426,7 @@ export class PregelLoop {
445
426
  cache: params.cache,
446
427
  interruptAfter: params.interruptAfter,
447
428
  interruptBefore: params.interruptBefore,
448
- checkpointDuring: params.checkpointDuring,
429
+ durability: params.durability,
449
430
  debug: params.debug,
450
431
  triggerToNodes: params.triggerToNodes,
451
432
  });
@@ -456,13 +437,6 @@ export class PregelLoop {
456
437
  });
457
438
  this.checkpointerPromises.push(this._checkpointerChainedPromise);
458
439
  }
459
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
460
- async updateManagedValues(key, values) {
461
- const mv = this.managed.get(key);
462
- if (mv && "update" in mv && typeof mv.update === "function") {
463
- await mv.update(values);
464
- }
465
- }
466
440
  /**
467
441
  * Put writes for a task, to be read by the next tick.
468
442
  * @param taskId
@@ -482,16 +456,12 @@ export class PregelLoop {
482
456
  for (const [c, v] of writesCopy) {
483
457
  this.checkpointPendingWrites.push([taskId, c, v]);
484
458
  }
485
- const putWritePromise = this.checkpointer?.putWrites({
486
- ...this.checkpointConfig,
487
- configurable: {
488
- ...this.checkpointConfig.configurable,
489
- checkpoint_ns: this.config.configurable?.checkpoint_ns ?? "",
490
- checkpoint_id: this.checkpoint.id,
491
- },
492
- }, writesCopy, taskId);
493
- if (putWritePromise !== undefined) {
494
- this.checkpointerPromises.push(putWritePromise);
459
+ const config = patchConfigurable(this.checkpointConfig, {
460
+ [CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
461
+ [CONFIG_KEY_CHECKPOINT_ID]: this.checkpoint.id,
462
+ });
463
+ if (this.durability !== "exit" && this.checkpointer != null) {
464
+ this.checkpointerPromises.push(this.checkpointer.putWrites(config, writesCopy, taskId));
495
465
  }
496
466
  if (this.tasks) {
497
467
  this._outputWrites(taskId, writesCopy);
@@ -582,7 +552,7 @@ export class PregelLoop {
582
552
  */
583
553
  async tick(params) {
584
554
  if (this.store && !this.store.isRunning) {
585
- this.store?.start();
555
+ await this.store?.start();
586
556
  }
587
557
  const { inputKeys = [] } = params;
588
558
  if (this.status !== "pending") {
@@ -599,19 +569,13 @@ export class PregelLoop {
599
569
  // finish superstep
600
570
  const writes = Object.values(this.tasks).flatMap((t) => t.writes);
601
571
  // All tasks have finished
602
- const managedValueWrites = _applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
603
- for (const [key, values] of Object.entries(managedValueWrites)) {
604
- await this.updateManagedValues(key, values);
605
- }
572
+ _applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
606
573
  // produce values output
607
574
  const valuesOutput = await gatherIterator(prefixGenerator(mapOutputValues(this.outputKeys, writes, this.channels), "values"));
608
575
  this._emit(valuesOutput);
609
576
  // clear pending writes
610
577
  this.checkpointPendingWrites = [];
611
- await this._putCheckpoint({
612
- source: "loop",
613
- writes: mapOutputUpdates(this.outputKeys, Object.values(this.tasks).map((task) => [task, task.writes])).next().value ?? null,
614
- });
578
+ await this._putCheckpoint({ source: "loop" });
615
579
  // after execution, check if we should interrupt
616
580
  if (shouldInterrupt(this.checkpoint, this.interruptAfter, Object.values(this.tasks))) {
617
581
  this.status = "interrupt_after";
@@ -629,7 +593,7 @@ export class PregelLoop {
629
593
  this.status = "out_of_steps";
630
594
  return false;
631
595
  }
632
- const nextTasks = _prepareNextTasks(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, this.config, true, {
596
+ const nextTasks = _prepareNextTasks(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.config, true, {
633
597
  step: this.step,
634
598
  checkpointer: this.checkpointer,
635
599
  isResuming: this.isResuming,
@@ -679,7 +643,7 @@ export class PregelLoop {
679
643
  }
680
644
  async finishAndHandleError(error) {
681
645
  // persist current checkpoint and writes
682
- if (!this.checkpointDuring &&
646
+ if (this.durability === "exit" &&
683
647
  // if it's a top graph
684
648
  (!this.isNested ||
685
649
  // or a nested graph with error or interrupt
@@ -698,10 +662,7 @@ export class PregelLoop {
698
662
  if (this.tasks !== undefined &&
699
663
  this.checkpointPendingWrites.length > 0 &&
700
664
  Object.values(this.tasks).some((task) => task.writes.length > 0)) {
701
- const managedValueWrites = _applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
702
- for (const [key, values] of Object.entries(managedValueWrites)) {
703
- await this.updateManagedValues(key, values);
704
- }
665
+ _applyWrites(this.checkpoint, this.channels, Object.values(this.tasks), this.checkpointerGetNextVersion, this.triggerToNodes);
705
666
  this._emit(gatherIteratorSync(prefixGenerator(mapOutputValues(this.outputKeys, Object.values(this.tasks).flatMap((t) => t.writes), this.channels), "values")));
706
667
  }
707
668
  // Emit INTERRUPT event
@@ -720,7 +681,7 @@ export class PregelLoop {
720
681
  this.toInterrupt.push(task);
721
682
  return;
722
683
  }
723
- const pushed = _prepareSingleTask([PUSH, task.path ?? [], writeIdx, task.id, call], this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, task.config ?? {}, true, {
684
+ const pushed = _prepareSingleTask([PUSH, task.path ?? [], writeIdx, task.id, call], this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, task.config ?? {}, true, {
724
685
  step: this.step,
725
686
  checkpointer: this.checkpointer,
726
687
  manager: this.manager,
@@ -822,14 +783,14 @@ export class PregelLoop {
822
783
  // we need to create a new checkpoint for Command(update=...) or Command(goto=...)
823
784
  // in case the result of Command(goto=...) is an interrupt.
824
785
  // If not done, the checkpoint containing the interrupt will be lost.
825
- await this._putCheckpoint({ source: "input", writes: {} });
786
+ await this._putCheckpoint({ source: "input" });
826
787
  this.input = INPUT_DONE;
827
788
  }
828
789
  else {
829
790
  // map inputs to channel updates
830
791
  const inputWrites = await gatherIterator(mapInput(inputKeys, this.input));
831
792
  if (inputWrites.length > 0) {
832
- const discardTasks = _prepareNextTasks(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.managed, this.config, true, { step: this.step });
793
+ const discardTasks = _prepareNextTasks(this.checkpoint, this.checkpointPendingWrites, this.nodes, this.channels, this.config, true, { step: this.step });
833
794
  _applyWrites(this.checkpoint, this.channels, Object.values(discardTasks).concat([
834
795
  {
835
796
  name: INPUT,
@@ -838,10 +799,7 @@ export class PregelLoop {
838
799
  },
839
800
  ]), this.checkpointerGetNextVersion, this.triggerToNodes);
840
801
  // save input checkpoint
841
- await this._putCheckpoint({
842
- source: "input",
843
- writes: Object.fromEntries(inputWrites),
844
- });
802
+ await this._putCheckpoint({ source: "input" });
845
803
  this.input = INPUT_DONE;
846
804
  }
847
805
  else if (!(CONFIG_KEY_RESUMING in (this.config.configurable ?? {}))) {
@@ -892,7 +850,7 @@ export class PregelLoop {
892
850
  }
893
851
  _putCheckpoint(inputMetadata) {
894
852
  const exiting = this.checkpointMetadata === inputMetadata;
895
- const doCheckpoint = this.checkpointer != null && (this.checkpointDuring || exiting);
853
+ const doCheckpoint = this.checkpointer != null && (this.durability !== "exit" || exiting);
896
854
  const storeCheckpoint = (checkpoint) => {
897
855
  // store the previous checkpoint config for debug events
898
856
  this.prevCheckpointConfig = this.checkpointConfig?.configurable
@@ -903,13 +861,9 @@ export class PregelLoop {
903
861
  // this is achieved by writing child checkpoints as progress is made
904
862
  // (so that error recovery / resuming from interrupt don't lose work)
905
863
  // but doing so always with an id equal to that of the parent checkpoint
906
- this.checkpointConfig = {
907
- ...this.checkpointConfig,
908
- configurable: {
909
- ...this.checkpointConfig.configurable,
910
- checkpoint_ns: this.config.configurable?.checkpoint_ns ?? "",
911
- },
912
- };
864
+ this.checkpointConfig = patchConfigurable(this.checkpointConfig, {
865
+ [CONFIG_KEY_CHECKPOINT_NS]: this.config.configurable?.checkpoint_ns ?? "",
866
+ });
913
867
  const channelVersions = { ...this.checkpoint.channel_versions };
914
868
  const newVersions = getNewChannelVersions(this.checkpointPreviousVersions, channelVersions);
915
869
  this.checkpointPreviousVersions = channelVersions;
@@ -930,16 +884,6 @@ export class PregelLoop {
930
884
  },
931
885
  };
932
886
  };
933
- // We need to retroactively store the previous checkpoint
934
- // if it turns out that pending sends are scheduled.
935
- // TODO: remove when `pending_sends` is removed from checkpoints
936
- if (!exiting &&
937
- !this.checkpointDuring &&
938
- this.checkpointer != null &&
939
- this.prevCheckpoint != null &&
940
- this.checkpoint.pending_sends.length > 0) {
941
- storeCheckpoint(this.prevCheckpoint);
942
- }
943
887
  if (!exiting) {
944
888
  this.checkpointMetadata = {
945
889
  ...inputMetadata,
@@ -947,11 +891,6 @@ export class PregelLoop {
947
891
  parents: this.config.configurable?.[CONFIG_KEY_CHECKPOINT_MAP] ?? {},
948
892
  };
949
893
  }
950
- // Store previous checkpoint in case pending_sends are scheduled
951
- // for next checkpoint.
952
- if (!this.checkpointDuring) {
953
- this.prevCheckpoint = this.checkpoint;
954
- }
955
894
  // create new checkpoint
956
895
  this.checkpoint = createCheckpoint(this.checkpoint, doCheckpoint ? this.channels : undefined, this.step, exiting ? { id: this.checkpoint.id } : undefined);
957
896
  // Bail if no checkpointer