@langchain/langgraph 0.2.8 → 0.2.10-rc.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 (63) hide show
  1. package/dist/constants.cjs +11 -2
  2. package/dist/constants.d.ts +6 -1
  3. package/dist/constants.js +10 -1
  4. package/dist/errors.cjs +5 -4
  5. package/dist/errors.d.ts +1 -1
  6. package/dist/errors.js +5 -4
  7. package/dist/graph/graph.cjs +7 -2
  8. package/dist/graph/graph.js +8 -3
  9. package/dist/graph/message.cjs +2 -0
  10. package/dist/graph/message.js +2 -0
  11. package/dist/graph/state.cjs +8 -3
  12. package/dist/graph/state.d.ts +2 -3
  13. package/dist/graph/state.js +9 -4
  14. package/dist/managed/shared_value.cjs +12 -10
  15. package/dist/managed/shared_value.d.ts +6 -5
  16. package/dist/managed/shared_value.js +12 -10
  17. package/dist/pregel/algo.cjs +124 -54
  18. package/dist/pregel/algo.d.ts +13 -3
  19. package/dist/pregel/algo.js +122 -53
  20. package/dist/pregel/debug.cjs +15 -18
  21. package/dist/pregel/debug.d.ts +3 -2
  22. package/dist/pregel/debug.js +16 -19
  23. package/dist/pregel/index.cjs +307 -116
  24. package/dist/pregel/index.d.ts +21 -6
  25. package/dist/pregel/index.js +305 -117
  26. package/dist/pregel/io.cjs +15 -8
  27. package/dist/pregel/io.d.ts +2 -2
  28. package/dist/pregel/io.js +15 -8
  29. package/dist/pregel/loop.cjs +258 -113
  30. package/dist/pregel/loop.d.ts +24 -9
  31. package/dist/pregel/loop.js +258 -111
  32. package/dist/pregel/read.cjs +9 -2
  33. package/dist/pregel/read.d.ts +3 -2
  34. package/dist/pregel/read.js +9 -2
  35. package/dist/pregel/retry.d.ts +1 -1
  36. package/dist/pregel/runnable_types.cjs +2 -0
  37. package/dist/pregel/runnable_types.d.ts +5 -0
  38. package/dist/pregel/runnable_types.js +1 -0
  39. package/dist/pregel/types.d.ts +8 -4
  40. package/dist/pregel/utils/config.cjs +73 -0
  41. package/dist/pregel/utils/config.d.ts +3 -0
  42. package/dist/pregel/utils/config.js +69 -0
  43. package/dist/pregel/{utils.cjs → utils/index.cjs} +33 -10
  44. package/dist/pregel/{utils.d.ts → utils/index.d.ts} +4 -7
  45. package/dist/pregel/{utils.js → utils/index.js} +30 -8
  46. package/dist/utils.cjs +5 -3
  47. package/dist/utils.js +5 -3
  48. package/dist/web.cjs +4 -2
  49. package/dist/web.d.ts +4 -3
  50. package/dist/web.js +1 -2
  51. package/package.json +1 -1
  52. package/dist/store/base.cjs +0 -12
  53. package/dist/store/base.d.ts +0 -7
  54. package/dist/store/base.js +0 -8
  55. package/dist/store/batch.cjs +0 -126
  56. package/dist/store/batch.d.ts +0 -55
  57. package/dist/store/batch.js +0 -122
  58. package/dist/store/index.cjs +0 -19
  59. package/dist/store/index.d.ts +0 -3
  60. package/dist/store/index.js +0 -3
  61. package/dist/store/memory.cjs +0 -43
  62. package/dist/store/memory.d.ts +0 -6
  63. package/dist/store/memory.js +0 -39
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Pregel = exports.Channel = void 0;
4
7
  /* eslint-disable no-param-reassign */
5
8
  const runnables_1 = require("@langchain/core/runnables");
6
9
  const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
10
+ const double_ended_queue_1 = __importDefault(require("double-ended-queue"));
7
11
  const base_js_1 = require("../channels/base.cjs");
8
12
  const read_js_1 = require("./read.cjs");
9
13
  const validate_js_1 = require("./validate.cjs");
@@ -13,11 +17,12 @@ const write_js_1 = require("./write.cjs");
13
17
  const constants_js_1 = require("../constants.cjs");
14
18
  const errors_js_1 = require("../errors.cjs");
