@langchain/core 1.2.12 → 1.2.14

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,18 @@
1
1
  # @langchain/core
2
2
 
3
+ ## 1.2.14
4
+
5
+ ### Patch Changes
6
+
7
+ - [#11771](https://github.com/langchain-ai/langchainjs/pull/11771) [`bbed273`](https://github.com/langchain-ai/langchainjs/commit/bbed27359a9b355ff9fab478c6b2fe7bf2eb1a4a) Thanks [@thushanth-bengre-langchain](https://github.com/thushanth-bengre-langchain)! - Add `fileMimeTypes` to `ModelProfile` so models can advertise the MIME types they accept as generic file inputs. OpenAI Responses API models now report the file types `input_file` supports;
8
+ Chat Completions profiles are unchanged.
9
+
10
+ ## 1.2.13
11
+
12
+ ### Patch Changes
13
+
14
+ - [#11714](https://github.com/langchain-ai/langchainjs/pull/11714) [`a83dfb1`](https://github.com/langchain-ai/langchainjs/commit/a83dfb14f8e17fcb66dc7a915f0cf8ed7b0dffa1) Thanks [@ccurme](https://github.com/ccurme)! - Abbreviate long tool-call IDs when formatting chat messages as strings, keeping original messages unchanged.
15
+
3
16
  ## 1.2.12
4
17
 
5
18
  ### Patch Changes
@@ -139,7 +139,7 @@ var BaseLangChain = class extends require_base.Runnable {
139
139
  this.callbacks = params.callbacks;
140
140
  this.tags = params.tags ?? [];
141
141
  this.metadata = params.metadata ?? {};
142
- this._addVersion("@langchain/core", "1.2.12");
142
+ this._addVersion("@langchain/core", "1.2.14");
143
143
  }
144
144
  _addVersion(pkg, version) {
145
145
  const existing = this.metadata?.versions;
@@ -138,7 +138,7 @@ var BaseLangChain = class extends Runnable {
138
138
  this.callbacks = params.callbacks;
139
139
  this.tags = params.tags ?? [];
140
140
  this.metadata = params.metadata ?? {};
141
- this._addVersion("@langchain/core", "1.2.12");
141
+ this._addVersion("@langchain/core", "1.2.14");
142
142
  }
143
143
  _addVersion(pkg, version) {
144
144
  const existing = this.metadata?.versions;
@@ -1 +1 @@
1
- {"version":3,"file":"profile.cjs","names":[],"sources":["../../src/language_models/profile.ts"],"sourcesContent":["/**\n * Represents the capabilities and constraints of a language model.\n *\n * This interface defines the various features and limitations that a model may have,\n * including input/output constraints, multimodal support, and advanced capabilities\n * like tool calling and structured output.\n */\nexport interface ModelProfile {\n /**\n * Maximum number of tokens that can be included in the input context window.\n *\n * This represents the total token budget for the model's input, including\n * the prompt, system messages, conversation history, and any other context.\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxInputTokens: 128000 // Model supports up to 128k tokens\n * };\n * ```\n */\n maxInputTokens?: number;\n\n /**\n * Whether the model supports image inputs.\n *\n * When `true`, the model can process images as part of its input, enabling\n * multimodal interactions where visual content can be analyzed alongside text.\n *\n * @see {@link imageUrlInputs} for URL-based image input support\n */\n imageInputs?: boolean;\n\n /**\n * Whether the model supports image URL inputs.\n *\n * When `true`, the model can accept URLs pointing to images rather than\n * requiring the image data to be embedded directly in the request. This can\n * be more efficient for large images or when images are already hosted.\n *\n * @see {@link imageInputs} for direct image input support\n */\n imageUrlInputs?: boolean;\n\n /**\n * Whether the model supports PDF document inputs.\n *\n * When `true`, the model can process PDF files as input, allowing it to\n * analyze document content, extract information, or answer questions about\n * PDF documents.\n */\n pdfInputs?: boolean;\n\n /**\n * Whether the model supports audio inputs.\n *\n * When `true`, the model can process audio data as input, enabling\n * capabilities like speech recognition, audio analysis, or multimodal\n * interactions involving sound.\n */\n audioInputs?: boolean;\n\n /**\n * Whether the model supports video inputs.\n *\n * When `true`, the model can process video data as input, enabling\n * capabilities like video analysis, scene understanding, or multimodal\n * interactions involving moving images.\n */\n videoInputs?: boolean;\n\n /**\n * Whether the model supports image content in tool messages.\n *\n * When `true`, tool responses can include images that the model can process\n * and reason about. This enables workflows where tools return visual data\n * that the model needs to interpret.\n */\n imageToolMessage?: boolean;\n\n /**\n * Whether the model supports PDF content in tool messages.\n *\n * When `true`, tool responses can include PDF documents that the model can\n * process and reason about. This enables workflows where tools return\n * document data that the model needs to interpret.\n */\n pdfToolMessage?: boolean;\n\n /**\n * Maximum number of tokens the model can generate in its output.\n *\n * This represents the upper limit on the length of the model's response.\n * The actual output may be shorter depending on the completion criteria\n * (e.g., natural stopping point, stop sequences).\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxOutputTokens: 4096 // Model can generate up to 4k tokens\n * };\n * ```\n */\n maxOutputTokens?: number;\n\n /**\n * Whether the model supports reasoning or chain-of-thought output.\n *\n * When `true`, the model can produce explicit reasoning steps or\n * chain-of-thought explanations as part of its output. This is useful\n * for understanding the model's decision-making process and improving\n * transparency in complex reasoning tasks.\n */\n reasoningOutput?: boolean;\n\n /**\n * Whether the model can generate image outputs.\n *\n * When `true`, the model can produce images as part of its response,\n * enabling capabilities like image generation, editing, or visual\n * content creation.\n */\n imageOutputs?: boolean;\n\n /**\n * Whether the model can generate audio outputs.\n *\n * When `true`, the model can produce audio data as part of its response,\n * enabling capabilities like text-to-speech, audio generation, or\n * sound synthesis.\n */\n audioOutputs?: boolean;\n\n /**\n * Whether the model can generate video outputs.\n *\n * When `true`, the model can produce video data as part of its response,\n * enabling capabilities like video generation, editing, or visual\n * content creation with motion.\n */\n videoOutputs?: boolean;\n\n /**\n * Whether the model supports tool calling (function calling).\n *\n * When `true`, the model can invoke external tools or functions during\n * its reasoning process. The model can decide which tools to call,\n * with what arguments, and can incorporate the tool results into its\n * final response.\n *\n * @see {@link toolChoice} for controlling tool selection behavior\n * @see {@link https://docs.langchain.com/oss/javascript/langchain/models#tool-calling}\n */\n toolCalling?: boolean;\n\n /**\n * Whether the model supports tool choice control.\n *\n * When `true`, the caller can specify how the model should select tools,\n * such as forcing the use of a specific tool, allowing any tool, or\n * preventing tool use entirely. This provides fine-grained control over\n * the model's tool-calling behavior.\n *\n * @see {@link toolCalling} for basic tool calling support\n */\n toolChoice?: boolean;\n\n /**\n * Whether the model supports structured output generation.\n *\n * When `true`, the model can generate responses that conform to a\n * specified schema or structure (e.g., JSON with a particular format).\n * This is useful for ensuring the model's output can be reliably parsed\n * and processed programmatically.\n *\n * @example\n * ```typescript\n * // Model can be instructed to return JSON matching a schema\n * const profile: ModelProfile = {\n * structuredOutput: true\n * };\n * ```\n */\n structuredOutput?: boolean;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"profile.cjs","names":[],"sources":["../../src/language_models/profile.ts"],"sourcesContent":["/**\n * Represents the capabilities and constraints of a language model.\n *\n * This interface defines the various features and limitations that a model may have,\n * including input/output constraints, multimodal support, and advanced capabilities\n * like tool calling and structured output.\n */\nexport interface ModelProfile {\n /**\n * Maximum number of tokens that can be included in the input context window.\n *\n * This represents the total token budget for the model's input, including\n * the prompt, system messages, conversation history, and any other context.\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxInputTokens: 128000 // Model supports up to 128k tokens\n * };\n * ```\n */\n maxInputTokens?: number;\n\n /**\n * Whether the model supports image inputs.\n *\n * When `true`, the model can process images as part of its input, enabling\n * multimodal interactions where visual content can be analyzed alongside text.\n *\n * @see {@link imageUrlInputs} for URL-based image input support\n */\n imageInputs?: boolean;\n\n /**\n * Whether the model supports image URL inputs.\n *\n * When `true`, the model can accept URLs pointing to images rather than\n * requiring the image data to be embedded directly in the request. This can\n * be more efficient for large images or when images are already hosted.\n *\n * @see {@link imageInputs} for direct image input support\n */\n imageUrlInputs?: boolean;\n\n /**\n * Whether the model supports PDF document inputs.\n *\n * When `true`, the model can process PDF files as input, allowing it to\n * analyze document content, extract information, or answer questions about\n * PDF documents.\n */\n pdfInputs?: boolean;\n\n /**\n * Whether the model supports audio inputs.\n *\n * When `true`, the model can process audio data as input, enabling\n * capabilities like speech recognition, audio analysis, or multimodal\n * interactions involving sound.\n */\n audioInputs?: boolean;\n\n /**\n * Whether the model supports video inputs.\n *\n * When `true`, the model can process video data as input, enabling\n * capabilities like video analysis, scene understanding, or multimodal\n * interactions involving moving images.\n */\n videoInputs?: boolean;\n\n /**\n * MIME types the model accepts as generic file inputs.\n *\n * Covers file types beyond those with dedicated flags (e.g. {@link pdfInputs}),\n * such as office documents, source code, or plain text. When undefined, the\n * model's support for generic file inputs is unknown.\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * fileMimeTypes: [\"text/plain\", \"text/csv\", \"application/json\"]\n * };\n * ```\n */\n fileMimeTypes?: readonly string[];\n\n /**\n * Whether the model supports image content in tool messages.\n *\n * When `true`, tool responses can include images that the model can process\n * and reason about. This enables workflows where tools return visual data\n * that the model needs to interpret.\n */\n imageToolMessage?: boolean;\n\n /**\n * Whether the model supports PDF content in tool messages.\n *\n * When `true`, tool responses can include PDF documents that the model can\n * process and reason about. This enables workflows where tools return\n * document data that the model needs to interpret.\n */\n pdfToolMessage?: boolean;\n\n /**\n * Maximum number of tokens the model can generate in its output.\n *\n * This represents the upper limit on the length of the model's response.\n * The actual output may be shorter depending on the completion criteria\n * (e.g., natural stopping point, stop sequences).\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxOutputTokens: 4096 // Model can generate up to 4k tokens\n * };\n * ```\n */\n maxOutputTokens?: number;\n\n /**\n * Whether the model supports reasoning or chain-of-thought output.\n *\n * When `true`, the model can produce explicit reasoning steps or\n * chain-of-thought explanations as part of its output. This is useful\n * for understanding the model's decision-making process and improving\n * transparency in complex reasoning tasks.\n */\n reasoningOutput?: boolean;\n\n /**\n * Whether the model can generate image outputs.\n *\n * When `true`, the model can produce images as part of its response,\n * enabling capabilities like image generation, editing, or visual\n * content creation.\n */\n imageOutputs?: boolean;\n\n /**\n * Whether the model can generate audio outputs.\n *\n * When `true`, the model can produce audio data as part of its response,\n * enabling capabilities like text-to-speech, audio generation, or\n * sound synthesis.\n */\n audioOutputs?: boolean;\n\n /**\n * Whether the model can generate video outputs.\n *\n * When `true`, the model can produce video data as part of its response,\n * enabling capabilities like video generation, editing, or visual\n * content creation with motion.\n */\n videoOutputs?: boolean;\n\n /**\n * Whether the model supports tool calling (function calling).\n *\n * When `true`, the model can invoke external tools or functions during\n * its reasoning process. The model can decide which tools to call,\n * with what arguments, and can incorporate the tool results into its\n * final response.\n *\n * @see {@link toolChoice} for controlling tool selection behavior\n * @see {@link https://docs.langchain.com/oss/javascript/langchain/models#tool-calling}\n */\n toolCalling?: boolean;\n\n /**\n * Whether the model supports tool choice control.\n *\n * When `true`, the caller can specify how the model should select tools,\n * such as forcing the use of a specific tool, allowing any tool, or\n * preventing tool use entirely. This provides fine-grained control over\n * the model's tool-calling behavior.\n *\n * @see {@link toolCalling} for basic tool calling support\n */\n toolChoice?: boolean;\n\n /**\n * Whether the model supports structured output generation.\n *\n * When `true`, the model can generate responses that conform to a\n * specified schema or structure (e.g., JSON with a particular format).\n * This is useful for ensuring the model's output can be reliably parsed\n * and processed programmatically.\n *\n * @example\n * ```typescript\n * // Model can be instructed to return JSON matching a schema\n * const profile: ModelProfile = {\n * structuredOutput: true\n * };\n * ```\n */\n structuredOutput?: boolean;\n}\n"],"mappings":""}
@@ -64,6 +64,21 @@ interface ModelProfile {
64
64
  * interactions involving moving images.
65
65
  */
66
66
  videoInputs?: boolean;
67
+ /**
68
+ * MIME types the model accepts as generic file inputs.
69
+ *
70
+ * Covers file types beyond those with dedicated flags (e.g. {@link pdfInputs}),
71
+ * such as office documents, source code, or plain text. When undefined, the
72
+ * model's support for generic file inputs is unknown.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const profile: ModelProfile = {
77
+ * fileMimeTypes: ["text/plain", "text/csv", "application/json"]
78
+ * };
79
+ * ```
80
+ */
81
+ fileMimeTypes?: readonly string[];
67
82
  /**
68
83
  * Whether the model supports image content in tool messages.
69
84
  *
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.cts","names":[],"sources":["../../src/language_models/profile.ts"],"mappings":";;;;;;;;UAOiB;;;;;;;;;;;;;;EAcf;;;;;;;;;EAUA;;;;;;;;;;EAWA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;;;;EAgBA;;;;;;;;;EAUA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;EAaA;;;;;;;;;;;EAYA;;;;;;;;;;;;;;;;;EAkBA"}
1
+ {"version":3,"file":"profile.d.cts","names":[],"sources":["../../src/language_models/profile.ts"],"mappings":";;;;;;;;UAOiB;;;;;;;;;;;;;;EAcf;;;;;;;;;EAUA;;;;;;;;;;EAWA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;;;;EAgBA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;;;;EAgBA;;;;;;;;;EAUA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;EAaA;;;;;;;;;;;EAYA;;;;;;;;;;;;;;;;;EAkBA"}
@@ -64,6 +64,21 @@ interface ModelProfile {
64
64
  * interactions involving moving images.
65
65
  */
66
66
  videoInputs?: boolean;
67
+ /**
68
+ * MIME types the model accepts as generic file inputs.
69
+ *
70
+ * Covers file types beyond those with dedicated flags (e.g. {@link pdfInputs}),
71
+ * such as office documents, source code, or plain text. When undefined, the
72
+ * model's support for generic file inputs is unknown.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const profile: ModelProfile = {
77
+ * fileMimeTypes: ["text/plain", "text/csv", "application/json"]
78
+ * };
79
+ * ```
80
+ */
81
+ fileMimeTypes?: readonly string[];
67
82
  /**
68
83
  * Whether the model supports image content in tool messages.
69
84
  *
@@ -1 +1 @@
1
- {"version":3,"file":"profile.d.ts","names":[],"sources":["../../src/language_models/profile.ts"],"mappings":";;;;;;;;UAOiB;;;;;;;;;;;;;;EAcf;;;;;;;;;EAUA;;;;;;;;;;EAWA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;;;;EAgBA;;;;;;;;;EAUA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;EAaA;;;;;;;;;;;EAYA;;;;;;;;;;;;;;;;;EAkBA"}
1
+ {"version":3,"file":"profile.d.ts","names":[],"sources":["../../src/language_models/profile.ts"],"mappings":";;;;;;;;UAOiB;;;;;;;;;;;;;;EAcf;;;;;;;;;EAUA;;;;;;;;;;EAWA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;;;;EAgBA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;;;;EAgBA;;;;;;;;;EAUA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;EASA;;;;;;;;;;;;EAaA;;;;;;;;;;;EAYA;;;;;;;;;;;;;;;;;EAkBA"}
@@ -1 +1 @@
1
- {"version":3,"file":"profile.js","names":[],"sources":["../../src/language_models/profile.ts"],"sourcesContent":["/**\n * Represents the capabilities and constraints of a language model.\n *\n * This interface defines the various features and limitations that a model may have,\n * including input/output constraints, multimodal support, and advanced capabilities\n * like tool calling and structured output.\n */\nexport interface ModelProfile {\n /**\n * Maximum number of tokens that can be included in the input context window.\n *\n * This represents the total token budget for the model's input, including\n * the prompt, system messages, conversation history, and any other context.\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxInputTokens: 128000 // Model supports up to 128k tokens\n * };\n * ```\n */\n maxInputTokens?: number;\n\n /**\n * Whether the model supports image inputs.\n *\n * When `true`, the model can process images as part of its input, enabling\n * multimodal interactions where visual content can be analyzed alongside text.\n *\n * @see {@link imageUrlInputs} for URL-based image input support\n */\n imageInputs?: boolean;\n\n /**\n * Whether the model supports image URL inputs.\n *\n * When `true`, the model can accept URLs pointing to images rather than\n * requiring the image data to be embedded directly in the request. This can\n * be more efficient for large images or when images are already hosted.\n *\n * @see {@link imageInputs} for direct image input support\n */\n imageUrlInputs?: boolean;\n\n /**\n * Whether the model supports PDF document inputs.\n *\n * When `true`, the model can process PDF files as input, allowing it to\n * analyze document content, extract information, or answer questions about\n * PDF documents.\n */\n pdfInputs?: boolean;\n\n /**\n * Whether the model supports audio inputs.\n *\n * When `true`, the model can process audio data as input, enabling\n * capabilities like speech recognition, audio analysis, or multimodal\n * interactions involving sound.\n */\n audioInputs?: boolean;\n\n /**\n * Whether the model supports video inputs.\n *\n * When `true`, the model can process video data as input, enabling\n * capabilities like video analysis, scene understanding, or multimodal\n * interactions involving moving images.\n */\n videoInputs?: boolean;\n\n /**\n * Whether the model supports image content in tool messages.\n *\n * When `true`, tool responses can include images that the model can process\n * and reason about. This enables workflows where tools return visual data\n * that the model needs to interpret.\n */\n imageToolMessage?: boolean;\n\n /**\n * Whether the model supports PDF content in tool messages.\n *\n * When `true`, tool responses can include PDF documents that the model can\n * process and reason about. This enables workflows where tools return\n * document data that the model needs to interpret.\n */\n pdfToolMessage?: boolean;\n\n /**\n * Maximum number of tokens the model can generate in its output.\n *\n * This represents the upper limit on the length of the model's response.\n * The actual output may be shorter depending on the completion criteria\n * (e.g., natural stopping point, stop sequences).\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxOutputTokens: 4096 // Model can generate up to 4k tokens\n * };\n * ```\n */\n maxOutputTokens?: number;\n\n /**\n * Whether the model supports reasoning or chain-of-thought output.\n *\n * When `true`, the model can produce explicit reasoning steps or\n * chain-of-thought explanations as part of its output. This is useful\n * for understanding the model's decision-making process and improving\n * transparency in complex reasoning tasks.\n */\n reasoningOutput?: boolean;\n\n /**\n * Whether the model can generate image outputs.\n *\n * When `true`, the model can produce images as part of its response,\n * enabling capabilities like image generation, editing, or visual\n * content creation.\n */\n imageOutputs?: boolean;\n\n /**\n * Whether the model can generate audio outputs.\n *\n * When `true`, the model can produce audio data as part of its response,\n * enabling capabilities like text-to-speech, audio generation, or\n * sound synthesis.\n */\n audioOutputs?: boolean;\n\n /**\n * Whether the model can generate video outputs.\n *\n * When `true`, the model can produce video data as part of its response,\n * enabling capabilities like video generation, editing, or visual\n * content creation with motion.\n */\n videoOutputs?: boolean;\n\n /**\n * Whether the model supports tool calling (function calling).\n *\n * When `true`, the model can invoke external tools or functions during\n * its reasoning process. The model can decide which tools to call,\n * with what arguments, and can incorporate the tool results into its\n * final response.\n *\n * @see {@link toolChoice} for controlling tool selection behavior\n * @see {@link https://docs.langchain.com/oss/javascript/langchain/models#tool-calling}\n */\n toolCalling?: boolean;\n\n /**\n * Whether the model supports tool choice control.\n *\n * When `true`, the caller can specify how the model should select tools,\n * such as forcing the use of a specific tool, allowing any tool, or\n * preventing tool use entirely. This provides fine-grained control over\n * the model's tool-calling behavior.\n *\n * @see {@link toolCalling} for basic tool calling support\n */\n toolChoice?: boolean;\n\n /**\n * Whether the model supports structured output generation.\n *\n * When `true`, the model can generate responses that conform to a\n * specified schema or structure (e.g., JSON with a particular format).\n * This is useful for ensuring the model's output can be reliably parsed\n * and processed programmatically.\n *\n * @example\n * ```typescript\n * // Model can be instructed to return JSON matching a schema\n * const profile: ModelProfile = {\n * structuredOutput: true\n * };\n * ```\n */\n structuredOutput?: boolean;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"profile.js","names":[],"sources":["../../src/language_models/profile.ts"],"sourcesContent":["/**\n * Represents the capabilities and constraints of a language model.\n *\n * This interface defines the various features and limitations that a model may have,\n * including input/output constraints, multimodal support, and advanced capabilities\n * like tool calling and structured output.\n */\nexport interface ModelProfile {\n /**\n * Maximum number of tokens that can be included in the input context window.\n *\n * This represents the total token budget for the model's input, including\n * the prompt, system messages, conversation history, and any other context.\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxInputTokens: 128000 // Model supports up to 128k tokens\n * };\n * ```\n */\n maxInputTokens?: number;\n\n /**\n * Whether the model supports image inputs.\n *\n * When `true`, the model can process images as part of its input, enabling\n * multimodal interactions where visual content can be analyzed alongside text.\n *\n * @see {@link imageUrlInputs} for URL-based image input support\n */\n imageInputs?: boolean;\n\n /**\n * Whether the model supports image URL inputs.\n *\n * When `true`, the model can accept URLs pointing to images rather than\n * requiring the image data to be embedded directly in the request. This can\n * be more efficient for large images or when images are already hosted.\n *\n * @see {@link imageInputs} for direct image input support\n */\n imageUrlInputs?: boolean;\n\n /**\n * Whether the model supports PDF document inputs.\n *\n * When `true`, the model can process PDF files as input, allowing it to\n * analyze document content, extract information, or answer questions about\n * PDF documents.\n */\n pdfInputs?: boolean;\n\n /**\n * Whether the model supports audio inputs.\n *\n * When `true`, the model can process audio data as input, enabling\n * capabilities like speech recognition, audio analysis, or multimodal\n * interactions involving sound.\n */\n audioInputs?: boolean;\n\n /**\n * Whether the model supports video inputs.\n *\n * When `true`, the model can process video data as input, enabling\n * capabilities like video analysis, scene understanding, or multimodal\n * interactions involving moving images.\n */\n videoInputs?: boolean;\n\n /**\n * MIME types the model accepts as generic file inputs.\n *\n * Covers file types beyond those with dedicated flags (e.g. {@link pdfInputs}),\n * such as office documents, source code, or plain text. When undefined, the\n * model's support for generic file inputs is unknown.\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * fileMimeTypes: [\"text/plain\", \"text/csv\", \"application/json\"]\n * };\n * ```\n */\n fileMimeTypes?: readonly string[];\n\n /**\n * Whether the model supports image content in tool messages.\n *\n * When `true`, tool responses can include images that the model can process\n * and reason about. This enables workflows where tools return visual data\n * that the model needs to interpret.\n */\n imageToolMessage?: boolean;\n\n /**\n * Whether the model supports PDF content in tool messages.\n *\n * When `true`, tool responses can include PDF documents that the model can\n * process and reason about. This enables workflows where tools return\n * document data that the model needs to interpret.\n */\n pdfToolMessage?: boolean;\n\n /**\n * Maximum number of tokens the model can generate in its output.\n *\n * This represents the upper limit on the length of the model's response.\n * The actual output may be shorter depending on the completion criteria\n * (e.g., natural stopping point, stop sequences).\n *\n * @example\n * ```typescript\n * const profile: ModelProfile = {\n * maxOutputTokens: 4096 // Model can generate up to 4k tokens\n * };\n * ```\n */\n maxOutputTokens?: number;\n\n /**\n * Whether the model supports reasoning or chain-of-thought output.\n *\n * When `true`, the model can produce explicit reasoning steps or\n * chain-of-thought explanations as part of its output. This is useful\n * for understanding the model's decision-making process and improving\n * transparency in complex reasoning tasks.\n */\n reasoningOutput?: boolean;\n\n /**\n * Whether the model can generate image outputs.\n *\n * When `true`, the model can produce images as part of its response,\n * enabling capabilities like image generation, editing, or visual\n * content creation.\n */\n imageOutputs?: boolean;\n\n /**\n * Whether the model can generate audio outputs.\n *\n * When `true`, the model can produce audio data as part of its response,\n * enabling capabilities like text-to-speech, audio generation, or\n * sound synthesis.\n */\n audioOutputs?: boolean;\n\n /**\n * Whether the model can generate video outputs.\n *\n * When `true`, the model can produce video data as part of its response,\n * enabling capabilities like video generation, editing, or visual\n * content creation with motion.\n */\n videoOutputs?: boolean;\n\n /**\n * Whether the model supports tool calling (function calling).\n *\n * When `true`, the model can invoke external tools or functions during\n * its reasoning process. The model can decide which tools to call,\n * with what arguments, and can incorporate the tool results into its\n * final response.\n *\n * @see {@link toolChoice} for controlling tool selection behavior\n * @see {@link https://docs.langchain.com/oss/javascript/langchain/models#tool-calling}\n */\n toolCalling?: boolean;\n\n /**\n * Whether the model supports tool choice control.\n *\n * When `true`, the caller can specify how the model should select tools,\n * such as forcing the use of a specific tool, allowing any tool, or\n * preventing tool use entirely. This provides fine-grained control over\n * the model's tool-calling behavior.\n *\n * @see {@link toolCalling} for basic tool calling support\n */\n toolChoice?: boolean;\n\n /**\n * Whether the model supports structured output generation.\n *\n * When `true`, the model can generate responses that conform to a\n * specified schema or structure (e.g., JSON with a particular format).\n * This is useful for ensuring the model's output can be reliably parsed\n * and processed programmatically.\n *\n * @example\n * ```typescript\n * // Model can be instructed to return JSON matching a schema\n * const profile: ModelProfile = {\n * structuredOutput: true\n * };\n * ```\n */\n structuredOutput?: boolean;\n}\n"],"mappings":""}
@@ -124,6 +124,7 @@ function _contentBlockToString(block) {
124
124
  default: return block.type ? `[${block.type}]` : "";
125
125
  }
126
126
  }
127
+ const TOOL_CALL_ID_DISPLAY_LIMIT = 64;
127
128
  /**
128
129
  * This function is used by memory classes to get a string representation
129
130
  * of the chat message history, based on the message content and role.
@@ -136,6 +137,7 @@ function _contentBlockToString(block) {
136
137
  * ```
137
138
  *
138
139
  * This avoids token inflation from metadata when stringifying message objects directly.
140
+ * Tool-call IDs longer than 64 characters are shortened only in the rendered string.
139
141
  */
140
142
  function getBufferString(messages, humanPrefix = "Human", aiPrefix = "AI") {
141
143
  const string_messages = [];
@@ -152,8 +154,13 @@ function getBufferString(messages, humanPrefix = "Human", aiPrefix = "AI") {
152
154
  let message = `${role}: ${nameStr}${readableContent}`;
153
155
  if (m.type === "ai") {
154
156
  const aiMessage = m;
155
- if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) message += JSON.stringify(aiMessage.tool_calls);
156
- else if (aiMessage.additional_kwargs && "function_call" in aiMessage.additional_kwargs) message += JSON.stringify(aiMessage.additional_kwargs.function_call);
157
+ if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
158
+ const toolCalls = aiMessage.tool_calls;
159
+ message += JSON.stringify(toolCalls.some((call) => (call.id?.length ?? 0) > TOOL_CALL_ID_DISPLAY_LIMIT) ? toolCalls.map((call) => call.id && call.id.length > TOOL_CALL_ID_DISPLAY_LIMIT ? {
160
+ ...call,
161
+ id: `${call.id.slice(0, TOOL_CALL_ID_DISPLAY_LIMIT)}...`
162
+ } : call) : toolCalls);
163
+ } else if (aiMessage.additional_kwargs && "function_call" in aiMessage.additional_kwargs) message += JSON.stringify(aiMessage.additional_kwargs.function_call);
157
164
  }
158
165
  string_messages.push(message);
159
166
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs","names":["_isToolCall","HumanMessage","AIMessage","SystemMessage","ToolMessage","RemoveMessage","addLangChainErrorFields","isBaseMessage","_isMessageFieldWithRole","FunctionMessage","ChatMessage","HumanMessageChunk","AIMessageChunk","SystemMessageChunk","FunctionMessageChunk","ChatMessageChunk","parsePartialJson"],"sources":["../../src/messages/utils.ts"],"sourcesContent":["import { addLangChainErrorFields } from \"../errors/index.js\";\nimport { SerializedConstructor } from \"../load/serializable.js\";\nimport { _isToolCall } from \"../tools/utils.js\";\nimport { parsePartialJson } from \"../utils/json.js\";\nimport { AIMessage, AIMessageChunk, AIMessageChunkFields } from \"./ai.js\";\nimport {\n BaseMessageLike,\n BaseMessage,\n isBaseMessage,\n StoredMessage,\n StoredMessageV1,\n BaseMessageFields,\n _isMessageFieldWithRole,\n} from \"./base.js\";\nimport { ChatMessage, ChatMessageFields, ChatMessageChunk } from \"./chat.js\";\nimport {\n FunctionMessage,\n FunctionMessageChunk,\n FunctionMessageFields,\n} from \"./function.js\";\nimport { HumanMessage, HumanMessageChunk } from \"./human.js\";\nimport { RemoveMessage } from \"./modifier.js\";\nimport { SystemMessage, SystemMessageChunk } from \"./system.js\";\nimport {\n InvalidToolCall,\n ToolCall,\n ToolCallChunk,\n ToolMessage,\n ToolMessageFields,\n} from \"./tool.js\";\n\nexport type $Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;\n\n/**\n * Provider streaming marker for raw (non-JSON) tool input.\n * Not part of the public {@link ToolCallChunk} type; integrations may attach\n * `isCustomTool` at runtime and pass chunks typed as this alias.\n */\nexport type RawInputToolCallChunk = ToolCallChunk & { isCustomTool?: boolean };\n\nfunction chunkUsesRawInputArgs(chunk: ToolCallChunk): boolean {\n return (chunk as RawInputToolCallChunk).isCustomTool === true;\n}\n\n/**\n * Extracts the explicitly declared keys from a type T.\n *\n * @template T - The type to extract keys from\n * @returns A union of keys that are not string, number, or symbol\n */\ntype $KnownKeys<T> = {\n [K in keyof T]: string extends K\n ? never\n : number extends K\n ? never\n : symbol extends K\n ? never\n : K;\n}[keyof T];\n\n/**\n * Detects if T has an index signature.\n *\n * @template T - The type to check for index signatures\n * @returns True if T has an index signature, false otherwise\n */\ntype $HasIndexSignature<T> = string extends keyof T\n ? true\n : number extends keyof T\n ? true\n : symbol extends keyof T\n ? true\n : false;\n\n/**\n * Detects if T has an index signature and no known keys.\n *\n * @template T - The type to check for index signatures and no known keys\n * @returns True if T has an index signature and no known keys, false otherwise\n */\ntype $OnlyIndexSignatures<T> =\n $HasIndexSignature<T> extends true\n ? [$KnownKeys<T>] extends [never]\n ? true\n : false\n : false;\n\n/**\n * Recursively merges two object types T and U, with U taking precedence over T.\n *\n * This utility type performs a deep merge of two object types:\n * - For keys that exist in both T and U:\n * - If both values are objects (Record<string, unknown>), recursively merge them\n * - Otherwise, U's value takes precedence\n * - For keys that exist only in T, use T's value\n * - For keys that exist only in U, use U's value\n *\n * @template T - The first object type to merge\n * @template U - The second object type to merge (takes precedence over T)\n *\n * @example\n * ```ts\n * type ObjectA = {\n * shared: { a: string; b: number };\n * onlyInA: boolean;\n * };\n *\n * type ObjectB = {\n * shared: { b: string; c: Date };\n * onlyInB: symbol;\n * };\n *\n * type Merged = $MergeObjects<ObjectA, ObjectB>;\n * // Result: {\n * // shared: { a: string; b: string; c: Date };\n * // onlyInA: boolean;\n * // onlyInB: symbol;\n * // }\n * ```\n */\nexport type $MergeObjects<T, U> =\n // If U is purely index-signature based, prefer U as a whole\n $OnlyIndexSignatures<U> extends true\n ? U\n : // If T is purely index-signature based, prefer U as a whole (prevents leaking broad index signatures)\n $OnlyIndexSignatures<T> extends true\n ? U\n : {\n [K in keyof T | keyof U]: K extends keyof T\n ? K extends keyof U\n ? T[K] extends Record<string, unknown>\n ? U[K] extends Record<string, unknown>\n ? $MergeObjects<T[K], U[K]>\n : U[K]\n : U[K]\n : T[K]\n : K extends keyof U\n ? U[K]\n : never;\n };\n\n/**\n * Merges two discriminated unions A and B based on a discriminator key (defaults to \"type\").\n * For each possible value of the discriminator across both unions:\n * - If B has a member with that discriminator value, use B's member\n * - Otherwise use A's member with that discriminator value\n * This effectively merges the unions while giving B's members precedence over A's members.\n *\n * @template A - First discriminated union type that extends Record<Key, PropertyKey>\n * @template B - Second discriminated union type that extends Record<Key, PropertyKey>\n * @template Key - The discriminator key property, defaults to \"type\"\n */\nexport type $MergeDiscriminatedUnion<\n A extends Record<Key, PropertyKey>,\n B extends Record<Key, PropertyKey>,\n Key extends PropertyKey = \"type\",\n> = {\n // Create a mapped type over all possible discriminator values from both A and B\n [T in A[Key] | B[Key]]: [Extract<B, Record<Key, T>>] extends [never] // Check if B has a member with this discriminator value\n ? // If B doesn't have this discriminator value, use A's member\n Extract<A, Record<Key, T>>\n : // If B does have this discriminator value, merge A's and B's members (B takes precedence)\n [Extract<A, Record<Key, T>>] extends [never]\n ? Extract<B, Record<Key, T>>\n : $MergeObjects<Extract<A, Record<Key, T>>, Extract<B, Record<Key, T>>>;\n // Index into the mapped type with all possible discriminator values\n // This converts the mapped type back into a union\n}[A[Key] | B[Key]];\n\nexport type Constructor<T> = new (...args: unknown[]) => T;\n\n/**\n * Immediately-invoked function expression.\n *\n * @param fn - The function to execute\n * @returns The result of the function\n */\nexport const iife = <T>(fn: () => T) => fn();\n\nfunction _coerceToolCall(\n toolCall: ToolCall | Record<string, unknown>\n): ToolCall {\n if (_isToolCall(toolCall)) {\n return toolCall;\n } else if (\n typeof toolCall.id === \"string\" &&\n toolCall.type === \"function\" &&\n typeof toolCall.function === \"object\" &&\n toolCall.function !== null &&\n \"arguments\" in toolCall.function &&\n typeof toolCall.function.arguments === \"string\" &&\n \"name\" in toolCall.function &&\n typeof toolCall.function.name === \"string\"\n ) {\n // Handle OpenAI tool call format\n return {\n id: toolCall.id,\n args: JSON.parse(toolCall.function.arguments),\n name: toolCall.function.name,\n type: \"tool_call\",\n };\n } else {\n // TODO: Throw an error?\n return toolCall as unknown as ToolCall;\n }\n}\n\nfunction isSerializedConstructor(x: unknown): x is SerializedConstructor {\n return (\n typeof x === \"object\" &&\n x != null &&\n (x as SerializedConstructor).lc === 1 &&\n Array.isArray((x as SerializedConstructor).id) &&\n (x as SerializedConstructor).kwargs != null &&\n typeof (x as SerializedConstructor).kwargs === \"object\"\n );\n}\n\nfunction _constructMessageFromParams(\n params:\n | (BaseMessageFields & { type: string } & Record<string, unknown>)\n | SerializedConstructor\n) {\n let type: string;\n let rest: BaseMessageFields & Record<string, unknown>;\n // Support serialized messages\n if (isSerializedConstructor(params)) {\n const className = params.id.at(-1);\n if (className === \"HumanMessage\" || className === \"HumanMessageChunk\") {\n type = \"user\";\n } else if (className === \"AIMessage\" || className === \"AIMessageChunk\") {\n type = \"assistant\";\n } else if (\n className === \"SystemMessage\" ||\n className === \"SystemMessageChunk\"\n ) {\n type = \"system\";\n } else if (\n className === \"FunctionMessage\" ||\n className === \"FunctionMessageChunk\"\n ) {\n type = \"function\";\n } else if (\n className === \"ToolMessage\" ||\n className === \"ToolMessageChunk\"\n ) {\n type = \"tool\";\n } else {\n type = \"unknown\";\n }\n rest = params.kwargs as BaseMessageFields;\n } else {\n const { type: extractedType, ...otherParams } = params;\n type = extractedType;\n rest = otherParams;\n }\n if (type === \"human\" || type === \"user\") {\n return new HumanMessage(rest);\n } else if (type === \"ai\" || type === \"assistant\") {\n const { tool_calls: rawToolCalls, ...other } = rest;\n if (!Array.isArray(rawToolCalls)) {\n return new AIMessage(rest);\n }\n const tool_calls = rawToolCalls.map(_coerceToolCall);\n return new AIMessage({ ...other, tool_calls });\n } else if (type === \"system\") {\n return new SystemMessage(rest);\n } else if (type === \"developer\") {\n return new SystemMessage({\n ...rest,\n additional_kwargs: {\n ...rest.additional_kwargs,\n __openai_role__: \"developer\",\n },\n });\n } else if (type === \"tool\" && \"tool_call_id\" in rest) {\n return new ToolMessage({\n ...rest,\n content: rest.content,\n tool_call_id: rest.tool_call_id as string,\n name: rest.name,\n });\n } else if (type === \"remove\" && \"id\" in rest && typeof rest.id === \"string\") {\n return new RemoveMessage({ ...rest, id: rest.id });\n } else {\n const error = addLangChainErrorFields(\n new Error(\n `Unable to coerce message from array: only human, AI, system, developer, or tool message coercion is currently supported.\\n\\nReceived: ${JSON.stringify(\n params,\n null,\n 2\n )}`\n ),\n \"MESSAGE_COERCION_FAILURE\"\n );\n throw error;\n }\n}\n\nexport function coerceMessageLikeToMessage(\n messageLike: BaseMessageLike\n): BaseMessage {\n if (typeof messageLike === \"string\") {\n return new HumanMessage(messageLike);\n } else if (isBaseMessage(messageLike)) {\n return messageLike;\n }\n if (Array.isArray(messageLike)) {\n const [type, content] = messageLike;\n return _constructMessageFromParams({ type, content });\n } else if (_isMessageFieldWithRole(messageLike)) {\n const { role: type, ...rest } = messageLike;\n return _constructMessageFromParams({ ...rest, type });\n } else {\n return _constructMessageFromParams(messageLike);\n }\n}\n\n/**\n * Renders a single content block to a compact string representation.\n * Text blocks are returned as-is; multimodal blocks (image, audio, video, file)\n * become short placeholders like `[image]` so their existence is preserved\n * without inflating token counts with base64 data or metadata.\n */\nfunction _contentBlockToString(\n block: string | { type?: string; [key: string]: unknown }\n): string {\n if (typeof block === \"string\") return block;\n switch (block.type) {\n case \"text\":\n return (block as { text: string }).text ?? \"\";\n case \"text-plain\":\n return (block as { text?: string }).text ?? \"[text-plain file]\";\n case \"image\":\n case \"image_url\":\n return \"[image]\";\n case \"audio\":\n case \"input_audio\":\n return \"[audio]\";\n case \"video\":\n return \"[video]\";\n case \"file\":\n return \"[file]\";\n case \"reasoning\":\n case \"tool_call\":\n case \"tool_call_chunk\":\n case \"invalid_tool_call\":\n case \"server_tool_call\":\n case \"server_tool_call_chunk\":\n case \"server_tool_call_result\":\n case \"non_standard\":\n return \"\";\n default:\n return block.type ? `[${block.type}]` : \"\";\n }\n}\n\n/**\n * This function is used by memory classes to get a string representation\n * of the chat message history, based on the message content and role.\n *\n * Produces compact output like:\n * ```\n * Human: What's the weather?\n * AI: Let me check...[tool_calls]\n * Tool: 72°F and sunny\n * ```\n *\n * This avoids token inflation from metadata when stringifying message objects directly.\n */\nexport function getBufferString(\n messages: BaseMessage[],\n humanPrefix = \"Human\",\n aiPrefix = \"AI\"\n): string {\n const string_messages: string[] = [];\n for (const m of messages) {\n let role: string;\n if (m.type === \"human\") {\n role = humanPrefix;\n } else if (m.type === \"ai\") {\n role = aiPrefix;\n } else if (m.type === \"system\") {\n role = \"System\";\n } else if (m.type === \"tool\") {\n role = \"Tool\";\n } else if (m.type === \"generic\") {\n role = (m as ChatMessage).role;\n } else {\n throw new Error(`Got unsupported message type: ${m.type}`);\n }\n const nameStr = m.name ? `${m.name}, ` : \"\";\n\n // Render content compactly: text as-is, multimodal blocks as placeholders\n const readableContent =\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content.map(_contentBlockToString).filter(Boolean).join(\"\")\n : \"\";\n\n let message = `${role}: ${nameStr}${readableContent}`;\n\n // Include tool calls for AI messages (matching Python's get_buffer_string behavior)\n if (m.type === \"ai\") {\n const aiMessage = m as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n message += JSON.stringify(aiMessage.tool_calls);\n } else if (\n aiMessage.additional_kwargs &&\n \"function_call\" in aiMessage.additional_kwargs\n ) {\n // Legacy behavior assumes only one function call per message\n message += JSON.stringify(aiMessage.additional_kwargs.function_call);\n }\n }\n\n string_messages.push(message);\n }\n return string_messages.join(\"\\n\");\n}\n\n/**\n * Maps messages from an older format (V1) to the current `StoredMessage`\n * format. If the message is already in the `StoredMessage` format, it is\n * returned as is. Otherwise, it transforms the V1 message into a\n * `StoredMessage`. This function is important for maintaining\n * compatibility with older message formats.\n */\nfunction mapV1MessageToStoredMessage(\n message: StoredMessage | StoredMessageV1\n): StoredMessage {\n // TODO: Remove this mapper when we deprecate the old message format.\n if ((message as StoredMessage).data !== undefined) {\n return message as StoredMessage;\n } else {\n const v1Message = message as StoredMessageV1;\n return {\n type: v1Message.type,\n data: {\n content: v1Message.text,\n role: v1Message.role,\n name: undefined,\n tool_call_id: undefined,\n },\n };\n }\n}\n\nexport function mapStoredMessageToChatMessage(message: StoredMessage) {\n const storedMessage = mapV1MessageToStoredMessage(message);\n switch (storedMessage.type) {\n case \"human\":\n return new HumanMessage(storedMessage.data);\n case \"ai\":\n return new AIMessage(storedMessage.data);\n case \"system\":\n return new SystemMessage(storedMessage.data);\n case \"function\":\n if (storedMessage.data.name === undefined) {\n throw new Error(\"Name must be defined for function messages\");\n }\n return new FunctionMessage(storedMessage.data as FunctionMessageFields);\n case \"tool\":\n if (storedMessage.data.tool_call_id === undefined) {\n throw new Error(\"Tool call ID must be defined for tool messages\");\n }\n return new ToolMessage(storedMessage.data as ToolMessageFields);\n case \"generic\": {\n if (storedMessage.data.role === undefined) {\n throw new Error(\"Role must be defined for chat messages\");\n }\n return new ChatMessage(storedMessage.data as ChatMessageFields);\n }\n default:\n throw new Error(`Got unexpected type: ${storedMessage.type}`);\n }\n}\n\n/**\n * Transforms an array of `StoredMessage` instances into an array of\n * `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`\n * function to ensure all messages are in the `StoredMessage` format, then\n * creates new instances of the appropriate `BaseMessage` subclass based\n * on the type of each message. This function is used to prepare stored\n * messages for use in a chat context.\n */\nexport function mapStoredMessagesToChatMessages(\n messages: StoredMessage[]\n): BaseMessage[] {\n return messages.map(mapStoredMessageToChatMessage);\n}\n\n/**\n * Transforms an array of `BaseMessage` instances into an array of\n * `StoredMessage` instances. It does this by calling the `toDict` method\n * on each `BaseMessage`, which returns a `StoredMessage`. This function\n * is used to prepare chat messages for storage.\n */\nexport function mapChatMessagesToStoredMessages(\n messages: BaseMessage[]\n): StoredMessage[] {\n return messages.map((message) => message.toDict());\n}\n\nexport function convertToChunk(message: BaseMessage) {\n const type = message._getType();\n if (type === \"human\") {\n return new HumanMessageChunk({ ...message });\n } else if (type === \"ai\") {\n let aiChunkFields: AIMessageChunkFields = {\n ...message,\n };\n if (\"tool_calls\" in aiChunkFields) {\n aiChunkFields = {\n ...aiChunkFields,\n tool_call_chunks: aiChunkFields.tool_calls?.map((tc) => ({\n ...tc,\n type: \"tool_call_chunk\",\n index: undefined,\n args: JSON.stringify(tc.args),\n })),\n };\n }\n return new AIMessageChunk({ ...aiChunkFields });\n } else if (type === \"system\") {\n return new SystemMessageChunk({ ...message });\n } else if (type === \"function\") {\n return new FunctionMessageChunk({ ...message });\n } else if (ChatMessage.isInstance(message)) {\n return new ChatMessageChunk({ ...message });\n } else {\n throw new Error(\"Unknown message type.\");\n }\n}\n\n/**\n * Collapses an array of tool call chunks into complete tool calls.\n *\n * This function groups tool call chunks by their id and/or index, then attempts to\n * parse and validate the accumulated arguments for each group. Successfully parsed\n * tool calls are returned as valid `ToolCall` objects, while malformed ones are\n * returned as `InvalidToolCall` objects.\n *\n * @param chunks - An array of `ToolCallChunk` objects to collapse\n * @returns An object containing:\n * - `tool_call_chunks`: The original input chunks\n * - `tool_calls`: An array of successfully parsed and validated tool calls\n * - `invalid_tool_calls`: An array of tool calls that failed parsing or validation\n *\n * @remarks\n * Chunks are grouped using the following matching logic:\n * - If a chunk has both an id and index, it matches chunks with the same id and index\n * - If a chunk has only an id, it matches chunks with the same id\n * - If a chunk has only an index, it matches chunks with the same index\n *\n * For each group, the function:\n * 1. Concatenates all `args` strings from the chunks\n * 2. Attempts to parse the concatenated string as JSON\n * 3. Validates that the result is a non-null object with a valid id\n * 4. Creates either a `ToolCall` (if valid) or `InvalidToolCall` (if invalid)\n */\nexport function collapseToolCallChunks(chunks: ToolCallChunk[]): {\n tool_call_chunks: ToolCallChunk[];\n tool_calls: ToolCall[];\n invalid_tool_calls: InvalidToolCall[];\n} {\n const groupedToolCallChunks = chunks.reduce((acc, chunk) => {\n const matchedChunkIndex = acc.findIndex(([match]) => {\n // If chunk has an id and index, match if both are present\n if (\n \"id\" in chunk &&\n chunk.id &&\n \"index\" in chunk &&\n chunk.index !== undefined\n ) {\n return chunk.id === match.id && chunk.index === match.index;\n }\n // If chunk has an id, we match on id\n if (\"id\" in chunk && chunk.id) {\n return chunk.id === match.id;\n }\n // If chunk has an index, we match on index\n if (\"index\" in chunk && chunk.index !== undefined) {\n return chunk.index === match.index;\n }\n return false;\n });\n if (matchedChunkIndex !== -1) {\n acc[matchedChunkIndex].push(chunk);\n } else {\n acc.push([chunk]);\n }\n return acc;\n }, [] as ToolCallChunk[][]);\n\n const toolCalls: ToolCall[] = [];\n const invalidToolCalls: InvalidToolCall[] = [];\n for (const chunks of groupedToolCallChunks) {\n let parsedArgs: Record<string, unknown> | null = null;\n const usesRawInputArgs = chunks.some(chunkUsesRawInputArgs);\n const name = chunks[0]?.name ?? \"\";\n const joinedArgsRaw = chunks.map((c) => c.args || \"\").join(\"\");\n const joinedArgs = usesRawInputArgs ? joinedArgsRaw : joinedArgsRaw.trim();\n const argsStr = joinedArgs.length ? joinedArgs : \"{}\";\n const id = chunks.find((c) => c.id)?.id ?? chunks[0]?.id;\n if (usesRawInputArgs && id) {\n toolCalls.push({\n name,\n args: { input: joinedArgs },\n id,\n type: \"tool_call\",\n });\n continue;\n }\n try {\n parsedArgs = parsePartialJson(argsStr);\n if (\n !id ||\n parsedArgs === null ||\n typeof parsedArgs !== \"object\" ||\n Array.isArray(parsedArgs)\n ) {\n throw new Error(\"Malformed tool call chunk args.\");\n }\n toolCalls.push({\n name,\n args: parsedArgs,\n id,\n type: \"tool_call\",\n });\n } catch {\n invalidToolCalls.push({\n name,\n args: argsStr,\n id,\n error: \"Malformed args.\",\n type: \"invalid_tool_call\",\n });\n }\n }\n return {\n tool_call_chunks: chunks,\n tool_calls: toolCalls,\n invalid_tool_calls: invalidToolCalls,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.cjs","names":["_isToolCall","HumanMessage","AIMessage","SystemMessage","ToolMessage","RemoveMessage","addLangChainErrorFields","isBaseMessage","_isMessageFieldWithRole","FunctionMessage","ChatMessage","HumanMessageChunk","AIMessageChunk","SystemMessageChunk","FunctionMessageChunk","ChatMessageChunk","parsePartialJson"],"sources":["../../src/messages/utils.ts"],"sourcesContent":["import { addLangChainErrorFields } from \"../errors/index.js\";\nimport { SerializedConstructor } from \"../load/serializable.js\";\nimport { _isToolCall } from \"../tools/utils.js\";\nimport { parsePartialJson } from \"../utils/json.js\";\nimport { AIMessage, AIMessageChunk, AIMessageChunkFields } from \"./ai.js\";\nimport {\n BaseMessageLike,\n BaseMessage,\n isBaseMessage,\n StoredMessage,\n StoredMessageV1,\n BaseMessageFields,\n _isMessageFieldWithRole,\n} from \"./base.js\";\nimport { ChatMessage, ChatMessageFields, ChatMessageChunk } from \"./chat.js\";\nimport {\n FunctionMessage,\n FunctionMessageChunk,\n FunctionMessageFields,\n} from \"./function.js\";\nimport { HumanMessage, HumanMessageChunk } from \"./human.js\";\nimport { RemoveMessage } from \"./modifier.js\";\nimport { SystemMessage, SystemMessageChunk } from \"./system.js\";\nimport {\n InvalidToolCall,\n ToolCall,\n ToolCallChunk,\n ToolMessage,\n ToolMessageFields,\n} from \"./tool.js\";\n\nexport type $Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;\n\n/**\n * Provider streaming marker for raw (non-JSON) tool input.\n * Not part of the public {@link ToolCallChunk} type; integrations may attach\n * `isCustomTool` at runtime and pass chunks typed as this alias.\n */\nexport type RawInputToolCallChunk = ToolCallChunk & { isCustomTool?: boolean };\n\nfunction chunkUsesRawInputArgs(chunk: ToolCallChunk): boolean {\n return (chunk as RawInputToolCallChunk).isCustomTool === true;\n}\n\n/**\n * Extracts the explicitly declared keys from a type T.\n *\n * @template T - The type to extract keys from\n * @returns A union of keys that are not string, number, or symbol\n */\ntype $KnownKeys<T> = {\n [K in keyof T]: string extends K\n ? never\n : number extends K\n ? never\n : symbol extends K\n ? never\n : K;\n}[keyof T];\n\n/**\n * Detects if T has an index signature.\n *\n * @template T - The type to check for index signatures\n * @returns True if T has an index signature, false otherwise\n */\ntype $HasIndexSignature<T> = string extends keyof T\n ? true\n : number extends keyof T\n ? true\n : symbol extends keyof T\n ? true\n : false;\n\n/**\n * Detects if T has an index signature and no known keys.\n *\n * @template T - The type to check for index signatures and no known keys\n * @returns True if T has an index signature and no known keys, false otherwise\n */\ntype $OnlyIndexSignatures<T> =\n $HasIndexSignature<T> extends true\n ? [$KnownKeys<T>] extends [never]\n ? true\n : false\n : false;\n\n/**\n * Recursively merges two object types T and U, with U taking precedence over T.\n *\n * This utility type performs a deep merge of two object types:\n * - For keys that exist in both T and U:\n * - If both values are objects (Record<string, unknown>), recursively merge them\n * - Otherwise, U's value takes precedence\n * - For keys that exist only in T, use T's value\n * - For keys that exist only in U, use U's value\n *\n * @template T - The first object type to merge\n * @template U - The second object type to merge (takes precedence over T)\n *\n * @example\n * ```ts\n * type ObjectA = {\n * shared: { a: string; b: number };\n * onlyInA: boolean;\n * };\n *\n * type ObjectB = {\n * shared: { b: string; c: Date };\n * onlyInB: symbol;\n * };\n *\n * type Merged = $MergeObjects<ObjectA, ObjectB>;\n * // Result: {\n * // shared: { a: string; b: string; c: Date };\n * // onlyInA: boolean;\n * // onlyInB: symbol;\n * // }\n * ```\n */\nexport type $MergeObjects<T, U> =\n // If U is purely index-signature based, prefer U as a whole\n $OnlyIndexSignatures<U> extends true\n ? U\n : // If T is purely index-signature based, prefer U as a whole (prevents leaking broad index signatures)\n $OnlyIndexSignatures<T> extends true\n ? U\n : {\n [K in keyof T | keyof U]: K extends keyof T\n ? K extends keyof U\n ? T[K] extends Record<string, unknown>\n ? U[K] extends Record<string, unknown>\n ? $MergeObjects<T[K], U[K]>\n : U[K]\n : U[K]\n : T[K]\n : K extends keyof U\n ? U[K]\n : never;\n };\n\n/**\n * Merges two discriminated unions A and B based on a discriminator key (defaults to \"type\").\n * For each possible value of the discriminator across both unions:\n * - If B has a member with that discriminator value, use B's member\n * - Otherwise use A's member with that discriminator value\n * This effectively merges the unions while giving B's members precedence over A's members.\n *\n * @template A - First discriminated union type that extends Record<Key, PropertyKey>\n * @template B - Second discriminated union type that extends Record<Key, PropertyKey>\n * @template Key - The discriminator key property, defaults to \"type\"\n */\nexport type $MergeDiscriminatedUnion<\n A extends Record<Key, PropertyKey>,\n B extends Record<Key, PropertyKey>,\n Key extends PropertyKey = \"type\",\n> = {\n // Create a mapped type over all possible discriminator values from both A and B\n [T in A[Key] | B[Key]]: [Extract<B, Record<Key, T>>] extends [never] // Check if B has a member with this discriminator value\n ? // If B doesn't have this discriminator value, use A's member\n Extract<A, Record<Key, T>>\n : // If B does have this discriminator value, merge A's and B's members (B takes precedence)\n [Extract<A, Record<Key, T>>] extends [never]\n ? Extract<B, Record<Key, T>>\n : $MergeObjects<Extract<A, Record<Key, T>>, Extract<B, Record<Key, T>>>;\n // Index into the mapped type with all possible discriminator values\n // This converts the mapped type back into a union\n}[A[Key] | B[Key]];\n\nexport type Constructor<T> = new (...args: unknown[]) => T;\n\n/**\n * Immediately-invoked function expression.\n *\n * @param fn - The function to execute\n * @returns The result of the function\n */\nexport const iife = <T>(fn: () => T) => fn();\n\nfunction _coerceToolCall(\n toolCall: ToolCall | Record<string, unknown>\n): ToolCall {\n if (_isToolCall(toolCall)) {\n return toolCall;\n } else if (\n typeof toolCall.id === \"string\" &&\n toolCall.type === \"function\" &&\n typeof toolCall.function === \"object\" &&\n toolCall.function !== null &&\n \"arguments\" in toolCall.function &&\n typeof toolCall.function.arguments === \"string\" &&\n \"name\" in toolCall.function &&\n typeof toolCall.function.name === \"string\"\n ) {\n // Handle OpenAI tool call format\n return {\n id: toolCall.id,\n args: JSON.parse(toolCall.function.arguments),\n name: toolCall.function.name,\n type: \"tool_call\",\n };\n } else {\n // TODO: Throw an error?\n return toolCall as unknown as ToolCall;\n }\n}\n\nfunction isSerializedConstructor(x: unknown): x is SerializedConstructor {\n return (\n typeof x === \"object\" &&\n x != null &&\n (x as SerializedConstructor).lc === 1 &&\n Array.isArray((x as SerializedConstructor).id) &&\n (x as SerializedConstructor).kwargs != null &&\n typeof (x as SerializedConstructor).kwargs === \"object\"\n );\n}\n\nfunction _constructMessageFromParams(\n params:\n | (BaseMessageFields & { type: string } & Record<string, unknown>)\n | SerializedConstructor\n) {\n let type: string;\n let rest: BaseMessageFields & Record<string, unknown>;\n // Support serialized messages\n if (isSerializedConstructor(params)) {\n const className = params.id.at(-1);\n if (className === \"HumanMessage\" || className === \"HumanMessageChunk\") {\n type = \"user\";\n } else if (className === \"AIMessage\" || className === \"AIMessageChunk\") {\n type = \"assistant\";\n } else if (\n className === \"SystemMessage\" ||\n className === \"SystemMessageChunk\"\n ) {\n type = \"system\";\n } else if (\n className === \"FunctionMessage\" ||\n className === \"FunctionMessageChunk\"\n ) {\n type = \"function\";\n } else if (\n className === \"ToolMessage\" ||\n className === \"ToolMessageChunk\"\n ) {\n type = \"tool\";\n } else {\n type = \"unknown\";\n }\n rest = params.kwargs as BaseMessageFields;\n } else {\n const { type: extractedType, ...otherParams } = params;\n type = extractedType;\n rest = otherParams;\n }\n if (type === \"human\" || type === \"user\") {\n return new HumanMessage(rest);\n } else if (type === \"ai\" || type === \"assistant\") {\n const { tool_calls: rawToolCalls, ...other } = rest;\n if (!Array.isArray(rawToolCalls)) {\n return new AIMessage(rest);\n }\n const tool_calls = rawToolCalls.map(_coerceToolCall);\n return new AIMessage({ ...other, tool_calls });\n } else if (type === \"system\") {\n return new SystemMessage(rest);\n } else if (type === \"developer\") {\n return new SystemMessage({\n ...rest,\n additional_kwargs: {\n ...rest.additional_kwargs,\n __openai_role__: \"developer\",\n },\n });\n } else if (type === \"tool\" && \"tool_call_id\" in rest) {\n return new ToolMessage({\n ...rest,\n content: rest.content,\n tool_call_id: rest.tool_call_id as string,\n name: rest.name,\n });\n } else if (type === \"remove\" && \"id\" in rest && typeof rest.id === \"string\") {\n return new RemoveMessage({ ...rest, id: rest.id });\n } else {\n const error = addLangChainErrorFields(\n new Error(\n `Unable to coerce message from array: only human, AI, system, developer, or tool message coercion is currently supported.\\n\\nReceived: ${JSON.stringify(\n params,\n null,\n 2\n )}`\n ),\n \"MESSAGE_COERCION_FAILURE\"\n );\n throw error;\n }\n}\n\nexport function coerceMessageLikeToMessage(\n messageLike: BaseMessageLike\n): BaseMessage {\n if (typeof messageLike === \"string\") {\n return new HumanMessage(messageLike);\n } else if (isBaseMessage(messageLike)) {\n return messageLike;\n }\n if (Array.isArray(messageLike)) {\n const [type, content] = messageLike;\n return _constructMessageFromParams({ type, content });\n } else if (_isMessageFieldWithRole(messageLike)) {\n const { role: type, ...rest } = messageLike;\n return _constructMessageFromParams({ ...rest, type });\n } else {\n return _constructMessageFromParams(messageLike);\n }\n}\n\n/**\n * Renders a single content block to a compact string representation.\n * Text blocks are returned as-is; multimodal blocks (image, audio, video, file)\n * become short placeholders like `[image]` so their existence is preserved\n * without inflating token counts with base64 data or metadata.\n */\nfunction _contentBlockToString(\n block: string | { type?: string; [key: string]: unknown }\n): string {\n if (typeof block === \"string\") return block;\n switch (block.type) {\n case \"text\":\n return (block as { text: string }).text ?? \"\";\n case \"text-plain\":\n return (block as { text?: string }).text ?? \"[text-plain file]\";\n case \"image\":\n case \"image_url\":\n return \"[image]\";\n case \"audio\":\n case \"input_audio\":\n return \"[audio]\";\n case \"video\":\n return \"[video]\";\n case \"file\":\n return \"[file]\";\n case \"reasoning\":\n case \"tool_call\":\n case \"tool_call_chunk\":\n case \"invalid_tool_call\":\n case \"server_tool_call\":\n case \"server_tool_call_chunk\":\n case \"server_tool_call_result\":\n case \"non_standard\":\n return \"\";\n default:\n return block.type ? `[${block.type}]` : \"\";\n }\n}\n\nconst TOOL_CALL_ID_DISPLAY_LIMIT = 64;\n\n/**\n * This function is used by memory classes to get a string representation\n * of the chat message history, based on the message content and role.\n *\n * Produces compact output like:\n * ```\n * Human: What's the weather?\n * AI: Let me check...[tool_calls]\n * Tool: 72°F and sunny\n * ```\n *\n * This avoids token inflation from metadata when stringifying message objects directly.\n * Tool-call IDs longer than 64 characters are shortened only in the rendered string.\n */\nexport function getBufferString(\n messages: BaseMessage[],\n humanPrefix = \"Human\",\n aiPrefix = \"AI\"\n): string {\n const string_messages: string[] = [];\n for (const m of messages) {\n let role: string;\n if (m.type === \"human\") {\n role = humanPrefix;\n } else if (m.type === \"ai\") {\n role = aiPrefix;\n } else if (m.type === \"system\") {\n role = \"System\";\n } else if (m.type === \"tool\") {\n role = \"Tool\";\n } else if (m.type === \"generic\") {\n role = (m as ChatMessage).role;\n } else {\n throw new Error(`Got unsupported message type: ${m.type}`);\n }\n const nameStr = m.name ? `${m.name}, ` : \"\";\n\n // Render content compactly: text as-is, multimodal blocks as placeholders\n const readableContent =\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content.map(_contentBlockToString).filter(Boolean).join(\"\")\n : \"\";\n\n let message = `${role}: ${nameStr}${readableContent}`;\n\n // Include tool calls for AI messages (matching Python's get_buffer_string behavior)\n if (m.type === \"ai\") {\n const aiMessage = m as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n const toolCalls = aiMessage.tool_calls;\n message += JSON.stringify(\n toolCalls.some(\n (call) => (call.id?.length ?? 0) > TOOL_CALL_ID_DISPLAY_LIMIT\n )\n ? toolCalls.map((call) =>\n call.id && call.id.length > TOOL_CALL_ID_DISPLAY_LIMIT\n ? {\n ...call,\n id: `${call.id.slice(0, TOOL_CALL_ID_DISPLAY_LIMIT)}...`,\n }\n : call\n )\n : toolCalls\n );\n } else if (\n aiMessage.additional_kwargs &&\n \"function_call\" in aiMessage.additional_kwargs\n ) {\n // Legacy behavior assumes only one function call per message\n message += JSON.stringify(aiMessage.additional_kwargs.function_call);\n }\n }\n\n string_messages.push(message);\n }\n return string_messages.join(\"\\n\");\n}\n\n/**\n * Maps messages from an older format (V1) to the current `StoredMessage`\n * format. If the message is already in the `StoredMessage` format, it is\n * returned as is. Otherwise, it transforms the V1 message into a\n * `StoredMessage`. This function is important for maintaining\n * compatibility with older message formats.\n */\nfunction mapV1MessageToStoredMessage(\n message: StoredMessage | StoredMessageV1\n): StoredMessage {\n // TODO: Remove this mapper when we deprecate the old message format.\n if ((message as StoredMessage).data !== undefined) {\n return message as StoredMessage;\n } else {\n const v1Message = message as StoredMessageV1;\n return {\n type: v1Message.type,\n data: {\n content: v1Message.text,\n role: v1Message.role,\n name: undefined,\n tool_call_id: undefined,\n },\n };\n }\n}\n\nexport function mapStoredMessageToChatMessage(message: StoredMessage) {\n const storedMessage = mapV1MessageToStoredMessage(message);\n switch (storedMessage.type) {\n case \"human\":\n return new HumanMessage(storedMessage.data);\n case \"ai\":\n return new AIMessage(storedMessage.data);\n case \"system\":\n return new SystemMessage(storedMessage.data);\n case \"function\":\n if (storedMessage.data.name === undefined) {\n throw new Error(\"Name must be defined for function messages\");\n }\n return new FunctionMessage(storedMessage.data as FunctionMessageFields);\n case \"tool\":\n if (storedMessage.data.tool_call_id === undefined) {\n throw new Error(\"Tool call ID must be defined for tool messages\");\n }\n return new ToolMessage(storedMessage.data as ToolMessageFields);\n case \"generic\": {\n if (storedMessage.data.role === undefined) {\n throw new Error(\"Role must be defined for chat messages\");\n }\n return new ChatMessage(storedMessage.data as ChatMessageFields);\n }\n default:\n throw new Error(`Got unexpected type: ${storedMessage.type}`);\n }\n}\n\n/**\n * Transforms an array of `StoredMessage` instances into an array of\n * `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`\n * function to ensure all messages are in the `StoredMessage` format, then\n * creates new instances of the appropriate `BaseMessage` subclass based\n * on the type of each message. This function is used to prepare stored\n * messages for use in a chat context.\n */\nexport function mapStoredMessagesToChatMessages(\n messages: StoredMessage[]\n): BaseMessage[] {\n return messages.map(mapStoredMessageToChatMessage);\n}\n\n/**\n * Transforms an array of `BaseMessage` instances into an array of\n * `StoredMessage` instances. It does this by calling the `toDict` method\n * on each `BaseMessage`, which returns a `StoredMessage`. This function\n * is used to prepare chat messages for storage.\n */\nexport function mapChatMessagesToStoredMessages(\n messages: BaseMessage[]\n): StoredMessage[] {\n return messages.map((message) => message.toDict());\n}\n\nexport function convertToChunk(message: BaseMessage) {\n const type = message._getType();\n if (type === \"human\") {\n return new HumanMessageChunk({ ...message });\n } else if (type === \"ai\") {\n let aiChunkFields: AIMessageChunkFields = {\n ...message,\n };\n if (\"tool_calls\" in aiChunkFields) {\n aiChunkFields = {\n ...aiChunkFields,\n tool_call_chunks: aiChunkFields.tool_calls?.map((tc) => ({\n ...tc,\n type: \"tool_call_chunk\",\n index: undefined,\n args: JSON.stringify(tc.args),\n })),\n };\n }\n return new AIMessageChunk({ ...aiChunkFields });\n } else if (type === \"system\") {\n return new SystemMessageChunk({ ...message });\n } else if (type === \"function\") {\n return new FunctionMessageChunk({ ...message });\n } else if (ChatMessage.isInstance(message)) {\n return new ChatMessageChunk({ ...message });\n } else {\n throw new Error(\"Unknown message type.\");\n }\n}\n\n/**\n * Collapses an array of tool call chunks into complete tool calls.\n *\n * This function groups tool call chunks by their id and/or index, then attempts to\n * parse and validate the accumulated arguments for each group. Successfully parsed\n * tool calls are returned as valid `ToolCall` objects, while malformed ones are\n * returned as `InvalidToolCall` objects.\n *\n * @param chunks - An array of `ToolCallChunk` objects to collapse\n * @returns An object containing:\n * - `tool_call_chunks`: The original input chunks\n * - `tool_calls`: An array of successfully parsed and validated tool calls\n * - `invalid_tool_calls`: An array of tool calls that failed parsing or validation\n *\n * @remarks\n * Chunks are grouped using the following matching logic:\n * - If a chunk has both an id and index, it matches chunks with the same id and index\n * - If a chunk has only an id, it matches chunks with the same id\n * - If a chunk has only an index, it matches chunks with the same index\n *\n * For each group, the function:\n * 1. Concatenates all `args` strings from the chunks\n * 2. Attempts to parse the concatenated string as JSON\n * 3. Validates that the result is a non-null object with a valid id\n * 4. Creates either a `ToolCall` (if valid) or `InvalidToolCall` (if invalid)\n */\nexport function collapseToolCallChunks(chunks: ToolCallChunk[]): {\n tool_call_chunks: ToolCallChunk[];\n tool_calls: ToolCall[];\n invalid_tool_calls: InvalidToolCall[];\n} {\n const groupedToolCallChunks = chunks.reduce((acc, chunk) => {\n const matchedChunkIndex = acc.findIndex(([match]) => {\n // If chunk has an id and index, match if both are present\n if (\n \"id\" in chunk &&\n chunk.id &&\n \"index\" in chunk &&\n chunk.index !== undefined\n ) {\n return chunk.id === match.id && chunk.index === match.index;\n }\n // If chunk has an id, we match on id\n if (\"id\" in chunk && chunk.id) {\n return chunk.id === match.id;\n }\n // If chunk has an index, we match on index\n if (\"index\" in chunk && chunk.index !== undefined) {\n return chunk.index === match.index;\n }\n return false;\n });\n if (matchedChunkIndex !== -1) {\n acc[matchedChunkIndex].push(chunk);\n } else {\n acc.push([chunk]);\n }\n return acc;\n }, [] as ToolCallChunk[][]);\n\n const toolCalls: ToolCall[] = [];\n const invalidToolCalls: InvalidToolCall[] = [];\n for (const chunks of groupedToolCallChunks) {\n let parsedArgs: Record<string, unknown> | null = null;\n const usesRawInputArgs = chunks.some(chunkUsesRawInputArgs);\n const name = chunks[0]?.name ?? \"\";\n const joinedArgsRaw = chunks.map((c) => c.args || \"\").join(\"\");\n const joinedArgs = usesRawInputArgs ? joinedArgsRaw : joinedArgsRaw.trim();\n const argsStr = joinedArgs.length ? joinedArgs : \"{}\";\n const id = chunks.find((c) => c.id)?.id ?? chunks[0]?.id;\n if (usesRawInputArgs && id) {\n toolCalls.push({\n name,\n args: { input: joinedArgs },\n id,\n type: \"tool_call\",\n });\n continue;\n }\n try {\n parsedArgs = parsePartialJson(argsStr);\n if (\n !id ||\n parsedArgs === null ||\n typeof parsedArgs !== \"object\" ||\n Array.isArray(parsedArgs)\n ) {\n throw new Error(\"Malformed tool call chunk args.\");\n }\n toolCalls.push({\n name,\n args: parsedArgs,\n id,\n type: \"tool_call\",\n });\n } catch {\n invalidToolCalls.push({\n name,\n args: argsStr,\n id,\n error: \"Malformed args.\",\n type: \"invalid_tool_call\",\n });\n }\n }\n return {\n tool_call_chunks: chunks,\n tool_calls: toolCalls,\n invalid_tool_calls: invalidToolCalls,\n };\n}\n"],"mappings":"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"}
@@ -104,6 +104,7 @@ declare function coerceMessageLikeToMessage(messageLike: BaseMessageLike): BaseM
104
104
  * ```
105
105
  *
106
106
  * This avoids token inflation from metadata when stringifying message objects directly.
107
+ * Tool-call IDs longer than 64 characters are shortened only in the rendered string.
107
108
  */
108
109
  declare function getBufferString(messages: BaseMessage[], humanPrefix?: string, aiPrefix?: string): string;
109
110
  declare function mapStoredMessageToChatMessage(message: StoredMessage): AIMessage<MessageStructure<MessageToolSet>> | ChatMessage<MessageStructure<MessageToolSet>> | FunctionMessage<MessageStructure<MessageToolSet>> | HumanMessage<MessageStructure<MessageToolSet>> | SystemMessage<MessageStructure<MessageToolSet>> | ToolMessage<MessageStructure<MessageToolSet>>;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.cts","names":[],"sources":["../../src/messages/utils.ts"],"mappings":";;;;;;;;;KA+BY,QAAQ,KAAK,iBAAgB,QAAO,WAAW,IAAI,EAAE;;;;;;KAOrD,wBAAwB;EAAkB;;;;;;;;KAYjD,WAAW,QACb,WAAW,mBAAmB,2BAEZ,2BAEE,YAEb,WACF;;;;;;;KAQH,mBAAmB,0BAA0B,gCAEzB,gCAEE;;;;;;;KAUtB,qBAAqB,KACxB,mBAAmB,mBACd,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsCN,cAAc,GAAG,KAE3B,qBAAqB,kBACjB,IAEA,qBAAqB,kBACnB,OAEG,WAAW,UAAU,IAAI,gBAAgB,IACtC,gBAAgB,IACd,EAAE,WAAW,0BACX,EAAE,WAAW,0BACX,cAAc,EAAE,IAAI,EAAE,MACtB,EAAE,KACJ,EAAE,KACJ,EAAE,KACJ,gBAAgB,IACd,EAAE;;;;;;;;;;;;KAeN,yBACV,UAAU,OAAO,KAAK,cACtB,UAAU,OAAO,KAAK,cACtB,YAAY,2BAGX,KAAK,EAAE,OAAO,EAAE,QAAQ,QAAQ,GAAG,OAAO,KAAK,uBAE5C,QAAQ,GAAG,OAAO,KAAK,OAEtB,QAAQ,GAAG,OAAO,KAAK,uBACtB,QAAQ,GAAG,OAAO,KAAK,MACvB,cAAc,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,OAAO,KAAK,QAGvE,EAAE,OAAO,EAAE;KAED,YAAY,aAAa,oBAAoB;;;;;;;cAQ5C,OAAQ,GAAC,UAAY,MAAC;iBA0HnB,2BACd,aAAa,kBACZ;;;;;;;;;;;;;;iBAqEa,gBACd,UAAU,eACV,sBACA;iBA4Ec,8BAA8B,SAAS,gBAAa,UAAA,iBAAb,mBAAa,YAAA,iBAAA,mBAAA,gBAAA,iBAAA,mBAAA,aAAA,iBAAA,mBAAA,cAAA,iBAAA,mBAAA,YAAA,iBAAA;;;;;;;;;iBAsCpD,gCACd,UAAU,kBACT;;;;;;;iBAUa,gCACd,UAAU,gBACT;iBAIa,eAAe,SAAS,cAAW,eAAA,iBAAX,mBAAW,iBAAA,iBAAA,mBAAA,qBAAA,iBAAA,mBAAA,kBAAA,iBAAA,mBAAA,mBAAA,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDnC,uBAAuB,QAAQ;EAC7C,kBAAkB;EAClB,YAAY;EACZ,oBAAoB"}
1
+ {"version":3,"file":"utils.d.cts","names":[],"sources":["../../src/messages/utils.ts"],"mappings":";;;;;;;;;KA+BY,QAAQ,KAAK,iBAAgB,QAAO,WAAW,IAAI,EAAE;;;;;;KAOrD,wBAAwB;EAAkB;;;;;;;;KAYjD,WAAW,QACb,WAAW,mBAAmB,2BAEZ,2BAEE,YAEb,WACF;;;;;;;KAQH,mBAAmB,0BAA0B,gCAEzB,gCAEE;;;;;;;KAUtB,qBAAqB,KACxB,mBAAmB,mBACd,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsCN,cAAc,GAAG,KAE3B,qBAAqB,kBACjB,IAEA,qBAAqB,kBACnB,OAEG,WAAW,UAAU,IAAI,gBAAgB,IACtC,gBAAgB,IACd,EAAE,WAAW,0BACX,EAAE,WAAW,0BACX,cAAc,EAAE,IAAI,EAAE,MACtB,EAAE,KACJ,EAAE,KACJ,EAAE,KACJ,gBAAgB,IACd,EAAE;;;;;;;;;;;;KAeN,yBACV,UAAU,OAAO,KAAK,cACtB,UAAU,OAAO,KAAK,cACtB,YAAY,2BAGX,KAAK,EAAE,OAAO,EAAE,QAAQ,QAAQ,GAAG,OAAO,KAAK,uBAE5C,QAAQ,GAAG,OAAO,KAAK,OAEtB,QAAQ,GAAG,OAAO,KAAK,uBACtB,QAAQ,GAAG,OAAO,KAAK,MACvB,cAAc,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,OAAO,KAAK,QAGvE,EAAE,OAAO,EAAE;KAED,YAAY,aAAa,oBAAoB;;;;;;;cAQ5C,OAAQ,GAAC,UAAY,MAAC;iBA0HnB,2BACd,aAAa,kBACZ;;;;;;;;;;;;;;;iBAwEa,gBACd,UAAU,eACV,sBACA;iBA0Fc,8BAA8B,SAAS,gBAAa,UAAA,iBAAb,mBAAa,YAAA,iBAAA,mBAAA,gBAAA,iBAAA,mBAAA,aAAA,iBAAA,mBAAA,cAAA,iBAAA,mBAAA,YAAA,iBAAA;;;;;;;;;iBAsCpD,gCACd,UAAU,kBACT;;;;;;;iBAUa,gCACd,UAAU,gBACT;iBAIa,eAAe,SAAS,cAAW,eAAA,iBAAX,mBAAW,iBAAA,iBAAA,mBAAA,qBAAA,iBAAA,mBAAA,kBAAA,iBAAA,mBAAA,mBAAA,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDnC,uBAAuB,QAAQ;EAC7C,kBAAkB;EAClB,YAAY;EACZ,oBAAoB"}
@@ -104,6 +104,7 @@ declare function coerceMessageLikeToMessage(messageLike: BaseMessageLike): BaseM
104
104
  * ```
105
105
  *
106
106
  * This avoids token inflation from metadata when stringifying message objects directly.
107
+ * Tool-call IDs longer than 64 characters are shortened only in the rendered string.
107
108
  */
108
109
  declare function getBufferString(messages: BaseMessage[], humanPrefix?: string, aiPrefix?: string): string;
109
110
  declare function mapStoredMessageToChatMessage(message: StoredMessage): AIMessage<MessageStructure<MessageToolSet>> | ChatMessage<MessageStructure<MessageToolSet>> | FunctionMessage<MessageStructure<MessageToolSet>> | HumanMessage<MessageStructure<MessageToolSet>> | SystemMessage<MessageStructure<MessageToolSet>> | ToolMessage<MessageStructure<MessageToolSet>>;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/messages/utils.ts"],"mappings":";;;;;;;;;KA+BY,QAAQ,KAAK,iBAAgB,QAAO,WAAW,IAAI,EAAE;;;;;;KAOrD,wBAAwB;EAAkB;;;;;;;;KAYjD,WAAW,QACb,WAAW,mBAAmB,2BAEZ,2BAEE,YAEb,WACF;;;;;;;KAQH,mBAAmB,0BAA0B,gCAEzB,gCAEE;;;;;;;KAUtB,qBAAqB,KACxB,mBAAmB,mBACd,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsCN,cAAc,GAAG,KAE3B,qBAAqB,kBACjB,IAEA,qBAAqB,kBACnB,OAEG,WAAW,UAAU,IAAI,gBAAgB,IACtC,gBAAgB,IACd,EAAE,WAAW,0BACX,EAAE,WAAW,0BACX,cAAc,EAAE,IAAI,EAAE,MACtB,EAAE,KACJ,EAAE,KACJ,EAAE,KACJ,gBAAgB,IACd,EAAE;;;;;;;;;;;;KAeN,yBACV,UAAU,OAAO,KAAK,cACtB,UAAU,OAAO,KAAK,cACtB,YAAY,2BAGX,KAAK,EAAE,OAAO,EAAE,QAAQ,QAAQ,GAAG,OAAO,KAAK,uBAE5C,QAAQ,GAAG,OAAO,KAAK,OAEtB,QAAQ,GAAG,OAAO,KAAK,uBACtB,QAAQ,GAAG,OAAO,KAAK,MACvB,cAAc,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,OAAO,KAAK,QAGvE,EAAE,OAAO,EAAE;KAED,YAAY,aAAa,oBAAoB;;;;;;;cAQ5C,OAAQ,GAAC,UAAY,MAAC;iBA0HnB,2BACd,aAAa,kBACZ;;;;;;;;;;;;;;iBAqEa,gBACd,UAAU,eACV,sBACA;iBA4Ec,8BAA8B,SAAS,gBAAa,UAAA,iBAAb,mBAAa,YAAA,iBAAA,mBAAA,gBAAA,iBAAA,mBAAA,aAAA,iBAAA,mBAAA,cAAA,iBAAA,mBAAA,YAAA,iBAAA;;;;;;;;;iBAsCpD,gCACd,UAAU,kBACT;;;;;;;iBAUa,gCACd,UAAU,gBACT;iBAIa,eAAe,SAAS,cAAW,eAAA,iBAAX,mBAAW,iBAAA,iBAAA,mBAAA,qBAAA,iBAAA,mBAAA,kBAAA,iBAAA,mBAAA,mBAAA,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDnC,uBAAuB,QAAQ;EAC7C,kBAAkB;EAClB,YAAY;EACZ,oBAAoB"}
1
+ {"version":3,"file":"utils.d.ts","names":[],"sources":["../../src/messages/utils.ts"],"mappings":";;;;;;;;;KA+BY,QAAQ,KAAK,iBAAgB,QAAO,WAAW,IAAI,EAAE;;;;;;KAOrD,wBAAwB;EAAkB;;;;;;;;KAYjD,WAAW,QACb,WAAW,mBAAmB,2BAEZ,2BAEE,YAEb,WACF;;;;;;;KAQH,mBAAmB,0BAA0B,gCAEzB,gCAEE;;;;;;;KAUtB,qBAAqB,KACxB,mBAAmB,mBACd,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsCN,cAAc,GAAG,KAE3B,qBAAqB,kBACjB,IAEA,qBAAqB,kBACnB,OAEG,WAAW,UAAU,IAAI,gBAAgB,IACtC,gBAAgB,IACd,EAAE,WAAW,0BACX,EAAE,WAAW,0BACX,cAAc,EAAE,IAAI,EAAE,MACtB,EAAE,KACJ,EAAE,KACJ,EAAE,KACJ,gBAAgB,IACd,EAAE;;;;;;;;;;;;KAeN,yBACV,UAAU,OAAO,KAAK,cACtB,UAAU,OAAO,KAAK,cACtB,YAAY,2BAGX,KAAK,EAAE,OAAO,EAAE,QAAQ,QAAQ,GAAG,OAAO,KAAK,uBAE5C,QAAQ,GAAG,OAAO,KAAK,OAEtB,QAAQ,GAAG,OAAO,KAAK,uBACtB,QAAQ,GAAG,OAAO,KAAK,MACvB,cAAc,QAAQ,GAAG,OAAO,KAAK,KAAK,QAAQ,GAAG,OAAO,KAAK,QAGvE,EAAE,OAAO,EAAE;KAED,YAAY,aAAa,oBAAoB;;;;;;;cAQ5C,OAAQ,GAAC,UAAY,MAAC;iBA0HnB,2BACd,aAAa,kBACZ;;;;;;;;;;;;;;;iBAwEa,gBACd,UAAU,eACV,sBACA;iBA0Fc,8BAA8B,SAAS,gBAAa,UAAA,iBAAb,mBAAa,YAAA,iBAAA,mBAAA,gBAAA,iBAAA,mBAAA,aAAA,iBAAA,mBAAA,cAAA,iBAAA,mBAAA,YAAA,iBAAA;;;;;;;;;iBAsCpD,gCACd,UAAU,kBACT;;;;;;;iBAUa,gCACd,UAAU,gBACT;iBAIa,eAAe,SAAS,cAAW,eAAA,iBAAX,mBAAW,iBAAA,iBAAA,mBAAA,qBAAA,iBAAA,mBAAA,kBAAA,iBAAA,mBAAA,mBAAA,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyDnC,uBAAuB,QAAQ;EAC7C,kBAAkB;EAClB,YAAY;EACZ,oBAAoB"}
@@ -124,6 +124,7 @@ function _contentBlockToString(block) {
124
124
  default: return block.type ? `[${block.type}]` : "";
125
125
  }
126
126
  }
127
+ const TOOL_CALL_ID_DISPLAY_LIMIT = 64;
127
128
  /**
128
129
  * This function is used by memory classes to get a string representation
129
130
  * of the chat message history, based on the message content and role.
@@ -136,6 +137,7 @@ function _contentBlockToString(block) {
136
137
  * ```
137
138
  *
138
139
  * This avoids token inflation from metadata when stringifying message objects directly.
140
+ * Tool-call IDs longer than 64 characters are shortened only in the rendered string.
139
141
  */
140
142
  function getBufferString(messages, humanPrefix = "Human", aiPrefix = "AI") {
141
143
  const string_messages = [];
@@ -152,8 +154,13 @@ function getBufferString(messages, humanPrefix = "Human", aiPrefix = "AI") {
152
154
  let message = `${role}: ${nameStr}${readableContent}`;
153
155
  if (m.type === "ai") {
154
156
  const aiMessage = m;
155
- if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) message += JSON.stringify(aiMessage.tool_calls);
156
- else if (aiMessage.additional_kwargs && "function_call" in aiMessage.additional_kwargs) message += JSON.stringify(aiMessage.additional_kwargs.function_call);
157
+ if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
158
+ const toolCalls = aiMessage.tool_calls;
159
+ message += JSON.stringify(toolCalls.some((call) => (call.id?.length ?? 0) > TOOL_CALL_ID_DISPLAY_LIMIT) ? toolCalls.map((call) => call.id && call.id.length > TOOL_CALL_ID_DISPLAY_LIMIT ? {
160
+ ...call,
161
+ id: `${call.id.slice(0, TOOL_CALL_ID_DISPLAY_LIMIT)}...`
162
+ } : call) : toolCalls);
163
+ } else if (aiMessage.additional_kwargs && "function_call" in aiMessage.additional_kwargs) message += JSON.stringify(aiMessage.additional_kwargs.function_call);
157
164
  }
158
165
  string_messages.push(message);
159
166
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../../src/messages/utils.ts"],"sourcesContent":["import { addLangChainErrorFields } from \"../errors/index.js\";\nimport { SerializedConstructor } from \"../load/serializable.js\";\nimport { _isToolCall } from \"../tools/utils.js\";\nimport { parsePartialJson } from \"../utils/json.js\";\nimport { AIMessage, AIMessageChunk, AIMessageChunkFields } from \"./ai.js\";\nimport {\n BaseMessageLike,\n BaseMessage,\n isBaseMessage,\n StoredMessage,\n StoredMessageV1,\n BaseMessageFields,\n _isMessageFieldWithRole,\n} from \"./base.js\";\nimport { ChatMessage, ChatMessageFields, ChatMessageChunk } from \"./chat.js\";\nimport {\n FunctionMessage,\n FunctionMessageChunk,\n FunctionMessageFields,\n} from \"./function.js\";\nimport { HumanMessage, HumanMessageChunk } from \"./human.js\";\nimport { RemoveMessage } from \"./modifier.js\";\nimport { SystemMessage, SystemMessageChunk } from \"./system.js\";\nimport {\n InvalidToolCall,\n ToolCall,\n ToolCallChunk,\n ToolMessage,\n ToolMessageFields,\n} from \"./tool.js\";\n\nexport type $Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;\n\n/**\n * Provider streaming marker for raw (non-JSON) tool input.\n * Not part of the public {@link ToolCallChunk} type; integrations may attach\n * `isCustomTool` at runtime and pass chunks typed as this alias.\n */\nexport type RawInputToolCallChunk = ToolCallChunk & { isCustomTool?: boolean };\n\nfunction chunkUsesRawInputArgs(chunk: ToolCallChunk): boolean {\n return (chunk as RawInputToolCallChunk).isCustomTool === true;\n}\n\n/**\n * Extracts the explicitly declared keys from a type T.\n *\n * @template T - The type to extract keys from\n * @returns A union of keys that are not string, number, or symbol\n */\ntype $KnownKeys<T> = {\n [K in keyof T]: string extends K\n ? never\n : number extends K\n ? never\n : symbol extends K\n ? never\n : K;\n}[keyof T];\n\n/**\n * Detects if T has an index signature.\n *\n * @template T - The type to check for index signatures\n * @returns True if T has an index signature, false otherwise\n */\ntype $HasIndexSignature<T> = string extends keyof T\n ? true\n : number extends keyof T\n ? true\n : symbol extends keyof T\n ? true\n : false;\n\n/**\n * Detects if T has an index signature and no known keys.\n *\n * @template T - The type to check for index signatures and no known keys\n * @returns True if T has an index signature and no known keys, false otherwise\n */\ntype $OnlyIndexSignatures<T> =\n $HasIndexSignature<T> extends true\n ? [$KnownKeys<T>] extends [never]\n ? true\n : false\n : false;\n\n/**\n * Recursively merges two object types T and U, with U taking precedence over T.\n *\n * This utility type performs a deep merge of two object types:\n * - For keys that exist in both T and U:\n * - If both values are objects (Record<string, unknown>), recursively merge them\n * - Otherwise, U's value takes precedence\n * - For keys that exist only in T, use T's value\n * - For keys that exist only in U, use U's value\n *\n * @template T - The first object type to merge\n * @template U - The second object type to merge (takes precedence over T)\n *\n * @example\n * ```ts\n * type ObjectA = {\n * shared: { a: string; b: number };\n * onlyInA: boolean;\n * };\n *\n * type ObjectB = {\n * shared: { b: string; c: Date };\n * onlyInB: symbol;\n * };\n *\n * type Merged = $MergeObjects<ObjectA, ObjectB>;\n * // Result: {\n * // shared: { a: string; b: string; c: Date };\n * // onlyInA: boolean;\n * // onlyInB: symbol;\n * // }\n * ```\n */\nexport type $MergeObjects<T, U> =\n // If U is purely index-signature based, prefer U as a whole\n $OnlyIndexSignatures<U> extends true\n ? U\n : // If T is purely index-signature based, prefer U as a whole (prevents leaking broad index signatures)\n $OnlyIndexSignatures<T> extends true\n ? U\n : {\n [K in keyof T | keyof U]: K extends keyof T\n ? K extends keyof U\n ? T[K] extends Record<string, unknown>\n ? U[K] extends Record<string, unknown>\n ? $MergeObjects<T[K], U[K]>\n : U[K]\n : U[K]\n : T[K]\n : K extends keyof U\n ? U[K]\n : never;\n };\n\n/**\n * Merges two discriminated unions A and B based on a discriminator key (defaults to \"type\").\n * For each possible value of the discriminator across both unions:\n * - If B has a member with that discriminator value, use B's member\n * - Otherwise use A's member with that discriminator value\n * This effectively merges the unions while giving B's members precedence over A's members.\n *\n * @template A - First discriminated union type that extends Record<Key, PropertyKey>\n * @template B - Second discriminated union type that extends Record<Key, PropertyKey>\n * @template Key - The discriminator key property, defaults to \"type\"\n */\nexport type $MergeDiscriminatedUnion<\n A extends Record<Key, PropertyKey>,\n B extends Record<Key, PropertyKey>,\n Key extends PropertyKey = \"type\",\n> = {\n // Create a mapped type over all possible discriminator values from both A and B\n [T in A[Key] | B[Key]]: [Extract<B, Record<Key, T>>] extends [never] // Check if B has a member with this discriminator value\n ? // If B doesn't have this discriminator value, use A's member\n Extract<A, Record<Key, T>>\n : // If B does have this discriminator value, merge A's and B's members (B takes precedence)\n [Extract<A, Record<Key, T>>] extends [never]\n ? Extract<B, Record<Key, T>>\n : $MergeObjects<Extract<A, Record<Key, T>>, Extract<B, Record<Key, T>>>;\n // Index into the mapped type with all possible discriminator values\n // This converts the mapped type back into a union\n}[A[Key] | B[Key]];\n\nexport type Constructor<T> = new (...args: unknown[]) => T;\n\n/**\n * Immediately-invoked function expression.\n *\n * @param fn - The function to execute\n * @returns The result of the function\n */\nexport const iife = <T>(fn: () => T) => fn();\n\nfunction _coerceToolCall(\n toolCall: ToolCall | Record<string, unknown>\n): ToolCall {\n if (_isToolCall(toolCall)) {\n return toolCall;\n } else if (\n typeof toolCall.id === \"string\" &&\n toolCall.type === \"function\" &&\n typeof toolCall.function === \"object\" &&\n toolCall.function !== null &&\n \"arguments\" in toolCall.function &&\n typeof toolCall.function.arguments === \"string\" &&\n \"name\" in toolCall.function &&\n typeof toolCall.function.name === \"string\"\n ) {\n // Handle OpenAI tool call format\n return {\n id: toolCall.id,\n args: JSON.parse(toolCall.function.arguments),\n name: toolCall.function.name,\n type: \"tool_call\",\n };\n } else {\n // TODO: Throw an error?\n return toolCall as unknown as ToolCall;\n }\n}\n\nfunction isSerializedConstructor(x: unknown): x is SerializedConstructor {\n return (\n typeof x === \"object\" &&\n x != null &&\n (x as SerializedConstructor).lc === 1 &&\n Array.isArray((x as SerializedConstructor).id) &&\n (x as SerializedConstructor).kwargs != null &&\n typeof (x as SerializedConstructor).kwargs === \"object\"\n );\n}\n\nfunction _constructMessageFromParams(\n params:\n | (BaseMessageFields & { type: string } & Record<string, unknown>)\n | SerializedConstructor\n) {\n let type: string;\n let rest: BaseMessageFields & Record<string, unknown>;\n // Support serialized messages\n if (isSerializedConstructor(params)) {\n const className = params.id.at(-1);\n if (className === \"HumanMessage\" || className === \"HumanMessageChunk\") {\n type = \"user\";\n } else if (className === \"AIMessage\" || className === \"AIMessageChunk\") {\n type = \"assistant\";\n } else if (\n className === \"SystemMessage\" ||\n className === \"SystemMessageChunk\"\n ) {\n type = \"system\";\n } else if (\n className === \"FunctionMessage\" ||\n className === \"FunctionMessageChunk\"\n ) {\n type = \"function\";\n } else if (\n className === \"ToolMessage\" ||\n className === \"ToolMessageChunk\"\n ) {\n type = \"tool\";\n } else {\n type = \"unknown\";\n }\n rest = params.kwargs as BaseMessageFields;\n } else {\n const { type: extractedType, ...otherParams } = params;\n type = extractedType;\n rest = otherParams;\n }\n if (type === \"human\" || type === \"user\") {\n return new HumanMessage(rest);\n } else if (type === \"ai\" || type === \"assistant\") {\n const { tool_calls: rawToolCalls, ...other } = rest;\n if (!Array.isArray(rawToolCalls)) {\n return new AIMessage(rest);\n }\n const tool_calls = rawToolCalls.map(_coerceToolCall);\n return new AIMessage({ ...other, tool_calls });\n } else if (type === \"system\") {\n return new SystemMessage(rest);\n } else if (type === \"developer\") {\n return new SystemMessage({\n ...rest,\n additional_kwargs: {\n ...rest.additional_kwargs,\n __openai_role__: \"developer\",\n },\n });\n } else if (type === \"tool\" && \"tool_call_id\" in rest) {\n return new ToolMessage({\n ...rest,\n content: rest.content,\n tool_call_id: rest.tool_call_id as string,\n name: rest.name,\n });\n } else if (type === \"remove\" && \"id\" in rest && typeof rest.id === \"string\") {\n return new RemoveMessage({ ...rest, id: rest.id });\n } else {\n const error = addLangChainErrorFields(\n new Error(\n `Unable to coerce message from array: only human, AI, system, developer, or tool message coercion is currently supported.\\n\\nReceived: ${JSON.stringify(\n params,\n null,\n 2\n )}`\n ),\n \"MESSAGE_COERCION_FAILURE\"\n );\n throw error;\n }\n}\n\nexport function coerceMessageLikeToMessage(\n messageLike: BaseMessageLike\n): BaseMessage {\n if (typeof messageLike === \"string\") {\n return new HumanMessage(messageLike);\n } else if (isBaseMessage(messageLike)) {\n return messageLike;\n }\n if (Array.isArray(messageLike)) {\n const [type, content] = messageLike;\n return _constructMessageFromParams({ type, content });\n } else if (_isMessageFieldWithRole(messageLike)) {\n const { role: type, ...rest } = messageLike;\n return _constructMessageFromParams({ ...rest, type });\n } else {\n return _constructMessageFromParams(messageLike);\n }\n}\n\n/**\n * Renders a single content block to a compact string representation.\n * Text blocks are returned as-is; multimodal blocks (image, audio, video, file)\n * become short placeholders like `[image]` so their existence is preserved\n * without inflating token counts with base64 data or metadata.\n */\nfunction _contentBlockToString(\n block: string | { type?: string; [key: string]: unknown }\n): string {\n if (typeof block === \"string\") return block;\n switch (block.type) {\n case \"text\":\n return (block as { text: string }).text ?? \"\";\n case \"text-plain\":\n return (block as { text?: string }).text ?? \"[text-plain file]\";\n case \"image\":\n case \"image_url\":\n return \"[image]\";\n case \"audio\":\n case \"input_audio\":\n return \"[audio]\";\n case \"video\":\n return \"[video]\";\n case \"file\":\n return \"[file]\";\n case \"reasoning\":\n case \"tool_call\":\n case \"tool_call_chunk\":\n case \"invalid_tool_call\":\n case \"server_tool_call\":\n case \"server_tool_call_chunk\":\n case \"server_tool_call_result\":\n case \"non_standard\":\n return \"\";\n default:\n return block.type ? `[${block.type}]` : \"\";\n }\n}\n\n/**\n * This function is used by memory classes to get a string representation\n * of the chat message history, based on the message content and role.\n *\n * Produces compact output like:\n * ```\n * Human: What's the weather?\n * AI: Let me check...[tool_calls]\n * Tool: 72°F and sunny\n * ```\n *\n * This avoids token inflation from metadata when stringifying message objects directly.\n */\nexport function getBufferString(\n messages: BaseMessage[],\n humanPrefix = \"Human\",\n aiPrefix = \"AI\"\n): string {\n const string_messages: string[] = [];\n for (const m of messages) {\n let role: string;\n if (m.type === \"human\") {\n role = humanPrefix;\n } else if (m.type === \"ai\") {\n role = aiPrefix;\n } else if (m.type === \"system\") {\n role = \"System\";\n } else if (m.type === \"tool\") {\n role = \"Tool\";\n } else if (m.type === \"generic\") {\n role = (m as ChatMessage).role;\n } else {\n throw new Error(`Got unsupported message type: ${m.type}`);\n }\n const nameStr = m.name ? `${m.name}, ` : \"\";\n\n // Render content compactly: text as-is, multimodal blocks as placeholders\n const readableContent =\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content.map(_contentBlockToString).filter(Boolean).join(\"\")\n : \"\";\n\n let message = `${role}: ${nameStr}${readableContent}`;\n\n // Include tool calls for AI messages (matching Python's get_buffer_string behavior)\n if (m.type === \"ai\") {\n const aiMessage = m as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n message += JSON.stringify(aiMessage.tool_calls);\n } else if (\n aiMessage.additional_kwargs &&\n \"function_call\" in aiMessage.additional_kwargs\n ) {\n // Legacy behavior assumes only one function call per message\n message += JSON.stringify(aiMessage.additional_kwargs.function_call);\n }\n }\n\n string_messages.push(message);\n }\n return string_messages.join(\"\\n\");\n}\n\n/**\n * Maps messages from an older format (V1) to the current `StoredMessage`\n * format. If the message is already in the `StoredMessage` format, it is\n * returned as is. Otherwise, it transforms the V1 message into a\n * `StoredMessage`. This function is important for maintaining\n * compatibility with older message formats.\n */\nfunction mapV1MessageToStoredMessage(\n message: StoredMessage | StoredMessageV1\n): StoredMessage {\n // TODO: Remove this mapper when we deprecate the old message format.\n if ((message as StoredMessage).data !== undefined) {\n return message as StoredMessage;\n } else {\n const v1Message = message as StoredMessageV1;\n return {\n type: v1Message.type,\n data: {\n content: v1Message.text,\n role: v1Message.role,\n name: undefined,\n tool_call_id: undefined,\n },\n };\n }\n}\n\nexport function mapStoredMessageToChatMessage(message: StoredMessage) {\n const storedMessage = mapV1MessageToStoredMessage(message);\n switch (storedMessage.type) {\n case \"human\":\n return new HumanMessage(storedMessage.data);\n case \"ai\":\n return new AIMessage(storedMessage.data);\n case \"system\":\n return new SystemMessage(storedMessage.data);\n case \"function\":\n if (storedMessage.data.name === undefined) {\n throw new Error(\"Name must be defined for function messages\");\n }\n return new FunctionMessage(storedMessage.data as FunctionMessageFields);\n case \"tool\":\n if (storedMessage.data.tool_call_id === undefined) {\n throw new Error(\"Tool call ID must be defined for tool messages\");\n }\n return new ToolMessage(storedMessage.data as ToolMessageFields);\n case \"generic\": {\n if (storedMessage.data.role === undefined) {\n throw new Error(\"Role must be defined for chat messages\");\n }\n return new ChatMessage(storedMessage.data as ChatMessageFields);\n }\n default:\n throw new Error(`Got unexpected type: ${storedMessage.type}`);\n }\n}\n\n/**\n * Transforms an array of `StoredMessage` instances into an array of\n * `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`\n * function to ensure all messages are in the `StoredMessage` format, then\n * creates new instances of the appropriate `BaseMessage` subclass based\n * on the type of each message. This function is used to prepare stored\n * messages for use in a chat context.\n */\nexport function mapStoredMessagesToChatMessages(\n messages: StoredMessage[]\n): BaseMessage[] {\n return messages.map(mapStoredMessageToChatMessage);\n}\n\n/**\n * Transforms an array of `BaseMessage` instances into an array of\n * `StoredMessage` instances. It does this by calling the `toDict` method\n * on each `BaseMessage`, which returns a `StoredMessage`. This function\n * is used to prepare chat messages for storage.\n */\nexport function mapChatMessagesToStoredMessages(\n messages: BaseMessage[]\n): StoredMessage[] {\n return messages.map((message) => message.toDict());\n}\n\nexport function convertToChunk(message: BaseMessage) {\n const type = message._getType();\n if (type === \"human\") {\n return new HumanMessageChunk({ ...message });\n } else if (type === \"ai\") {\n let aiChunkFields: AIMessageChunkFields = {\n ...message,\n };\n if (\"tool_calls\" in aiChunkFields) {\n aiChunkFields = {\n ...aiChunkFields,\n tool_call_chunks: aiChunkFields.tool_calls?.map((tc) => ({\n ...tc,\n type: \"tool_call_chunk\",\n index: undefined,\n args: JSON.stringify(tc.args),\n })),\n };\n }\n return new AIMessageChunk({ ...aiChunkFields });\n } else if (type === \"system\") {\n return new SystemMessageChunk({ ...message });\n } else if (type === \"function\") {\n return new FunctionMessageChunk({ ...message });\n } else if (ChatMessage.isInstance(message)) {\n return new ChatMessageChunk({ ...message });\n } else {\n throw new Error(\"Unknown message type.\");\n }\n}\n\n/**\n * Collapses an array of tool call chunks into complete tool calls.\n *\n * This function groups tool call chunks by their id and/or index, then attempts to\n * parse and validate the accumulated arguments for each group. Successfully parsed\n * tool calls are returned as valid `ToolCall` objects, while malformed ones are\n * returned as `InvalidToolCall` objects.\n *\n * @param chunks - An array of `ToolCallChunk` objects to collapse\n * @returns An object containing:\n * - `tool_call_chunks`: The original input chunks\n * - `tool_calls`: An array of successfully parsed and validated tool calls\n * - `invalid_tool_calls`: An array of tool calls that failed parsing or validation\n *\n * @remarks\n * Chunks are grouped using the following matching logic:\n * - If a chunk has both an id and index, it matches chunks with the same id and index\n * - If a chunk has only an id, it matches chunks with the same id\n * - If a chunk has only an index, it matches chunks with the same index\n *\n * For each group, the function:\n * 1. Concatenates all `args` strings from the chunks\n * 2. Attempts to parse the concatenated string as JSON\n * 3. Validates that the result is a non-null object with a valid id\n * 4. Creates either a `ToolCall` (if valid) or `InvalidToolCall` (if invalid)\n */\nexport function collapseToolCallChunks(chunks: ToolCallChunk[]): {\n tool_call_chunks: ToolCallChunk[];\n tool_calls: ToolCall[];\n invalid_tool_calls: InvalidToolCall[];\n} {\n const groupedToolCallChunks = chunks.reduce((acc, chunk) => {\n const matchedChunkIndex = acc.findIndex(([match]) => {\n // If chunk has an id and index, match if both are present\n if (\n \"id\" in chunk &&\n chunk.id &&\n \"index\" in chunk &&\n chunk.index !== undefined\n ) {\n return chunk.id === match.id && chunk.index === match.index;\n }\n // If chunk has an id, we match on id\n if (\"id\" in chunk && chunk.id) {\n return chunk.id === match.id;\n }\n // If chunk has an index, we match on index\n if (\"index\" in chunk && chunk.index !== undefined) {\n return chunk.index === match.index;\n }\n return false;\n });\n if (matchedChunkIndex !== -1) {\n acc[matchedChunkIndex].push(chunk);\n } else {\n acc.push([chunk]);\n }\n return acc;\n }, [] as ToolCallChunk[][]);\n\n const toolCalls: ToolCall[] = [];\n const invalidToolCalls: InvalidToolCall[] = [];\n for (const chunks of groupedToolCallChunks) {\n let parsedArgs: Record<string, unknown> | null = null;\n const usesRawInputArgs = chunks.some(chunkUsesRawInputArgs);\n const name = chunks[0]?.name ?? \"\";\n const joinedArgsRaw = chunks.map((c) => c.args || \"\").join(\"\");\n const joinedArgs = usesRawInputArgs ? joinedArgsRaw : joinedArgsRaw.trim();\n const argsStr = joinedArgs.length ? joinedArgs : \"{}\";\n const id = chunks.find((c) => c.id)?.id ?? chunks[0]?.id;\n if (usesRawInputArgs && id) {\n toolCalls.push({\n name,\n args: { input: joinedArgs },\n id,\n type: \"tool_call\",\n });\n continue;\n }\n try {\n parsedArgs = parsePartialJson(argsStr);\n if (\n !id ||\n parsedArgs === null ||\n typeof parsedArgs !== \"object\" ||\n Array.isArray(parsedArgs)\n ) {\n throw new Error(\"Malformed tool call chunk args.\");\n }\n toolCalls.push({\n name,\n args: parsedArgs,\n id,\n type: \"tool_call\",\n });\n } catch {\n invalidToolCalls.push({\n name,\n args: argsStr,\n id,\n error: \"Malformed args.\",\n type: \"invalid_tool_call\",\n });\n }\n }\n return {\n tool_call_chunks: chunks,\n tool_calls: toolCalls,\n invalid_tool_calls: invalidToolCalls,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../src/messages/utils.ts"],"sourcesContent":["import { addLangChainErrorFields } from \"../errors/index.js\";\nimport { SerializedConstructor } from \"../load/serializable.js\";\nimport { _isToolCall } from \"../tools/utils.js\";\nimport { parsePartialJson } from \"../utils/json.js\";\nimport { AIMessage, AIMessageChunk, AIMessageChunkFields } from \"./ai.js\";\nimport {\n BaseMessageLike,\n BaseMessage,\n isBaseMessage,\n StoredMessage,\n StoredMessageV1,\n BaseMessageFields,\n _isMessageFieldWithRole,\n} from \"./base.js\";\nimport { ChatMessage, ChatMessageFields, ChatMessageChunk } from \"./chat.js\";\nimport {\n FunctionMessage,\n FunctionMessageChunk,\n FunctionMessageFields,\n} from \"./function.js\";\nimport { HumanMessage, HumanMessageChunk } from \"./human.js\";\nimport { RemoveMessage } from \"./modifier.js\";\nimport { SystemMessage, SystemMessageChunk } from \"./system.js\";\nimport {\n InvalidToolCall,\n ToolCall,\n ToolCallChunk,\n ToolMessage,\n ToolMessageFields,\n} from \"./tool.js\";\n\nexport type $Expand<T> = T extends infer U ? { [K in keyof U]: U[K] } : never;\n\n/**\n * Provider streaming marker for raw (non-JSON) tool input.\n * Not part of the public {@link ToolCallChunk} type; integrations may attach\n * `isCustomTool` at runtime and pass chunks typed as this alias.\n */\nexport type RawInputToolCallChunk = ToolCallChunk & { isCustomTool?: boolean };\n\nfunction chunkUsesRawInputArgs(chunk: ToolCallChunk): boolean {\n return (chunk as RawInputToolCallChunk).isCustomTool === true;\n}\n\n/**\n * Extracts the explicitly declared keys from a type T.\n *\n * @template T - The type to extract keys from\n * @returns A union of keys that are not string, number, or symbol\n */\ntype $KnownKeys<T> = {\n [K in keyof T]: string extends K\n ? never\n : number extends K\n ? never\n : symbol extends K\n ? never\n : K;\n}[keyof T];\n\n/**\n * Detects if T has an index signature.\n *\n * @template T - The type to check for index signatures\n * @returns True if T has an index signature, false otherwise\n */\ntype $HasIndexSignature<T> = string extends keyof T\n ? true\n : number extends keyof T\n ? true\n : symbol extends keyof T\n ? true\n : false;\n\n/**\n * Detects if T has an index signature and no known keys.\n *\n * @template T - The type to check for index signatures and no known keys\n * @returns True if T has an index signature and no known keys, false otherwise\n */\ntype $OnlyIndexSignatures<T> =\n $HasIndexSignature<T> extends true\n ? [$KnownKeys<T>] extends [never]\n ? true\n : false\n : false;\n\n/**\n * Recursively merges two object types T and U, with U taking precedence over T.\n *\n * This utility type performs a deep merge of two object types:\n * - For keys that exist in both T and U:\n * - If both values are objects (Record<string, unknown>), recursively merge them\n * - Otherwise, U's value takes precedence\n * - For keys that exist only in T, use T's value\n * - For keys that exist only in U, use U's value\n *\n * @template T - The first object type to merge\n * @template U - The second object type to merge (takes precedence over T)\n *\n * @example\n * ```ts\n * type ObjectA = {\n * shared: { a: string; b: number };\n * onlyInA: boolean;\n * };\n *\n * type ObjectB = {\n * shared: { b: string; c: Date };\n * onlyInB: symbol;\n * };\n *\n * type Merged = $MergeObjects<ObjectA, ObjectB>;\n * // Result: {\n * // shared: { a: string; b: string; c: Date };\n * // onlyInA: boolean;\n * // onlyInB: symbol;\n * // }\n * ```\n */\nexport type $MergeObjects<T, U> =\n // If U is purely index-signature based, prefer U as a whole\n $OnlyIndexSignatures<U> extends true\n ? U\n : // If T is purely index-signature based, prefer U as a whole (prevents leaking broad index signatures)\n $OnlyIndexSignatures<T> extends true\n ? U\n : {\n [K in keyof T | keyof U]: K extends keyof T\n ? K extends keyof U\n ? T[K] extends Record<string, unknown>\n ? U[K] extends Record<string, unknown>\n ? $MergeObjects<T[K], U[K]>\n : U[K]\n : U[K]\n : T[K]\n : K extends keyof U\n ? U[K]\n : never;\n };\n\n/**\n * Merges two discriminated unions A and B based on a discriminator key (defaults to \"type\").\n * For each possible value of the discriminator across both unions:\n * - If B has a member with that discriminator value, use B's member\n * - Otherwise use A's member with that discriminator value\n * This effectively merges the unions while giving B's members precedence over A's members.\n *\n * @template A - First discriminated union type that extends Record<Key, PropertyKey>\n * @template B - Second discriminated union type that extends Record<Key, PropertyKey>\n * @template Key - The discriminator key property, defaults to \"type\"\n */\nexport type $MergeDiscriminatedUnion<\n A extends Record<Key, PropertyKey>,\n B extends Record<Key, PropertyKey>,\n Key extends PropertyKey = \"type\",\n> = {\n // Create a mapped type over all possible discriminator values from both A and B\n [T in A[Key] | B[Key]]: [Extract<B, Record<Key, T>>] extends [never] // Check if B has a member with this discriminator value\n ? // If B doesn't have this discriminator value, use A's member\n Extract<A, Record<Key, T>>\n : // If B does have this discriminator value, merge A's and B's members (B takes precedence)\n [Extract<A, Record<Key, T>>] extends [never]\n ? Extract<B, Record<Key, T>>\n : $MergeObjects<Extract<A, Record<Key, T>>, Extract<B, Record<Key, T>>>;\n // Index into the mapped type with all possible discriminator values\n // This converts the mapped type back into a union\n}[A[Key] | B[Key]];\n\nexport type Constructor<T> = new (...args: unknown[]) => T;\n\n/**\n * Immediately-invoked function expression.\n *\n * @param fn - The function to execute\n * @returns The result of the function\n */\nexport const iife = <T>(fn: () => T) => fn();\n\nfunction _coerceToolCall(\n toolCall: ToolCall | Record<string, unknown>\n): ToolCall {\n if (_isToolCall(toolCall)) {\n return toolCall;\n } else if (\n typeof toolCall.id === \"string\" &&\n toolCall.type === \"function\" &&\n typeof toolCall.function === \"object\" &&\n toolCall.function !== null &&\n \"arguments\" in toolCall.function &&\n typeof toolCall.function.arguments === \"string\" &&\n \"name\" in toolCall.function &&\n typeof toolCall.function.name === \"string\"\n ) {\n // Handle OpenAI tool call format\n return {\n id: toolCall.id,\n args: JSON.parse(toolCall.function.arguments),\n name: toolCall.function.name,\n type: \"tool_call\",\n };\n } else {\n // TODO: Throw an error?\n return toolCall as unknown as ToolCall;\n }\n}\n\nfunction isSerializedConstructor(x: unknown): x is SerializedConstructor {\n return (\n typeof x === \"object\" &&\n x != null &&\n (x as SerializedConstructor).lc === 1 &&\n Array.isArray((x as SerializedConstructor).id) &&\n (x as SerializedConstructor).kwargs != null &&\n typeof (x as SerializedConstructor).kwargs === \"object\"\n );\n}\n\nfunction _constructMessageFromParams(\n params:\n | (BaseMessageFields & { type: string } & Record<string, unknown>)\n | SerializedConstructor\n) {\n let type: string;\n let rest: BaseMessageFields & Record<string, unknown>;\n // Support serialized messages\n if (isSerializedConstructor(params)) {\n const className = params.id.at(-1);\n if (className === \"HumanMessage\" || className === \"HumanMessageChunk\") {\n type = \"user\";\n } else if (className === \"AIMessage\" || className === \"AIMessageChunk\") {\n type = \"assistant\";\n } else if (\n className === \"SystemMessage\" ||\n className === \"SystemMessageChunk\"\n ) {\n type = \"system\";\n } else if (\n className === \"FunctionMessage\" ||\n className === \"FunctionMessageChunk\"\n ) {\n type = \"function\";\n } else if (\n className === \"ToolMessage\" ||\n className === \"ToolMessageChunk\"\n ) {\n type = \"tool\";\n } else {\n type = \"unknown\";\n }\n rest = params.kwargs as BaseMessageFields;\n } else {\n const { type: extractedType, ...otherParams } = params;\n type = extractedType;\n rest = otherParams;\n }\n if (type === \"human\" || type === \"user\") {\n return new HumanMessage(rest);\n } else if (type === \"ai\" || type === \"assistant\") {\n const { tool_calls: rawToolCalls, ...other } = rest;\n if (!Array.isArray(rawToolCalls)) {\n return new AIMessage(rest);\n }\n const tool_calls = rawToolCalls.map(_coerceToolCall);\n return new AIMessage({ ...other, tool_calls });\n } else if (type === \"system\") {\n return new SystemMessage(rest);\n } else if (type === \"developer\") {\n return new SystemMessage({\n ...rest,\n additional_kwargs: {\n ...rest.additional_kwargs,\n __openai_role__: \"developer\",\n },\n });\n } else if (type === \"tool\" && \"tool_call_id\" in rest) {\n return new ToolMessage({\n ...rest,\n content: rest.content,\n tool_call_id: rest.tool_call_id as string,\n name: rest.name,\n });\n } else if (type === \"remove\" && \"id\" in rest && typeof rest.id === \"string\") {\n return new RemoveMessage({ ...rest, id: rest.id });\n } else {\n const error = addLangChainErrorFields(\n new Error(\n `Unable to coerce message from array: only human, AI, system, developer, or tool message coercion is currently supported.\\n\\nReceived: ${JSON.stringify(\n params,\n null,\n 2\n )}`\n ),\n \"MESSAGE_COERCION_FAILURE\"\n );\n throw error;\n }\n}\n\nexport function coerceMessageLikeToMessage(\n messageLike: BaseMessageLike\n): BaseMessage {\n if (typeof messageLike === \"string\") {\n return new HumanMessage(messageLike);\n } else if (isBaseMessage(messageLike)) {\n return messageLike;\n }\n if (Array.isArray(messageLike)) {\n const [type, content] = messageLike;\n return _constructMessageFromParams({ type, content });\n } else if (_isMessageFieldWithRole(messageLike)) {\n const { role: type, ...rest } = messageLike;\n return _constructMessageFromParams({ ...rest, type });\n } else {\n return _constructMessageFromParams(messageLike);\n }\n}\n\n/**\n * Renders a single content block to a compact string representation.\n * Text blocks are returned as-is; multimodal blocks (image, audio, video, file)\n * become short placeholders like `[image]` so their existence is preserved\n * without inflating token counts with base64 data or metadata.\n */\nfunction _contentBlockToString(\n block: string | { type?: string; [key: string]: unknown }\n): string {\n if (typeof block === \"string\") return block;\n switch (block.type) {\n case \"text\":\n return (block as { text: string }).text ?? \"\";\n case \"text-plain\":\n return (block as { text?: string }).text ?? \"[text-plain file]\";\n case \"image\":\n case \"image_url\":\n return \"[image]\";\n case \"audio\":\n case \"input_audio\":\n return \"[audio]\";\n case \"video\":\n return \"[video]\";\n case \"file\":\n return \"[file]\";\n case \"reasoning\":\n case \"tool_call\":\n case \"tool_call_chunk\":\n case \"invalid_tool_call\":\n case \"server_tool_call\":\n case \"server_tool_call_chunk\":\n case \"server_tool_call_result\":\n case \"non_standard\":\n return \"\";\n default:\n return block.type ? `[${block.type}]` : \"\";\n }\n}\n\nconst TOOL_CALL_ID_DISPLAY_LIMIT = 64;\n\n/**\n * This function is used by memory classes to get a string representation\n * of the chat message history, based on the message content and role.\n *\n * Produces compact output like:\n * ```\n * Human: What's the weather?\n * AI: Let me check...[tool_calls]\n * Tool: 72°F and sunny\n * ```\n *\n * This avoids token inflation from metadata when stringifying message objects directly.\n * Tool-call IDs longer than 64 characters are shortened only in the rendered string.\n */\nexport function getBufferString(\n messages: BaseMessage[],\n humanPrefix = \"Human\",\n aiPrefix = \"AI\"\n): string {\n const string_messages: string[] = [];\n for (const m of messages) {\n let role: string;\n if (m.type === \"human\") {\n role = humanPrefix;\n } else if (m.type === \"ai\") {\n role = aiPrefix;\n } else if (m.type === \"system\") {\n role = \"System\";\n } else if (m.type === \"tool\") {\n role = \"Tool\";\n } else if (m.type === \"generic\") {\n role = (m as ChatMessage).role;\n } else {\n throw new Error(`Got unsupported message type: ${m.type}`);\n }\n const nameStr = m.name ? `${m.name}, ` : \"\";\n\n // Render content compactly: text as-is, multimodal blocks as placeholders\n const readableContent =\n typeof m.content === \"string\"\n ? m.content\n : Array.isArray(m.content)\n ? m.content.map(_contentBlockToString).filter(Boolean).join(\"\")\n : \"\";\n\n let message = `${role}: ${nameStr}${readableContent}`;\n\n // Include tool calls for AI messages (matching Python's get_buffer_string behavior)\n if (m.type === \"ai\") {\n const aiMessage = m as AIMessage;\n if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {\n const toolCalls = aiMessage.tool_calls;\n message += JSON.stringify(\n toolCalls.some(\n (call) => (call.id?.length ?? 0) > TOOL_CALL_ID_DISPLAY_LIMIT\n )\n ? toolCalls.map((call) =>\n call.id && call.id.length > TOOL_CALL_ID_DISPLAY_LIMIT\n ? {\n ...call,\n id: `${call.id.slice(0, TOOL_CALL_ID_DISPLAY_LIMIT)}...`,\n }\n : call\n )\n : toolCalls\n );\n } else if (\n aiMessage.additional_kwargs &&\n \"function_call\" in aiMessage.additional_kwargs\n ) {\n // Legacy behavior assumes only one function call per message\n message += JSON.stringify(aiMessage.additional_kwargs.function_call);\n }\n }\n\n string_messages.push(message);\n }\n return string_messages.join(\"\\n\");\n}\n\n/**\n * Maps messages from an older format (V1) to the current `StoredMessage`\n * format. If the message is already in the `StoredMessage` format, it is\n * returned as is. Otherwise, it transforms the V1 message into a\n * `StoredMessage`. This function is important for maintaining\n * compatibility with older message formats.\n */\nfunction mapV1MessageToStoredMessage(\n message: StoredMessage | StoredMessageV1\n): StoredMessage {\n // TODO: Remove this mapper when we deprecate the old message format.\n if ((message as StoredMessage).data !== undefined) {\n return message as StoredMessage;\n } else {\n const v1Message = message as StoredMessageV1;\n return {\n type: v1Message.type,\n data: {\n content: v1Message.text,\n role: v1Message.role,\n name: undefined,\n tool_call_id: undefined,\n },\n };\n }\n}\n\nexport function mapStoredMessageToChatMessage(message: StoredMessage) {\n const storedMessage = mapV1MessageToStoredMessage(message);\n switch (storedMessage.type) {\n case \"human\":\n return new HumanMessage(storedMessage.data);\n case \"ai\":\n return new AIMessage(storedMessage.data);\n case \"system\":\n return new SystemMessage(storedMessage.data);\n case \"function\":\n if (storedMessage.data.name === undefined) {\n throw new Error(\"Name must be defined for function messages\");\n }\n return new FunctionMessage(storedMessage.data as FunctionMessageFields);\n case \"tool\":\n if (storedMessage.data.tool_call_id === undefined) {\n throw new Error(\"Tool call ID must be defined for tool messages\");\n }\n return new ToolMessage(storedMessage.data as ToolMessageFields);\n case \"generic\": {\n if (storedMessage.data.role === undefined) {\n throw new Error(\"Role must be defined for chat messages\");\n }\n return new ChatMessage(storedMessage.data as ChatMessageFields);\n }\n default:\n throw new Error(`Got unexpected type: ${storedMessage.type}`);\n }\n}\n\n/**\n * Transforms an array of `StoredMessage` instances into an array of\n * `BaseMessage` instances. It uses the `mapV1MessageToStoredMessage`\n * function to ensure all messages are in the `StoredMessage` format, then\n * creates new instances of the appropriate `BaseMessage` subclass based\n * on the type of each message. This function is used to prepare stored\n * messages for use in a chat context.\n */\nexport function mapStoredMessagesToChatMessages(\n messages: StoredMessage[]\n): BaseMessage[] {\n return messages.map(mapStoredMessageToChatMessage);\n}\n\n/**\n * Transforms an array of `BaseMessage` instances into an array of\n * `StoredMessage` instances. It does this by calling the `toDict` method\n * on each `BaseMessage`, which returns a `StoredMessage`. This function\n * is used to prepare chat messages for storage.\n */\nexport function mapChatMessagesToStoredMessages(\n messages: BaseMessage[]\n): StoredMessage[] {\n return messages.map((message) => message.toDict());\n}\n\nexport function convertToChunk(message: BaseMessage) {\n const type = message._getType();\n if (type === \"human\") {\n return new HumanMessageChunk({ ...message });\n } else if (type === \"ai\") {\n let aiChunkFields: AIMessageChunkFields = {\n ...message,\n };\n if (\"tool_calls\" in aiChunkFields) {\n aiChunkFields = {\n ...aiChunkFields,\n tool_call_chunks: aiChunkFields.tool_calls?.map((tc) => ({\n ...tc,\n type: \"tool_call_chunk\",\n index: undefined,\n args: JSON.stringify(tc.args),\n })),\n };\n }\n return new AIMessageChunk({ ...aiChunkFields });\n } else if (type === \"system\") {\n return new SystemMessageChunk({ ...message });\n } else if (type === \"function\") {\n return new FunctionMessageChunk({ ...message });\n } else if (ChatMessage.isInstance(message)) {\n return new ChatMessageChunk({ ...message });\n } else {\n throw new Error(\"Unknown message type.\");\n }\n}\n\n/**\n * Collapses an array of tool call chunks into complete tool calls.\n *\n * This function groups tool call chunks by their id and/or index, then attempts to\n * parse and validate the accumulated arguments for each group. Successfully parsed\n * tool calls are returned as valid `ToolCall` objects, while malformed ones are\n * returned as `InvalidToolCall` objects.\n *\n * @param chunks - An array of `ToolCallChunk` objects to collapse\n * @returns An object containing:\n * - `tool_call_chunks`: The original input chunks\n * - `tool_calls`: An array of successfully parsed and validated tool calls\n * - `invalid_tool_calls`: An array of tool calls that failed parsing or validation\n *\n * @remarks\n * Chunks are grouped using the following matching logic:\n * - If a chunk has both an id and index, it matches chunks with the same id and index\n * - If a chunk has only an id, it matches chunks with the same id\n * - If a chunk has only an index, it matches chunks with the same index\n *\n * For each group, the function:\n * 1. Concatenates all `args` strings from the chunks\n * 2. Attempts to parse the concatenated string as JSON\n * 3. Validates that the result is a non-null object with a valid id\n * 4. Creates either a `ToolCall` (if valid) or `InvalidToolCall` (if invalid)\n */\nexport function collapseToolCallChunks(chunks: ToolCallChunk[]): {\n tool_call_chunks: ToolCallChunk[];\n tool_calls: ToolCall[];\n invalid_tool_calls: InvalidToolCall[];\n} {\n const groupedToolCallChunks = chunks.reduce((acc, chunk) => {\n const matchedChunkIndex = acc.findIndex(([match]) => {\n // If chunk has an id and index, match if both are present\n if (\n \"id\" in chunk &&\n chunk.id &&\n \"index\" in chunk &&\n chunk.index !== undefined\n ) {\n return chunk.id === match.id && chunk.index === match.index;\n }\n // If chunk has an id, we match on id\n if (\"id\" in chunk && chunk.id) {\n return chunk.id === match.id;\n }\n // If chunk has an index, we match on index\n if (\"index\" in chunk && chunk.index !== undefined) {\n return chunk.index === match.index;\n }\n return false;\n });\n if (matchedChunkIndex !== -1) {\n acc[matchedChunkIndex].push(chunk);\n } else {\n acc.push([chunk]);\n }\n return acc;\n }, [] as ToolCallChunk[][]);\n\n const toolCalls: ToolCall[] = [];\n const invalidToolCalls: InvalidToolCall[] = [];\n for (const chunks of groupedToolCallChunks) {\n let parsedArgs: Record<string, unknown> | null = null;\n const usesRawInputArgs = chunks.some(chunkUsesRawInputArgs);\n const name = chunks[0]?.name ?? \"\";\n const joinedArgsRaw = chunks.map((c) => c.args || \"\").join(\"\");\n const joinedArgs = usesRawInputArgs ? joinedArgsRaw : joinedArgsRaw.trim();\n const argsStr = joinedArgs.length ? joinedArgs : \"{}\";\n const id = chunks.find((c) => c.id)?.id ?? chunks[0]?.id;\n if (usesRawInputArgs && id) {\n toolCalls.push({\n name,\n args: { input: joinedArgs },\n id,\n type: \"tool_call\",\n });\n continue;\n }\n try {\n parsedArgs = parsePartialJson(argsStr);\n if (\n !id ||\n parsedArgs === null ||\n typeof parsedArgs !== \"object\" ||\n Array.isArray(parsedArgs)\n ) {\n throw new Error(\"Malformed tool call chunk args.\");\n }\n toolCalls.push({\n name,\n args: parsedArgs,\n id,\n type: \"tool_call\",\n });\n } catch {\n invalidToolCalls.push({\n name,\n args: argsStr,\n id,\n error: \"Malformed args.\",\n type: \"invalid_tool_call\",\n });\n }\n }\n return {\n tool_call_chunks: chunks,\n tool_calls: toolCalls,\n invalid_tool_calls: invalidToolCalls,\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "1.2.12",
3
+ "version": "1.2.14",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {