@langchain/langgraph 0.1.0-rc.0 → 0.1.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 (62) hide show
  1. package/LICENSE +1 -1
  2. package/dist/channels/base.cjs +20 -15
  3. package/dist/channels/base.d.ts +2 -3
  4. package/dist/channels/base.js +18 -13
  5. package/dist/checkpoint/sqlite.cjs +14 -199
  6. package/dist/checkpoint/sqlite.d.ts +1 -16
  7. package/dist/checkpoint/sqlite.js +1 -195
  8. package/dist/graph/graph.d.ts +1 -1
  9. package/dist/graph/message.d.ts +0 -3
  10. package/dist/graph/messages_annotation.cjs +12 -0
  11. package/dist/graph/messages_annotation.d.ts +4 -0
  12. package/dist/graph/messages_annotation.js +9 -0
  13. package/dist/graph/state.cjs +2 -1
  14. package/dist/graph/state.d.ts +1 -1
  15. package/dist/graph/state.js +2 -1
  16. package/dist/index.cjs +3 -0
  17. package/dist/index.d.ts +1 -0
  18. package/dist/index.js +1 -0
  19. package/dist/prebuilt/react_agent_executor.d.ts +3 -3
  20. package/dist/prebuilt/tool_node.d.ts +3 -3
  21. package/dist/pregel/algo.cjs +112 -105
  22. package/dist/pregel/algo.d.ts +8 -5
  23. package/dist/pregel/algo.js +109 -102
  24. package/dist/pregel/debug.cjs +9 -12
  25. package/dist/pregel/debug.d.ts +3 -2
  26. package/dist/pregel/debug.js +6 -10
  27. package/dist/pregel/index.cjs +92 -26
  28. package/dist/pregel/index.d.ts +41 -3
  29. package/dist/pregel/index.js +90 -24
  30. package/dist/pregel/io.d.ts +1 -1
  31. package/dist/pregel/loop.cjs +13 -9
  32. package/dist/pregel/loop.d.ts +1 -2
  33. package/dist/pregel/loop.js +8 -4
  34. package/dist/pregel/types.d.ts +5 -2
  35. package/dist/pregel/utils.cjs +25 -10
  36. package/dist/pregel/utils.d.ts +8 -1
  37. package/dist/pregel/utils.js +22 -9
  38. package/dist/web.cjs +6 -7
  39. package/dist/web.d.ts +1 -4
  40. package/dist/web.js +1 -2
  41. package/package.json +12 -12
  42. package/dist/checkpoint/base.cjs +0 -75
  43. package/dist/checkpoint/base.d.ts +0 -78
  44. package/dist/checkpoint/base.js +0 -66
  45. package/dist/checkpoint/id.cjs +0 -20
  46. package/dist/checkpoint/id.d.ts +0 -2
  47. package/dist/checkpoint/id.js +0 -15
  48. package/dist/checkpoint/index.cjs +0 -9
  49. package/dist/checkpoint/index.d.ts +0 -3
  50. package/dist/checkpoint/index.js +0 -2
  51. package/dist/checkpoint/memory.cjs +0 -195
  52. package/dist/checkpoint/memory.d.ts +0 -13
  53. package/dist/checkpoint/memory.js +0 -191
  54. package/dist/checkpoint/serde/types.cjs +0 -2
  55. package/dist/checkpoint/serde/types.d.ts +0 -40
  56. package/dist/checkpoint/serde/types.js +0 -1
  57. package/dist/checkpoint/types.cjs +0 -2
  58. package/dist/checkpoint/types.d.ts +0 -28
  59. package/dist/checkpoint/types.js +0 -1
  60. package/dist/serde/base.cjs +0 -8
  61. package/dist/serde/base.d.ts +0 -12
  62. package/dist/serde/base.js +0 -5
@@ -1,6 +1,7 @@
1
1
  import { Runnable, RunnableConfig, RunnableFunc } from "@langchain/core/runnables";
2
+ import { IterableReadableStream } from "@langchain/core/utils/stream";
3
+ import { BaseCheckpointSaver, CheckpointListOptions } from "@langchain/langgraph-checkpoint";
2
4
  import { BaseChannel } from "../channels/base.js";
3
- import { BaseCheckpointSaver, CheckpointListOptions } from "../checkpoint/base.js";
4
5
  import { PregelNode } from "./read.js";
5
6
  import { ChannelWrite } from "./write.js";
6
7
  import { All, PregelInterface, PregelParams, StateSnapshot, StreamMode } from "./types.js";
@@ -53,8 +54,19 @@ export declare class Pregel<Nn extends StrRecord<string, PregelNode>, Cc extends
53
54
  validate(): this;
54
55
  get streamChannelsList(): Array<keyof Cc>;
55
56
  get streamChannelsAsIs(): keyof Cc | Array<keyof Cc>;
57
+ /**
58
+ * Get the current state of the graph.
59
+ */
56
60
  getState(config: RunnableConfig): Promise<StateSnapshot>;
61
+ /**
62
+ * Get the history of the state of the graph.
63
+ */
57
64
  getStateHistory(config: RunnableConfig, options?: CheckpointListOptions): AsyncIterableIterator<StateSnapshot>;
