langchain 1.5.2 → 1.5.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # langchain
2
2
 
3
+ ## 1.5.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#11167](https://github.com/langchain-ai/langchainjs/pull/11167) [`4c7a06e`](https://github.com/langchain-ai/langchainjs/commit/4c7a06ec3e4728bb036a28f678dd8ec2521e1c82) Thanks [@colifran](https://github.com/colifran)! - fix(langchain): malformed tool input schemas are unrecoverable
8
+
3
9
  ## 1.5.2
4
10
 
5
11
  ### Patch Changes
@@ -32,6 +32,7 @@ var StructuredOutputParsingError = class extends Error {
32
32
  * Raised when a tool call is throwing an error.
33
33
  */
34
34
  var ToolInvocationError = class extends Error {
35
+ "~brand" = "ToolInvocationError";
35
36
  toolCall;
36
37
  toolError;
37
38
  constructor(toolError, toolCall) {
@@ -41,6 +42,14 @@ var ToolInvocationError = class extends Error {
41
42
  this.toolCall = toolCall;
42
43
  this.toolError = error;
43
44
  }
45
+ /**
46
+ * Check if the error is a ToolInvocationError.
47
+ * @param error - The error to check
48
+ * @returns Whether the error is a ToolInvocationError
49
+ */
50
+ static isInstance(error) {
51
+ return error instanceof Error && "~brand" in error && error["~brand"] === "ToolInvocationError";
52
+ }
44
53
  };
45
54
  /**
46
55
  * Error thrown when a middleware fails.
@@ -49,7 +58,7 @@ var ToolInvocationError = class extends Error {
49
58
  * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.
50
59
  */
51
60
  var MiddlewareError = class MiddlewareError extends Error {
52
- static "~brand" = "MiddlewareError";
61
+ "~brand" = "MiddlewareError";
53
62
  constructor(error, middlewareName) {
54
63
  const errorMessage = error instanceof Error ? error.message : String(error);
55
64
  super(errorMessage);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.cjs","names":[],"sources":["../../src/agents/errors.ts"],"sourcesContent":["/* oxlint-disable no-instanceof/no-instanceof */\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { isGraphBubbleUp } from \"@langchain/langgraph\";\n\nexport class MultipleToolsBoundError extends Error {\n constructor() {\n super(\n \"The provided LLM already has bound tools. \" +\n \"Please provide an LLM without bound tools to createAgent. \" +\n \"The agent will bind the tools provided in the 'tools' parameter.\"\n );\n }\n}\n\n/**\n * Raised when model returns multiple structured output tool calls when only one is expected.\n */\nexport class MultipleStructuredOutputsError extends Error {\n public readonly toolNames: string[];\n\n constructor(toolNames: string[]) {\n super(\n `The model has called multiple tools: ${toolNames.join(\n \", \"\n )} to return a structured output. ` +\n \"This is not supported. Please provide a single structured output.\"\n );\n this.toolNames = toolNames;\n }\n}\n\n/**\n * Raised when structured output tool call arguments fail to parse according to the schema.\n */\nexport class StructuredOutputParsingError extends Error {\n public readonly toolName: string;\n\n public readonly errors: string[];\n\n constructor(toolName: string, errors: string[]) {\n super(\n `Failed to parse structured output for tool '${toolName}':${errors\n .map((e) => `\\n - ${e}`)\n .join(\"\")}.`\n );\n this.toolName = toolName;\n this.errors = errors;\n }\n}\n\n/**\n * Raised when a tool call is throwing an error.\n */\nexport class ToolInvocationError extends Error {\n public readonly toolCall: ToolCall;\n\n public readonly toolError: Error;\n\n constructor(toolError: unknown, toolCall: ToolCall) {\n const error =\n toolError instanceof Error ? toolError : new Error(String(toolError));\n const toolArgs = JSON.stringify(toolCall.args);\n super(\n `Error invoking tool '${toolCall.name}' with kwargs ${toolArgs} with error: ${error.stack}\\n Please fix the error and try again.`\n );\n\n this.toolCall = toolCall;\n this.toolError = error;\n }\n}\n\n/**\n * Error thrown when a middleware fails.\n *\n * Use `MiddlewareError.wrap()` to create instances. The constructor is private\n * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.\n */\nexport class MiddlewareError extends Error {\n static readonly \"~brand\" = \"MiddlewareError\";\n\n private constructor(error: unknown, middlewareName: string) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n super(errorMessage);\n this.name =\n error instanceof Error\n ? error.name\n : `${middlewareName[0].toUpperCase() + middlewareName.slice(1)}Error`;\n\n if (error instanceof Error) {\n this.cause = error;\n }\n }\n\n /**\n * Wrap an error in a MiddlewareError, unless it's a GraphBubbleUp error\n * (like GraphInterrupt) which should propagate unchanged.\n *\n * @param error - The error to wrap\n * @param middlewareName - The name of the middleware that threw the error\n * @returns The original error if it's a GraphBubbleUp, otherwise a new MiddlewareError\n */\n static wrap(error: unknown, middlewareName: string): Error {\n // Don't wrap GraphBubbleUp errors (GraphInterrupt, NodeInterrupt, etc.)\n // These are control flow mechanisms that need to bubble up unchanged\n if (isGraphBubbleUp(error)) {\n return error;\n }\n return new MiddlewareError(error, middlewareName);\n }\n\n /**\n * Check if the error is a MiddlewareError.\n * @param error - The error to check\n * @returns Whether the error is a MiddlewareError\n */\n static isInstance(error: unknown): error is MiddlewareError {\n return (\n error instanceof Error &&\n \"~brand\" in error &&\n error[\"~brand\"] === \"MiddlewareError\"\n );\n }\n}\n"],"mappings":";;;AAIA,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;AACZ,QACE,uKAGD;;;;;;AAOL,IAAa,iCAAb,cAAoD,MAAM;CACxD;CAEA,YAAY,WAAqB;AAC/B,QACE,wCAAwC,UAAU,KAChD,KACD,CAAC,mGAEH;AACD,OAAK,YAAY;;;;;;AAOrB,IAAa,+BAAb,cAAkD,MAAM;CACtD;CAEA;CAEA,YAAY,UAAkB,QAAkB;AAC9C,QACE,+CAA+C,SAAS,IAAI,OACzD,KAAK,MAAM,SAAS,IAAI,CACxB,KAAK,GAAG,CAAC,GACb;AACD,OAAK,WAAW;AAChB,OAAK,SAAS;;;;;;AAOlB,IAAa,sBAAb,cAAyC,MAAM;CAC7C;CAEA;CAEA,YAAY,WAAoB,UAAoB;EAClD,MAAM,QACJ,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,UAAU,CAAC;EACvE,MAAM,WAAW,KAAK,UAAU,SAAS,KAAK;AAC9C,QACE,wBAAwB,SAAS,KAAK,gBAAgB,SAAS,eAAe,MAAM,MAAM,wCAC3F;AAED,OAAK,WAAW;AAChB,OAAK,YAAY;;;;;;;;;AAUrB,IAAa,kBAAb,MAAa,wBAAwB,MAAM;CACzC,OAAgB,WAAW;CAE3B,YAAoB,OAAgB,gBAAwB;EAC1D,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QAAM,aAAa;AACnB,OAAK,OACH,iBAAiB,QACb,MAAM,OACN,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,MAAM,EAAE,CAAC;AAEnE,MAAI,iBAAiB,MACnB,MAAK,QAAQ;;;;;;;;;;CAYjB,OAAO,KAAK,OAAgB,gBAA+B;AAGzD,OAAA,GAAA,qBAAA,iBAAoB,MAAM,CACxB,QAAO;AAET,SAAO,IAAI,gBAAgB,OAAO,eAAe;;;;;;;CAQnD,OAAO,WAAW,OAA0C;AAC1D,SACE,iBAAiB,SACjB,YAAY,SACZ,MAAM,cAAc"}
1
+ {"version":3,"file":"errors.cjs","names":[],"sources":["../../src/agents/errors.ts"],"sourcesContent":["/* oxlint-disable no-instanceof/no-instanceof */\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { isGraphBubbleUp } from \"@langchain/langgraph\";\n\nexport class MultipleToolsBoundError extends Error {\n constructor() {\n super(\n \"The provided LLM already has bound tools. \" +\n \"Please provide an LLM without bound tools to createAgent. \" +\n \"The agent will bind the tools provided in the 'tools' parameter.\"\n );\n }\n}\n\n/**\n * Raised when model returns multiple structured output tool calls when only one is expected.\n */\nexport class MultipleStructuredOutputsError extends Error {\n public readonly toolNames: string[];\n\n constructor(toolNames: string[]) {\n super(\n `The model has called multiple tools: ${toolNames.join(\n \", \"\n )} to return a structured output. ` +\n \"This is not supported. Please provide a single structured output.\"\n );\n this.toolNames = toolNames;\n }\n}\n\n/**\n * Raised when structured output tool call arguments fail to parse according to the schema.\n */\nexport class StructuredOutputParsingError extends Error {\n public readonly toolName: string;\n\n public readonly errors: string[];\n\n constructor(toolName: string, errors: string[]) {\n super(\n `Failed to parse structured output for tool '${toolName}':${errors\n .map((e) => `\\n - ${e}`)\n .join(\"\")}.`\n );\n this.toolName = toolName;\n this.errors = errors;\n }\n}\n\n/**\n * Raised when a tool call is throwing an error.\n */\nexport class ToolInvocationError extends Error {\n readonly \"~brand\" = \"ToolInvocationError\";\n\n public readonly toolCall: ToolCall;\n\n public readonly toolError: Error;\n\n constructor(toolError: unknown, toolCall: ToolCall) {\n const error =\n toolError instanceof Error ? toolError : new Error(String(toolError));\n const toolArgs = JSON.stringify(toolCall.args);\n super(\n `Error invoking tool '${toolCall.name}' with kwargs ${toolArgs} with error: ${error.stack}\\n Please fix the error and try again.`\n );\n\n this.toolCall = toolCall;\n this.toolError = error;\n }\n\n /**\n * Check if the error is a ToolInvocationError.\n * @param error - The error to check\n * @returns Whether the error is a ToolInvocationError\n */\n static isInstance(error: unknown): error is ToolInvocationError {\n return (\n error instanceof Error &&\n \"~brand\" in error &&\n error[\"~brand\"] === \"ToolInvocationError\"\n );\n }\n}\n\n/**\n * Error thrown when a middleware fails.\n *\n * Use `MiddlewareError.wrap()` to create instances. The constructor is private\n * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.\n */\nexport class MiddlewareError extends Error {\n readonly \"~brand\" = \"MiddlewareError\";\n\n private constructor(error: unknown, middlewareName: string) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n super(errorMessage);\n this.name =\n error instanceof Error\n ? error.name\n : `${middlewareName[0].toUpperCase() + middlewareName.slice(1)}Error`;\n\n if (error instanceof Error) {\n this.cause = error;\n }\n }\n\n /**\n * Wrap an error in a MiddlewareError, unless it's a GraphBubbleUp error\n * (like GraphInterrupt) which should propagate unchanged.\n *\n * @param error - The error to wrap\n * @param middlewareName - The name of the middleware that threw the error\n * @returns The original error if it's a GraphBubbleUp, otherwise a new MiddlewareError\n */\n static wrap(error: unknown, middlewareName: string): Error {\n // Don't wrap GraphBubbleUp errors (GraphInterrupt, NodeInterrupt, etc.)\n // These are control flow mechanisms that need to bubble up unchanged\n if (isGraphBubbleUp(error)) {\n return error;\n }\n return new MiddlewareError(error, middlewareName);\n }\n\n /**\n * Check if the error is a MiddlewareError.\n * @param error - The error to check\n * @returns Whether the error is a MiddlewareError\n */\n static isInstance(error: unknown): error is MiddlewareError {\n return (\n error instanceof Error &&\n \"~brand\" in error &&\n error[\"~brand\"] === \"MiddlewareError\"\n );\n }\n}\n"],"mappings":";;;AAIA,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;AACZ,QACE,uKAGD;;;;;;AAOL,IAAa,iCAAb,cAAoD,MAAM;CACxD;CAEA,YAAY,WAAqB;AAC/B,QACE,wCAAwC,UAAU,KAChD,KACD,CAAC,mGAEH;AACD,OAAK,YAAY;;;;;;AAOrB,IAAa,+BAAb,cAAkD,MAAM;CACtD;CAEA;CAEA,YAAY,UAAkB,QAAkB;AAC9C,QACE,+CAA+C,SAAS,IAAI,OACzD,KAAK,MAAM,SAAS,IAAI,CACxB,KAAK,GAAG,CAAC,GACb;AACD,OAAK,WAAW;AAChB,OAAK,SAAS;;;;;;AAOlB,IAAa,sBAAb,cAAyC,MAAM;CAC7C,WAAoB;CAEpB;CAEA;CAEA,YAAY,WAAoB,UAAoB;EAClD,MAAM,QACJ,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,UAAU,CAAC;EACvE,MAAM,WAAW,KAAK,UAAU,SAAS,KAAK;AAC9C,QACE,wBAAwB,SAAS,KAAK,gBAAgB,SAAS,eAAe,MAAM,MAAM,wCAC3F;AAED,OAAK,WAAW;AAChB,OAAK,YAAY;;;;;;;CAQnB,OAAO,WAAW,OAA8C;AAC9D,SACE,iBAAiB,SACjB,YAAY,SACZ,MAAM,cAAc;;;;;;;;;AAW1B,IAAa,kBAAb,MAAa,wBAAwB,MAAM;CACzC,WAAoB;CAEpB,YAAoB,OAAgB,gBAAwB;EAC1D,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QAAM,aAAa;AACnB,OAAK,OACH,iBAAiB,QACb,MAAM,OACN,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,MAAM,EAAE,CAAC;AAEnE,MAAI,iBAAiB,MACnB,MAAK,QAAQ;;;;;;;;;;CAYjB,OAAO,KAAK,OAAgB,gBAA+B;AAGzD,OAAA,GAAA,qBAAA,iBAAoB,MAAM,CACxB,QAAO;AAET,SAAO,IAAI,gBAAgB,OAAO,eAAe;;;;;;;CAQnD,OAAO,WAAW,OAA0C;AAC1D,SACE,iBAAiB,SACjB,YAAY,SACZ,MAAM,cAAc"}
@@ -23,9 +23,16 @@ declare class StructuredOutputParsingError extends Error {
23
23
  * Raised when a tool call is throwing an error.
24
24
  */
25
25
  declare class ToolInvocationError extends Error {
26
+ readonly "~brand" = "ToolInvocationError";
26
27
  readonly toolCall: ToolCall;
27
28
  readonly toolError: Error;
28
29
  constructor(toolError: unknown, toolCall: ToolCall);
30
+ /**
31
+ * Check if the error is a ToolInvocationError.
32
+ * @param error - The error to check
33
+ * @returns Whether the error is a ToolInvocationError
34
+ */
35
+ static isInstance(error: unknown): error is ToolInvocationError;
29
36
  }
30
37
  /**
31
38
  * Error thrown when a middleware fails.
@@ -34,7 +41,7 @@ declare class ToolInvocationError extends Error {
34
41
  * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.
35
42
  */
36
43
  declare class MiddlewareError extends Error {
37
- static readonly "~brand" = "MiddlewareError";
44
+ readonly "~brand" = "MiddlewareError";
38
45
  private constructor();
39
46
  /**
40
47
  * Wrap an error in a MiddlewareError, unless it's a GraphBubbleUp error
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.cts","names":[],"sources":["../../src/agents/errors.ts"],"mappings":";;;cAIa,uBAAA,SAAgC,KAAA;EAC3C,WAAA,CAAA;AAAA;;;;cAYW,8BAAA,SAAuC,KAAA;EAAA,SAClC,SAAA;EAEhB,WAAA,CAAY,SAAA;AAAA;;;;cAcD,4BAAA,SAAqC,KAAA;EAAA,SAChC,QAAA;EAAA,SAEA,MAAA;EAEhB,WAAA,CAAY,QAAA,UAAkB,MAAA;AAAA;;;;cAcnB,mBAAA,SAA4B,KAAA;EAAA,SACvB,QAAA,EAAU,QAAA;EAAA,SAEV,SAAA,EAAW,KAAA;EAE3B,WAAA,CAAY,SAAA,WAAoB,QAAA,EAAU,QAAA;AAAA;;;;AAL5C;;;cAwBa,eAAA,SAAwB,KAAA;EAAA;EAAA,QAG5B,WAAA,CAAA;EA3BgC;;;;;;;;EAAA,OAgDhC,IAAA,CAAK,KAAA,WAAgB,cAAA,WAAyB,KAAA;EA3CzC;;;;;EAAA,OAyDL,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,eAAA;AAAA"}
1
+ {"version":3,"file":"errors.d.cts","names":[],"sources":["../../src/agents/errors.ts"],"mappings":";;;cAIa,uBAAA,SAAgC,KAAA;EAC3C,WAAA,CAAA;AAAA;;;;cAYW,8BAAA,SAAuC,KAAA;EAAA,SAClC,SAAA;EAEhB,WAAA,CAAY,SAAA;AAAA;;;;cAcD,4BAAA,SAAqC,KAAA;EAAA,SAChC,QAAA;EAAA,SAEA,MAAA;EAEhB,WAAA,CAAY,QAAA,UAAkB,MAAA;AAAA;;;;cAcnB,mBAAA,SAA4B,KAAA;EAAA;EAAA,SAGvB,QAAA,EAAU,QAAA;EAAA,SAEV,SAAA,EAAW,KAAA;EAE3B,WAAA,CAAY,SAAA,WAAoB,QAAA,EAAU,QAAA;EArBZ;;;AAchC;;EAdgC,OAsCvB,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,mBAAA;AAAA;;;;;;;cAejC,eAAA,SAAwB,KAAA;EAAA;EAAA,QAG5B,WAAA,CAAA;EArCS;;;;;;;;EAAA,OA0DT,IAAA,CAAK,KAAA,WAAgB,cAAA,WAAyB,KAAA;EAvCT;;;AAe9C;;EAf8C,OAqDrC,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,eAAA;AAAA"}
@@ -23,9 +23,16 @@ declare class StructuredOutputParsingError extends Error {
23
23
  * Raised when a tool call is throwing an error.
24
24
  */
25
25
  declare class ToolInvocationError extends Error {
26
+ readonly "~brand" = "ToolInvocationError";
26
27
  readonly toolCall: ToolCall;
27
28
  readonly toolError: Error;
28
29
  constructor(toolError: unknown, toolCall: ToolCall);
30
+ /**
31
+ * Check if the error is a ToolInvocationError.
32
+ * @param error - The error to check
33
+ * @returns Whether the error is a ToolInvocationError
34
+ */
35
+ static isInstance(error: unknown): error is ToolInvocationError;
29
36
  }
30
37
  /**
31
38
  * Error thrown when a middleware fails.
@@ -34,7 +41,7 @@ declare class ToolInvocationError extends Error {
34
41
  * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.
35
42
  */
36
43
  declare class MiddlewareError extends Error {
37
- static readonly "~brand" = "MiddlewareError";
44
+ readonly "~brand" = "MiddlewareError";
38
45
  private constructor();
39
46
  /**
40
47
  * Wrap an error in a MiddlewareError, unless it's a GraphBubbleUp error
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/agents/errors.ts"],"mappings":";;;cAIa,uBAAA,SAAgC,KAAA;EAC3C,WAAA,CAAA;AAAA;;;;cAYW,8BAAA,SAAuC,KAAA;EAAA,SAClC,SAAA;EAEhB,WAAA,CAAY,SAAA;AAAA;;;;cAcD,4BAAA,SAAqC,KAAA;EAAA,SAChC,QAAA;EAAA,SAEA,MAAA;EAEhB,WAAA,CAAY,QAAA,UAAkB,MAAA;AAAA;;;;cAcnB,mBAAA,SAA4B,KAAA;EAAA,SACvB,QAAA,EAAU,QAAA;EAAA,SAEV,SAAA,EAAW,KAAA;EAE3B,WAAA,CAAY,SAAA,WAAoB,QAAA,EAAU,QAAA;AAAA;;;;AAL5C;;;cAwBa,eAAA,SAAwB,KAAA;EAAA;EAAA,QAG5B,WAAA,CAAA;EA3BgC;;;;;;;;EAAA,OAgDhC,IAAA,CAAK,KAAA,WAAgB,cAAA,WAAyB,KAAA;EA3CzC;;;;;EAAA,OAyDL,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,eAAA;AAAA"}
1
+ {"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/agents/errors.ts"],"mappings":";;;cAIa,uBAAA,SAAgC,KAAA;EAC3C,WAAA,CAAA;AAAA;;;;cAYW,8BAAA,SAAuC,KAAA;EAAA,SAClC,SAAA;EAEhB,WAAA,CAAY,SAAA;AAAA;;;;cAcD,4BAAA,SAAqC,KAAA;EAAA,SAChC,QAAA;EAAA,SAEA,MAAA;EAEhB,WAAA,CAAY,QAAA,UAAkB,MAAA;AAAA;;;;cAcnB,mBAAA,SAA4B,KAAA;EAAA;EAAA,SAGvB,QAAA,EAAU,QAAA;EAAA,SAEV,SAAA,EAAW,KAAA;EAE3B,WAAA,CAAY,SAAA,WAAoB,QAAA,EAAU,QAAA;EArBZ;;;AAchC;;EAdgC,OAsCvB,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,mBAAA;AAAA;;;;;;;cAejC,eAAA,SAAwB,KAAA;EAAA;EAAA,QAG5B,WAAA,CAAA;EArCS;;;;;;;;EAAA,OA0DT,IAAA,CAAK,KAAA,WAAgB,cAAA,WAAyB,KAAA;EAvCT;;;AAe9C;;EAf8C,OAqDrC,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,eAAA;AAAA"}
@@ -31,6 +31,7 @@ var StructuredOutputParsingError = class extends Error {
31
31
  * Raised when a tool call is throwing an error.
32
32
  */
33
33
  var ToolInvocationError = class extends Error {
34
+ "~brand" = "ToolInvocationError";
34
35
  toolCall;
35
36
  toolError;
36
37
  constructor(toolError, toolCall) {
@@ -40,6 +41,14 @@ var ToolInvocationError = class extends Error {
40
41
  this.toolCall = toolCall;
41
42
  this.toolError = error;
42
43
  }
44
+ /**
45
+ * Check if the error is a ToolInvocationError.
46
+ * @param error - The error to check
47
+ * @returns Whether the error is a ToolInvocationError
48
+ */
49
+ static isInstance(error) {
50
+ return error instanceof Error && "~brand" in error && error["~brand"] === "ToolInvocationError";
51
+ }
43
52
  };
44
53
  /**
45
54
  * Error thrown when a middleware fails.
@@ -48,7 +57,7 @@ var ToolInvocationError = class extends Error {
48
57
  * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.
49
58
  */
50
59
  var MiddlewareError = class MiddlewareError extends Error {
51
- static "~brand" = "MiddlewareError";
60
+ "~brand" = "MiddlewareError";
52
61
  constructor(error, middlewareName) {
53
62
  const errorMessage = error instanceof Error ? error.message : String(error);
54
63
  super(errorMessage);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../src/agents/errors.ts"],"sourcesContent":["/* oxlint-disable no-instanceof/no-instanceof */\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { isGraphBubbleUp } from \"@langchain/langgraph\";\n\nexport class MultipleToolsBoundError extends Error {\n constructor() {\n super(\n \"The provided LLM already has bound tools. \" +\n \"Please provide an LLM without bound tools to createAgent. \" +\n \"The agent will bind the tools provided in the 'tools' parameter.\"\n );\n }\n}\n\n/**\n * Raised when model returns multiple structured output tool calls when only one is expected.\n */\nexport class MultipleStructuredOutputsError extends Error {\n public readonly toolNames: string[];\n\n constructor(toolNames: string[]) {\n super(\n `The model has called multiple tools: ${toolNames.join(\n \", \"\n )} to return a structured output. ` +\n \"This is not supported. Please provide a single structured output.\"\n );\n this.toolNames = toolNames;\n }\n}\n\n/**\n * Raised when structured output tool call arguments fail to parse according to the schema.\n */\nexport class StructuredOutputParsingError extends Error {\n public readonly toolName: string;\n\n public readonly errors: string[];\n\n constructor(toolName: string, errors: string[]) {\n super(\n `Failed to parse structured output for tool '${toolName}':${errors\n .map((e) => `\\n - ${e}`)\n .join(\"\")}.`\n );\n this.toolName = toolName;\n this.errors = errors;\n }\n}\n\n/**\n * Raised when a tool call is throwing an error.\n */\nexport class ToolInvocationError extends Error {\n public readonly toolCall: ToolCall;\n\n public readonly toolError: Error;\n\n constructor(toolError: unknown, toolCall: ToolCall) {\n const error =\n toolError instanceof Error ? toolError : new Error(String(toolError));\n const toolArgs = JSON.stringify(toolCall.args);\n super(\n `Error invoking tool '${toolCall.name}' with kwargs ${toolArgs} with error: ${error.stack}\\n Please fix the error and try again.`\n );\n\n this.toolCall = toolCall;\n this.toolError = error;\n }\n}\n\n/**\n * Error thrown when a middleware fails.\n *\n * Use `MiddlewareError.wrap()` to create instances. The constructor is private\n * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.\n */\nexport class MiddlewareError extends Error {\n static readonly \"~brand\" = \"MiddlewareError\";\n\n private constructor(error: unknown, middlewareName: string) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n super(errorMessage);\n this.name =\n error instanceof Error\n ? error.name\n : `${middlewareName[0].toUpperCase() + middlewareName.slice(1)}Error`;\n\n if (error instanceof Error) {\n this.cause = error;\n }\n }\n\n /**\n * Wrap an error in a MiddlewareError, unless it's a GraphBubbleUp error\n * (like GraphInterrupt) which should propagate unchanged.\n *\n * @param error - The error to wrap\n * @param middlewareName - The name of the middleware that threw the error\n * @returns The original error if it's a GraphBubbleUp, otherwise a new MiddlewareError\n */\n static wrap(error: unknown, middlewareName: string): Error {\n // Don't wrap GraphBubbleUp errors (GraphInterrupt, NodeInterrupt, etc.)\n // These are control flow mechanisms that need to bubble up unchanged\n if (isGraphBubbleUp(error)) {\n return error;\n }\n return new MiddlewareError(error, middlewareName);\n }\n\n /**\n * Check if the error is a MiddlewareError.\n * @param error - The error to check\n * @returns Whether the error is a MiddlewareError\n */\n static isInstance(error: unknown): error is MiddlewareError {\n return (\n error instanceof Error &&\n \"~brand\" in error &&\n error[\"~brand\"] === \"MiddlewareError\"\n );\n }\n}\n"],"mappings":";;AAIA,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;AACZ,QACE,uKAGD;;;;;;AAOL,IAAa,iCAAb,cAAoD,MAAM;CACxD;CAEA,YAAY,WAAqB;AAC/B,QACE,wCAAwC,UAAU,KAChD,KACD,CAAC,mGAEH;AACD,OAAK,YAAY;;;;;;AAOrB,IAAa,+BAAb,cAAkD,MAAM;CACtD;CAEA;CAEA,YAAY,UAAkB,QAAkB;AAC9C,QACE,+CAA+C,SAAS,IAAI,OACzD,KAAK,MAAM,SAAS,IAAI,CACxB,KAAK,GAAG,CAAC,GACb;AACD,OAAK,WAAW;AAChB,OAAK,SAAS;;;;;;AAOlB,IAAa,sBAAb,cAAyC,MAAM;CAC7C;CAEA;CAEA,YAAY,WAAoB,UAAoB;EAClD,MAAM,QACJ,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,UAAU,CAAC;EACvE,MAAM,WAAW,KAAK,UAAU,SAAS,KAAK;AAC9C,QACE,wBAAwB,SAAS,KAAK,gBAAgB,SAAS,eAAe,MAAM,MAAM,wCAC3F;AAED,OAAK,WAAW;AAChB,OAAK,YAAY;;;;;;;;;AAUrB,IAAa,kBAAb,MAAa,wBAAwB,MAAM;CACzC,OAAgB,WAAW;CAE3B,YAAoB,OAAgB,gBAAwB;EAC1D,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QAAM,aAAa;AACnB,OAAK,OACH,iBAAiB,QACb,MAAM,OACN,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,MAAM,EAAE,CAAC;AAEnE,MAAI,iBAAiB,MACnB,MAAK,QAAQ;;;;;;;;;;CAYjB,OAAO,KAAK,OAAgB,gBAA+B;AAGzD,MAAI,gBAAgB,MAAM,CACxB,QAAO;AAET,SAAO,IAAI,gBAAgB,OAAO,eAAe;;;;;;;CAQnD,OAAO,WAAW,OAA0C;AAC1D,SACE,iBAAiB,SACjB,YAAY,SACZ,MAAM,cAAc"}
1
+ {"version":3,"file":"errors.js","names":[],"sources":["../../src/agents/errors.ts"],"sourcesContent":["/* oxlint-disable no-instanceof/no-instanceof */\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { isGraphBubbleUp } from \"@langchain/langgraph\";\n\nexport class MultipleToolsBoundError extends Error {\n constructor() {\n super(\n \"The provided LLM already has bound tools. \" +\n \"Please provide an LLM without bound tools to createAgent. \" +\n \"The agent will bind the tools provided in the 'tools' parameter.\"\n );\n }\n}\n\n/**\n * Raised when model returns multiple structured output tool calls when only one is expected.\n */\nexport class MultipleStructuredOutputsError extends Error {\n public readonly toolNames: string[];\n\n constructor(toolNames: string[]) {\n super(\n `The model has called multiple tools: ${toolNames.join(\n \", \"\n )} to return a structured output. ` +\n \"This is not supported. Please provide a single structured output.\"\n );\n this.toolNames = toolNames;\n }\n}\n\n/**\n * Raised when structured output tool call arguments fail to parse according to the schema.\n */\nexport class StructuredOutputParsingError extends Error {\n public readonly toolName: string;\n\n public readonly errors: string[];\n\n constructor(toolName: string, errors: string[]) {\n super(\n `Failed to parse structured output for tool '${toolName}':${errors\n .map((e) => `\\n - ${e}`)\n .join(\"\")}.`\n );\n this.toolName = toolName;\n this.errors = errors;\n }\n}\n\n/**\n * Raised when a tool call is throwing an error.\n */\nexport class ToolInvocationError extends Error {\n readonly \"~brand\" = \"ToolInvocationError\";\n\n public readonly toolCall: ToolCall;\n\n public readonly toolError: Error;\n\n constructor(toolError: unknown, toolCall: ToolCall) {\n const error =\n toolError instanceof Error ? toolError : new Error(String(toolError));\n const toolArgs = JSON.stringify(toolCall.args);\n super(\n `Error invoking tool '${toolCall.name}' with kwargs ${toolArgs} with error: ${error.stack}\\n Please fix the error and try again.`\n );\n\n this.toolCall = toolCall;\n this.toolError = error;\n }\n\n /**\n * Check if the error is a ToolInvocationError.\n * @param error - The error to check\n * @returns Whether the error is a ToolInvocationError\n */\n static isInstance(error: unknown): error is ToolInvocationError {\n return (\n error instanceof Error &&\n \"~brand\" in error &&\n error[\"~brand\"] === \"ToolInvocationError\"\n );\n }\n}\n\n/**\n * Error thrown when a middleware fails.\n *\n * Use `MiddlewareError.wrap()` to create instances. The constructor is private\n * to ensure that GraphBubbleUp errors (like GraphInterrupt) are never wrapped.\n */\nexport class MiddlewareError extends Error {\n readonly \"~brand\" = \"MiddlewareError\";\n\n private constructor(error: unknown, middlewareName: string) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n super(errorMessage);\n this.name =\n error instanceof Error\n ? error.name\n : `${middlewareName[0].toUpperCase() + middlewareName.slice(1)}Error`;\n\n if (error instanceof Error) {\n this.cause = error;\n }\n }\n\n /**\n * Wrap an error in a MiddlewareError, unless it's a GraphBubbleUp error\n * (like GraphInterrupt) which should propagate unchanged.\n *\n * @param error - The error to wrap\n * @param middlewareName - The name of the middleware that threw the error\n * @returns The original error if it's a GraphBubbleUp, otherwise a new MiddlewareError\n */\n static wrap(error: unknown, middlewareName: string): Error {\n // Don't wrap GraphBubbleUp errors (GraphInterrupt, NodeInterrupt, etc.)\n // These are control flow mechanisms that need to bubble up unchanged\n if (isGraphBubbleUp(error)) {\n return error;\n }\n return new MiddlewareError(error, middlewareName);\n }\n\n /**\n * Check if the error is a MiddlewareError.\n * @param error - The error to check\n * @returns Whether the error is a MiddlewareError\n */\n static isInstance(error: unknown): error is MiddlewareError {\n return (\n error instanceof Error &&\n \"~brand\" in error &&\n error[\"~brand\"] === \"MiddlewareError\"\n );\n }\n}\n"],"mappings":";;AAIA,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;AACZ,QACE,uKAGD;;;;;;AAOL,IAAa,iCAAb,cAAoD,MAAM;CACxD;CAEA,YAAY,WAAqB;AAC/B,QACE,wCAAwC,UAAU,KAChD,KACD,CAAC,mGAEH;AACD,OAAK,YAAY;;;;;;AAOrB,IAAa,+BAAb,cAAkD,MAAM;CACtD;CAEA;CAEA,YAAY,UAAkB,QAAkB;AAC9C,QACE,+CAA+C,SAAS,IAAI,OACzD,KAAK,MAAM,SAAS,IAAI,CACxB,KAAK,GAAG,CAAC,GACb;AACD,OAAK,WAAW;AAChB,OAAK,SAAS;;;;;;AAOlB,IAAa,sBAAb,cAAyC,MAAM;CAC7C,WAAoB;CAEpB;CAEA;CAEA,YAAY,WAAoB,UAAoB;EAClD,MAAM,QACJ,qBAAqB,QAAQ,YAAY,IAAI,MAAM,OAAO,UAAU,CAAC;EACvE,MAAM,WAAW,KAAK,UAAU,SAAS,KAAK;AAC9C,QACE,wBAAwB,SAAS,KAAK,gBAAgB,SAAS,eAAe,MAAM,MAAM,wCAC3F;AAED,OAAK,WAAW;AAChB,OAAK,YAAY;;;;;;;CAQnB,OAAO,WAAW,OAA8C;AAC9D,SACE,iBAAiB,SACjB,YAAY,SACZ,MAAM,cAAc;;;;;;;;;AAW1B,IAAa,kBAAb,MAAa,wBAAwB,MAAM;CACzC,WAAoB;CAEpB,YAAoB,OAAgB,gBAAwB;EAC1D,MAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAC3E,QAAM,aAAa;AACnB,OAAK,OACH,iBAAiB,QACb,MAAM,OACN,GAAG,eAAe,GAAG,aAAa,GAAG,eAAe,MAAM,EAAE,CAAC;AAEnE,MAAI,iBAAiB,MACnB,MAAK,QAAQ;;;;;;;;;;CAYjB,OAAO,KAAK,OAAgB,gBAA+B;AAGzD,MAAI,gBAAgB,MAAM,CACxB,QAAO;AAET,SAAO,IAAI,gBAAgB,OAAO,eAAe;;;;;;;CAQnD,OAAO,WAAW,OAA0C;AAC1D,SACE,iBAAiB,SACjB,YAAY,SACZ,MAAM,cAAc"}
@@ -30,7 +30,7 @@ const isSendInput = (input) => typeof input === "object" && input != null && "lg
30
30
  * This allows the LLM to see the error and potentially retry with different arguments.
31
31
  */
32
32
  function defaultHandleToolErrors(error, toolCall) {
33
- if (error instanceof require_errors.ToolInvocationError) return new _langchain_core_messages.ToolMessage({
33
+ if (require_errors.ToolInvocationError.isInstance(error)) return new _langchain_core_messages.ToolMessage({
34
34
  content: error.message,
35
35
  tool_call_id: toolCall.id,
36
36
  name: toolCall.name
@@ -126,33 +126,51 @@ var ToolNode = class extends require_RunnableCallable.RunnableCallable {
126
126
  */
127
127
  if (this.signal?.aborted) throw error;
128
128
  /**
129
+ * A recoverable tool error (e.g. tool-input schema validation) can be
130
+ * rewrapped as a {@link MiddlewareError} with the original error on `.cause`
131
+ * — once per `wrapToolCall` middleware, so it may be nested several layers
132
+ * deep. Walk the cause chain to the root; if it's a {@link ToolInvocationError},
133
+ * unwrap it so the intended `handleToolErrors` self-correction path still
134
+ * applies. Genuine middleware errors stay fatal by default.
135
+ */
136
+ let effectiveError = error;
137
+ let errorFromMiddleware = isMiddlewareError;
138
+ if (isMiddlewareError) {
139
+ let unwrapped = error;
140
+ while (require_errors.MiddlewareError.isInstance(unwrapped)) unwrapped = unwrapped.cause;
141
+ if (require_errors.ToolInvocationError.isInstance(unwrapped)) {
142
+ effectiveError = unwrapped;
143
+ errorFromMiddleware = false;
144
+ }
145
+ }
146
+ /**
129
147
  * If error is from middleware and handleToolErrors is not true, bubble up
130
148
  * (default handler and false both re-raise middleware errors)
131
149
  */
132
- if (isMiddlewareError && this.handleToolErrors !== true) throw error;
150
+ if (errorFromMiddleware && this.handleToolErrors !== true) throw effectiveError;
133
151
  /**
134
152
  * If handleToolErrors is false, throw all errors
135
153
  */
136
- if (!this.handleToolErrors) throw error;
154
+ if (!this.handleToolErrors) throw effectiveError;
137
155
  /**
138
156
  * Apply handleToolErrors to the error
139
157
  */
140
158
  if (typeof this.handleToolErrors === "function") {
141
- const result = this.handleToolErrors(error, call);
159
+ const result = this.handleToolErrors(effectiveError, call);
142
160
  if (result && _langchain_core_messages.ToolMessage.isInstance(result)) return result;
143
161
  /**
144
162
  * `handleToolErrors` returned undefined - re-raise
145
163
  */
146
- throw error;
164
+ throw effectiveError;
147
165
  } else if (this.handleToolErrors) return new _langchain_core_messages.ToolMessage({
148
166
  name: call.name,
149
- content: `${error}\n Please fix your mistakes.`,
167
+ content: `${effectiveError}\n Please fix your mistakes.`,
150
168
  tool_call_id: call.id
151
169
  });
152
170
  /**
153
171
  * Shouldn't reach here, but throw as fallback
154
172
  */
155
- throw error;
173
+ throw effectiveError;
156
174
  }
157
175
  async runTool(call, config, state) {
158
176
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ToolNode.cjs","names":["BaseMessage","ToolInvocationError","ToolMessage","RunnableCallable","mergeAbortSignals","ToolInputParsingException","#handleError","AIMessage","isCommand","Command","Send"],"sources":["../../../src/agents/nodes/ToolNode.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\n/* oxlint-disable no-instanceof/no-instanceof */\nimport { BaseMessage, ToolMessage, AIMessage } from \"@langchain/core/messages\";\nimport { RunnableConfig, RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n DynamicTool,\n StructuredToolInterface,\n ToolInputParsingException,\n} from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport type { InteropZodObject } from \"@langchain/core/utils/types\";\nimport {\n isCommand,\n Command,\n Send,\n isGraphInterrupt,\n type LangGraphRunnableConfig,\n StateDefinitionInit,\n} from \"@langchain/langgraph\";\n\nimport { RunnableCallable } from \"../RunnableCallable.js\";\nimport { mergeAbortSignals } from \"./utils.js\";\nimport { ToolInvocationError } from \"../errors.js\";\nimport type {\n WrapToolCallHook,\n ToolCallRequest,\n ToAnnotationRoot,\n} from \"../middleware/types.js\";\nimport type { AgentBuiltInState } from \"../runtime.js\";\n\n/**\n * Error message template for when middleware adds tools that can't be executed.\n * This happens when middleware modifies tools in wrapModelCall but doesn't provide\n * a wrapToolCall handler to execute them.\n */\nconst getInvalidToolError = (\n toolName: string,\n availableTools: string[]\n): string =>\n `Error: ${toolName} is not a valid tool, try one of [${availableTools.join(\", \")}].`;\n\n/**\n * The name of the tool node in the state graph.\n */\nexport const TOOLS_NODE_NAME = \"tools\";\n\nexport interface ToolNodeOptions {\n /**\n * The name of the tool node.\n */\n name?: string;\n /**\n * The tags to add to the tool call.\n */\n tags?: string[];\n /**\n * The abort signal to cancel the tool call.\n */\n signal?: AbortSignal;\n /**\n * Whether to throw the error immediately if the tool fails or handle it by the `onToolError` function or via ToolMessage.\n *\n * **Default behavior** (matches Python):\n * - Catches only `ToolInvocationError` (invalid arguments from model) and converts to ToolMessage\n * - Re-raises all other errors including errors from `wrapToolCall` middleware\n *\n * If `true`:\n * - Catches all errors and returns a ToolMessage with the error\n *\n * If `false`:\n * - All errors are thrown immediately\n *\n * If a function is provided:\n * - If function returns a `ToolMessage`, use it as the result\n * - If function returns `undefined`, re-raise the error\n *\n * @default A function that only catches ToolInvocationError\n */\n handleToolErrors?:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined);\n /**\n * Optional wrapper function for tool execution.\n * Allows middleware to intercept and modify tool calls before execution.\n * The wrapper receives the tool call request and a handler function to execute the tool.\n */\n wrapToolCall?: WrapToolCallHook;\n}\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(BaseMessage.isInstance);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (\n input: unknown\n): input is { lg_tool_call: ToolCall; jumpTo?: string } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * Default error handler for tool errors.\n *\n * This is applied to errors from baseHandler (tool execution).\n * For errors from wrapToolCall middleware, those are handled separately\n * and will bubble up by default.\n *\n * Catches all tool execution errors and converts them to ToolMessage.\n * This allows the LLM to see the error and potentially retry with different arguments.\n */\nfunction defaultHandleToolErrors(\n error: unknown,\n toolCall: ToolCall\n): ToolMessage | undefined {\n if (error instanceof ToolInvocationError) {\n return new ToolMessage({\n content: error.message,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n }\n /**\n * Catch all other tool errors and convert to ToolMessage\n */\n return new ToolMessage({\n content: `${error}\\n Please fix your mistakes.`,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n}\n\n/**\n * `ToolNode` is a built-in LangGraph component that handles tool calls within an agent's workflow.\n * It works seamlessly with `createAgent`, offering advanced tool execution control, built\n * in parallelism, and error handling.\n *\n * @example\n * ```ts\n * import { ToolNode, tool, AIMessage } from \"langchain\";\n * import { z } from \"zod/v3\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n */\nexport class ToolNode<\n StateSchema extends StateDefinitionInit = any,\n ContextSchema extends InteropZodObject = any,\n> extends RunnableCallable<StateSchema, ContextSchema> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n trace = false;\n\n signal?: AbortSignal;\n\n handleToolErrors:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined) =\n defaultHandleToolErrors;\n\n wrapToolCall: WrapToolCallHook | undefined;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n public options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors, signal, wrapToolCall } =\n options ?? {};\n super({\n name,\n tags,\n func: (state, config) =>\n this.run(\n state as ToAnnotationRoot<StateDefinitionInit>[\"State\"] &\n AgentBuiltInState,\n config as RunnableConfig\n ),\n });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n this.signal = signal;\n this.wrapToolCall = wrapToolCall;\n }\n\n /**\n * Handle errors from tool execution or middleware.\n * @param error - The error to handle\n * @param call - The tool call that caused the error\n * @param isMiddlewareError - Whether the error came from wrapToolCall middleware\n * @returns ToolMessage if error is handled, otherwise re-throws\n */\n #handleError(\n error: unknown,\n call: ToolCall,\n isMiddlewareError: boolean\n ): ToolMessage {\n /**\n * {@link NodeInterrupt} errors are a breakpoint to bring a human into the loop.\n * As such, they are not recoverable by the agent and shouldn't be fed\n * back. Instead, re-throw these errors even when `handleToolErrors = true`.\n */\n if (isGraphInterrupt(error)) {\n throw error;\n }\n\n /**\n * If the signal is aborted, we want to bubble up the error to the invoke caller.\n */\n if (this.signal?.aborted) {\n throw error;\n }\n\n /**\n * If error is from middleware and handleToolErrors is not true, bubble up\n * (default handler and false both re-raise middleware errors)\n */\n if (isMiddlewareError && this.handleToolErrors !== true) {\n throw error;\n }\n\n /**\n * If handleToolErrors is false, throw all errors\n */\n if (!this.handleToolErrors) {\n throw error;\n }\n\n /**\n * Apply handleToolErrors to the error\n */\n if (typeof this.handleToolErrors === \"function\") {\n const result = this.handleToolErrors(error, call);\n if (result && ToolMessage.isInstance(result)) {\n return result;\n }\n\n /**\n * `handleToolErrors` returned undefined - re-raise\n */\n throw error;\n } else if (this.handleToolErrors) {\n return new ToolMessage({\n name: call.name,\n content: `${error}\\n Please fix your mistakes.`,\n tool_call_id: call.id!,\n });\n }\n\n /**\n * Shouldn't reach here, but throw as fallback\n */\n throw error;\n }\n\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig,\n state: AgentBuiltInState\n ): Promise<ToolMessage | Command> {\n /**\n * Build runtime from LangGraph config\n */\n const lgConfig = config as LangGraphRunnableConfig;\n const runtime = {\n context: lgConfig?.context,\n store: lgConfig?.store,\n configurable: lgConfig?.configurable,\n writer: lgConfig?.writer,\n interrupt: lgConfig?.interrupt,\n signal: lgConfig?.signal,\n };\n\n /**\n * Find the tool instance to include in the request.\n * For dynamically registered tools, this may be undefined.\n */\n const registeredTool = this.tools.find((t) => t.name === call.name);\n\n /**\n * Define the base handler that executes the tool.\n * When wrapToolCall middleware is present, this handler does NOT catch errors\n * so the middleware can handle them.\n * When no middleware, errors are caught and handled here.\n *\n * The handler now accepts an overridden tool from the request, allowing\n * middleware to provide tool implementations for dynamically registered tools.\n */\n const baseHandler = async (\n request: ToolCallRequest\n ): Promise<ToolMessage | Command> => {\n const { toolCall, tool: requestTool } = request;\n\n /**\n * Use the tool from the request (which may be overridden via spread syntax)\n * or fall back to finding it in registered tools.\n * This allows middleware to provide dynamic tool implementations.\n */\n const tool =\n requestTool ?? this.tools.find((t) => t.name === toolCall.name);\n\n if (tool === undefined) {\n /**\n * Tool not found - return a graceful error message rather than throwing.\n * This allows the LLM to see the error and potentially retry.\n */\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(toolCall.name, availableTools),\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n status: \"error\",\n });\n }\n\n /**\n * Cast tool to a common invokable type.\n * The tool can be from registered tools (StructuredToolInterface | DynamicTool | RunnableToolLike)\n * or from middleware override (ClientTool | ServerTool).\n */\n const invokableTool = tool as\n | StructuredToolInterface\n | DynamicTool\n | RunnableToolLike;\n\n try {\n const output = await invokableTool.invoke(\n { ...toolCall, type: \"tool_call\" },\n {\n ...config,\n /**\n * extend to match ToolRuntime\n */\n config,\n toolCallId: toolCall.id!,\n state: config.configurable?.__pregel_scratchpad?.currentTaskInput,\n signal: mergeAbortSignals(this.signal, config.signal),\n }\n );\n\n if (ToolMessage.isInstance(output) || isCommand(output)) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n name: invokableTool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: toolCall.id!,\n });\n } catch (e: unknown) {\n /**\n * Handle errors from tool execution (not from wrapToolCall)\n * If tool invocation fails due to input parsing error, throw a {@link ToolInvocationError}\n */\n if (e instanceof ToolInputParsingException) {\n throw new ToolInvocationError(e, toolCall);\n }\n /**\n * Re-throw to be handled by caller\n */\n throw e;\n }\n };\n\n /**\n * Create request object for middleware\n * Cast to ToolCallRequest<AgentBuiltInState> to satisfy type constraints\n * of wrapToolCall which expects AgentBuiltInState\n */\n const request: ToolCallRequest<AgentBuiltInState> = {\n toolCall: call,\n tool: registeredTool,\n state,\n runtime,\n };\n\n /**\n * If wrapToolCall is provided, use it to wrap the tool execution\n */\n if (this.wrapToolCall) {\n try {\n return await this.wrapToolCall(request, baseHandler);\n } catch (e: unknown) {\n /**\n * Handle middleware errors\n */\n return this.#handleError(e, call, true);\n }\n }\n\n /**\n * No wrapToolCall - if tool wasn't found, return graceful error\n */\n if (!registeredTool) {\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(call.name, availableTools),\n tool_call_id: call.id!,\n name: call.name,\n status: \"error\",\n });\n }\n\n /**\n * No wrapToolCall - execute tool directly and handle errors here\n */\n try {\n return await baseHandler(request);\n } catch (e: unknown) {\n /**\n * Handle tool errors when no middleware provided\n */\n return this.#handleError(e, call, false);\n }\n }\n\n protected async run(\n state: ToAnnotationRoot<StateSchema>[\"State\"] & AgentBuiltInState,\n config: RunnableConfig\n ): Promise<ContextSchema> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(state)) {\n const { lg_tool_call: _, jumpTo: __, ...newState } = state;\n outputs = [await this.runTool(state.lg_tool_call, config, newState)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(state)) {\n messages = state;\n } else if (isMessagesState(state)) {\n messages = state.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (AIMessage.isInstance(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (!AIMessage.isInstance(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config, state)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(state)\n ? outputs\n : { messages: outputs }) as unknown as ContextSchema;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(state) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as unknown as ContextSchema;\n }\n}\n\nexport function isSend(x: unknown): x is Send {\n return x instanceof Send;\n}\n"],"mappings":";;;;;;;;;;;;;AAmCA,MAAM,uBACJ,UACA,mBAEA,UAAU,SAAS,oCAAoC,eAAe,KAAK,KAAK,CAAC;;;;AAKnF,MAAa,kBAAkB;AA6C/B,MAAM,sBAAsB,UAC1B,MAAM,QAAQ,MAAM,IAAI,MAAM,MAAMA,yBAAAA,YAAY,WAAW;AAE7D,MAAM,mBACJ,UAEA,OAAO,UAAU,YACjB,SAAS,QACT,cAAc,SACd,mBAAmB,MAAM,SAAS;AAEpC,MAAM,eACJ,UAEA,OAAO,UAAU,YAAY,SAAS,QAAQ,kBAAkB;;;;;;;;;;;AAYlE,SAAS,wBACP,OACA,UACyB;AACzB,KAAI,iBAAiBC,eAAAA,oBACnB,QAAO,IAAIC,yBAAAA,YAAY;EACrB,SAAS,MAAM;EACf,cAAc,SAAS;EACvB,MAAM,SAAS;EAChB,CAAC;;;;AAKJ,QAAO,IAAIA,yBAAAA,YAAY;EACrB,SAAS,GAAG,MAAM;EAClB,cAAc,SAAS;EACvB,MAAM,SAAS;EAChB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CJ,IAAa,WAAb,cAGUC,yBAAAA,iBAA6C;CACrD;CAEA,QAAQ;CAER;CAEA,mBAGE;CAEF;CAEA,YACE,OACA,SACA;EACA,MAAM,EAAE,MAAM,MAAM,kBAAkB,QAAQ,iBAC5C,WAAW,EAAE;AACf,QAAM;GACJ;GACA;GACA,OAAO,OAAO,WACZ,KAAK,IACH,OAEA,OACD;GACJ,CAAC;AAbK,OAAA,UAAA;AAcP,OAAK,QAAQ;AACb,OAAK,mBAAmB,oBAAoB,KAAK;AACjD,OAAK,SAAS;AACd,OAAK,eAAe;;;;;;;;;CAUtB,aACE,OACA,MACA,mBACa;;;;;;AAMb,OAAA,GAAA,qBAAA,kBAAqB,MAAM,CACzB,OAAM;;;;AAMR,MAAI,KAAK,QAAQ,QACf,OAAM;;;;;AAOR,MAAI,qBAAqB,KAAK,qBAAqB,KACjD,OAAM;;;;AAMR,MAAI,CAAC,KAAK,iBACR,OAAM;;;;AAMR,MAAI,OAAO,KAAK,qBAAqB,YAAY;GAC/C,MAAM,SAAS,KAAK,iBAAiB,OAAO,KAAK;AACjD,OAAI,UAAUD,yBAAAA,YAAY,WAAW,OAAO,CAC1C,QAAO;;;;AAMT,SAAM;aACG,KAAK,iBACd,QAAO,IAAIA,yBAAAA,YAAY;GACrB,MAAM,KAAK;GACX,SAAS,GAAG,MAAM;GAClB,cAAc,KAAK;GACpB,CAAC;;;;AAMJ,QAAM;;CAGR,MAAgB,QACd,MACA,QACA,OACgC;;;;EAIhC,MAAM,WAAW;EACjB,MAAM,UAAU;GACd,SAAS,UAAU;GACnB,OAAO,UAAU;GACjB,cAAc,UAAU;GACxB,QAAQ,UAAU;GAClB,WAAW,UAAU;GACrB,QAAQ,UAAU;GACnB;;;;;EAMD,MAAM,iBAAiB,KAAK,MAAM,MAAM,MAAM,EAAE,SAAS,KAAK,KAAK;;;;;;;;;;EAWnE,MAAM,cAAc,OAClB,YACmC;GACnC,MAAM,EAAE,UAAU,MAAM,gBAAgB;;;;;;GAOxC,MAAM,OACJ,eAAe,KAAK,MAAM,MAAM,MAAM,EAAE,SAAS,SAAS,KAAK;AAEjE,OAAI,SAAS,KAAA,GAAW;;;;;IAKtB,MAAM,iBAAiB,KAAK,MAAM,KAAK,MAAM,EAAE,KAAK;AACpD,WAAO,IAAIA,yBAAAA,YAAY;KACrB,SAAS,oBAAoB,SAAS,MAAM,eAAe;KAC3D,cAAc,SAAS;KACvB,MAAM,SAAS;KACf,QAAQ;KACT,CAAC;;;;;;;GAQJ,MAAM,gBAAgB;AAKtB,OAAI;IACF,MAAM,SAAS,MAAM,cAAc,OACjC;KAAE,GAAG;KAAU,MAAM;KAAa,EAClC;KACE,GAAG;;;;KAIH;KACA,YAAY,SAAS;KACrB,OAAO,OAAO,cAAc,qBAAqB;KACjD,QAAQE,cAAAA,kBAAkB,KAAK,QAAQ,OAAO,OAAO;KACtD,CACF;AAED,QAAIF,yBAAAA,YAAY,WAAW,OAAO,KAAA,GAAA,qBAAA,WAAc,OAAO,CACrD,QAAO;AAGT,WAAO,IAAIA,yBAAAA,YAAY;KACrB,MAAM,cAAc;KACpB,SAAS,OAAO,WAAW,WAAW,SAAS,KAAK,UAAU,OAAO;KACrE,cAAc,SAAS;KACxB,CAAC;YACK,GAAY;;;;;AAKnB,QAAI,aAAaG,sBAAAA,0BACf,OAAM,IAAIJ,eAAAA,oBAAoB,GAAG,SAAS;;;;AAK5C,UAAM;;;;;;;;EASV,MAAM,UAA8C;GAClD,UAAU;GACV,MAAM;GACN;GACA;GACD;;;;AAKD,MAAI,KAAK,aACP,KAAI;AACF,UAAO,MAAM,KAAK,aAAa,SAAS,YAAY;WAC7C,GAAY;;;;AAInB,UAAO,MAAA,YAAkB,GAAG,MAAM,KAAK;;;;;AAO3C,MAAI,CAAC,gBAAgB;GACnB,MAAM,iBAAiB,KAAK,MAAM,KAAK,MAAM,EAAE,KAAK;AACpD,UAAO,IAAIC,yBAAAA,YAAY;IACrB,SAAS,oBAAoB,KAAK,MAAM,eAAe;IACvD,cAAc,KAAK;IACnB,MAAM,KAAK;IACX,QAAQ;IACT,CAAC;;;;;AAMJ,MAAI;AACF,UAAO,MAAM,YAAY,QAAQ;WAC1B,GAAY;;;;AAInB,UAAO,MAAA,YAAkB,GAAG,MAAM,MAAM;;;CAI5C,MAAgB,IACd,OACA,QACwB;EACxB,IAAI;AAEJ,MAAI,YAAY,MAAM,EAAE;GACtB,MAAM,EAAE,cAAc,GAAG,QAAQ,IAAI,GAAG,aAAa;AACrD,aAAU,CAAC,MAAM,KAAK,QAAQ,MAAM,cAAc,QAAQ,SAAS,CAAC;SAC/D;GACL,IAAI;AACJ,OAAI,mBAAmB,MAAM,CAC3B,YAAW;YACF,gBAAgB,MAAM,CAC/B,YAAW,MAAM;OAEjB,OAAM,IAAI,MACR,+EACD;GAGH,MAAM,iBAA8B,IAAI,IACtC,SACG,QAAQ,QAAQ,IAAI,SAAS,KAAK,OAAO,CACzC,KAAK,QAAS,IAAoB,aAAa,CACnD;GAED,IAAI;AACJ,QAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK,GAAG;IAChD,MAAM,UAAU,SAAS;AACzB,QAAIK,yBAAAA,UAAU,WAAW,QAAQ,EAAE;AACjC,iBAAY;AACZ;;;AAIJ,OAAI,CAACA,yBAAAA,UAAU,WAAW,UAAU,CAClC,OAAM,IAAI,MAAM,6CAA6C;AAG/D,aAAU,MAAM,QAAQ,IACtB,UAAU,YACN,QAAQ,SAAS,KAAK,MAAM,QAAQ,CAAC,eAAe,IAAI,KAAK,GAAG,CAAC,CAClE,KAAK,SAAS,KAAK,QAAQ,MAAM,QAAQ,MAAM,CAAC,IAAI,EAAE,CAC1D;;AAIH,MAAI,CAAC,QAAQ,KAAKC,qBAAAA,UAAU,CAC1B,QAAQ,MAAM,QAAQ,MAAM,GACxB,UACA,EAAE,UAAU,SAAS;EAI3B,MAAM,kBAIA,EAAE;EACR,IAAI,gBAAgC;AAEpC,OAAK,MAAM,UAAU,QACnB,MAAA,GAAA,qBAAA,WAAc,OAAO,CACnB,KACE,OAAO,UAAUC,qBAAAA,QAAQ,UACzB,MAAM,QAAQ,OAAO,KAAK,IAC1B,OAAO,KAAK,OAAO,SAAS,OAAO,KAAK,CAAC,CAEzC,KAAI,cACD,eAAc,KAAgB,KAAK,GAAI,OAAO,KAAgB;MAE/D,iBAAgB,IAAIA,qBAAAA,QAAQ;GAC1B,OAAOA,qBAAAA,QAAQ;GACf,MAAM,OAAO;GACd,CAAC;MAGJ,iBAAgB,KAAK,OAAO;MAG9B,iBAAgB,KACd,MAAM,QAAQ,MAAM,GAAG,CAAC,OAAO,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,CACzD;AAIL,MAAI,cACF,iBAAgB,KAAK,cAAc;AAGrC,SAAO;;;AAIX,SAAgB,OAAO,GAAuB;AAC5C,QAAO,aAAaC,qBAAAA"}
1
+ {"version":3,"file":"ToolNode.cjs","names":["BaseMessage","ToolInvocationError","ToolMessage","RunnableCallable","MiddlewareError","mergeAbortSignals","ToolInputParsingException","#handleError","AIMessage","isCommand","Command","Send"],"sources":["../../../src/agents/nodes/ToolNode.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\n/* oxlint-disable no-instanceof/no-instanceof */\nimport { BaseMessage, ToolMessage, AIMessage } from \"@langchain/core/messages\";\nimport { RunnableConfig, RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n DynamicTool,\n StructuredToolInterface,\n ToolInputParsingException,\n} from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport type { InteropZodObject } from \"@langchain/core/utils/types\";\nimport {\n isCommand,\n Command,\n Send,\n isGraphInterrupt,\n type LangGraphRunnableConfig,\n StateDefinitionInit,\n} from \"@langchain/langgraph\";\n\nimport { RunnableCallable } from \"../RunnableCallable.js\";\nimport { mergeAbortSignals } from \"./utils.js\";\nimport { MiddlewareError, ToolInvocationError } from \"../errors.js\";\nimport type {\n WrapToolCallHook,\n ToolCallRequest,\n ToAnnotationRoot,\n} from \"../middleware/types.js\";\nimport type { AgentBuiltInState } from \"../runtime.js\";\n\n/**\n * Error message template for when middleware adds tools that can't be executed.\n * This happens when middleware modifies tools in wrapModelCall but doesn't provide\n * a wrapToolCall handler to execute them.\n */\nconst getInvalidToolError = (\n toolName: string,\n availableTools: string[]\n): string =>\n `Error: ${toolName} is not a valid tool, try one of [${availableTools.join(\", \")}].`;\n\n/**\n * The name of the tool node in the state graph.\n */\nexport const TOOLS_NODE_NAME = \"tools\";\n\nexport interface ToolNodeOptions {\n /**\n * The name of the tool node.\n */\n name?: string;\n /**\n * The tags to add to the tool call.\n */\n tags?: string[];\n /**\n * The abort signal to cancel the tool call.\n */\n signal?: AbortSignal;\n /**\n * Whether to throw the error immediately if the tool fails or handle it by the `onToolError` function or via ToolMessage.\n *\n * **Default behavior** (matches Python):\n * - Catches only `ToolInvocationError` (invalid arguments from model) and converts to ToolMessage\n * - Re-raises all other errors including errors from `wrapToolCall` middleware\n *\n * If `true`:\n * - Catches all errors and returns a ToolMessage with the error\n *\n * If `false`:\n * - All errors are thrown immediately\n *\n * If a function is provided:\n * - If function returns a `ToolMessage`, use it as the result\n * - If function returns `undefined`, re-raise the error\n *\n * @default A function that only catches ToolInvocationError\n */\n handleToolErrors?:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined);\n /**\n * Optional wrapper function for tool execution.\n * Allows middleware to intercept and modify tool calls before execution.\n * The wrapper receives the tool call request and a handler function to execute the tool.\n */\n wrapToolCall?: WrapToolCallHook;\n}\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(BaseMessage.isInstance);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (\n input: unknown\n): input is { lg_tool_call: ToolCall; jumpTo?: string } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * Default error handler for tool errors.\n *\n * This is applied to errors from baseHandler (tool execution).\n * For errors from wrapToolCall middleware, those are handled separately\n * and will bubble up by default.\n *\n * Catches all tool execution errors and converts them to ToolMessage.\n * This allows the LLM to see the error and potentially retry with different arguments.\n */\nfunction defaultHandleToolErrors(\n error: unknown,\n toolCall: ToolCall\n): ToolMessage | undefined {\n if (ToolInvocationError.isInstance(error)) {\n return new ToolMessage({\n content: error.message,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n }\n /**\n * Catch all other tool errors and convert to ToolMessage\n */\n return new ToolMessage({\n content: `${error}\\n Please fix your mistakes.`,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n}\n\n/**\n * `ToolNode` is a built-in LangGraph component that handles tool calls within an agent's workflow.\n * It works seamlessly with `createAgent`, offering advanced tool execution control, built\n * in parallelism, and error handling.\n *\n * @example\n * ```ts\n * import { ToolNode, tool, AIMessage } from \"langchain\";\n * import { z } from \"zod/v3\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n */\nexport class ToolNode<\n StateSchema extends StateDefinitionInit = any,\n ContextSchema extends InteropZodObject = any,\n> extends RunnableCallable<StateSchema, ContextSchema> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n trace = false;\n\n signal?: AbortSignal;\n\n handleToolErrors:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined) =\n defaultHandleToolErrors;\n\n wrapToolCall: WrapToolCallHook | undefined;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n public options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors, signal, wrapToolCall } =\n options ?? {};\n super({\n name,\n tags,\n func: (state, config) =>\n this.run(\n state as ToAnnotationRoot<StateDefinitionInit>[\"State\"] &\n AgentBuiltInState,\n config as RunnableConfig\n ),\n });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n this.signal = signal;\n this.wrapToolCall = wrapToolCall;\n }\n\n /**\n * Handle errors from tool execution or middleware.\n * @param error - The error to handle\n * @param call - The tool call that caused the error\n * @param isMiddlewareError - Whether the error came from wrapToolCall middleware\n * @returns ToolMessage if error is handled, otherwise re-throws\n */\n #handleError(\n error: unknown,\n call: ToolCall,\n isMiddlewareError: boolean\n ): ToolMessage {\n /**\n * {@link NodeInterrupt} errors are a breakpoint to bring a human into the loop.\n * As such, they are not recoverable by the agent and shouldn't be fed\n * back. Instead, re-throw these errors even when `handleToolErrors = true`.\n */\n if (isGraphInterrupt(error)) {\n throw error;\n }\n\n /**\n * If the signal is aborted, we want to bubble up the error to the invoke caller.\n */\n if (this.signal?.aborted) {\n throw error;\n }\n\n /**\n * A recoverable tool error (e.g. tool-input schema validation) can be\n * rewrapped as a {@link MiddlewareError} with the original error on `.cause`\n * — once per `wrapToolCall` middleware, so it may be nested several layers\n * deep. Walk the cause chain to the root; if it's a {@link ToolInvocationError},\n * unwrap it so the intended `handleToolErrors` self-correction path still\n * applies. Genuine middleware errors stay fatal by default.\n */\n let effectiveError = error;\n let errorFromMiddleware = isMiddlewareError;\n if (isMiddlewareError) {\n let unwrapped: unknown = error;\n while (MiddlewareError.isInstance(unwrapped)) {\n unwrapped = unwrapped.cause;\n }\n if (ToolInvocationError.isInstance(unwrapped)) {\n effectiveError = unwrapped;\n errorFromMiddleware = false;\n }\n }\n\n /**\n * If error is from middleware and handleToolErrors is not true, bubble up\n * (default handler and false both re-raise middleware errors)\n */\n if (errorFromMiddleware && this.handleToolErrors !== true) {\n throw effectiveError;\n }\n\n /**\n * If handleToolErrors is false, throw all errors\n */\n if (!this.handleToolErrors) {\n throw effectiveError;\n }\n\n /**\n * Apply handleToolErrors to the error\n */\n if (typeof this.handleToolErrors === \"function\") {\n const result = this.handleToolErrors(effectiveError, call);\n if (result && ToolMessage.isInstance(result)) {\n return result;\n }\n\n /**\n * `handleToolErrors` returned undefined - re-raise\n */\n throw effectiveError;\n } else if (this.handleToolErrors) {\n return new ToolMessage({\n name: call.name,\n content: `${effectiveError}\\n Please fix your mistakes.`,\n tool_call_id: call.id!,\n });\n }\n\n /**\n * Shouldn't reach here, but throw as fallback\n */\n throw effectiveError;\n }\n\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig,\n state: AgentBuiltInState\n ): Promise<ToolMessage | Command> {\n /**\n * Build runtime from LangGraph config\n */\n const lgConfig = config as LangGraphRunnableConfig;\n const runtime = {\n context: lgConfig?.context,\n store: lgConfig?.store,\n configurable: lgConfig?.configurable,\n writer: lgConfig?.writer,\n interrupt: lgConfig?.interrupt,\n signal: lgConfig?.signal,\n };\n\n /**\n * Find the tool instance to include in the request.\n * For dynamically registered tools, this may be undefined.\n */\n const registeredTool = this.tools.find((t) => t.name === call.name);\n\n /**\n * Define the base handler that executes the tool.\n * When wrapToolCall middleware is present, this handler does NOT catch errors\n * so the middleware can handle them.\n * When no middleware, errors are caught and handled here.\n *\n * The handler now accepts an overridden tool from the request, allowing\n * middleware to provide tool implementations for dynamically registered tools.\n */\n const baseHandler = async (\n request: ToolCallRequest\n ): Promise<ToolMessage | Command> => {\n const { toolCall, tool: requestTool } = request;\n\n /**\n * Use the tool from the request (which may be overridden via spread syntax)\n * or fall back to finding it in registered tools.\n * This allows middleware to provide dynamic tool implementations.\n */\n const tool =\n requestTool ?? this.tools.find((t) => t.name === toolCall.name);\n\n if (tool === undefined) {\n /**\n * Tool not found - return a graceful error message rather than throwing.\n * This allows the LLM to see the error and potentially retry.\n */\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(toolCall.name, availableTools),\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n status: \"error\",\n });\n }\n\n /**\n * Cast tool to a common invokable type.\n * The tool can be from registered tools (StructuredToolInterface | DynamicTool | RunnableToolLike)\n * or from middleware override (ClientTool | ServerTool).\n */\n const invokableTool = tool as\n | StructuredToolInterface\n | DynamicTool\n | RunnableToolLike;\n\n try {\n const output = await invokableTool.invoke(\n { ...toolCall, type: \"tool_call\" },\n {\n ...config,\n /**\n * extend to match ToolRuntime\n */\n config,\n toolCallId: toolCall.id!,\n state: config.configurable?.__pregel_scratchpad?.currentTaskInput,\n signal: mergeAbortSignals(this.signal, config.signal),\n }\n );\n\n if (ToolMessage.isInstance(output) || isCommand(output)) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n name: invokableTool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: toolCall.id!,\n });\n } catch (e: unknown) {\n /**\n * Handle errors from tool execution (not from wrapToolCall)\n * If tool invocation fails due to input parsing error, throw a {@link ToolInvocationError}\n */\n if (e instanceof ToolInputParsingException) {\n throw new ToolInvocationError(e, toolCall);\n }\n /**\n * Re-throw to be handled by caller\n */\n throw e;\n }\n };\n\n /**\n * Create request object for middleware\n * Cast to ToolCallRequest<AgentBuiltInState> to satisfy type constraints\n * of wrapToolCall which expects AgentBuiltInState\n */\n const request: ToolCallRequest<AgentBuiltInState> = {\n toolCall: call,\n tool: registeredTool,\n state,\n runtime,\n };\n\n /**\n * If wrapToolCall is provided, use it to wrap the tool execution\n */\n if (this.wrapToolCall) {\n try {\n return await this.wrapToolCall(request, baseHandler);\n } catch (e: unknown) {\n /**\n * Handle middleware errors\n */\n return this.#handleError(e, call, true);\n }\n }\n\n /**\n * No wrapToolCall - if tool wasn't found, return graceful error\n */\n if (!registeredTool) {\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(call.name, availableTools),\n tool_call_id: call.id!,\n name: call.name,\n status: \"error\",\n });\n }\n\n /**\n * No wrapToolCall - execute tool directly and handle errors here\n */\n try {\n return await baseHandler(request);\n } catch (e: unknown) {\n /**\n * Handle tool errors when no middleware provided\n */\n return this.#handleError(e, call, false);\n }\n }\n\n protected async run(\n state: ToAnnotationRoot<StateSchema>[\"State\"] & AgentBuiltInState,\n config: RunnableConfig\n ): Promise<ContextSchema> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(state)) {\n const { lg_tool_call: _, jumpTo: __, ...newState } = state;\n outputs = [await this.runTool(state.lg_tool_call, config, newState)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(state)) {\n messages = state;\n } else if (isMessagesState(state)) {\n messages = state.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (AIMessage.isInstance(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (!AIMessage.isInstance(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config, state)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(state)\n ? outputs\n : { messages: outputs }) as unknown as ContextSchema;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(state) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as unknown as ContextSchema;\n }\n}\n\nexport function isSend(x: unknown): x is Send {\n return x instanceof Send;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ToolInvocationError } from "../errors.js";
1
+ import { MiddlewareError, ToolInvocationError } from "../errors.js";
2
2
  import { RunnableCallable } from "../RunnableCallable.js";
3
3
  import { mergeAbortSignals } from "./utils.js";
4
4
  import { AIMessage, BaseMessage, ToolMessage } from "@langchain/core/messages";
@@ -29,7 +29,7 @@ const isSendInput = (input) => typeof input === "object" && input != null && "lg
29
29
  * This allows the LLM to see the error and potentially retry with different arguments.
30
30
  */
31
31
  function defaultHandleToolErrors(error, toolCall) {
32
- if (error instanceof ToolInvocationError) return new ToolMessage({
32
+ if (ToolInvocationError.isInstance(error)) return new ToolMessage({
33
33
  content: error.message,
34
34
  tool_call_id: toolCall.id,
35
35
  name: toolCall.name
@@ -125,33 +125,51 @@ var ToolNode = class extends RunnableCallable {
125
125
  */
126
126
  if (this.signal?.aborted) throw error;
127
127
  /**
128
+ * A recoverable tool error (e.g. tool-input schema validation) can be
129
+ * rewrapped as a {@link MiddlewareError} with the original error on `.cause`
130
+ * — once per `wrapToolCall` middleware, so it may be nested several layers
131
+ * deep. Walk the cause chain to the root; if it's a {@link ToolInvocationError},
132
+ * unwrap it so the intended `handleToolErrors` self-correction path still
133
+ * applies. Genuine middleware errors stay fatal by default.
134
+ */
135
+ let effectiveError = error;
136
+ let errorFromMiddleware = isMiddlewareError;
137
+ if (isMiddlewareError) {
138
+ let unwrapped = error;
139
+ while (MiddlewareError.isInstance(unwrapped)) unwrapped = unwrapped.cause;
140
+ if (ToolInvocationError.isInstance(unwrapped)) {
141
+ effectiveError = unwrapped;
142
+ errorFromMiddleware = false;
143
+ }
144
+ }
145
+ /**
128
146
  * If error is from middleware and handleToolErrors is not true, bubble up
129
147
  * (default handler and false both re-raise middleware errors)
130
148
  */
131
- if (isMiddlewareError && this.handleToolErrors !== true) throw error;
149
+ if (errorFromMiddleware && this.handleToolErrors !== true) throw effectiveError;
132
150
  /**
133
151
  * If handleToolErrors is false, throw all errors
134
152
  */
135
- if (!this.handleToolErrors) throw error;
153
+ if (!this.handleToolErrors) throw effectiveError;
136
154
  /**
137
155
  * Apply handleToolErrors to the error
138
156
  */
139
157
  if (typeof this.handleToolErrors === "function") {
140
- const result = this.handleToolErrors(error, call);
158
+ const result = this.handleToolErrors(effectiveError, call);
141
159
  if (result && ToolMessage.isInstance(result)) return result;
142
160
  /**
143
161
  * `handleToolErrors` returned undefined - re-raise
144
162
  */
145
- throw error;
163
+ throw effectiveError;
146
164
  } else if (this.handleToolErrors) return new ToolMessage({
147
165
  name: call.name,
148
- content: `${error}\n Please fix your mistakes.`,
166
+ content: `${effectiveError}\n Please fix your mistakes.`,
149
167
  tool_call_id: call.id
150
168
  });
151
169
  /**
152
170
  * Shouldn't reach here, but throw as fallback
153
171
  */
154
- throw error;
172
+ throw effectiveError;
155
173
  }
156
174
  async runTool(call, config, state) {
157
175
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ToolNode.js","names":["#handleError"],"sources":["../../../src/agents/nodes/ToolNode.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\n/* oxlint-disable no-instanceof/no-instanceof */\nimport { BaseMessage, ToolMessage, AIMessage } from \"@langchain/core/messages\";\nimport { RunnableConfig, RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n DynamicTool,\n StructuredToolInterface,\n ToolInputParsingException,\n} from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport type { InteropZodObject } from \"@langchain/core/utils/types\";\nimport {\n isCommand,\n Command,\n Send,\n isGraphInterrupt,\n type LangGraphRunnableConfig,\n StateDefinitionInit,\n} from \"@langchain/langgraph\";\n\nimport { RunnableCallable } from \"../RunnableCallable.js\";\nimport { mergeAbortSignals } from \"./utils.js\";\nimport { ToolInvocationError } from \"../errors.js\";\nimport type {\n WrapToolCallHook,\n ToolCallRequest,\n ToAnnotationRoot,\n} from \"../middleware/types.js\";\nimport type { AgentBuiltInState } from \"../runtime.js\";\n\n/**\n * Error message template for when middleware adds tools that can't be executed.\n * This happens when middleware modifies tools in wrapModelCall but doesn't provide\n * a wrapToolCall handler to execute them.\n */\nconst getInvalidToolError = (\n toolName: string,\n availableTools: string[]\n): string =>\n `Error: ${toolName} is not a valid tool, try one of [${availableTools.join(\", \")}].`;\n\n/**\n * The name of the tool node in the state graph.\n */\nexport const TOOLS_NODE_NAME = \"tools\";\n\nexport interface ToolNodeOptions {\n /**\n * The name of the tool node.\n */\n name?: string;\n /**\n * The tags to add to the tool call.\n */\n tags?: string[];\n /**\n * The abort signal to cancel the tool call.\n */\n signal?: AbortSignal;\n /**\n * Whether to throw the error immediately if the tool fails or handle it by the `onToolError` function or via ToolMessage.\n *\n * **Default behavior** (matches Python):\n * - Catches only `ToolInvocationError` (invalid arguments from model) and converts to ToolMessage\n * - Re-raises all other errors including errors from `wrapToolCall` middleware\n *\n * If `true`:\n * - Catches all errors and returns a ToolMessage with the error\n *\n * If `false`:\n * - All errors are thrown immediately\n *\n * If a function is provided:\n * - If function returns a `ToolMessage`, use it as the result\n * - If function returns `undefined`, re-raise the error\n *\n * @default A function that only catches ToolInvocationError\n */\n handleToolErrors?:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined);\n /**\n * Optional wrapper function for tool execution.\n * Allows middleware to intercept and modify tool calls before execution.\n * The wrapper receives the tool call request and a handler function to execute the tool.\n */\n wrapToolCall?: WrapToolCallHook;\n}\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(BaseMessage.isInstance);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (\n input: unknown\n): input is { lg_tool_call: ToolCall; jumpTo?: string } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * Default error handler for tool errors.\n *\n * This is applied to errors from baseHandler (tool execution).\n * For errors from wrapToolCall middleware, those are handled separately\n * and will bubble up by default.\n *\n * Catches all tool execution errors and converts them to ToolMessage.\n * This allows the LLM to see the error and potentially retry with different arguments.\n */\nfunction defaultHandleToolErrors(\n error: unknown,\n toolCall: ToolCall\n): ToolMessage | undefined {\n if (error instanceof ToolInvocationError) {\n return new ToolMessage({\n content: error.message,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n }\n /**\n * Catch all other tool errors and convert to ToolMessage\n */\n return new ToolMessage({\n content: `${error}\\n Please fix your mistakes.`,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n}\n\n/**\n * `ToolNode` is a built-in LangGraph component that handles tool calls within an agent's workflow.\n * It works seamlessly with `createAgent`, offering advanced tool execution control, built\n * in parallelism, and error handling.\n *\n * @example\n * ```ts\n * import { ToolNode, tool, AIMessage } from \"langchain\";\n * import { z } from \"zod/v3\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n */\nexport class ToolNode<\n StateSchema extends StateDefinitionInit = any,\n ContextSchema extends InteropZodObject = any,\n> extends RunnableCallable<StateSchema, ContextSchema> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n trace = false;\n\n signal?: AbortSignal;\n\n handleToolErrors:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined) =\n defaultHandleToolErrors;\n\n wrapToolCall: WrapToolCallHook | undefined;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n public options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors, signal, wrapToolCall } =\n options ?? {};\n super({\n name,\n tags,\n func: (state, config) =>\n this.run(\n state as ToAnnotationRoot<StateDefinitionInit>[\"State\"] &\n AgentBuiltInState,\n config as RunnableConfig\n ),\n });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n this.signal = signal;\n this.wrapToolCall = wrapToolCall;\n }\n\n /**\n * Handle errors from tool execution or middleware.\n * @param error - The error to handle\n * @param call - The tool call that caused the error\n * @param isMiddlewareError - Whether the error came from wrapToolCall middleware\n * @returns ToolMessage if error is handled, otherwise re-throws\n */\n #handleError(\n error: unknown,\n call: ToolCall,\n isMiddlewareError: boolean\n ): ToolMessage {\n /**\n * {@link NodeInterrupt} errors are a breakpoint to bring a human into the loop.\n * As such, they are not recoverable by the agent and shouldn't be fed\n * back. Instead, re-throw these errors even when `handleToolErrors = true`.\n */\n if (isGraphInterrupt(error)) {\n throw error;\n }\n\n /**\n * If the signal is aborted, we want to bubble up the error to the invoke caller.\n */\n if (this.signal?.aborted) {\n throw error;\n }\n\n /**\n * If error is from middleware and handleToolErrors is not true, bubble up\n * (default handler and false both re-raise middleware errors)\n */\n if (isMiddlewareError && this.handleToolErrors !== true) {\n throw error;\n }\n\n /**\n * If handleToolErrors is false, throw all errors\n */\n if (!this.handleToolErrors) {\n throw error;\n }\n\n /**\n * Apply handleToolErrors to the error\n */\n if (typeof this.handleToolErrors === \"function\") {\n const result = this.handleToolErrors(error, call);\n if (result && ToolMessage.isInstance(result)) {\n return result;\n }\n\n /**\n * `handleToolErrors` returned undefined - re-raise\n */\n throw error;\n } else if (this.handleToolErrors) {\n return new ToolMessage({\n name: call.name,\n content: `${error}\\n Please fix your mistakes.`,\n tool_call_id: call.id!,\n });\n }\n\n /**\n * Shouldn't reach here, but throw as fallback\n */\n throw error;\n }\n\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig,\n state: AgentBuiltInState\n ): Promise<ToolMessage | Command> {\n /**\n * Build runtime from LangGraph config\n */\n const lgConfig = config as LangGraphRunnableConfig;\n const runtime = {\n context: lgConfig?.context,\n store: lgConfig?.store,\n configurable: lgConfig?.configurable,\n writer: lgConfig?.writer,\n interrupt: lgConfig?.interrupt,\n signal: lgConfig?.signal,\n };\n\n /**\n * Find the tool instance to include in the request.\n * For dynamically registered tools, this may be undefined.\n */\n const registeredTool = this.tools.find((t) => t.name === call.name);\n\n /**\n * Define the base handler that executes the tool.\n * When wrapToolCall middleware is present, this handler does NOT catch errors\n * so the middleware can handle them.\n * When no middleware, errors are caught and handled here.\n *\n * The handler now accepts an overridden tool from the request, allowing\n * middleware to provide tool implementations for dynamically registered tools.\n */\n const baseHandler = async (\n request: ToolCallRequest\n ): Promise<ToolMessage | Command> => {\n const { toolCall, tool: requestTool } = request;\n\n /**\n * Use the tool from the request (which may be overridden via spread syntax)\n * or fall back to finding it in registered tools.\n * This allows middleware to provide dynamic tool implementations.\n */\n const tool =\n requestTool ?? this.tools.find((t) => t.name === toolCall.name);\n\n if (tool === undefined) {\n /**\n * Tool not found - return a graceful error message rather than throwing.\n * This allows the LLM to see the error and potentially retry.\n */\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(toolCall.name, availableTools),\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n status: \"error\",\n });\n }\n\n /**\n * Cast tool to a common invokable type.\n * The tool can be from registered tools (StructuredToolInterface | DynamicTool | RunnableToolLike)\n * or from middleware override (ClientTool | ServerTool).\n */\n const invokableTool = tool as\n | StructuredToolInterface\n | DynamicTool\n | RunnableToolLike;\n\n try {\n const output = await invokableTool.invoke(\n { ...toolCall, type: \"tool_call\" },\n {\n ...config,\n /**\n * extend to match ToolRuntime\n */\n config,\n toolCallId: toolCall.id!,\n state: config.configurable?.__pregel_scratchpad?.currentTaskInput,\n signal: mergeAbortSignals(this.signal, config.signal),\n }\n );\n\n if (ToolMessage.isInstance(output) || isCommand(output)) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n name: invokableTool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: toolCall.id!,\n });\n } catch (e: unknown) {\n /**\n * Handle errors from tool execution (not from wrapToolCall)\n * If tool invocation fails due to input parsing error, throw a {@link ToolInvocationError}\n */\n if (e instanceof ToolInputParsingException) {\n throw new ToolInvocationError(e, toolCall);\n }\n /**\n * Re-throw to be handled by caller\n */\n throw e;\n }\n };\n\n /**\n * Create request object for middleware\n * Cast to ToolCallRequest<AgentBuiltInState> to satisfy type constraints\n * of wrapToolCall which expects AgentBuiltInState\n */\n const request: ToolCallRequest<AgentBuiltInState> = {\n toolCall: call,\n tool: registeredTool,\n state,\n runtime,\n };\n\n /**\n * If wrapToolCall is provided, use it to wrap the tool execution\n */\n if (this.wrapToolCall) {\n try {\n return await this.wrapToolCall(request, baseHandler);\n } catch (e: unknown) {\n /**\n * Handle middleware errors\n */\n return this.#handleError(e, call, true);\n }\n }\n\n /**\n * No wrapToolCall - if tool wasn't found, return graceful error\n */\n if (!registeredTool) {\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(call.name, availableTools),\n tool_call_id: call.id!,\n name: call.name,\n status: \"error\",\n });\n }\n\n /**\n * No wrapToolCall - execute tool directly and handle errors here\n */\n try {\n return await baseHandler(request);\n } catch (e: unknown) {\n /**\n * Handle tool errors when no middleware provided\n */\n return this.#handleError(e, call, false);\n }\n }\n\n protected async run(\n state: ToAnnotationRoot<StateSchema>[\"State\"] & AgentBuiltInState,\n config: RunnableConfig\n ): Promise<ContextSchema> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(state)) {\n const { lg_tool_call: _, jumpTo: __, ...newState } = state;\n outputs = [await this.runTool(state.lg_tool_call, config, newState)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(state)) {\n messages = state;\n } else if (isMessagesState(state)) {\n messages = state.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (AIMessage.isInstance(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (!AIMessage.isInstance(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config, state)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(state)\n ? outputs\n : { messages: outputs }) as unknown as ContextSchema;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(state) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as unknown as ContextSchema;\n }\n}\n\nexport function isSend(x: unknown): x is Send {\n return x instanceof Send;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ToolNode.js","names":["#handleError"],"sources":["../../../src/agents/nodes/ToolNode.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\n/* oxlint-disable no-instanceof/no-instanceof */\nimport { BaseMessage, ToolMessage, AIMessage } from \"@langchain/core/messages\";\nimport { RunnableConfig, RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n DynamicTool,\n StructuredToolInterface,\n ToolInputParsingException,\n} from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport type { InteropZodObject } from \"@langchain/core/utils/types\";\nimport {\n isCommand,\n Command,\n Send,\n isGraphInterrupt,\n type LangGraphRunnableConfig,\n StateDefinitionInit,\n} from \"@langchain/langgraph\";\n\nimport { RunnableCallable } from \"../RunnableCallable.js\";\nimport { mergeAbortSignals } from \"./utils.js\";\nimport { MiddlewareError, ToolInvocationError } from \"../errors.js\";\nimport type {\n WrapToolCallHook,\n ToolCallRequest,\n ToAnnotationRoot,\n} from \"../middleware/types.js\";\nimport type { AgentBuiltInState } from \"../runtime.js\";\n\n/**\n * Error message template for when middleware adds tools that can't be executed.\n * This happens when middleware modifies tools in wrapModelCall but doesn't provide\n * a wrapToolCall handler to execute them.\n */\nconst getInvalidToolError = (\n toolName: string,\n availableTools: string[]\n): string =>\n `Error: ${toolName} is not a valid tool, try one of [${availableTools.join(\", \")}].`;\n\n/**\n * The name of the tool node in the state graph.\n */\nexport const TOOLS_NODE_NAME = \"tools\";\n\nexport interface ToolNodeOptions {\n /**\n * The name of the tool node.\n */\n name?: string;\n /**\n * The tags to add to the tool call.\n */\n tags?: string[];\n /**\n * The abort signal to cancel the tool call.\n */\n signal?: AbortSignal;\n /**\n * Whether to throw the error immediately if the tool fails or handle it by the `onToolError` function or via ToolMessage.\n *\n * **Default behavior** (matches Python):\n * - Catches only `ToolInvocationError` (invalid arguments from model) and converts to ToolMessage\n * - Re-raises all other errors including errors from `wrapToolCall` middleware\n *\n * If `true`:\n * - Catches all errors and returns a ToolMessage with the error\n *\n * If `false`:\n * - All errors are thrown immediately\n *\n * If a function is provided:\n * - If function returns a `ToolMessage`, use it as the result\n * - If function returns `undefined`, re-raise the error\n *\n * @default A function that only catches ToolInvocationError\n */\n handleToolErrors?:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined);\n /**\n * Optional wrapper function for tool execution.\n * Allows middleware to intercept and modify tool calls before execution.\n * The wrapper receives the tool call request and a handler function to execute the tool.\n */\n wrapToolCall?: WrapToolCallHook;\n}\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(BaseMessage.isInstance);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (\n input: unknown\n): input is { lg_tool_call: ToolCall; jumpTo?: string } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * Default error handler for tool errors.\n *\n * This is applied to errors from baseHandler (tool execution).\n * For errors from wrapToolCall middleware, those are handled separately\n * and will bubble up by default.\n *\n * Catches all tool execution errors and converts them to ToolMessage.\n * This allows the LLM to see the error and potentially retry with different arguments.\n */\nfunction defaultHandleToolErrors(\n error: unknown,\n toolCall: ToolCall\n): ToolMessage | undefined {\n if (ToolInvocationError.isInstance(error)) {\n return new ToolMessage({\n content: error.message,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n }\n /**\n * Catch all other tool errors and convert to ToolMessage\n */\n return new ToolMessage({\n content: `${error}\\n Please fix your mistakes.`,\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n });\n}\n\n/**\n * `ToolNode` is a built-in LangGraph component that handles tool calls within an agent's workflow.\n * It works seamlessly with `createAgent`, offering advanced tool execution control, built\n * in parallelism, and error handling.\n *\n * @example\n * ```ts\n * import { ToolNode, tool, AIMessage } from \"langchain\";\n * import { z } from \"zod/v3\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n */\nexport class ToolNode<\n StateSchema extends StateDefinitionInit = any,\n ContextSchema extends InteropZodObject = any,\n> extends RunnableCallable<StateSchema, ContextSchema> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n trace = false;\n\n signal?: AbortSignal;\n\n handleToolErrors:\n | boolean\n | ((error: unknown, toolCall: ToolCall) => ToolMessage | undefined) =\n defaultHandleToolErrors;\n\n wrapToolCall: WrapToolCallHook | undefined;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n public options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors, signal, wrapToolCall } =\n options ?? {};\n super({\n name,\n tags,\n func: (state, config) =>\n this.run(\n state as ToAnnotationRoot<StateDefinitionInit>[\"State\"] &\n AgentBuiltInState,\n config as RunnableConfig\n ),\n });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n this.signal = signal;\n this.wrapToolCall = wrapToolCall;\n }\n\n /**\n * Handle errors from tool execution or middleware.\n * @param error - The error to handle\n * @param call - The tool call that caused the error\n * @param isMiddlewareError - Whether the error came from wrapToolCall middleware\n * @returns ToolMessage if error is handled, otherwise re-throws\n */\n #handleError(\n error: unknown,\n call: ToolCall,\n isMiddlewareError: boolean\n ): ToolMessage {\n /**\n * {@link NodeInterrupt} errors are a breakpoint to bring a human into the loop.\n * As such, they are not recoverable by the agent and shouldn't be fed\n * back. Instead, re-throw these errors even when `handleToolErrors = true`.\n */\n if (isGraphInterrupt(error)) {\n throw error;\n }\n\n /**\n * If the signal is aborted, we want to bubble up the error to the invoke caller.\n */\n if (this.signal?.aborted) {\n throw error;\n }\n\n /**\n * A recoverable tool error (e.g. tool-input schema validation) can be\n * rewrapped as a {@link MiddlewareError} with the original error on `.cause`\n * — once per `wrapToolCall` middleware, so it may be nested several layers\n * deep. Walk the cause chain to the root; if it's a {@link ToolInvocationError},\n * unwrap it so the intended `handleToolErrors` self-correction path still\n * applies. Genuine middleware errors stay fatal by default.\n */\n let effectiveError = error;\n let errorFromMiddleware = isMiddlewareError;\n if (isMiddlewareError) {\n let unwrapped: unknown = error;\n while (MiddlewareError.isInstance(unwrapped)) {\n unwrapped = unwrapped.cause;\n }\n if (ToolInvocationError.isInstance(unwrapped)) {\n effectiveError = unwrapped;\n errorFromMiddleware = false;\n }\n }\n\n /**\n * If error is from middleware and handleToolErrors is not true, bubble up\n * (default handler and false both re-raise middleware errors)\n */\n if (errorFromMiddleware && this.handleToolErrors !== true) {\n throw effectiveError;\n }\n\n /**\n * If handleToolErrors is false, throw all errors\n */\n if (!this.handleToolErrors) {\n throw effectiveError;\n }\n\n /**\n * Apply handleToolErrors to the error\n */\n if (typeof this.handleToolErrors === \"function\") {\n const result = this.handleToolErrors(effectiveError, call);\n if (result && ToolMessage.isInstance(result)) {\n return result;\n }\n\n /**\n * `handleToolErrors` returned undefined - re-raise\n */\n throw effectiveError;\n } else if (this.handleToolErrors) {\n return new ToolMessage({\n name: call.name,\n content: `${effectiveError}\\n Please fix your mistakes.`,\n tool_call_id: call.id!,\n });\n }\n\n /**\n * Shouldn't reach here, but throw as fallback\n */\n throw effectiveError;\n }\n\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig,\n state: AgentBuiltInState\n ): Promise<ToolMessage | Command> {\n /**\n * Build runtime from LangGraph config\n */\n const lgConfig = config as LangGraphRunnableConfig;\n const runtime = {\n context: lgConfig?.context,\n store: lgConfig?.store,\n configurable: lgConfig?.configurable,\n writer: lgConfig?.writer,\n interrupt: lgConfig?.interrupt,\n signal: lgConfig?.signal,\n };\n\n /**\n * Find the tool instance to include in the request.\n * For dynamically registered tools, this may be undefined.\n */\n const registeredTool = this.tools.find((t) => t.name === call.name);\n\n /**\n * Define the base handler that executes the tool.\n * When wrapToolCall middleware is present, this handler does NOT catch errors\n * so the middleware can handle them.\n * When no middleware, errors are caught and handled here.\n *\n * The handler now accepts an overridden tool from the request, allowing\n * middleware to provide tool implementations for dynamically registered tools.\n */\n const baseHandler = async (\n request: ToolCallRequest\n ): Promise<ToolMessage | Command> => {\n const { toolCall, tool: requestTool } = request;\n\n /**\n * Use the tool from the request (which may be overridden via spread syntax)\n * or fall back to finding it in registered tools.\n * This allows middleware to provide dynamic tool implementations.\n */\n const tool =\n requestTool ?? this.tools.find((t) => t.name === toolCall.name);\n\n if (tool === undefined) {\n /**\n * Tool not found - return a graceful error message rather than throwing.\n * This allows the LLM to see the error and potentially retry.\n */\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(toolCall.name, availableTools),\n tool_call_id: toolCall.id!,\n name: toolCall.name,\n status: \"error\",\n });\n }\n\n /**\n * Cast tool to a common invokable type.\n * The tool can be from registered tools (StructuredToolInterface | DynamicTool | RunnableToolLike)\n * or from middleware override (ClientTool | ServerTool).\n */\n const invokableTool = tool as\n | StructuredToolInterface\n | DynamicTool\n | RunnableToolLike;\n\n try {\n const output = await invokableTool.invoke(\n { ...toolCall, type: \"tool_call\" },\n {\n ...config,\n /**\n * extend to match ToolRuntime\n */\n config,\n toolCallId: toolCall.id!,\n state: config.configurable?.__pregel_scratchpad?.currentTaskInput,\n signal: mergeAbortSignals(this.signal, config.signal),\n }\n );\n\n if (ToolMessage.isInstance(output) || isCommand(output)) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n name: invokableTool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: toolCall.id!,\n });\n } catch (e: unknown) {\n /**\n * Handle errors from tool execution (not from wrapToolCall)\n * If tool invocation fails due to input parsing error, throw a {@link ToolInvocationError}\n */\n if (e instanceof ToolInputParsingException) {\n throw new ToolInvocationError(e, toolCall);\n }\n /**\n * Re-throw to be handled by caller\n */\n throw e;\n }\n };\n\n /**\n * Create request object for middleware\n * Cast to ToolCallRequest<AgentBuiltInState> to satisfy type constraints\n * of wrapToolCall which expects AgentBuiltInState\n */\n const request: ToolCallRequest<AgentBuiltInState> = {\n toolCall: call,\n tool: registeredTool,\n state,\n runtime,\n };\n\n /**\n * If wrapToolCall is provided, use it to wrap the tool execution\n */\n if (this.wrapToolCall) {\n try {\n return await this.wrapToolCall(request, baseHandler);\n } catch (e: unknown) {\n /**\n * Handle middleware errors\n */\n return this.#handleError(e, call, true);\n }\n }\n\n /**\n * No wrapToolCall - if tool wasn't found, return graceful error\n */\n if (!registeredTool) {\n const availableTools = this.tools.map((t) => t.name);\n return new ToolMessage({\n content: getInvalidToolError(call.name, availableTools),\n tool_call_id: call.id!,\n name: call.name,\n status: \"error\",\n });\n }\n\n /**\n * No wrapToolCall - execute tool directly and handle errors here\n */\n try {\n return await baseHandler(request);\n } catch (e: unknown) {\n /**\n * Handle tool errors when no middleware provided\n */\n return this.#handleError(e, call, false);\n }\n }\n\n protected async run(\n state: ToAnnotationRoot<StateSchema>[\"State\"] & AgentBuiltInState,\n config: RunnableConfig\n ): Promise<ContextSchema> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(state)) {\n const { lg_tool_call: _, jumpTo: __, ...newState } = state;\n outputs = [await this.runTool(state.lg_tool_call, config, newState)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(state)) {\n messages = state;\n } else if (isMessagesState(state)) {\n messages = state.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (AIMessage.isInstance(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (!AIMessage.isInstance(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config, state)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(state)\n ? outputs\n : { messages: outputs }) as unknown as ContextSchema;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(state) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as unknown as ContextSchema;\n }\n}\n\nexport function isSend(x: unknown): x is Send {\n return x instanceof Send;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langchain",
3
- "version": "1.5.2",
3
+ "version": "1.5.3",
4
4
  "description": "Typescript bindings for langchain",
5
5
  "author": "LangChain",
6
6
  "license": "MIT",
@@ -33,17 +33,17 @@
33
33
  "homepage": "https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain/",
34
34
  "devDependencies": {
35
35
  "@hono/node-server": "^1.19.14",
36
- "@langchain/langgraph-api": "^1.3.1",
37
- "@langchain/langgraph-sdk": "^1.9.23",
36
+ "@langchain/langgraph-api": "^1.4.1",
37
+ "@langchain/langgraph-sdk": "^1.9.25",
38
38
  "@tsconfig/recommended": "^1.0.2",
39
39
  "@types/js-yaml": "^4",
40
40
  "@types/jsdom": "^28.0.3",
41
41
  "@types/ws": "^8",
42
- "@vitest/coverage-v8": "^4.1.8",
42
+ "@vitest/coverage-v8": "^4.1.9",
43
43
  "cheerio": "1.2.0",
44
44
  "dotenv": "^17.4.0",
45
45
  "dpdm": "^3.14.0",
46
- "hono": "^4.12.18",
46
+ "hono": "^4.12.25",
47
47
  "openai": "^6.41.0",
48
48
  "peggy": "^5.1.0",
49
49
  "reflect-metadata": "^0.2.2",
@@ -54,9 +54,9 @@
54
54
  "vitest": "^4.1.8",
55
55
  "yaml": "^2.9.0",
56
56
  "@langchain/anthropic": "1.5.1",
57
- "@langchain/aws": "1.4.2",
58
- "@langchain/core": "^1.2.1",
59
57
  "@langchain/fireworks": "0.2.3",
58
+ "@langchain/core": "^1.2.1",
59
+ "@langchain/aws": "1.4.2",
60
60
  "@langchain/openai": "1.5.3",
61
61
  "@langchain/tsconfig": "0.0.1"
62
62
  },
@@ -64,8 +64,8 @@
64
64
  "@langchain/core": "^1.2.1"
65
65
  },
66
66
  "dependencies": {
67
- "@langchain/langgraph": "^1.4.4",
68
- "@langchain/langgraph-checkpoint": "^1.1.2",
67
+ "@langchain/langgraph": "^1.4.7",
68
+ "@langchain/langgraph-checkpoint": "^1.1.3",
69
69
  "langsmith": ">=0.5.0 <1.0.0",
70
70
  "zod": "^3.25.76 || ^4"
71
71
  },