@langchain/langgraph 0.2.7 → 0.2.9

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 (45) hide show
  1. package/dist/constants.cjs +12 -2
  2. package/dist/constants.d.ts +7 -1
  3. package/dist/constants.js +11 -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 +9 -7
  12. package/dist/graph/state.d.ts +2 -2
  13. package/dist/graph/state.js +10 -8
  14. package/dist/managed/shared_value.cjs +1 -1
  15. package/dist/managed/shared_value.js +1 -1
  16. package/dist/pregel/algo.cjs +119 -54
  17. package/dist/pregel/algo.d.ts +5 -2
  18. package/dist/pregel/algo.js +117 -53
  19. package/dist/pregel/debug.cjs +15 -18
  20. package/dist/pregel/debug.d.ts +3 -2
  21. package/dist/pregel/debug.js +16 -19
  22. package/dist/pregel/index.cjs +295 -123
  23. package/dist/pregel/index.d.ts +16 -5
  24. package/dist/pregel/index.js +292 -123
  25. package/dist/pregel/io.cjs +15 -8
  26. package/dist/pregel/io.d.ts +2 -2
  27. package/dist/pregel/io.js +15 -8
  28. package/dist/pregel/loop.cjs +256 -111
  29. package/dist/pregel/loop.d.ts +21 -5
  30. package/dist/pregel/loop.js +256 -109
  31. package/dist/pregel/read.cjs +9 -2
  32. package/dist/pregel/read.d.ts +2 -1
  33. package/dist/pregel/read.js +9 -2
  34. package/dist/pregel/retry.d.ts +1 -1
  35. package/dist/pregel/types.d.ts +5 -2
  36. package/dist/pregel/utils/config.cjs +72 -0
  37. package/dist/pregel/utils/config.d.ts +2 -0
  38. package/dist/pregel/utils/config.js +68 -0
  39. package/dist/pregel/{utils.cjs → utils/index.cjs} +33 -10
  40. package/dist/pregel/{utils.d.ts → utils/index.d.ts} +4 -7
  41. package/dist/pregel/{utils.js → utils/index.js} +30 -8
  42. package/dist/utils.cjs +5 -3
  43. package/dist/utils.js +5 -3
  44. package/dist/web.d.ts +2 -1
  45. package/package.json +1 -1
@@ -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";
@@ -113,12 +128,6 @@ class Pregel extends runnables_1.Runnable {
113
128
  writable: true,
114
129
  value: void 0
115
130
  });