65
+ /**
66
+ * Update the state of the graph with the given values, as if they came from
67
+ * node `as_node`. If `as_node` is not provided, it will be set to the last node
68
+ * that updated the state, if not ambiguous.
69
+ */
58
70
  updateState(config: RunnableConfig, values: Record<string, unknown> | unknown, asNode?: keyof Nn): Promise<RunnableConfig>;
59
71
  _defaults(config: PregelOptions<Nn, Cc>): [
60
72
  boolean,
@@ -71,11 +83,37 @@ export declare class Pregel<Nn extends StrRecord<string, PregelNode>, Cc extends
71
83
  // interrupt after
72
84
  BaseCheckpointSaver | undefined
73
85
  ];
86
+ /**
87
+ * Stream graph steps for a single input.
88
+ * @param input The input to the graph.
89
+ * @param options The configuration to use for the run.
90
+ * @param options.streamMode The mode to stream output. Defaults to value set on initialization.
91
+ * Options are "values", "updates", and "debug". Default is "values".
92
+ * values: Emit the current values of the state for each step.
93
+ * updates: Emit only the updates to the state for each step.
94
+ * Output is a dict with the node name as key and the updated values as value.
95
+ * debug: Emit debug events for each step.
96
+ * @param options.outputKeys The keys to stream. Defaults to all non-context channels.
97
+ * @param options.interruptBefore Nodes to interrupt before.
98
+ * @param options.interruptAfter Nodes to interrupt after.
99
+ * @param options.debug Whether to print debug information during execution.
100
+ */
101
+ stream(input: PregelInputType, options?: Partial<PregelOptions<Nn, Cc>>): Promise<IterableReadableStream<PregelOutputType>>;
74
102
  _streamIterator(input: PregelInputType, options?: Partial<PregelOptions<Nn, Cc>>): AsyncGenerator<PregelOutputType>;
75
103
  /**
76
104
  * Run the graph with a single input and config.
77
- * @param input
78
- * @param options
105
+ * @param input The input to the graph.
106
+ * @param options The configuration to use for the run.
107
+ * @param options.streamMode The mode to stream output. Defaults to value set on initialization.
108
+ * Options are "values", "updates", and "debug". Default is "values".
109
+ * values: Emit the current values of the state for each step.
110
+ * updates: Emit only the updates to the state for each step.
111
+ * Output is a dict with the node name as key and the updated values as value.
112
+ * debug: Emit debug events for each step.
113
+ * @param options.outputKeys The keys to stream. Defaults to all non-context channels.
114
+ * @param options.interruptBefore Nodes to interrupt before.
115
+ * @param options.interruptAfter Nodes to interrupt after.
116
+ * @param options.debug Whether to print debug information during execution.
79
117
  */
80
118
  invoke(input: PregelInputType, options?: Partial<PregelOptions<Nn, Cc>>): Promise<PregelOutputType>;
81
119
  }
@@ -1,16 +1,15 @@
1
1
  /* eslint-disable no-param-reassign */
2
2
  import { Runnable, RunnableSequence, _coerceToRunnable, ensureConfig, getCallbackManagerForConfig, patchConfig, } from "@langchain/core/runnables";
3
+ import { copyCheckpoint, emptyCheckpoint, uuid5, } from "@langchain/langgraph-checkpoint";
3
4
  import { createCheckpoint, emptyChannels, } from "../channels/base.js";
4
- import { copyCheckpoint, emptyCheckpoint, } from "../checkpoint/base.js";
5
5
  import { PregelNode } from "./read.js";
6
6
  import { validateGraph, validateKeys } from "./validate.js";
7
7
  import { mapOutputUpdates, readChannels } from "./io.js";
8
- import { mapDebugTaskResults, printStepCheckpoint, printStepTasks, printStepWrites, } from "./debug.js";
8
+ import { mapDebugTaskResults, printStepCheckpoint, printStepTasks, printStepWrites, tasksWithWrites, } from "./debug.js";
9
9
  import { ChannelWrite, PASSTHROUGH } from "./write.js";
10
- import { CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_READ, CONFIG_KEY_SEND, INTERRUPT, } from "../constants.js";
10
+ import { CONFIG_KEY_CHECKPOINTER, CONFIG_KEY_READ, CONFIG_KEY_SEND, ERROR, INTERRUPT, } from "../constants.js";
11
11
  import { GraphRecursionError, GraphValueError, InvalidUpdateError, } from "../errors.js";
12
12
  import { executeTasks, _prepareNextTasks, _localRead, _applyWrites, } from "./algo.js";
13
- import { uuid5 } from "../checkpoint/id.js";
14
13
  import { prefixGenerator } from "../utils.js";
15
14
  import { _coerceToDict, getNewChannelVersions } from "./utils.js";
16
15
  import { PregelLoop } from "./loop.js";
@@ -207,6 +206,9 @@ export class Pregel extends Runnable {
207
206
  return Object.keys(this.channels);
208
207
  }
209
208
  }
