@langchain/core 1.3.6 → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/errors/index.cjs +56 -0
  3. package/dist/errors/index.cjs.map +1 -1
  4. package/dist/errors/index.d.cts +48 -0
  5. package/dist/errors/index.d.cts.map +1 -1
  6. package/dist/errors/index.d.ts +48 -0
  7. package/dist/errors/index.d.ts.map +1 -1
  8. package/dist/errors/index.js +56 -1
  9. package/dist/errors/index.js.map +1 -1
  10. package/dist/language_models/base.cjs +1 -1
  11. package/dist/language_models/base.js +1 -1
  12. package/dist/messages/block_translators/anthropic.cjs +18 -0
  13. package/dist/messages/block_translators/anthropic.cjs.map +1 -1
  14. package/dist/messages/block_translators/anthropic.js +18 -0
  15. package/dist/messages/block_translators/anthropic.js.map +1 -1
  16. package/dist/messages/block_translators/google.cjs +27 -1
  17. package/dist/messages/block_translators/google.cjs.map +1 -1
  18. package/dist/messages/block_translators/google.js +27 -1
  19. package/dist/messages/block_translators/google.js.map +1 -1
  20. package/dist/messages/block_translators/openai.cjs +25 -0
  21. package/dist/messages/block_translators/openai.cjs.map +1 -1
  22. package/dist/messages/block_translators/openai.js +25 -0
  23. package/dist/messages/block_translators/openai.js.map +1 -1
  24. package/dist/messages/content/index.cjs +1 -0
  25. package/dist/messages/content/index.cjs.map +1 -1
  26. package/dist/messages/content/index.d.cts +23 -1
  27. package/dist/messages/content/index.d.cts.map +1 -1
  28. package/dist/messages/content/index.d.ts +23 -1
  29. package/dist/messages/content/index.d.ts.map +1 -1
  30. package/dist/messages/content/index.js +1 -0
  31. package/dist/messages/content/index.js.map +1 -1
  32. package/dist/output_parsers/json.cjs +8 -0
  33. package/dist/output_parsers/json.cjs.map +1 -1
  34. package/dist/output_parsers/json.d.cts +5 -0
  35. package/dist/output_parsers/json.d.cts.map +1 -1
  36. package/dist/output_parsers/json.d.ts +5 -0
  37. package/dist/output_parsers/json.d.ts.map +1 -1
  38. package/dist/output_parsers/json.js +8 -0
  39. package/dist/output_parsers/json.js.map +1 -1
  40. package/dist/output_parsers/openai_tools/json_output_tools_parsers.cjs +3 -0
  41. package/dist/output_parsers/openai_tools/json_output_tools_parsers.cjs.map +1 -1
  42. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.cts.map +1 -1
  43. package/dist/output_parsers/openai_tools/json_output_tools_parsers.d.ts.map +1 -1
  44. package/dist/output_parsers/openai_tools/json_output_tools_parsers.js +3 -0
  45. package/dist/output_parsers/openai_tools/json_output_tools_parsers.js.map +1 -1
  46. package/dist/output_parsers/refusal.cjs +23 -0
  47. package/dist/output_parsers/refusal.cjs.map +1 -0
  48. package/dist/output_parsers/refusal.js +23 -0
  49. package/dist/output_parsers/refusal.js.map +1 -0
  50. package/dist/output_parsers/standard_schema.cjs +8 -0
  51. package/dist/output_parsers/standard_schema.cjs.map +1 -1
  52. package/dist/output_parsers/standard_schema.d.cts +6 -0
  53. package/dist/output_parsers/standard_schema.d.cts.map +1 -1
  54. package/dist/output_parsers/standard_schema.d.ts +6 -0
  55. package/dist/output_parsers/standard_schema.d.ts.map +1 -1
  56. package/dist/output_parsers/standard_schema.js +8 -0
  57. package/dist/output_parsers/standard_schema.js.map +1 -1
  58. package/dist/output_parsers/structured.cjs +8 -0
  59. package/dist/output_parsers/structured.cjs.map +1 -1
  60. package/dist/output_parsers/structured.d.cts +6 -0
  61. package/dist/output_parsers/structured.d.cts.map +1 -1
  62. package/dist/output_parsers/structured.d.ts +6 -0
  63. package/dist/output_parsers/structured.d.ts.map +1 -1
  64. package/dist/output_parsers/structured.js +8 -0
  65. package/dist/output_parsers/structured.js.map +1 -1
  66. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","names":[],"sources":["../../../src/messages/block_translators/anthropic.ts"],"sourcesContent":["import type { StandardContentBlockTranslator } from \"./index.js\";\nimport type { ContentBlock } from \"../content/index.js\";\nimport type { AIMessageChunk, AIMessage } from \"../ai.js\";\nimport type { BaseMessage, BaseMessageChunk } from \"../base.js\";\nimport {\n _isArray,\n _isContentBlock,\n _isNumber,\n _isObject,\n _isString,\n safeParseJson,\n iife,\n} from \"./utils.js\";\n\nfunction convertAnthropicAnnotation(\n citation: ContentBlock\n): ContentBlock.Citation | undefined {\n if (\n citation.type === \"char_location\" &&\n _isString(citation.document_title) &&\n _isNumber(citation.start_char_index) &&\n _isNumber(citation.end_char_index) &&\n _isString(citation.cited_text)\n ) {\n const {\n document_title,\n start_char_index,\n end_char_index,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"char\",\n title: document_title ?? undefined,\n startIndex: start_char_index,\n endIndex: end_char_index,\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"page_location\" &&\n _isString(citation.document_title) &&\n _isNumber(citation.start_page_number) &&\n _isNumber(citation.end_page_number) &&\n _isString(citation.cited_text)\n ) {\n const {\n document_title,\n start_page_number,\n end_page_number,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"page\",\n title: document_title ?? undefined,\n startIndex: start_page_number,\n endIndex: end_page_number,\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"content_block_location\" &&\n _isString(citation.document_title) &&\n _isNumber(citation.start_block_index) &&\n _isNumber(citation.end_block_index) &&\n _isString(citation.cited_text)\n ) {\n const {\n document_title,\n start_block_index,\n end_block_index,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"block\",\n title: document_title ?? undefined,\n startIndex: start_block_index,\n endIndex: end_block_index,\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"web_search_result_location\" &&\n _isString(citation.url) &&\n _isString(citation.title) &&\n _isString(citation.encrypted_index) &&\n _isString(citation.cited_text)\n ) {\n const { url, title, encrypted_index, cited_text, ...rest } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"url\",\n url,\n title,\n startIndex: Number(encrypted_index),\n endIndex: Number(encrypted_index),\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"search_result_location\" &&\n _isString(citation.source) &&\n _isString(citation.title) &&\n _isNumber(citation.start_block_index) &&\n _isNumber(citation.end_block_index) &&\n _isString(citation.cited_text)\n ) {\n const {\n source,\n title,\n start_block_index,\n end_block_index,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"search\",\n url: source,\n title: title ?? undefined,\n startIndex: start_block_index,\n endIndex: end_block_index,\n citedText: cited_text,\n };\n }\n return undefined;\n}\n\n/**\n * Converts an Anthropic content block to a standard V1 content block.\n *\n * This function handles the conversion of Anthropic-specific content blocks\n * (document and image blocks) to the standardized V1 format. It supports\n * various source types including base64 data, URLs, file IDs, and text data.\n *\n * @param block - The Anthropic content block to convert\n * @returns A standard V1 content block if conversion is successful, undefined otherwise\n *\n * @example\n * ```typescript\n * const anthropicBlock = {\n * type: \"image\",\n * source: {\n * type: \"base64\",\n * media_type: \"image/png\",\n * data: \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==\"\n * }\n * };\n *\n * const standardBlock = convertToV1FromAnthropicContentBlock(anthropicBlock);\n * // Returns: { type: \"image\", mimeType: \"image/png\", data: \"...\" }\n * ```\n */\nexport function convertToV1FromAnthropicContentBlock(\n block: ContentBlock\n): ContentBlock.Standard | undefined {\n if (\n _isContentBlock(block, \"document\") &&\n _isObject(block.source) &&\n \"type\" in block.source\n ) {\n if (\n block.source.type === \"base64\" &&\n _isString(block.source.media_type) &&\n _isString(block.source.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.source.media_type,\n data: block.source.data,\n };\n } else if (block.source.type === \"url\" && _isString(block.source.url)) {\n return {\n type: \"file\",\n url: block.source.url,\n };\n } else if (\n block.source.type === \"file\" &&\n _isString(block.source.file_id)\n ) {\n return {\n type: \"file\",\n fileId: block.source.file_id,\n };\n } else if (block.source.type === \"text\" && _isString(block.source.data)) {\n return {\n type: \"file\",\n mimeType: String(block.source.media_type ?? \"text/plain\"),\n data: block.source.data,\n };\n }\n } else if (\n _isContentBlock(block, \"image\") &&\n _isObject(block.source) &&\n \"type\" in block.source\n ) {\n if (\n block.source.type === \"base64\" &&\n _isString(block.source.media_type) &&\n _isString(block.source.data)\n ) {\n return {\n type: \"image\",\n mimeType: block.source.media_type,\n data: block.source.data,\n };\n } else if (block.source.type === \"url\" && _isString(block.source.url)) {\n return {\n type: \"image\",\n url: block.source.url,\n };\n } else if (\n block.source.type === \"file\" &&\n _isString(block.source.file_id)\n ) {\n return {\n type: \"image\",\n fileId: block.source.file_id,\n };\n }\n }\n return undefined;\n}\n\n/**\n * Converts an array of content blocks from Anthropic format to v1 standard format.\n *\n * This function processes each content block in the input array, attempting to convert\n * Anthropic-specific block formats (like image blocks with source objects, document blocks, etc.)\n * to the standardized v1 content block format. If a block cannot be converted, it is\n * passed through as-is with a type assertion to ContentBlock.Standard.\n *\n * @param content - Array of content blocks in Anthropic format to be converted\n * @returns Array of content blocks in v1 standard format\n */\nexport function convertToV1FromAnthropicInput(\n content: Array<ContentBlock>\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n for (const block of content) {\n const stdBlock = convertToV1FromAnthropicContentBlock(block);\n if (stdBlock) {\n yield stdBlock;\n } else {\n yield block as ContentBlock.Standard;\n }\n }\n }\n return Array.from(iterateContent());\n}\n\n/**\n * Converts an Anthropic AI message to an array of v1 standard content blocks.\n *\n * This function processes an AI message containing Anthropic-specific content blocks\n * and converts them to the standardized v1 content block format.\n *\n * @param message - The AI message containing Anthropic-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage([\n * { type: \"text\", text: \"Hello world\" },\n * { type: \"thinking\", text: \"Let me think about this...\" },\n * { type: \"tool_use\", id: \"123\", name: \"calculator\", input: { a: 1, b: 2 } }\n * ]);\n *\n * const standardBlocks = convertToV1FromAnthropicMessage(message);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello world\" },\n * // { type: \"reasoning\", reasoning: \"Let me think about this...\" },\n * // { type: \"tool_call\", id: \"123\", name: \"calculator\", args: { a: 1, b: 2 } }\n * // ]\n * ```\n */\nexport function convertToV1FromAnthropicMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content =\n typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n for (const block of content) {\n // TextBlock\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n const { text, citations, ...rest } = block;\n if (_isArray(citations) && citations.length) {\n const _citations = citations.reduce<ContentBlock.Citation[]>(\n (acc, item) => {\n const citation = convertAnthropicAnnotation(item as ContentBlock);\n if (citation) {\n return [...acc, citation];\n }\n return acc;\n },\n []\n );\n yield {\n ...rest,\n type: \"text\",\n text,\n annotations: _citations,\n };\n continue;\n } else {\n yield {\n ...rest,\n type: \"text\",\n text,\n };\n continue;\n }\n }\n // ThinkingBlock\n else if (\n _isContentBlock(block, \"thinking\") &&\n _isString(block.thinking)\n ) {\n const { thinking, signature, ...rest } = block;\n yield {\n ...rest,\n type: \"reasoning\",\n reasoning: thinking,\n signature,\n };\n continue;\n }\n // RedactedThinkingBlock\n else if (_isContentBlock(block, \"redacted_thinking\")) {\n yield { type: \"non_standard\", value: block };\n continue;\n }\n // ToolUseBlock\n else if (\n _isContentBlock(block, \"tool_use\") &&\n _isString(block.name) &&\n _isString(block.id)\n ) {\n yield {\n type: \"tool_call\",\n id: block.id,\n name: block.name,\n args: block.input,\n };\n continue;\n }\n // message chunks can have input_json_delta contents\n else if (_isContentBlock(block, \"input_json_delta\")) {\n if (_isAIMessageChunk(message) && message.tool_call_chunks?.length) {\n const tool_call_chunk = message.tool_call_chunks[0];\n yield {\n type: \"tool_call_chunk\",\n id: tool_call_chunk.id,\n name: tool_call_chunk.name,\n args: tool_call_chunk.args,\n index: tool_call_chunk.index,\n };\n continue;\n }\n }\n // ServerToolUseBlock\n else if (\n _isContentBlock(block, \"server_tool_use\") &&\n _isString(block.name) &&\n _isString(block.id)\n ) {\n const { name, id } = block;\n if (name === \"web_search\") {\n const query = iife(() => {\n if (typeof block.input === \"string\") {\n return block.input;\n } else if (_isObject(block.input) && _isString(block.input.query)) {\n return block.input.query;\n } else if (_isString(block.partial_json)) {\n const json = safeParseJson<{ query?: string }>(\n block.partial_json\n );\n if (json?.query) {\n return json.query;\n }\n }\n return \"\";\n });\n yield {\n id,\n type: \"server_tool_call\",\n name: \"web_search\",\n args: { query },\n };\n continue;\n } else if (block.name === \"code_execution\") {\n const code = iife(() => {\n if (typeof block.input === \"string\") {\n return block.input;\n } else if (_isObject(block.input) && _isString(block.input.code)) {\n return block.input.code;\n } else if (_isString(block.partial_json)) {\n const json = safeParseJson<{ code?: string }>(block.partial_json);\n if (json?.code) {\n return json.code;\n }\n }\n return \"\";\n });\n yield {\n id,\n type: \"server_tool_call\",\n name: \"code_execution\",\n args: { code },\n };\n continue;\n }\n }\n // WebSearchToolResultBlock\n else if (\n _isContentBlock(block, \"web_search_tool_result\") &&\n _isString(block.tool_use_id) &&\n _isArray(block.content)\n ) {\n const { content, tool_use_id } = block;\n const urls = content.reduce<string[]>((acc, content) => {\n if (_isContentBlock(content, \"web_search_result\")) {\n return [...acc, content.url as string];\n }\n return acc;\n }, []);\n yield {\n type: \"server_tool_call_result\",\n name: \"web_search\",\n toolCallId: tool_use_id,\n status: \"success\",\n output: {\n urls,\n },\n };\n continue;\n }\n // CodeExecutionToolResultBlock\n else if (\n _isContentBlock(block, \"code_execution_tool_result\") &&\n _isString(block.tool_use_id) &&\n _isObject(block.content)\n ) {\n yield {\n type: \"server_tool_call_result\",\n name: \"code_execution\",\n toolCallId: block.tool_use_id,\n status: \"success\",\n output: block.content,\n };\n continue;\n }\n // MCPToolUseBlock\n else if (_isContentBlock(block, \"mcp_tool_use\")) {\n yield {\n id: block.id,\n type: \"server_tool_call\",\n name: \"mcp_tool_use\",\n args: block.input,\n };\n continue;\n }\n // MCPToolResultBlock\n else if (\n _isContentBlock(block, \"mcp_tool_result\") &&\n _isString(block.tool_use_id) &&\n _isObject(block.content)\n ) {\n yield {\n type: \"server_tool_call_result\",\n name: \"mcp_tool_use\",\n toolCallId: block.tool_use_id,\n status: \"success\",\n output: block.content,\n };\n continue;\n }\n // ContainerUploadBlock\n else if (_isContentBlock(block, \"container_upload\")) {\n yield {\n type: \"server_tool_call\",\n name: \"container_upload\",\n args: block.input,\n };\n continue;\n }\n // SearchResultBlockParam\n else if (_isContentBlock(block, \"search_result\")) {\n yield { id: block.id, type: \"non_standard\", value: block };\n continue;\n }\n // ToolResultBlockParam\n else if (_isContentBlock(block, \"tool_result\")) {\n yield { id: block.id, type: \"non_standard\", value: block };\n continue;\n } else {\n // For all other blocks, we try to convert them to a standard block\n const stdBlock = convertToV1FromAnthropicContentBlock(block);\n if (stdBlock) {\n yield stdBlock;\n continue;\n }\n }\n yield { type: \"non_standard\", value: block };\n }\n }\n return Array.from(iterateContent());\n}\n\nexport const ChatAnthropicTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromAnthropicMessage,\n translateContentChunk: convertToV1FromAnthropicMessage,\n};\n\nfunction _isAIMessageChunk(message: unknown): message is AIMessageChunk {\n return (\n typeof (message as BaseMessage)?._getType === \"function\" &&\n typeof (message as BaseMessageChunk).concat === \"function\" &&\n (message as BaseMessageChunk)._getType() === \"ai\"\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"anthropic.js","names":[],"sources":["../../../src/messages/block_translators/anthropic.ts"],"sourcesContent":["import type { StandardContentBlockTranslator } from \"./index.js\";\nimport type { ContentBlock } from \"../content/index.js\";\nimport type { AIMessageChunk, AIMessage } from \"../ai.js\";\nimport type { BaseMessage, BaseMessageChunk } from \"../base.js\";\nimport {\n _isArray,\n _isContentBlock,\n _isNumber,\n _isObject,\n _isString,\n safeParseJson,\n iife,\n} from \"./utils.js\";\n\nfunction convertAnthropicAnnotation(\n citation: ContentBlock\n): ContentBlock.Citation | undefined {\n if (\n citation.type === \"char_location\" &&\n _isString(citation.document_title) &&\n _isNumber(citation.start_char_index) &&\n _isNumber(citation.end_char_index) &&\n _isString(citation.cited_text)\n ) {\n const {\n document_title,\n start_char_index,\n end_char_index,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"char\",\n title: document_title ?? undefined,\n startIndex: start_char_index,\n endIndex: end_char_index,\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"page_location\" &&\n _isString(citation.document_title) &&\n _isNumber(citation.start_page_number) &&\n _isNumber(citation.end_page_number) &&\n _isString(citation.cited_text)\n ) {\n const {\n document_title,\n start_page_number,\n end_page_number,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"page\",\n title: document_title ?? undefined,\n startIndex: start_page_number,\n endIndex: end_page_number,\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"content_block_location\" &&\n _isString(citation.document_title) &&\n _isNumber(citation.start_block_index) &&\n _isNumber(citation.end_block_index) &&\n _isString(citation.cited_text)\n ) {\n const {\n document_title,\n start_block_index,\n end_block_index,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"block\",\n title: document_title ?? undefined,\n startIndex: start_block_index,\n endIndex: end_block_index,\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"web_search_result_location\" &&\n _isString(citation.url) &&\n _isString(citation.title) &&\n _isString(citation.encrypted_index) &&\n _isString(citation.cited_text)\n ) {\n const { url, title, encrypted_index, cited_text, ...rest } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"url\",\n url,\n title,\n startIndex: Number(encrypted_index),\n endIndex: Number(encrypted_index),\n citedText: cited_text,\n };\n }\n if (\n citation.type === \"search_result_location\" &&\n _isString(citation.source) &&\n _isString(citation.title) &&\n _isNumber(citation.start_block_index) &&\n _isNumber(citation.end_block_index) &&\n _isString(citation.cited_text)\n ) {\n const {\n source,\n title,\n start_block_index,\n end_block_index,\n cited_text,\n ...rest\n } = citation;\n return {\n ...rest,\n type: \"citation\",\n source: \"search\",\n url: source,\n title: title ?? undefined,\n startIndex: start_block_index,\n endIndex: end_block_index,\n citedText: cited_text,\n };\n }\n return undefined;\n}\n\n/**\n * Converts an Anthropic content block to a standard V1 content block.\n *\n * This function handles the conversion of Anthropic-specific content blocks\n * (document and image blocks) to the standardized V1 format. It supports\n * various source types including base64 data, URLs, file IDs, and text data.\n *\n * @param block - The Anthropic content block to convert\n * @returns A standard V1 content block if conversion is successful, undefined otherwise\n *\n * @example\n * ```typescript\n * const anthropicBlock = {\n * type: \"image\",\n * source: {\n * type: \"base64\",\n * media_type: \"image/png\",\n * data: \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==\"\n * }\n * };\n *\n * const standardBlock = convertToV1FromAnthropicContentBlock(anthropicBlock);\n * // Returns: { type: \"image\", mimeType: \"image/png\", data: \"...\" }\n * ```\n */\nexport function convertToV1FromAnthropicContentBlock(\n block: ContentBlock\n): ContentBlock.Standard | undefined {\n if (\n _isContentBlock(block, \"document\") &&\n _isObject(block.source) &&\n \"type\" in block.source\n ) {\n if (\n block.source.type === \"base64\" &&\n _isString(block.source.media_type) &&\n _isString(block.source.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.source.media_type,\n data: block.source.data,\n };\n } else if (block.source.type === \"url\" && _isString(block.source.url)) {\n return {\n type: \"file\",\n url: block.source.url,\n };\n } else if (\n block.source.type === \"file\" &&\n _isString(block.source.file_id)\n ) {\n return {\n type: \"file\",\n fileId: block.source.file_id,\n };\n } else if (block.source.type === \"text\" && _isString(block.source.data)) {\n return {\n type: \"file\",\n mimeType: String(block.source.media_type ?? \"text/plain\"),\n data: block.source.data,\n };\n }\n } else if (\n _isContentBlock(block, \"image\") &&\n _isObject(block.source) &&\n \"type\" in block.source\n ) {\n if (\n block.source.type === \"base64\" &&\n _isString(block.source.media_type) &&\n _isString(block.source.data)\n ) {\n return {\n type: \"image\",\n mimeType: block.source.media_type,\n data: block.source.data,\n };\n } else if (block.source.type === \"url\" && _isString(block.source.url)) {\n return {\n type: \"image\",\n url: block.source.url,\n };\n } else if (\n block.source.type === \"file\" &&\n _isString(block.source.file_id)\n ) {\n return {\n type: \"image\",\n fileId: block.source.file_id,\n };\n }\n }\n return undefined;\n}\n\n/**\n * Converts an array of content blocks from Anthropic format to v1 standard format.\n *\n * This function processes each content block in the input array, attempting to convert\n * Anthropic-specific block formats (like image blocks with source objects, document blocks, etc.)\n * to the standardized v1 content block format. If a block cannot be converted, it is\n * passed through as-is with a type assertion to ContentBlock.Standard.\n *\n * @param content - Array of content blocks in Anthropic format to be converted\n * @returns Array of content blocks in v1 standard format\n */\nexport function convertToV1FromAnthropicInput(\n content: Array<ContentBlock>\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n for (const block of content) {\n const stdBlock = convertToV1FromAnthropicContentBlock(block);\n if (stdBlock) {\n yield stdBlock;\n } else {\n yield block as ContentBlock.Standard;\n }\n }\n }\n return Array.from(iterateContent());\n}\n\n/**\n * Converts an Anthropic AI message to an array of v1 standard content blocks.\n *\n * This function processes an AI message containing Anthropic-specific content blocks\n * and converts them to the standardized v1 content block format.\n *\n * @param message - The AI message containing Anthropic-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage([\n * { type: \"text\", text: \"Hello world\" },\n * { type: \"thinking\", text: \"Let me think about this...\" },\n * { type: \"tool_use\", id: \"123\", name: \"calculator\", input: { a: 1, b: 2 } }\n * ]);\n *\n * const standardBlocks = convertToV1FromAnthropicMessage(message);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello world\" },\n * // { type: \"reasoning\", reasoning: \"Let me think about this...\" },\n * // { type: \"tool_call\", id: \"123\", name: \"calculator\", args: { a: 1, b: 2 } }\n * // ]\n * ```\n */\nexport function convertToV1FromAnthropicMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n let hasRefusal = false;\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content =\n typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n for (const block of content) {\n // TextBlock\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n const { text, citations, ...rest } = block;\n if (_isArray(citations) && citations.length) {\n const _citations = citations.reduce<ContentBlock.Citation[]>(\n (acc, item) => {\n const citation = convertAnthropicAnnotation(item as ContentBlock);\n if (citation) {\n return [...acc, citation];\n }\n return acc;\n },\n []\n );\n yield {\n ...rest,\n type: \"text\",\n text,\n annotations: _citations,\n };\n continue;\n } else {\n yield {\n ...rest,\n type: \"text\",\n text,\n };\n continue;\n }\n }\n // ThinkingBlock\n else if (\n _isContentBlock(block, \"thinking\") &&\n _isString(block.thinking)\n ) {\n const { thinking, signature, ...rest } = block;\n yield {\n ...rest,\n type: \"reasoning\",\n reasoning: thinking,\n signature,\n };\n continue;\n }\n // RedactedThinkingBlock\n else if (_isContentBlock(block, \"redacted_thinking\")) {\n yield { type: \"non_standard\", value: block };\n continue;\n }\n // ToolUseBlock\n else if (\n _isContentBlock(block, \"tool_use\") &&\n _isString(block.name) &&\n _isString(block.id)\n ) {\n yield {\n type: \"tool_call\",\n id: block.id,\n name: block.name,\n args: block.input,\n };\n continue;\n }\n // message chunks can have input_json_delta contents\n else if (_isContentBlock(block, \"input_json_delta\")) {\n if (_isAIMessageChunk(message) && message.tool_call_chunks?.length) {\n const tool_call_chunk = message.tool_call_chunks[0];\n yield {\n type: \"tool_call_chunk\",\n id: tool_call_chunk.id,\n name: tool_call_chunk.name,\n args: tool_call_chunk.args,\n index: tool_call_chunk.index,\n };\n continue;\n }\n }\n // ServerToolUseBlock\n else if (\n _isContentBlock(block, \"server_tool_use\") &&\n _isString(block.name) &&\n _isString(block.id)\n ) {\n const { name, id } = block;\n if (name === \"web_search\") {\n const query = iife(() => {\n if (typeof block.input === \"string\") {\n return block.input;\n } else if (_isObject(block.input) && _isString(block.input.query)) {\n return block.input.query;\n } else if (_isString(block.partial_json)) {\n const json = safeParseJson<{ query?: string }>(\n block.partial_json\n );\n if (json?.query) {\n return json.query;\n }\n }\n return \"\";\n });\n yield {\n id,\n type: \"server_tool_call\",\n name: \"web_search\",\n args: { query },\n };\n continue;\n } else if (block.name === \"code_execution\") {\n const code = iife(() => {\n if (typeof block.input === \"string\") {\n return block.input;\n } else if (_isObject(block.input) && _isString(block.input.code)) {\n return block.input.code;\n } else if (_isString(block.partial_json)) {\n const json = safeParseJson<{ code?: string }>(block.partial_json);\n if (json?.code) {\n return json.code;\n }\n }\n return \"\";\n });\n yield {\n id,\n type: \"server_tool_call\",\n name: \"code_execution\",\n args: { code },\n };\n continue;\n }\n }\n // WebSearchToolResultBlock\n else if (\n _isContentBlock(block, \"web_search_tool_result\") &&\n _isString(block.tool_use_id) &&\n _isArray(block.content)\n ) {\n const { content, tool_use_id } = block;\n const urls = content.reduce<string[]>((acc, content) => {\n if (_isContentBlock(content, \"web_search_result\")) {\n return [...acc, content.url as string];\n }\n return acc;\n }, []);\n yield {\n type: \"server_tool_call_result\",\n name: \"web_search\",\n toolCallId: tool_use_id,\n status: \"success\",\n output: {\n urls,\n },\n };\n continue;\n }\n // CodeExecutionToolResultBlock\n else if (\n _isContentBlock(block, \"code_execution_tool_result\") &&\n _isString(block.tool_use_id) &&\n _isObject(block.content)\n ) {\n yield {\n type: \"server_tool_call_result\",\n name: \"code_execution\",\n toolCallId: block.tool_use_id,\n status: \"success\",\n output: block.content,\n };\n continue;\n }\n // MCPToolUseBlock\n else if (_isContentBlock(block, \"mcp_tool_use\")) {\n yield {\n id: block.id,\n type: \"server_tool_call\",\n name: \"mcp_tool_use\",\n args: block.input,\n };\n continue;\n }\n // MCPToolResultBlock\n else if (\n _isContentBlock(block, \"mcp_tool_result\") &&\n _isString(block.tool_use_id) &&\n _isObject(block.content)\n ) {\n yield {\n type: \"server_tool_call_result\",\n name: \"mcp_tool_use\",\n toolCallId: block.tool_use_id,\n status: \"success\",\n output: block.content,\n };\n continue;\n }\n // ContainerUploadBlock\n else if (_isContentBlock(block, \"container_upload\")) {\n yield {\n type: \"server_tool_call\",\n name: \"container_upload\",\n args: block.input,\n };\n continue;\n }\n // SearchResultBlockParam\n else if (_isContentBlock(block, \"search_result\")) {\n yield { id: block.id, type: \"non_standard\", value: block };\n continue;\n }\n // ToolResultBlockParam\n else if (_isContentBlock(block, \"tool_result\")) {\n yield { id: block.id, type: \"non_standard\", value: block };\n continue;\n } else {\n // Anthropic has no refusal part; this is a stored standard block.\n if (_isContentBlock(block, \"refusal\") && _isString(block.refusal)) {\n hasRefusal = true;\n yield block as ContentBlock.Refusal;\n continue;\n }\n // For all other blocks, we try to convert them to a standard block\n const stdBlock = convertToV1FromAnthropicContentBlock(block);\n if (stdBlock) {\n yield stdBlock;\n continue;\n }\n }\n yield { type: \"non_standard\", value: block };\n }\n // Streamed chunks carry `message_delta` fields in `additional_kwargs`.\n const stopFields =\n message.response_metadata.stop_reason !== undefined\n ? message.response_metadata\n : message.additional_kwargs;\n if (!hasRefusal && stopFields.stop_reason === \"refusal\") {\n yield refusalFromStopDetails(stopFields.stop_details);\n }\n }\n return Array.from(iterateContent());\n}\n\nfunction refusalFromStopDetails(details: unknown): ContentBlock.Refusal {\n const stopDetails = _isObject(details) ? details : {};\n const explanation = stopDetails.explanation;\n const category = stopDetails.category;\n return {\n type: \"refusal\",\n refusal: _isString(explanation) ? explanation : \"\",\n ...(_isString(category) ? { extras: { category } } : {}),\n };\n}\n\nexport const ChatAnthropicTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromAnthropicMessage,\n translateContentChunk: convertToV1FromAnthropicMessage,\n};\n\nfunction _isAIMessageChunk(message: unknown): message is AIMessageChunk {\n return (\n typeof (message as BaseMessage)?._getType === \"function\" &&\n typeof (message as BaseMessageChunk).concat === \"function\" &&\n (message as BaseMessageChunk)._getType() === \"ai\"\n );\n}\n"],"mappings":"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"}