116
- Object.defineProperty(this, "configKeys", {
117
- enumerable: true,
118
- configurable: true,
119
- writable: true,
120
- value: void 0
121
- });
122
131
  Object.defineProperty(this, "autoValidate", {
123
132
  enumerable: true,
124
133
  configurable: true,
@@ -173,6 +182,12 @@ class Pregel extends runnables_1.Runnable {
173
182
  writable: true,
174
183
  value: void 0
175
184
  });
185
+ Object.defineProperty(this, "config", {
186
+ enumerable: true,
187
+ configurable: true,
188
+ writable: true,
189
+ value: void 0
190
+ });
176
191
  Object.defineProperty(this, "store", {
177
192
  enumerable: true,
178
193
  configurable: true,
@@ -189,7 +204,6 @@ class Pregel extends runnables_1.Runnable {
189
204
  this.streamMode = streamMode ?? this.streamMode;
190
205
  this.inputChannels = fields.inputChannels;
191
206
  this.outputChannels = fields.outputChannels;
192
- this.configKeys = fields.configKeys;
193
207
  this.streamChannels = fields.streamChannels ?? this.streamChannels;
194
208
  this.interruptAfter = fields.interruptAfter;
195
209
  this.interruptBefore = fields.interruptBefore;
@@ -197,11 +211,18 @@ class Pregel extends runnables_1.Runnable {
197
211
  this.debug = fields.debug ?? this.debug;
198
212
  this.checkpointer = fields.checkpointer;
199
213
  this.retryPolicy = fields.retryPolicy;
214
+ this.config = fields.config;
200
215
  this.store = fields.store;
201
216
  if (this.autoValidate) {
202
217
  this.validate();
203
218
  }
204
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
+ }
205
226
  validate() {
206
227
  (0, validate_js_1.validateGraph)({
207
228
  nodes: this.nodes,
@@ -233,50 +254,181 @@ class Pregel extends runnables_1.Runnable {
233
254
  return Object.keys(this.channels);
234
255
  }
235
256
  }
236
- /**
237
- * Get the current state of the graph.
238
- */
239
- async getState(config) {
240
- if (!this.checkpointer) {
241
- 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
+ };
242
311
  }
243
- const saved = await this.checkpointer.getTuple(config);
244
- const checkpoint = saved ? saved.checkpoint : (0, langgraph_checkpoint_1.emptyCheckpoint)();
245
- const channels = (0, base_js_1.emptyChannels)(this.channels, checkpoint);
246
312
  // Pass `skipManaged: true` as managed values should not be returned in get state calls.
247
313
  const { managed } = await this.prepareSpecs(config, { skipManaged: true });
248
- 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
249
354
  return {
250
355
  values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
251
356
  next: nextTasks.map((task) => task.name),
252
- tasks: (0, debug_js_1.tasksWithWrites)(nextTasks, saved?.pendingWrites ?? []),
253
- metadata: saved?.metadata,
254
- config: saved ? saved.config : config,
255
- createdAt: saved?.checkpoint.ts,
256
- 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,
257
362
  };
258
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
+ }
259
398
  /**
260
399
  * Get the history of the state of the graph.
261
400
  */
262
401
  async *getStateHistory(config, options) {
263
- if (!this.checkpointer) {
264
- 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.`);
265
423
  }
266
- // Pass `skipManaged: true` as managed values should not be returned in get state calls.
267
- const { managed } = await this.prepareSpecs(config, { skipManaged: true });
268
- for await (const saved of this.checkpointer.list(config, options)) {
269
- const channels = (0, base_js_1.emptyChannels)(this.channels, saved.checkpoint);
270
- const nextTasks = (0, algo_js_1._prepareNextTasks)(saved.checkpoint, this.nodes, channels, managed, saved.config, false, { step: -1 });
271
- yield {
272
- values: (0, io_js_1.readChannels)(channels, this.streamChannelsAsIs),
273
- next: nextTasks.map((task) => task.name),
274
- tasks: (0, debug_js_1.tasksWithWrites)(nextTasks, saved.pendingWrites ?? []),
275
- metadata: saved.metadata,
276
- config: saved.config,
277
- createdAt: saved.checkpoint.ts,
278
- parentConfig: saved.parentConfig,
279
- };
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
+ });
280
432
  }
281
433
  }
282
434
  /**
@@ -284,34 +436,59 @@ class Pregel extends runnables_1.Runnable {
284
436
  * node `as_node`. If `as_node` is not provided, it will be set to the last node
285
437
  * that updated the state, if not ambiguous.
286
438
  */
287
- async updateState(config, values, asNode) {
288
- 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) {
289
442
  throw new errors_js_1.GraphValueError("No checkpointer set");
290
443
  }
291
- // Get the latest checkpoint
292
- const saved = await this.checkpointer.getTuple(config);
293
- 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
294
470
  ? (0, langgraph_checkpoint_1.copyCheckpoint)(saved.checkpoint)
295
471
  : (0, langgraph_checkpoint_1.emptyCheckpoint)();
296
- const checkpointPreviousVersions = saved?.checkpoint.channel_versions ?? {};
472
+ const checkpointPreviousVersions = {
473
+ ...saved?.checkpoint.channel_versions,
474
+ };
297
475
  const step = saved?.metadata?.step ?? -1;
298
476
  // merge configurable fields with previous checkpoint config
299
- const checkpointConfig = {
300
- ...config,
301
- configurable: {
302
- ...config.configurable,
303
- // TODO: add proper support for updating nested subgraph state
304
- checkpoint_ns: "",
305
- ...saved?.config.configurable,
306
- },
307
- };
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
+ }
308
483
  // Find last node that updated the state, if not provided
309
484
  if (values == null && asNode === undefined) {
310
- 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), {
311
486
  source: "update",
312
487
  step,
313
488
  writes: {},
489
+ parents: saved?.metadata?.parents ?? {},
314
490
  }, {});
491
+ return (0, index_js_1.patchCheckpointMap)(nextConfig, saved ? saved.metadata : undefined);
315
492
  }
316
493
  const nonNullVersion = Object.values(checkpoint.versions_seen)
317
494
  .map((seenVersions) => {
@@ -326,7 +503,6 @@ class Pregel extends runnables_1.Runnable {
326
503
  }
327
504
  }
328
505
  else if (asNode === undefined) {
329
- // TODO: Double check
330
506
  const lastSeenByNode = Object.entries(checkpoint.versions_seen)
331
507
  .map(([n, seen]) => {
332
508
  return Object.values(seen).map((v) => {
@@ -383,18 +559,21 @@ class Pregel extends runnables_1.Runnable {
383
559
  task, select_, fresh_),
384
560
  },
385
561
  }));
562
+ // save task writes
386
563
  if (saved !== undefined) {
387
- await this.checkpointer.putWrites(checkpointConfig, task.writes, task.id);
564
+ await checkpointer.putWrites(checkpointConfig, task.writes, task.id);
388
565
  }
389
566
  // apply to checkpoint
390
567
  // TODO: Why does keyof StrRecord allow number and symbol?
391
- (0, algo_js_1._applyWrites)(checkpoint, channels, [task], this.checkpointer.getNextVersion.bind(this.checkpointer));
392
- const newVersions = (0, utils_js_1.getNewChannelVersions)(checkpointPreviousVersions, checkpoint.channel_versions);
393
- return await this.checkpointer.put(checkpointConfig, (0, base_js_1.createCheckpoint)(checkpoint, channels, step + 1), {
568
+ (0, algo_js_1._applyWrites)(checkpoint, channels, [task], checkpointer.getNextVersion.bind(this.checkpointer));
569
+ const newVersions = (0, index_js_1.getNewChannelVersions)(checkpointPreviousVersions, checkpoint.channel_versions);
570
+ const nextConfig = await checkpointer.put(checkpointConfig, (0, base_js_1.createCheckpoint)(checkpoint, channels, step + 1), {
394
571
  source: "update",
395
572
  step: step + 1,
396
573
  writes: { [asNode]: values },
574
+ parents: saved?.metadata?.parents ?? {},
397
575
  }, newVersions);
576
+ return (0, index_js_1.patchCheckpointMap)(nextConfig, saved ? saved.metadata : undefined);
398
577
  }
399
578
  _defaults(config) {
400
579
  const { debug, streamMode, inputKeys, outputKeys, interruptAfter, interruptBefore, ...rest } = config;
@@ -422,25 +601,18 @@ class Pregel extends runnables_1.Runnable {
422
601
  else {
423
602
  defaultStreamMode = this.streamMode;
424
603
  }
425
- let defaultCheckpointer;
426
- if (config.configurable !== undefined &&
427
- config.configurable[constants_js_1.CONFIG_KEY_READ] !== undefined) {
604
+ // if being called as a node in another graph, always use values mode
605
+ if (config.configurable?.[constants_js_1.CONFIG_KEY_TASK_ID] !== undefined) {
428
606
  defaultStreamMode = ["values"];
429
607
  }
608
+ let defaultCheckpointer;
430
609
  if (config !== undefined &&
431
- config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] !== undefined &&
432
- (defaultInterruptAfter.length > 0 || defaultInterruptBefore.length > 0)) {
610
+ config.configurable?.[constants_js_1.CONFIG_KEY_CHECKPOINTER] !== undefined) {
433
611
  defaultCheckpointer = config.configurable[constants_js_1.CONFIG_KEY_CHECKPOINTER];
434
612
  }
435
613
  else {
436
614
  defaultCheckpointer = this.checkpointer;
437
615
  }
438
- if (this.configKeys !== undefined) {
439
- const newConfigurable = Object.fromEntries(Object.entries(rest.configurable ?? {}).filter(([key]) => {
440
- return this.configKeys?.includes(key);
441
- }));
442
- rest.configurable = newConfigurable;
443
- }
444
616
  return [
445
617
  defaultDebug,
446
618
  defaultStreamMode,
@@ -471,7 +643,7 @@ class Pregel extends runnables_1.Runnable {
471
643
  return super.stream(input, options);
472
644
  }
473
645
  async prepareSpecs(config, options) {
474
- const configForManaged = (0, utils_js_2.patchConfigurable)(config, {
646
+ const configForManaged = (0, utils_js_1.patchConfigurable)(config, {
475
647
  [constants_js_1.CONFIG_KEY_STORE]: this.store,
476
648
  });
477
649
  const channelSpecs = {};
@@ -514,7 +686,8 @@ class Pregel extends runnables_1.Runnable {
514
686
  };
515
687
  }
516
688
  async *_streamIterator(input, options) {
517
- const inputConfig = (0, runnables_1.ensureConfig)(options);
689
+ const streamSubgraphs = options?.subgraphs;
690
+ const inputConfig = (0, config_js_1.ensureLangGraphConfig)(this.config, options);
518
691
  if (inputConfig.recursionLimit === undefined ||
519
692
  inputConfig.recursionLimit < 1) {
520
693
  throw new Error(`Passed "recursionLimit" must be at least 1.`);
@@ -524,12 +697,36 @@ class Pregel extends runnables_1.Runnable {
524
697
  throw new Error(`Checkpointer requires one or more of the following "configurable" keys: "thread_id", "checkpoint_ns", "checkpoint_id"`);
525
698
  }
526
699
  const callbackManager = await (0, runnables_1.getCallbackManagerForConfig)(inputConfig);
527
- const runManager = await callbackManager?.handleChainStart(this.toJSON(), (0, utils_js_1._coerceToDict)(input, "input"), inputConfig.runId, undefined, undefined, undefined, inputConfig?.runName ?? this.getName());
700
+ const runManager = await callbackManager?.handleChainStart(this.toJSON(), (0, index_js_1._coerceToDict)(input, "input"), inputConfig.runId, undefined, undefined, undefined, inputConfig?.runName ?? this.getName());
528
701
  delete inputConfig.runId;
529
702
  // assign defaults
530
703
  const [debug, streamMode, , outputKeys, config, interruptBefore, interruptAfter, checkpointer,] = this._defaults(inputConfig);
531
704
  const { channelSpecs, managed } = await this.prepareSpecs(config);
532
705
  let loop;
706
+ const stream = new double_ended_queue_1.default();
707
+ function* emitCurrentLoopOutputs() {
708
+ while (loop !== undefined && stream.length > 0) {
709
+ const nextItem = stream.shift();
710
+ if (nextItem === undefined) {
711
+ throw new Error("Data structure error.");
712
+ }
713
+ const [namespace, mode, payload] = nextItem;
714
+ if (streamMode.includes(mode)) {
715
+ if (streamSubgraphs && streamMode.length > 1) {
716
+ yield [namespace, mode, payload];
717
+ }
718
+ else if (streamMode.length > 1) {
719
+ yield [mode, payload];
720
+ }
721
+ else if (streamSubgraphs) {
722
+ yield [namespace, payload];
723
+ }
724
+ else {
725
+ yield payload;
726
+ }
727
+ }
728
+ }
729
+ }
533
730
  try {
534
731
  loop = await loop_js_1.PregelLoop.initialize({
535
732
  input,
@@ -541,7 +738,14 @@ class Pregel extends runnables_1.Runnable {
541
738
  outputKeys,
542
739
  streamKeys: this.streamChannelsAsIs,
543
740
  store: this.store,
741
+ stream: new loop_js_1.StreamProtocol((chunk) => stream.push(chunk), new Set(streamMode)),
544
742
  });
743
+ if (options?.subgraphs) {
744
+ loop.config.configurable = {
745
+ ...loop.config.configurable,
746
+ [constants_js_1.CONFIG_KEY_STREAM]: loop.stream,
747
+ };
748
+ }
545
749
  while (await loop.tick({
546
750
  inputKeys: this.inputChannels,
547
751
  interruptAfter,
@@ -551,27 +755,14 @@ class Pregel extends runnables_1.Runnable {
551
755
  if (debug) {
552
756
  (0, debug_js_1.printStepCheckpoint)(loop.checkpointMetadata.step, loop.channels, this.streamChannelsList);
553
757
  }
554
- while (loop.stream.length > 0) {
555
- const nextItem = loop.stream.shift();
556
- if (nextItem === undefined) {
557
- throw new Error("Data structure error.");
558
- }
559
- if (streamMode.includes(nextItem[0])) {
560
- if (streamMode.length === 1) {
561
- yield nextItem[1];
562
- }
563
- else {
564
- yield nextItem;
565
- }
566
- }
567
- }
758
+ yield* emitCurrentLoopOutputs();
568
759
  if (debug) {
569
- (0, debug_js_1.printStepTasks)(loop.step, loop.tasks);
760
+ (0, debug_js_1.printStepTasks)(loop.step, Object.values(loop.tasks));
570
761
  }
571
762
  // execute tasks, and wait for one to fail or all to finish.
572
763
  // each task is independent from all other concurrent tasks
573
764
  // yield updates/debug output as each task finishes
574
- const taskStream = (0, retry_js_1.executeTasksWithRetry)(loop.tasks.filter((task) => task.writes.length === 0), {
765
+ const taskStream = (0, retry_js_1.executeTasksWithRetry)(Object.values(loop.tasks).filter((task) => task.writes.length === 0), {
575
766
  stepTimeout: this.stepTimeout,
576
767
  signal: config.signal,
577
768
  retryPolicy: this.retryPolicy,
@@ -580,7 +771,12 @@ class Pregel extends runnables_1.Runnable {
580
771
  for await (const { task, error } of taskStream) {
581
772
  if (error !== undefined) {
582
773
  if ((0, errors_js_1.isGraphInterrupt)(error)) {
583
- loop.putWrites(task.id, error.interrupts.map((interrupt) => [constants_js_1.INTERRUPT, interrupt]));
774
+ if (loop.isNested) {
775
+ throw error;
776
+ }
777
+ if (error.interrupts.length) {
778
+ loop.putWrites(task.id, error.interrupts.map((interrupt) => [constants_js_1.INTERRUPT, interrupt]));
779
+ }
584
780
  }
585
781
  else {
586
782
  loop.putWrites(task.id, [
@@ -591,42 +787,18 @@ class Pregel extends runnables_1.Runnable {
591
787
  else {
592
788
  loop.putWrites(task.id, task.writes);
593
789
  }
594
- while (loop.stream.length > 0) {
595
- const nextItem = loop.stream.shift();
596
- if (nextItem === undefined) {
597
- throw new Error("Data structure error.");
598
- }
599
- if (streamMode.includes(nextItem[0])) {
600
- if (streamMode.length === 1) {
601
- yield nextItem[1];
602
- }
603
- else {
604
- yield nextItem;
605
- }
606
- }
607
- }
790
+ yield* emitCurrentLoopOutputs();
608
791
  if (error !== undefined && !(0, errors_js_1.isGraphInterrupt)(error)) {
609
792
  throw error;
610
793
  }
611
794
  }
612
795
  if (debug) {
613
- (0, debug_js_1.printStepWrites)(loop.step, loop.tasks.map((task) => task.writes).flat(), this.streamChannelsList);
614
- }
615
- }
616
- while (loop.stream.length > 0) {
617
- const nextItem = loop.stream.shift();
618
- if (nextItem === undefined) {
619
- throw new Error("Data structure error.");
620
- }
621
- if (streamMode.includes(nextItem[0])) {
622
- if (streamMode.length === 1) {
623
- yield nextItem[1];
624
- }
625
- else {
626
- yield nextItem;
627
- }
796
+ (0, debug_js_1.printStepWrites)(loop.step, Object.values(loop.tasks)
797
+ .map((task) => task.writes)
798
+ .flat(), this.streamChannelsList);
628
799
  }
629
800
  }
801
+ yield* emitCurrentLoopOutputs();
630
802
  if (loop.status === "out_of_steps") {
631
803
  throw new errors_js_1.GraphRecursionError([
632
804
  `Recursion limit of ${config.recursionLimit} reached`,
@@ -635,7 +807,7 @@ class Pregel extends runnables_1.Runnable {
635
807
  ].join(" "));
636
808
  }
637
809
  await Promise.all(loop?.checkpointerPromises ?? []);
638
- await runManager?.handleChainEnd((0, io_js_1.readChannels)(loop.channels, outputKeys));
810
+ await runManager?.handleChainEnd(loop.output);
639
811
  }
640
812
  catch (e) {
641
813
  await runManager?.handleChainError(e);
@@ -670,7 +842,7 @@ class Pregel extends runnables_1.Runnable {
670
842
  async invoke(input, options) {
671
843
  const streamMode = options?.streamMode ?? "values";
672
844
  const config = {
673
- ...(0, runnables_1.ensureConfig)(options),
845
+ ...options,
674
846
  outputKeys: options?.outputKeys ?? this.outputChannels,
675
847
  streamMode,
676
848
  };