209
+ /**
210
+ * Get the current state of the graph.
211
+ */
210
212
  async getState(config) {
211
213
  if (!this.checkpointer) {
212
214
  throw new GraphValueError("No checkpointer set");
@@ -214,26 +216,31 @@ export class Pregel extends Runnable {
214
216
  const saved = await this.checkpointer.getTuple(config);
215
217
  const checkpoint = saved ? saved.checkpoint : emptyCheckpoint();
216
218
  const channels = emptyChannels(this.channels, checkpoint);
217
- const [, nextTasks] = _prepareNextTasks(checkpoint, this.nodes, channels, saved !== undefined ? saved.config : config, false, { step: -1 });
219
+ const nextTasks = _prepareNextTasks(checkpoint, this.nodes, channels, saved !== undefined ? saved.config : config, false, { step: saved ? (saved.metadata?.step ?? -1) + 1 : -1 });
218
220
  return {
219
221
  values: readChannels(channels, this.streamChannelsAsIs),
220
222
  next: nextTasks.map((task) => task.name),
223
+ tasks: tasksWithWrites(nextTasks, saved?.pendingWrites ?? []),
221
224
  metadata: saved?.metadata,
222
225
  config: saved ? saved.config : config,
223
226
  createdAt: saved?.checkpoint.ts,
224
227
  parentConfig: saved?.parentConfig,
225
228
  };
226
229
  }
230
+ /**
231
+ * Get the history of the state of the graph.
232
+ */
227
233
  async *getStateHistory(config, options) {
228
234
  if (!this.checkpointer) {
229
235
  throw new GraphValueError("No checkpointer set");
230
236
  }
231
237
  for await (const saved of this.checkpointer.list(config, options)) {
232
238
  const channels = emptyChannels(this.channels, saved.checkpoint);
233
- const [, nextTasks] = _prepareNextTasks(saved.checkpoint, this.nodes, channels, saved.config, false, { step: -1 });
239
+ const nextTasks = _prepareNextTasks(saved.checkpoint, this.nodes, channels, saved.config, false, { step: -1 });
234
240
  yield {
235
241
  values: readChannels(channels, this.streamChannelsAsIs),
236
242
  next: nextTasks.map((task) => task.name),
243
+ tasks: tasksWithWrites(nextTasks, saved.pendingWrites ?? []),
237
244
  metadata: saved.metadata,
238
245
  config: saved.config,
239
246
  createdAt: saved.checkpoint.ts,
@@ -241,6 +248,11 @@ export class Pregel extends Runnable {
241
248
  };
242
249
  }
243
250
  }
251
+ /**
252
+ * Update the state of the graph with the given values, as if they came from
253
+ * node `as_node`. If `as_node` is not provided, it will be set to the last node
254
+ * that updated the state, if not ambiguous.
255
+ */
244
256
  async updateState(config, values, asNode) {
245
257
  if (!this.checkpointer) {
246
258
  throw new GraphValueError("No checkpointer set");
@@ -263,8 +275,8 @@ export class Pregel extends Runnable {
263
275
  },
264
276
  };
265
277
  // Find last node that updated the state, if not provided
266
- if (values === undefined && asNode === undefined) {
267
- return await this.checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, {}, step), {
278
+ if (values == null && asNode === undefined) {
279
+ return await this.checkpointer.put(checkpointConfig, createCheckpoint(checkpoint, undefined, step), {
268
280
  source: "update",
269
281
  step,
270
282
  writes: {},
@@ -276,7 +288,7 @@ export class Pregel extends Runnable {
276
288
  })
277
289
  .flat()
278
290
  .find((v) => !!v);
279
- if (asNode === undefined && !nonNullVersion) {
291
+ if (asNode === undefined && nonNullVersion === undefined) {
280
292
  if (typeof this.inputChannels === "string" &&
281
293
  this.nodes[this.inputChannels] !== undefined) {
282
294
  asNode = this.inputChannels;
@@ -401,6 +413,24 @@ export class Pregel extends Runnable {
401
413
  defaultCheckpointer,
402
414
  ];
403
415
  }
416
+ /**
417
+ * Stream graph steps for a single input.
418
+ * @param input The input to the graph.
419
+ * @param options The configuration to use for the run.
420
+ * @param options.streamMode The mode to stream output. Defaults to value set on initialization.
421
+ * Options are "values", "updates", and "debug". Default is "values".
422
+ * values: Emit the current values of the state for each step.
423
+ * updates: Emit only the updates to the state for each step.
424
+ * Output is a dict with the node name as key and the updated values as value.
425
+ * debug: Emit debug events for each step.
426
+ * @param options.outputKeys The keys to stream. Defaults to all non-context channels.
427
+ * @param options.interruptBefore Nodes to interrupt before.
428
+ * @param options.interruptAfter Nodes to interrupt after.
429
+ * @param options.debug Whether to print debug information during execution.
430
+ */
431
+ async stream(input, options) {
432
+ return super.stream(input, options);
433
+ }
404
434
  async *_streamIterator(input, options) {
405
435
  const inputConfig = ensureConfig(options);
406
436
  if (inputConfig.recursionLimit === undefined ||
@@ -459,21 +489,47 @@ export class Pregel extends Runnable {
459
489
  // execute tasks, and wait for one to fail or all to finish.
460
490
  // each task is independent from all other concurrent tasks
461
491
  // yield updates/debug output as each task finishes
462
- const tasks = loop.tasks.map((pregelTask) => () => {
463
- return pregelTask.proc.invoke(pregelTask.input, pregelTask.config);
464
- });
465
- await executeTasks(tasks, this.stepTimeout, config.signal);
466
- for (const task of loop.tasks) {
467
- loop.putWrites(task.id, task.writes);
468
- }
469
- if (streamMode.includes("updates")) {
470
- // TODO: Refactor
471
- for await (const task of loop.tasks) {
472
- yield* prefixGenerator(mapOutputUpdates(outputKeys, [task]), streamMode.length > 1 ? "updates" : undefined);
492
+ const tasks = Object.fromEntries(loop.tasks
493
+ .filter((task) => task.writes.length === 0)
494
+ .map((pregelTask) => {
495
+ return [
496
+ pregelTask.id,
497
+ async () => {
498
+ let error;
499
+ let result;
500
+ try {
501
+ result = await pregelTask.proc.invoke(pregelTask.input, pregelTask.config);
502
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
503
+ }
504
+ catch (e) {
505
+ error = e;
506
+ error.pregelTaskId = pregelTask.id;
507
+ }
508
+ return {
509
+ task: pregelTask,
510
+ result,
511
+ error,
512
+ };
513
+ },
514
+ ];
515
+ }));
516
+ try {
517
+ for await (const task of executeTasks(tasks, this.stepTimeout, config.signal)) {
518
+ loop.putWrites(task.id, task.writes);
519
+ if (streamMode.includes("updates")) {
520
+ yield* prefixGenerator(mapOutputUpdates(outputKeys, [task]), streamMode.length > 1 ? "updates" : undefined);
521
+ }
522
+ if (streamMode.includes("debug")) {
523
+ yield* prefixGenerator(mapDebugTaskResults(loop.step, [task], this.streamChannelsList), streamMode.length > 1 ? "debug" : undefined);
524
+ }
473
525
  }
526
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
474
527
  }
475
- if (streamMode.includes("debug")) {
476
- yield* prefixGenerator(mapDebugTaskResults(loop.step, loop.tasks, this.streamChannelsList), streamMode.length > 1 ? "debug" : undefined);
528
+ catch (e) {
529
+ if (e.pregelTaskId) {
530
+ loop.putWrites(e.pregelTaskId, [[ERROR, { message: e.message }]]);
531
+ }
532
+ throw e;
477
533
  }
478
534
  if (debug) {
479
535
  printStepWrites(loop.step, loop.tasks.map((task) => task.writes).flat(), this.streamChannelsList);
@@ -515,8 +571,18 @@ export class Pregel extends Runnable {
515
571
  }
516
572
  /**
517
573
  * Run the graph with a single input and config.
518
- * @param input
519
- * @param options
574
+ * @param input The input to the graph.
575
+ * @param options The configuration to use for the run.
576
+ * @param options.streamMode The mode to stream output. Defaults to value set on initialization.
577
+ * Options are "values", "updates", and "debug". Default is "values".
578
+ * values: Emit the current values of the state for each step.
579
+ * updates: Emit only the updates to the state for each step.
580
+ * Output is a dict with the node name as key and the updated values as value.
581
+ * debug: Emit debug events for each step.
582
+ * @param options.outputKeys The keys to stream. Defaults to all non-context channels.
583
+ * @param options.interruptBefore Nodes to interrupt before.
584
+ * @param options.interruptAfter Nodes to interrupt after.
585
+ * @param options.debug Whether to print debug information during execution.
520
586
  */
521
587
  async invoke(input, options) {
522
588
  const streamMode = options?.streamMode ?? "values";
@@ -1,6 +1,6 @@
1
+ import type { PendingWrite } from "@langchain/langgraph-checkpoint";
1
2
  import type { BaseChannel } from "../channels/base.js";
2
3
  import type { PregelExecutableTask } from "./types.js";
3
- import type { PendingWrite } from "../checkpoint/types.js";
4
4
  export declare function readChannel<C extends PropertyKey>(channels: Record<C, BaseChannel>, chan: C, catchErrors?: boolean, returnException?: boolean): unknown | null;
5
5
  export declare function readChannels<C extends PropertyKey>(channels: Record<C, BaseChannel>, select: C | Array<C>, skipEmpty?: boolean): Record<string, any> | any;
6
6
  /**
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.PregelLoop = void 0;
7
7
  const double_ended_queue_1 = __importDefault(require("double-ended-queue"));
8
- const base_js_1 = require("../checkpoint/base.cjs");
9
- const base_js_2 = require("../channels/base.cjs");
8
+ const langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
9
+ const base_js_1 = require("../channels/base.cjs");
10
10
  const constants_js_1 = require("../constants.cjs");
11
11
  const algo_js_1 = require("./algo.cjs");
12
12
  const utils_js_1 = require("../utils.cjs");
@@ -167,7 +167,7 @@ class PregelLoop {
167
167
  static async initialize(params) {
168
168
  const saved = (await params.checkpointer?.getTuple(params.config)) ?? {
169
169
  config: params.config,
170
- checkpoint: (0, base_js_1.emptyCheckpoint)(),
170
+ checkpoint: (0, langgraph_checkpoint_1.emptyCheckpoint)(),
171
171
  metadata: {
172
172
  source: "input",
173
173
  step: -2,
@@ -183,10 +183,10 @@ class PregelLoop {
183
183
  ...saved.config.configurable,
184
184
  },
185
185
  };
186
- const checkpoint = (0, base_js_1.copyCheckpoint)(saved.checkpoint);
186
+ const checkpoint = (0, langgraph_checkpoint_1.copyCheckpoint)(saved.checkpoint);
187
187
  const checkpointMetadata = { ...saved.metadata };
188
188
  const checkpointPendingWrites = saved.pendingWrites ?? [];
189
- const channels = (0, base_js_2.emptyChannels)(params.graph.channels, checkpoint);
189
+ const channels = (0, base_js_1.emptyChannels)(params.graph.channels, checkpoint);
190
190
  const step = (checkpointMetadata.step ?? 0) + 1;
191
191
  const stop = step + (params.config.recursionLimit ?? DEFAULT_LOOP_LIMIT) + 1;
192
192
  const checkpointPreviousVersions = { ...checkpoint.channel_versions };
@@ -289,7 +289,7 @@ class PregelLoop {
289
289
  this.status = "out_of_steps";
290
290
  return false;
291
291
  }
292
- const [, nextTasks] = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.graph.nodes, this.channels, this.config, true, {
292
+ const nextTasks = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.graph.nodes, this.channels, this.config, true, {
293
293
  step: this.step,
294
294
  checkpointer: this.checkpointer,
295
295
  isResuming: this.input === INPUT_RESUMING,
@@ -308,6 +308,10 @@ class PregelLoop {
308
308
  // if there are pending writes from a previous loop, apply them
309
309
  if (this.checkpointPendingWrites.length > 0) {
310
310
  for (const [tid, k, v] of this.checkpointPendingWrites) {
311
+ // TODO: Do the same for INTERRUPT
312
+ if (k === constants_js_1.ERROR) {
313
+ continue;
314
+ }
311
315
  const task = this.tasks.find((t) => t.id === tid);
312
316
  if (task) {
313
317
  task.writes.push([k, v]);
@@ -364,7 +368,7 @@ class PregelLoop {
364
368
  if (inputWrites.length === 0) {
365
369
  throw new errors_js_1.EmptyInputError(`Received no input writes for ${JSON.stringify(this.graph.inputChannels, null, 2)}`);
366
370
  }
367
- const [, discardTasks] = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.graph.nodes, this.channels, this.config, true, { step: this.step });
371
+ const discardTasks = (0, algo_js_1._prepareNextTasks)(this.checkpoint, this.graph.nodes, this.channels, this.config, true, { step: this.step });
368
372
  (0, algo_js_1._applyWrites)(this.checkpoint, this.channels, discardTasks.concat([
369
373
  {
370
374
  name: constants_js_1.INPUT,
@@ -392,7 +396,7 @@ class PregelLoop {
392
396
  // this is achieved by writing child checkpoints as progress is made
393
397
  // (so that error recovery / resuming from interrupt don't lose work)
394
398
  // but doing so always with an id equal to that of the parent checkpoint
395
- this.checkpoint = (0, base_js_2.createCheckpoint)(this.checkpoint, this.channels, this.step
399
+ this.checkpoint = (0, base_js_1.createCheckpoint)(this.checkpoint, this.channels, this.step
396
400
  // id: this.isNested ? this.config.configurable?.checkpoint_id : undefined,
397
401
  );
398
402
  this.checkpointConfig = {
@@ -410,7 +414,7 @@ class PregelLoop {
410
414
  // ensuring checkpointers receive checkpoints in order
411
415
  void this._checkpointerPutAfterPrevious({
412
416
  config: { ...this.checkpointConfig },
413
- checkpoint: (0, base_js_1.copyCheckpoint)(this.checkpoint),
417
+ checkpoint: (0, langgraph_checkpoint_1.copyCheckpoint)(this.checkpoint),
414
418
  metadata: { ...this.checkpointMetadata },
415
419
  newVersions,
416
420
  });
@@ -1,10 +1,9 @@
1
1
  import Deque from "double-ended-queue";
2
2
  import type { RunnableConfig } from "@langchain/core/runnables";
3
3
  import type { CallbackManagerForChainRun } from "@langchain/core/callbacks/manager";
4
- import { BaseCheckpointSaver, Checkpoint } from "../checkpoint/base.js";
4
+ import { BaseCheckpointSaver, Checkpoint, PendingWrite, CheckpointPendingWrite, CheckpointMetadata, All } from "@langchain/langgraph-checkpoint";
5
5
  import { BaseChannel } from "../channels/base.js";
6
6
  import { PregelExecutableTask, PregelInterface, StreamMode } from "./types.js";
7
- import { PendingWrite, CheckpointPendingWrite, CheckpointMetadata, All } from "../checkpoint/types.js";
8
7
  export type PregelLoopInitializeParams = {
9
8
  input?: any;
10
9
  config: RunnableConfig;
@@ -1,7 +1,7 @@
1
1
  import Deque from "double-ended-queue";
2
- import { copyCheckpoint, emptyCheckpoint, } from "../checkpoint/base.js";
2
+ import { copyCheckpoint, emptyCheckpoint, } from "@langchain/langgraph-checkpoint";
3
3
  import { createCheckpoint, emptyChannels, } from "../channels/base.js";
4
- import { CONFIG_KEY_READ, CONFIG_KEY_RESUMING, INPUT, INTERRUPT, } from "../constants.js";
4
+ import { CONFIG_KEY_READ, CONFIG_KEY_RESUMING, ERROR, INPUT, INTERRUPT, } from "../constants.js";
5
5
  import { _applyWrites, _prepareNextTasks, increment, shouldInterrupt, } from "./algo.js";
6
6
  import { gatherIterator, prefixGenerator } from "../utils.js";
7
7
  import { mapInput, mapOutputUpdates, mapOutputValues } from "./io.js";
@@ -283,7 +283,7 @@ export class PregelLoop {
283
283
  this.status = "out_of_steps";
284
284
  return false;
285
285
  }
286
- const [, nextTasks] = _prepareNextTasks(this.checkpoint, this.graph.nodes, this.channels, this.config, true, {
286
+ const nextTasks = _prepareNextTasks(this.checkpoint, this.graph.nodes, this.channels, this.config, true, {
287
287
  step: this.step,
288
288
  checkpointer: this.checkpointer,
289
289
  isResuming: this.input === INPUT_RESUMING,
@@ -302,6 +302,10 @@ export class PregelLoop {
302
302
  // if there are pending writes from a previous loop, apply them
303
303
  if (this.checkpointPendingWrites.length > 0) {
304
304
  for (const [tid, k, v] of this.checkpointPendingWrites) {
305
+ // TODO: Do the same for INTERRUPT
306
+ if (k === ERROR) {
307
+ continue;
308
+ }
305
309
  const task = this.tasks.find((t) => t.id === tid);
306
310
  if (task) {
307
311
  task.writes.push([k, v]);
@@ -358,7 +362,7 @@ export class PregelLoop {
358
362
  if (inputWrites.length === 0) {
359
363
  throw new EmptyInputError(`Received no input writes for ${JSON.stringify(this.graph.inputChannels, null, 2)}`);
360
364
  }
361
- const [, discardTasks] = _prepareNextTasks(this.checkpoint, this.graph.nodes, this.channels, this.config, true, { step: this.step });
365
+ const discardTasks = _prepareNextTasks(this.checkpoint, this.graph.nodes, this.channels, this.config, true, { step: this.step });
362
366
  _applyWrites(this.checkpoint, this.channels, discardTasks.concat([
363
367
  {
364
368
  name: INPUT,
@@ -1,6 +1,5 @@
1
1
  import type { Runnable, RunnableConfig } from "@langchain/core/runnables";
2
- import type { PendingWrite, CheckpointMetadata } from "../checkpoint/types.js";
3
- import type { BaseCheckpointSaver } from "../checkpoint/base.js";
2
+ import type { PendingWrite, CheckpointMetadata, BaseCheckpointSaver } from "@langchain/langgraph-checkpoint";
4
3
  import type { BaseChannel } from "../channels/base.js";
5
4
  import type { PregelNode } from "./read.js";
6
5
  export type StreamMode = "values" | "updates" | "debug";
@@ -85,6 +84,10 @@ export interface StateSnapshot {
85
84
  * @default undefined
86
85
  */
87
86
  readonly parentConfig?: RunnableConfig | undefined;
87
+ /**
88
+ * Tasks to execute in this step. If already attempted, may contain an error.
89
+ */
90
+ readonly tasks: PregelTaskDescription[];
88
91
  }
89
92
  export type All = "*";
90
93
  export {};
@@ -1,18 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._coerceToDict = exports.getNewChannelVersions = void 0;
3
+ exports._getIdMetadata = exports._coerceToDict = exports.getNewChannelVersions = exports.getNullChannelVersion = void 0;
4
+ function getNullChannelVersion(currentVersions) {
5
+ const versionValues = Object.values(currentVersions);
6
+ const versionType = versionValues.length > 0 ? typeof versionValues[0] : undefined;
7
+ let nullVersion;
8
+ if (versionType === "number") {
9
+ nullVersion = 0;
10
+ }
11
+ else if (versionType === "string") {
12
+ nullVersion = "";
13
+ }
14
+ return nullVersion;
15
+ }
16
+ exports.getNullChannelVersion = getNullChannelVersion;
4
17
  function getNewChannelVersions(previousVersions, currentVersions) {
5
18
  // Get new channel versions
6
19
  if (Object.keys(previousVersions).length > 0) {
7
- const versionValues = Object.values(currentVersions);
8
- const versionType = versionValues.length > 0 ? typeof versionValues[0] : undefined;
9
- let nullVersion;
10
- if (versionType === "number") {
11
- nullVersion = 0;
12
- }
13
- else if (versionType === "string") {
14
- nullVersion = "";
15
- }
20
+ const nullVersion = getNullChannelVersion(currentVersions);
16
21
  return Object.fromEntries(Object.entries(currentVersions).filter(([k, v]) => v > (previousVersions[k] ?? nullVersion)));
17
22
  }
18
23
  else {
@@ -31,3 +36,13 @@ function _coerceToDict(value, defaultKey) {
31
36
  : { [defaultKey]: value };
32
37
  }
33
38
  exports._coerceToDict = _coerceToDict;
39
+ // Order matters
40
+ function _getIdMetadata(metadata) {
41
+ return {
42
+ langgraph_step: metadata.langgraph_step,
43
+ langgraph_node: metadata.langgraph_node,
44
+ langgraph_triggers: metadata.langgraph_triggers,
45
+ langgraph_task_idx: metadata.langgraph_task_idx,
46
+ };
47
+ }
48
+ exports._getIdMetadata = _getIdMetadata;
@@ -1,3 +1,10 @@
1
- import type { ChannelVersions } from "../checkpoint/base.js";
1
+ import type { ChannelVersions } from "@langchain/langgraph-checkpoint";
2
+ export declare function getNullChannelVersion(currentVersions: ChannelVersions): string | number | undefined;
2
3
  export declare function getNewChannelVersions(previousVersions: ChannelVersions, currentVersions: ChannelVersions): ChannelVersions;
3
4
  export declare function _coerceToDict(value: any, defaultKey: string): any;
5
+ export declare function _getIdMetadata(metadata: Record<string, unknown>): {
6
+ langgraph_step: unknown;
7
+ langgraph_node: unknown;
8
+ langgraph_triggers: unknown;
9
+ langgraph_task_idx: unknown;
10
+ };
@@ -1,15 +1,19 @@
1
+ export function getNullChannelVersion(currentVersions) {
2
+ const versionValues = Object.values(currentVersions);
3
+ const versionType = versionValues.length > 0 ? typeof versionValues[0] : undefined;
4
+ let nullVersion;
5
+ if (versionType === "number") {
6
+ nullVersion = 0;
7
+ }
8
+ else if (versionType === "string") {
9
+ nullVersion = "";
10
+ }
11
+ return nullVersion;
12
+ }
1
13
  export function getNewChannelVersions(previousVersions, currentVersions) {
2
14
  // Get new channel versions
3
15
  if (Object.keys(previousVersions).length > 0) {
4
- const versionValues = Object.values(currentVersions);
5
- const versionType = versionValues.length > 0 ? typeof versionValues[0] : undefined;
6
- let nullVersion;
7
- if (versionType === "number") {
8
- nullVersion = 0;
9
- }
10
- else if (versionType === "string") {
11
- nullVersion = "";
12
- }
16
+ const nullVersion = getNullChannelVersion(currentVersions);
13
17
  return Object.fromEntries(Object.entries(currentVersions).filter(([k, v]) => v > (previousVersions[k] ?? nullVersion)));
14
18
  }
15
19
  else {
@@ -26,3 +30,12 @@ export function _coerceToDict(value, defaultKey) {
26
30
  ? value
27
31
  : { [defaultKey]: value };
28
32
  }
33
+ // Order matters
34
+ export function _getIdMetadata(metadata) {
35
+ return {
36
+ langgraph_step: metadata.langgraph_step,
37
+ langgraph_node: metadata.langgraph_node,
38
+ langgraph_triggers: metadata.langgraph_triggers,
39
+ langgraph_task_idx: metadata.langgraph_task_idx,
40
+ };
41
+ }
package/dist/web.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Send = exports.EmptyChannelError = exports.InvalidUpdateError = exports.GraphValueError = exports.GraphRecursionError = exports.BaseCheckpointSaver = exports.emptyCheckpoint = exports.copyCheckpoint = exports.MemorySaver = exports.Annotation = exports.messagesStateReducer = exports.MessageGraph = exports.StateGraph = exports.START = exports.Graph = exports.END = void 0;
3
+ exports.BaseCheckpointSaver = exports.emptyCheckpoint = exports.copyCheckpoint = exports.MemorySaver = exports.Send = exports.EmptyChannelError = exports.InvalidUpdateError = exports.GraphValueError = exports.GraphRecursionError = exports.Annotation = exports.messagesStateReducer = exports.MessageGraph = exports.StateGraph = exports.START = exports.Graph = exports.END = void 0;
4
4
  var index_js_1 = require("./graph/index.cjs");
5
5
  Object.defineProperty(exports, "END", { enumerable: true, get: function () { return index_js_1.END; } });
6
6
  Object.defineProperty(exports, "Graph", { enumerable: true, get: function () { return index_js_1.Graph; } });
@@ -9,12 +9,6 @@ Object.defineProperty(exports, "StateGraph", { enumerable: true, get: function (
9
9
  Object.defineProperty(exports, "MessageGraph", { enumerable: true, get: function () { return index_js_1.MessageGraph; } });
10
10
  Object.defineProperty(exports, "messagesStateReducer", { enumerable: true, get: function () { return index_js_1.messagesStateReducer; } });
11
11
  Object.defineProperty(exports, "Annotation", { enumerable: true, get: function () { return index_js_1.Annotation; } });
12
- var memory_js_1 = require("./checkpoint/memory.cjs");
13
- Object.defineProperty(exports, "MemorySaver", { enumerable: true, get: function () { return memory_js_1.MemorySaver; } });
14
- var base_js_1 = require("./checkpoint/base.cjs");
15
- Object.defineProperty(exports, "copyCheckpoint", { enumerable: true, get: function () { return base_js_1.copyCheckpoint; } });
16
- Object.defineProperty(exports, "emptyCheckpoint", { enumerable: true, get: function () { return base_js_1.emptyCheckpoint; } });
17
- Object.defineProperty(exports, "BaseCheckpointSaver", { enumerable: true, get: function () { return base_js_1.BaseCheckpointSaver; } });
18
12
  var errors_js_1 = require("./errors.cjs");
19
13
  Object.defineProperty(exports, "GraphRecursionError", { enumerable: true, get: function () { return errors_js_1.GraphRecursionError; } });
20
14
  Object.defineProperty(exports, "GraphValueError", { enumerable: true, get: function () { return errors_js_1.GraphValueError; } });
@@ -22,3 +16,8 @@ Object.defineProperty(exports, "InvalidUpdateError", { enumerable: true, get: fu
22
16
  Object.defineProperty(exports, "EmptyChannelError", { enumerable: true, get: function () { return errors_js_1.EmptyChannelError; } });
23
17
  var constants_js_1 = require("./constants.cjs");
24
18
  Object.defineProperty(exports, "Send", { enumerable: true, get: function () { return constants_js_1.Send; } });
19
+ var langgraph_checkpoint_1 = require("@langchain/langgraph-checkpoint");
20
+ Object.defineProperty(exports, "MemorySaver", { enumerable: true, get: function () { return langgraph_checkpoint_1.MemorySaver; } });
21
+ Object.defineProperty(exports, "copyCheckpoint", { enumerable: true, get: function () { return langgraph_checkpoint_1.copyCheckpoint; } });
22
+ Object.defineProperty(exports, "emptyCheckpoint", { enumerable: true, get: function () { return langgraph_checkpoint_1.emptyCheckpoint; } });
23
+ Object.defineProperty(exports, "BaseCheckpointSaver", { enumerable: true, get: function () { return langgraph_checkpoint_1.BaseCheckpointSaver; } });
package/dist/web.d.ts CHANGED
@@ -1,7 +1,4 @@
1
1
  export { END, Graph, type StateGraphArgs, START, StateGraph, type CompiledStateGraph, MessageGraph, messagesStateReducer, Annotation, type StateType, type UpdateType, type CompiledGraph, } from "./graph/index.js";
2
- export { MemorySaver } from "./checkpoint/memory.js";
3
- export { type Checkpoint, type CheckpointTuple, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "./checkpoint/base.js";
4
- export { type CheckpointMetadata } from "./checkpoint/types.js";
5
2
  export { GraphRecursionError, GraphValueError, InvalidUpdateError, EmptyChannelError, } from "./errors.js";
6
- export { type SerializerProtocol } from "./serde/base.js";
7
3
  export { Send } from "./constants.js";
4
+ export { MemorySaver, type Checkpoint, type CheckpointMetadata, type CheckpointTuple, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "@langchain/langgraph-checkpoint";
package/dist/web.js CHANGED
@@ -1,5 +1,4 @@
1
1
  export { END, Graph, START, StateGraph, MessageGraph, messagesStateReducer, Annotation, } from "./graph/index.js";
2
- export { MemorySaver } from "./checkpoint/memory.js";
3
- export { copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "./checkpoint/base.js";
4
2
  export { GraphRecursionError, GraphValueError, InvalidUpdateError, EmptyChannelError, } from "./errors.js";
5
3
  export { Send } from "./constants.js";
4
+ export { MemorySaver, copyCheckpoint, emptyCheckpoint, BaseCheckpointSaver, } from "@langchain/langgraph-checkpoint";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph",
3
- "version": "0.1.0-rc.0",
3
+ "version": "0.1.0",
4
4
  "description": "LangGraph",
5
5
  "type": "module",
6
6
  "engines": {
@@ -31,26 +31,34 @@
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
33
  "@langchain/core": ">=0.2.20 <0.3.0",
34
+ "@langchain/langgraph-checkpoint": "0.0.0",
35
+ "@langchain/langgraph-checkpoint-sqlite": "0.0.0",
34
36
  "double-ended-queue": "^2.1.0-0",
35
37
  "uuid": "^10.0.0",
36
38
  "zod": "^3.23.8"
37
39
  },
40
+ "peerDependencies": {
41
+ "better-sqlite3": "^9.5.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "better-sqlite3": {
45
+ "optional": true
46
+ }
47
+ },
38
48
  "devDependencies": {
39
49
  "@jest/globals": "^29.5.0",
40
50
  "@langchain/anthropic": "^0.2.12",
41
51
  "@langchain/community": "^0.2.25",
42
52
  "@langchain/openai": "^0.2.4",
43
- "@langchain/scripts": "^0.0.21",
53
+ "@langchain/scripts": "^0.0.23",
44
54
  "@swc/core": "^1.3.90",
45
55
  "@swc/jest": "^0.2.29",
46
56
  "@tsconfig/recommended": "^1.0.3",
47
- "@types/better-sqlite3": "^7.6.9",
48
57
  "@types/double-ended-queue": "^2",
49
58
  "@types/uuid": "^10",
50
59
  "@typescript-eslint/eslint-plugin": "^6.12.0",
51
60
  "@typescript-eslint/parser": "^6.12.0",
52
61
  "@xenova/transformers": "^2.17.2",
53
- "better-sqlite3": "^9.5.0",
54
62
  "cheerio": "1.0.0-rc.12",
55
63
  "dotenv": "^16.3.1",
56
64
  "dpdm": "^3.12.0",
@@ -72,14 +80,6 @@
72
80
  "typescript": "^4.9.5 || ^5.4.5",
73
81
  "zod-to-json-schema": "^3.22.4"
74
82
  },
75
- "peerDependencies": {
76
- "better-sqlite3": "^9.5.0"
77
- },
78
- "peerDependenciesMeta": {
79
- "better-sqlite3": {
80
- "optional": true
81
- }
82
- },
83
83
  "publishConfig": {
84
84
  "access": "public",
85
85
  "registry": "https://registry.npmjs.org/"