@@ -1,5 +1,28 @@
1
1
  const require_utils = require("./utils.cjs");
2
2
  // src/messages/block_translators/google.ts
3
+ const GEMINI_REFUSAL_FINISH_REASONS = /* @__PURE__ */ new Set([
4
+ "SAFETY",
5
+ "PROHIBITED_CONTENT",
6
+ "BLOCKLIST"
7
+ ]);
8
+ /**
9
+ * Builds a refusal block from a Gemini finish reason.
10
+ *
11
+ * A blocked prompt has no message: `@langchain/google` throws
12
+ * `PromptBlockedError` for it instead.
13
+ */
14
+ function refusalFromMetadata(message) {
15
+ const metadata = message.response_metadata;
16
+ const kwargs = message.additional_kwargs;
17
+ const finishReason = metadata.finishReason ?? metadata.finish_reason ?? kwargs.finishReason;
18
+ if (!require_utils._isString(finishReason) || !GEMINI_REFUSAL_FINISH_REASONS.has(finishReason)) return;
19
+ const finishMessage = metadata.finishMessage ?? kwargs.finishMessage;
20
+ return {
21
+ type: "refusal",
22
+ refusal: require_utils._isString(finishMessage) ? finishMessage : "",
23
+ extras: { finishReason }
24
+ };
25
+ }
3
26
  function convertToV1FromChatGoogleMessage(message) {
4
27
  function* iterateContent() {
5
28
  const content = require_utils.iife(() => {
@@ -86,7 +109,10 @@ function convertToV1FromChatGoogleMessage(message) {
86
109
  yield ret;
87
110
  }
88
111
  }
89
- return Array.from(iterateContent());
112
+ const blocks = Array.from(iterateContent());
113
+ const refusal = refusalFromMetadata(message);
114
+ if (refusal) blocks.push(refusal);
115
+ return blocks;
90
116
  }
91
117
  const ChatGoogleTranslator = {
92
118
  translateContent: convertToV1FromChatGoogleMessage,
@@ -1 +1 @@
1
- {"version":3,"file":"google.cjs","names":["iife","_isContentBlock","_isString","_isObject"],"sources":["../../../src/messages/block_translators/google.ts"],"sourcesContent":["import { AIMessage } from \"../ai.js\";\nimport { ContentBlock } from \"../content/index.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { iife, _isContentBlock, _isObject, _isString } from \"./utils.js\";\n\nfunction convertToV1FromChatGoogleMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content = iife(() => {\n if (typeof message.content === \"string\") {\n if (message.additional_kwargs.originalTextContentBlock) {\n return [\n {\n ...message.additional_kwargs.originalTextContentBlock,\n type: \"text\",\n },\n ];\n } else {\n return [{ type: \"text\", text: message.content }];\n }\n } else {\n const originalBlock = message.additional_kwargs\n ?.originalTextContentBlock as Record<string, unknown> | undefined;\n if (originalBlock?.thoughtSignature) {\n // During streaming with thinking models, thoughtSignature arrives in\n // a metadata-only chunk and is stored in originalTextContentBlock.\n // When content is an array (due to thinking parts), this signature\n // isn't carried into the content array by mergeContent().\n // Merge it into the last non-thinking text block.\n const hasSignatureInContent = message.content.some(\n (b: Record<string, unknown>) => \"thoughtSignature\" in b\n );\n if (!hasSignatureInContent) {\n const result = [...message.content];\n for (let i = result.length - 1; i >= 0; i--) {\n const block = result[i] as Record<string, unknown>;\n if (block.type === \"text\" && !block.thought) {\n block.thoughtSignature = originalBlock.thoughtSignature;\n return result;\n }\n }\n }\n }\n return message.content;\n }\n });\n for (const block of content) {\n const contentBlockBase: ContentBlock.Standard = iife(() => {\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n return {\n type: \"text\",\n text: block.text,\n };\n } else if (\n _isContentBlock(block, \"inlineData\") &&\n _isObject(block.inlineData) &&\n _isString(block.inlineData.mimeType) &&\n _isString(block.inlineData.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.inlineData.mimeType,\n data: block.inlineData.data,\n };\n } else if (\n _isContentBlock(block, \"functionCall\") &&\n _isObject(block.functionCall) &&\n _isString(block.functionCall.name) &&\n _isObject(block.functionCall.args)\n ) {\n return {\n type: \"tool_call\",\n id: message.id,\n name: block.functionCall.name,\n args: block.functionCall.args,\n };\n } else if (_isContentBlock(block, \"functionResponse\")) {\n return { type: \"non_standard\", value: block };\n } else if (\n _isContentBlock(block, \"fileData\") &&\n _isObject(block.fileData) &&\n _isString(block.fileData.mimeType) &&\n _isString(block.fileData.fileUri)\n ) {\n return {\n type: \"file\",\n mimeType: block.fileData.mimeType,\n fileId: block.fileData.fileUri,\n };\n } else if (_isContentBlock(block, \"executableCode\")) {\n return { type: \"non_standard\", value: block };\n } else if (_isContentBlock(block, \"codeExecutionResult\")) {\n return { type: \"non_standard\", value: block };\n }\n return { type: \"non_standard\", value: block };\n });\n const contentBlock: ContentBlock.Standard = iife(() => {\n if (\"thought\" in block && block.thought) {\n const reasoning: string =\n contentBlockBase.type === \"text\" ? contentBlockBase.text : \"\";\n return {\n type: \"reasoning\",\n reasoning,\n reasoningContentBlock: contentBlockBase,\n };\n } else {\n return contentBlockBase;\n }\n });\n\n const ret: ContentBlock.Standard = {\n thought: block.thought,\n thoughtSignature: block.thoughtSignature,\n partMetadata: block.partMetadata,\n ...contentBlock,\n };\n for (const attribute in ret) {\n if (ret[attribute] === undefined) {\n delete ret[attribute];\n }\n }\n\n yield ret;\n continue;\n }\n }\n return Array.from(iterateContent());\n}\n\nexport const ChatGoogleTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromChatGoogleMessage,\n translateContentChunk: convertToV1FromChatGoogleMessage,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"google.cjs","names":["_isString","iife","_isContentBlock","_isObject"],"sources":["../../../src/messages/block_translators/google.ts"],"sourcesContent":["import { AIMessage } from \"../ai.js\";\nimport { ContentBlock } from \"../content/index.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { iife, _isContentBlock, _isObject, _isString } from \"./utils.js\";\n\nconst GEMINI_REFUSAL_FINISH_REASONS = new Set([\n \"SAFETY\",\n \"PROHIBITED_CONTENT\",\n \"BLOCKLIST\",\n]);\n\n/**\n * Builds a refusal block from a Gemini finish reason.\n *\n * A blocked prompt has no message: `@langchain/google` throws\n * `PromptBlockedError` for it instead.\n */\nfunction refusalFromMetadata(\n message: AIMessage\n): ContentBlock.Refusal | undefined {\n const metadata = message.response_metadata;\n const kwargs = message.additional_kwargs;\n // `invoke` sets `finish_reason`, stream events set `finishReason`, and\n // streamed chunks keep both fields only in `additional_kwargs`.\n const finishReason =\n metadata.finishReason ?? metadata.finish_reason ?? kwargs.finishReason;\n if (\n !_isString(finishReason) ||\n !GEMINI_REFUSAL_FINISH_REASONS.has(finishReason)\n ) {\n return undefined;\n }\n const finishMessage = metadata.finishMessage ?? kwargs.finishMessage;\n return {\n type: \"refusal\",\n refusal: _isString(finishMessage) ? finishMessage : \"\",\n extras: { finishReason },\n };\n}\n\nfunction convertToV1FromChatGoogleMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content = iife(() => {\n if (typeof message.content === \"string\") {\n if (message.additional_kwargs.originalTextContentBlock) {\n return [\n {\n ...message.additional_kwargs.originalTextContentBlock,\n type: \"text\",\n },\n ];\n } else {\n return [{ type: \"text\", text: message.content }];\n }\n } else {\n const originalBlock = message.additional_kwargs\n ?.originalTextContentBlock as Record<string, unknown> | undefined;\n if (originalBlock?.thoughtSignature) {\n // During streaming with thinking models, thoughtSignature arrives in\n // a metadata-only chunk and is stored in originalTextContentBlock.\n // When content is an array (due to thinking parts), this signature\n // isn't carried into the content array by mergeContent().\n // Merge it into the last non-thinking text block.\n const hasSignatureInContent = message.content.some(\n (b: Record<string, unknown>) => \"thoughtSignature\" in b\n );\n if (!hasSignatureInContent) {\n const result = [...message.content];\n for (let i = result.length - 1; i >= 0; i--) {\n const block = result[i] as Record<string, unknown>;\n if (block.type === \"text\" && !block.thought) {\n block.thoughtSignature = originalBlock.thoughtSignature;\n return result;\n }\n }\n }\n }\n return message.content;\n }\n });\n for (const block of content) {\n const contentBlockBase: ContentBlock.Standard = iife(() => {\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n return {\n type: \"text\",\n text: block.text,\n };\n } else if (\n _isContentBlock(block, \"inlineData\") &&\n _isObject(block.inlineData) &&\n _isString(block.inlineData.mimeType) &&\n _isString(block.inlineData.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.inlineData.mimeType,\n data: block.inlineData.data,\n };\n } else if (\n _isContentBlock(block, \"functionCall\") &&\n _isObject(block.functionCall) &&\n _isString(block.functionCall.name) &&\n _isObject(block.functionCall.args)\n ) {\n return {\n type: \"tool_call\",\n id: message.id,\n name: block.functionCall.name,\n args: block.functionCall.args,\n };\n } else if (_isContentBlock(block, \"functionResponse\")) {\n return { type: \"non_standard\", value: block };\n } else if (\n _isContentBlock(block, \"fileData\") &&\n _isObject(block.fileData) &&\n _isString(block.fileData.mimeType) &&\n _isString(block.fileData.fileUri)\n ) {\n return {\n type: \"file\",\n mimeType: block.fileData.mimeType,\n fileId: block.fileData.fileUri,\n };\n } else if (_isContentBlock(block, \"executableCode\")) {\n return { type: \"non_standard\", value: block };\n } else if (_isContentBlock(block, \"codeExecutionResult\")) {\n return { type: \"non_standard\", value: block };\n }\n return { type: \"non_standard\", value: block };\n });\n const contentBlock: ContentBlock.Standard = iife(() => {\n if (\"thought\" in block && block.thought) {\n const reasoning: string =\n contentBlockBase.type === \"text\" ? contentBlockBase.text : \"\";\n return {\n type: \"reasoning\",\n reasoning,\n reasoningContentBlock: contentBlockBase,\n };\n } else {\n return contentBlockBase;\n }\n });\n\n const ret: ContentBlock.Standard = {\n thought: block.thought,\n thoughtSignature: block.thoughtSignature,\n partMetadata: block.partMetadata,\n ...contentBlock,\n };\n for (const attribute in ret) {\n if (ret[attribute] === undefined) {\n delete ret[attribute];\n }\n }\n\n yield ret;\n continue;\n }\n }\n const blocks = Array.from(iterateContent());\n const refusal = refusalFromMetadata(message);\n if (refusal) blocks.push(refusal);\n return blocks;\n}\n\nexport const ChatGoogleTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromChatGoogleMessage,\n translateContentChunk: convertToV1FromChatGoogleMessage,\n};\n"],"mappings":"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"}
@@ -1,5 +1,28 @@
1
1
  import { _isContentBlock, _isObject, _isString, iife } from "./utils.js";
2
2
  // src/messages/block_translators/google.ts
3
+ const GEMINI_REFUSAL_FINISH_REASONS = /* @__PURE__ */ new Set([
4
+ "SAFETY",
5
+ "PROHIBITED_CONTENT",
6
+ "BLOCKLIST"
7
+ ]);
8
+ /**
9
+ * Builds a refusal block from a Gemini finish reason.
10
+ *
11
+ * A blocked prompt has no message: `@langchain/google` throws
12
+ * `PromptBlockedError` for it instead.
13
+ */
14
+ function refusalFromMetadata(message) {
15
+ const metadata = message.response_metadata;
16
+ const kwargs = message.additional_kwargs;
17
+ const finishReason = metadata.finishReason ?? metadata.finish_reason ?? kwargs.finishReason;
18
+ if (!_isString(finishReason) || !GEMINI_REFUSAL_FINISH_REASONS.has(finishReason)) return;
19
+ const finishMessage = metadata.finishMessage ?? kwargs.finishMessage;
20
+ return {
21
+ type: "refusal",
22
+ refusal: _isString(finishMessage) ? finishMessage : "",
23
+ extras: { finishReason }
24
+ };
25
+ }
3
26
  function convertToV1FromChatGoogleMessage(message) {
4
27
  function* iterateContent() {
5
28
  const content = iife(() => {
@@ -86,7 +109,10 @@ function convertToV1FromChatGoogleMessage(message) {
86
109
  yield ret;
87
110
  }
88
111
  }
89
- return Array.from(iterateContent());
112
+ const blocks = Array.from(iterateContent());
113
+ const refusal = refusalFromMetadata(message);
114
+ if (refusal) blocks.push(refusal);
115
+ return blocks;
90
116
  }
91
117
  const ChatGoogleTranslator = {
92
118
  translateContent: convertToV1FromChatGoogleMessage,
@@ -1 +1 @@
1
- {"version":3,"file":"google.js","names":[],"sources":["../../../src/messages/block_translators/google.ts"],"sourcesContent":["import { AIMessage } from \"../ai.js\";\nimport { ContentBlock } from \"../content/index.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { iife, _isContentBlock, _isObject, _isString } from \"./utils.js\";\n\nfunction convertToV1FromChatGoogleMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content = iife(() => {\n if (typeof message.content === \"string\") {\n if (message.additional_kwargs.originalTextContentBlock) {\n return [\n {\n ...message.additional_kwargs.originalTextContentBlock,\n type: \"text\",\n },\n ];\n } else {\n return [{ type: \"text\", text: message.content }];\n }\n } else {\n const originalBlock = message.additional_kwargs\n ?.originalTextContentBlock as Record<string, unknown> | undefined;\n if (originalBlock?.thoughtSignature) {\n // During streaming with thinking models, thoughtSignature arrives in\n // a metadata-only chunk and is stored in originalTextContentBlock.\n // When content is an array (due to thinking parts), this signature\n // isn't carried into the content array by mergeContent().\n // Merge it into the last non-thinking text block.\n const hasSignatureInContent = message.content.some(\n (b: Record<string, unknown>) => \"thoughtSignature\" in b\n );\n if (!hasSignatureInContent) {\n const result = [...message.content];\n for (let i = result.length - 1; i >= 0; i--) {\n const block = result[i] as Record<string, unknown>;\n if (block.type === \"text\" && !block.thought) {\n block.thoughtSignature = originalBlock.thoughtSignature;\n return result;\n }\n }\n }\n }\n return message.content;\n }\n });\n for (const block of content) {\n const contentBlockBase: ContentBlock.Standard = iife(() => {\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n return {\n type: \"text\",\n text: block.text,\n };\n } else if (\n _isContentBlock(block, \"inlineData\") &&\n _isObject(block.inlineData) &&\n _isString(block.inlineData.mimeType) &&\n _isString(block.inlineData.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.inlineData.mimeType,\n data: block.inlineData.data,\n };\n } else if (\n _isContentBlock(block, \"functionCall\") &&\n _isObject(block.functionCall) &&\n _isString(block.functionCall.name) &&\n _isObject(block.functionCall.args)\n ) {\n return {\n type: \"tool_call\",\n id: message.id,\n name: block.functionCall.name,\n args: block.functionCall.args,\n };\n } else if (_isContentBlock(block, \"functionResponse\")) {\n return { type: \"non_standard\", value: block };\n } else if (\n _isContentBlock(block, \"fileData\") &&\n _isObject(block.fileData) &&\n _isString(block.fileData.mimeType) &&\n _isString(block.fileData.fileUri)\n ) {\n return {\n type: \"file\",\n mimeType: block.fileData.mimeType,\n fileId: block.fileData.fileUri,\n };\n } else if (_isContentBlock(block, \"executableCode\")) {\n return { type: \"non_standard\", value: block };\n } else if (_isContentBlock(block, \"codeExecutionResult\")) {\n return { type: \"non_standard\", value: block };\n }\n return { type: \"non_standard\", value: block };\n });\n const contentBlock: ContentBlock.Standard = iife(() => {\n if (\"thought\" in block && block.thought) {\n const reasoning: string =\n contentBlockBase.type === \"text\" ? contentBlockBase.text : \"\";\n return {\n type: \"reasoning\",\n reasoning,\n reasoningContentBlock: contentBlockBase,\n };\n } else {\n return contentBlockBase;\n }\n });\n\n const ret: ContentBlock.Standard = {\n thought: block.thought,\n thoughtSignature: block.thoughtSignature,\n partMetadata: block.partMetadata,\n ...contentBlock,\n };\n for (const attribute in ret) {\n if (ret[attribute] === undefined) {\n delete ret[attribute];\n }\n }\n\n yield ret;\n continue;\n }\n }\n return Array.from(iterateContent());\n}\n\nexport const ChatGoogleTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromChatGoogleMessage,\n translateContentChunk: convertToV1FromChatGoogleMessage,\n};\n"],"mappings":";;AAKA,SAAS,iCACP,SAC8B;CAC9B,UAAU,iBAAkD;EAC1D,MAAM,UAAU,WAAW;GACzB,IAAI,OAAO,QAAQ,YAAY,UAAU;IACvC,IAAI,QAAQ,kBAAkB,0BAC5B,OAAO,CACL;KACE,GAAG,QAAQ,kBAAkB;KAC7B,MAAM;IACR,CACF;SAEA,OAAO,CAAC;KAAE,MAAM;KAAQ,MAAM,QAAQ;IAAQ,CAAC;GAEnD,OAAO;IACL,MAAM,gBAAgB,QAAQ,mBAC1B;IACJ,IAAI,eAAe,kBASb;SAAA,CAH0B,QAAQ,QAAQ,MAC3C,MAA+B,sBAAsB,CAE/B,GAAG;MAC1B,MAAM,SAAS,CAAC,GAAG,QAAQ,OAAO;MAClC,KAAK,IAAI,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;OAC3C,MAAM,QAAQ,OAAO;OACrB,IAAI,MAAM,SAAS,UAAU,CAAC,MAAM,SAAS;QAC3C,MAAM,mBAAmB,cAAc;QACvC,OAAO;OACT;MACF;KACF;;IAEF,OAAO,QAAQ;GACjB;EACF,CAAC;EACD,KAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,mBAA0C,WAAW;IACzD,IAAI,gBAAgB,OAAO,MAAM,KAAK,UAAU,MAAM,IAAI,GACxD,OAAO;KACL,MAAM;KACN,MAAM,MAAM;IACd;SACK,IACL,gBAAgB,OAAO,YAAY,KACnC,UAAU,MAAM,UAAU,KAC1B,UAAU,MAAM,WAAW,QAAQ,KACnC,UAAU,MAAM,WAAW,IAAI,GAE/B,OAAO;KACL,MAAM;KACN,UAAU,MAAM,WAAW;KAC3B,MAAM,MAAM,WAAW;IACzB;SACK,IACL,gBAAgB,OAAO,cAAc,KACrC,UAAU,MAAM,YAAY,KAC5B,UAAU,MAAM,aAAa,IAAI,KACjC,UAAU,MAAM,aAAa,IAAI,GAEjC,OAAO;KACL,MAAM;KACN,IAAI,QAAQ;KACZ,MAAM,MAAM,aAAa;KACzB,MAAM,MAAM,aAAa;IAC3B;SACK,IAAI,gBAAgB,OAAO,kBAAkB,GAClD,OAAO;KAAE,MAAM;KAAgB,OAAO;IAAM;SACvC,IACL,gBAAgB,OAAO,UAAU,KACjC,UAAU,MAAM,QAAQ,KACxB,UAAU,MAAM,SAAS,QAAQ,KACjC,UAAU,MAAM,SAAS,OAAO,GAEhC,OAAO;KACL,MAAM;KACN,UAAU,MAAM,SAAS;KACzB,QAAQ,MAAM,SAAS;IACzB;SACK,IAAI,gBAAgB,OAAO,gBAAgB,GAChD,OAAO;KAAE,MAAM;KAAgB,OAAO;IAAM;SACvC,IAAI,gBAAgB,OAAO,qBAAqB,GACrD,OAAO;KAAE,MAAM;KAAgB,OAAO;IAAM;IAE9C,OAAO;KAAE,MAAM;KAAgB,OAAO;IAAM;GAC9C,CAAC;GACD,MAAM,eAAsC,WAAW;IACrD,IAAI,aAAa,SAAS,MAAM,SAG9B,OAAO;KACL,MAAM;KACN,WAHA,iBAAiB,SAAS,SAAS,iBAAiB,OAAO;KAI3D,uBAAuB;IACzB;SAEA,OAAO;GAEX,CAAC;GAED,MAAM,MAA6B;IACjC,SAAS,MAAM;IACf,kBAAkB,MAAM;IACxB,cAAc,MAAM;IACpB,GAAG;GACL;GACA,KAAK,MAAM,aAAa,KACtB,IAAI,IAAI,eAAe,KAAA,GACrB,OAAO,IAAI;GAIf,MAAM;EAER;CACF;CACA,OAAO,MAAM,KAAK,eAAe,CAAC;AACpC;AAEA,MAAa,uBAAuD;CAClE,kBAAkB;CAClB,uBAAuB;AACzB"}
1
+ {"version":3,"file":"google.js","names":[],"sources":["../../../src/messages/block_translators/google.ts"],"sourcesContent":["import { AIMessage } from \"../ai.js\";\nimport { ContentBlock } from \"../content/index.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { iife, _isContentBlock, _isObject, _isString } from \"./utils.js\";\n\nconst GEMINI_REFUSAL_FINISH_REASONS = new Set([\n \"SAFETY\",\n \"PROHIBITED_CONTENT\",\n \"BLOCKLIST\",\n]);\n\n/**\n * Builds a refusal block from a Gemini finish reason.\n *\n * A blocked prompt has no message: `@langchain/google` throws\n * `PromptBlockedError` for it instead.\n */\nfunction refusalFromMetadata(\n message: AIMessage\n): ContentBlock.Refusal | undefined {\n const metadata = message.response_metadata;\n const kwargs = message.additional_kwargs;\n // `invoke` sets `finish_reason`, stream events set `finishReason`, and\n // streamed chunks keep both fields only in `additional_kwargs`.\n const finishReason =\n metadata.finishReason ?? metadata.finish_reason ?? kwargs.finishReason;\n if (\n !_isString(finishReason) ||\n !GEMINI_REFUSAL_FINISH_REASONS.has(finishReason)\n ) {\n return undefined;\n }\n const finishMessage = metadata.finishMessage ?? kwargs.finishMessage;\n return {\n type: \"refusal\",\n refusal: _isString(finishMessage) ? finishMessage : \"\",\n extras: { finishReason },\n };\n}\n\nfunction convertToV1FromChatGoogleMessage(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n const content = iife(() => {\n if (typeof message.content === \"string\") {\n if (message.additional_kwargs.originalTextContentBlock) {\n return [\n {\n ...message.additional_kwargs.originalTextContentBlock,\n type: \"text\",\n },\n ];\n } else {\n return [{ type: \"text\", text: message.content }];\n }\n } else {\n const originalBlock = message.additional_kwargs\n ?.originalTextContentBlock as Record<string, unknown> | undefined;\n if (originalBlock?.thoughtSignature) {\n // During streaming with thinking models, thoughtSignature arrives in\n // a metadata-only chunk and is stored in originalTextContentBlock.\n // When content is an array (due to thinking parts), this signature\n // isn't carried into the content array by mergeContent().\n // Merge it into the last non-thinking text block.\n const hasSignatureInContent = message.content.some(\n (b: Record<string, unknown>) => \"thoughtSignature\" in b\n );\n if (!hasSignatureInContent) {\n const result = [...message.content];\n for (let i = result.length - 1; i >= 0; i--) {\n const block = result[i] as Record<string, unknown>;\n if (block.type === \"text\" && !block.thought) {\n block.thoughtSignature = originalBlock.thoughtSignature;\n return result;\n }\n }\n }\n }\n return message.content;\n }\n });\n for (const block of content) {\n const contentBlockBase: ContentBlock.Standard = iife(() => {\n if (_isContentBlock(block, \"text\") && _isString(block.text)) {\n return {\n type: \"text\",\n text: block.text,\n };\n } else if (\n _isContentBlock(block, \"inlineData\") &&\n _isObject(block.inlineData) &&\n _isString(block.inlineData.mimeType) &&\n _isString(block.inlineData.data)\n ) {\n return {\n type: \"file\",\n mimeType: block.inlineData.mimeType,\n data: block.inlineData.data,\n };\n } else if (\n _isContentBlock(block, \"functionCall\") &&\n _isObject(block.functionCall) &&\n _isString(block.functionCall.name) &&\n _isObject(block.functionCall.args)\n ) {\n return {\n type: \"tool_call\",\n id: message.id,\n name: block.functionCall.name,\n args: block.functionCall.args,\n };\n } else if (_isContentBlock(block, \"functionResponse\")) {\n return { type: \"non_standard\", value: block };\n } else if (\n _isContentBlock(block, \"fileData\") &&\n _isObject(block.fileData) &&\n _isString(block.fileData.mimeType) &&\n _isString(block.fileData.fileUri)\n ) {\n return {\n type: \"file\",\n mimeType: block.fileData.mimeType,\n fileId: block.fileData.fileUri,\n };\n } else if (_isContentBlock(block, \"executableCode\")) {\n return { type: \"non_standard\", value: block };\n } else if (_isContentBlock(block, \"codeExecutionResult\")) {\n return { type: \"non_standard\", value: block };\n }\n return { type: \"non_standard\", value: block };\n });\n const contentBlock: ContentBlock.Standard = iife(() => {\n if (\"thought\" in block && block.thought) {\n const reasoning: string =\n contentBlockBase.type === \"text\" ? contentBlockBase.text : \"\";\n return {\n type: \"reasoning\",\n reasoning,\n reasoningContentBlock: contentBlockBase,\n };\n } else {\n return contentBlockBase;\n }\n });\n\n const ret: ContentBlock.Standard = {\n thought: block.thought,\n thoughtSignature: block.thoughtSignature,\n partMetadata: block.partMetadata,\n ...contentBlock,\n };\n for (const attribute in ret) {\n if (ret[attribute] === undefined) {\n delete ret[attribute];\n }\n }\n\n yield ret;\n continue;\n }\n }\n const blocks = Array.from(iterateContent());\n const refusal = refusalFromMetadata(message);\n if (refusal) blocks.push(refusal);\n return blocks;\n}\n\nexport const ChatGoogleTranslator: StandardContentBlockTranslator = {\n translateContent: convertToV1FromChatGoogleMessage,\n translateContentChunk: convertToV1FromChatGoogleMessage,\n};\n"],"mappings":"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"}
@@ -1,6 +1,14 @@
1
1
  const require_data = require("./data.cjs");
2
2
  const require_utils = require("./utils.cjs");
3
3
  // src/messages/block_translators/openai.ts
4
+ /** The refusal Chat Completions and Responses keep in `additional_kwargs`. */
5
+ function refusalFromAdditionalKwargs(message) {
6
+ const refusal = message.additional_kwargs.refusal;
7
+ return require_utils._isString(refusal) && refusal.length > 0 ? {
8
+ type: "refusal",
9
+ refusal
10
+ } : void 0;
11
+ }
4
12
  /**
5
13
  * Converts a ChatOpenAICompletions message to an array of v1 standard content blocks.
6
14
  *
@@ -51,6 +59,8 @@ function convertToV1FromChatCompletions(message) {
51
59
  name: toolCall.name,
52
60
  args: toolCall.args
53
61
  });
62
+ const refusal = refusalFromAdditionalKwargs(message);
63
+ if (refusal) blocks.push(refusal);
54
64
  return blocks;
55
65
  }
56
66
  /**
@@ -101,6 +111,8 @@ function convertToV1FromChatCompletionsChunk(message) {
101
111
  name: toolCall.name,
102
112
  args: toolCall.args
103
113
  });
114
+ const refusal = refusalFromAdditionalKwargs(message);
115
+ if (refusal) blocks.push(refusal);
104
116
  return blocks;
105
117
  }
106
118
  /**
@@ -407,6 +419,19 @@ function convertToV1FromResponses(message) {
407
419
  ...Array.isArray(annotations) ? { annotations: annotations.map(convertResponsesAnnotation) } : {}
408
420
  }, textBlockKey];
409
421
  }
422
+ let hasRefusalPart = false;
423
+ for (const block of content) if (require_utils._isContentBlock(block, "refusal") && require_utils._isString(block.refusal)) {
424
+ hasRefusalPart = true;
425
+ yield [{
426
+ type: "refusal",
427
+ refusal: block.refusal,
428
+ ...require_utils._isString(block.id) ? { id: block.id } : {}
429
+ }, textBlockKey];
430
+ }
431
+ if (!hasRefusalPart) {
432
+ const refusal = refusalFromAdditionalKwargs(message);
433
+ if (refusal) yield [refusal, textBlockKey];
434
+ }
410
435
  for (const toolCall of message.tool_calls ?? []) yield [{
411
436
  type: "tool_call",
412
437
  id: toolCall.id,
@@ -1 +1 @@
1
- {"version":3,"file":"openai.cjs","names":["isOpenAIDataBlock","convertToV1FromOpenAIDataBlock","_isArray","_isObject","_isString","_isContentBlock","iife"],"sources":["../../../src/messages/block_translators/openai.ts"],"sourcesContent":["import type { ContentBlock } from \"../content/index.js\";\nimport type { AIMessageChunk, AIMessage } from \"../ai.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { convertToV1FromOpenAIDataBlock, isOpenAIDataBlock } from \"./data.js\";\nimport {\n _isArray,\n _isContentBlock,\n _isObject,\n _isString,\n iife,\n} from \"./utils.js\";\n\n/**\n * Converts a ChatOpenAICompletions message to an array of v1 standard content blocks.\n *\n * This function processes an AI message from ChatOpenAICompletions API format\n * and converts it to the standardized v1 content block format. It handles both\n * string content and structured content blocks, as well as tool calls.\n *\n * @param message - The AI message containing ChatOpenAICompletions formatted content\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage(\"Hello world\");\n * const standardBlocks = convertToV1FromChatCompletions(message);\n * // Returns: [{ type: \"text\", text: \"Hello world\" }]\n * ```\n *\n * @example\n * ```typescript\n * const message = new AIMessage([\n * { type: \"text\", text: \"Hello\" },\n * { type: \"image_url\", image_url: { url: \"https://example.com/image.png\" } }\n * ]);\n * message.tool_calls = [\n * { id: \"call_123\", name: \"calculator\", args: { a: 1, b: 2 } }\n * ];\n *\n * const standardBlocks = convertToV1FromChatCompletions(message);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello\" },\n * // { type: \"image\", url: \"https://example.com/image.png\" },\n * // { type: \"tool_call\", id: \"call_123\", name: \"calculator\", args: { a: 1, b: 2 } }\n * // ]\n * ```\n */\nexport function convertToV1FromChatCompletions(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n const blocks: Array<ContentBlock.Standard> = [];\n if (typeof message.content === \"string\") {\n // Only add text block if content is non-empty\n if (message.content.length > 0) {\n blocks.push({\n type: \"text\",\n text: message.content,\n });\n }\n } else {\n blocks.push(...convertToV1FromChatCompletionsInput(message.content));\n }\n for (const toolCall of message.tool_calls ?? []) {\n blocks.push({\n type: \"tool_call\",\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.args,\n });\n }\n return blocks;\n}\n\n/**\n * Converts a ChatOpenAICompletions message chunk to an array of v1 standard content blocks.\n *\n * This function processes an AI message chunk from OpenAI's chat completions API and converts\n * it to the standardized v1 content block format. It handles both string and array content,\n * as well as tool calls that may be present in the chunk.\n *\n * @param message - The AI message chunk containing OpenAI-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const chunk = new AIMessage(\"Hello\");\n * const standardBlocks = convertToV1FromChatCompletionsChunk(chunk);\n * // Returns: [{ type: \"text\", text: \"Hello\" }]\n * ```\n *\n * @example\n * ```typescript\n * const chunk = new AIMessage([\n * { type: \"text\", text: \"Processing...\" }\n * ]);\n * chunk.tool_calls = [\n * { id: \"call_456\", name: \"search\", args: { query: \"test\" } }\n * ];\n *\n * const standardBlocks = convertToV1FromChatCompletionsChunk(chunk);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Processing...\" },\n * // { type: \"tool_call\", id: \"call_456\", name: \"search\", args: { query: \"test\" } }\n * // ]\n * ```\n */\nexport function convertToV1FromChatCompletionsChunk(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n const blocks: Array<ContentBlock.Standard> = [];\n if (typeof message.content === \"string\") {\n // Only add text block if content is non-empty\n if (message.content.length > 0) {\n blocks.push({\n type: \"text\",\n text: message.content,\n });\n }\n } else {\n blocks.push(...convertToV1FromChatCompletionsInput(message.content));\n }\n\n // TODO: parse chunk position information\n for (const toolCall of message.tool_calls ?? []) {\n blocks.push({\n type: \"tool_call\",\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.args,\n });\n }\n return blocks;\n}\n\n/**\n * Converts an array of ChatOpenAICompletions content blocks to v1 standard content blocks.\n *\n * This function processes content blocks from OpenAI's Chat Completions API format\n * and converts them to the standardized v1 content block format. It handles both\n * OpenAI-specific data blocks (which require conversion) and standard blocks\n * (which are passed through with type assertion).\n *\n * @param blocks - Array of content blocks in ChatOpenAICompletions format\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const openaiBlocks = [\n * { type: \"text\", text: \"Hello world\" },\n * { type: \"image_url\", image_url: { url: \"https://example.com/image.png\" } }\n * ];\n *\n * const standardBlocks = convertToV1FromChatCompletionsInput(openaiBlocks);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello world\" },\n * // { type: \"image\", url: \"https://example.com/image.png\" }\n * // ]\n * ```\n */\nexport function convertToV1FromChatCompletionsInput(\n blocks: Array<ContentBlock>\n): Array<ContentBlock.Standard> {\n const convertedBlocks: Array<ContentBlock.Standard> = [];\n for (const block of blocks) {\n if (isOpenAIDataBlock(block)) {\n convertedBlocks.push(convertToV1FromOpenAIDataBlock(block));\n } else {\n convertedBlocks.push(block as ContentBlock.Standard);\n }\n }\n return convertedBlocks;\n}\n\nfunction convertResponsesAnnotation(\n annotation: ContentBlock\n): ContentBlock | ContentBlock.Citation {\n if (annotation.type === \"url_citation\") {\n const { url, title, start_index, end_index } = annotation;\n return {\n type: \"citation\",\n url,\n title,\n startIndex: start_index,\n endIndex: end_index,\n };\n }\n if (annotation.type === \"file_citation\") {\n const { file_id, filename, index } = annotation;\n return {\n type: \"citation\",\n title: filename,\n startIndex: index,\n endIndex: index,\n fileId: file_id,\n };\n }\n return annotation;\n}\n\n/** Builds a reasoning content block, including id/encrypted_content when present. */\nfunction mapReasoningItemToV1(\n item: Record<string, unknown>\n): ContentBlock.Standard | undefined {\n if (!_isArray(item.summary)) return undefined;\n const summary = item.summary.reduce<string>((acc, part) => {\n if (_isObject(part) && _isString(part.text)) {\n return `${acc}${part.text}`;\n }\n return acc;\n }, \"\");\n return {\n type: \"reasoning\",\n reasoning: summary,\n ...(_isString(item.id) ? { id: item.id } : {}),\n ...(_isString(item.encrypted_content)\n ? { encrypted_content: item.encrypted_content }\n : {}),\n } as ContentBlock.Standard;\n}\n\n// Converts a single built-in tool call/result entry into v1 content blocks.\nfunction* mapToolOutputToV1Blocks(\n toolOutput: unknown\n): Iterable<ContentBlock.Standard> {\n if (_isContentBlock(toolOutput, \"web_search_call\")) {\n const webSearchArgs: Record<string, unknown> = {};\n if (_isObject(toolOutput.action) && _isString(toolOutput.action.query)) {\n webSearchArgs.query = toolOutput.action.query;\n }\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"web_search\",\n args: webSearchArgs,\n };\n // Emit a server_tool_call_result when the search has completed or failed\n if (toolOutput.status === \"completed\" || toolOutput.status === \"failed\") {\n const output: Record<string, unknown> = {};\n if (_isObject(toolOutput.action)) {\n output.action = toolOutput.action;\n }\n yield {\n type: \"server_tool_call_result\",\n toolCallId: _isString(toolOutput.id) ? toolOutput.id : \"\",\n status: toolOutput.status === \"completed\" ? \"success\" : \"error\",\n output,\n };\n }\n return;\n }\n if (_isContentBlock(toolOutput, \"file_search_call\")) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"file_search\",\n args: {\n queries: _isArray(toolOutput.queries) ? toolOutput.queries : [],\n },\n };\n // Emit a server_tool_call_result when results are available\n if (toolOutput.status === \"completed\" || toolOutput.status === \"failed\") {\n yield {\n type: \"server_tool_call_result\",\n toolCallId: _isString(toolOutput.id) ? toolOutput.id : \"\",\n status: toolOutput.status === \"completed\" ? \"success\" : \"error\",\n output: _isArray(toolOutput.results)\n ? { results: toolOutput.results }\n : {},\n };\n }\n return;\n }\n if (_isContentBlock(toolOutput, \"computer_call\")) {\n yield { type: \"non_standard\", value: toolOutput };\n return;\n }\n if (_isContentBlock(toolOutput, \"code_interpreter_call\")) {\n if (_isString(toolOutput.code)) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"code_interpreter\",\n args: { code: toolOutput.code },\n };\n }\n if (_isArray(toolOutput.outputs)) {\n const returnCode = iife(() => {\n if (toolOutput.status === \"in_progress\") return undefined;\n if (toolOutput.status === \"completed\") return 0;\n if (toolOutput.status === \"incomplete\") return 127;\n if (toolOutput.status === \"interpreting\") return undefined;\n if (toolOutput.status === \"failed\") return 1;\n return undefined;\n });\n for (const output of toolOutput.outputs) {\n if (_isContentBlock(output, \"logs\")) {\n yield {\n type: \"server_tool_call_result\",\n toolCallId: toolOutput.id ?? \"\",\n status: \"success\",\n output: {\n type: \"code_interpreter_output\",\n returnCode: returnCode ?? 0,\n stderr: [0, undefined].includes(returnCode)\n ? undefined\n : String(output.logs),\n stdout: [0, undefined].includes(returnCode)\n ? String(output.logs)\n : undefined,\n },\n };\n }\n }\n }\n return;\n }\n if (_isContentBlock(toolOutput, \"mcp_call\")) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"mcp_call\",\n args: toolOutput.input,\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"mcp_list_tools\")) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"mcp_list_tools\",\n args: toolOutput.input,\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"mcp_approval_request\")) {\n yield { type: \"non_standard\", value: toolOutput };\n return;\n }\n if (_isContentBlock(toolOutput, \"tool_search_call\")) {\n const toolSearchArgs: Record<string, unknown> = {};\n if (_isObject(toolOutput.arguments)) {\n Object.assign(toolSearchArgs, toolOutput.arguments);\n }\n const toolSearchCallExtras: Record<string, unknown> = {};\n if (_isString(toolOutput.execution)) {\n toolSearchCallExtras.execution = toolOutput.execution;\n }\n if (_isString(toolOutput.status)) {\n toolSearchCallExtras.status = toolOutput.status;\n }\n if (_isString(toolOutput.call_id)) {\n toolSearchCallExtras.call_id = toolOutput.call_id;\n }\n yield {\n id: _isString(toolOutput.id) ? toolOutput.id : \"\",\n type: \"server_tool_call\",\n name: \"tool_search\",\n args: toolSearchArgs,\n ...(Object.keys(toolSearchCallExtras).length > 0\n ? { extras: toolSearchCallExtras }\n : {}),\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"tool_search_output\")) {\n const toolSearchOutputExtras: Record<string, unknown> = {\n name: \"tool_search\",\n };\n if (_isString(toolOutput.execution)) {\n toolSearchOutputExtras.execution = toolOutput.execution;\n }\n yield {\n type: \"server_tool_call_result\",\n toolCallId: _isString(toolOutput.id) ? toolOutput.id : \"\",\n status:\n toolOutput.status === \"completed\"\n ? \"success\"\n : toolOutput.status === \"failed\"\n ? \"error\"\n : \"success\",\n output: {\n tools: _isArray(toolOutput.tools) ? toolOutput.tools : [],\n },\n extras: toolSearchOutputExtras,\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"image_generation_call\")) {\n // Convert image_generation_call to proper image content block if result is available\n if (_isString(toolOutput.result)) {\n yield {\n type: \"image\",\n mimeType: \"image/png\",\n data: toolOutput.result,\n id: _isString(toolOutput.id) ? toolOutput.id : undefined,\n metadata: {\n status: _isString(toolOutput.status) ? toolOutput.status : undefined,\n },\n };\n }\n // Also yield as non_standard for backwards compatibility\n yield { type: \"non_standard\", value: toolOutput };\n return;\n }\n if (_isObject(toolOutput)) {\n yield { type: \"non_standard\", value: toolOutput };\n }\n}\n\n/**\n * Converts a ChatOpenAIResponses message to an array of v1 standard content blocks.\n *\n * This function processes an AI message containing OpenAI Responses-specific content blocks\n * and converts them to the standardized v1 content block format. It handles reasoning summaries,\n * text content with annotations, tool calls, and various tool outputs including code interpreter,\n * web search, file search, computer calls, and MCP-related blocks.\n *\n * A response can hold more than one reasoning item (e.g. multiple tool calls\n * in one turn, common on GPT-5.6-class models). When `response_metadata.output`\n * is available, each item's own `id`/`encrypted_content` is preserved and\n * blocks are sorted back into original order, so replay under Zero Data\n * Retention interleaves reasoning and tool calls correctly. Without it (e.g.\n * a hand-built message), falls back to a single reasoning block from\n * `additional_kwargs.reasoning`, as before.\n *\n * @param message - The AI message containing OpenAI Responses-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage({\n * content: [{ type: \"text\", text: \"Hello world\", annotations: [] }],\n * tool_calls: [{ id: \"123\", name: \"calculator\", args: { a: 1, b: 2 } }],\n * additional_kwargs: {\n * reasoning: { summary: [{ text: \"Let me calculate this...\" }] },\n * tool_outputs: [\n * {\n * type: \"code_interpreter_call\",\n * code: \"print('hello')\",\n * outputs: [{ type: \"logs\", logs: \"hello\" }]\n * }\n * ]\n * }\n * });\n *\n * const standardBlocks = convertToV1FromResponses(message);\n * // Returns:\n * // [\n * // { type: \"reasoning\", reasoning: \"Let me calculate this...\" },\n * // { type: \"text\", text: \"Hello world\", annotations: [] },\n * // { type: \"tool_call\", id: \"123\", name: \"calculator\", args: { a: 1, b: 2 } },\n * // { type: \"server_tool_call\", name: \"code_interpreter\", args: { code: \"print('hello')\" } },\n * // { type: \"server_tool_call_result\", toolCallId: \"\", status: \"success\", output: { type: \"code_interpreter_output\", returnCode: 0, stdout: \"hello\" } }\n * // ]\n * ```\n */\nexport function convertToV1FromResponses(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n const rawOutput = message.response_metadata?.output;\n const hasRawOutput = _isArray(rawOutput) && rawOutput.length > 0;\n\n // Maps a per-item key (namespaced by type, since ids aren't globally unique) to its original response.output position.\n const positionByKey = new Map<string, number>();\n let messageItemCount = 0;\n let onlyMessageItemIndex: number | undefined;\n if (hasRawOutput) {\n (rawOutput as unknown[]).forEach((rawItem, index) => {\n if (!_isObject(rawItem) || !_isString(rawItem.type)) return;\n if (rawItem.type === \"reasoning\" && _isString(rawItem.id)) {\n positionByKey.set(`reasoning:${rawItem.id}`, index);\n } else if (\n // These three types all become tool_call blocks keyed by call_id.\n (rawItem.type === \"function_call\" ||\n rawItem.type === \"custom_tool_call\" ||\n rawItem.type === \"computer_call\") &&\n _isString(rawItem.call_id)\n ) {\n positionByKey.set(`tool_call:${rawItem.call_id}`, index);\n } else if (rawItem.type === \"message\") {\n messageItemCount += 1;\n onlyMessageItemIndex = index;\n } else if (_isString(rawItem.id)) {\n positionByKey.set(`other:${rawItem.type}:${rawItem.id}`, index);\n }\n });\n }\n // Text isn't keyed to a specific \"message\" item, so only position it when exactly one exists (an unambiguous match).\n const textBlockKey =\n messageItemCount === 1 && onlyMessageItemIndex != null\n ? `message:${onlyMessageItemIndex}`\n : undefined;\n if (textBlockKey != null) {\n positionByKey.set(textBlockKey, onlyMessageItemIndex as number);\n }\n\n function* iterateContent(): Iterable<\n [block: ContentBlock.Standard, key: string | undefined]\n > {\n if (hasRawOutput) {\n for (const rawItem of rawOutput as unknown[]) {\n if (_isObject(rawItem) && rawItem.type === \"reasoning\") {\n const block = mapReasoningItemToV1(rawItem);\n if (block) {\n yield [\n block,\n _isString(rawItem.id) ? `reasoning:${rawItem.id}` : undefined,\n ];\n }\n }\n }\n } else if (\n _isObject(message.additional_kwargs?.reasoning) &&\n _isArray(message.additional_kwargs.reasoning.summary)\n ) {\n const block = mapReasoningItemToV1(message.additional_kwargs.reasoning);\n if (block) yield [block, undefined];\n }\n\n const content =\n typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n for (const block of content) {\n if (_isContentBlock(block, \"text\")) {\n const {\n text,\n annotations,\n phase,\n extras: existingExtras,\n ...rest\n } = block;\n const extras: Record<string, unknown> = _isObject(existingExtras)\n ? { ...(existingExtras as Record<string, unknown>) }\n : {};\n if (_isString(phase)) {\n extras.phase = phase;\n }\n const extrasSpread = Object.keys(extras).length > 0 ? { extras } : {};\n yield [\n {\n ...rest,\n ...extrasSpread,\n type: \"text\",\n text: String(text),\n ...(Array.isArray(annotations)\n ? { annotations: annotations.map(convertResponsesAnnotation) }\n : {}),\n },\n textBlockKey,\n ];\n }\n }\n for (const toolCall of message.tool_calls ?? []) {\n yield [\n {\n type: \"tool_call\",\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.args,\n },\n toolCall.id ? `tool_call:${toolCall.id}` : undefined,\n ];\n }\n if (\n _isObject(message.additional_kwargs) &&\n _isArray(message.additional_kwargs.tool_outputs)\n ) {\n for (const toolOutput of message.additional_kwargs.tool_outputs) {\n // All blocks from one tool output share this key -- fine since the API returns a call and its result as one item.\n const key =\n _isObject(toolOutput) &&\n _isString(toolOutput.type) &&\n _isString(toolOutput.id)\n ? `other:${toolOutput.type}:${toolOutput.id}`\n : undefined;\n for (const block of mapToolOutputToV1Blocks(toolOutput)) {\n yield [block, key];\n }\n }\n }\n }\n\n const withKeys = Array.from(iterateContent());\n if (!hasRawOutput) {\n return withKeys.map(([block]) => block);\n }\n // Stable sort by original position; unkeyed blocks sort last, in push order.\n return withKeys\n .map(([block, key], pushIndex) => ({\n block,\n pushIndex,\n position: key != null ? positionByKey.get(key) : undefined,\n }))\n .sort((a, b) => {\n const aPos = a.position ?? Number.POSITIVE_INFINITY;\n const bPos = b.position ?? Number.POSITIVE_INFINITY;\n if (aPos !== bPos) return aPos - bPos;\n return a.pushIndex - b.pushIndex;\n })\n .map((entry) => entry.block);\n}\n\n/**\n * Converts a ChatOpenAIResponses message chunk to an array of v1 standard content blocks.\n *\n * This function processes an AI message chunk containing OpenAI-specific content blocks\n * and converts them to the standardized v1 content block format. It handles both the\n * regular message content and tool call chunks that are specific to streaming responses.\n *\n * @param message - The AI message chunk containing OpenAI-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const messageChunk = new AIMessageChunk({\n * content: [{ type: \"text\", text: \"Hello\" }],\n * tool_call_chunks: [\n * { id: \"call_123\", name: \"calculator\", args: '{\"a\": 1' }\n * ]\n * });\n *\n * const standardBlocks = convertToV1FromResponsesChunk(messageChunk);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello\" },\n * // { type: \"tool_call_chunk\", id: \"call_123\", name: \"calculator\", args: '{\"a\": 1' }\n * // ]\n * ```\n */\nexport function convertToV1FromResponsesChunk(\n message: AIMessageChunk\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n yield* convertToV1FromResponses(message);\n for (const toolCallChunk of message.tool_call_chunks ?? []) {\n yield {\n type: \"tool_call_chunk\",\n id: toolCallChunk.id,\n name: toolCallChunk.name,\n args: toolCallChunk.args,\n };\n }\n }\n return Array.from(iterateContent());\n}\n\nexport const ChatOpenAITranslator: StandardContentBlockTranslator = {\n translateContent: (message) => {\n if (typeof message.content === \"string\") {\n return convertToV1FromChatCompletions(message);\n }\n return convertToV1FromResponses(message);\n },\n translateContentChunk: (message) => {\n if (typeof message.content === \"string\") {\n return convertToV1FromChatCompletionsChunk(message);\n }\n return convertToV1FromResponsesChunk(message);\n },\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"openai.cjs","names":["_isString","isOpenAIDataBlock","convertToV1FromOpenAIDataBlock","_isArray","_isObject","_isContentBlock","iife"],"sources":["../../../src/messages/block_translators/openai.ts"],"sourcesContent":["import type { ContentBlock } from \"../content/index.js\";\nimport type { AIMessageChunk, AIMessage } from \"../ai.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { convertToV1FromOpenAIDataBlock, isOpenAIDataBlock } from \"./data.js\";\nimport {\n _isArray,\n _isContentBlock,\n _isObject,\n _isString,\n iife,\n} from \"./utils.js\";\n\n/** The refusal Chat Completions and Responses keep in `additional_kwargs`. */\nfunction refusalFromAdditionalKwargs(\n message: AIMessage\n): ContentBlock.Refusal | undefined {\n const refusal = message.additional_kwargs.refusal;\n return _isString(refusal) && refusal.length > 0\n ? { type: \"refusal\", refusal }\n : undefined;\n}\n\n/**\n * Converts a ChatOpenAICompletions message to an array of v1 standard content blocks.\n *\n * This function processes an AI message from ChatOpenAICompletions API format\n * and converts it to the standardized v1 content block format. It handles both\n * string content and structured content blocks, as well as tool calls.\n *\n * @param message - The AI message containing ChatOpenAICompletions formatted content\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage(\"Hello world\");\n * const standardBlocks = convertToV1FromChatCompletions(message);\n * // Returns: [{ type: \"text\", text: \"Hello world\" }]\n * ```\n *\n * @example\n * ```typescript\n * const message = new AIMessage([\n * { type: \"text\", text: \"Hello\" },\n * { type: \"image_url\", image_url: { url: \"https://example.com/image.png\" } }\n * ]);\n * message.tool_calls = [\n * { id: \"call_123\", name: \"calculator\", args: { a: 1, b: 2 } }\n * ];\n *\n * const standardBlocks = convertToV1FromChatCompletions(message);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello\" },\n * // { type: \"image\", url: \"https://example.com/image.png\" },\n * // { type: \"tool_call\", id: \"call_123\", name: \"calculator\", args: { a: 1, b: 2 } }\n * // ]\n * ```\n */\nexport function convertToV1FromChatCompletions(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n const blocks: Array<ContentBlock.Standard> = [];\n if (typeof message.content === \"string\") {\n // Only add text block if content is non-empty\n if (message.content.length > 0) {\n blocks.push({\n type: \"text\",\n text: message.content,\n });\n }\n } else {\n blocks.push(...convertToV1FromChatCompletionsInput(message.content));\n }\n for (const toolCall of message.tool_calls ?? []) {\n blocks.push({\n type: \"tool_call\",\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.args,\n });\n }\n const refusal = refusalFromAdditionalKwargs(message);\n if (refusal) blocks.push(refusal);\n return blocks;\n}\n\n/**\n * Converts a ChatOpenAICompletions message chunk to an array of v1 standard content blocks.\n *\n * This function processes an AI message chunk from OpenAI's chat completions API and converts\n * it to the standardized v1 content block format. It handles both string and array content,\n * as well as tool calls that may be present in the chunk.\n *\n * @param message - The AI message chunk containing OpenAI-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const chunk = new AIMessage(\"Hello\");\n * const standardBlocks = convertToV1FromChatCompletionsChunk(chunk);\n * // Returns: [{ type: \"text\", text: \"Hello\" }]\n * ```\n *\n * @example\n * ```typescript\n * const chunk = new AIMessage([\n * { type: \"text\", text: \"Processing...\" }\n * ]);\n * chunk.tool_calls = [\n * { id: \"call_456\", name: \"search\", args: { query: \"test\" } }\n * ];\n *\n * const standardBlocks = convertToV1FromChatCompletionsChunk(chunk);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Processing...\" },\n * // { type: \"tool_call\", id: \"call_456\", name: \"search\", args: { query: \"test\" } }\n * // ]\n * ```\n */\nexport function convertToV1FromChatCompletionsChunk(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n const blocks: Array<ContentBlock.Standard> = [];\n if (typeof message.content === \"string\") {\n // Only add text block if content is non-empty\n if (message.content.length > 0) {\n blocks.push({\n type: \"text\",\n text: message.content,\n });\n }\n } else {\n blocks.push(...convertToV1FromChatCompletionsInput(message.content));\n }\n\n // TODO: parse chunk position information\n for (const toolCall of message.tool_calls ?? []) {\n blocks.push({\n type: \"tool_call\",\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.args,\n });\n }\n const refusal = refusalFromAdditionalKwargs(message);\n if (refusal) blocks.push(refusal);\n return blocks;\n}\n\n/**\n * Converts an array of ChatOpenAICompletions content blocks to v1 standard content blocks.\n *\n * This function processes content blocks from OpenAI's Chat Completions API format\n * and converts them to the standardized v1 content block format. It handles both\n * OpenAI-specific data blocks (which require conversion) and standard blocks\n * (which are passed through with type assertion).\n *\n * @param blocks - Array of content blocks in ChatOpenAICompletions format\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const openaiBlocks = [\n * { type: \"text\", text: \"Hello world\" },\n * { type: \"image_url\", image_url: { url: \"https://example.com/image.png\" } }\n * ];\n *\n * const standardBlocks = convertToV1FromChatCompletionsInput(openaiBlocks);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello world\" },\n * // { type: \"image\", url: \"https://example.com/image.png\" }\n * // ]\n * ```\n */\nexport function convertToV1FromChatCompletionsInput(\n blocks: Array<ContentBlock>\n): Array<ContentBlock.Standard> {\n const convertedBlocks: Array<ContentBlock.Standard> = [];\n for (const block of blocks) {\n if (isOpenAIDataBlock(block)) {\n convertedBlocks.push(convertToV1FromOpenAIDataBlock(block));\n } else {\n convertedBlocks.push(block as ContentBlock.Standard);\n }\n }\n return convertedBlocks;\n}\n\nfunction convertResponsesAnnotation(\n annotation: ContentBlock\n): ContentBlock | ContentBlock.Citation {\n if (annotation.type === \"url_citation\") {\n const { url, title, start_index, end_index } = annotation;\n return {\n type: \"citation\",\n url,\n title,\n startIndex: start_index,\n endIndex: end_index,\n };\n }\n if (annotation.type === \"file_citation\") {\n const { file_id, filename, index } = annotation;\n return {\n type: \"citation\",\n title: filename,\n startIndex: index,\n endIndex: index,\n fileId: file_id,\n };\n }\n return annotation;\n}\n\n/** Builds a reasoning content block, including id/encrypted_content when present. */\nfunction mapReasoningItemToV1(\n item: Record<string, unknown>\n): ContentBlock.Standard | undefined {\n if (!_isArray(item.summary)) return undefined;\n const summary = item.summary.reduce<string>((acc, part) => {\n if (_isObject(part) && _isString(part.text)) {\n return `${acc}${part.text}`;\n }\n return acc;\n }, \"\");\n return {\n type: \"reasoning\",\n reasoning: summary,\n ...(_isString(item.id) ? { id: item.id } : {}),\n ...(_isString(item.encrypted_content)\n ? { encrypted_content: item.encrypted_content }\n : {}),\n } as ContentBlock.Standard;\n}\n\n// Converts a single built-in tool call/result entry into v1 content blocks.\nfunction* mapToolOutputToV1Blocks(\n toolOutput: unknown\n): Iterable<ContentBlock.Standard> {\n if (_isContentBlock(toolOutput, \"web_search_call\")) {\n const webSearchArgs: Record<string, unknown> = {};\n if (_isObject(toolOutput.action) && _isString(toolOutput.action.query)) {\n webSearchArgs.query = toolOutput.action.query;\n }\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"web_search\",\n args: webSearchArgs,\n };\n // Emit a server_tool_call_result when the search has completed or failed\n if (toolOutput.status === \"completed\" || toolOutput.status === \"failed\") {\n const output: Record<string, unknown> = {};\n if (_isObject(toolOutput.action)) {\n output.action = toolOutput.action;\n }\n yield {\n type: \"server_tool_call_result\",\n toolCallId: _isString(toolOutput.id) ? toolOutput.id : \"\",\n status: toolOutput.status === \"completed\" ? \"success\" : \"error\",\n output,\n };\n }\n return;\n }\n if (_isContentBlock(toolOutput, \"file_search_call\")) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"file_search\",\n args: {\n queries: _isArray(toolOutput.queries) ? toolOutput.queries : [],\n },\n };\n // Emit a server_tool_call_result when results are available\n if (toolOutput.status === \"completed\" || toolOutput.status === \"failed\") {\n yield {\n type: \"server_tool_call_result\",\n toolCallId: _isString(toolOutput.id) ? toolOutput.id : \"\",\n status: toolOutput.status === \"completed\" ? \"success\" : \"error\",\n output: _isArray(toolOutput.results)\n ? { results: toolOutput.results }\n : {},\n };\n }\n return;\n }\n if (_isContentBlock(toolOutput, \"computer_call\")) {\n yield { type: \"non_standard\", value: toolOutput };\n return;\n }\n if (_isContentBlock(toolOutput, \"code_interpreter_call\")) {\n if (_isString(toolOutput.code)) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"code_interpreter\",\n args: { code: toolOutput.code },\n };\n }\n if (_isArray(toolOutput.outputs)) {\n const returnCode = iife(() => {\n if (toolOutput.status === \"in_progress\") return undefined;\n if (toolOutput.status === \"completed\") return 0;\n if (toolOutput.status === \"incomplete\") return 127;\n if (toolOutput.status === \"interpreting\") return undefined;\n if (toolOutput.status === \"failed\") return 1;\n return undefined;\n });\n for (const output of toolOutput.outputs) {\n if (_isContentBlock(output, \"logs\")) {\n yield {\n type: \"server_tool_call_result\",\n toolCallId: toolOutput.id ?? \"\",\n status: \"success\",\n output: {\n type: \"code_interpreter_output\",\n returnCode: returnCode ?? 0,\n stderr: [0, undefined].includes(returnCode)\n ? undefined\n : String(output.logs),\n stdout: [0, undefined].includes(returnCode)\n ? String(output.logs)\n : undefined,\n },\n };\n }\n }\n }\n return;\n }\n if (_isContentBlock(toolOutput, \"mcp_call\")) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"mcp_call\",\n args: toolOutput.input,\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"mcp_list_tools\")) {\n yield {\n id: toolOutput.id,\n type: \"server_tool_call\",\n name: \"mcp_list_tools\",\n args: toolOutput.input,\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"mcp_approval_request\")) {\n yield { type: \"non_standard\", value: toolOutput };\n return;\n }\n if (_isContentBlock(toolOutput, \"tool_search_call\")) {\n const toolSearchArgs: Record<string, unknown> = {};\n if (_isObject(toolOutput.arguments)) {\n Object.assign(toolSearchArgs, toolOutput.arguments);\n }\n const toolSearchCallExtras: Record<string, unknown> = {};\n if (_isString(toolOutput.execution)) {\n toolSearchCallExtras.execution = toolOutput.execution;\n }\n if (_isString(toolOutput.status)) {\n toolSearchCallExtras.status = toolOutput.status;\n }\n if (_isString(toolOutput.call_id)) {\n toolSearchCallExtras.call_id = toolOutput.call_id;\n }\n yield {\n id: _isString(toolOutput.id) ? toolOutput.id : \"\",\n type: \"server_tool_call\",\n name: \"tool_search\",\n args: toolSearchArgs,\n ...(Object.keys(toolSearchCallExtras).length > 0\n ? { extras: toolSearchCallExtras }\n : {}),\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"tool_search_output\")) {\n const toolSearchOutputExtras: Record<string, unknown> = {\n name: \"tool_search\",\n };\n if (_isString(toolOutput.execution)) {\n toolSearchOutputExtras.execution = toolOutput.execution;\n }\n yield {\n type: \"server_tool_call_result\",\n toolCallId: _isString(toolOutput.id) ? toolOutput.id : \"\",\n status:\n toolOutput.status === \"completed\"\n ? \"success\"\n : toolOutput.status === \"failed\"\n ? \"error\"\n : \"success\",\n output: {\n tools: _isArray(toolOutput.tools) ? toolOutput.tools : [],\n },\n extras: toolSearchOutputExtras,\n };\n return;\n }\n if (_isContentBlock(toolOutput, \"image_generation_call\")) {\n // Convert image_generation_call to proper image content block if result is available\n if (_isString(toolOutput.result)) {\n yield {\n type: \"image\",\n mimeType: \"image/png\",\n data: toolOutput.result,\n id: _isString(toolOutput.id) ? toolOutput.id : undefined,\n metadata: {\n status: _isString(toolOutput.status) ? toolOutput.status : undefined,\n },\n };\n }\n // Also yield as non_standard for backwards compatibility\n yield { type: \"non_standard\", value: toolOutput };\n return;\n }\n if (_isObject(toolOutput)) {\n yield { type: \"non_standard\", value: toolOutput };\n }\n}\n\n/**\n * Converts a ChatOpenAIResponses message to an array of v1 standard content blocks.\n *\n * This function processes an AI message containing OpenAI Responses-specific content blocks\n * and converts them to the standardized v1 content block format. It handles reasoning summaries,\n * text content with annotations, tool calls, and various tool outputs including code interpreter,\n * web search, file search, computer calls, and MCP-related blocks.\n *\n * A response can hold more than one reasoning item (e.g. multiple tool calls\n * in one turn, common on GPT-5.6-class models). When `response_metadata.output`\n * is available, each item's own `id`/`encrypted_content` is preserved and\n * blocks are sorted back into original order, so replay under Zero Data\n * Retention interleaves reasoning and tool calls correctly. Without it (e.g.\n * a hand-built message), falls back to a single reasoning block from\n * `additional_kwargs.reasoning`, as before.\n *\n * @param message - The AI message containing OpenAI Responses-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage({\n * content: [{ type: \"text\", text: \"Hello world\", annotations: [] }],\n * tool_calls: [{ id: \"123\", name: \"calculator\", args: { a: 1, b: 2 } }],\n * additional_kwargs: {\n * reasoning: { summary: [{ text: \"Let me calculate this...\" }] },\n * tool_outputs: [\n * {\n * type: \"code_interpreter_call\",\n * code: \"print('hello')\",\n * outputs: [{ type: \"logs\", logs: \"hello\" }]\n * }\n * ]\n * }\n * });\n *\n * const standardBlocks = convertToV1FromResponses(message);\n * // Returns:\n * // [\n * // { type: \"reasoning\", reasoning: \"Let me calculate this...\" },\n * // { type: \"text\", text: \"Hello world\", annotations: [] },\n * // { type: \"tool_call\", id: \"123\", name: \"calculator\", args: { a: 1, b: 2 } },\n * // { type: \"server_tool_call\", name: \"code_interpreter\", args: { code: \"print('hello')\" } },\n * // { type: \"server_tool_call_result\", toolCallId: \"\", status: \"success\", output: { type: \"code_interpreter_output\", returnCode: 0, stdout: \"hello\" } }\n * // ]\n * ```\n */\nexport function convertToV1FromResponses(\n message: AIMessage\n): Array<ContentBlock.Standard> {\n const rawOutput = message.response_metadata?.output;\n const hasRawOutput = _isArray(rawOutput) && rawOutput.length > 0;\n\n // Maps a per-item key (namespaced by type, since ids aren't globally unique) to its original response.output position.\n const positionByKey = new Map<string, number>();\n let messageItemCount = 0;\n let onlyMessageItemIndex: number | undefined;\n if (hasRawOutput) {\n (rawOutput as unknown[]).forEach((rawItem, index) => {\n if (!_isObject(rawItem) || !_isString(rawItem.type)) return;\n if (rawItem.type === \"reasoning\" && _isString(rawItem.id)) {\n positionByKey.set(`reasoning:${rawItem.id}`, index);\n } else if (\n // These three types all become tool_call blocks keyed by call_id.\n (rawItem.type === \"function_call\" ||\n rawItem.type === \"custom_tool_call\" ||\n rawItem.type === \"computer_call\") &&\n _isString(rawItem.call_id)\n ) {\n positionByKey.set(`tool_call:${rawItem.call_id}`, index);\n } else if (rawItem.type === \"message\") {\n messageItemCount += 1;\n onlyMessageItemIndex = index;\n } else if (_isString(rawItem.id)) {\n positionByKey.set(`other:${rawItem.type}:${rawItem.id}`, index);\n }\n });\n }\n // Text isn't keyed to a specific \"message\" item, so only position it when exactly one exists (an unambiguous match).\n const textBlockKey =\n messageItemCount === 1 && onlyMessageItemIndex != null\n ? `message:${onlyMessageItemIndex}`\n : undefined;\n if (textBlockKey != null) {\n positionByKey.set(textBlockKey, onlyMessageItemIndex as number);\n }\n\n function* iterateContent(): Iterable<\n [block: ContentBlock.Standard, key: string | undefined]\n > {\n if (hasRawOutput) {\n for (const rawItem of rawOutput as unknown[]) {\n if (_isObject(rawItem) && rawItem.type === \"reasoning\") {\n const block = mapReasoningItemToV1(rawItem);\n if (block) {\n yield [\n block,\n _isString(rawItem.id) ? `reasoning:${rawItem.id}` : undefined,\n ];\n }\n }\n }\n } else if (\n _isObject(message.additional_kwargs?.reasoning) &&\n _isArray(message.additional_kwargs.reasoning.summary)\n ) {\n const block = mapReasoningItemToV1(message.additional_kwargs.reasoning);\n if (block) yield [block, undefined];\n }\n\n const content =\n typeof message.content === \"string\"\n ? [{ type: \"text\", text: message.content }]\n : message.content;\n for (const block of content) {\n if (_isContentBlock(block, \"text\")) {\n const {\n text,\n annotations,\n phase,\n extras: existingExtras,\n ...rest\n } = block;\n const extras: Record<string, unknown> = _isObject(existingExtras)\n ? { ...(existingExtras as Record<string, unknown>) }\n : {};\n if (_isString(phase)) {\n extras.phase = phase;\n }\n const extrasSpread = Object.keys(extras).length > 0 ? { extras } : {};\n yield [\n {\n ...rest,\n ...extrasSpread,\n type: \"text\",\n text: String(text),\n ...(Array.isArray(annotations)\n ? { annotations: annotations.map(convertResponsesAnnotation) }\n : {}),\n },\n textBlockKey,\n ];\n }\n }\n let hasRefusalPart = false;\n for (const block of content) {\n if (_isContentBlock(block, \"refusal\") && _isString(block.refusal)) {\n hasRefusalPart = true;\n yield [\n {\n type: \"refusal\",\n refusal: block.refusal,\n ...(_isString(block.id) ? { id: block.id } : {}),\n },\n textBlockKey,\n ];\n }\n }\n if (!hasRefusalPart) {\n const refusal = refusalFromAdditionalKwargs(message);\n if (refusal) yield [refusal, textBlockKey];\n }\n for (const toolCall of message.tool_calls ?? []) {\n yield [\n {\n type: \"tool_call\",\n id: toolCall.id,\n name: toolCall.name,\n args: toolCall.args,\n },\n toolCall.id ? `tool_call:${toolCall.id}` : undefined,\n ];\n }\n if (\n _isObject(message.additional_kwargs) &&\n _isArray(message.additional_kwargs.tool_outputs)\n ) {\n for (const toolOutput of message.additional_kwargs.tool_outputs) {\n // All blocks from one tool output share this key -- fine since the API returns a call and its result as one item.\n const key =\n _isObject(toolOutput) &&\n _isString(toolOutput.type) &&\n _isString(toolOutput.id)\n ? `other:${toolOutput.type}:${toolOutput.id}`\n : undefined;\n for (const block of mapToolOutputToV1Blocks(toolOutput)) {\n yield [block, key];\n }\n }\n }\n }\n\n const withKeys = Array.from(iterateContent());\n if (!hasRawOutput) {\n return withKeys.map(([block]) => block);\n }\n // Stable sort by original position; unkeyed blocks sort last, in push order.\n return withKeys\n .map(([block, key], pushIndex) => ({\n block,\n pushIndex,\n position: key != null ? positionByKey.get(key) : undefined,\n }))\n .sort((a, b) => {\n const aPos = a.position ?? Number.POSITIVE_INFINITY;\n const bPos = b.position ?? Number.POSITIVE_INFINITY;\n if (aPos !== bPos) return aPos - bPos;\n return a.pushIndex - b.pushIndex;\n })\n .map((entry) => entry.block);\n}\n\n/**\n * Converts a ChatOpenAIResponses message chunk to an array of v1 standard content blocks.\n *\n * This function processes an AI message chunk containing OpenAI-specific content blocks\n * and converts them to the standardized v1 content block format. It handles both the\n * regular message content and tool call chunks that are specific to streaming responses.\n *\n * @param message - The AI message chunk containing OpenAI-formatted content blocks\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const messageChunk = new AIMessageChunk({\n * content: [{ type: \"text\", text: \"Hello\" }],\n * tool_call_chunks: [\n * { id: \"call_123\", name: \"calculator\", args: '{\"a\": 1' }\n * ]\n * });\n *\n * const standardBlocks = convertToV1FromResponsesChunk(messageChunk);\n * // Returns:\n * // [\n * // { type: \"text\", text: \"Hello\" },\n * // { type: \"tool_call_chunk\", id: \"call_123\", name: \"calculator\", args: '{\"a\": 1' }\n * // ]\n * ```\n */\nexport function convertToV1FromResponsesChunk(\n message: AIMessageChunk\n): Array<ContentBlock.Standard> {\n function* iterateContent(): Iterable<ContentBlock.Standard> {\n yield* convertToV1FromResponses(message);\n for (const toolCallChunk of message.tool_call_chunks ?? []) {\n yield {\n type: \"tool_call_chunk\",\n id: toolCallChunk.id,\n name: toolCallChunk.name,\n args: toolCallChunk.args,\n };\n }\n }\n return Array.from(iterateContent());\n}\n\nexport const ChatOpenAITranslator: StandardContentBlockTranslator = {\n translateContent: (message) => {\n if (typeof message.content === \"string\") {\n return convertToV1FromChatCompletions(message);\n }\n return convertToV1FromResponses(message);\n },\n translateContentChunk: (message) => {\n if (typeof message.content === \"string\") {\n return convertToV1FromChatCompletionsChunk(message);\n }\n return convertToV1FromResponsesChunk(message);\n },\n};\n"],"mappings":";;;;AAaA,SAAS,4BACP,SACkC;CAClC,MAAM,UAAU,QAAQ,kBAAkB;CAC1C,OAAOA,cAAAA,UAAU,OAAO,KAAK,QAAQ,SAAS,IAC1C;EAAE,MAAM;EAAW;CAAQ,IAC3B,KAAA;AACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,+BACd,SAC8B;CAC9B,MAAM,SAAuC,CAAC;CAC9C,IAAI,OAAO,QAAQ,YAAY,UAEzB;MAAA,QAAQ,QAAQ,SAAS,GAC3B,OAAO,KAAK;GACV,MAAM;GACN,MAAM,QAAQ;EAChB,CAAC;CAAA,OAGH,OAAO,KAAK,GAAG,oCAAoC,QAAQ,OAAO,CAAC;CAErE,KAAK,MAAM,YAAY,QAAQ,cAAc,CAAC,GAC5C,OAAO,KAAK;EACV,MAAM;EACN,IAAI,SAAS;EACb,MAAM,SAAS;EACf,MAAM,SAAS;CACjB,CAAC;CAEH,MAAM,UAAU,4BAA4B,OAAO;CACnD,IAAI,SAAS,OAAO,KAAK,OAAO;CAChC,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,oCACd,SAC8B;CAC9B,MAAM,SAAuC,CAAC;CAC9C,IAAI,OAAO,QAAQ,YAAY,UAEzB;MAAA,QAAQ,QAAQ,SAAS,GAC3B,OAAO,KAAK;GACV,MAAM;GACN,MAAM,QAAQ;EAChB,CAAC;CAAA,OAGH,OAAO,KAAK,GAAG,oCAAoC,QAAQ,OAAO,CAAC;CAIrE,KAAK,MAAM,YAAY,QAAQ,cAAc,CAAC,GAC5C,OAAO,KAAK;EACV,MAAM;EACN,IAAI,SAAS;EACb,MAAM,SAAS;EACf,MAAM,SAAS;CACjB,CAAC;CAEH,MAAM,UAAU,4BAA4B,OAAO;CACnD,IAAI,SAAS,OAAO,KAAK,OAAO;CAChC,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,oCACd,QAC8B;CAC9B,MAAM,kBAAgD,CAAC;CACvD,KAAK,MAAM,SAAS,QAClB,IAAIC,aAAAA,kBAAkB,KAAK,GACzB,gBAAgB,KAAKC,aAAAA,+BAA+B,KAAK,CAAC;MAE1D,gBAAgB,KAAK,KAA8B;CAGvD,OAAO;AACT;AAEA,SAAS,2BACP,YACsC;CACtC,IAAI,WAAW,SAAS,gBAAgB;EACtC,MAAM,EAAE,KAAK,OAAO,aAAa,cAAc;EAC/C,OAAO;GACL,MAAM;GACN;GACA;GACA,YAAY;GACZ,UAAU;EACZ;CACF;CACA,IAAI,WAAW,SAAS,iBAAiB;EACvC,MAAM,EAAE,SAAS,UAAU,UAAU;EACrC,OAAO;GACL,MAAM;GACN,OAAO;GACP,YAAY;GACZ,UAAU;GACV,QAAQ;EACV;CACF;CACA,OAAO;AACT;;AAGA,SAAS,qBACP,MACmC;CACnC,IAAI,CAACC,cAAAA,SAAS,KAAK,OAAO,GAAG,OAAO,KAAA;CAOpC,OAAO;EACL,MAAM;EACN,WARc,KAAK,QAAQ,QAAgB,KAAK,SAAS;GACzD,IAAIC,cAAAA,UAAU,IAAI,KAAKJ,cAAAA,UAAU,KAAK,IAAI,GACxC,OAAO,GAAG,MAAM,KAAK;GAEvB,OAAO;EACT,GAAG,EAGgB;EACjB,GAAIA,cAAAA,UAAU,KAAK,EAAE,IAAI,EAAE,IAAI,KAAK,GAAG,IAAI,CAAC;EAC5C,GAAIA,cAAAA,UAAU,KAAK,iBAAiB,IAChC,EAAE,mBAAmB,KAAK,kBAAkB,IAC5C,CAAC;CACP;AACF;AAGA,UAAU,wBACR,YACiC;CACjC,IAAIK,cAAAA,gBAAgB,YAAY,iBAAiB,GAAG;EAClD,MAAM,gBAAyC,CAAC;EAChD,IAAID,cAAAA,UAAU,WAAW,MAAM,KAAKJ,cAAAA,UAAU,WAAW,OAAO,KAAK,GACnE,cAAc,QAAQ,WAAW,OAAO;EAE1C,MAAM;GACJ,IAAI,WAAW;GACf,MAAM;GACN,MAAM;GACN,MAAM;EACR;EAEA,IAAI,WAAW,WAAW,eAAe,WAAW,WAAW,UAAU;GACvE,MAAM,SAAkC,CAAC;GACzC,IAAII,cAAAA,UAAU,WAAW,MAAM,GAC7B,OAAO,SAAS,WAAW;GAE7B,MAAM;IACJ,MAAM;IACN,YAAYJ,cAAAA,UAAU,WAAW,EAAE,IAAI,WAAW,KAAK;IACvD,QAAQ,WAAW,WAAW,cAAc,YAAY;IACxD;GACF;EACF;EACA;CACF;CACA,IAAIK,cAAAA,gBAAgB,YAAY,kBAAkB,GAAG;EACnD,MAAM;GACJ,IAAI,WAAW;GACf,MAAM;GACN,MAAM;GACN,MAAM,EACJ,SAASF,cAAAA,SAAS,WAAW,OAAO,IAAI,WAAW,UAAU,CAAC,EAChE;EACF;EAEA,IAAI,WAAW,WAAW,eAAe,WAAW,WAAW,UAC7D,MAAM;GACJ,MAAM;GACN,YAAYH,cAAAA,UAAU,WAAW,EAAE,IAAI,WAAW,KAAK;GACvD,QAAQ,WAAW,WAAW,cAAc,YAAY;GACxD,QAAQG,cAAAA,SAAS,WAAW,OAAO,IAC/B,EAAE,SAAS,WAAW,QAAQ,IAC9B,CAAC;EACP;EAEF;CACF;CACA,IAAIE,cAAAA,gBAAgB,YAAY,eAAe,GAAG;EAChD,MAAM;GAAE,MAAM;GAAgB,OAAO;EAAW;EAChD;CACF;CACA,IAAIA,cAAAA,gBAAgB,YAAY,uBAAuB,GAAG;EACxD,IAAIL,cAAAA,UAAU,WAAW,IAAI,GAC3B,MAAM;GACJ,IAAI,WAAW;GACf,MAAM;GACN,MAAM;GACN,MAAM,EAAE,MAAM,WAAW,KAAK;EAChC;EAEF,IAAIG,cAAAA,SAAS,WAAW,OAAO,GAAG;GAChC,MAAM,aAAaG,cAAAA,WAAW;IAC5B,IAAI,WAAW,WAAW,eAAe,OAAO,KAAA;IAChD,IAAI,WAAW,WAAW,aAAa,OAAO;IAC9C,IAAI,WAAW,WAAW,cAAc,OAAO;IAC/C,IAAI,WAAW,WAAW,gBAAgB,OAAO,KAAA;IACjD,IAAI,WAAW,WAAW,UAAU,OAAO;GAE7C,CAAC;GACD,KAAK,MAAM,UAAU,WAAW,SAC9B,IAAID,cAAAA,gBAAgB,QAAQ,MAAM,GAChC,MAAM;IACJ,MAAM;IACN,YAAY,WAAW,MAAM;IAC7B,QAAQ;IACR,QAAQ;KACN,MAAM;KACN,YAAY,cAAc;KAC1B,QAAQ,CAAC,GAAG,KAAA,CAAS,CAAC,CAAC,SAAS,UAAU,IACtC,KAAA,IACA,OAAO,OAAO,IAAI;KACtB,QAAQ,CAAC,GAAG,KAAA,CAAS,CAAC,CAAC,SAAS,UAAU,IACtC,OAAO,OAAO,IAAI,IAClB,KAAA;IACN;GACF;EAGN;EACA;CACF;CACA,IAAIA,cAAAA,gBAAgB,YAAY,UAAU,GAAG;EAC3C,MAAM;GACJ,IAAI,WAAW;GACf,MAAM;GACN,MAAM;GACN,MAAM,WAAW;EACnB;EACA;CACF;CACA,IAAIA,cAAAA,gBAAgB,YAAY,gBAAgB,GAAG;EACjD,MAAM;GACJ,IAAI,WAAW;GACf,MAAM;GACN,MAAM;GACN,MAAM,WAAW;EACnB;EACA;CACF;CACA,IAAIA,cAAAA,gBAAgB,YAAY,sBAAsB,GAAG;EACvD,MAAM;GAAE,MAAM;GAAgB,OAAO;EAAW;EAChD;CACF;CACA,IAAIA,cAAAA,gBAAgB,YAAY,kBAAkB,GAAG;EACnD,MAAM,iBAA0C,CAAC;EACjD,IAAID,cAAAA,UAAU,WAAW,SAAS,GAChC,OAAO,OAAO,gBAAgB,WAAW,SAAS;EAEpD,MAAM,uBAAgD,CAAC;EACvD,IAAIJ,cAAAA,UAAU,WAAW,SAAS,GAChC,qBAAqB,YAAY,WAAW;EAE9C,IAAIA,cAAAA,UAAU,WAAW,MAAM,GAC7B,qBAAqB,SAAS,WAAW;EAE3C,IAAIA,cAAAA,UAAU,WAAW,OAAO,GAC9B,qBAAqB,UAAU,WAAW;EAE5C,MAAM;GACJ,IAAIA,cAAAA,UAAU,WAAW,EAAE,IAAI,WAAW,KAAK;GAC/C,MAAM;GACN,MAAM;GACN,MAAM;GACN,GAAI,OAAO,KAAK,oBAAoB,CAAC,CAAC,SAAS,IAC3C,EAAE,QAAQ,qBAAqB,IAC/B,CAAC;EACP;EACA;CACF;CACA,IAAIK,cAAAA,gBAAgB,YAAY,oBAAoB,GAAG;EACrD,MAAM,yBAAkD,EACtD,MAAM,cACR;EACA,IAAIL,cAAAA,UAAU,WAAW,SAAS,GAChC,uBAAuB,YAAY,WAAW;EAEhD,MAAM;GACJ,MAAM;GACN,YAAYA,cAAAA,UAAU,WAAW,EAAE,IAAI,WAAW,KAAK;GACvD,QACE,WAAW,WAAW,cAClB,YACA,WAAW,WAAW,WACpB,UACA;GACR,QAAQ,EACN,OAAOG,cAAAA,SAAS,WAAW,KAAK,IAAI,WAAW,QAAQ,CAAC,EAC1D;GACA,QAAQ;EACV;EACA;CACF;CACA,IAAIE,cAAAA,gBAAgB,YAAY,uBAAuB,GAAG;EAExD,IAAIL,cAAAA,UAAU,WAAW,MAAM,GAC7B,MAAM;GACJ,MAAM;GACN,UAAU;GACV,MAAM,WAAW;GACjB,IAAIA,cAAAA,UAAU,WAAW,EAAE,IAAI,WAAW,KAAK,KAAA;GAC/C,UAAU,EACR,QAAQA,cAAAA,UAAU,WAAW,MAAM,IAAI,WAAW,SAAS,KAAA,EAC7D;EACF;EAGF,MAAM;GAAE,MAAM;GAAgB,OAAO;EAAW;EAChD;CACF;CACA,IAAII,cAAAA,UAAU,UAAU,GACtB,MAAM;EAAE,MAAM;EAAgB,OAAO;CAAW;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiDA,SAAgB,yBACd,SAC8B;CAC9B,MAAM,YAAY,QAAQ,mBAAmB;CAC7C,MAAM,eAAeD,cAAAA,SAAS,SAAS,KAAK,UAAU,SAAS;CAG/D,MAAM,gCAAgB,IAAI,IAAoB;CAC9C,IAAI,mBAAmB;CACvB,IAAI;CACJ,IAAI,cACF,UAAyB,SAAS,SAAS,UAAU;EACnD,IAAI,CAACC,cAAAA,UAAU,OAAO,KAAK,CAACJ,cAAAA,UAAU,QAAQ,IAAI,GAAG;EACrD,IAAI,QAAQ,SAAS,eAAeA,cAAAA,UAAU,QAAQ,EAAE,GACtD,cAAc,IAAI,aAAa,QAAQ,MAAM,KAAK;OAC7C,KAEJ,QAAQ,SAAS,mBAChB,QAAQ,SAAS,sBACjB,QAAQ,SAAS,oBACnBA,cAAAA,UAAU,QAAQ,OAAO,GAEzB,cAAc,IAAI,aAAa,QAAQ,WAAW,KAAK;OAClD,IAAI,QAAQ,SAAS,WAAW;GACrC,oBAAoB;GACpB,uBAAuB;EACzB,OAAO,IAAIA,cAAAA,UAAU,QAAQ,EAAE,GAC7B,cAAc,IAAI,SAAS,QAAQ,KAAK,GAAG,QAAQ,MAAM,KAAK;CAElE,CAAC;CAGH,MAAM,eACJ,qBAAqB,KAAK,wBAAwB,OAC9C,WAAW,yBACX,KAAA;CACN,IAAI,gBAAgB,MAClB,cAAc,IAAI,cAAc,oBAA8B;CAGhE,UAAU,iBAER;EACA,IAAI,cACG;QAAA,MAAM,WAAW,WACpB,IAAII,cAAAA,UAAU,OAAO,KAAK,QAAQ,SAAS,aAAa;IACtD,MAAM,QAAQ,qBAAqB,OAAO;IAC1C,IAAI,OACF,MAAM,CACJ,OACAJ,cAAAA,UAAU,QAAQ,EAAE,IAAI,aAAa,QAAQ,OAAO,KAAA,CACtD;GAEJ;SAEG,IACLI,cAAAA,UAAU,QAAQ,mBAAmB,SAAS,KAC9CD,cAAAA,SAAS,QAAQ,kBAAkB,UAAU,OAAO,GACpD;GACA,MAAM,QAAQ,qBAAqB,QAAQ,kBAAkB,SAAS;GACtE,IAAI,OAAO,MAAM,CAAC,OAAO,KAAA,CAAS;EACpC;EAEA,MAAM,UACJ,OAAO,QAAQ,YAAY,WACvB,CAAC;GAAE,MAAM;GAAQ,MAAM,QAAQ;EAAQ,CAAC,IACxC,QAAQ;EACd,KAAK,MAAM,SAAS,SAClB,IAAIE,cAAAA,gBAAgB,OAAO,MAAM,GAAG;GAClC,MAAM,EACJ,MACA,aACA,OACA,QAAQ,gBACR,GAAG,SACD;GACJ,MAAM,SAAkCD,cAAAA,UAAU,cAAc,IAC5D,EAAE,GAAI,eAA2C,IACjD,CAAC;GACL,IAAIJ,cAAAA,UAAU,KAAK,GACjB,OAAO,QAAQ;GAEjB,MAAM,eAAe,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,IAAI,EAAE,OAAO,IAAI,CAAC;GACpE,MAAM,CACJ;IACE,GAAG;IACH,GAAG;IACH,MAAM;IACN,MAAM,OAAO,IAAI;IACjB,GAAI,MAAM,QAAQ,WAAW,IACzB,EAAE,aAAa,YAAY,IAAI,0BAA0B,EAAE,IAC3D,CAAC;GACP,GACA,YACF;EACF;EAEF,IAAI,iBAAiB;EACrB,KAAK,MAAM,SAAS,SAClB,IAAIK,cAAAA,gBAAgB,OAAO,SAAS,KAAKL,cAAAA,UAAU,MAAM,OAAO,GAAG;GACjE,iBAAiB;GACjB,MAAM,CACJ;IACE,MAAM;IACN,SAAS,MAAM;IACf,GAAIA,cAAAA,UAAU,MAAM,EAAE,IAAI,EAAE,IAAI,MAAM,GAAG,IAAI,CAAC;GAChD,GACA,YACF;EACF;EAEF,IAAI,CAAC,gBAAgB;GACnB,MAAM,UAAU,4BAA4B,OAAO;GACnD,IAAI,SAAS,MAAM,CAAC,SAAS,YAAY;EAC3C;EACA,KAAK,MAAM,YAAY,QAAQ,cAAc,CAAC,GAC5C,MAAM,CACJ;GACE,MAAM;GACN,IAAI,SAAS;GACb,MAAM,SAAS;GACf,MAAM,SAAS;EACjB,GACA,SAAS,KAAK,aAAa,SAAS,OAAO,KAAA,CAC7C;EAEF,IACEI,cAAAA,UAAU,QAAQ,iBAAiB,KACnCD,cAAAA,SAAS,QAAQ,kBAAkB,YAAY,GAE/C,KAAK,MAAM,cAAc,QAAQ,kBAAkB,cAAc;GAE/D,MAAM,MACJC,cAAAA,UAAU,UAAU,KACpBJ,cAAAA,UAAU,WAAW,IAAI,KACzBA,cAAAA,UAAU,WAAW,EAAE,IACnB,SAAS,WAAW,KAAK,GAAG,WAAW,OACvC,KAAA;GACN,KAAK,MAAM,SAAS,wBAAwB,UAAU,GACpD,MAAM,CAAC,OAAO,GAAG;EAErB;CAEJ;CAEA,MAAM,WAAW,MAAM,KAAK,eAAe,CAAC;CAC5C,IAAI,CAAC,cACH,OAAO,SAAS,KAAK,CAAC,WAAW,KAAK;CAGxC,OAAO,SACJ,KAAK,CAAC,OAAO,MAAM,eAAe;EACjC;EACA;EACA,UAAU,OAAO,OAAO,cAAc,IAAI,GAAG,IAAI,KAAA;CACnD,EAAE,CAAC,CACF,MAAM,GAAG,MAAM;EACd,MAAM,OAAO,EAAE,YAAY,OAAO;EAClC,MAAM,OAAO,EAAE,YAAY,OAAO;EAClC,IAAI,SAAS,MAAM,OAAO,OAAO;EACjC,OAAO,EAAE,YAAY,EAAE;CACzB,CAAC,CAAC,CACD,KAAK,UAAU,MAAM,KAAK;AAC/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6BA,SAAgB,8BACd,SAC8B;CAC9B,UAAU,iBAAkD;EAC1D,OAAO,yBAAyB,OAAO;EACvC,KAAK,MAAM,iBAAiB,QAAQ,oBAAoB,CAAC,GACvD,MAAM;GACJ,MAAM;GACN,IAAI,cAAc;GAClB,MAAM,cAAc;GACpB,MAAM,cAAc;EACtB;CAEJ;CACA,OAAO,MAAM,KAAK,eAAe,CAAC;AACpC;AAEA,MAAa,uBAAuD;CAClE,mBAAmB,YAAY;EAC7B,IAAI,OAAO,QAAQ,YAAY,UAC7B,OAAO,+BAA+B,OAAO;EAE/C,OAAO,yBAAyB,OAAO;CACzC;CACA,wBAAwB,YAAY;EAClC,IAAI,OAAO,QAAQ,YAAY,UAC7B,OAAO,oCAAoC,OAAO;EAEpD,OAAO,8BAA8B,OAAO;CAC9C;AACF"}
@@ -1,6 +1,14 @@
1
1
  import { convertToV1FromOpenAIDataBlock, isOpenAIDataBlock } from "./data.js";
2
2
  import { _isArray, _isContentBlock, _isObject, _isString, iife } from "./utils.js";
3
3
  // src/messages/block_translators/openai.ts
4
+ /** The refusal Chat Completions and Responses keep in `additional_kwargs`. */
5
+ function refusalFromAdditionalKwargs(message) {
6
+ const refusal = message.additional_kwargs.refusal;
7
+ return _isString(refusal) && refusal.length > 0 ? {
8
+ type: "refusal",
9
+ refusal
10
+ } : void 0;
11
+ }
4
12
  /**
5
13
  * Converts a ChatOpenAICompletions message to an array of v1 standard content blocks.
6
14
  *
@@ -51,6 +59,8 @@ function convertToV1FromChatCompletions(message) {
51
59
  name: toolCall.name,
52
60
  args: toolCall.args
53
61
  });
62
+ const refusal = refusalFromAdditionalKwargs(message);
63
+ if (refusal) blocks.push(refusal);
54
64
  return blocks;
55
65
  }
56
66
  /**
@@ -101,6 +111,8 @@ function convertToV1FromChatCompletionsChunk(message) {
101
111
  name: toolCall.name,
102
112
  args: toolCall.args
103
113
  });
114
+ const refusal = refusalFromAdditionalKwargs(message);
115
+ if (refusal) blocks.push(refusal);
104
116
  return blocks;
105
117
  }
106
118
  /**
@@ -407,6 +419,19 @@ function convertToV1FromResponses(message) {
407
419
  ...Array.isArray(annotations) ? { annotations: annotations.map(convertResponsesAnnotation) } : {}
408
420
  }, textBlockKey];
409
421
  }
422
+ let hasRefusalPart = false;
423
+ for (const block of content) if (_isContentBlock(block, "refusal") && _isString(block.refusal)) {
424
+ hasRefusalPart = true;
425
+ yield [{
426
+ type: "refusal",
427
+ refusal: block.refusal,
428
+ ..._isString(block.id) ? { id: block.id } : {}
429
+ }, textBlockKey];
430
+ }
431
+ if (!hasRefusalPart) {
432
+ const refusal = refusalFromAdditionalKwargs(message);
433
+ if (refusal) yield [refusal, textBlockKey];
434
+ }
410
435
  for (const toolCall of message.tool_calls ?? []) yield [{
411
436
  type: "tool_call",
412
437
  id: toolCall.id,