@providerprotocol/ai 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anthropic/index.d.ts +1 -1
- package/dist/anthropic/index.js +38 -1
- package/dist/anthropic/index.js.map +1 -1
- package/dist/{chunk-6AZVUI6H.js → chunk-ILR2D5PN.js} +7 -1
- package/dist/chunk-ILR2D5PN.js.map +1 -0
- package/dist/{chunk-MKDLXV4O.js → chunk-NSE7QN3P.js} +1 -1
- package/dist/chunk-NSE7QN3P.js.map +1 -0
- package/dist/embedding-DtyOFIsS.d.ts +158 -0
- package/dist/google/index.d.ts +1 -1
- package/dist/google/index.js +41 -4
- package/dist/google/index.js.map +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/index.d.ts +430 -669
- package/dist/index.js +627 -3
- package/dist/index.js.map +1 -1
- package/dist/llm-DgDEy9il.d.ts +3118 -0
- package/dist/ollama/index.d.ts +1 -1
- package/dist/ollama/index.js +2 -1
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.js +70 -3
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +20 -2
- package/dist/openrouter/index.js +134 -13
- package/dist/openrouter/index.js.map +1 -1
- package/dist/proxy/index.d.ts +220 -3
- package/dist/proxy/index.js +817 -22
- package/dist/proxy/index.js.map +1 -1
- package/dist/{retry-DTfjXXPh.d.ts → retry-DXLQnTuU.d.ts} +1 -1
- package/dist/xai/index.d.ts +1 -1
- package/dist/xai/index.js +7 -3
- package/dist/xai/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6AZVUI6H.js.map +0 -1
- package/dist/chunk-MKDLXV4O.js.map +0 -1
- package/dist/provider-x4RocsnK.d.ts +0 -1474
- package/dist/stream-ITNFNnO4.d.ts +0 -1080
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/openrouter/transform.completions.ts","../../src/providers/openrouter/llm.completions.ts","../../src/providers/openrouter/transform.responses.ts","../../src/providers/openrouter/llm.responses.ts","../../src/providers/openrouter/embed.ts","../../src/providers/openrouter/index.ts"],"sourcesContent":["/**\n * Transform utilities for OpenRouter Chat Completions API.\n *\n * This module handles bidirectional conversion between UPP (Unified Provider Protocol)\n * request/response formats and OpenRouter's Chat Completions API format, which is\n * compatible with the OpenAI Chat Completions API.\n *\n * @module transform.completions\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock, AssistantContent, ReasoningBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n OpenRouterCompletionsParams,\n OpenRouterCompletionsRequest,\n OpenRouterCompletionsMessage,\n OpenRouterSystemContent,\n OpenRouterUserContent,\n OpenRouterCompletionsTool,\n OpenRouterCompletionsResponse,\n OpenRouterCompletionsStreamChunk,\n OpenRouterToolCall,\n OpenRouterCacheControl,\n OpenRouterReasoningDetail,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLMRequest into an OpenRouter Chat Completions API request body.\n *\n * Parameters are spread directly to enable pass-through of any OpenRouter API fields,\n * even those not explicitly defined in our types. This allows developers to use new\n * API features without waiting for library updates.\n *\n * @param request - The UPP LLM request containing messages, tools, and parameters\n * @param modelId - The OpenRouter model identifier (e.g., 'openai/gpt-4o')\n * @returns A fully formed OpenRouter Chat Completions request body\n */\nexport function transformRequest(\n request: LLMRequest<OpenRouterCompletionsParams>,\n modelId: string\n): OpenRouterCompletionsRequest {\n const params = request.params ?? ({} as OpenRouterCompletionsParams);\n\n const openrouterRequest: OpenRouterCompletionsRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n openrouterRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openrouterRequest.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openrouterRequest;\n}\n\n/**\n * Transforms UPP messages into OpenRouter Chat Completions message format.\n *\n * Handles system prompts, user messages, assistant messages, and tool results.\n * Tool result messages are expanded into individual tool messages.\n *\n * System prompts support both string and array formats:\n * - String: Simple text system prompt\n * - Array: Content blocks with optional cache_control for Anthropic/Gemini models\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array with cache_control)\n * @returns Array of OpenRouter-formatted messages\n */\nfunction transformMessages(\n messages: Message[],\n system?: string | unknown[]\n): OpenRouterCompletionsMessage[] {\n const result: OpenRouterCompletionsMessage[] = [];\n\n if (system !== undefined && system !== null) {\n const normalizedSystem = normalizeSystem(system);\n if (typeof normalizedSystem === 'string') {\n if (normalizedSystem.length > 0) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n } else if (normalizedSystem.length > 0) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n }\n\n for (const message of messages) {\n if (isToolResultMessage(message)) {\n const toolMessages = transformToolResults(message);\n result.push(...toolMessages);\n } else {\n const transformed = transformMessage(message);\n if (transformed) {\n result.push(transformed);\n }\n }\n }\n\n return result;\n}\n\nfunction normalizeSystem(system: string | unknown[]): string | OpenRouterSystemContent[] {\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const blocks: OpenRouterSystemContent[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object') {\n throw new UPPError(\n 'System prompt array must contain objects with type \"text\"',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n const candidate = block as { type?: unknown; text?: unknown; cache_control?: unknown };\n if (candidate.type !== 'text' || typeof candidate.text !== 'string') {\n throw new UPPError(\n 'OpenRouter system blocks must be of type \"text\" with a string text field',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n if (candidate.cache_control !== undefined && !isValidCacheControl(candidate.cache_control)) {\n throw new UPPError(\n 'Invalid cache_control for OpenRouter system prompt',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n blocks.push(block as OpenRouterSystemContent);\n }\n\n return blocks;\n}\n\nfunction isValidCacheControl(value: unknown): value is OpenRouterCacheControl {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as { type?: unknown; ttl?: unknown };\n if (candidate.type !== 'ephemeral') return false;\n if (candidate.ttl !== undefined && candidate.ttl !== '1h') return false;\n return true;\n}\n\n/**\n * Filters content blocks to only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with string type properties\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Extracts cache control configuration from message metadata.\n *\n * @param message - The message to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractCacheControl(message: Message): OpenRouterCacheControl | undefined {\n const openrouterMeta = message.metadata?.openrouter as\n | { cache_control?: OpenRouterCacheControl }\n | undefined;\n return openrouterMeta?.cache_control;\n}\n\n/**\n * Transforms a single UPP message to OpenRouter Chat Completions format.\n *\n * Cache control can be specified via message metadata:\n * ```typescript\n * new UserMessage(content, {\n * metadata: { openrouter: { cache_control: { type: \"ephemeral\" } } }\n * })\n * ```\n *\n * @param message - The UPP message to transform\n * @returns The transformed OpenRouter message, or null if the message type is unsupported\n */\nfunction transformMessage(message: Message): OpenRouterCompletionsMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n const cacheControl = extractCacheControl(message);\n\n // If cache_control is present, always use array format to attach it\n if (cacheControl) {\n const content = validContent.map(transformContentBlock);\n // Apply cache_control to the last text content block\n for (let i = content.length - 1; i >= 0; i--) {\n const block = content[i];\n if (block?.type === 'text') {\n content[i] = { type: 'text', text: block.text, cache_control: cacheControl };\n break;\n }\n }\n return { role: 'user', content };\n }\n\n // No cache_control: use string shortcut for single text block\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return {\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n };\n }\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n // Filter out reasoning blocks - they're preserved via reasoning_details in metadata\n const nonReasoningContent = validContent.filter(c => c.type !== 'reasoning');\n const textContent = nonReasoningContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n const assistantMessage: OpenRouterCompletionsMessage = {\n role: 'assistant',\n content: textContent || null,\n };\n\n if (message.toolCalls && message.toolCalls.length > 0) {\n (assistantMessage as { tool_calls?: OpenRouterToolCall[] }).tool_calls =\n message.toolCalls.map((call) => ({\n id: call.toolCallId,\n type: 'function' as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n },\n }));\n }\n\n // Forward reasoning_details from metadata for multi-turn context preservation\n const openrouterMeta = message.metadata?.openrouter as\n | { reasoning_details?: OpenRouterReasoningDetail[] }\n | undefined;\n if (openrouterMeta?.reasoning_details && openrouterMeta.reasoning_details.length > 0) {\n (assistantMessage as { reasoning_details?: OpenRouterReasoningDetail[] }).reasoning_details =\n openrouterMeta.reasoning_details;\n }\n\n return assistantMessage;\n }\n\n if (isToolResultMessage(message)) {\n const results = message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transforms a tool result message into multiple OpenRouter tool messages.\n *\n * Each tool result in the UPP ToolResultMessage becomes a separate OpenRouter\n * tool message with the corresponding tool_call_id.\n *\n * @param message - The UPP message (expected to be a ToolResultMessage)\n * @returns Array of OpenRouter tool messages\n */\nexport function transformToolResults(\n message: Message\n): OpenRouterCompletionsMessage[] {\n if (!isToolResultMessage(message)) {\n const single = transformMessage(message);\n return single ? [single] : [];\n }\n\n return message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n}\n\n/**\n * Transforms a UPP content block to OpenRouter user content format.\n *\n * Supports text and image content types. Images are converted to data URLs\n * or passed through as URL references.\n *\n * @param block - The UPP content block to transform\n * @returns OpenRouter user content part\n * @throws Error if the content type is unsupported\n */\nfunction transformContentBlock(block: ContentBlock): OpenRouterUserContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let url: string;\n\n if (imageBlock.source.type === 'base64') {\n url = `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`;\n } else if (imageBlock.source.type === 'url') {\n url = imageBlock.source.url;\n } else if (imageBlock.source.type === 'bytes') {\n // Convert bytes to base64\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n url = `data:${imageBlock.mimeType};base64,${base64}`;\n } else {\n throw new Error('Unknown image source type');\n }\n\n return {\n type: 'image_url',\n image_url: { url },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transforms a UPP Tool definition to OpenRouter function tool format.\n *\n * @param tool - The UPP tool definition\n * @returns OpenRouter function tool definition\n */\nfunction transformTool(tool: Tool): OpenRouterCompletionsTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n },\n };\n}\n\n/**\n * Transforms an OpenRouter Chat Completions API response to UPP LLMResponse format.\n *\n * Extracts text content, tool calls, usage statistics, and stop reason from\n * the OpenRouter response. Attempts to parse JSON content for structured output.\n *\n * @param data - The raw OpenRouter Chat Completions response\n * @returns UPP-formatted LLM response\n * @throws Error if no choices are present in the response\n */\nexport function transformResponse(data: OpenRouterCompletionsResponse): LLMResponse {\n const choice = data.choices[0];\n if (!choice) {\n throw new Error('No choices in OpenRouter response');\n }\n\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Extract reasoning from reasoning_details\n if (choice.message.reasoning_details && choice.message.reasoning_details.length > 0) {\n for (const detail of choice.message.reasoning_details) {\n if (detail.type === 'reasoning.text' && detail.text) {\n reasoningContent.push({ type: 'reasoning', text: detail.text });\n } else if (detail.type === 'reasoning.summary' && detail.summary) {\n reasoningContent.push({ type: 'reasoning', text: detail.summary });\n }\n // reasoning.encrypted blocks don't have displayable text\n }\n }\n\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n\n if (choice.message.images && choice.message.images.length > 0) {\n for (const image of choice.message.images) {\n const imageBlock = parseGeneratedImage(image.image_url.url);\n if (imageBlock) {\n textContent.push(imageBlock);\n }\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const toolCalls: ToolCall[] = [];\n if (choice.message.tool_calls) {\n for (const call of choice.message.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(call.function.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n toolCalls.push({\n toolCallId: call.id,\n toolName: call.function.name,\n arguments: args,\n });\n }\n }\n\n const responseId = data.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n openrouter: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\n // Store reasoning_details for multi-turn context preservation\n reasoning_details: choice.message.reasoning_details,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.prompt_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (choice.finish_reason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Parses a generated image data URL into an ImageBlock.\n *\n * @param dataUrl - The data URL from the image generation response\n * @returns An ImageBlock or null if parsing fails\n */\nfunction parseGeneratedImage(dataUrl: string): ImageBlock | null {\n const match = dataUrl.match(/^data:(image\\/[^;]+);base64,(.+)$/);\n if (!match) {\n return null;\n }\n const [, mimeType, data] = match;\n if (!mimeType || !data) {\n return null;\n }\n return {\n type: 'image',\n mimeType,\n source: { type: 'base64', data },\n };\n}\n\n/**\n * Mutable state object for accumulating streaming response data.\n *\n * Used during streaming to collect text deltas, tool call fragments,\n * and usage statistics before building the final LLMResponse.\n */\nexport interface CompletionsStreamState {\n /** Response ID from the first chunk */\n id: string;\n /** Model identifier from the response */\n model: string;\n /** Accumulated text content */\n text: string;\n /** Accumulated reasoning text from reasoning_details */\n reasoning: string;\n /** Raw reasoning_details for multi-turn context preservation */\n reasoningDetails: OpenRouterReasoningDetail[];\n /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n /** Generated image data URLs from image generation models */\n images: string[];\n /** Final finish reason from the stream */\n finishReason: string | null;\n /** Input token count from usage */\n inputTokens: number;\n /** Output token count from usage */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n}\n\n/**\n * Creates an empty stream state object for accumulating streaming data.\n *\n * @returns A new CompletionsStreamState with all fields initialized\n */\nexport function createStreamState(): CompletionsStreamState {\n return {\n id: '',\n model: '',\n text: '',\n reasoning: '',\n reasoningDetails: [],\n toolCalls: new Map(),\n images: [],\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n };\n}\n\n/**\n * Transforms an OpenRouter streaming chunk into UPP StreamEvents.\n *\n * Processes the chunk to extract text deltas, tool call updates, and finish signals.\n * Updates the provided state object with accumulated data. Returns an array because\n * a single chunk may produce multiple events (e.g., text delta and tool call delta).\n *\n * @param chunk - The OpenRouter streaming chunk to process\n * @param state - The mutable state object to update with chunk data\n * @returns Array of UPP StreamEvents generated from this chunk\n */\nexport function transformStreamEvent(\n chunk: OpenRouterCompletionsStreamChunk,\n state: CompletionsStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (chunk.id && !state.id) {\n state.id = chunk.id;\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n }\n if (chunk.model) {\n state.model = chunk.model;\n }\n\n const choice = chunk.choices[0];\n if (choice) {\n if (choice.delta.content) {\n state.text += choice.delta.content;\n events.push({\n type: StreamEventType.TextDelta,\n index: 0,\n delta: { text: choice.delta.content },\n });\n }\n\n if (choice.delta.tool_calls) {\n for (const toolCallDelta of choice.delta.tool_calls) {\n const index = toolCallDelta.index;\n let toolCall = state.toolCalls.get(index);\n\n if (!toolCall) {\n toolCall = { id: '', name: '', arguments: '' };\n state.toolCalls.set(index, toolCall);\n }\n\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: index,\n delta: {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n argumentsJson: toolCallDelta.function.arguments,\n },\n });\n }\n }\n }\n\n if (choice.delta.images) {\n for (const image of choice.delta.images) {\n state.images.push(image.image_url.url);\n }\n }\n\n // Handle reasoning_details in streaming\n if (choice.delta.reasoning_details) {\n for (const detail of choice.delta.reasoning_details) {\n state.reasoningDetails.push(detail);\n // Extract text for ReasoningDelta events\n if (detail.type === 'reasoning.text' && detail.text) {\n state.reasoning += detail.text;\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: detail.text },\n });\n } else if (detail.type === 'reasoning.summary' && detail.summary) {\n state.reasoning += detail.summary;\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: detail.summary },\n });\n }\n // reasoning.encrypted blocks don't have displayable text\n }\n }\n\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n }\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n state.cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;\n }\n\n return events;\n}\n\n/**\n * Builds the final LLMResponse from accumulated streaming state.\n *\n * Constructs the complete response after streaming has finished, including\n * the assistant message, tool calls, usage statistics, and stop reason.\n *\n * @param state - The accumulated stream state\n * @returns Complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: CompletionsStreamState): LLMResponse {\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Add reasoning content if present\n if (state.reasoning) {\n reasoningContent.push({ type: 'reasoning', text: state.reasoning });\n }\n\n if (state.text) {\n textContent.push({ type: 'text', text: state.text });\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n\n for (const imageUrl of state.images) {\n const imageBlock = parseGeneratedImage(imageUrl);\n if (imageBlock) {\n textContent.push(imageBlock);\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const toolCalls: ToolCall[] = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n }\n toolCalls.push({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n arguments: args,\n });\n }\n\n const messageId = state.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: messageId,\n metadata: {\n openrouter: {\n model: state.model,\n finish_reason: state.finishReason,\n // Store reasoning_details for multi-turn context preservation\n reasoning_details: state.reasoningDetails.length > 0 ? state.reasoningDetails : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (state.finishReason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * OpenRouter Chat Completions API LLM handler.\n *\n * This module implements the LLMHandler interface for OpenRouter's Chat Completions API,\n * which is compatible with the OpenAI Chat Completions API format.\n *\n * @module llm.completions\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type { OpenRouterCompletionsParams, OpenRouterCompletionsResponse, OpenRouterCompletionsStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.completions.ts';\n\n/** Base URL for OpenRouter's Chat Completions API endpoint. */\nconst OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';\n\n/**\n * Capability flags for the OpenRouter Chat Completions API.\n *\n * OpenRouter supports streaming, function calling (tools), structured JSON output,\n * and image inputs. Video and audio inputs are not currently supported.\n */\nconst OPENROUTER_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n imageOutput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for OpenRouter's Chat Completions API.\n *\n * This handler implements the UPP LLMHandler interface and provides\n * both synchronous completion and streaming capabilities.\n *\n * @returns An LLMHandler configured for OpenRouter Chat Completions\n *\n * @example\n * ```typescript\n * const handler = createCompletionsLLMHandler();\n * handler._setProvider(provider);\n * const model = handler.bind('openai/gpt-4o');\n * const response = await model.complete(request);\n * ```\n */\nexport function createCompletionsLLMHandler(): LLMHandler<OpenRouterCompletionsParams> {\n let providerRef: LLMProvider<OpenRouterCompletionsParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenRouterCompletionsParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenRouterCompletionsParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<OpenRouterCompletionsParams> = {\n modelId,\n capabilities: OPENROUTER_CAPABILITIES,\n\n get provider(): LLMProvider<OpenRouterCompletionsParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenRouterCompletionsParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n const data = await parseJsonResponse<OpenRouterCompletionsResponse>(response, 'openrouter', 'llm');\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenRouterCompletionsParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n body.stream_options = { include_usage: true };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openrouter', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenRouter error event\n if (typeof data === 'object' && data !== null) {\n const chunk = data as OpenRouterCompletionsStreamChunk;\n\n // Check for error in chunk\n if ('error' in chunk && chunk.error) {\n const errorData = chunk.error as { message?: string; type?: string };\n const error = new UPPError(\n errorData.message ?? 'Unknown error',\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(chunk, state);\n for (const event of uppEvents) {\n yield event;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * Transform utilities for OpenRouter Responses API (beta).\n *\n * This module handles bidirectional conversion between UPP (Unified Provider Protocol)\n * request/response formats and OpenRouter's Responses API format. The Responses API\n * uses a different structure than Chat Completions, with input items and output items.\n *\n * @module transform.responses\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock, AssistantContent, ReasoningBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n OpenRouterResponsesParams,\n OpenRouterResponsesRequest,\n OpenRouterResponsesInputItem,\n OpenRouterResponsesContentPart,\n OpenRouterResponsesTool,\n OpenRouterResponsesResponse,\n OpenRouterResponsesStreamEvent,\n OpenRouterSystemContent,\n OpenRouterCacheControl,\n OpenRouterResponsesReasoningOutput,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLMRequest into an OpenRouter Responses API request body.\n *\n * Parameters are spread directly to enable pass-through of any OpenRouter API fields,\n * even those not explicitly defined in our types. This allows developers to use new\n * API features without waiting for library updates.\n *\n * @param request - The UPP LLM request containing messages, tools, and parameters\n * @param modelId - The OpenRouter model identifier (e.g., 'openai/gpt-4o')\n * @returns A fully formed OpenRouter Responses API request body\n */\nexport function transformRequest(\n request: LLMRequest<OpenRouterResponsesParams>,\n modelId: string\n): OpenRouterResponsesRequest {\n const params = request.params ?? ({} as OpenRouterResponsesParams);\n\n const openrouterRequest: OpenRouterResponsesRequest = {\n ...params,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n openrouterRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openrouterRequest.text = {\n format: {\n type: 'json_schema',\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openrouterRequest;\n}\n\n/**\n * Transforms UPP messages into Responses API input items.\n *\n * Handles system prompts, user messages, assistant messages, function calls,\n * and tool results. Returns a string for simple single-message requests.\n *\n * System prompts support both string and array formats for cache_control.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array with cache_control)\n * @returns Array of input items, or a simple string for single-message requests\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string | unknown[]\n): OpenRouterResponsesInputItem[] | string {\n const result: OpenRouterResponsesInputItem[] = [];\n\n if (system !== undefined && system !== null) {\n const normalizedSystem = normalizeSystem(system);\n if (typeof normalizedSystem === 'string') {\n if (normalizedSystem.length > 0) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n } as OpenRouterResponsesInputItem);\n }\n } else if (normalizedSystem.length > 0) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n } as OpenRouterResponsesInputItem);\n }\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n if (result.length === 1 && result[0]?.type === 'message') {\n const item = result[0] as { role?: string; content?: string | unknown[] };\n if (item.role === 'user' && typeof item.content === 'string') {\n return item.content;\n }\n }\n\n return result;\n}\n\nfunction normalizeSystem(system: string | unknown[]): string | OpenRouterSystemContent[] {\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const blocks: OpenRouterSystemContent[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object') {\n throw new UPPError(\n 'System prompt array must contain objects with type \"text\"',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n const candidate = block as { type?: unknown; text?: unknown; cache_control?: unknown };\n if (candidate.type !== 'text' || typeof candidate.text !== 'string') {\n throw new UPPError(\n 'OpenRouter system blocks must be of type \"text\" with a string text field',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n if (candidate.cache_control !== undefined && !isValidCacheControl(candidate.cache_control)) {\n throw new UPPError(\n 'Invalid cache_control for OpenRouter system prompt',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n blocks.push(block as OpenRouterSystemContent);\n }\n\n return blocks;\n}\n\nfunction isValidCacheControl(value: unknown): value is OpenRouterCacheControl {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as { type?: unknown; ttl?: unknown };\n if (candidate.type !== 'ephemeral') return false;\n if (candidate.ttl !== undefined && candidate.ttl !== '1h') return false;\n return true;\n}\n\n/**\n * Filters content blocks to only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with string type properties\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a single UPP message to Responses API input items.\n *\n * May return multiple input items for messages containing tool calls,\n * as function_call items must be separate from message items.\n *\n * @param message - The UPP message to transform\n * @returns Array of Responses API input items\n */\nfunction transformMessage(message: Message): OpenRouterResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return [\n {\n type: 'message',\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n },\n ];\n }\n return [\n {\n type: 'message',\n role: 'user',\n content: validContent.map(transformContentPart),\n },\n ];\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const items: OpenRouterResponsesInputItem[] = [];\n\n // Filter out reasoning blocks - they're preserved via reasoningEncryptedContent in metadata\n const contentParts: OpenRouterResponsesContentPart[] = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c): OpenRouterResponsesContentPart => ({\n type: 'output_text',\n text: c.text,\n annotations: [],\n }));\n\n const messageId = message.id || generateId();\n\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n id: messageId,\n status: 'completed',\n content: contentParts,\n });\n }\n\n const openrouterMeta = message.metadata?.openrouter as\n | {\n functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }>;\n // Encrypted reasoning content for multi-turn context (stateless mode)\n reasoningEncryptedContent?: string;\n }\n | undefined;\n const functionCallItems = openrouterMeta?.functionCallItems;\n\n // Add reasoning item for multi-turn context preservation (must be passed back as-is)\n if (openrouterMeta?.reasoningEncryptedContent) {\n try {\n const reasoningData = JSON.parse(openrouterMeta.reasoningEncryptedContent) as {\n id: string;\n summary: Array<{ type: 'summary_text'; text: string }>;\n encrypted_content?: string;\n };\n items.push({\n type: 'reasoning',\n id: reasoningData.id,\n summary: reasoningData.summary,\n encrypted_content: reasoningData.encrypted_content,\n } as OpenRouterResponsesInputItem);\n } catch {\n // Invalid JSON - skip reasoning item\n }\n }\n\n if (functionCallItems && functionCallItems.length > 0) {\n for (const fc of functionCallItems) {\n items.push({\n type: 'function_call',\n id: fc.id,\n call_id: fc.call_id,\n name: fc.name,\n arguments: fc.arguments,\n });\n }\n } else if (message.toolCalls && message.toolCalls.length > 0) {\n for (const call of message.toolCalls) {\n items.push({\n type: 'function_call',\n id: `fc_${call.toolCallId}`,\n call_id: call.toolCallId,\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n });\n }\n }\n\n return items;\n }\n\n if (isToolResultMessage(message)) {\n return message.results.map((result, index) => ({\n type: 'function_call_output' as const,\n id: `fco_${result.toolCallId}_${index}`,\n call_id: result.toolCallId,\n output:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n\n return [];\n}\n\n/**\n * Transforms a UPP content block to Responses API content part format.\n *\n * Supports text and image content types. Images are converted to data URLs\n * or passed through as URL references.\n *\n * @param block - The UPP content block to transform\n * @returns Responses API content part\n * @throws Error if the content type is unsupported\n */\nfunction transformContentPart(block: ContentBlock): OpenRouterResponsesContentPart {\n switch (block.type) {\n case 'text':\n return { type: 'input_text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`,\n detail: 'auto',\n };\n }\n\n if (imageBlock.source.type === 'url') {\n return {\n type: 'input_image',\n image_url: imageBlock.source.url,\n detail: 'auto',\n };\n }\n\n if (imageBlock.source.type === 'bytes') {\n // Convert bytes to base64\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${base64}`,\n detail: 'auto',\n };\n }\n\n throw new Error('Unknown image source type');\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transforms a UPP Tool definition to Responses API function tool format.\n *\n * @param tool - The UPP tool definition\n * @returns Responses API function tool definition\n */\nfunction transformTool(tool: Tool): OpenRouterResponsesTool {\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n };\n}\n\n/**\n * Transforms an OpenRouter Responses API response to UPP LLMResponse format.\n *\n * Extracts text content, tool calls, usage statistics, and stop reason from\n * the Responses API output items. Handles refusals and structured output parsing.\n *\n * @param data - The raw OpenRouter Responses API response\n * @returns UPP-formatted LLM response\n */\nexport function transformResponse(data: OpenRouterResponsesResponse): LLMResponse {\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n let hadRefusal = false;\n let structuredData: unknown;\n let reasoningEncryptedContent: string | undefined;\n\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item;\n for (const part of messageItem.content) {\n if (part.type === 'output_text') {\n textContent.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n } else if (part.type === 'refusal') {\n textContent.push({ type: 'text', text: part.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item;\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(functionCall.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n toolCalls.push({\n toolCallId: functionCall.call_id,\n toolName: functionCall.name,\n arguments: args,\n });\n functionCallItems.push({\n id: functionCall.id,\n call_id: functionCall.call_id,\n name: functionCall.name,\n arguments: functionCall.arguments,\n });\n } else if (item.type === 'image_generation_call') {\n const imageGen = item;\n if (imageGen.result) {\n textContent.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageGen.result },\n } as ImageBlock);\n }\n } else if (item.type === 'reasoning') {\n const reasoningItem = item as OpenRouterResponsesReasoningOutput;\n // Extract reasoning text from summary\n const reasoningText = reasoningItem.summary\n .filter((s): s is { type: 'summary_text'; text: string } => s.type === 'summary_text')\n .map(s => s.text)\n .join('');\n if (reasoningText) {\n reasoningContent.push({ type: 'reasoning', text: reasoningText });\n }\n // Store full reasoning item for multi-turn context preservation (must be passed back as-is)\n reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const responseId = data.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n openrouter: {\n model: data.model,\n status: data.status,\n // Store response_id for multi-turn tool calling\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n // Store encrypted reasoning content for multi-turn context (stateless mode)\n reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.input_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (data.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (data.status === 'incomplete') {\n stopReason = data.incomplete_details?.reason === 'max_output_tokens'\n ? 'max_tokens'\n : 'end_turn';\n } else if (data.status === 'failed') {\n stopReason = 'error';\n }\n if (hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating Responses API streaming data.\n *\n * Used during streaming to collect text deltas, tool call fragments,\n * and usage statistics before building the final LLMResponse.\n */\nexport interface ResponsesStreamState {\n /** Response ID from the created event */\n id: string;\n /** Model identifier from the response */\n model: string;\n /** Map of output index to accumulated text content */\n textByIndex: Map<number, string>;\n /** Map of output index to accumulated reasoning text */\n reasoningByIndex: Map<number, string>;\n /** Map of output index to accumulated tool call data */\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n /** Map of output index to generated image data (base64) */\n images: Map<number, string>;\n /** Current response status */\n status: string;\n /** Input token count from usage */\n inputTokens: number;\n /** Output token count from usage */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Whether a refusal was encountered */\n hadRefusal: boolean;\n /** Serialized reasoning item for multi-turn context preservation (includes encrypted_content) */\n reasoningEncryptedContent?: string;\n}\n\n/**\n * Creates an empty stream state object for accumulating Responses API streaming data.\n *\n * @returns A new ResponsesStreamState with all fields initialized\n */\nexport function createStreamState(): ResponsesStreamState {\n return {\n id: '',\n model: '',\n textByIndex: new Map(),\n reasoningByIndex: new Map(),\n toolCalls: new Map(),\n images: new Map(),\n status: 'in_progress',\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenRouter Responses API streaming event into UPP StreamEvents.\n *\n * Handles the various Responses API event types including response lifecycle events,\n * output item events, content deltas, function call arguments, and reasoning deltas.\n * Updates the provided state object with accumulated data.\n *\n * @param event - The OpenRouter Responses API streaming event to process\n * @param state - The mutable state object to update with event data\n * @returns Array of UPP StreamEvents generated from this event\n */\nexport function transformStreamEvent(\n event: OpenRouterResponsesStreamEvent,\n state: ResponsesStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n switch (event.type) {\n case 'response.created':\n state.id = event.response.id;\n state.model = event.response.model;\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n break;\n\n case 'response.in_progress':\n state.status = 'in_progress';\n break;\n\n case 'response.completed':\n case 'response.done':\n state.status = 'completed';\n if (event.response?.usage) {\n state.inputTokens = event.response.usage.input_tokens;\n state.outputTokens = event.response.usage.output_tokens;\n state.cacheReadTokens = event.response.usage.input_tokens_details?.cached_tokens ?? 0;\n }\n if (event.response?.output) {\n for (let i = 0; i < event.response.output.length; i++) {\n const item = event.response.output[i];\n if (item && item.type === 'function_call') {\n const functionCall = item;\n const existing = state.toolCalls.get(i) ?? { arguments: '' };\n existing.itemId = functionCall.id ?? existing.itemId;\n existing.callId = functionCall.call_id ?? existing.callId;\n existing.name = functionCall.name ?? existing.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(i, existing);\n }\n }\n }\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n break;\n\n case 'response.failed':\n state.status = 'failed';\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n break;\n\n case 'response.output_item.added':\n if (event.item.type === 'function_call') {\n const functionCall = event.item;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n }\n events.push({\n type: StreamEventType.ContentBlockStart,\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_item.done':\n if (event.item.type === 'function_call') {\n const functionCall = event.item;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n } else if (event.item.type === 'message') {\n // Extract text from completed message item (may not have incremental deltas)\n const messageItem = event.item;\n for (const content of messageItem.content || []) {\n if (content.type === 'output_text') {\n const existingText = state.textByIndex.get(event.output_index) ?? '';\n if (!existingText && content.text) {\n // Only use done text if we didn't get incremental deltas\n state.textByIndex.set(event.output_index, content.text);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: content.text },\n });\n }\n }\n }\n } else if (event.item.type === 'image_generation_call') {\n const imageGen = event.item;\n if (imageGen.result) {\n state.images.set(event.output_index, imageGen.result);\n }\n } else if (event.item.type === 'reasoning') {\n // Capture full reasoning item for multi-turn context preservation (must be passed back as-is)\n const reasoningItem = event.item as OpenRouterResponsesReasoningOutput;\n state.reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n events.push({\n type: StreamEventType.ContentBlockStop,\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.content_part.delta':\n case 'response.output_text.delta': {\n const textDelta = (event as { delta: string }).delta;\n const currentText = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentText + textDelta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: textDelta },\n });\n break;\n }\n\n case 'response.output_text.done':\n case 'response.content_part.done':\n if ('text' in event) {\n state.textByIndex.set(event.output_index, (event as { text: string }).text);\n }\n break;\n\n case 'response.refusal.delta': {\n state.hadRefusal = true;\n const currentRefusal = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentRefusal + event.delta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.refusal.done':\n state.hadRefusal = true;\n state.textByIndex.set(event.output_index, event.refusal);\n break;\n\n case 'response.function_call_arguments.delta': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id && !toolCall.itemId) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id && !toolCall.callId) {\n toolCall.callId = event.call_id;\n }\n toolCall.arguments += event.delta;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: event.output_index,\n delta: {\n toolCallId: toolCall.callId ?? toolCall.itemId ?? '',\n toolName: toolCall.name,\n argumentsJson: event.delta,\n },\n });\n break;\n }\n\n case 'response.function_call_arguments.done': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id) {\n toolCall.callId = event.call_id;\n }\n toolCall.name = event.name;\n toolCall.arguments = event.arguments;\n break;\n }\n\n case 'response.reasoning.delta': {\n // Accumulate reasoning text\n const currentReasoning = state.reasoningByIndex.get(0) ?? '';\n state.reasoningByIndex.set(0, currentReasoning + event.delta);\n // Emit reasoning as a reasoning_delta event\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'error':\n break;\n\n default:\n break;\n }\n\n return events;\n}\n\n/**\n * Builds the final LLMResponse from accumulated Responses API streaming state.\n *\n * Constructs the complete response after streaming has finished, including\n * the assistant message, tool calls, usage statistics, and stop reason.\n *\n * @param state - The accumulated stream state\n * @returns Complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: ResponsesStreamState): LLMResponse {\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Add reasoning content if present\n for (const [, reasoning] of state.reasoningByIndex) {\n if (reasoning) {\n reasoningContent.push({ type: 'reasoning', text: reasoning });\n }\n }\n\n for (const [, text] of state.textByIndex) {\n if (text) {\n textContent.push({ type: 'text', text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n }\n }\n\n for (const [, imageData] of state.images) {\n if (imageData) {\n textContent.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageData },\n } as ImageBlock);\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n }\n const itemId = toolCall.itemId ?? '';\n const callId = toolCall.callId ?? toolCall.itemId ?? '';\n const name = toolCall.name ?? '';\n toolCalls.push({\n toolCallId: callId,\n toolName: name,\n arguments: args,\n });\n\n if (itemId && callId && name) {\n functionCallItems.push({\n id: itemId,\n call_id: callId,\n name,\n arguments: toolCall.arguments,\n });\n }\n }\n\n const responseId = state.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n openrouter: {\n model: state.model,\n status: state.status,\n // Store response_id for multi-turn tool calling\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n // Store encrypted reasoning content for multi-turn context (stateless mode)\n reasoningEncryptedContent: state.reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (state.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (state.status === 'failed') {\n stopReason = 'error';\n }\n if (state.hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * OpenRouter Responses API LLM handler.\n *\n * This module implements the LLMHandler interface for OpenRouter's Responses API,\n * which is currently in beta and provides additional features like reasoning support.\n *\n * @module llm.responses\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type { OpenRouterResponsesParams, OpenRouterResponsesResponse, OpenRouterResponsesStreamEvent, OpenRouterResponseErrorEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.responses.ts';\n\n/** Base URL for OpenRouter's Responses API endpoint (beta). */\nconst OPENROUTER_RESPONSES_API_URL = 'https://openrouter.ai/api/v1/responses';\n\n/**\n * Capability flags for the OpenRouter Responses API.\n *\n * The Responses API shares the same capabilities as the Completions API,\n * with additional support for reasoning models.\n */\nconst OPENROUTER_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n imageOutput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an LLM handler for OpenRouter's Responses API (beta).\n *\n * The Responses API provides a different interface than Chat Completions,\n * with features like reasoning effort configuration and different output formats.\n *\n * @returns An LLMHandler configured for OpenRouter Responses API\n *\n * @example\n * ```typescript\n * const handler = createResponsesLLMHandler();\n * handler._setProvider(provider);\n * const model = handler.bind('openai/gpt-4o');\n * const response = await model.complete(request);\n * ```\n */\nexport function createResponsesLLMHandler(): LLMHandler<OpenRouterResponsesParams> {\n let providerRef: LLMProvider<OpenRouterResponsesParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenRouterResponsesParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenRouterResponsesParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<OpenRouterResponsesParams> = {\n modelId,\n capabilities: OPENROUTER_CAPABILITIES,\n\n get provider(): LLMProvider<OpenRouterResponsesParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenRouterResponsesParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n const data = await parseJsonResponse<OpenRouterResponsesResponse>(response, 'openrouter', 'llm');\n\n // Check for error in response\n if (data.status === 'failed' && data.error) {\n throw new UPPError(\n data.error.message,\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenRouterResponsesParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openrouter', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenRouter error event\n if (typeof data === 'object' && data !== null) {\n const event = data as OpenRouterResponsesStreamEvent;\n\n // Check for error event\n if (event.type === 'error') {\n const errorEvent = event as OpenRouterResponseErrorEvent;\n const error = new UPPError(\n errorEvent.error.message,\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(event, state);\n for (const uppEvent of uppEvents) {\n yield uppEvent;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview OpenRouter Embeddings API Handler\n *\n * This module implements the embedding handler for OpenRouter's embeddings API.\n * OpenRouter provides access to multiple embedding providers through an OpenAI-compatible endpoint.\n *\n * @see {@link https://openrouter.ai/docs/api/reference/embeddings OpenRouter Embeddings API Reference}\n * @module providers/openrouter/embed\n */\n\nimport type {\n EmbeddingHandler,\n BoundEmbeddingModel,\n EmbeddingRequest,\n EmbeddingResponse,\n EmbeddingProvider,\n} from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch } from '../../http/fetch.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\n\n/** Base URL for OpenRouter's Embeddings API endpoint */\nconst OPENROUTER_EMBEDDINGS_API_URL = 'https://openrouter.ai/api/v1/embeddings';\n\n/**\n * OpenRouter embedding parameters.\n * Passed through unchanged to the API.\n */\nexport interface OpenRouterEmbedParams {\n /** Output dimensions (model-dependent) */\n dimensions?: number;\n /** Encoding format: 'float' or 'base64' */\n encoding_format?: 'float' | 'base64';\n /** A unique identifier representing your end-user */\n user?: string;\n /** Input type hint for some models */\n input_type?: string;\n}\n\n/**\n * OpenRouter embeddings API response structure (OpenAI-compatible).\n */\ninterface OpenRouterEmbeddingsResponse {\n id: string;\n object: 'list';\n data: Array<{\n index: number;\n embedding: number[] | string;\n type: 'embedding';\n }>;\n model: string;\n usage: {\n prompt_tokens: number;\n total_tokens: number;\n cost?: number;\n };\n}\n\n/**\n * Get default dimensions for a model.\n */\nfunction getDefaultDimensions(modelId: string): number {\n if (modelId.includes('text-embedding-3-large')) {\n return 3072;\n }\n if (modelId.includes('text-embedding-3-small') || modelId.includes('ada-002')) {\n return 1536;\n }\n if (modelId.includes('gemini-embedding')) {\n return 3072;\n }\n return 1536;\n}\n\n/**\n * Creates an embedding handler for OpenRouter's Embeddings API.\n *\n * @returns An embedding handler configured for OpenRouter\n *\n * @example\n * ```typescript\n * const handler = createEmbeddingHandler();\n * const model = handler.bind('openai/text-embedding-3-large');\n *\n * const response = await model.embed({\n * inputs: ['Hello world'],\n * config: { apiKey: 'sk-or-...' }\n * });\n * ```\n */\nexport function createEmbeddingHandler(): EmbeddingHandler<OpenRouterEmbedParams> {\n let providerRef: EmbeddingProvider<OpenRouterEmbedParams> | null = null;\n\n return {\n supportedInputs: ['text'],\n\n _setProvider(provider: EmbeddingProvider<OpenRouterEmbedParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundEmbeddingModel<OpenRouterEmbedParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.Embedding\n );\n }\n\n const model: BoundEmbeddingModel<OpenRouterEmbedParams> = {\n modelId,\n maxBatchSize: 2048,\n maxInputLength: 8191,\n dimensions: getDefaultDimensions(modelId),\n\n get provider(): EmbeddingProvider<OpenRouterEmbedParams> {\n return providerRef!;\n },\n\n async embed(request: EmbeddingRequest<OpenRouterEmbedParams>): Promise<EmbeddingResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'embedding'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_EMBEDDINGS_API_URL;\n\n // Transform inputs to strings\n const inputTexts = request.inputs.map((input) => {\n if (typeof input === 'string') {\n return input;\n }\n if ('text' in input) {\n return input.text;\n }\n throw new UPPError(\n 'OpenRouter embeddings only support text input',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.Embedding\n );\n });\n\n // Build request body - params pass through unchanged\n const body: Record<string, unknown> = {\n model: modelId,\n input: inputTexts,\n };\n\n // Pass through OpenRouter-specific params\n if (request.params?.dimensions !== undefined) {\n body.dimensions = request.params.dimensions;\n }\n if (request.params?.encoding_format !== undefined) {\n body.encoding_format = request.params.encoding_format;\n }\n if (request.params?.user !== undefined) {\n body.user = request.params.user;\n }\n if (request.params?.input_type !== undefined) {\n body.input_type = request.params.input_type;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n // Merge custom headers\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(baseUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n }, request.config, 'openrouter', 'embedding');\n\n const data = await parseJsonResponse<OpenRouterEmbeddingsResponse>(response, 'openrouter', 'embedding');\n\n // Return EmbeddingResponse - vector is floats or base64 string\n return {\n embeddings: data.data.map((d) => ({\n vector: d.embedding,\n index: d.index,\n })),\n usage: { totalTokens: data.usage.total_tokens },\n metadata: data.usage.cost !== undefined ? { cost: data.usage.cost } : undefined,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import type { Provider } from '../../types/provider.ts';\nimport { createProvider } from '../../core/provider.ts';\nimport type { LLMHandlerResolver } from '../../core/provider-handlers.ts';\nimport { createCompletionsLLMHandler } from './llm.completions.ts';\nimport { createResponsesLLMHandler } from './llm.responses.ts';\nimport { createEmbeddingHandler } from './embed.ts';\n\n/**\n * Configuration options for creating an OpenRouter model reference.\n *\n * OpenRouter supports two distinct APIs:\n * - Chat Completions API: Stable, production-ready, supports most models\n * - Responses API: Beta, supports advanced features like reasoning\n */\nexport interface OpenRouterProviderOptions {\n /**\n * Which OpenRouter API to use.\n *\n * - `'completions'`: Chat Completions API (default, recommended for production)\n * - `'responses'`: Responses API (beta, supports reasoning models)\n */\n api?: 'completions' | 'responses';\n}\n\n/**\n * OpenRouter provider interface with configurable API mode.\n *\n * OpenRouter is a unified API that provides access to hundreds of AI models\n * through a single endpoint, including models from OpenAI, Anthropic, Google,\n * Meta, Mistral, and many others.\n *\n * @example Using the Chat Completions API (default)\n * ```typescript\n * const model = openrouter('openai/gpt-4o');\n * ```\n *\n * @example Using the Responses API (beta)\n * ```typescript\n * const model = openrouter('openai/gpt-4o', { api: 'responses' });\n * ```\n *\n * @example Using Anthropic models\n * ```typescript\n * const model = openrouter('anthropic/claude-3.5-sonnet', { api: 'completions' });\n * ```\n */\n/**\n * Type alias for the OpenRouter provider with its options.\n */\nexport type OpenRouterProvider = Provider<OpenRouterProviderOptions>;\n\n/**\n * LLM handler resolver for OpenRouter's dual API support.\n *\n * Dynamically selects between Completions and Responses API handlers\n * based on the options stored on the ModelReference. This eliminates\n * race conditions from shared mutable state.\n */\nconst llmResolver: LLMHandlerResolver<OpenRouterProviderOptions> = {\n handlers: {\n completions: createCompletionsLLMHandler(),\n responses: createResponsesLLMHandler(),\n },\n defaultMode: 'completions',\n getMode: (options) => options?.api ?? 'completions',\n};\n\n/**\n * OpenRouter provider singleton.\n *\n * OpenRouter is a unified API that provides access to hundreds of AI models\n * through a single endpoint, including models from OpenAI, Anthropic, Google,\n * Meta, Mistral, and many others.\n *\n * Supports both the Chat Completions API (default) and Responses API (beta).\n *\n * @example Basic usage with Chat Completions API\n * ```typescript\n * import { openrouter } from './providers/openrouter';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: openrouter('openai/gpt-4o'),\n * params: { max_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example Using the Responses API (beta)\n * ```typescript\n * const betaModel = llm({\n * model: openrouter('openai/gpt-4o', { api: 'responses' }),\n * params: { max_output_tokens: 1000 }\n * });\n * ```\n *\n * @example Model routing and fallback configuration\n * ```typescript\n * const routedModel = llm({\n * model: openrouter('openai/gpt-4o'),\n * params: {\n * max_tokens: 1000,\n * models: ['openai/gpt-4o', 'anthropic/claude-3.5-sonnet'],\n * route: 'fallback',\n * provider: {\n * allow_fallbacks: true,\n * require_parameters: true,\n * },\n * }\n * });\n * ```\n *\n * @see {@link https://openrouter.ai/docs | OpenRouter Documentation}\n */\nexport const openrouter = createProvider<OpenRouterProviderOptions>({\n name: 'openrouter',\n version: '1.0.0',\n handlers: {\n llm: llmResolver,\n embedding: createEmbeddingHandler(),\n },\n}) as OpenRouterProvider;\n\nexport type {\n OpenRouterCompletionsParams,\n OpenRouterResponsesParams,\n OpenRouterConfig,\n OpenRouterAPIMode,\n OpenRouterModelOptions,\n OpenRouterModelReference,\n OpenRouterProviderPreferences,\n OpenRouterImageConfig,\n OpenRouterHeaders,\n} from './types.ts';\n\nexport type { OpenRouterEmbedParams } from './embed.ts';\n"],"mappings":"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","names":["transformRequest","transformTool","normalizeSystem","transformMessage","isValidCacheControl","filterValidContent","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState","OPENROUTER_CAPABILITIES","transformRequest","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState"]}
|
|
1
|
+
{"version":3,"sources":["../../src/providers/openrouter/transform.completions.ts","../../src/providers/openrouter/llm.completions.ts","../../src/providers/openrouter/transform.responses.ts","../../src/providers/openrouter/llm.responses.ts","../../src/providers/openrouter/embed.ts","../../src/providers/openrouter/index.ts"],"sourcesContent":["/**\n * Transform utilities for OpenRouter Chat Completions API.\n *\n * This module handles bidirectional conversion between UPP (Unified Provider Protocol)\n * request/response formats and OpenRouter's Chat Completions API format, which is\n * compatible with the OpenAI Chat Completions API.\n *\n * @module transform.completions\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type {\n ContentBlock,\n TextBlock,\n ImageBlock,\n DocumentBlock,\n AudioBlock,\n VideoBlock,\n AssistantContent,\n ReasoningBlock,\n} from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n OpenRouterCompletionsParams,\n OpenRouterCompletionsRequest,\n OpenRouterCompletionsMessage,\n OpenRouterSystemContent,\n OpenRouterUserContent,\n OpenRouterCompletionsTool,\n OpenRouterCompletionsResponse,\n OpenRouterCompletionsStreamChunk,\n OpenRouterToolCall,\n OpenRouterCacheControl,\n OpenRouterReasoningDetail,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLMRequest into an OpenRouter Chat Completions API request body.\n *\n * Parameters are spread directly to enable pass-through of any OpenRouter API fields,\n * even those not explicitly defined in our types. This allows developers to use new\n * API features without waiting for library updates.\n *\n * @param request - The UPP LLM request containing messages, tools, and parameters\n * @param modelId - The OpenRouter model identifier (e.g., 'openai/gpt-4o')\n * @returns A fully formed OpenRouter Chat Completions request body\n */\nexport function transformRequest(\n request: LLMRequest<OpenRouterCompletionsParams>,\n modelId: string\n): OpenRouterCompletionsRequest {\n const params = request.params ?? ({} as OpenRouterCompletionsParams);\n\n const openrouterRequest: OpenRouterCompletionsRequest = {\n ...params,\n model: modelId,\n messages: transformMessages(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n openrouterRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openrouterRequest.response_format = {\n type: 'json_schema',\n json_schema: {\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openrouterRequest;\n}\n\n/**\n * Transforms UPP messages into OpenRouter Chat Completions message format.\n *\n * Handles system prompts, user messages, assistant messages, and tool results.\n * Tool result messages are expanded into individual tool messages.\n *\n * System prompts support both string and array formats:\n * - String: Simple text system prompt\n * - Array: Content blocks with optional cache_control for Anthropic/Gemini models\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array with cache_control)\n * @returns Array of OpenRouter-formatted messages\n */\nfunction transformMessages(\n messages: Message[],\n system?: string | unknown[]\n): OpenRouterCompletionsMessage[] {\n const result: OpenRouterCompletionsMessage[] = [];\n\n if (system !== undefined && system !== null) {\n const normalizedSystem = normalizeSystem(system);\n if (typeof normalizedSystem === 'string') {\n if (normalizedSystem.length > 0) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n } else if (normalizedSystem.length > 0) {\n result.push({\n role: 'system',\n content: normalizedSystem,\n });\n }\n }\n\n for (const message of messages) {\n if (isToolResultMessage(message)) {\n const toolMessages = transformToolResults(message);\n result.push(...toolMessages);\n } else {\n const transformed = transformMessage(message);\n if (transformed) {\n result.push(transformed);\n }\n }\n }\n\n return result;\n}\n\nfunction normalizeSystem(system: string | unknown[]): string | OpenRouterSystemContent[] {\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const blocks: OpenRouterSystemContent[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object') {\n throw new UPPError(\n 'System prompt array must contain objects with type \"text\"',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n const candidate = block as { type?: unknown; text?: unknown; cache_control?: unknown };\n if (candidate.type !== 'text' || typeof candidate.text !== 'string') {\n throw new UPPError(\n 'OpenRouter system blocks must be of type \"text\" with a string text field',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n if (candidate.cache_control !== undefined && !isValidCacheControl(candidate.cache_control)) {\n throw new UPPError(\n 'Invalid cache_control for OpenRouter system prompt',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n blocks.push(block as OpenRouterSystemContent);\n }\n\n return blocks;\n}\n\nfunction isValidCacheControl(value: unknown): value is OpenRouterCacheControl {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as { type?: unknown; ttl?: unknown };\n if (candidate.type !== 'ephemeral') return false;\n if (candidate.ttl !== undefined && candidate.ttl !== '1h') return false;\n return true;\n}\n\n/**\n * Filters content blocks to only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with string type properties\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Extracts cache control configuration from message metadata.\n *\n * @param message - The message to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractCacheControl(message: Message): OpenRouterCacheControl | undefined {\n const openrouterMeta = message.metadata?.openrouter as\n | { cache_control?: OpenRouterCacheControl }\n | undefined;\n return openrouterMeta?.cache_control;\n}\n\n/**\n * Transforms a single UPP message to OpenRouter Chat Completions format.\n *\n * Cache control can be specified via message metadata:\n * ```typescript\n * new UserMessage(content, {\n * metadata: { openrouter: { cache_control: { type: \"ephemeral\" } } }\n * })\n * ```\n *\n * @param message - The UPP message to transform\n * @returns The transformed OpenRouter message, or null if the message type is unsupported\n */\nfunction transformMessage(message: Message): OpenRouterCompletionsMessage | null {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n const cacheControl = extractCacheControl(message);\n\n // If cache_control is present, always use array format to attach it\n if (cacheControl) {\n const content = validContent.map(transformContentBlock);\n // Apply cache_control to the last text content block\n for (let i = content.length - 1; i >= 0; i--) {\n const block = content[i];\n if (block?.type === 'text') {\n content[i] = { type: 'text', text: block.text, cache_control: cacheControl };\n break;\n }\n }\n return { role: 'user', content };\n }\n\n // No cache_control: use string shortcut for single text block\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return {\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n };\n }\n return {\n role: 'user',\n content: validContent.map(transformContentBlock),\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n // Filter out reasoning blocks - they're preserved via reasoning_details in metadata\n const nonReasoningContent = validContent.filter(c => c.type !== 'reasoning');\n const textContent = nonReasoningContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c) => c.text)\n .join('');\n\n const assistantMessage: OpenRouterCompletionsMessage = {\n role: 'assistant',\n content: textContent || null,\n };\n\n if (message.toolCalls && message.toolCalls.length > 0) {\n (assistantMessage as { tool_calls?: OpenRouterToolCall[] }).tool_calls =\n message.toolCalls.map((call) => ({\n id: call.toolCallId,\n type: 'function' as const,\n function: {\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n },\n }));\n }\n\n // Forward reasoning_details from metadata for multi-turn context preservation\n const openrouterMeta = message.metadata?.openrouter as\n | { reasoning_details?: OpenRouterReasoningDetail[] }\n | undefined;\n if (openrouterMeta?.reasoning_details && openrouterMeta.reasoning_details.length > 0) {\n (assistantMessage as { reasoning_details?: OpenRouterReasoningDetail[] }).reasoning_details =\n openrouterMeta.reasoning_details;\n }\n\n return assistantMessage;\n }\n\n if (isToolResultMessage(message)) {\n const results = message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n\n return results[0] ?? null;\n }\n\n return null;\n}\n\n/**\n * Transforms a tool result message into multiple OpenRouter tool messages.\n *\n * Each tool result in the UPP ToolResultMessage becomes a separate OpenRouter\n * tool message with the corresponding tool_call_id.\n *\n * @param message - The UPP message (expected to be a ToolResultMessage)\n * @returns Array of OpenRouter tool messages\n */\nexport function transformToolResults(\n message: Message\n): OpenRouterCompletionsMessage[] {\n if (!isToolResultMessage(message)) {\n const single = transformMessage(message);\n return single ? [single] : [];\n }\n\n return message.results.map((result) => ({\n role: 'tool' as const,\n tool_call_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n}\n\n/**\n * Transforms a UPP content block to OpenRouter user content format.\n *\n * Supports text and image content types. Images are converted to data URLs\n * or passed through as URL references.\n *\n * @param block - The UPP content block to transform\n * @returns OpenRouter user content part\n * @throws Error if the content type is unsupported\n */\nfunction transformContentBlock(block: ContentBlock): OpenRouterUserContent {\n switch (block.type) {\n case 'text':\n return { type: 'text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let url: string;\n\n if (imageBlock.source.type === 'base64') {\n url = `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`;\n } else if (imageBlock.source.type === 'url') {\n url = imageBlock.source.url;\n } else if (imageBlock.source.type === 'bytes') {\n // Convert bytes to base64\n const base64 = Buffer.from(imageBlock.source.data).toString('base64');\n url = `data:${imageBlock.mimeType};base64,${base64}`;\n } else {\n throw new Error('Unknown image source type');\n }\n\n return {\n type: 'image_url',\n image_url: { url },\n };\n }\n\n case 'document': {\n const documentBlock = block as DocumentBlock;\n\n // Text documents: include as inline text (OpenRouter file type is for PDFs)\n if (documentBlock.source.type === 'text') {\n if (!documentBlock.source.data) {\n throw new UPPError(\n 'Text document source data is empty',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n const title = documentBlock.title ? `[Document: ${documentBlock.title}]\\n` : '';\n return { type: 'text', text: `${title}${documentBlock.source.data}` };\n }\n\n // PDF documents: use file type\n const filename = documentBlock.title ?? 'document.pdf';\n\n if (documentBlock.source.type === 'base64') {\n const fileData = `data:${documentBlock.mimeType};base64,${documentBlock.source.data}`;\n return {\n type: 'file',\n file: {\n filename,\n file_data: fileData,\n },\n };\n }\n\n if (documentBlock.source.type === 'url') {\n return {\n type: 'file',\n file: {\n filename,\n file_url: documentBlock.source.url,\n },\n };\n }\n\n throw new UPPError(\n 'Unknown document source type',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n case 'audio': {\n const audioBlock = block as AudioBlock;\n // Audio requires base64 encoding; direct URLs are not supported\n const base64 = Buffer.from(audioBlock.data).toString('base64');\n // Extract format from mime type (e.g., 'audio/mp3' -> 'mp3')\n const format = audioBlock.mimeType.split('/')[1] ?? 'mp3';\n\n return {\n type: 'input_audio',\n input_audio: {\n data: base64,\n format,\n },\n };\n }\n\n case 'video': {\n const videoBlock = block as VideoBlock;\n // Convert bytes to base64 data URL\n const base64 = Buffer.from(videoBlock.data).toString('base64');\n const url = `data:${videoBlock.mimeType};base64,${base64}`;\n\n return {\n type: 'video_url',\n video_url: { url },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transforms a UPP Tool definition to OpenRouter function tool format.\n *\n * @param tool - The UPP tool definition\n * @returns OpenRouter function tool definition\n */\nfunction transformTool(tool: Tool): OpenRouterCompletionsTool {\n return {\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n },\n };\n}\n\n/**\n * Transforms an OpenRouter Chat Completions API response to UPP LLMResponse format.\n *\n * Extracts text content, tool calls, usage statistics, and stop reason from\n * the OpenRouter response. Attempts to parse JSON content for structured output.\n *\n * @param data - The raw OpenRouter Chat Completions response\n * @returns UPP-formatted LLM response\n * @throws Error if no choices are present in the response\n */\nexport function transformResponse(data: OpenRouterCompletionsResponse): LLMResponse {\n const choice = data.choices[0];\n if (!choice) {\n throw new Error('No choices in OpenRouter response');\n }\n\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Extract reasoning from reasoning_details\n if (choice.message.reasoning_details && choice.message.reasoning_details.length > 0) {\n for (const detail of choice.message.reasoning_details) {\n if (detail.type === 'reasoning.text' && detail.text) {\n reasoningContent.push({ type: 'reasoning', text: detail.text });\n } else if (detail.type === 'reasoning.summary' && detail.summary) {\n reasoningContent.push({ type: 'reasoning', text: detail.summary });\n }\n // reasoning.encrypted blocks don't have displayable text\n }\n }\n\n if (choice.message.content) {\n textContent.push({ type: 'text', text: choice.message.content });\n try {\n structuredData = JSON.parse(choice.message.content);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n\n if (choice.message.images && choice.message.images.length > 0) {\n for (const image of choice.message.images) {\n const imageBlock = parseGeneratedImage(image.image_url.url);\n if (imageBlock) {\n textContent.push(imageBlock);\n }\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const toolCalls: ToolCall[] = [];\n if (choice.message.tool_calls) {\n for (const call of choice.message.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(call.function.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n toolCalls.push({\n toolCallId: call.id,\n toolName: call.function.name,\n arguments: args,\n });\n }\n }\n\n const responseId = data.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n openrouter: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\n // Store reasoning_details for multi-turn context preservation\n reasoning_details: choice.message.reasoning_details,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.prompt_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (choice.finish_reason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Parses a generated image data URL into an ImageBlock.\n *\n * @param dataUrl - The data URL from the image generation response\n * @returns An ImageBlock or null if parsing fails\n */\nfunction parseGeneratedImage(dataUrl: string): ImageBlock | null {\n const match = dataUrl.match(/^data:(image\\/[^;]+);base64,(.+)$/);\n if (!match) {\n return null;\n }\n const [, mimeType, data] = match;\n if (!mimeType || !data) {\n return null;\n }\n return {\n type: 'image',\n mimeType,\n source: { type: 'base64', data },\n };\n}\n\n/**\n * Mutable state object for accumulating streaming response data.\n *\n * Used during streaming to collect text deltas, tool call fragments,\n * and usage statistics before building the final LLMResponse.\n */\nexport interface CompletionsStreamState {\n /** Response ID from the first chunk */\n id: string;\n /** Model identifier from the response */\n model: string;\n /** Accumulated text content */\n text: string;\n /** Accumulated reasoning text from reasoning_details */\n reasoning: string;\n /** Raw reasoning_details for multi-turn context preservation */\n reasoningDetails: OpenRouterReasoningDetail[];\n /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: string }>;\n /** Generated image data URLs from image generation models */\n images: string[];\n /** Final finish reason from the stream */\n finishReason: string | null;\n /** Input token count from usage */\n inputTokens: number;\n /** Output token count from usage */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n}\n\n/**\n * Creates an empty stream state object for accumulating streaming data.\n *\n * @returns A new CompletionsStreamState with all fields initialized\n */\nexport function createStreamState(): CompletionsStreamState {\n return {\n id: '',\n model: '',\n text: '',\n reasoning: '',\n reasoningDetails: [],\n toolCalls: new Map(),\n images: [],\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n };\n}\n\n/**\n * Transforms an OpenRouter streaming chunk into UPP StreamEvents.\n *\n * Processes the chunk to extract text deltas, tool call updates, and finish signals.\n * Updates the provided state object with accumulated data. Returns an array because\n * a single chunk may produce multiple events (e.g., text delta and tool call delta).\n *\n * @param chunk - The OpenRouter streaming chunk to process\n * @param state - The mutable state object to update with chunk data\n * @returns Array of UPP StreamEvents generated from this chunk\n */\nexport function transformStreamEvent(\n chunk: OpenRouterCompletionsStreamChunk,\n state: CompletionsStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (chunk.id && !state.id) {\n state.id = chunk.id;\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n }\n if (chunk.model) {\n state.model = chunk.model;\n }\n\n const choice = chunk.choices[0];\n if (choice) {\n if (choice.delta.content) {\n state.text += choice.delta.content;\n events.push({\n type: StreamEventType.TextDelta,\n index: 0,\n delta: { text: choice.delta.content },\n });\n }\n\n if (choice.delta.tool_calls) {\n for (const toolCallDelta of choice.delta.tool_calls) {\n const index = toolCallDelta.index;\n let toolCall = state.toolCalls.get(index);\n\n if (!toolCall) {\n toolCall = { id: '', name: '', arguments: '' };\n state.toolCalls.set(index, toolCall);\n }\n\n if (toolCallDelta.id) {\n toolCall.id = toolCallDelta.id;\n }\n if (toolCallDelta.function?.name) {\n toolCall.name = toolCallDelta.function.name;\n }\n if (toolCallDelta.function?.arguments) {\n toolCall.arguments += toolCallDelta.function.arguments;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: index,\n delta: {\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n argumentsJson: toolCallDelta.function.arguments,\n },\n });\n }\n }\n }\n\n if (choice.delta.images) {\n for (const image of choice.delta.images) {\n state.images.push(image.image_url.url);\n }\n }\n\n // Handle reasoning_details in streaming\n if (choice.delta.reasoning_details) {\n for (const detail of choice.delta.reasoning_details) {\n state.reasoningDetails.push(detail);\n // Extract text for ReasoningDelta events\n if (detail.type === 'reasoning.text' && detail.text) {\n state.reasoning += detail.text;\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: detail.text },\n });\n } else if (detail.type === 'reasoning.summary' && detail.summary) {\n state.reasoning += detail.summary;\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: detail.summary },\n });\n }\n // reasoning.encrypted blocks don't have displayable text\n }\n }\n\n if (choice.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n }\n }\n\n if (chunk.usage) {\n state.inputTokens = chunk.usage.prompt_tokens;\n state.outputTokens = chunk.usage.completion_tokens;\n state.cacheReadTokens = chunk.usage.prompt_tokens_details?.cached_tokens ?? 0;\n }\n\n return events;\n}\n\n/**\n * Builds the final LLMResponse from accumulated streaming state.\n *\n * Constructs the complete response after streaming has finished, including\n * the assistant message, tool calls, usage statistics, and stop reason.\n *\n * @param state - The accumulated stream state\n * @returns Complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: CompletionsStreamState): LLMResponse {\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Add reasoning content if present\n if (state.reasoning) {\n reasoningContent.push({ type: 'reasoning', text: state.reasoning });\n }\n\n if (state.text) {\n textContent.push({ type: 'text', text: state.text });\n try {\n structuredData = JSON.parse(state.text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n\n for (const imageUrl of state.images) {\n const imageBlock = parseGeneratedImage(imageUrl);\n if (imageBlock) {\n textContent.push(imageBlock);\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const toolCalls: ToolCall[] = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n }\n toolCalls.push({\n toolCallId: toolCall.id,\n toolName: toolCall.name,\n arguments: args,\n });\n }\n\n const messageId = state.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: messageId,\n metadata: {\n openrouter: {\n model: state.model,\n finish_reason: state.finishReason,\n // Store reasoning_details for multi-turn context preservation\n reasoning_details: state.reasoningDetails.length > 0 ? state.reasoningDetails : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n switch (state.finishReason) {\n case 'stop':\n stopReason = 'end_turn';\n break;\n case 'length':\n stopReason = 'max_tokens';\n break;\n case 'tool_calls':\n stopReason = 'tool_use';\n break;\n case 'content_filter':\n stopReason = 'content_filter';\n break;\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * OpenRouter Chat Completions API LLM handler.\n *\n * This module implements the LLMHandler interface for OpenRouter's Chat Completions API,\n * which is compatible with the OpenAI Chat Completions API format.\n *\n * @module llm.completions\n */\n\nimport type { BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { LLMHandler } from '../../types/provider.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type { OpenRouterCompletionsParams, OpenRouterCompletionsResponse, OpenRouterCompletionsStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.completions.ts';\n\n/** Base URL for OpenRouter's Chat Completions API endpoint. */\nconst OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';\n\n/**\n * Capability flags for the OpenRouter Chat Completions API.\n *\n * OpenRouter supports streaming, function calling (tools), structured JSON output,\n * image inputs, document/PDF inputs, audio inputs, and video inputs.\n */\nconst OPENROUTER_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n documentInput: true,\n imageOutput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Creates an LLM handler for OpenRouter's Chat Completions API.\n *\n * This handler implements the UPP LLMHandler interface and provides\n * both synchronous completion and streaming capabilities.\n *\n * @returns An LLMHandler configured for OpenRouter Chat Completions\n *\n * @example\n * ```typescript\n * const handler = createCompletionsLLMHandler();\n * handler._setProvider(provider);\n * const model = handler.bind('openai/gpt-4o');\n * const response = await model.complete(request);\n * ```\n */\nexport function createCompletionsLLMHandler(): LLMHandler<OpenRouterCompletionsParams> {\n let providerRef: LLMProvider<OpenRouterCompletionsParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenRouterCompletionsParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenRouterCompletionsParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<OpenRouterCompletionsParams> = {\n modelId,\n capabilities: OPENROUTER_CAPABILITIES,\n\n get provider(): LLMProvider<OpenRouterCompletionsParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenRouterCompletionsParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n const data = await parseJsonResponse<OpenRouterCompletionsResponse>(response, 'openrouter', 'llm');\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenRouterCompletionsParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n body.stream_options = { include_usage: true };\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openrouter', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenRouter error event\n if (typeof data === 'object' && data !== null) {\n const chunk = data as OpenRouterCompletionsStreamChunk;\n\n // Check for error in chunk\n if ('error' in chunk && chunk.error) {\n const errorData = chunk.error as { message?: string; type?: string };\n const error = new UPPError(\n errorData.message ?? 'Unknown error',\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(chunk, state);\n for (const event of uppEvents) {\n yield event;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * Transform utilities for OpenRouter Responses API (beta).\n *\n * This module handles bidirectional conversion between UPP (Unified Provider Protocol)\n * request/response formats and OpenRouter's Responses API format. The Responses API\n * uses a different structure than Chat Completions, with input items and output items.\n *\n * @module transform.responses\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport { StreamEventType } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type {\n ContentBlock,\n TextBlock,\n ImageBlock,\n DocumentBlock,\n AudioBlock,\n VideoBlock,\n AssistantContent,\n ReasoningBlock,\n} from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { generateId } from '../../utils/id.ts';\nimport type {\n OpenRouterResponsesParams,\n OpenRouterResponsesRequest,\n OpenRouterResponsesInputItem,\n OpenRouterResponsesContentPart,\n OpenRouterResponsesTool,\n OpenRouterResponsesResponse,\n OpenRouterResponsesStreamEvent,\n OpenRouterSystemContent,\n OpenRouterCacheControl,\n OpenRouterResponsesReasoningOutput,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLMRequest into an OpenRouter Responses API request body.\n *\n * Parameters are spread directly to enable pass-through of any OpenRouter API fields,\n * even those not explicitly defined in our types. This allows developers to use new\n * API features without waiting for library updates.\n *\n * @param request - The UPP LLM request containing messages, tools, and parameters\n * @param modelId - The OpenRouter model identifier (e.g., 'openai/gpt-4o')\n * @returns A fully formed OpenRouter Responses API request body\n */\nexport function transformRequest(\n request: LLMRequest<OpenRouterResponsesParams>,\n modelId: string\n): OpenRouterResponsesRequest {\n const params = request.params ?? ({} as OpenRouterResponsesParams);\n\n const openrouterRequest: OpenRouterResponsesRequest = {\n ...params,\n model: modelId,\n input: transformInputItems(request.messages, request.system),\n };\n\n if (request.tools && request.tools.length > 0) {\n openrouterRequest.tools = request.tools.map(transformTool);\n }\n\n if (request.structure) {\n const schema: Record<string, unknown> = {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n ...(request.structure.additionalProperties !== undefined\n ? { additionalProperties: request.structure.additionalProperties }\n : { additionalProperties: false }),\n };\n if (request.structure.description) {\n schema.description = request.structure.description;\n }\n\n openrouterRequest.text = {\n format: {\n type: 'json_schema',\n name: 'json_response',\n description: request.structure.description,\n schema,\n strict: true,\n },\n };\n }\n\n return openrouterRequest;\n}\n\n/**\n * Transforms UPP messages into Responses API input items.\n *\n * Handles system prompts, user messages, assistant messages, function calls,\n * and tool results. Returns a string for simple single-message requests.\n *\n * System prompts support both string and array formats for cache_control.\n *\n * @param messages - Array of UPP messages to transform\n * @param system - Optional system prompt (string or array with cache_control)\n * @returns Array of input items, or a simple string for single-message requests\n */\nfunction transformInputItems(\n messages: Message[],\n system?: string | unknown[]\n): OpenRouterResponsesInputItem[] | string {\n const result: OpenRouterResponsesInputItem[] = [];\n\n if (system !== undefined && system !== null) {\n const normalizedSystem = normalizeSystem(system);\n if (typeof normalizedSystem === 'string') {\n if (normalizedSystem.length > 0) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n } as OpenRouterResponsesInputItem);\n }\n } else if (normalizedSystem.length > 0) {\n result.push({\n type: 'message',\n role: 'system',\n content: normalizedSystem,\n } as OpenRouterResponsesInputItem);\n }\n }\n\n for (const message of messages) {\n const items = transformMessage(message);\n result.push(...items);\n }\n\n if (result.length === 1 && result[0]?.type === 'message') {\n const item = result[0] as { role?: string; content?: string | unknown[] };\n if (item.role === 'user' && typeof item.content === 'string') {\n return item.content;\n }\n }\n\n return result;\n}\n\nfunction normalizeSystem(system: string | unknown[]): string | OpenRouterSystemContent[] {\n if (typeof system === 'string') return system;\n if (!Array.isArray(system)) {\n throw new UPPError(\n 'System prompt must be a string or an array of text blocks',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const blocks: OpenRouterSystemContent[] = [];\n for (const block of system) {\n if (!block || typeof block !== 'object') {\n throw new UPPError(\n 'System prompt array must contain objects with type \"text\"',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n const candidate = block as { type?: unknown; text?: unknown; cache_control?: unknown };\n if (candidate.type !== 'text' || typeof candidate.text !== 'string') {\n throw new UPPError(\n 'OpenRouter system blocks must be of type \"text\" with a string text field',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n if (candidate.cache_control !== undefined && !isValidCacheControl(candidate.cache_control)) {\n throw new UPPError(\n 'Invalid cache_control for OpenRouter system prompt',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n blocks.push(block as OpenRouterSystemContent);\n }\n\n return blocks;\n}\n\nfunction isValidCacheControl(value: unknown): value is OpenRouterCacheControl {\n if (!value || typeof value !== 'object') return false;\n const candidate = value as { type?: unknown; ttl?: unknown };\n if (candidate.type !== 'ephemeral') return false;\n if (candidate.ttl !== undefined && candidate.ttl !== '1h') return false;\n return true;\n}\n\n/**\n * Filters content blocks to only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with string type properties\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms a single UPP message to Responses API input items.\n *\n * May return multiple input items for messages containing tool calls,\n * as function_call items must be separate from message items.\n *\n * @param message - The UPP message to transform\n * @returns Array of Responses API input items\n */\nfunction transformMessage(message: Message): OpenRouterResponsesInputItem[] {\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n if (validContent.length === 1 && validContent[0]?.type === 'text') {\n return [\n {\n type: 'message',\n role: 'user',\n content: (validContent[0] as TextBlock).text,\n },\n ];\n }\n return [\n {\n type: 'message',\n role: 'user',\n content: validContent.map(transformContentPart),\n },\n ];\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const items: OpenRouterResponsesInputItem[] = [];\n\n // Filter out reasoning blocks - they're preserved via reasoningEncryptedContent in metadata\n const contentParts: OpenRouterResponsesContentPart[] = validContent\n .filter((c): c is TextBlock => c.type === 'text')\n .map((c): OpenRouterResponsesContentPart => ({\n type: 'output_text',\n text: c.text,\n annotations: [],\n }));\n\n const messageId = message.id || generateId();\n\n if (contentParts.length > 0) {\n items.push({\n type: 'message',\n role: 'assistant',\n id: messageId,\n status: 'completed',\n content: contentParts,\n });\n }\n\n const openrouterMeta = message.metadata?.openrouter as\n | {\n functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }>;\n // Encrypted reasoning content for multi-turn context (stateless mode)\n reasoningEncryptedContent?: string;\n }\n | undefined;\n const functionCallItems = openrouterMeta?.functionCallItems;\n\n // Add reasoning item for multi-turn context preservation (must be passed back as-is)\n if (openrouterMeta?.reasoningEncryptedContent) {\n try {\n const reasoningData = JSON.parse(openrouterMeta.reasoningEncryptedContent) as {\n id: string;\n summary: Array<{ type: 'summary_text'; text: string }>;\n encrypted_content?: string;\n };\n items.push({\n type: 'reasoning',\n id: reasoningData.id,\n summary: reasoningData.summary,\n encrypted_content: reasoningData.encrypted_content,\n } as OpenRouterResponsesInputItem);\n } catch {\n // Invalid JSON - skip reasoning item\n }\n }\n\n if (functionCallItems && functionCallItems.length > 0) {\n for (const fc of functionCallItems) {\n items.push({\n type: 'function_call',\n id: fc.id,\n call_id: fc.call_id,\n name: fc.name,\n arguments: fc.arguments,\n });\n }\n } else if (message.toolCalls && message.toolCalls.length > 0) {\n for (const call of message.toolCalls) {\n items.push({\n type: 'function_call',\n id: `fc_${call.toolCallId}`,\n call_id: call.toolCallId,\n name: call.toolName,\n arguments: JSON.stringify(call.arguments),\n });\n }\n }\n\n return items;\n }\n\n if (isToolResultMessage(message)) {\n return message.results.map((result, index) => ({\n type: 'function_call_output' as const,\n id: `fco_${result.toolCallId}_${index}`,\n call_id: result.toolCallId,\n output:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n }));\n }\n\n return [];\n}\n\n/**\n * Transforms a UPP content block to Responses API content part format.\n *\n * Supports text and image content types. Images are converted to data URLs\n * or passed through as URL references.\n *\n * @param block - The UPP content block to transform\n * @returns Responses API content part\n * @throws Error if the content type is unsupported\n */\nfunction transformContentPart(block: ContentBlock): OpenRouterResponsesContentPart {\n switch (block.type) {\n case 'text':\n return { type: 'input_text', text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${imageBlock.source.data}`,\n detail: 'auto',\n };\n }\n\n if (imageBlock.source.type === 'url') {\n return {\n type: 'input_image',\n image_url: imageBlock.source.url,\n detail: 'auto',\n };\n }\n\n if (imageBlock.source.type === 'bytes') {\n // Convert bytes to base64\n const base64 = Buffer.from(imageBlock.source.data).toString('base64');\n return {\n type: 'input_image',\n image_url: `data:${imageBlock.mimeType};base64,${base64}`,\n detail: 'auto',\n };\n }\n\n throw new Error('Unknown image source type');\n }\n\n case 'document': {\n const documentBlock = block as DocumentBlock;\n\n // Text documents: include as inline text (OpenRouter file type is for PDFs)\n if (documentBlock.source.type === 'text') {\n if (!documentBlock.source.data) {\n throw new UPPError(\n 'Text document source data is empty',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n const title = documentBlock.title ? `[Document: ${documentBlock.title}]\\n` : '';\n return { type: 'input_text', text: `${title}${documentBlock.source.data}` };\n }\n\n // PDF documents: use file type\n const filename = documentBlock.title ?? 'document.pdf';\n\n if (documentBlock.source.type === 'base64') {\n // Use data URL format\n const fileData = `data:${documentBlock.mimeType};base64,${documentBlock.source.data}`;\n return {\n type: 'input_file',\n filename,\n file_data: fileData,\n };\n }\n\n if (documentBlock.source.type === 'url') {\n return {\n type: 'input_file',\n filename,\n file_url: documentBlock.source.url,\n };\n }\n\n throw new UPPError(\n 'Unknown document source type',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n case 'audio': {\n const audioBlock = block as AudioBlock;\n // Audio requires base64 encoding\n const base64 = Buffer.from(audioBlock.data).toString('base64');\n // Extract format from mime type (e.g., 'audio/mp3' -> 'mp3')\n const format = audioBlock.mimeType.split('/')[1] ?? 'mp3';\n\n return {\n type: 'input_audio',\n input_audio: {\n data: base64,\n format,\n },\n };\n }\n\n case 'video': {\n const videoBlock = block as VideoBlock;\n // Convert bytes to base64 data URL\n const base64 = Buffer.from(videoBlock.data).toString('base64');\n const url = `data:${videoBlock.mimeType};base64,${base64}`;\n\n return {\n type: 'input_video',\n video_url: url,\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transforms a UPP Tool definition to Responses API function tool format.\n *\n * @param tool - The UPP tool definition\n * @returns Responses API function tool definition\n */\nfunction transformTool(tool: Tool): OpenRouterResponsesTool {\n return {\n type: 'function',\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n ...(tool.parameters.additionalProperties !== undefined\n ? { additionalProperties: tool.parameters.additionalProperties }\n : {}),\n },\n };\n}\n\n/**\n * Transforms an OpenRouter Responses API response to UPP LLMResponse format.\n *\n * Extracts text content, tool calls, usage statistics, and stop reason from\n * the Responses API output items. Handles refusals and structured output parsing.\n *\n * @param data - The raw OpenRouter Responses API response\n * @returns UPP-formatted LLM response\n */\nexport function transformResponse(data: OpenRouterResponsesResponse): LLMResponse {\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n let hadRefusal = false;\n let structuredData: unknown;\n let reasoningEncryptedContent: string | undefined;\n\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item;\n for (const part of messageItem.content) {\n if (part.type === 'output_text') {\n textContent.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n } else if (part.type === 'refusal') {\n textContent.push({ type: 'text', text: part.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item;\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(functionCall.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n toolCalls.push({\n toolCallId: functionCall.call_id,\n toolName: functionCall.name,\n arguments: args,\n });\n functionCallItems.push({\n id: functionCall.id,\n call_id: functionCall.call_id,\n name: functionCall.name,\n arguments: functionCall.arguments,\n });\n } else if (item.type === 'image_generation_call') {\n const imageGen = item;\n if (imageGen.result) {\n textContent.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageGen.result },\n } as ImageBlock);\n }\n } else if (item.type === 'reasoning') {\n const reasoningItem = item as OpenRouterResponsesReasoningOutput;\n // Extract reasoning text from summary\n const reasoningText = reasoningItem.summary\n .filter((s): s is { type: 'summary_text'; text: string } => s.type === 'summary_text')\n .map(s => s.text)\n .join('');\n if (reasoningText) {\n reasoningContent.push({ type: 'reasoning', text: reasoningText });\n }\n // Store full reasoning item for multi-turn context preservation (must be passed back as-is)\n reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const responseId = data.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n openrouter: {\n model: data.model,\n status: data.status,\n // Store response_id for multi-turn tool calling\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n // Store encrypted reasoning content for multi-turn context (stateless mode)\n reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n cacheReadTokens: data.usage.input_tokens_details?.cached_tokens ?? 0,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (data.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (data.status === 'incomplete') {\n stopReason = data.incomplete_details?.reason === 'max_output_tokens'\n ? 'max_tokens'\n : 'end_turn';\n } else if (data.status === 'failed') {\n stopReason = 'error';\n }\n if (hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating Responses API streaming data.\n *\n * Used during streaming to collect text deltas, tool call fragments,\n * and usage statistics before building the final LLMResponse.\n */\nexport interface ResponsesStreamState {\n /** Response ID from the created event */\n id: string;\n /** Model identifier from the response */\n model: string;\n /** Map of output index to accumulated text content */\n textByIndex: Map<number, string>;\n /** Map of output index to accumulated reasoning text */\n reasoningByIndex: Map<number, string>;\n /** Map of output index to accumulated tool call data */\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\n /** Map of output index to generated image data (base64) */\n images: Map<number, string>;\n /** Current response status */\n status: string;\n /** Input token count from usage */\n inputTokens: number;\n /** Output token count from usage */\n outputTokens: number;\n /** Number of tokens read from cache */\n cacheReadTokens: number;\n /** Whether a refusal was encountered */\n hadRefusal: boolean;\n /** Serialized reasoning item for multi-turn context preservation (includes encrypted_content) */\n reasoningEncryptedContent?: string;\n}\n\n/**\n * Creates an empty stream state object for accumulating Responses API streaming data.\n *\n * @returns A new ResponsesStreamState with all fields initialized\n */\nexport function createStreamState(): ResponsesStreamState {\n return {\n id: '',\n model: '',\n textByIndex: new Map(),\n reasoningByIndex: new Map(),\n toolCalls: new Map(),\n images: new Map(),\n status: 'in_progress',\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n hadRefusal: false,\n };\n}\n\n/**\n * Transforms an OpenRouter Responses API streaming event into UPP StreamEvents.\n *\n * Handles the various Responses API event types including response lifecycle events,\n * output item events, content deltas, function call arguments, and reasoning deltas.\n * Updates the provided state object with accumulated data.\n *\n * @param event - The OpenRouter Responses API streaming event to process\n * @param state - The mutable state object to update with event data\n * @returns Array of UPP StreamEvents generated from this event\n */\nexport function transformStreamEvent(\n event: OpenRouterResponsesStreamEvent,\n state: ResponsesStreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n switch (event.type) {\n case 'response.created':\n state.id = event.response.id;\n state.model = event.response.model;\n events.push({ type: StreamEventType.MessageStart, index: 0, delta: {} });\n break;\n\n case 'response.in_progress':\n state.status = 'in_progress';\n break;\n\n case 'response.completed':\n case 'response.done':\n state.status = 'completed';\n if (event.response?.usage) {\n state.inputTokens = event.response.usage.input_tokens;\n state.outputTokens = event.response.usage.output_tokens;\n state.cacheReadTokens = event.response.usage.input_tokens_details?.cached_tokens ?? 0;\n }\n if (event.response?.output) {\n for (let i = 0; i < event.response.output.length; i++) {\n const item = event.response.output[i];\n if (item && item.type === 'function_call') {\n const functionCall = item;\n const existing = state.toolCalls.get(i) ?? { arguments: '' };\n existing.itemId = functionCall.id ?? existing.itemId;\n existing.callId = functionCall.call_id ?? existing.callId;\n existing.name = functionCall.name ?? existing.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(i, existing);\n }\n }\n }\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n break;\n\n case 'response.failed':\n state.status = 'failed';\n events.push({ type: StreamEventType.MessageStop, index: 0, delta: {} });\n break;\n\n case 'response.output_item.added':\n if (event.item.type === 'function_call') {\n const functionCall = event.item;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n }\n events.push({\n type: StreamEventType.ContentBlockStart,\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.output_item.done':\n if (event.item.type === 'function_call') {\n const functionCall = event.item;\n const existing = state.toolCalls.get(event.output_index) ?? {\n arguments: '',\n };\n existing.itemId = functionCall.id;\n existing.callId = functionCall.call_id;\n existing.name = functionCall.name;\n if (functionCall.arguments) {\n existing.arguments = functionCall.arguments;\n }\n state.toolCalls.set(event.output_index, existing);\n } else if (event.item.type === 'message') {\n // Extract text from completed message item (may not have incremental deltas)\n const messageItem = event.item;\n for (const content of messageItem.content || []) {\n if (content.type === 'output_text') {\n const existingText = state.textByIndex.get(event.output_index) ?? '';\n if (!existingText && content.text) {\n // Only use done text if we didn't get incremental deltas\n state.textByIndex.set(event.output_index, content.text);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: content.text },\n });\n }\n }\n }\n } else if (event.item.type === 'image_generation_call') {\n const imageGen = event.item;\n if (imageGen.result) {\n state.images.set(event.output_index, imageGen.result);\n }\n } else if (event.item.type === 'reasoning') {\n // Capture full reasoning item for multi-turn context preservation (must be passed back as-is)\n const reasoningItem = event.item as OpenRouterResponsesReasoningOutput;\n state.reasoningEncryptedContent = JSON.stringify({\n id: reasoningItem.id,\n summary: reasoningItem.summary,\n encrypted_content: reasoningItem.encrypted_content,\n });\n }\n events.push({\n type: StreamEventType.ContentBlockStop,\n index: event.output_index,\n delta: {},\n });\n break;\n\n case 'response.content_part.delta':\n case 'response.output_text.delta': {\n const textDelta = (event as { delta: string }).delta;\n const currentText = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentText + textDelta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: textDelta },\n });\n break;\n }\n\n case 'response.output_text.done':\n case 'response.content_part.done':\n if ('text' in event) {\n state.textByIndex.set(event.output_index, (event as { text: string }).text);\n }\n break;\n\n case 'response.refusal.delta': {\n state.hadRefusal = true;\n const currentRefusal = state.textByIndex.get(event.output_index) ?? '';\n state.textByIndex.set(event.output_index, currentRefusal + event.delta);\n events.push({\n type: StreamEventType.TextDelta,\n index: event.output_index,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'response.refusal.done':\n state.hadRefusal = true;\n state.textByIndex.set(event.output_index, event.refusal);\n break;\n\n case 'response.function_call_arguments.delta': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id && !toolCall.itemId) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id && !toolCall.callId) {\n toolCall.callId = event.call_id;\n }\n toolCall.arguments += event.delta;\n events.push({\n type: StreamEventType.ToolCallDelta,\n index: event.output_index,\n delta: {\n toolCallId: toolCall.callId ?? toolCall.itemId ?? '',\n toolName: toolCall.name,\n argumentsJson: event.delta,\n },\n });\n break;\n }\n\n case 'response.function_call_arguments.done': {\n let toolCall = state.toolCalls.get(event.output_index);\n if (!toolCall) {\n toolCall = { arguments: '' };\n state.toolCalls.set(event.output_index, toolCall);\n }\n if (event.item_id) {\n toolCall.itemId = event.item_id;\n }\n if (event.call_id) {\n toolCall.callId = event.call_id;\n }\n toolCall.name = event.name;\n toolCall.arguments = event.arguments;\n break;\n }\n\n case 'response.reasoning.delta': {\n // Accumulate reasoning text\n const currentReasoning = state.reasoningByIndex.get(0) ?? '';\n state.reasoningByIndex.set(0, currentReasoning + event.delta);\n // Emit reasoning as a reasoning_delta event\n events.push({\n type: StreamEventType.ReasoningDelta,\n index: 0,\n delta: { text: event.delta },\n });\n break;\n }\n\n case 'error':\n break;\n\n default:\n break;\n }\n\n return events;\n}\n\n/**\n * Builds the final LLMResponse from accumulated Responses API streaming state.\n *\n * Constructs the complete response after streaming has finished, including\n * the assistant message, tool calls, usage statistics, and stop reason.\n *\n * @param state - The accumulated stream state\n * @returns Complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: ResponsesStreamState): LLMResponse {\n const reasoningContent: ReasoningBlock[] = [];\n const textContent: AssistantContent[] = [];\n let structuredData: unknown;\n\n // Add reasoning content if present\n for (const [, reasoning] of state.reasoningByIndex) {\n if (reasoning) {\n reasoningContent.push({ type: 'reasoning', text: reasoning });\n }\n }\n\n for (const [, text] of state.textByIndex) {\n if (text) {\n textContent.push({ type: 'text', text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n }\n }\n\n for (const [, imageData] of state.images) {\n if (imageData) {\n textContent.push({\n type: 'image',\n mimeType: 'image/png',\n source: { type: 'base64', data: imageData },\n } as ImageBlock);\n }\n }\n\n // Combine reasoning before text content (matches other providers' pattern)\n const content: AssistantContent[] = [...reasoningContent, ...textContent];\n\n const toolCalls: ToolCall[] = [];\n const functionCallItems: Array<{\n id: string;\n call_id: string;\n name: string;\n arguments: string;\n }> = [];\n for (const [, toolCall] of state.toolCalls) {\n let args: Record<string, unknown> = {};\n if (toolCall.arguments) {\n try {\n args = JSON.parse(toolCall.arguments);\n } catch {\n // Invalid JSON arguments - use empty object as fallback\n }\n }\n const itemId = toolCall.itemId ?? '';\n const callId = toolCall.callId ?? toolCall.itemId ?? '';\n const name = toolCall.name ?? '';\n toolCalls.push({\n toolCallId: callId,\n toolName: name,\n arguments: args,\n });\n\n if (itemId && callId && name) {\n functionCallItems.push({\n id: itemId,\n call_id: callId,\n name,\n arguments: toolCall.arguments,\n });\n }\n }\n\n const responseId = state.id || generateId();\n const message = new AssistantMessage(\n content,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: responseId,\n metadata: {\n openrouter: {\n model: state.model,\n status: state.status,\n // Store response_id for multi-turn tool calling\n response_id: responseId,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\n // Store encrypted reasoning content for multi-turn context (stateless mode)\n reasoningEncryptedContent: state.reasoningEncryptedContent,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n let stopReason = 'end_turn';\n if (state.status === 'completed') {\n stopReason = toolCalls.length > 0 ? 'tool_use' : 'end_turn';\n } else if (state.status === 'failed') {\n stopReason = 'error';\n }\n if (state.hadRefusal && stopReason !== 'error') {\n stopReason = 'content_filter';\n }\n\n return {\n message,\n usage,\n stopReason,\n data: structuredData,\n };\n}\n","/**\n * OpenRouter Responses API LLM handler.\n *\n * This module implements the LLMHandler interface for OpenRouter's Responses API,\n * which is currently in beta and provides additional features like reasoning support.\n *\n * @module llm.responses\n */\n\nimport type { BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { LLMHandler } from '../../types/provider.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\nimport { toError } from '../../utils/error.ts';\nimport type { OpenRouterResponsesParams, OpenRouterResponsesResponse, OpenRouterResponsesStreamEvent, OpenRouterResponseErrorEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.responses.ts';\n\n/** Base URL for OpenRouter's Responses API endpoint (beta). */\nconst OPENROUTER_RESPONSES_API_URL = 'https://openrouter.ai/api/v1/responses';\n\n/**\n * Capability flags for the OpenRouter Responses API.\n *\n * The Responses API supports streaming, function calling (tools), structured JSON output,\n * image inputs, document/PDF inputs, audio inputs, video inputs, and reasoning models.\n */\nconst OPENROUTER_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n documentInput: true,\n imageOutput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Creates an LLM handler for OpenRouter's Responses API (beta).\n *\n * The Responses API provides a different interface than Chat Completions,\n * with features like reasoning effort configuration and different output formats.\n *\n * @returns An LLMHandler configured for OpenRouter Responses API\n *\n * @example\n * ```typescript\n * const handler = createResponsesLLMHandler();\n * handler._setProvider(provider);\n * const model = handler.bind('openai/gpt-4o');\n * const response = await model.complete(request);\n * ```\n */\nexport function createResponsesLLMHandler(): LLMHandler<OpenRouterResponsesParams> {\n let providerRef: LLMProvider<OpenRouterResponsesParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<OpenRouterResponsesParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<OpenRouterResponsesParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider() or have _setProvider called.',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n const model: BoundLLMModel<OpenRouterResponsesParams> = {\n modelId,\n capabilities: OPENROUTER_CAPABILITIES,\n\n get provider(): LLMProvider<OpenRouterResponsesParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<OpenRouterResponsesParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n const data = await parseJsonResponse<OpenRouterResponsesResponse>(response, 'openrouter', 'llm');\n\n // Check for error in response\n if (data.status === 'failed') {\n const message = data.error?.message ?? 'Provider returned a failed response.';\n throw new UPPError(\n message,\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n }\n\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<OpenRouterResponsesParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_RESPONSES_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n Accept: 'text/event-stream',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'openrouter', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n // Skip [DONE] marker\n if (data === '[DONE]') {\n continue;\n }\n\n // Check for OpenRouter error event\n if (typeof data === 'object' && data !== null) {\n const event = data as OpenRouterResponsesStreamEvent;\n\n // Check for error event\n if (event.type === 'error') {\n const errorEvent = event as OpenRouterResponseErrorEvent;\n const error = new UPPError(\n errorEvent.error.message,\n ErrorCode.ProviderError,\n 'openrouter',\n ModalityType.LLM\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvents = transformStreamEvent(event, state);\n for (const uppEvent of uppEvents) {\n yield uppEvent;\n }\n }\n }\n\n // Build final response\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n const err = toError(error);\n responseReject(err);\n throw err;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview OpenRouter Embeddings API Handler\n *\n * This module implements the embedding handler for OpenRouter's embeddings API.\n * OpenRouter provides access to multiple embedding providers through an OpenAI-compatible endpoint.\n *\n * @see {@link https://openrouter.ai/docs/api/reference/embeddings OpenRouter Embeddings API Reference}\n * @module providers/openrouter/embed\n */\n\nimport type {\n EmbeddingHandler,\n BoundEmbeddingModel,\n EmbeddingRequest,\n EmbeddingResponse,\n EmbeddingProvider,\n} from '../../types/provider.ts';\nimport { UPPError, ErrorCode, ModalityType } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch } from '../../http/fetch.ts';\nimport { parseJsonResponse } from '../../http/json.ts';\n\n/** Base URL for OpenRouter's Embeddings API endpoint */\nconst OPENROUTER_EMBEDDINGS_API_URL = 'https://openrouter.ai/api/v1/embeddings';\n\n/**\n * OpenRouter embedding parameters.\n * Passed through unchanged to the API.\n */\nexport interface OpenRouterEmbedParams {\n /** Output dimensions (model-dependent) */\n dimensions?: number;\n /** Encoding format: 'float' or 'base64' */\n encoding_format?: 'float' | 'base64';\n /** A unique identifier representing your end-user */\n user?: string;\n /** Input type hint for some models */\n input_type?: string;\n}\n\n/**\n * OpenRouter embeddings API response structure (OpenAI-compatible).\n */\ninterface OpenRouterEmbeddingsResponse {\n id: string;\n object: 'list';\n data: Array<{\n index: number;\n embedding: number[] | string;\n type: 'embedding';\n }>;\n model: string;\n usage: {\n prompt_tokens: number;\n total_tokens: number;\n cost?: number;\n };\n}\n\n/**\n * Get default dimensions for a model.\n */\nfunction getDefaultDimensions(modelId: string): number {\n if (modelId.includes('text-embedding-3-large')) {\n return 3072;\n }\n if (modelId.includes('text-embedding-3-small') || modelId.includes('ada-002')) {\n return 1536;\n }\n if (modelId.includes('gemini-embedding')) {\n return 3072;\n }\n return 1536;\n}\n\n/**\n * Creates an embedding handler for OpenRouter's Embeddings API.\n *\n * @returns An embedding handler configured for OpenRouter\n *\n * @example\n * ```typescript\n * const handler = createEmbeddingHandler();\n * const model = handler.bind('openai/text-embedding-3-large');\n *\n * const response = await model.embed({\n * inputs: ['Hello world'],\n * config: { apiKey: 'sk-or-...' }\n * });\n * ```\n */\nexport function createEmbeddingHandler(): EmbeddingHandler<OpenRouterEmbedParams> {\n let providerRef: EmbeddingProvider<OpenRouterEmbedParams> | null = null;\n\n return {\n supportedInputs: ['text'],\n\n _setProvider(provider: EmbeddingProvider<OpenRouterEmbedParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundEmbeddingModel<OpenRouterEmbedParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.Embedding\n );\n }\n\n const model: BoundEmbeddingModel<OpenRouterEmbedParams> = {\n modelId,\n maxBatchSize: 2048,\n maxInputLength: 8191,\n dimensions: getDefaultDimensions(modelId),\n\n get provider(): EmbeddingProvider<OpenRouterEmbedParams> {\n return providerRef!;\n },\n\n async embed(request: EmbeddingRequest<OpenRouterEmbedParams>): Promise<EmbeddingResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'OPENROUTER_API_KEY',\n 'openrouter',\n 'embedding'\n );\n\n const baseUrl = request.config.baseUrl ?? OPENROUTER_EMBEDDINGS_API_URL;\n\n // Transform inputs to strings\n const inputTexts = request.inputs.map((input) => {\n if (typeof input === 'string') {\n return input;\n }\n if ('text' in input) {\n return input.text;\n }\n throw new UPPError(\n 'OpenRouter embeddings only support text input',\n ErrorCode.InvalidRequest,\n 'openrouter',\n ModalityType.Embedding\n );\n });\n\n // Build request body - params pass through unchanged\n const body: Record<string, unknown> = {\n model: modelId,\n input: inputTexts,\n };\n\n // Pass through OpenRouter-specific params\n if (request.params?.dimensions !== undefined) {\n body.dimensions = request.params.dimensions;\n }\n if (request.params?.encoding_format !== undefined) {\n body.encoding_format = request.params.encoding_format;\n }\n if (request.params?.user !== undefined) {\n body.user = request.params.user;\n }\n if (request.params?.input_type !== undefined) {\n body.input_type = request.params.input_type;\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n };\n\n // Merge custom headers\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(baseUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n }, request.config, 'openrouter', 'embedding');\n\n const data = await parseJsonResponse<OpenRouterEmbeddingsResponse>(response, 'openrouter', 'embedding');\n\n // Return EmbeddingResponse - vector is floats or base64 string\n return {\n embeddings: data.data.map((d) => ({\n vector: d.embedding,\n index: d.index,\n })),\n usage: { totalTokens: data.usage.total_tokens },\n metadata: data.usage.cost !== undefined ? { cost: data.usage.cost } : undefined,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import type { Provider } from '../../types/provider.ts';\nimport { createProvider } from '../../core/provider.ts';\nimport type { LLMHandlerResolver } from '../../core/provider-handlers.ts';\nimport { createCompletionsLLMHandler } from './llm.completions.ts';\nimport { createResponsesLLMHandler } from './llm.responses.ts';\nimport { createEmbeddingHandler } from './embed.ts';\n\n/**\n * Configuration options for creating an OpenRouter model reference.\n *\n * OpenRouter supports two distinct APIs:\n * - Chat Completions API: Stable, production-ready, supports most models\n * - Responses API: Beta, supports advanced features like reasoning\n */\nexport interface OpenRouterProviderOptions {\n /**\n * Which OpenRouter API to use.\n *\n * - `'completions'`: Chat Completions API (default, recommended for production)\n * - `'responses'`: Responses API (beta, supports reasoning models)\n */\n api?: 'completions' | 'responses';\n}\n\n/**\n * OpenRouter provider interface with configurable API mode.\n *\n * OpenRouter is a unified API that provides access to hundreds of AI models\n * through a single endpoint, including models from OpenAI, Anthropic, Google,\n * Meta, Mistral, and many others.\n *\n * @example Using the Chat Completions API (default)\n * ```typescript\n * const model = openrouter('openai/gpt-4o');\n * ```\n *\n * @example Using the Responses API (beta)\n * ```typescript\n * const model = openrouter('openai/gpt-4o', { api: 'responses' });\n * ```\n *\n * @example Using Anthropic models\n * ```typescript\n * const model = openrouter('anthropic/claude-3.5-sonnet', { api: 'completions' });\n * ```\n */\n/**\n * Type alias for the OpenRouter provider with its options.\n */\nexport type OpenRouterProvider = Provider<OpenRouterProviderOptions>;\n\n/**\n * LLM handler resolver for OpenRouter's dual API support.\n *\n * Dynamically selects between Completions and Responses API handlers\n * based on the options stored on the ModelReference. This eliminates\n * race conditions from shared mutable state.\n */\nconst llmResolver: LLMHandlerResolver<OpenRouterProviderOptions> = {\n handlers: {\n completions: createCompletionsLLMHandler(),\n responses: createResponsesLLMHandler(),\n },\n defaultMode: 'completions',\n getMode: (options) => options?.api ?? 'completions',\n};\n\n/**\n * OpenRouter provider singleton.\n *\n * OpenRouter is a unified API that provides access to hundreds of AI models\n * through a single endpoint, including models from OpenAI, Anthropic, Google,\n * Meta, Mistral, and many others.\n *\n * Supports both the Chat Completions API (default) and Responses API (beta).\n *\n * @example Basic usage with Chat Completions API\n * ```typescript\n * import { openrouter } from './providers/openrouter';\n * import { llm } from './core/llm';\n *\n * const model = llm({\n * model: openrouter('openai/gpt-4o'),\n * params: { max_tokens: 1000 }\n * });\n *\n * const turn = await model.generate('Hello!');\n * console.log(turn.response.text);\n * ```\n *\n * @example Using the Responses API (beta)\n * ```typescript\n * const betaModel = llm({\n * model: openrouter('openai/gpt-4o', { api: 'responses' }),\n * params: { max_output_tokens: 1000 }\n * });\n * ```\n *\n * @example Model routing and fallback configuration\n * ```typescript\n * const routedModel = llm({\n * model: openrouter('openai/gpt-4o'),\n * params: {\n * max_tokens: 1000,\n * models: ['openai/gpt-4o', 'anthropic/claude-3.5-sonnet'],\n * route: 'fallback',\n * provider: {\n * allow_fallbacks: true,\n * require_parameters: true,\n * },\n * }\n * });\n * ```\n *\n * @see {@link https://openrouter.ai/docs | OpenRouter Documentation}\n */\nexport const openrouter = createProvider<OpenRouterProviderOptions>({\n name: 'openrouter',\n version: '1.0.0',\n handlers: {\n llm: llmResolver,\n embedding: createEmbeddingHandler(),\n },\n}) as OpenRouterProvider;\n\nexport type {\n OpenRouterCompletionsParams,\n OpenRouterResponsesParams,\n OpenRouterConfig,\n OpenRouterAPIMode,\n OpenRouterModelOptions,\n OpenRouterModelReference,\n OpenRouterProviderPreferences,\n OpenRouterImageConfig,\n OpenRouterHeaders,\n} from './types.ts';\n\nexport type { OpenRouterEmbedParams } from './embed.ts';\n"],"mappings":"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","names":["transformRequest","transformTool","normalizeSystem","transformMessage","isValidCacheControl","filterValidContent","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState","OPENROUTER_CAPABILITIES","transformRequest","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState"]}
|