{"version":3,"file":"openrouter.cjs","names":["_isString"],"sources":["../../../src/messages/block_translators/openrouter.ts"],"sourcesContent":["import { AIMessage } from \"../ai.js\";\nimport { ContentBlock } from \"../content/index.js\";\nimport type { StandardContentBlockTranslator } from \"./index.js\";\nimport { _isString } from \"./utils.js\";\n\n/**\n * Converts an OpenRouter AI message to an array of v1 standard content blocks.\n *\n * OpenRouter returns reasoning output through two places on the Chat\n * Completions response:\n *\n * 1. `message.reasoning` / `delta.reasoning` — a flat string that summarizes\n *    the model's chain of thought. The `@langchain/openrouter` converter\n *    normalizes this into `additional_kwargs.reasoning_content` so it matches\n *    the DeepSeek convention already used elsewhere in LangChain.\n * 2. `message.reasoning_details` / `delta.reasoning_details` — a structured\n *    array of provider-specific reasoning artifacts (see the\n *    `reasoning.summary` / `reasoning.encrypted` / `reasoning.text` union in\n *    the OpenRouter API types). The converter preserves these verbatim under\n *    `additional_kwargs.reasoning_details` for round-tripping back to the\n *    provider on subsequent turns (e.g. Anthropic extended thinking requires\n *    the original `signature` to be echoed back).\n *\n * When `reasoning_details` is present, visible blocks are emitted from\n * `reasoning.summary` / `reasoning.text` entries. If the array contains only\n * opaque artifacts (e.g. `reasoning.encrypted`), the flat `reasoning_content`\n * string is used as a fallback when available.\n *\n * @param message - The AI message containing OpenRouter-formatted content\n * @returns Array of content blocks in v1 standard format\n *\n * @example\n * ```typescript\n * const message = new AIMessage({\n *   content: \"The answer is 42\",\n *   additional_kwargs: { reasoning_content: \"Let me think about this...\" },\n *   response_metadata: { model_provider: \"openrouter\" },\n * });\n * message.contentBlocks;\n * // [\n * //   { type: \"reasoning\", reasoning: \"Let me think about this...\" },\n * //   { type: \"text\", text: \"The answer is 42\" }\n * // ]\n * ```\n */\nexport function convertToV1FromOpenRouterMessage(\n  message: AIMessage\n): Array<ContentBlock.Standard> {\n  const blocks: Array<ContentBlock.Standard> = [];\n\n  // Prefer structured reasoning_details when present — they can carry\n  // multiple distinct reasoning artifacts (summary, encrypted, text).\n  const reasoningDetails = message.additional_kwargs?.reasoning_details;\n  let hasVisibleReasoningFromDetails = false;\n  if (Array.isArray(reasoningDetails) && reasoningDetails.length > 0) {\n    for (const detail of reasoningDetails) {\n      if (detail == null || typeof detail !== \"object\") continue;\n      const type = (detail as { type?: unknown }).type;\n      if (type === \"reasoning.summary\") {\n        const summary = (detail as { summary?: unknown }).summary;\n        if (_isString(summary) && summary.length > 0) {\n          blocks.push({ type: \"reasoning\", reasoning: summary });\n          hasVisibleReasoningFromDetails = true;\n        }\n      } else if (type === \"reasoning.text\") {\n        const text = (detail as { text?: unknown }).text;\n        if (_isString(text) && text.length > 0) {\n          blocks.push({ type: \"reasoning\", reasoning: text });\n          hasVisibleReasoningFromDetails = true;\n        }\n      }\n      // `reasoning.encrypted` details carry no human-readable text (only an\n      // opaque `data` blob that must be echoed back to the provider), so they\n      // do not become visible reasoning blocks. They stay in\n      // `additional_kwargs.reasoning_details` for round-tripping.\n    }\n  }\n\n  if (!hasVisibleReasoningFromDetails) {\n    const reasoningContent = message.additional_kwargs?.reasoning_content;\n    if (_isString(reasoningContent) && reasoningContent.length > 0) {\n      blocks.push({\n        type: \"reasoning\",\n        reasoning: reasoningContent,\n      });\n    }\n  }\n\n  // Handle text content (string or multi-block array).\n  if (typeof message.content === \"string\") {\n    if (message.content.length > 0) {\n      blocks.push({\n        type: \"text\",\n        text: message.content,\n      });\n    }\n  } else {\n    for (const block of message.content) {\n      if (\n        typeof block === \"object\" &&\n        \"type\" in block &&\n        block.type === \"text\" &&\n        \"text\" in block &&\n        _isString(block.text)\n      ) {\n        blocks.push({\n          type: \"text\",\n          text: block.text,\n        });\n      }\n    }\n  }\n\n  // Add tool calls if present.\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\n  return blocks;\n}\n\nexport const ChatOpenRouterTranslator: StandardContentBlockTranslator = {\n  translateContent: convertToV1FromOpenRouterMessage,\n  translateContentChunk: convertToV1FromOpenRouterMessage,\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,SAAgB,iCACd,SAC8B;CAC9B,MAAM,SAAuC,EAAE;CAI/C,MAAM,mBAAmB,QAAQ,mBAAmB;CACpD,IAAI,iCAAiC;AACrC,KAAI,MAAM,QAAQ,iBAAiB,IAAI,iBAAiB,SAAS,EAC/D,MAAK,MAAM,UAAU,kBAAkB;AACrC,MAAI,UAAU,QAAQ,OAAO,WAAW,SAAU;EAClD,MAAM,OAAQ,OAA8B;AAC5C,MAAI,SAAS,qBAAqB;GAChC,MAAM,UAAW,OAAiC;AAClD,OAAIA,cAAAA,UAAU,QAAQ,IAAI,QAAQ,SAAS,GAAG;AAC5C,WAAO,KAAK;KAAE,MAAM;KAAa,WAAW;KAAS,CAAC;AACtD,qCAAiC;;aAE1B,SAAS,kBAAkB;GACpC,MAAM,OAAQ,OAA8B;AAC5C,OAAIA,cAAAA,UAAU,KAAK,IAAI,KAAK,SAAS,GAAG;AACtC,WAAO,KAAK;KAAE,MAAM;KAAa,WAAW;KAAM,CAAC;AACnD,qCAAiC;;;;AAUzC,KAAI,CAAC,gCAAgC;EACnC,MAAM,mBAAmB,QAAQ,mBAAmB;AACpD,MAAIA,cAAAA,UAAU,iBAAiB,IAAI,iBAAiB,SAAS,EAC3D,QAAO,KAAK;GACV,MAAM;GACN,WAAW;GACZ,CAAC;;AAKN,KAAI,OAAO,QAAQ,YAAY;MACzB,QAAQ,QAAQ,SAAS,EAC3B,QAAO,KAAK;GACV,MAAM;GACN,MAAM,QAAQ;GACf,CAAC;OAGJ,MAAK,MAAM,SAAS,QAAQ,QAC1B,KACE,OAAO,UAAU,YACjB,UAAU,SACV,MAAM,SAAS,UACf,UAAU,SACVA,cAAAA,UAAU,MAAM,KAAK,CAErB,QAAO,KAAK;EACV,MAAM;EACN,MAAM,MAAM;EACb,CAAC;AAMR,MAAK,MAAM,YAAY,QAAQ,cAAc,EAAE,CAC7C,QAAO,KAAK;EACV,MAAM;EACN,IAAI,SAAS;EACb,MAAM,SAAS;EACf,MAAM,SAAS;EAChB,CAAC;AAGJ,QAAO;;AAGT,MAAa,2BAA2D;CACtE,kBAAkB;CAClB,uBAAuB;CACxB"}