@langchain/langgraph 0.2.15 → 0.2.17

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.
@@ -39,7 +39,9 @@ class LastValue extends base_js_1.BaseChannel {
39
39
  return false;
40
40
  }
41
41
  if (values.length !== 1) {
42
- throw new errors_js_1.InvalidUpdateError("LastValue can only receive one value per step.");
42
+ throw new errors_js_1.InvalidUpdateError("LastValue can only receive one value per step.", {
43
+ lc_error_code: "INVALID_CONCURRENT_GRAPH_UPDATE",
44
+ });
43
45
  }
44
46
  // eslint-disable-next-line prefer-destructuring
45
47
  this.value = values[values.length - 1];
@@ -36,7 +36,9 @@ export class LastValue extends BaseChannel {
36
36
  return false;
37
37
  }
38
38
  if (values.length !== 1) {
39
- throw new InvalidUpdateError("LastValue can only receive one value per step.");
39
+ throw new InvalidUpdateError("LastValue can only receive one value per step.", {
40
+ lc_error_code: "INVALID_CONCURRENT_GRAPH_UPDATE",
41
+ });
40
42
  }
41
43
  // eslint-disable-next-line prefer-destructuring
42
44
  this.value = values[values.length - 1];
package/dist/errors.cjs CHANGED
@@ -1,9 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSubgraphsSeenSet = exports.MultipleSubgraphsError = exports.InvalidUpdateError = exports.EmptyChannelError = exports.EmptyInputError = exports.isGraphInterrupt = exports.NodeInterrupt = exports.GraphInterrupt = exports.GraphValueError = exports.GraphRecursionError = void 0;
4
- class GraphRecursionError extends Error {
5
- constructor(message) {
6
- super(message);
3
+ exports.getSubgraphsSeenSet = exports.MultipleSubgraphsError = exports.InvalidUpdateError = exports.EmptyChannelError = exports.EmptyInputError = exports.isGraphInterrupt = exports.NodeInterrupt = exports.GraphInterrupt = exports.GraphValueError = exports.GraphRecursionError = exports.BaseLangGraphError = void 0;
4
+ // TODO: Merge with base LangChain error class when we drop support for core@0.2.0
5
+ class BaseLangGraphError extends Error {
6
+ constructor(message, fields) {
7
+ let finalMessage = message ?? "";
8
+ if (fields?.lc_error_code) {
9
+ finalMessage = `${finalMessage}\n\nTroubleshooting URL: https://js.langchain.com/docs/troubleshooting/errors/${fields.lc_error_code}/\n`;
10
+ }
11
+ super(finalMessage);
12
+ Object.defineProperty(this, "lc_error_code", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ this.lc_error_code = fields?.lc_error_code;
19
+ }
20
+ }
21
+ exports.BaseLangGraphError = BaseLangGraphError;
22
+ class GraphRecursionError extends BaseLangGraphError {
23
+ constructor(message, fields) {
24
+ super(message, fields);
7
25
  this.name = "GraphRecursionError";
8
26
  }
9
27
  static get unminifiable_name() {
@@ -11,9 +29,9 @@ class GraphRecursionError extends Error {
11
29
  }
12
30
  }
13
31
  exports.GraphRecursionError = GraphRecursionError;
14
- class GraphValueError extends Error {
15
- constructor(message) {
16
- super(message);
32
+ class GraphValueError extends BaseLangGraphError {
33
+ constructor(message, fields) {
34
+ super(message, fields);
17
35
  this.name = "GraphValueError";
18
36
  }
19
37
  static get unminifiable_name() {
@@ -21,9 +39,9 @@ class GraphValueError extends Error {
21
39
  }
22
40
  }
23
41
  exports.GraphValueError = GraphValueError;
24
- class GraphInterrupt extends Error {
25
- constructor(interrupts = []) {
26
- super(JSON.stringify(interrupts, null, 2));
42
+ class GraphInterrupt extends BaseLangGraphError {
43
+ constructor(interrupts, fields) {
44
+ super(JSON.stringify(interrupts, null, 2), fields);
27
45
  Object.defineProperty(this, "interrupts", {
28
46
  enumerable: true,
29
47
  configurable: true,
@@ -31,7 +49,7 @@ class GraphInterrupt extends Error {
31
49
  value: void 0
32
50
  });
33
51
  this.name = "GraphInterrupt";
34
- this.interrupts = interrupts;
52
+ this.interrupts = interrupts ?? [];
35
53
  }
36
54
  static get unminifiable_name() {
37
55
  return "GraphInterrupt";
@@ -40,13 +58,13 @@ class GraphInterrupt extends Error {
40
58
  exports.GraphInterrupt = GraphInterrupt;
41
59
  /** Raised by a node to interrupt execution. */
42
60
  class NodeInterrupt extends GraphInterrupt {
43
- constructor(message) {
61
+ constructor(message, fields) {
44
62
  super([
45
63
  {
46
64
  value: message,
47
65
  when: "during",
48
66
  },
49
- ]);
67
+ ], fields);
50
68
  this.name = "NodeInterrupt";
51
69
  }
52
70
  static get unminifiable_name() {
@@ -62,9 +80,9 @@ function isGraphInterrupt(e) {
62
80
  ].includes(e.name));
63
81
  }
64
82
  exports.isGraphInterrupt = isGraphInterrupt;
65
- class EmptyInputError extends Error {
66
- constructor(message) {
67
- super(message);
83
+ class EmptyInputError extends BaseLangGraphError {
84
+ constructor(message, fields) {
85
+ super(message, fields);
68
86
  this.name = "EmptyInputError";
69
87
  }
70
88
  static get unminifiable_name() {
@@ -72,9 +90,9 @@ class EmptyInputError extends Error {
72
90
  }
73
91
  }
74
92
  exports.EmptyInputError = EmptyInputError;
75
- class EmptyChannelError extends Error {
76
- constructor(message) {
77
- super(message);
93
+ class EmptyChannelError extends BaseLangGraphError {
94
+ constructor(message, fields) {
95
+ super(message, fields);
78
96
  this.name = "EmptyChannelError";
79
97
  }
80
98
  static get unminifiable_name() {
@@ -82,9 +100,9 @@ class EmptyChannelError extends Error {
82
100
  }
83
101
  }
84
102
  exports.EmptyChannelError = EmptyChannelError;
85
- class InvalidUpdateError extends Error {
86
- constructor(message) {
87
- super(message);
103
+ class InvalidUpdateError extends BaseLangGraphError {
104
+ constructor(message, fields) {
105
+ super(message, fields);
88
106
  this.name = "InvalidUpdateError";
89
107
  }
90
108
  static get unminifiable_name() {
@@ -92,9 +110,9 @@ class InvalidUpdateError extends Error {
92
110
  }
93
111
  }
94
112
  exports.InvalidUpdateError = InvalidUpdateError;
95
- class MultipleSubgraphsError extends Error {
96
- constructor(message) {
97
- super(message);
113
+ class MultipleSubgraphsError extends BaseLangGraphError {
114
+ constructor(message, fields) {
115
+ super(message, fields);
98
116
  this.name = "MultipleSubgraphError";
99
117
  }
100
118
  static get unminifiable_name() {
package/dist/errors.d.ts CHANGED
@@ -1,37 +1,44 @@
1
1
  import { Interrupt } from "./constants.js";
2
- export declare class GraphRecursionError extends Error {
3
- constructor(message?: string);
2
+ export type BaseLangGraphErrorFields = {
3
+ lc_error_code?: string;
4
+ };
5
+ export declare class BaseLangGraphError extends Error {
6
+ lc_error_code?: string;
7
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
8
+ }
9
+ export declare class GraphRecursionError extends BaseLangGraphError {
10
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
4
11
  static get unminifiable_name(): string;
5
12
  }
6
- export declare class GraphValueError extends Error {
7
- constructor(message?: string);
13
+ export declare class GraphValueError extends BaseLangGraphError {
14
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
8
15
  static get unminifiable_name(): string;
9
16
  }
10
- export declare class GraphInterrupt extends Error {
17
+ export declare class GraphInterrupt extends BaseLangGraphError {
11
18
  interrupts: Interrupt[];
12
- constructor(interrupts?: Interrupt[]);
19
+ constructor(interrupts?: Interrupt[], fields?: BaseLangGraphErrorFields);
13
20
  static get unminifiable_name(): string;
14
21
  }
15
22
  /** Raised by a node to interrupt execution. */
16
23
  export declare class NodeInterrupt extends GraphInterrupt {
17
- constructor(message: string);
24
+ constructor(message: string, fields?: BaseLangGraphErrorFields);
18
25
  static get unminifiable_name(): string;
19
26
  }
20
27
  export declare function isGraphInterrupt(e?: GraphInterrupt | Error): e is GraphInterrupt;
21
- export declare class EmptyInputError extends Error {
22
- constructor(message?: string);
28
+ export declare class EmptyInputError extends BaseLangGraphError {
29
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
23
30
  static get unminifiable_name(): string;
24
31
  }
25
- export declare class EmptyChannelError extends Error {
26
- constructor(message?: string);
32
+ export declare class EmptyChannelError extends BaseLangGraphError {
33
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
27
34
  static get unminifiable_name(): string;
28
35
  }
29
- export declare class InvalidUpdateError extends Error {
30
- constructor(message?: string);
36
+ export declare class InvalidUpdateError extends BaseLangGraphError {
37
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
31
38
  static get unminifiable_name(): string;
32
39
  }
33
- export declare class MultipleSubgraphsError extends Error {
34
- constructor(message?: string);
40
+ export declare class MultipleSubgraphsError extends BaseLangGraphError {
41
+ constructor(message?: string, fields?: BaseLangGraphErrorFields);
35
42
  static get unminifiable_name(): string;
36
43
  }
37
44
  /**
package/dist/errors.js CHANGED
@@ -1,24 +1,41 @@
1
- export class GraphRecursionError extends Error {
2
- constructor(message) {
3
- super(message);
1
+ // TODO: Merge with base LangChain error class when we drop support for core@0.2.0
2
+ export class BaseLangGraphError extends Error {
3
+ constructor(message, fields) {
4
+ let finalMessage = message ?? "";
5
+ if (fields?.lc_error_code) {
6
+ finalMessage = `${finalMessage}\n\nTroubleshooting URL: https://js.langchain.com/docs/troubleshooting/errors/${fields.lc_error_code}/\n`;
7
+ }
8
+ super(finalMessage);
9
+ Object.defineProperty(this, "lc_error_code", {
10
+ enumerable: true,
11
+ configurable: true,
12
+ writable: true,
13
+ value: void 0
14
+ });
15
+ this.lc_error_code = fields?.lc_error_code;
16
+ }
17
+ }
18
+ export class GraphRecursionError extends BaseLangGraphError {
19
+ constructor(message, fields) {
20
+ super(message, fields);
4
21
  this.name = "GraphRecursionError";
5
22
  }
6
23
  static get unminifiable_name() {
7
24
  return "GraphRecursionError";
8
25
  }
9
26
  }
10
- export class GraphValueError extends Error {
11
- constructor(message) {
12
- super(message);
27
+ export class GraphValueError extends BaseLangGraphError {
28
+ constructor(message, fields) {
29
+ super(message, fields);
13
30
  this.name = "GraphValueError";
14
31
  }
15
32
  static get unminifiable_name() {
16
33
  return "GraphValueError";
17
34
  }
18
35
  }
19
- export class GraphInterrupt extends Error {
20
- constructor(interrupts = []) {
21
- super(JSON.stringify(interrupts, null, 2));
36
+ export class GraphInterrupt extends BaseLangGraphError {
37
+ constructor(interrupts, fields) {
38
+ super(JSON.stringify(interrupts, null, 2), fields);
22
39
  Object.defineProperty(this, "interrupts", {
23
40
  enumerable: true,
24
41
  configurable: true,
@@ -26,7 +43,7 @@ export class GraphInterrupt extends Error {
26
43
  value: void 0
27
44
  });
28
45
  this.name = "GraphInterrupt";
29
- this.interrupts = interrupts;
46
+ this.interrupts = interrupts ?? [];
30
47
  }
31
48
  static get unminifiable_name() {
32
49
  return "GraphInterrupt";
@@ -34,13 +51,13 @@ export class GraphInterrupt extends Error {
34
51
  }
35
52
  /** Raised by a node to interrupt execution. */
36
53
  export class NodeInterrupt extends GraphInterrupt {
37
- constructor(message) {
54
+ constructor(message, fields) {
38
55
  super([
39
56
  {
40
57
  value: message,
41
58
  when: "during",
42
59
  },
43
- ]);
60
+ ], fields);
44
61
  this.name = "NodeInterrupt";
45
62
  }
46
63
  static get unminifiable_name() {
@@ -54,36 +71,36 @@ export function isGraphInterrupt(e) {
54
71
  NodeInterrupt.unminifiable_name,
55
72
  ].includes(e.name));
56
73
  }
57
- export class EmptyInputError extends Error {
58
- constructor(message) {
59
- super(message);
74
+ export class EmptyInputError extends BaseLangGraphError {
75
+ constructor(message, fields) {
76
+ super(message, fields);
60
77
  this.name = "EmptyInputError";
61
78
  }
62
79
  static get unminifiable_name() {
63
80
  return "EmptyInputError";
64
81
  }
65
82
  }
66
- export class EmptyChannelError extends Error {
67
- constructor(message) {
68
- super(message);
83
+ export class EmptyChannelError extends BaseLangGraphError {
84
+ constructor(message, fields) {
85
+ super(message, fields);
69
86
  this.name = "EmptyChannelError";
70
87
  }
71
88
  static get unminifiable_name() {
72
89
  return "EmptyChannelError";
73
90
  }
74
91
  }
75
- export class InvalidUpdateError extends Error {
76
- constructor(message) {
77
- super(message);
92
+ export class InvalidUpdateError extends BaseLangGraphError {
93
+ constructor(message, fields) {
94
+ super(message, fields);
78
95
  this.name = "InvalidUpdateError";
79
96
  }
80
97
  static get unminifiable_name() {
81
98
  return "InvalidUpdateError";
82
99
  }
83
100
  }
84
- export class MultipleSubgraphsError extends Error {
85
- constructor(message) {
86
- super(message);
101
+ export class MultipleSubgraphsError extends BaseLangGraphError {
102
+ constructor(message, fields) {
103
+ super(message, fields);
87
104
  this.name = "MultipleSubgraphError";
88
105
  }
89
106
  static get unminifiable_name() {
@@ -13,6 +13,7 @@ const write_js_1 = require("../pregel/write.cjs");
13
13
  const constants_js_1 = require("../constants.cjs");
14
14
  const utils_js_1 = require("../utils.cjs");
15
15
  const errors_js_1 = require("../errors.cjs");
16
+ const subgraph_js_1 = require("../pregel/utils/subgraph.cjs");
16
17
  /** Special reserved node name denoting the start of a graph. */
17
18
  exports.START = "__start__";
18
19
  /** Special reserved node name denoting the end of a graph. */
@@ -140,11 +141,13 @@ class Graph {
140
141
  if (key === exports.END) {
141
142
  throw new Error(`Node \`${key}\` is reserved.`);
142
143
  }
144
+ const runnable = (0, runnables_1._coerceToRunnable)(
145
+ // Account for arbitrary state due to Send API
146
+ action);
143
147
  this.nodes[key] = {
144
- runnable: (0, runnables_1._coerceToRunnable)(
145
- // Account for arbitrary state due to Send API
146
- action),
148
+ runnable,
147
149
  metadata: options?.metadata,
150
+ subgraphs: (0, subgraph_js_1.isPregelLike)(runnable) ? [runnable] : options?.subgraphs,
148
151
  };
149
152
  return this;
150
153
  }
@@ -300,6 +303,7 @@ class CompiledGraph extends index_js_1.Pregel {
300
303
  channels: [],
301
304
  triggers: [],
302
305
  metadata: node.metadata,
306
+ subgraphs: node.subgraphs,
303
307
  })
304
308
  .pipe(node.runnable)
305
309
  .pipe(new write_js_1.ChannelWrite([{ channel: key, value: write_js_1.PASSTHROUGH }], [constants_js_1.TAG_HIDDEN]));
@@ -28,9 +28,11 @@ export declare class Branch<IO, N extends string, CallOptions extends LangGraphR
28
28
  export type NodeSpec<RunInput, RunOutput> = {
29
29
  runnable: Runnable<RunInput, RunOutput>;
30
30
  metadata?: Record<string, unknown>;
31
+ subgraphs?: Pregel<any, any>[];
31
32
  };
32
33
  export type AddNodeOptions = {
33
34
  metadata?: Record<string, unknown>;
35
+ subgraphs?: Pregel<any, any>[];
34
36
  };
35
37
  export declare class Graph<N extends string = typeof END, RunInput = any, RunOutput = any, NodeSpecType extends NodeSpec<RunInput, RunOutput> = NodeSpec<RunInput, RunOutput>, C extends StateDefinition = StateDefinition> {
36
38
  nodes: Record<N, NodeSpecType>;
@@ -10,6 +10,7 @@ import { ChannelWrite, PASSTHROUGH } from "../pregel/write.js";
10
10
  import { _isSend, CHECKPOINT_NAMESPACE_END, CHECKPOINT_NAMESPACE_SEPARATOR, TAG_HIDDEN, } from "../constants.js";
11
11
  import { gatherIteratorSync, RunnableCallable } from "../utils.js";
12
12
  import { InvalidUpdateError, NodeInterrupt } from "../errors.js";
13
+ import { isPregelLike } from "../pregel/utils/subgraph.js";
13
14
  /** Special reserved node name denoting the start of a graph. */
14
15
  export const START = "__start__";
15
16
  /** Special reserved node name denoting the end of a graph. */
@@ -136,11 +137,13 @@ export class Graph {
136
137
  if (key === END) {
137
138
  throw new Error(`Node \`${key}\` is reserved.`);
138
139
  }
140
+ const runnable = _coerceToRunnable(
141
+ // Account for arbitrary state due to Send API
142
+ action);
139
143
  this.nodes[key] = {
140
- runnable: _coerceToRunnable(
141
- // Account for arbitrary state due to Send API
142
- action),
144
+ runnable,
143
145
  metadata: options?.metadata,
146
+ subgraphs: isPregelLike(runnable) ? [runnable] : options?.subgraphs,
144
147
  };
145
148
  return this;
146
149
  }
@@ -295,6 +298,7 @@ export class CompiledGraph extends Pregel {
295
298
  channels: [],
296
299
  triggers: [],
297
300
  metadata: node.metadata,
301
+ subgraphs: node.subgraphs,
298
302
  })
299
303
  .pipe(node.runnable)
300
304
  .pipe(new ChannelWrite([{ channel: key, value: PASSTHROUGH }], [TAG_HIDDEN]));
@@ -14,6 +14,7 @@ const constants_js_1 = require("../constants.cjs");
14
14
  const errors_js_1 = require("../errors.cjs");
15
15
  const annotation_js_1 = require("./annotation.cjs");
16
16
  const base_js_2 = require("../managed/base.cjs");
17
+ const subgraph_js_1 = require("../pregel/utils/subgraph.cjs");
17
18
  const ROOT = "__root__";
18
19
  /**
19
20
  * A graph whose nodes communicate by reading and writing to a shared state.
@@ -216,11 +217,16 @@ class StateGraph extends graph_js_1.Graph {
216
217
  if (options?.input !== undefined) {
217
218
  this._addSchema(options.input.spec);
218
219
  }
220
+ const runnable = (0, runnables_1._coerceToRunnable)(action);
219
221
  const nodeSpec = {
220
- runnable: (0, runnables_1._coerceToRunnable)(action),
222
+ runnable,
221
223
  retryPolicy: options?.retryPolicy,
222
224
  metadata: options?.metadata,
223
225
  input: options?.input?.spec ?? this._schemaDefinition,
226
+ subgraphs: (0, subgraph_js_1.isPregelLike)(runnable)
227
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
228
+ [runnable]
229
+ : options?.subgraphs,
224
230
  };
225
231
  this.nodes[key] = nodeSpec;
226
232
  return this;
@@ -238,14 +244,14 @@ class StateGraph extends graph_js_1.Graph {
238
244
  throw new Error("END cannot be a start node");
239
245
  }
240
246
  if (!Object.keys(this.nodes).some((node) => node === start)) {
241
- throw new Error(`Need to addNode ${start} first`);
247
+ throw new Error(`Need to add a node named "${start}" first`);
242
248
  }
243
249
  }
244
250
  if (endKey === graph_js_1.END) {
245
251
  throw new Error("END cannot be an end node");
246
252
  }
247
253
  if (!Object.keys(this.nodes).some((node) => node === endKey)) {
248
- throw new Error(`Need to addNode ${endKey} first`);
254
+ throw new Error(`Need to add a node named "${endKey}" first`);
249
255
  }
250
256
  this.waitingEdges.add([startKey, endKey]);
251
257
  return this;
@@ -326,7 +332,9 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
326
332
  }
327
333
  else if (typeof input !== "object" || Array.isArray(input)) {
328
334
  const typeofInput = Array.isArray(input) ? "array" : typeof input;
329
- throw new errors_js_1.InvalidUpdateError(`Expected object, got ${typeofInput}`);
335
+ throw new errors_js_1.InvalidUpdateError(`Expected node "${key.toString()}" to return an object, received ${typeofInput}`, {
336
+ lc_error_code: "INVALID_GRAPH_NODE_RETURN_VALUE",
337
+ });
330
338
  }
331
339
  else {
332
340
  return key in input ? input[key] : write_js_1.SKIP_WRITE;
@@ -375,6 +383,7 @@ class CompiledStateGraph extends graph_js_1.CompiledGraph {
375
383
  bound: node?.runnable,
376
384
  metadata: node?.metadata,
377
385
  retryPolicy: node?.retryPolicy,
386
+ subgraphs: node?.subgraphs,
378
387
  });
379
388
  }
380
389
  }
@@ -11,6 +11,7 @@ import { _isSend, CHECKPOINT_NAMESPACE_END, CHECKPOINT_NAMESPACE_SEPARATOR, TAG_
11
11
  import { InvalidUpdateError } from "../errors.js";
12
12
  import { getChannel, } from "./annotation.js";
13
13
  import { isConfiguredManagedValue } from "../managed/base.js";
14
+ import { isPregelLike } from "../pregel/utils/subgraph.js";
14
15
  const ROOT = "__root__";
15
16
  /**
16
17
  * A graph whose nodes communicate by reading and writing to a shared state.
@@ -213,11 +214,16 @@ export class StateGraph extends Graph {
213
214
  if (options?.input !== undefined) {
214
215
  this._addSchema(options.input.spec);
215
216
  }
217
+ const runnable = _coerceToRunnable(action);
216
218
  const nodeSpec = {
217
- runnable: _coerceToRunnable(action),
219
+ runnable,
218
220
  retryPolicy: options?.retryPolicy,
219
221
  metadata: options?.metadata,
220
222
  input: options?.input?.spec ?? this._schemaDefinition,
223
+ subgraphs: isPregelLike(runnable)
224
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
225
+ [runnable]
226
+ : options?.subgraphs,
221
227
  };
222
228
  this.nodes[key] = nodeSpec;
223
229
  return this;
@@ -235,14 +241,14 @@ export class StateGraph extends Graph {
235
241
  throw new Error("END cannot be a start node");
236
242
  }
237
243
  if (!Object.keys(this.nodes).some((node) => node === start)) {
238
- throw new Error(`Need to addNode ${start} first`);
244
+ throw new Error(`Need to add a node named "${start}" first`);
239
245
  }
240
246
  }
241
247
  if (endKey === END) {
242
248
  throw new Error("END cannot be an end node");
243
249
  }
244
250
  if (!Object.keys(this.nodes).some((node) => node === endKey)) {
245
- throw new Error(`Need to addNode ${endKey} first`);
251
+ throw new Error(`Need to add a node named "${endKey}" first`);
246
252
  }
247
253
  this.waitingEdges.add([startKey, endKey]);
248
254
  return this;
@@ -322,7 +328,9 @@ export class CompiledStateGraph extends CompiledGraph {
322
328
  }
323
329
  else if (typeof input !== "object" || Array.isArray(input)) {
324
330
  const typeofInput = Array.isArray(input) ? "array" : typeof input;
325
- throw new InvalidUpdateError(`Expected object, got ${typeofInput}`);
331
+ throw new InvalidUpdateError(`Expected node "${key.toString()}" to return an object, received ${typeofInput}`, {
332
+ lc_error_code: "INVALID_GRAPH_NODE_RETURN_VALUE",
333
+ });
326
334
  }
327
335
  else {
328
336
  return key in input ? input[key] : SKIP_WRITE;
@@ -371,6 +379,7 @@ export class CompiledStateGraph extends CompiledGraph {
371
379
  bound: node?.runnable,
372
380
  metadata: node?.metadata,
373
381
  retryPolicy: node?.retryPolicy,
382
+ subgraphs: node?.subgraphs,
374
383
  });
375
384
  }
376
385
  }
@@ -2,4 +2,4 @@ export { type AgentExecutorState, createAgentExecutor, } from "./agent_executor.
2
2
  export { type FunctionCallingExecutorState, createFunctionCallingExecutor, } from "./chat_agent_executor.js";
3
3
  export { type AgentState, createReactAgent } from "./react_agent_executor.js";
4
4
  export { type ToolExecutorArgs, type ToolInvocationInterface, ToolExecutor, } from "./tool_executor.js";
5
- export { ToolNode, toolsCondition } from "./tool_node.js";
5
+ export { ToolNode, toolsCondition, type ToolNodeOptions } from "./tool_node.js";
@@ -1,5 +1,5 @@
1
1
  import { BaseMessage } from "@langchain/core/messages";
2
- import { RunnableToolLike } from "@langchain/core/runnables";
2
+ import { RunnableConfig, RunnableToolLike } from "@langchain/core/runnables";
3
3
  import { StructuredToolInterface } from "@langchain/core/tools";
4
4
  import { RunnableCallable } from "../utils.js";
5
5
  import { END } from "../graph/graph.js";
@@ -130,6 +130,6 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
130
130
  tools: (StructuredToolInterface | RunnableToolLike)[];
131
131
  handleToolErrors: boolean;
132
132
  constructor(tools: (StructuredToolInterface | RunnableToolLike)[], options?: ToolNodeOptions);
133
- private run;
133
+ protected run(input: any, config: RunnableConfig): Promise<T>;
134
134
  }
135
135
  export declare function toolsCondition(state: BaseMessage[] | typeof MessagesAnnotation.State): "tools" | typeof END;
@@ -84,7 +84,7 @@ writes) {
84
84
  throw new errors_js_1.InvalidUpdateError(`Invalid packet type, expected SendProtocol, got ${JSON.stringify(value)}`);
85
85
  }
86
86
  if (!(value.node in processes)) {
87
- throw new errors_js_1.InvalidUpdateError(`Invalid node name ${value.node} in packet`);
87
+ throw new errors_js_1.InvalidUpdateError(`Invalid node name "${value.node}" in Send packet`);
88
88
  }
89
89
  // replace any runtime values with placeholders
90
90
  managed.replaceRuntimeValues(step, value.args);
@@ -178,7 +178,9 @@ getNextVersion) {
178
178
  }
179
179
  catch (e) {
180
180
  if (e.name === errors_js_1.InvalidUpdateError.unminifiable_name) {
181
- throw new errors_js_1.InvalidUpdateError(`Invalid update for channel ${chan} with values ${JSON.stringify(vals)}: ${e.message}`);
181
+ const wrappedError = new errors_js_1.InvalidUpdateError(`Invalid update for channel "${chan}" with values ${JSON.stringify(vals)}: ${e.message}`);
182
+ wrappedError.lc_error_code = e.lc_error_code;
183
+ throw wrappedError;
182
184
  }
183
185
  else {
184
186
  throw e;
@@ -273,6 +275,7 @@ function _prepareSingleTask(taskPath, checkpoint, processes, channels, managed,
273
275
  name: packet.node,
274
276
  input: packet.args,
275
277
  proc: node,
278
+ subgraphs: proc.subgraphs,
276
279
  writes,
277
280
  config: (0, runnables_1.patchConfig)((0, runnables_1.mergeConfigs)(config, {
278
281
  metadata,
@@ -369,6 +372,7 @@ function _prepareSingleTask(taskPath, checkpoint, processes, channels, managed,
369
372
  name,
370
373
  input: val,
371
374
  proc: node,
375
+ subgraphs: proc.subgraphs,
372
376
  writes,
373
377
  config: (0, runnables_1.patchConfig)((0, runnables_1.mergeConfigs)(config, {
374
378
  metadata,
@@ -78,7 +78,7 @@ writes) {
78
78
  throw new InvalidUpdateError(`Invalid packet type, expected SendProtocol, got ${JSON.stringify(value)}`);
79
79
  }
80
80
  if (!(value.node in processes)) {
81
- throw new InvalidUpdateError(`Invalid node name ${value.node} in packet`);
81
+ throw new InvalidUpdateError(`Invalid node name "${value.node}" in Send packet`);
82
82
  }
83
83
  // replace any runtime values with placeholders
84
84
  managed.replaceRuntimeValues(step, value.args);
@@ -171,7 +171,9 @@ getNextVersion) {
171
171
  }
172
172
  catch (e) {
173
173
  if (e.name === InvalidUpdateError.unminifiable_name) {
174
- throw new InvalidUpdateError(`Invalid update for channel ${chan} with values ${JSON.stringify(vals)}: ${e.message}`);
174
+ const wrappedError = new InvalidUpdateError(`Invalid update for channel "${chan}" with values ${JSON.stringify(vals)}: ${e.message}`);
175
+ wrappedError.lc_error_code = e.lc_error_code;
176
+ throw wrappedError;
175
177
  }
176
178
  else {
177
179
  throw e;
@@ -264,6 +266,7 @@ export function _prepareSingleTask(taskPath, checkpoint, processes, channels, ma
264
266
  name: packet.node,
265
267
  input: packet.args,
266
268
  proc: node,
269
+ subgraphs: proc.subgraphs,
267
270
  writes,
268
271
  config: patchConfig(mergeConfigs(config, {
269
272
  metadata,
@@ -360,6 +363,7 @@ export function _prepareSingleTask(taskPath, checkpoint, processes, channels, ma
360
363
  name,
361
364
  input: val,
362
365
  proc: node,
366
+ subgraphs: proc.subgraphs,
363
367
  writes,
364
368
  config: patchConfig(mergeConfigs(config, {
365
369
  metadata,
@@ -127,7 +127,8 @@ function* mapDebugCheckpoint(step, config, channels, streamChannels, metadata, t
127
127
  const parentNs = config.configurable?.checkpoint_ns;
128
128
  const taskStates = {};
129
129
  for (const task of tasks) {
130
- if (!(0, subgraph_js_1.findSubgraphPregel)(task.proc))
130
+ const candidates = task.subgraphs?.length ? task.subgraphs : [task.proc];
131
+ if (!candidates.find(subgraph_js_1.findSubgraphPregel))
131
132
  continue;
132
133
  let taskNs = `${task.name}:${task.id}`;
133
134
  if (parentNs)
@@ -121,7 +121,8 @@ export function* mapDebugCheckpoint(step, config, channels, streamChannels, meta
121
121
  const parentNs = config.configurable?.checkpoint_ns;
122
122
  const taskStates = {};
123
123
  for (const task of tasks) {
124
- if (!findSubgraphPregel(task.proc))
124
+ const candidates = task.subgraphs?.length ? task.subgraphs : [task.proc];
125
+ if (!candidates.find(findSubgraphPregel))
125
126
  continue;
126
127
  let taskNs = `${task.name}:${task.id}`;
127
128
  if (parentNs)
@@ -255,26 +255,28 @@ class Pregel extends runnables_1.Runnable {
255
255
  continue;
256
256
  }
257
257
  }
258
- const graph = (0, subgraph_js_1.findSubgraphPregel)(node.bound);
259
- // if found, yield recursively
260
- if (graph !== undefined) {
261
- if (name === namespace) {
262
- yield [name, graph];
263
- return;
264
- }
265
- if (namespace === undefined) {
266
- yield [name, graph];
267
- }
268
- if (recurse) {
269
- let newNamespace = namespace;
270
- if (namespace !== undefined) {
271
- newNamespace = namespace.slice(name.length + 1);
258
+ const candidates = node.subgraphs?.length ? node.subgraphs : [node.bound];
259
+ for (const candidate of candidates) {
260
+ const graph = (0, subgraph_js_1.findSubgraphPregel)(candidate);
261
+ if (graph !== undefined) {
262
+ if (name === namespace) {
263
+ yield [name, graph];
264
+ return;
272
265
  }
273
- for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) {
274
- yield [
275
- `${name}${constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`,
276
- subgraph,
277
- ];
266
+ if (namespace === undefined) {
267
+ yield [name, graph];
268
+ }
269
+ if (recurse) {
270
+ let newNamespace = namespace;
271
+ if (namespace !== undefined) {
272
+ newNamespace = namespace.slice(name.length + 1);
273
+ }
274
+ for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) {
275
+ yield [
276
+ `${name}${constants_js_1.CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`,
277
+ subgraph,
278
+ ];
279
+ }
278
280
  }
279
281
  }
280
282
  }
@@ -794,7 +796,9 @@ class Pregel extends runnables_1.Runnable {
794
796
  `Recursion limit of ${config.recursionLimit} reached`,
795
797
  "without hitting a stop condition. You can increase the",
796
798
  `limit by setting the "recursionLimit" config key.`,
797
- ].join(" "));
799
+ ].join(" "), {
800
+ lc_error_code: "GRAPH_RECURSION_LIMIT",
801
+ });
798
802
  }
799
803
  await Promise.all(loop?.checkpointerPromises ?? []);
800
804
  await runManager?.handleChainEnd(loop.output);
@@ -248,26 +248,28 @@ export class Pregel extends Runnable {
248
248
  continue;
249
249
  }
250
250
  }
251
- const graph = findSubgraphPregel(node.bound);
252
- // if found, yield recursively
253
- if (graph !== undefined) {
254
- if (name === namespace) {
255
- yield [name, graph];
256
- return;
257
- }
258
- if (namespace === undefined) {
259
- yield [name, graph];
260
- }
261
- if (recurse) {
262
- let newNamespace = namespace;
263
- if (namespace !== undefined) {
264
- newNamespace = namespace.slice(name.length + 1);
251
+ const candidates = node.subgraphs?.length ? node.subgraphs : [node.bound];
252
+ for (const candidate of candidates) {
253
+ const graph = findSubgraphPregel(candidate);
254
+ if (graph !== undefined) {
255
+ if (name === namespace) {
256
+ yield [name, graph];
257
+ return;
265
258
  }
266
- for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) {
267
- yield [
268
- `${name}${CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`,
269
- subgraph,
270
- ];
259
+ if (namespace === undefined) {
260
+ yield [name, graph];
261
+ }
262
+ if (recurse) {
263
+ let newNamespace = namespace;
264
+ if (namespace !== undefined) {
265
+ newNamespace = namespace.slice(name.length + 1);
266
+ }
267
+ for (const [subgraphName, subgraph] of graph.getSubgraphs(newNamespace, recurse)) {
268
+ yield [
269
+ `${name}${CHECKPOINT_NAMESPACE_SEPARATOR}${subgraphName}`,
270
+ subgraph,
271
+ ];
272
+ }
271
273
  }
272
274
  }
273
275
  }
@@ -787,7 +789,9 @@ export class Pregel extends Runnable {
787
789
  `Recursion limit of ${config.recursionLimit} reached`,
788
790
  "without hitting a stop condition. You can increase the",
789
791
  `limit by setting the "recursionLimit" config key.`,
790
- ].join(" "));
792
+ ].join(" "), {
793
+ lc_error_code: "GRAPH_RECURSION_LIMIT",
794
+ });
791
795
  }
792
796
  await Promise.all(loop?.checkpointerPromises ?? []);
793
797
  await runManager?.handleChainEnd(loop.output);
@@ -313,7 +313,9 @@ class PregelLoop {
313
313
  "This is not allowed if checkpointing is enabled.",
314
314
  "",
315
315
  `You can disable checkpointing for a subgraph by compiling it with ".compile({ checkpointer: false });"`,
316
- ].join("\n"));
316
+ ].join("\n"), {
317
+ lc_error_code: "MULTIPLE_SUBGRAPHS",
318
+ });
317
319
  }
318
320
  else {
319
321
  (0, errors_js_1.getSubgraphsSeenSet)().add(config.configurable?.checkpoint_ns);
@@ -309,7 +309,9 @@ export class PregelLoop {
309
309
  "This is not allowed if checkpointing is enabled.",
310
310
  "",
311
311
  `You can disable checkpointing for a subgraph by compiling it with ".compile({ checkpointer: false });"`,
312
- ].join("\n"));
312
+ ].join("\n"), {
313
+ lc_error_code: "MULTIPLE_SUBGRAPHS",
314
+ });
313
315
  }
314
316
  else {
315
317
  getSubgraphsSeenSet().add(config.configurable?.checkpoint_ns);
@@ -63,7 +63,7 @@ const defaultRunnableBound =
63
63
  /* #__PURE__ */ new runnables_1.RunnablePassthrough();
64
64
  class PregelNode extends runnables_1.RunnableBinding {
65
65
  constructor(fields) {
66
- const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, } = fields;
66
+ const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, subgraphs, } = fields;
67
67
  const mergedTags = [
68
68
  ...(fields.config?.tags ? fields.config.tags : []),
69
69
  ...(tags ?? []),
@@ -139,6 +139,12 @@ class PregelNode extends runnables_1.RunnableBinding {
139
139
  writable: true,
140
140
  value: void 0
141
141
  });
142
+ Object.defineProperty(this, "subgraphs", {
143
+ enumerable: true,
144
+ configurable: true,
145
+ writable: true,
146
+ value: void 0
147
+ });
142
148
  this.channels = channels;
143
149
  this.triggers = triggers;
144
150
  this.mapper = mapper;
@@ -148,6 +154,7 @@ class PregelNode extends runnables_1.RunnableBinding {
148
154
  this.metadata = metadata ?? this.metadata;
149
155
  this.tags = mergedTags;
150
156
  this.retryPolicy = retryPolicy;
157
+ this.subgraphs = subgraphs;
151
158
  }
152
159
  getWriters() {
153
160
  const newWriters = [...this.writers];
@@ -20,6 +20,7 @@ interface PregelNodeArgs<RunInput, RunOutput> extends Partial<RunnableBindingArg
20
20
  config?: RunnableConfig;
21
21
  metadata?: Record<string, unknown>;
22
22
  retryPolicy?: RetryPolicy;
23
+ subgraphs?: Runnable[];
23
24
  }
24
25
  export type PregelNodeInputType = any;
25
26
  export type PregelNodeOutputType = any;
@@ -34,6 +35,7 @@ export declare class PregelNode<RunInput = PregelNodeInputType, RunOutput = Preg
34
35
  metadata: Record<string, unknown>;
35
36
  tags: string[];
36
37
  retryPolicy?: RetryPolicy;
38
+ subgraphs?: Runnable[];
37
39
  constructor(fields: PregelNodeArgs<RunInput, RunOutput>);
38
40
  getWriters(): Array<Runnable>;
39
41
  getNode(): Runnable<RunInput, RunOutput> | undefined;
@@ -59,7 +59,7 @@ const defaultRunnableBound =
59
59
  /* #__PURE__ */ new RunnablePassthrough();
60
60
  export class PregelNode extends RunnableBinding {
61
61
  constructor(fields) {
62
- const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, } = fields;
62
+ const { channels, triggers, mapper, writers, bound, kwargs, metadata, retryPolicy, tags, subgraphs, } = fields;
63
63
  const mergedTags = [
64
64
  ...(fields.config?.tags ? fields.config.tags : []),
65
65
  ...(tags ?? []),
@@ -135,6 +135,12 @@ export class PregelNode extends RunnableBinding {
135
135
  writable: true,
136
136
  value: void 0
137
137
  });
138
+ Object.defineProperty(this, "subgraphs", {
139
+ enumerable: true,
140
+ configurable: true,
141
+ writable: true,
142
+ value: void 0
143
+ });
138
144
  this.channels = channels;
139
145
  this.triggers = triggers;
140
146
  this.mapper = mapper;
@@ -144,6 +150,7 @@ export class PregelNode extends RunnableBinding {
144
150
  this.metadata = metadata ?? this.metadata;
145
151
  this.tags = mergedTags;
146
152
  this.retryPolicy = retryPolicy;
153
+ this.subgraphs = subgraphs;
147
154
  }
148
155
  getWriters() {
149
156
  const newWriters = [...this.writers];
@@ -71,6 +71,7 @@ export interface PregelExecutableTask<N extends PropertyKey, C extends PropertyK
71
71
  readonly retry_policy?: RetryPolicy;
72
72
  readonly id: string;
73
73
  readonly path?: [string, ...(string | number)[]];
74
+ readonly subgraphs?: Runnable[];
74
75
  }
75
76
  export interface StateSnapshot {
76
77
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.findSubgraphPregel = void 0;
3
+ exports.findSubgraphPregel = exports.isPregelLike = void 0;
4
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
5
  function isRunnableSequence(x) {
6
6
  return "steps" in x && Array.isArray(x.steps);
@@ -15,6 +15,7 @@ x
15
15
  "outputChannels" &&
16
16
  x.outputChannels !== undefined);
17
17
  }
18
+ exports.isPregelLike = isPregelLike;
18
19
  function findSubgraphPregel(candidate
19
20
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
21
  ) {
@@ -1,3 +1,4 @@
1
- import { Runnable } from "@langchain/core/runnables";
1
+ import { Runnable, RunnableLike } from "@langchain/core/runnables";
2
2
  import type { PregelInterface } from "../types.js";
3
+ export declare function isPregelLike(x: PregelInterface<any, any> | RunnableLike<any, any, any>): x is PregelInterface<any, any>;
3
4
  export declare function findSubgraphPregel(candidate: Runnable): PregelInterface<any, any> | undefined;
@@ -2,7 +2,7 @@
2
2
  function isRunnableSequence(x) {
3
3
  return "steps" in x && Array.isArray(x.steps);
4
4
  }
5
- function isPregelLike(
5
+ export function isPregelLike(
6
6
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
7
  x
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/langgraph",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "LangGraph",
5
5
  "type": "module",
6
6
  "engines": {