15
19
  const algo_js_1 = require("./algo.cjs");
16
- const utils_js_1 = require("./utils.cjs");
20
+ const index_js_1 = require("./utils/index.cjs");
17
21
  const loop_js_1 = require("./loop.cjs");
18
22
  const retry_js_1 = require("./retry.cjs");
19
23
  const base_js_2 = require("../managed/base.cjs");
20
- const utils_js_2 = require("../utils.cjs");
24
+ const utils_js_1 = require("../utils.cjs");
25
+ const config_js_1 = require("./utils/config.cjs");
21
26
  function isString(value) {
22
27
  return typeof value === "string";
23
28
  }
@@ -76,6 +81,16 @@ class Channel {
76
81
  }
77
82
  }
78
83
  exports.Channel = Channel;
84
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
+ function isPregel(x) {
86
+ return ("inputChannels" in x &&
87
+ x.inputChannels !== undefined &&
88
+ "outputChannels" &&
89
+ x.outputChannels !== undefined);
90
+ }
91
+ function isRunnableSequence(x) {
92
+ return "steps" in x && Array.isArray(x.steps);
93
+ }
79
94
  class Pregel extends runnables_1.Runnable {
80
95
  static lc_name() {
81
96
  return "LangGraph";
@@ -167,6 +182,12 @@ class Pregel extends runnables_1.Runnable {
167
182
  writable: true,
168
183
  value: void 0
169
184
  });
185
+ Object.defineProperty(this, "config", {
186
+ enumerable: true,
187
+ configurable: true,
188
+ writable: true,
189
+ value: void 0
190
+ });
170
191
  Object.defineProperty(this, "store", {
171
192
  enumerable: true,
172
193
  configurable: true,
@@ -190,11 +211,18 @@ class Pregel extends runnables_1.Runnable {
190
211
  this.debug = fields.debug ?? this.debug;
191
212
  this.checkpointer = fields.checkpointer;
192
213
  this.retryPolicy = fields.retryPolicy;
214
+ this.config = fields.config;
193
215
  this.store = fields.store;
194
216
  if (this.autoValidate) {
195
217
  this.validate();
196
218
  }
197
219
  }
220
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
221
+ // @ts-ignore Remove ignore when we remove support for 0.2 versions of core
222
+ withConfig(config) {
223
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
+ return new this.constructor({ ...this, config });
225
+ }
198
226
  validate() {
199
227
  (0, validate_js_1.validateGraph)({
200
228
  nodes: this.nodes,
@@ -226,50 +254,181 @@ class Pregel extends runnables_1.Runnable {
226
254
  return Object.keys(this.channels);
227
255
  }
228
256
  }
229
- /**
230
- * Get the current state of the graph.
231
- */
232
- async getState(config) {
233
- if (!this.checkpointer) {
234
- throw new errors_js_1.GraphValueError("No checkpointer set");
257
+ *getSubgraphs(namespace, recurse
258
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
259
+ ) {
260
+ for (const [name, node] of Object.entries(this.nodes)) {
261
+ // filter by prefix
262
+ if (namespace !== undefined) {
263
+ if (!namespace.startsWith(name)) {
264
+ continue;
265
+ }
266
+ }
267
+ // find the subgraph if any
268
+ let graph;
269
+ const candidates = [node.bound];
270
+ for (const candidate of candidates) {
271
+ if (isPregel(candidate)) {
272
+ graph = candidate;
273
+ break;
274
+ }
275
+ else if (isRunnableSequence(candidate)) {
276
+ candidates.push(...candidate.steps);
277
+ }
278
+ }
279
+ // if found, yield recursively
280
+ if (graph !== undefined) {
281
+ if (name === namespace) {
282
+ yield [name, graph];
283
+ return;
284
+ }
285
+ if (namespace === undefined) {
286
+ yield [name, graph];
287
+ }
288
+ if (recurse) {
289
+ let newNamespace = namespace;
290
+ if (namespace !== undefined) {
291
+ newNamespace = namespace.slice(name.length + 1);
292
+ }
293
+ for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) {
294
+ yield [
295
+ `${name}${constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`,
296
+ subgraph,
297
+ ];
298
+ }
299
+ }
300
+ }
301
+ }
302
+ }
303
+ async _prepareStateSnapshot({ config, saved, subgraphCheckpointer, }) {
304
+ if (saved === undefined) {
305
+ return {
306
+ values: {},
307
+ next: [],
308
+ config,
309
+ tasks: [],
310
+ };
235
311
  }
236
- const saved = await this.checkpointer.getTuple(config);
237
- const checkpoint = saved ? saved.checkpoint : (0, langgraph_checkpoint_1.emptyCheckpoint)();
238
- const channels = (0, base_js_1.emptyChannels)(this.channels, checkpoint);
239
312
  // Pass `skipManaged: true` as managed values should not be returned in get state calls.
240
313
  const { managed } = await this.prepareSpecs(config, { skipManaged: true });
241
- const nextTasks = (0, algo_js_1._prepareNextTasks)(checkpoint, this.nodes, channels, managed, saved !== undefined ? saved.config : config, false, { step: saved ? (saved.metadata?.step ?? -1) + 1 : -1 });
314
+ const channels = (0, base_js_1.emptyChannels)(this.channels, saved.checkpoint);
315
+ const nextTasks = Object.values((0, algo_js_1._prepareNextTasks)(saved.checkpoint, this.nodes, channels, managed, saved.config, false, { step: (saved.metadata?.step ?? -1) + 1 }));
316
+ const subgraphs = await (0, utils_js_1.gatherIterator)(this.getSubgraphs());
317
+ const parentNamespace = saved.config.configurable?.checkpoint_ns ?? "";
318
+ const taskStates = {};
319
+ for (const task of nextTasks) {
320
+ const matchingSubgraph = subgraphs.find(([name]) => name === task.name);
321
+ if (!matchingSubgraph) {
322
+ continue;
323
+ }
324
+ // assemble checkpoint_ns for this task
325
+ let taskNs = `${task.name}${constants_js_1.CHECKPOINT_NAMESPACE_END}${task.id}`;
326
+ if (parentNamespace) {
327
+ taskNs = `${parentNamespace}${constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR}${taskNs}`;
328
+ }
329
+ if (subgraphCheckpointer === undefined) {
330
+ // set config as signal that subgraph checkpoints exist
331
+ const config = {
332
+ configurable: {
333
+ thread_id: saved.config.configurable?.thread_id,
334
+ checkpoint_ns: taskNs,
335
+ },
336
+ };
337
+ taskStates[task.id] = config;
338
+ }
339
+ else {
340
+ // get the state of the subgraph
341
+ const config = {
342
+ configurable: {
343
+ [constants_js_1.CONFIG_KEY_CHECKPOINTER]: subgraphCheckpointer,
344
+ thread_id: saved.config.configurable?.thread_id,
345
+ checkpoint_ns: taskNs,
346
+ },
347
+ };
348
+ taskStates[task.id] = await matchingSubgraph[1].getState(config, {
349
+ subgraphs: true,
350
+ });
351
+ }
352
+ }
353
+ // assemble the state snapshot
242
354
  return {
243
355
  values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
244
356
  next: nextTasks.map((task) => task.name),
245
- tasks: (0, debug_js_1.tasksWithWrites)(nextTasks, saved?.pendingWrites ?? []),
246
- metadata: saved?.metadata,
247
- config: saved ? saved.config : config,
248
- createdAt: saved?.checkpoint.ts,
249
- parentConfig: saved?.parentConfig,
357
+ tasks: (0, debug_js_1.tasksWithWrites)(nextTasks, saved?.pendingWrites ?? [], taskStates),
358
+ metadata: saved.metadata,
359
+ config: (0, index_js_1.patchCheckpointMap)(saved.config, saved.metadata),
360
+ createdAt: saved.checkpoint.ts,
361
+ parentConfig: saved.parentConfig,
250
362
  };
251
363
  }
364
+ /**
365
+ * Get the current state of the graph.
366
+ */
367
+ async getState(config, options) {
368
+ const checkpointer = config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
369
+ if (!checkpointer) {
370
+ throw new errors_js_1.GraphValueError("No checkpointer set");
371
+ }
372
+ const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
373
+ if (checkpointNamespace !== "" &&
374
+ config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] === undefined) {
375
+ // remove task_ids from checkpoint_ns
376
+ const recastCheckpointNamespace = checkpointNamespace
377
+ .split(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR)
378
+ .map((part) => part.split(constants_js_1.CHECKPOINT_NAMESPACE_END)[0])
379
+ .join(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR);
380
+ for (const [name, subgraph] of this.getSubgraphs(recastCheckpointNamespace, true)) {
381
+ if (name === recastCheckpointNamespace) {
382
+ return await subgraph.getState((0, utils_js_1.patchConfigurable)(config, {
383
+ [constants_js_1.CONFIG_KEY_CHECKPOINTER]: checkpointer,
384
+ }), { subgraphs: options?.subgraphs });
385
+ }
386
+ }
387
+ throw new Error(`Subgraph with namespace "${recastCheckpointNamespace}" not found.`);
388
+ }
389
+ const mergedConfig = (0, runnables_1.mergeConfigs)(this.config, config);
390
+ const saved = await checkpointer.getTuple(config);
391
+ const snapshot = await this._prepareStateSnapshot({
392
+ config: mergedConfig,
393
+ saved,
394
+ subgraphCheckpointer: options?.subgraphs ? checkpointer : undefined,
395
+ });
396
+ return snapshot;
397
+ }
252
398
  /**
253
399
  * Get the history of the state of the graph.
254
400
  */
255
401
  async *getStateHistory(config, options) {
256
- if (!this.checkpointer) {
257
- throw new errors_js_1.GraphValueError("No checkpointer set");
402
+ const checkpointer = config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
403
+ if (!checkpointer) {
404
+ throw new Error("No checkpointer set");
405
+ }
406
+ const checkpointNamespace = config.configurable?.checkpoint_ns ?? "";
407
+ if (checkpointNamespace !== "" &&
408
+ config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] === undefined) {
409
+ const recastCheckpointNamespace = checkpointNamespace
410
+ .split(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR)
411
+ .map((part) => part.split(constants_js_1.CHECKPOINT_NAMESPACE_END)[0])
412
+ .join(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR);
413
+ // find the subgraph with the matching name
414
+ for (const [name, pregel] of this.getSubgraphs(recastCheckpointNamespace, true)) {
415
+ if (name === recastCheckpointNamespace) {
416
+ yield* pregel.getStateHistory((0, utils_js_1.patchConfigurable)(config, {
417
+ [constants_js_1.CONFIG_KEY_CHECKPOINTER]: checkpointer,
418
+ }), options);
419
+ return;
420
+ }
421
+ }
422
+ throw new Error(`Subgraph with namespace "${recastCheckpointNamespace}" not found.`);
258
423
  }
259
- // Pass `skipManaged: true` as managed values should not be returned in get state calls.
260
- const { managed } = await this.prepareSpecs(config, { skipManaged: true });
261
- for await (const saved of this.checkpointer.list(config, options)) {
262
- const channels = (0, base_js_1.emptyChannels)(this.channels, saved.checkpoint);
263
- const nextTasks = (0, algo_js_1._prepareNextTasks)(saved.checkpoint, this.nodes, channels, managed, saved.config, false, { step: -1 });
264
- yield {
265
- values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
266
- next: nextTasks.map((task) => task.name),
267
- tasks: (0, debug_js_1.tasksWithWrites)(nextTasks, saved.pendingWrites ?? []),
268
- metadata: saved.metadata,
269
- config: saved.config,
270
- createdAt: saved.checkpoint.ts,
271
- parentConfig: saved.parentConfig,
272
- };
424
+ const mergedConfig = (0, runnables_1.mergeConfigs)(this.config, config, {
425
+ configurable: { checkpoint_ns: checkpointNamespace },
426
+ });
427
+ for await (const checkpointTuple of checkpointer.list(mergedConfig, options)) {
428
+ yield this._prepareStateSnapshot({
429
+ config: checkpointTuple.config,
430
+ saved: checkpointTuple,
431
+ });
273
432
  }
274
433
  }
275
434
  /**
@@ -277,34 +436,59 @@ class Pregel extends runnables_1.Runnable {
277
436
  * node `as_node`. If `as_node` is not provided, it will be set to the last node
278
437
  * that updated the state, if not ambiguous.
279
438
  */
280
- async updateState(config, values, asNode) {
281
- if (!this.checkpointer) {
439
+ async updateState(inputConfig, values, asNode) {
440
+ const checkpointer = inputConfig.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] ?? this.checkpointer;
441
+ if (!checkpointer) {
282
442
  throw new errors_js_1.GraphValueError("No checkpointer set");
283
443
  }
284
- // Get the latest checkpoint
285
- const saved = await this.checkpointer.getTuple(config);
286
- const checkpoint = saved
444
+ // delegate to subgraph
445
+ const checkpointNamespace = inputConfig.configurable?.checkpoint_ns ?? "";
446
+ if (checkpointNamespace !== "" &&
447
+ inputConfig.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] === undefined) {
448
+ // remove task_ids from checkpoint_ns
449
+ const recastCheckpointNamespace = checkpointNamespace
450
+ .split(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR)
451
+ .map((part) => {
452
+ return part.split(constants_js_1.CHECKPOINT_NAMESPACE_END)[0];
453
+ })
454
+ .join(constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR);
455
+ // find the subgraph with the matching name
456
+ // eslint-disable-next-line no-unreachable-loop
457
+ for (const [, pregel] of this.getSubgraphs(recastCheckpointNamespace, true)) {
458
+ return await pregel.updateState((0, utils_js_1.patchConfigurable)(inputConfig, {
459
+ [constants_js_1.CONFIG_KEY_CHECKPOINTER]: checkpointer,
460
+ }), values, asNode);
461
+ }
462
+ throw new Error(`Subgraph "${recastCheckpointNamespace}" not found`);
463
+ }
464
+ // get last checkpoint
465
+ const config = this.config
466
+ ? (0, runnables_1.mergeConfigs)(this.config, inputConfig)
467
+ : inputConfig;
468
+ const saved = await checkpointer.getTuple(config);
469
+ const checkpoint = saved !== undefined
287
470
  ? (0, langgraph_checkpoint_1.copyCheckpoint)(saved.checkpoint)
288
471
  : (0, langgraph_checkpoint_1.emptyCheckpoint)();
289
- const checkpointPreviousVersions = saved?.checkpoint.channel_versions ?? {};
472
+ const checkpointPreviousVersions = {
473
+ ...saved?.checkpoint.channel_versions,
474
+ };
290
475
  const step = saved?.metadata?.step ?? -1;
291
476
  // merge configurable fields with previous checkpoint config
292
- const checkpointConfig = {
293
- ...config,
294
- configurable: {
295
- ...config.configurable,
296
- // TODO: add proper support for updating nested subgraph state
297
- checkpoint_ns: "",
298
- ...saved?.config.configurable,
299
- },
300
- };
477
+ let checkpointConfig = (0, utils_js_1.patchConfigurable)(config, {
478
+ checkpoint_ns: config.configurable?.checkpoint_ns ?? "",
479
+ });
480
+ if (saved) {
481
+ checkpointConfig = (0, utils_js_1.patchConfigurable)(config, saved.config.configurable);
482
+ }
301
483
  // Find last node that updated the state, if not provided
302
484
  if (values == null && asNode === undefined) {
303
- return await this.checkpointer.put(checkpointConfig, (0, base_js_1.createCheckpoint)(checkpoint, undefined, step), {
485
+ const nextConfig = await checkpointer.put(checkpointConfig, (0, base_js_1.createCheckpoint)(checkpoint, undefined, step), {
304
486
  source: "update",
305
487
  step,
306
488
  writes: {},
489
+ parents: saved?.metadata?.parents ?? {},
307
490
  }, {});
491
+ return (0, index_js_1.patchCheckpointMap)(nextConfig, saved ? saved.metadata : undefined);
308
492
  }
309
493
  const nonNullVersion = Object.values(checkpoint.versions_seen)
310
494
  .map((seenVersions) => {
@@ -319,7 +503,6 @@ class Pregel extends runnables_1.Runnable {
319
503
  }
320
504
  }
321
505
  else if (asNode === undefined) {
322
- // TODO: Double check
323
506
  const lastSeenByNode = Object.entries(checkpoint.versions_seen)
324
507
  .map(([n, seen]) => {
325
508
  return Object.values(seen).map((v) => {
@@ -367,7 +550,10 @@ class Pregel extends runnables_1.Runnable {
367
550
  id: (0, langgraph_checkpoint_1.uuid5)(constants_js_1.INTERRUPT, checkpoint.id),
368
551
  };
369
552
  // execute task
370
- await task.proc.invoke(task.input, (0, runnables_1.patchConfig)(config, {
553
+ await task.proc.invoke(task.input, (0, runnables_1.patchConfig)({
554
+ ...config,
555
+ store: config?.store ?? this.store,
556
+ }, {
371
557
  runName: config.runName ?? `${this.getName()}UpdateState`,
372
558
  configurable: {
373
559
  [constants_js_1.CONFIG_KEY_SEND]: (items) => task.writes.push(...items),
@@ -376,18 +562,21 @@ class Pregel extends runnables_1.Runnable {
376
562
  task, select_, fresh_),
377
563
  },
378
564
  }));
565
+ // save task writes
379
566
  if (saved !== undefined) {
380
- await this.checkpointer.putWrites(checkpointConfig, task.writes, task.id);
567
+ await checkpointer.putWrites(checkpointConfig, task.writes, task.id);
381
568
  }
382
569
  // apply to checkpoint
383
570
  // TODO: Why does keyof StrRecord allow number and symbol?
384
- (0, algo_js_1._applyWrites)(checkpoint, channels, [task], this.checkpointer.getNextVersion.bind(this.checkpointer));
385
- const newVersions = (0, utils_js_1.getNewChannelVersions)(checkpointPreviousVersions, checkpoint.channel_versions);
386
- return await this.checkpointer.put(checkpointConfig, (0, base_js_1.createCheckpoint)(checkpoint, channels, step + 1), {
571
+ (0, algo_js_1._applyWrites)(checkpoint, channels, [task], checkpointer.getNextVersion.bind(this.checkpointer));
572
+ const newVersions = (0, index_js_1.getNewChannelVersions)(checkpointPreviousVersions, checkpoint.channel_versions);
573
+ const nextConfig = await checkpointer.put(checkpointConfig, (0, base_js_1.createCheckpoint)(checkpoint, channels, step + 1), {
387
574
  source: "update",
388
575
  step: step + 1,
389
576
  writes: { [asNode]: values },
577
+ parents: saved?.metadata?.parents ?? {},
390
578
  }, newVersions);
579
+ return (0, index_js_1.patchCheckpointMap)(nextConfig, saved ? saved.metadata : undefined);
391
580
  }
392
581
  _defaults(config) {
393
582
  const { debug, streamMode, inputKeys, outputKeys, interruptAfter, interruptBefore, ...rest } = config;
@@ -415,19 +604,19 @@ class Pregel extends runnables_1.Runnable {
415
604
  else {
416
605
  defaultStreamMode = this.streamMode;
417
606
  }
418
- let defaultCheckpointer;
419
- if (config.configurable !== undefined &&
420
- config.configurable[constants_js_1.CONFIG_KEY_READ] !== undefined) {
607
+ // if being called as a node in another graph, always use values mode
608
+ if (config.configurable?.[constants_js_1.CONFIG_KEY_TASK_ID] !== undefined) {
421
609
  defaultStreamMode = ["values"];
422
610
  }
611
+ let defaultCheckpointer;
423
612
  if (config !== undefined &&
424
- config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] !== undefined &&
425
- (defaultInterruptAfter.length > 0 || defaultInterruptBefore.length > 0)) {
613
+ config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] !== undefined) {
426
614
  defaultCheckpointer = config.configurable[constants_js_1.CONFIG_KEY_CHECKPOINTER];
427
615
  }
428
616
  else {
429
617
  defaultCheckpointer = this.checkpointer;
430
618
  }
619
+ const defaultStore = config.store ?? this.store;
431
620
  return [
432
621
  defaultDebug,
433
622
  defaultStreamMode,
@@ -437,6 +626,7 @@ class Pregel extends runnables_1.Runnable {
437
626
  defaultInterruptBefore,
438
627
  defaultInterruptAfter,
439
628
  defaultCheckpointer,
629
+ defaultStore,
440
630
  ];
441
631
  }
442
632
  /**
@@ -458,9 +648,10 @@ class Pregel extends runnables_1.Runnable {
458
648
  return super.stream(input, options);
459
649
  }
460
650
  async prepareSpecs(config, options) {
461
- const configForManaged = (0, utils_js_2.patchConfigurable)(config, {
462
- [constants_js_1.CONFIG_KEY_STORE]: this.store,
463
- });
651
+ const configForManaged = {
652
+ ...config,
653
+ store: this.store,
654
+ };
464
655
  const channelSpecs = {};
465
656
  const managedSpecs = {};
466
657
  for (const [name, spec] of Object.entries(this.channels)) {
@@ -501,7 +692,8 @@ class Pregel extends runnables_1.Runnable {
501
692
  };
502
693
  }
503
694
  async *_streamIterator(input, options) {
504
- const inputConfig = (0, runnables_1.ensureConfig)(options);
695
+ const streamSubgraphs = options?.subgraphs;
696
+ const inputConfig = (0, config_js_1.ensureLangGraphConfig)(this.config, options);
505
697
  if (inputConfig.recursionLimit === undefined ||
506
698
  inputConfig.recursionLimit < 1) {
507
699
  throw new Error(`Passed "recursionLimit" must be at least 1.`);
@@ -511,12 +703,36 @@ class Pregel extends runnables_1.Runnable {
511
703
  throw new Error(`Checkpointer requires one or more of the following "configurable" keys: "thread_id", "checkpoint_ns", "checkpoint_id"`);
512
704
  }
513
705
  const callbackManager = await (0, runnables_1.getCallbackManagerForConfig)(inputConfig);
514
- const runManager = await callbackManager?.handleChainStart(this.toJSON(), (0, utils_js_1._coerceToDict)(input, "input"), inputConfig.runId, undefined, undefined, undefined, inputConfig?.runName ?? this.getName());
706
+ const runManager = await callbackManager?.handleChainStart(this.toJSON(), (0, index_js_1._coerceToDict)(input, "input"), inputConfig.runId, undefined, undefined, undefined, inputConfig?.runName ?? this.getName());
515
707
  delete inputConfig.runId;
516
708
  // assign defaults
517
- const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer,] = this._defaults(inputConfig);
709
+ const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer, store,] = this._defaults(inputConfig);
518
710
  const { channelSpecs, managed } = await this.prepareSpecs(config);
519
711
  let loop;
712
+ const stream = new double_ended_queue_1.default();
713
+ function* emitCurrentLoopOutputs() {
714
+ while (loop !== undefined && stream.length > 0) {
715
+ const nextItem = stream.shift();
716
+ if (nextItem === undefined) {
717
+ throw new Error("Data structure error.");
718
+ }
719
+ const [namespace, mode, payload] = nextItem;
720
+ if (streamMode.includes(mode)) {
721
+ if (streamSubgraphs && streamMode.length > 1) {
722
+ yield [namespace, mode, payload];
723
+ }
724
+ else if (streamMode.length > 1) {
725
+ yield [mode, payload];
726
+ }
727
+ else if (streamSubgraphs) {
728
+ yield [namespace, payload];
729
+ }
730
+ else {
731
+ yield payload;
732
+ }
733
+ }
734
+ }
735
+ }
520
736
  try {
521
737
  loop = await loop_js_1.PregelLoop.initialize({
522
738
  input,
@@ -527,8 +743,15 @@ class Pregel extends runnables_1.Runnable {
527
743
  managed,
528
744
  outputKeys,
529
745
  streamKeys: this.streamChannelsAsIs,
530
- store: this.store,
746
+ store,
747
+ stream: new loop_js_1.StreamProtocol((chunk) => stream.push(chunk), new Set(streamMode)),
531
748
  });
749
+ if (options?.subgraphs) {
750
+ loop.config.configurable = {
751
+ ...loop.config.configurable,
752
+ [constants_js_1.CONFIG_KEY_STREAM]: loop.stream,
753
+ };
754
+ }
532
755
  while (await loop.tick({
533
756
  inputKeys: this.inputChannels,
534
757
  interruptAfter,
@@ -538,27 +761,14 @@ class Pregel extends runnables_1.Runnable {
538
761
  if (debug) {
539
762
  (0, debug_js_1.printStepCheckpoint)(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
540
763
  }
541
- while (loop.stream.length > 0) {
542
- const nextItem = loop.stream.shift();
543
- if (nextItem === undefined) {
544
- throw new Error("Data structure error.");
545
- }
546
- if (streamMode.includes(nextItem[0])) {
547
- if (streamMode.length === 1) {
548
- yield nextItem[1];
549
- }
550
- else {
551
- yield nextItem;
552
- }
553
- }
554
- }
764
+ yield* emitCurrentLoopOutputs();
555
765
  if (debug) {
556
- (0, debug_js_1.printStepTasks)(loop.step, loop.tasks);
766
+ (0, debug_js_1.printStepTasks)(loop.step, Object.values(loop.tasks));
557
767
  }
558
768
  // execute tasks, and wait for one to fail or all to finish.
559
769
  // each task is independent from all other concurrent tasks
560
770
  // yield updates/debug output as each task finishes
561
- const taskStream = (0, retry_js_1.executeTasksWithRetry)(loop.tasks.filter((task) => task.writes.length === 0), {
771
+ const taskStream = (0, retry_js_1.executeTasksWithRetry)(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
562
772
  stepTimeout: this.stepTimeout,
563
773
  signal: config.signal,
564
774
  retryPolicy: this.retryPolicy,
@@ -567,7 +777,12 @@ class Pregel extends runnables_1.Runnable {
567
777
  for await (const { task, error } of taskStream) {
568
778
  if (error !== undefined) {
569
779
  if ((0, errors_js_1.isGraphInterrupt)(error)) {
570
- loop.putWrites(task.id, error.interrupts.map((interrupt) => [constants_js_1.INTERRUPT, interrupt]));
780
+ if (loop.isNested) {
781
+ throw error;
782
+ }
783
+ if (error.interrupts.length) {
784
+ loop.putWrites(task.id, error.interrupts.map((interrupt) => [constants_js_1.INTERRUPT, interrupt]));
785
+ }
571
786
  }
572
787
  else {
573
788
  loop.putWrites(task.id, [
@@ -578,42 +793,18 @@ class Pregel extends runnables_1.Runnable {
578
793
  else {
579
794
  loop.putWrites(task.id, task.writes);
580
795
  }
581
- while (loop.stream.length > 0) {
582
- const nextItem = loop.stream.shift();
583
- if (nextItem === undefined) {
584
- throw new Error("Data structure error.");
585
- }
586
- if (streamMode.includes(nextItem[0])) {
587
- if (streamMode.length === 1) {
588
- yield nextItem[1];
589
- }
590
- else {
591
- yield nextItem;
592
- }
593
- }
594
- }
796
+ yield* emitCurrentLoopOutputs();
595
797
  if (error !== undefined && !(0, errors_js_1.isGraphInterrupt)(error)) {
596
798
  throw error;
597
799
  }
598
800
  }
599
801
  if (debug) {
600
- (0, debug_js_1.printStepWrites)(loop.step, loop.tasks.map((task) => task.writes).flat(), this.streamChannelsList);
601
- }
602
- }
603
- while (loop.stream.length > 0) {
604
- const nextItem = loop.stream.shift();
605
- if (nextItem === undefined) {
606
- throw new Error("Data structure error.");
607
- }
608
- if (streamMode.includes(nextItem[0])) {
609
- if (streamMode.length === 1) {
610
- yield nextItem[1];
611
- }
612
- else {
613
- yield nextItem;
614
- }
802
+ (0, debug_js_1.printStepWrites)(loop.step, Object.values(loop.tasks)
803
+ .map((task) => task.writes)
804
+ .flat(), this.streamChannelsList);
615
805
  }
616
806
  }
807
+ yield* emitCurrentLoopOutputs();
617
808
  if (loop.status === "out_of_steps") {
618
809
  throw new errors_js_1.GraphRecursionError([
619
810
  `Recursion limit of ${config.recursionLimit} reached`,
@@ -622,7 +813,7 @@ class Pregel extends runnables_1.Runnable {
622
813
  ].join(" "));
623
814
  }
624
815
  await Promise.all(loop?.checkpointerPromises ?? []);
625
- await runManager?.handleChainEnd((0, io_js_1.readChannels)(loop.channels, outputKeys));
816
+ await runManager?.handleChainEnd(loop.output);
626
817
  }
627
818
  catch (e) {
628
819
  await runManager?.handleChainError(e);
@@ -631,7 +822,7 @@ class Pregel extends runnables_1.Runnable {
631
822
  finally {
632
823
  // Call `.stop()` again incase it was not called in the loop, e.g due to an error.
633
824
  if (loop) {
634
- loop.store?.stop();
825
+ await loop.store?.stop();
635
826
  }
636
827
  await Promise.all([
637
828
  loop?.checkpointerPromises ?? [],
@@ -657,7 +848,7 @@ class Pregel extends runnables_1.Runnable {
657
848
  async invoke(input, options) {
658
849
  const streamMode = options?.streamMode ?? "values";
659
850
  const config = {
660
- ...(0, runnables_1.ensureConfig)(options),
851
+ ...options,
661
852
  outputKeys: options?.outputKeys ?? this.outputChannels,
662
853
  streamMode,
663
854
  };