{"version":3,"file":"openai.cjs","names":["message: AIMessage","blocks: Array<ContentBlock.Standard>","blocks: Array<ContentBlock>","convertedBlocks: Array<ContentBlock.Standard>","isOpenAIDataBlock","convertToV1FromOpenAIDataBlock","annotation: ContentBlock","_isObject","_isArray","_isString","_isContentBlock","iife","message: AIMessageChunk","ChatOpenAITranslator: StandardContentBlockTranslator"],"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    blocks.push({\n      type: \"text\",\n      text: message.content,\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    blocks.push({\n      type: \"text\",\n      text: message.content,\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/**\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 * @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: \"code_interpreter_call\", code: \"print('hello')\" },\n * //   { type: \"code_interpreter_result\", output: [{ type: \"code_interpreter_output\", returnCode: 0, stdout: \"hello\" }] }\n * // ]\n * ```\n */\nexport function convertToV1FromResponses(\n  message: AIMessage\n): Array<ContentBlock.Standard> {\n  function* iterateContent(): Iterable<ContentBlock.Standard> {\n    if (\n      _isObject(message.additional_kwargs?.reasoning) &&\n      _isArray(message.additional_kwargs.reasoning.summary)\n    ) {\n      const summary =\n        message.additional_kwargs.reasoning.summary.reduce<string>(\n          (acc, item) => {\n            if (_isObject(item) && _isString(item.text)) {\n              return `${acc}${item.text}`;\n            }\n            return acc;\n          },\n          \"\"\n        );\n      yield {\n        type: \"reasoning\",\n        reasoning: summary,\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 { text, annotations, ...rest } = block;\n        if (Array.isArray(annotations)) {\n          yield {\n            ...rest,\n            type: \"text\",\n            text: String(text),\n            annotations: annotations.map(convertResponsesAnnotation),\n          };\n        } else {\n          yield {\n            ...rest,\n            type: \"text\",\n            text: String(text),\n          };\n        }\n      }\n    }\n    for (const toolCall of message.tool_calls ?? []) {\n      yield {\n        type: \"tool_call\",\n        id: toolCall.id,\n        name: toolCall.name,\n        args: toolCall.args,\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        if (_isContentBlock(toolOutput, \"web_search_call\")) {\n          yield {\n            id: toolOutput.id,\n            type: \"server_tool_call\",\n            name: \"web_search\",\n            args: { query: toolOutput.query },\n          };\n          continue;\n        } else if (_isContentBlock(toolOutput, \"file_search_call\")) {\n          yield {\n            id: toolOutput.id,\n            type: \"server_tool_call\",\n            name: \"file_search\",\n            args: { query: toolOutput.query },\n          };\n          continue;\n        } else if (_isContentBlock(toolOutput, \"computer_call\")) {\n          yield { type: \"non_standard\", value: toolOutput };\n          continue;\n        } else 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                continue;\n              }\n            }\n          }\n          continue;\n        } else 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          continue;\n        } else 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          continue;\n        } else if (_isContentBlock(toolOutput, \"mcp_approval_request\")) {\n          yield { type: \"non_standard\", value: toolOutput };\n          continue;\n        } else if (_isContentBlock(toolOutput, \"image_generation_call\")) {\n          yield { type: \"non_standard\", value: toolOutput };\n          continue;\n        }\n        if (_isObject(toolOutput)) {\n          yield { type: \"non_standard\", value: toolOutput };\n        }\n      }\n    }\n  }\n  return Array.from(iterateContent());\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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"}