@langchain/anthropic 1.3.8 → 1.3.10-dev-1768425582638

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,12 @@
1
1
  # @langchain/anthropic
2
2
 
3
+ ## 1.3.9
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [[`bd1ab45`](https://github.com/langchain-ai/langchainjs/commit/bd1ab45364391f69ce93ecba36a4a15dafca2b76)]:
8
+ - @langchain/core@1.1.14
9
+
3
10
  ## 1.3.8
4
11
 
5
12
  ### Patch Changes
@@ -124,8 +124,12 @@ function* _formatContentBlocks(content) {
124
124
  };
125
125
  else if (toolTypes.find((t) => t === contentPart.type)) {
126
126
  const contentPartCopy = { ...contentPart };
127
+ if (contentPartCopy.type === "tool_use" && typeof contentPartCopy.input === "string") {
128
+ const inputDeltas = content.filter((nestedContentPart) => nestedContentPart.index === contentPartCopy.index && nestedContentPart.type === "input_json_delta" && typeof nestedContentPart.input === "string");
129
+ contentPartCopy.input = inputDeltas.reduce((accumulator, nestedContentPart) => accumulator + nestedContentPart.input, contentPartCopy.input);
130
+ }
131
+ if (contentPartCopy.type === "input_json_delta") continue;
127
132
  if ("index" in contentPartCopy) delete contentPartCopy.index;
128
- if (contentPartCopy.type === "input_json_delta") contentPartCopy.type = "tool_use";
129
133
  if ("input" in contentPartCopy) {
130
134
  if (typeof contentPartCopy.input === "string") try {
131
135
  contentPartCopy.input = JSON.parse(contentPartCopy.input);
@@ -1 +1 @@
1
- {"version":3,"file":"message_inputs.cjs","names":["imageUrl: string","parsedUrl: URL","messages: BaseMessage[]","HumanMessage","toolCall: ToolCall","content: ContentBlock[]","standardContentBlockConverter","_isAnthropicImageBlockParam","_isAnthropicThinkingBlock","block: AnthropicThinkingBlockParam","_isAnthropicRedactedThinkingBlock","block: AnthropicRedactedThinkingBlockParam","_isAnthropicSearchResultBlock","block: AnthropicSearchResultBlockParam","message: BaseMessage","_formatStandardContent","messages: AnthropicMessageCreateParams[\"messages\"]","result: AnthropicMessageCreateParams[\"messages\"]","content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >","msg: (typeof messages)[0]"],"sources":["../../src/utils/message_inputs.ts"],"sourcesContent":["/**\n * This util file contains functions for converting LangChain messages to Anthropic messages.\n */\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n type BaseMessage,\n HumanMessage,\n ToolMessage,\n MessageContentComplex,\n isDataContentBlock,\n convertToProviderContentBlock,\n parseBase64DataUrl,\n ContentBlock,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\nimport {\n AnthropicImageBlockParam,\n AnthropicMessageCreateParams,\n AnthropicTextBlockParam,\n AnthropicToolResultBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicDocumentBlockParam,\n AnthropicThinkingBlockParam,\n AnthropicRedactedThinkingBlockParam,\n AnthropicServerToolUseBlockParam,\n AnthropicWebSearchToolResultBlockParam,\n AnthropicSearchResultBlockParam,\n AnthropicToolResponse,\n AnthropicContainerUploadBlockParam,\n} from \"../types.js\";\nimport {\n _isAnthropicImageBlockParam,\n _isAnthropicRedactedThinkingBlock,\n _isAnthropicSearchResultBlock,\n _isAnthropicThinkingBlock,\n standardContentBlockConverter,\n} from \"./content.js\";\nimport { _formatStandardContent } from \"./standard.js\";\n\nfunction _formatImage(imageUrl: string) {\n const parsed = parseBase64DataUrl({ dataUrl: imageUrl });\n if (parsed) {\n return {\n type: \"base64\",\n media_type: parsed.mime_type,\n data: parsed.data,\n };\n }\n let parsedUrl: URL;\n\n try {\n parsedUrl = new URL(imageUrl);\n } catch {\n throw new Error(\n [\n `Malformed image URL: ${JSON.stringify(\n imageUrl\n )}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n }\n\n if (parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\") {\n return {\n type: \"url\",\n url: imageUrl,\n };\n }\n\n throw new Error(\n [\n `Invalid image URL protocol: ${JSON.stringify(\n parsedUrl.protocol\n )}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n}\n\nfunction _ensureMessageContents(messages: BaseMessage[]): BaseMessage[] {\n // Merge runs of human/tool messages into single human messages with content blocks.\n const updatedMsgs = [];\n for (const message of messages) {\n if (message._getType() === \"tool\") {\n if (typeof message.content === \"string\") {\n const previousMessage = updatedMsgs[updatedMsgs.length - 1];\n if (\n previousMessage?._getType() === \"human\" &&\n Array.isArray(previousMessage.content) &&\n \"type\" in previousMessage.content[0] &&\n previousMessage.content[0].type === \"tool_result\"\n ) {\n // If the previous message was a tool result, we merge this tool message into it.\n (previousMessage.content as MessageContentComplex[]).push({\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n });\n } else {\n // If not, we create a new human message with the tool result.\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n // rare case: message.content could be undefined\n ...(message.content != null\n ? { content: _formatContent(message) }\n : {}),\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(message);\n }\n }\n return updatedMsgs;\n}\n\nexport function _convertLangChainToolCallToAnthropic(\n toolCall: ToolCall\n): AnthropicToolResponse {\n if (toolCall.id === undefined) {\n throw new Error(`Anthropic requires all tool calls to have an \"id\".`);\n }\n return {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args,\n };\n}\n\nfunction* _formatContentBlocks(\n content: ContentBlock[]\n): Generator<Anthropic.Beta.BetaContentBlockParam> {\n const toolTypes = [\n \"bash_code_execution_tool_result\",\n \"input_json_delta\",\n \"server_tool_use\",\n \"text_editor_code_execution_tool_result\",\n \"tool_result\",\n \"tool_use\",\n \"web_search_result\",\n \"web_search_tool_result\",\n ];\n const textTypes = [\"text\", \"text_delta\"];\n for (const contentPart of content) {\n if (isDataContentBlock(contentPart)) {\n yield convertToProviderContentBlock(\n contentPart,\n standardContentBlockConverter\n );\n }\n\n const cacheControl =\n \"cache_control\" in contentPart ? contentPart.cache_control : undefined;\n\n if (contentPart.type === \"image_url\") {\n let source;\n if (typeof contentPart.image_url === \"string\") {\n source = _formatImage(contentPart.image_url);\n } else if (\n typeof contentPart.image_url === \"object\" &&\n contentPart.image_url !== null &&\n \"url\" in contentPart.image_url &&\n typeof contentPart.image_url.url === \"string\"\n ) {\n source = _formatImage(contentPart.image_url.url);\n }\n if (source) {\n yield {\n type: \"image\" as const, // Explicitly setting the type as \"image\"\n source,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.ImageBlockParam;\n }\n } else if (_isAnthropicImageBlockParam(contentPart)) {\n return contentPart;\n } else if (contentPart.type === \"document\") {\n // PDF\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.DocumentBlockParam;\n } else if (_isAnthropicThinkingBlock(contentPart)) {\n const block: AnthropicThinkingBlockParam = {\n type: \"thinking\" as const, // Explicitly setting the type as \"thinking\"\n thinking: contentPart.thinking,\n signature: contentPart.signature,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicRedactedThinkingBlock(contentPart)) {\n const block: AnthropicRedactedThinkingBlockParam = {\n type: \"redacted_thinking\" as const, // Explicitly setting the type as \"redacted_thinking\"\n data: contentPart.data,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicSearchResultBlock(contentPart)) {\n const block: AnthropicSearchResultBlockParam = {\n type: \"search_result\" as const, // Explicitly setting the type as \"search_result\"\n title: contentPart.title,\n source: contentPart.source,\n ...(\"cache_control\" in contentPart && contentPart.cache_control\n ? { cache_control: contentPart.cache_control }\n : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n content: contentPart.content,\n };\n yield block as Anthropic.Beta.BetaSearchResultBlockParam;\n } else if (\n textTypes.find((t) => t === contentPart.type) &&\n \"text\" in contentPart\n ) {\n // Assuming contentPart is of type MessageContentText here\n yield {\n type: \"text\" as const, // Explicitly setting the type as \"text\"\n text: contentPart.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n } as Anthropic.Messages.TextBlockParam;\n } else if (toolTypes.find((t) => t === contentPart.type)) {\n const contentPartCopy = { ...contentPart };\n if (\"index\" in contentPartCopy) {\n // Anthropic does not support passing the index field here, so we remove it.\n delete contentPartCopy.index;\n }\n\n if (contentPartCopy.type === \"input_json_delta\") {\n // `input_json_delta` type only represents yielding partial tool inputs\n // and is not a valid type for Anthropic messages.\n contentPartCopy.type = \"tool_use\";\n }\n\n if (\"input\" in contentPartCopy) {\n // Anthropic tool use inputs should be valid objects, when applicable.\n if (typeof contentPartCopy.input === \"string\") {\n try {\n contentPartCopy.input = JSON.parse(contentPartCopy.input);\n } catch {\n contentPartCopy.input = {};\n }\n }\n }\n // TODO: Fix when SDK types are fixed\n yield {\n ...contentPartCopy,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n } else if (contentPart.type === \"container_upload\") {\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as AnthropicContainerUploadBlockParam;\n }\n\n // Note that we are intentionally dropping any blocks that we don't\n // recognize. This is to allow for cross-compatibility between different\n // providers that may have different block types. Ie if we take a message\n // output from OpenAI and send it to Anthropic, we want to drop any blocks\n // that Anthropic doesn't understand.\n }\n}\n\nfunction _formatContent(message: BaseMessage) {\n const { content } = message;\n\n if (typeof content === \"string\") {\n return content;\n } else {\n return Array.from(_formatContentBlocks(content));\n }\n}\n\n/**\n * Formats messages as a prompt for the model.\n * Used in LangSmith, export is important here.\n * @param messages The base messages to format as a prompt.\n * @returns The formatted prompt.\n */\nexport function _convertMessagesToAnthropicPayload(\n messages: BaseMessage[]\n): AnthropicMessageCreateParams {\n const mergedMessages = _ensureMessageContents(messages);\n let system;\n if (mergedMessages.length > 0 && mergedMessages[0]._getType() === \"system\") {\n system = messages[0].content;\n }\n const conversationMessages =\n system !== undefined ? mergedMessages.slice(1) : mergedMessages;\n const formattedMessages = conversationMessages.map((message) => {\n let role;\n if (message._getType() === \"human\") {\n role = \"user\" as const;\n } else if (message._getType() === \"ai\") {\n role = \"assistant\" as const;\n } else if (message._getType() === \"tool\") {\n role = \"user\" as const;\n } else if (message._getType() === \"system\") {\n throw new Error(\n \"System messages are only permitted as the first passed message.\"\n );\n } else {\n throw new Error(`Message type \"${message.type}\" is not supported.`);\n }\n if (\n isAIMessage(message) &&\n message.response_metadata?.output_version === \"v1\"\n ) {\n return {\n role,\n content: _formatStandardContent(message),\n };\n }\n if (isAIMessage(message) && !!message.tool_calls?.length) {\n if (typeof message.content === \"string\") {\n if (message.content === \"\") {\n return {\n role,\n content: message.tool_calls.map(\n _convertLangChainToolCallToAnthropic\n ),\n };\n } else {\n return {\n role,\n content: [\n { type: \"text\", text: message.content },\n ...message.tool_calls.map(_convertLangChainToolCallToAnthropic),\n ],\n };\n }\n } else {\n const { content } = message;\n const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) =>\n content.find(\n (contentPart) =>\n (contentPart.type === \"tool_use\" ||\n contentPart.type === \"input_json_delta\" ||\n contentPart.type === \"server_tool_use\") &&\n contentPart.id === toolCall.id\n )\n );\n if (hasMismatchedToolCalls) {\n console.warn(\n `The \"tool_calls\" field on a message is only respected if content is a string.`\n );\n }\n return {\n role,\n content: _formatContent(message),\n };\n }\n } else {\n return {\n role,\n content: _formatContent(message),\n };\n }\n });\n return {\n messages: mergeMessages(\n formattedMessages as AnthropicMessageCreateParams[\"messages\"]\n ),\n system,\n } as AnthropicMessageCreateParams;\n}\n\nfunction mergeMessages(messages: AnthropicMessageCreateParams[\"messages\"]) {\n if (!messages || messages.length <= 1) {\n return messages;\n }\n\n const result: AnthropicMessageCreateParams[\"messages\"] = [];\n let currentMessage = messages[0];\n\n const normalizeContent = (\n content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >\n ): Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n > => {\n if (typeof content === \"string\") {\n return [\n {\n type: \"text\",\n text: content,\n },\n ];\n }\n return content;\n };\n\n const isToolResultMessage = (msg: (typeof messages)[0]) => {\n if (msg.role !== \"user\") return false;\n\n if (typeof msg.content === \"string\") {\n return false;\n }\n\n return (\n Array.isArray(msg.content) &&\n msg.content.every((item) => item.type === \"tool_result\")\n );\n };\n\n for (let i = 1; i < messages.length; i += 1) {\n const nextMessage = messages[i];\n\n if (\n isToolResultMessage(currentMessage) &&\n isToolResultMessage(nextMessage)\n ) {\n // Merge the messages by combining their content arrays\n currentMessage = {\n ...currentMessage,\n content: [\n ...normalizeContent(currentMessage.content),\n ...normalizeContent(nextMessage.content),\n ],\n };\n } else {\n result.push(currentMessage);\n currentMessage = nextMessage;\n }\n }\n\n result.push(currentMessage);\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"message_inputs.cjs","names":["imageUrl: string","parsedUrl: URL","messages: BaseMessage[]","HumanMessage","toolCall: ToolCall","content: ContentBlock[]","standardContentBlockConverter","_isAnthropicImageBlockParam","_isAnthropicThinkingBlock","block: AnthropicThinkingBlockParam","_isAnthropicRedactedThinkingBlock","block: AnthropicRedactedThinkingBlockParam","_isAnthropicSearchResultBlock","block: AnthropicSearchResultBlockParam","message: BaseMessage","_formatStandardContent","messages: AnthropicMessageCreateParams[\"messages\"]","result: AnthropicMessageCreateParams[\"messages\"]","content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >","msg: (typeof messages)[0]"],"sources":["../../src/utils/message_inputs.ts"],"sourcesContent":["/**\n * This util file contains functions for converting LangChain messages to Anthropic messages.\n */\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n type BaseMessage,\n HumanMessage,\n ToolMessage,\n MessageContentComplex,\n isDataContentBlock,\n convertToProviderContentBlock,\n parseBase64DataUrl,\n ContentBlock,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\nimport {\n AnthropicImageBlockParam,\n AnthropicMessageCreateParams,\n AnthropicTextBlockParam,\n AnthropicToolResultBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicDocumentBlockParam,\n AnthropicThinkingBlockParam,\n AnthropicRedactedThinkingBlockParam,\n AnthropicServerToolUseBlockParam,\n AnthropicWebSearchToolResultBlockParam,\n AnthropicSearchResultBlockParam,\n AnthropicToolResponse,\n AnthropicContainerUploadBlockParam,\n} from \"../types.js\";\nimport {\n _isAnthropicImageBlockParam,\n _isAnthropicRedactedThinkingBlock,\n _isAnthropicSearchResultBlock,\n _isAnthropicThinkingBlock,\n standardContentBlockConverter,\n} from \"./content.js\";\nimport { _formatStandardContent } from \"./standard.js\";\n\nfunction _formatImage(imageUrl: string) {\n const parsed = parseBase64DataUrl({ dataUrl: imageUrl });\n if (parsed) {\n return {\n type: \"base64\",\n media_type: parsed.mime_type,\n data: parsed.data,\n };\n }\n let parsedUrl: URL;\n\n try {\n parsedUrl = new URL(imageUrl);\n } catch {\n throw new Error(\n [\n `Malformed image URL: ${JSON.stringify(\n imageUrl\n )}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n }\n\n if (parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\") {\n return {\n type: \"url\",\n url: imageUrl,\n };\n }\n\n throw new Error(\n [\n `Invalid image URL protocol: ${JSON.stringify(\n parsedUrl.protocol\n )}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n}\n\nfunction _ensureMessageContents(messages: BaseMessage[]): BaseMessage[] {\n // Merge runs of human/tool messages into single human messages with content blocks.\n const updatedMsgs = [];\n for (const message of messages) {\n if (message._getType() === \"tool\") {\n if (typeof message.content === \"string\") {\n const previousMessage = updatedMsgs[updatedMsgs.length - 1];\n if (\n previousMessage?._getType() === \"human\" &&\n Array.isArray(previousMessage.content) &&\n \"type\" in previousMessage.content[0] &&\n previousMessage.content[0].type === \"tool_result\"\n ) {\n // If the previous message was a tool result, we merge this tool message into it.\n (previousMessage.content as MessageContentComplex[]).push({\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n });\n } else {\n // If not, we create a new human message with the tool result.\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n // rare case: message.content could be undefined\n ...(message.content != null\n ? { content: _formatContent(message) }\n : {}),\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(message);\n }\n }\n return updatedMsgs;\n}\n\nexport function _convertLangChainToolCallToAnthropic(\n toolCall: ToolCall\n): AnthropicToolResponse {\n if (toolCall.id === undefined) {\n throw new Error(`Anthropic requires all tool calls to have an \"id\".`);\n }\n return {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args,\n };\n}\n\nfunction* _formatContentBlocks(\n content: ContentBlock[]\n): Generator<Anthropic.Beta.BetaContentBlockParam> {\n const toolTypes = [\n \"bash_code_execution_tool_result\",\n \"input_json_delta\",\n \"server_tool_use\",\n \"text_editor_code_execution_tool_result\",\n \"tool_result\",\n \"tool_use\",\n \"web_search_result\",\n \"web_search_tool_result\",\n ];\n const textTypes = [\"text\", \"text_delta\"];\n for (const contentPart of content) {\n if (isDataContentBlock(contentPart)) {\n yield convertToProviderContentBlock(\n contentPart,\n standardContentBlockConverter\n );\n }\n\n const cacheControl =\n \"cache_control\" in contentPart ? contentPart.cache_control : undefined;\n\n if (contentPart.type === \"image_url\") {\n let source;\n if (typeof contentPart.image_url === \"string\") {\n source = _formatImage(contentPart.image_url);\n } else if (\n typeof contentPart.image_url === \"object\" &&\n contentPart.image_url !== null &&\n \"url\" in contentPart.image_url &&\n typeof contentPart.image_url.url === \"string\"\n ) {\n source = _formatImage(contentPart.image_url.url);\n }\n if (source) {\n yield {\n type: \"image\" as const, // Explicitly setting the type as \"image\"\n source,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.ImageBlockParam;\n }\n } else if (_isAnthropicImageBlockParam(contentPart)) {\n return contentPart;\n } else if (contentPart.type === \"document\") {\n // PDF\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.DocumentBlockParam;\n } else if (_isAnthropicThinkingBlock(contentPart)) {\n const block: AnthropicThinkingBlockParam = {\n type: \"thinking\" as const, // Explicitly setting the type as \"thinking\"\n thinking: contentPart.thinking,\n signature: contentPart.signature,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicRedactedThinkingBlock(contentPart)) {\n const block: AnthropicRedactedThinkingBlockParam = {\n type: \"redacted_thinking\" as const, // Explicitly setting the type as \"redacted_thinking\"\n data: contentPart.data,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicSearchResultBlock(contentPart)) {\n const block: AnthropicSearchResultBlockParam = {\n type: \"search_result\" as const, // Explicitly setting the type as \"search_result\"\n title: contentPart.title,\n source: contentPart.source,\n ...(\"cache_control\" in contentPart && contentPart.cache_control\n ? { cache_control: contentPart.cache_control }\n : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n content: contentPart.content,\n };\n yield block as Anthropic.Beta.BetaSearchResultBlockParam;\n } else if (\n textTypes.find((t) => t === contentPart.type) &&\n \"text\" in contentPart\n ) {\n // Assuming contentPart is of type MessageContentText here\n yield {\n type: \"text\" as const, // Explicitly setting the type as \"text\"\n text: contentPart.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n } as Anthropic.Messages.TextBlockParam;\n } else if (toolTypes.find((t) => t === contentPart.type)) {\n const contentPartCopy = { ...contentPart };\n\n if (\n contentPartCopy.type === \"tool_use\" &&\n typeof contentPartCopy.input === \"string\"\n ) {\n // `tool_use` content part may be followed by `input_json_delta` content parts\n // which are chunks of a stringified JSON input, so we need to collect them\n // and merge their inputs.\n const inputDeltas = content.filter(\n (nestedContentPart) =>\n nestedContentPart.index === contentPartCopy.index &&\n nestedContentPart.type === \"input_json_delta\" &&\n typeof nestedContentPart.input === \"string\"\n );\n // If no `input_json_delta` parts are found, this line will just\n // return `contentPartCopy.input`, so no additional check is needed\n contentPartCopy.input = inputDeltas.reduce(\n (accumulator, nestedContentPart) =>\n accumulator + nestedContentPart.input,\n contentPartCopy.input\n );\n }\n\n if (contentPartCopy.type === \"input_json_delta\") {\n // `input_json_delta` type only represents yielding partial tool inputs\n // and is not a valid type for Anthropic messages,\n // and since we collect these inputs for a relevant `tool_use`, we can skip it.\n continue;\n }\n\n if (\"index\" in contentPartCopy) {\n // Anthropic does not support passing the index field here, so we remove it.\n delete contentPartCopy.index;\n }\n\n if (\"input\" in contentPartCopy) {\n // Anthropic tool use inputs should be valid objects, when applicable.\n if (typeof contentPartCopy.input === \"string\") {\n try {\n contentPartCopy.input = JSON.parse(contentPartCopy.input);\n } catch {\n contentPartCopy.input = {};\n }\n }\n }\n // TODO: Fix when SDK types are fixed\n yield {\n ...contentPartCopy,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n } else if (contentPart.type === \"container_upload\") {\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as AnthropicContainerUploadBlockParam;\n }\n\n // Note that we are intentionally dropping any blocks that we don't\n // recognize. This is to allow for cross-compatibility between different\n // providers that may have different block types. Ie if we take a message\n // output from OpenAI and send it to Anthropic, we want to drop any blocks\n // that Anthropic doesn't understand.\n }\n}\n\nfunction _formatContent(message: BaseMessage) {\n const { content } = message;\n\n if (typeof content === \"string\") {\n return content;\n } else {\n return Array.from(_formatContentBlocks(content));\n }\n}\n\n/**\n * Formats messages as a prompt for the model.\n * Used in LangSmith, export is important here.\n * @param messages The base messages to format as a prompt.\n * @returns The formatted prompt.\n */\nexport function _convertMessagesToAnthropicPayload(\n messages: BaseMessage[]\n): AnthropicMessageCreateParams {\n const mergedMessages = _ensureMessageContents(messages);\n let system;\n if (mergedMessages.length > 0 && mergedMessages[0]._getType() === \"system\") {\n system = messages[0].content;\n }\n const conversationMessages =\n system !== undefined ? mergedMessages.slice(1) : mergedMessages;\n const formattedMessages = conversationMessages.map((message) => {\n let role;\n if (message._getType() === \"human\") {\n role = \"user\" as const;\n } else if (message._getType() === \"ai\") {\n role = \"assistant\" as const;\n } else if (message._getType() === \"tool\") {\n role = \"user\" as const;\n } else if (message._getType() === \"system\") {\n throw new Error(\n \"System messages are only permitted as the first passed message.\"\n );\n } else {\n throw new Error(`Message type \"${message.type}\" is not supported.`);\n }\n if (\n isAIMessage(message) &&\n message.response_metadata?.output_version === \"v1\"\n ) {\n return {\n role,\n content: _formatStandardContent(message),\n };\n }\n if (isAIMessage(message) && !!message.tool_calls?.length) {\n if (typeof message.content === \"string\") {\n if (message.content === \"\") {\n return {\n role,\n content: message.tool_calls.map(\n _convertLangChainToolCallToAnthropic\n ),\n };\n } else {\n return {\n role,\n content: [\n { type: \"text\", text: message.content },\n ...message.tool_calls.map(_convertLangChainToolCallToAnthropic),\n ],\n };\n }\n } else {\n const { content } = message;\n const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) =>\n content.find(\n (contentPart) =>\n (contentPart.type === \"tool_use\" ||\n contentPart.type === \"input_json_delta\" ||\n contentPart.type === \"server_tool_use\") &&\n contentPart.id === toolCall.id\n )\n );\n if (hasMismatchedToolCalls) {\n console.warn(\n `The \"tool_calls\" field on a message is only respected if content is a string.`\n );\n }\n return {\n role,\n content: _formatContent(message),\n };\n }\n } else {\n return {\n role,\n content: _formatContent(message),\n };\n }\n });\n return {\n messages: mergeMessages(\n formattedMessages as AnthropicMessageCreateParams[\"messages\"]\n ),\n system,\n } as AnthropicMessageCreateParams;\n}\n\nfunction mergeMessages(messages: AnthropicMessageCreateParams[\"messages\"]) {\n if (!messages || messages.length <= 1) {\n return messages;\n }\n\n const result: AnthropicMessageCreateParams[\"messages\"] = [];\n let currentMessage = messages[0];\n\n const normalizeContent = (\n content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >\n ): Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n > => {\n if (typeof content === \"string\") {\n return [\n {\n type: \"text\",\n text: content,\n },\n ];\n }\n return content;\n };\n\n const isToolResultMessage = (msg: (typeof messages)[0]) => {\n if (msg.role !== \"user\") return false;\n\n if (typeof msg.content === \"string\") {\n return false;\n }\n\n return (\n Array.isArray(msg.content) &&\n msg.content.every((item) => item.type === \"tool_result\")\n );\n };\n\n for (let i = 1; i < messages.length; i += 1) {\n const nextMessage = messages[i];\n\n if (\n isToolResultMessage(currentMessage) &&\n isToolResultMessage(nextMessage)\n ) {\n // Merge the messages by combining their content arrays\n currentMessage = {\n ...currentMessage,\n content: [\n ...normalizeContent(currentMessage.content),\n ...normalizeContent(nextMessage.content),\n ],\n };\n } else {\n result.push(currentMessage);\n currentMessage = nextMessage;\n }\n }\n\n result.push(currentMessage);\n return result;\n}\n"],"mappings":"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"}
@@ -123,8 +123,12 @@ function* _formatContentBlocks(content) {
123
123
  };
124
124
  else if (toolTypes.find((t) => t === contentPart.type)) {
125
125
  const contentPartCopy = { ...contentPart };
126
+ if (contentPartCopy.type === "tool_use" && typeof contentPartCopy.input === "string") {
127
+ const inputDeltas = content.filter((nestedContentPart) => nestedContentPart.index === contentPartCopy.index && nestedContentPart.type === "input_json_delta" && typeof nestedContentPart.input === "string");
128
+ contentPartCopy.input = inputDeltas.reduce((accumulator, nestedContentPart) => accumulator + nestedContentPart.input, contentPartCopy.input);
129
+ }
130
+ if (contentPartCopy.type === "input_json_delta") continue;
126
131
  if ("index" in contentPartCopy) delete contentPartCopy.index;
127
- if (contentPartCopy.type === "input_json_delta") contentPartCopy.type = "tool_use";
128
132
  if ("input" in contentPartCopy) {
129
133
  if (typeof contentPartCopy.input === "string") try {
130
134
  contentPartCopy.input = JSON.parse(contentPartCopy.input);
@@ -1 +1 @@
1
- {"version":3,"file":"message_inputs.js","names":["imageUrl: string","parsedUrl: URL","messages: BaseMessage[]","toolCall: ToolCall","content: ContentBlock[]","block: AnthropicThinkingBlockParam","block: AnthropicRedactedThinkingBlockParam","block: AnthropicSearchResultBlockParam","message: BaseMessage","messages: AnthropicMessageCreateParams[\"messages\"]","result: AnthropicMessageCreateParams[\"messages\"]","content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >","msg: (typeof messages)[0]"],"sources":["../../src/utils/message_inputs.ts"],"sourcesContent":["/**\n * This util file contains functions for converting LangChain messages to Anthropic messages.\n */\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n type BaseMessage,\n HumanMessage,\n ToolMessage,\n MessageContentComplex,\n isDataContentBlock,\n convertToProviderContentBlock,\n parseBase64DataUrl,\n ContentBlock,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\nimport {\n AnthropicImageBlockParam,\n AnthropicMessageCreateParams,\n AnthropicTextBlockParam,\n AnthropicToolResultBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicDocumentBlockParam,\n AnthropicThinkingBlockParam,\n AnthropicRedactedThinkingBlockParam,\n AnthropicServerToolUseBlockParam,\n AnthropicWebSearchToolResultBlockParam,\n AnthropicSearchResultBlockParam,\n AnthropicToolResponse,\n AnthropicContainerUploadBlockParam,\n} from \"../types.js\";\nimport {\n _isAnthropicImageBlockParam,\n _isAnthropicRedactedThinkingBlock,\n _isAnthropicSearchResultBlock,\n _isAnthropicThinkingBlock,\n standardContentBlockConverter,\n} from \"./content.js\";\nimport { _formatStandardContent } from \"./standard.js\";\n\nfunction _formatImage(imageUrl: string) {\n const parsed = parseBase64DataUrl({ dataUrl: imageUrl });\n if (parsed) {\n return {\n type: \"base64\",\n media_type: parsed.mime_type,\n data: parsed.data,\n };\n }\n let parsedUrl: URL;\n\n try {\n parsedUrl = new URL(imageUrl);\n } catch {\n throw new Error(\n [\n `Malformed image URL: ${JSON.stringify(\n imageUrl\n )}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n }\n\n if (parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\") {\n return {\n type: \"url\",\n url: imageUrl,\n };\n }\n\n throw new Error(\n [\n `Invalid image URL protocol: ${JSON.stringify(\n parsedUrl.protocol\n )}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n}\n\nfunction _ensureMessageContents(messages: BaseMessage[]): BaseMessage[] {\n // Merge runs of human/tool messages into single human messages with content blocks.\n const updatedMsgs = [];\n for (const message of messages) {\n if (message._getType() === \"tool\") {\n if (typeof message.content === \"string\") {\n const previousMessage = updatedMsgs[updatedMsgs.length - 1];\n if (\n previousMessage?._getType() === \"human\" &&\n Array.isArray(previousMessage.content) &&\n \"type\" in previousMessage.content[0] &&\n previousMessage.content[0].type === \"tool_result\"\n ) {\n // If the previous message was a tool result, we merge this tool message into it.\n (previousMessage.content as MessageContentComplex[]).push({\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n });\n } else {\n // If not, we create a new human message with the tool result.\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n // rare case: message.content could be undefined\n ...(message.content != null\n ? { content: _formatContent(message) }\n : {}),\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(message);\n }\n }\n return updatedMsgs;\n}\n\nexport function _convertLangChainToolCallToAnthropic(\n toolCall: ToolCall\n): AnthropicToolResponse {\n if (toolCall.id === undefined) {\n throw new Error(`Anthropic requires all tool calls to have an \"id\".`);\n }\n return {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args,\n };\n}\n\nfunction* _formatContentBlocks(\n content: ContentBlock[]\n): Generator<Anthropic.Beta.BetaContentBlockParam> {\n const toolTypes = [\n \"bash_code_execution_tool_result\",\n \"input_json_delta\",\n \"server_tool_use\",\n \"text_editor_code_execution_tool_result\",\n \"tool_result\",\n \"tool_use\",\n \"web_search_result\",\n \"web_search_tool_result\",\n ];\n const textTypes = [\"text\", \"text_delta\"];\n for (const contentPart of content) {\n if (isDataContentBlock(contentPart)) {\n yield convertToProviderContentBlock(\n contentPart,\n standardContentBlockConverter\n );\n }\n\n const cacheControl =\n \"cache_control\" in contentPart ? contentPart.cache_control : undefined;\n\n if (contentPart.type === \"image_url\") {\n let source;\n if (typeof contentPart.image_url === \"string\") {\n source = _formatImage(contentPart.image_url);\n } else if (\n typeof contentPart.image_url === \"object\" &&\n contentPart.image_url !== null &&\n \"url\" in contentPart.image_url &&\n typeof contentPart.image_url.url === \"string\"\n ) {\n source = _formatImage(contentPart.image_url.url);\n }\n if (source) {\n yield {\n type: \"image\" as const, // Explicitly setting the type as \"image\"\n source,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.ImageBlockParam;\n }\n } else if (_isAnthropicImageBlockParam(contentPart)) {\n return contentPart;\n } else if (contentPart.type === \"document\") {\n // PDF\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.DocumentBlockParam;\n } else if (_isAnthropicThinkingBlock(contentPart)) {\n const block: AnthropicThinkingBlockParam = {\n type: \"thinking\" as const, // Explicitly setting the type as \"thinking\"\n thinking: contentPart.thinking,\n signature: contentPart.signature,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicRedactedThinkingBlock(contentPart)) {\n const block: AnthropicRedactedThinkingBlockParam = {\n type: \"redacted_thinking\" as const, // Explicitly setting the type as \"redacted_thinking\"\n data: contentPart.data,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicSearchResultBlock(contentPart)) {\n const block: AnthropicSearchResultBlockParam = {\n type: \"search_result\" as const, // Explicitly setting the type as \"search_result\"\n title: contentPart.title,\n source: contentPart.source,\n ...(\"cache_control\" in contentPart && contentPart.cache_control\n ? { cache_control: contentPart.cache_control }\n : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n content: contentPart.content,\n };\n yield block as Anthropic.Beta.BetaSearchResultBlockParam;\n } else if (\n textTypes.find((t) => t === contentPart.type) &&\n \"text\" in contentPart\n ) {\n // Assuming contentPart is of type MessageContentText here\n yield {\n type: \"text\" as const, // Explicitly setting the type as \"text\"\n text: contentPart.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n } as Anthropic.Messages.TextBlockParam;\n } else if (toolTypes.find((t) => t === contentPart.type)) {\n const contentPartCopy = { ...contentPart };\n if (\"index\" in contentPartCopy) {\n // Anthropic does not support passing the index field here, so we remove it.\n delete contentPartCopy.index;\n }\n\n if (contentPartCopy.type === \"input_json_delta\") {\n // `input_json_delta` type only represents yielding partial tool inputs\n // and is not a valid type for Anthropic messages.\n contentPartCopy.type = \"tool_use\";\n }\n\n if (\"input\" in contentPartCopy) {\n // Anthropic tool use inputs should be valid objects, when applicable.\n if (typeof contentPartCopy.input === \"string\") {\n try {\n contentPartCopy.input = JSON.parse(contentPartCopy.input);\n } catch {\n contentPartCopy.input = {};\n }\n }\n }\n // TODO: Fix when SDK types are fixed\n yield {\n ...contentPartCopy,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n } else if (contentPart.type === \"container_upload\") {\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as AnthropicContainerUploadBlockParam;\n }\n\n // Note that we are intentionally dropping any blocks that we don't\n // recognize. This is to allow for cross-compatibility between different\n // providers that may have different block types. Ie if we take a message\n // output from OpenAI and send it to Anthropic, we want to drop any blocks\n // that Anthropic doesn't understand.\n }\n}\n\nfunction _formatContent(message: BaseMessage) {\n const { content } = message;\n\n if (typeof content === \"string\") {\n return content;\n } else {\n return Array.from(_formatContentBlocks(content));\n }\n}\n\n/**\n * Formats messages as a prompt for the model.\n * Used in LangSmith, export is important here.\n * @param messages The base messages to format as a prompt.\n * @returns The formatted prompt.\n */\nexport function _convertMessagesToAnthropicPayload(\n messages: BaseMessage[]\n): AnthropicMessageCreateParams {\n const mergedMessages = _ensureMessageContents(messages);\n let system;\n if (mergedMessages.length > 0 && mergedMessages[0]._getType() === \"system\") {\n system = messages[0].content;\n }\n const conversationMessages =\n system !== undefined ? mergedMessages.slice(1) : mergedMessages;\n const formattedMessages = conversationMessages.map((message) => {\n let role;\n if (message._getType() === \"human\") {\n role = \"user\" as const;\n } else if (message._getType() === \"ai\") {\n role = \"assistant\" as const;\n } else if (message._getType() === \"tool\") {\n role = \"user\" as const;\n } else if (message._getType() === \"system\") {\n throw new Error(\n \"System messages are only permitted as the first passed message.\"\n );\n } else {\n throw new Error(`Message type \"${message.type}\" is not supported.`);\n }\n if (\n isAIMessage(message) &&\n message.response_metadata?.output_version === \"v1\"\n ) {\n return {\n role,\n content: _formatStandardContent(message),\n };\n }\n if (isAIMessage(message) && !!message.tool_calls?.length) {\n if (typeof message.content === \"string\") {\n if (message.content === \"\") {\n return {\n role,\n content: message.tool_calls.map(\n _convertLangChainToolCallToAnthropic\n ),\n };\n } else {\n return {\n role,\n content: [\n { type: \"text\", text: message.content },\n ...message.tool_calls.map(_convertLangChainToolCallToAnthropic),\n ],\n };\n }\n } else {\n const { content } = message;\n const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) =>\n content.find(\n (contentPart) =>\n (contentPart.type === \"tool_use\" ||\n contentPart.type === \"input_json_delta\" ||\n contentPart.type === \"server_tool_use\") &&\n contentPart.id === toolCall.id\n )\n );\n if (hasMismatchedToolCalls) {\n console.warn(\n `The \"tool_calls\" field on a message is only respected if content is a string.`\n );\n }\n return {\n role,\n content: _formatContent(message),\n };\n }\n } else {\n return {\n role,\n content: _formatContent(message),\n };\n }\n });\n return {\n messages: mergeMessages(\n formattedMessages as AnthropicMessageCreateParams[\"messages\"]\n ),\n system,\n } as AnthropicMessageCreateParams;\n}\n\nfunction mergeMessages(messages: AnthropicMessageCreateParams[\"messages\"]) {\n if (!messages || messages.length <= 1) {\n return messages;\n }\n\n const result: AnthropicMessageCreateParams[\"messages\"] = [];\n let currentMessage = messages[0];\n\n const normalizeContent = (\n content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >\n ): Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n > => {\n if (typeof content === \"string\") {\n return [\n {\n type: \"text\",\n text: content,\n },\n ];\n }\n return content;\n };\n\n const isToolResultMessage = (msg: (typeof messages)[0]) => {\n if (msg.role !== \"user\") return false;\n\n if (typeof msg.content === \"string\") {\n return false;\n }\n\n return (\n Array.isArray(msg.content) &&\n msg.content.every((item) => item.type === \"tool_result\")\n );\n };\n\n for (let i = 1; i < messages.length; i += 1) {\n const nextMessage = messages[i];\n\n if (\n isToolResultMessage(currentMessage) &&\n isToolResultMessage(nextMessage)\n ) {\n // Merge the messages by combining their content arrays\n currentMessage = {\n ...currentMessage,\n content: [\n ...normalizeContent(currentMessage.content),\n ...normalizeContent(nextMessage.content),\n ],\n };\n } else {\n result.push(currentMessage);\n currentMessage = nextMessage;\n }\n }\n\n result.push(currentMessage);\n return result;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"message_inputs.js","names":["imageUrl: string","parsedUrl: URL","messages: BaseMessage[]","toolCall: ToolCall","content: ContentBlock[]","block: AnthropicThinkingBlockParam","block: AnthropicRedactedThinkingBlockParam","block: AnthropicSearchResultBlockParam","message: BaseMessage","messages: AnthropicMessageCreateParams[\"messages\"]","result: AnthropicMessageCreateParams[\"messages\"]","content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >","msg: (typeof messages)[0]"],"sources":["../../src/utils/message_inputs.ts"],"sourcesContent":["/**\n * This util file contains functions for converting LangChain messages to Anthropic messages.\n */\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport {\n type BaseMessage,\n HumanMessage,\n ToolMessage,\n MessageContentComplex,\n isDataContentBlock,\n convertToProviderContentBlock,\n parseBase64DataUrl,\n ContentBlock,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\nimport {\n AnthropicImageBlockParam,\n AnthropicMessageCreateParams,\n AnthropicTextBlockParam,\n AnthropicToolResultBlockParam,\n AnthropicToolUseBlockParam,\n AnthropicDocumentBlockParam,\n AnthropicThinkingBlockParam,\n AnthropicRedactedThinkingBlockParam,\n AnthropicServerToolUseBlockParam,\n AnthropicWebSearchToolResultBlockParam,\n AnthropicSearchResultBlockParam,\n AnthropicToolResponse,\n AnthropicContainerUploadBlockParam,\n} from \"../types.js\";\nimport {\n _isAnthropicImageBlockParam,\n _isAnthropicRedactedThinkingBlock,\n _isAnthropicSearchResultBlock,\n _isAnthropicThinkingBlock,\n standardContentBlockConverter,\n} from \"./content.js\";\nimport { _formatStandardContent } from \"./standard.js\";\n\nfunction _formatImage(imageUrl: string) {\n const parsed = parseBase64DataUrl({ dataUrl: imageUrl });\n if (parsed) {\n return {\n type: \"base64\",\n media_type: parsed.mime_type,\n data: parsed.data,\n };\n }\n let parsedUrl: URL;\n\n try {\n parsedUrl = new URL(imageUrl);\n } catch {\n throw new Error(\n [\n `Malformed image URL: ${JSON.stringify(\n imageUrl\n )}. Content blocks of type 'image_url' must be a valid http, https, or base64-encoded data URL.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n }\n\n if (parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\") {\n return {\n type: \"url\",\n url: imageUrl,\n };\n }\n\n throw new Error(\n [\n `Invalid image URL protocol: ${JSON.stringify(\n parsedUrl.protocol\n )}. Anthropic only supports images as http, https, or base64-encoded data URLs on 'image_url' content blocks.`,\n \"Example: data:image/png;base64,/9j/4AAQSk...\",\n \"Example: https://example.com/image.jpg\",\n ].join(\"\\n\\n\")\n );\n}\n\nfunction _ensureMessageContents(messages: BaseMessage[]): BaseMessage[] {\n // Merge runs of human/tool messages into single human messages with content blocks.\n const updatedMsgs = [];\n for (const message of messages) {\n if (message._getType() === \"tool\") {\n if (typeof message.content === \"string\") {\n const previousMessage = updatedMsgs[updatedMsgs.length - 1];\n if (\n previousMessage?._getType() === \"human\" &&\n Array.isArray(previousMessage.content) &&\n \"type\" in previousMessage.content[0] &&\n previousMessage.content[0].type === \"tool_result\"\n ) {\n // If the previous message was a tool result, we merge this tool message into it.\n (previousMessage.content as MessageContentComplex[]).push({\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n });\n } else {\n // If not, we create a new human message with the tool result.\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n content: message.content,\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(\n new HumanMessage({\n content: [\n {\n type: \"tool_result\",\n // rare case: message.content could be undefined\n ...(message.content != null\n ? { content: _formatContent(message) }\n : {}),\n tool_use_id: (message as ToolMessage).tool_call_id,\n },\n ],\n })\n );\n }\n } else {\n updatedMsgs.push(message);\n }\n }\n return updatedMsgs;\n}\n\nexport function _convertLangChainToolCallToAnthropic(\n toolCall: ToolCall\n): AnthropicToolResponse {\n if (toolCall.id === undefined) {\n throw new Error(`Anthropic requires all tool calls to have an \"id\".`);\n }\n return {\n type: \"tool_use\",\n id: toolCall.id,\n name: toolCall.name,\n input: toolCall.args,\n };\n}\n\nfunction* _formatContentBlocks(\n content: ContentBlock[]\n): Generator<Anthropic.Beta.BetaContentBlockParam> {\n const toolTypes = [\n \"bash_code_execution_tool_result\",\n \"input_json_delta\",\n \"server_tool_use\",\n \"text_editor_code_execution_tool_result\",\n \"tool_result\",\n \"tool_use\",\n \"web_search_result\",\n \"web_search_tool_result\",\n ];\n const textTypes = [\"text\", \"text_delta\"];\n for (const contentPart of content) {\n if (isDataContentBlock(contentPart)) {\n yield convertToProviderContentBlock(\n contentPart,\n standardContentBlockConverter\n );\n }\n\n const cacheControl =\n \"cache_control\" in contentPart ? contentPart.cache_control : undefined;\n\n if (contentPart.type === \"image_url\") {\n let source;\n if (typeof contentPart.image_url === \"string\") {\n source = _formatImage(contentPart.image_url);\n } else if (\n typeof contentPart.image_url === \"object\" &&\n contentPart.image_url !== null &&\n \"url\" in contentPart.image_url &&\n typeof contentPart.image_url.url === \"string\"\n ) {\n source = _formatImage(contentPart.image_url.url);\n }\n if (source) {\n yield {\n type: \"image\" as const, // Explicitly setting the type as \"image\"\n source,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.ImageBlockParam;\n }\n } else if (_isAnthropicImageBlockParam(contentPart)) {\n return contentPart;\n } else if (contentPart.type === \"document\") {\n // PDF\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as Anthropic.Messages.DocumentBlockParam;\n } else if (_isAnthropicThinkingBlock(contentPart)) {\n const block: AnthropicThinkingBlockParam = {\n type: \"thinking\" as const, // Explicitly setting the type as \"thinking\"\n thinking: contentPart.thinking,\n signature: contentPart.signature,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicRedactedThinkingBlock(contentPart)) {\n const block: AnthropicRedactedThinkingBlockParam = {\n type: \"redacted_thinking\" as const, // Explicitly setting the type as \"redacted_thinking\"\n data: contentPart.data,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n yield block;\n } else if (_isAnthropicSearchResultBlock(contentPart)) {\n const block: AnthropicSearchResultBlockParam = {\n type: \"search_result\" as const, // Explicitly setting the type as \"search_result\"\n title: contentPart.title,\n source: contentPart.source,\n ...(\"cache_control\" in contentPart && contentPart.cache_control\n ? { cache_control: contentPart.cache_control }\n : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n content: contentPart.content,\n };\n yield block as Anthropic.Beta.BetaSearchResultBlockParam;\n } else if (\n textTypes.find((t) => t === contentPart.type) &&\n \"text\" in contentPart\n ) {\n // Assuming contentPart is of type MessageContentText here\n yield {\n type: \"text\" as const, // Explicitly setting the type as \"text\"\n text: contentPart.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n ...(\"citations\" in contentPart && contentPart.citations\n ? { citations: contentPart.citations }\n : {}),\n } as Anthropic.Messages.TextBlockParam;\n } else if (toolTypes.find((t) => t === contentPart.type)) {\n const contentPartCopy = { ...contentPart };\n\n if (\n contentPartCopy.type === \"tool_use\" &&\n typeof contentPartCopy.input === \"string\"\n ) {\n // `tool_use` content part may be followed by `input_json_delta` content parts\n // which are chunks of a stringified JSON input, so we need to collect them\n // and merge their inputs.\n const inputDeltas = content.filter(\n (nestedContentPart) =>\n nestedContentPart.index === contentPartCopy.index &&\n nestedContentPart.type === \"input_json_delta\" &&\n typeof nestedContentPart.input === \"string\"\n );\n // If no `input_json_delta` parts are found, this line will just\n // return `contentPartCopy.input`, so no additional check is needed\n contentPartCopy.input = inputDeltas.reduce(\n (accumulator, nestedContentPart) =>\n accumulator + nestedContentPart.input,\n contentPartCopy.input\n );\n }\n\n if (contentPartCopy.type === \"input_json_delta\") {\n // `input_json_delta` type only represents yielding partial tool inputs\n // and is not a valid type for Anthropic messages,\n // and since we collect these inputs for a relevant `tool_use`, we can skip it.\n continue;\n }\n\n if (\"index\" in contentPartCopy) {\n // Anthropic does not support passing the index field here, so we remove it.\n delete contentPartCopy.index;\n }\n\n if (\"input\" in contentPartCopy) {\n // Anthropic tool use inputs should be valid objects, when applicable.\n if (typeof contentPartCopy.input === \"string\") {\n try {\n contentPartCopy.input = JSON.parse(contentPartCopy.input);\n } catch {\n contentPartCopy.input = {};\n }\n }\n }\n // TODO: Fix when SDK types are fixed\n yield {\n ...contentPartCopy,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n } else if (contentPart.type === \"container_upload\") {\n yield {\n ...contentPart,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n } as AnthropicContainerUploadBlockParam;\n }\n\n // Note that we are intentionally dropping any blocks that we don't\n // recognize. This is to allow for cross-compatibility between different\n // providers that may have different block types. Ie if we take a message\n // output from OpenAI and send it to Anthropic, we want to drop any blocks\n // that Anthropic doesn't understand.\n }\n}\n\nfunction _formatContent(message: BaseMessage) {\n const { content } = message;\n\n if (typeof content === \"string\") {\n return content;\n } else {\n return Array.from(_formatContentBlocks(content));\n }\n}\n\n/**\n * Formats messages as a prompt for the model.\n * Used in LangSmith, export is important here.\n * @param messages The base messages to format as a prompt.\n * @returns The formatted prompt.\n */\nexport function _convertMessagesToAnthropicPayload(\n messages: BaseMessage[]\n): AnthropicMessageCreateParams {\n const mergedMessages = _ensureMessageContents(messages);\n let system;\n if (mergedMessages.length > 0 && mergedMessages[0]._getType() === \"system\") {\n system = messages[0].content;\n }\n const conversationMessages =\n system !== undefined ? mergedMessages.slice(1) : mergedMessages;\n const formattedMessages = conversationMessages.map((message) => {\n let role;\n if (message._getType() === \"human\") {\n role = \"user\" as const;\n } else if (message._getType() === \"ai\") {\n role = \"assistant\" as const;\n } else if (message._getType() === \"tool\") {\n role = \"user\" as const;\n } else if (message._getType() === \"system\") {\n throw new Error(\n \"System messages are only permitted as the first passed message.\"\n );\n } else {\n throw new Error(`Message type \"${message.type}\" is not supported.`);\n }\n if (\n isAIMessage(message) &&\n message.response_metadata?.output_version === \"v1\"\n ) {\n return {\n role,\n content: _formatStandardContent(message),\n };\n }\n if (isAIMessage(message) && !!message.tool_calls?.length) {\n if (typeof message.content === \"string\") {\n if (message.content === \"\") {\n return {\n role,\n content: message.tool_calls.map(\n _convertLangChainToolCallToAnthropic\n ),\n };\n } else {\n return {\n role,\n content: [\n { type: \"text\", text: message.content },\n ...message.tool_calls.map(_convertLangChainToolCallToAnthropic),\n ],\n };\n }\n } else {\n const { content } = message;\n const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) =>\n content.find(\n (contentPart) =>\n (contentPart.type === \"tool_use\" ||\n contentPart.type === \"input_json_delta\" ||\n contentPart.type === \"server_tool_use\") &&\n contentPart.id === toolCall.id\n )\n );\n if (hasMismatchedToolCalls) {\n console.warn(\n `The \"tool_calls\" field on a message is only respected if content is a string.`\n );\n }\n return {\n role,\n content: _formatContent(message),\n };\n }\n } else {\n return {\n role,\n content: _formatContent(message),\n };\n }\n });\n return {\n messages: mergeMessages(\n formattedMessages as AnthropicMessageCreateParams[\"messages\"]\n ),\n system,\n } as AnthropicMessageCreateParams;\n}\n\nfunction mergeMessages(messages: AnthropicMessageCreateParams[\"messages\"]) {\n if (!messages || messages.length <= 1) {\n return messages;\n }\n\n const result: AnthropicMessageCreateParams[\"messages\"] = [];\n let currentMessage = messages[0];\n\n const normalizeContent = (\n content:\n | string\n | Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n >\n ): Array<\n | AnthropicTextBlockParam\n | AnthropicImageBlockParam\n | AnthropicToolUseBlockParam\n | AnthropicToolResultBlockParam\n | AnthropicDocumentBlockParam\n | AnthropicThinkingBlockParam\n | AnthropicRedactedThinkingBlockParam\n | AnthropicServerToolUseBlockParam\n | AnthropicWebSearchToolResultBlockParam\n | AnthropicSearchResultBlockParam\n > => {\n if (typeof content === \"string\") {\n return [\n {\n type: \"text\",\n text: content,\n },\n ];\n }\n return content;\n };\n\n const isToolResultMessage = (msg: (typeof messages)[0]) => {\n if (msg.role !== \"user\") return false;\n\n if (typeof msg.content === \"string\") {\n return false;\n }\n\n return (\n Array.isArray(msg.content) &&\n msg.content.every((item) => item.type === \"tool_result\")\n );\n };\n\n for (let i = 1; i < messages.length; i += 1) {\n const nextMessage = messages[i];\n\n if (\n isToolResultMessage(currentMessage) &&\n isToolResultMessage(nextMessage)\n ) {\n // Merge the messages by combining their content arrays\n currentMessage = {\n ...currentMessage,\n content: [\n ...normalizeContent(currentMessage.content),\n ...normalizeContent(nextMessage.content),\n ],\n };\n } else {\n result.push(currentMessage);\n currentMessage = nextMessage;\n }\n }\n\n result.push(currentMessage);\n return result;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/anthropic",
3
- "version": "1.3.8",
3
+ "version": "1.3.10-dev-1768425582638",
4
4
  "description": "Anthropic integrations for LangChain.js",
5
5
  "author": "LangChain",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  "zod": "^3.25.76 || ^4"
19
19
  },
20
20
  "peerDependencies": {
21
- "@langchain/core": "1.1.13"
21
+ "@langchain/core": "1.1.14"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@anthropic-ai/vertex-sdk": "^0.11.5",
@@ -33,9 +33,9 @@
33
33
  "typescript": "~5.8.3",
34
34
  "uuid": "^13.0.0",
35
35
  "vitest": "^3.2.4",
36
- "@langchain/core": "1.1.13",
36
+ "@langchain/core": "1.1.14",
37
37
  "@langchain/eslint": "0.1.1",
38
- "@langchain/standard-tests": "0.0.16",
38
+ "@langchain/standard-tests": "0.0.17",
39
39
  "@langchain/tsconfig": "0.0.1"
40
40
  },
41
41
  "publishConfig": {