@providerprotocol/ai 0.0.13 → 0.0.15
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 +427 -2
- package/dist/anthropic/index.js +142 -13
- package/dist/anthropic/index.js.map +1 -1
- package/dist/google/index.d.ts +480 -7
- package/dist/google/index.js +104 -26
- package/dist/google/index.js.map +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/index.d.ts +7 -5
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/ollama/index.d.ts +1 -1
- package/dist/ollama/index.js +14 -0
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.js +48 -16
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +1 -1
- package/dist/openrouter/index.js +48 -16
- package/dist/openrouter/index.js.map +1 -1
- package/dist/{provider-mKkz7Q9U.d.ts → provider-Bi0nyNhA.d.ts} +17 -0
- package/dist/{retry-Dh70lgr0.d.ts → retry-BatS2hjD.d.ts} +1 -1
- package/dist/xai/index.d.ts +368 -6
- package/dist/xai/index.js +121 -26
- package/dist/xai/index.js.map +1 -1
- package/package.json +4 -3
package/dist/openrouter/index.js
CHANGED
|
@@ -436,14 +436,22 @@ function createCompletionsLLMHandler() {
|
|
|
436
436
|
);
|
|
437
437
|
const baseUrl = request.config.baseUrl ?? OPENROUTER_API_URL;
|
|
438
438
|
const body = transformRequest(request, modelId);
|
|
439
|
+
const headers = {
|
|
440
|
+
"Content-Type": "application/json",
|
|
441
|
+
Authorization: `Bearer ${apiKey}`
|
|
442
|
+
};
|
|
443
|
+
if (request.config.headers) {
|
|
444
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
445
|
+
if (value !== void 0) {
|
|
446
|
+
headers[key] = value;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
439
450
|
const response = await doFetch(
|
|
440
451
|
baseUrl,
|
|
441
452
|
{
|
|
442
453
|
method: "POST",
|
|
443
|
-
headers
|
|
444
|
-
"Content-Type": "application/json",
|
|
445
|
-
Authorization: `Bearer ${apiKey}`
|
|
446
|
-
},
|
|
454
|
+
headers,
|
|
447
455
|
body: JSON.stringify(body),
|
|
448
456
|
signal: request.signal
|
|
449
457
|
},
|
|
@@ -474,14 +482,22 @@ function createCompletionsLLMHandler() {
|
|
|
474
482
|
const body = transformRequest(request, modelId);
|
|
475
483
|
body.stream = true;
|
|
476
484
|
body.stream_options = { include_usage: true };
|
|
485
|
+
const headers = {
|
|
486
|
+
"Content-Type": "application/json",
|
|
487
|
+
Authorization: `Bearer ${apiKey}`
|
|
488
|
+
};
|
|
489
|
+
if (request.config.headers) {
|
|
490
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
491
|
+
if (value !== void 0) {
|
|
492
|
+
headers[key] = value;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
477
496
|
const response = await doStreamFetch(
|
|
478
497
|
baseUrl,
|
|
479
498
|
{
|
|
480
499
|
method: "POST",
|
|
481
|
-
headers
|
|
482
|
-
"Content-Type": "application/json",
|
|
483
|
-
Authorization: `Bearer ${apiKey}`
|
|
484
|
-
},
|
|
500
|
+
headers,
|
|
485
501
|
body: JSON.stringify(body),
|
|
486
502
|
signal: request.signal
|
|
487
503
|
},
|
|
@@ -1126,14 +1142,22 @@ function createResponsesLLMHandler() {
|
|
|
1126
1142
|
);
|
|
1127
1143
|
const baseUrl = request.config.baseUrl ?? OPENROUTER_RESPONSES_API_URL;
|
|
1128
1144
|
const body = transformRequest2(request, modelId);
|
|
1145
|
+
const headers = {
|
|
1146
|
+
"Content-Type": "application/json",
|
|
1147
|
+
Authorization: `Bearer ${apiKey}`
|
|
1148
|
+
};
|
|
1149
|
+
if (request.config.headers) {
|
|
1150
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
1151
|
+
if (value !== void 0) {
|
|
1152
|
+
headers[key] = value;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1129
1156
|
const response = await doFetch(
|
|
1130
1157
|
baseUrl,
|
|
1131
1158
|
{
|
|
1132
1159
|
method: "POST",
|
|
1133
|
-
headers
|
|
1134
|
-
"Content-Type": "application/json",
|
|
1135
|
-
Authorization: `Bearer ${apiKey}`
|
|
1136
|
-
},
|
|
1160
|
+
headers,
|
|
1137
1161
|
body: JSON.stringify(body),
|
|
1138
1162
|
signal: request.signal
|
|
1139
1163
|
},
|
|
@@ -1171,14 +1195,22 @@ function createResponsesLLMHandler() {
|
|
|
1171
1195
|
const baseUrl = request.config.baseUrl ?? OPENROUTER_RESPONSES_API_URL;
|
|
1172
1196
|
const body = transformRequest2(request, modelId);
|
|
1173
1197
|
body.stream = true;
|
|
1198
|
+
const headers = {
|
|
1199
|
+
"Content-Type": "application/json",
|
|
1200
|
+
Authorization: `Bearer ${apiKey}`
|
|
1201
|
+
};
|
|
1202
|
+
if (request.config.headers) {
|
|
1203
|
+
for (const [key, value] of Object.entries(request.config.headers)) {
|
|
1204
|
+
if (value !== void 0) {
|
|
1205
|
+
headers[key] = value;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1174
1209
|
const response = await doStreamFetch(
|
|
1175
1210
|
baseUrl,
|
|
1176
1211
|
{
|
|
1177
1212
|
method: "POST",
|
|
1178
|
-
headers
|
|
1179
|
-
"Content-Type": "application/json",
|
|
1180
|
-
Authorization: `Bearer ${apiKey}`
|
|
1181
|
-
},
|
|
1213
|
+
headers,
|
|
1182
1214
|
body: JSON.stringify(body),
|
|
1183
1215
|
signal: request.signal
|
|
1184
1216
|
},
|
|
@@ -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/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 type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenRouterCompletionsParams,\n OpenRouterCompletionsRequest,\n OpenRouterCompletionsMessage,\n OpenRouterUserContent,\n OpenRouterCompletionsTool,\n OpenRouterCompletionsResponse,\n OpenRouterCompletionsStreamChunk,\n OpenRouterToolCall,\n OpenRouterCacheControl,\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) {\n // Pass through directly - OpenRouter supports both string and array formats\n result.push({\n role: 'system',\n content: system as string | Array<{type: 'text'; text: string; cache_control?: {type: 'ephemeral'; ttl?: '1h'}}>,\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\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 const textContent = validContent\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 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 textContent: TextBlock[] = [];\n let structuredData: unknown;\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 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 message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openrouter: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\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 * 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 /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: 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 toolCalls: new Map(),\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: 'message_start', 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: 'text_delta',\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: 'tool_call_delta',\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.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: 'message_stop', 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 textContent: TextBlock[] = [];\n let structuredData: unknown;\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 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 message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openrouter: {\n model: state.model,\n finish_reason: state.finishReason,\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 } 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 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 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 'INVALID_REQUEST',\n 'openrouter',\n '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 response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n const data = (await response.json()) as OpenRouterCompletionsResponse;\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 response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 'PROVIDER_ERROR',\n 'openrouter',\n '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 'PROVIDER_ERROR',\n 'openrouter',\n '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 responseReject(error as Error);\n throw error;\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 type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenRouterResponsesParams,\n OpenRouterResponsesRequest,\n OpenRouterResponsesInputItem,\n OpenRouterResponsesContentPart,\n OpenRouterResponsesTool,\n OpenRouterResponsesResponse,\n OpenRouterResponsesStreamEvent,\n OpenRouterResponsesOutputItem,\n OpenRouterResponsesMessageOutput,\n OpenRouterResponsesFunctionCallOutput,\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) {\n // Pass through directly - OpenRouter supports both string and array formats\n // Array format enables cache_control for Anthropic/Gemini models\n result.push({\n type: 'message',\n role: 'system',\n content: system,\n } as OpenRouterResponsesInputItem);\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\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 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 ?? `msg_${Date.now()}`;\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 | { functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }> }\n | undefined;\n const functionCallItems = openrouterMeta?.functionCallItems;\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 textContent: TextBlock[] = [];\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\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item as OpenRouterResponsesMessageOutput;\n for (const content of messageItem.content) {\n if (content.type === 'output_text') {\n textContent.push({ type: 'text', text: content.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(content.text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n } else if (content.type === 'refusal') {\n textContent.push({ type: 'text', text: content.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item as OpenRouterResponsesFunctionCallOutput;\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 }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openrouter: {\n model: data.model,\n status: data.status,\n // Store response_id for multi-turn tool calling\n response_id: data.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\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 tool call data */\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\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}\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 toolCalls: 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: 'message_start', 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 as OpenRouterResponsesFunctionCallOutput;\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: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.failed':\n state.status = 'failed';\n events.push({ type: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.output_item.added':\n if (event.item.type === 'function_call') {\n const functionCall = event.item as OpenRouterResponsesFunctionCallOutput;\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: 'content_block_start',\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 as OpenRouterResponsesFunctionCallOutput;\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 as OpenRouterResponsesMessageOutput;\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: 'text_delta',\n index: event.output_index,\n delta: { text: content.text },\n });\n }\n }\n }\n }\n events.push({\n type: 'content_block_stop',\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: 'text_delta',\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: 'text_delta',\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: 'tool_call_delta',\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 // Emit reasoning as a reasoning_delta event\n events.push({\n type: 'reasoning_delta',\n index: 0,\n delta: { text: event.delta },\n });\n break;\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 textContent: TextBlock[] = [];\n let structuredData: unknown;\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 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 message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openrouter: {\n model: state.model,\n status: state.status,\n // Store response_id for multi-turn tool calling\n response_id: state.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : 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 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 } 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 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 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 'INVALID_REQUEST',\n 'openrouter',\n '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 response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'openrouter',\n 'llm'\n );\n\n const data = (await response.json()) as OpenRouterResponsesResponse;\n\n // Check for error in response\n if (data.status === 'failed' && data.error) {\n throw new UPPError(\n data.error.message,\n 'PROVIDER_ERROR',\n 'openrouter',\n '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 response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n },\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 'PROVIDER_ERROR',\n 'openrouter',\n '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 'PROVIDER_ERROR',\n 'openrouter',\n '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 responseReject(error as Error);\n throw error;\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","import type {\n Provider,\n ModelReference,\n LLMHandler,\n LLMProvider,\n} from '../../types/provider.ts';\nimport { createCompletionsLLMHandler } from './llm.completions.ts';\nimport { createResponsesLLMHandler } from './llm.responses.ts';\nimport type { OpenRouterCompletionsParams, OpenRouterResponsesParams } from './types.ts';\n\n/**\n * Union type for both Completions and Responses API parameter types.\n * Used internally to type the modalities handler.\n */\ntype OpenRouterLLMParamsUnion = OpenRouterCompletionsParams | OpenRouterResponsesParams;\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 */\nexport interface OpenRouterProvider extends Provider<OpenRouterProviderOptions> {\n /**\n * Creates a model reference for the specified model ID.\n *\n * @param modelId - The OpenRouter model identifier in `provider/model` format\n * (e.g., 'openai/gpt-4o', 'anthropic/claude-3.5-sonnet',\n * 'meta-llama/llama-3.1-70b-instruct')\n * @param options - Optional configuration including API selection\n * @returns A model reference that can be passed to llm()\n */\n (modelId: string, options?: OpenRouterProviderOptions): ModelReference<OpenRouterProviderOptions>;\n\n /** Provider identifier. Always 'openrouter'. */\n readonly name: 'openrouter';\n\n /** Semantic version of this provider implementation. */\n readonly version: string;\n\n /**\n * Supported modalities for this provider.\n * OpenRouter currently only supports LLM (text generation).\n */\n readonly modalities: {\n llm: LLMHandler<OpenRouterLLMParamsUnion>;\n };\n}\n\n/**\n * Factory function to create the OpenRouter provider singleton.\n *\n * Creates both Completions and Responses API handlers and manages\n * API mode switching based on the options passed when creating model references.\n *\n * @returns A fully configured OpenRouter provider instance\n * @internal\n */\nfunction createOpenRouterProvider(): OpenRouterProvider {\n let currentApiMode: 'completions' | 'responses' = 'completions';\n\n const completionsHandler = createCompletionsLLMHandler();\n const responsesHandler = createResponsesLLMHandler();\n\n const fn = function (\n modelId: string,\n options?: OpenRouterProviderOptions\n ): ModelReference<OpenRouterProviderOptions> {\n const apiMode = options?.api ?? 'completions';\n currentApiMode = apiMode;\n return { modelId, provider };\n };\n\n const modalities = {\n get llm(): LLMHandler<OpenRouterLLMParamsUnion> {\n return currentApiMode === 'responses'\n ? (responsesHandler as unknown as LLMHandler<OpenRouterLLMParamsUnion>)\n : (completionsHandler as unknown as LLMHandler<OpenRouterLLMParamsUnion>);\n },\n };\n\n Object.defineProperties(fn, {\n name: {\n value: 'openrouter',\n writable: false,\n configurable: true,\n },\n version: {\n value: '1.0.0',\n writable: false,\n configurable: true,\n },\n modalities: {\n value: modalities,\n writable: false,\n configurable: true,\n },\n });\n\n const provider = fn as OpenRouterProvider;\n\n completionsHandler._setProvider?.(provider as unknown as LLMProvider<OpenRouterCompletionsParams>);\n responsesHandler._setProvider?.(provider as unknown as LLMProvider<OpenRouterResponsesParams>);\n\n return provider;\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 = createOpenRouterProvider();\n\nexport type {\n OpenRouterCompletionsParams,\n OpenRouterResponsesParams,\n OpenRouterConfig,\n OpenRouterAPIMode,\n OpenRouterModelOptions,\n OpenRouterModelReference,\n OpenRouterProviderPreferences,\n} from './types.ts';\n"],"mappings":"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","names":["transformRequest","transformTool","transformMessage","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/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 type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenRouterCompletionsParams,\n OpenRouterCompletionsRequest,\n OpenRouterCompletionsMessage,\n OpenRouterUserContent,\n OpenRouterCompletionsTool,\n OpenRouterCompletionsResponse,\n OpenRouterCompletionsStreamChunk,\n OpenRouterToolCall,\n OpenRouterCacheControl,\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) {\n // Pass through directly - OpenRouter supports both string and array formats\n result.push({\n role: 'system',\n content: system as string | Array<{type: 'text'; text: string; cache_control?: {type: 'ephemeral'; ttl?: '1h'}}>,\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\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 const textContent = validContent\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 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 textContent: TextBlock[] = [];\n let structuredData: unknown;\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 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 message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openrouter: {\n model: data.model,\n finish_reason: choice.finish_reason,\n system_fingerprint: data.system_fingerprint,\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 * 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 /** Map of tool call index to accumulated tool call data */\n toolCalls: Map<number, { id: string; name: string; arguments: 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 toolCalls: new Map(),\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: 'message_start', 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: 'text_delta',\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: 'tool_call_delta',\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.finish_reason) {\n state.finishReason = choice.finish_reason;\n events.push({ type: 'message_stop', 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 textContent: TextBlock[] = [];\n let structuredData: unknown;\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 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 message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openrouter: {\n model: state.model,\n finish_reason: state.finishReason,\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 } 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 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 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 'INVALID_REQUEST',\n 'openrouter',\n '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 response.json()) as OpenRouterCompletionsResponse;\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 };\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 'PROVIDER_ERROR',\n 'openrouter',\n '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 'PROVIDER_ERROR',\n 'openrouter',\n '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 responseReject(error as Error);\n throw error;\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 type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n OpenRouterResponsesParams,\n OpenRouterResponsesRequest,\n OpenRouterResponsesInputItem,\n OpenRouterResponsesContentPart,\n OpenRouterResponsesTool,\n OpenRouterResponsesResponse,\n OpenRouterResponsesStreamEvent,\n OpenRouterResponsesOutputItem,\n OpenRouterResponsesMessageOutput,\n OpenRouterResponsesFunctionCallOutput,\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) {\n // Pass through directly - OpenRouter supports both string and array formats\n // Array format enables cache_control for Anthropic/Gemini models\n result.push({\n type: 'message',\n role: 'system',\n content: system,\n } as OpenRouterResponsesInputItem);\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\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 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 ?? `msg_${Date.now()}`;\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 | { functionCallItems?: Array<{ id: string; call_id: string; name: string; arguments: string }> }\n | undefined;\n const functionCallItems = openrouterMeta?.functionCallItems;\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 textContent: TextBlock[] = [];\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\n for (const item of data.output) {\n if (item.type === 'message') {\n const messageItem = item as OpenRouterResponsesMessageOutput;\n for (const content of messageItem.content) {\n if (content.type === 'output_text') {\n textContent.push({ type: 'text', text: content.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(content.text);\n } catch {\n // Content is not JSON - acceptable for non-structured responses\n }\n }\n } else if (content.type === 'refusal') {\n textContent.push({ type: 'text', text: content.refusal });\n hadRefusal = true;\n }\n }\n } else if (item.type === 'function_call') {\n const functionCall = item as OpenRouterResponsesFunctionCallOutput;\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 }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n openrouter: {\n model: data.model,\n status: data.status,\n // Store response_id for multi-turn tool calling\n response_id: data.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : undefined,\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 tool call data */\n toolCalls: Map<\n number,\n { itemId?: string; callId?: string; name?: string; arguments: string }\n >;\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}\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 toolCalls: 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: 'message_start', 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 as OpenRouterResponsesFunctionCallOutput;\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: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.failed':\n state.status = 'failed';\n events.push({ type: 'message_stop', index: 0, delta: {} });\n break;\n\n case 'response.output_item.added':\n if (event.item.type === 'function_call') {\n const functionCall = event.item as OpenRouterResponsesFunctionCallOutput;\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: 'content_block_start',\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 as OpenRouterResponsesFunctionCallOutput;\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 as OpenRouterResponsesMessageOutput;\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: 'text_delta',\n index: event.output_index,\n delta: { text: content.text },\n });\n }\n }\n }\n }\n events.push({\n type: 'content_block_stop',\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: 'text_delta',\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: 'text_delta',\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: 'tool_call_delta',\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 // Emit reasoning as a reasoning_delta event\n events.push({\n type: 'reasoning_delta',\n index: 0,\n delta: { text: event.delta },\n });\n break;\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 textContent: TextBlock[] = [];\n let structuredData: unknown;\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 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 message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.id,\n metadata: {\n openrouter: {\n model: state.model,\n status: state.status,\n // Store response_id for multi-turn tool calling\n response_id: state.id,\n functionCallItems:\n functionCallItems.length > 0 ? functionCallItems : 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 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 } 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 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 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 'INVALID_REQUEST',\n 'openrouter',\n '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 response.json()) as OpenRouterResponsesResponse;\n\n // Check for error in response\n if (data.status === 'failed' && data.error) {\n throw new UPPError(\n data.error.message,\n 'PROVIDER_ERROR',\n 'openrouter',\n '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 };\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 'PROVIDER_ERROR',\n 'openrouter',\n '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 'PROVIDER_ERROR',\n 'openrouter',\n '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 responseReject(error as Error);\n throw error;\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","import type {\n Provider,\n ModelReference,\n LLMHandler,\n LLMProvider,\n} from '../../types/provider.ts';\nimport { createCompletionsLLMHandler } from './llm.completions.ts';\nimport { createResponsesLLMHandler } from './llm.responses.ts';\nimport type { OpenRouterCompletionsParams, OpenRouterResponsesParams } from './types.ts';\n\n/**\n * Union type for both Completions and Responses API parameter types.\n * Used internally to type the modalities handler.\n */\ntype OpenRouterLLMParamsUnion = OpenRouterCompletionsParams | OpenRouterResponsesParams;\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 */\nexport interface OpenRouterProvider extends Provider<OpenRouterProviderOptions> {\n /**\n * Creates a model reference for the specified model ID.\n *\n * @param modelId - The OpenRouter model identifier in `provider/model` format\n * (e.g., 'openai/gpt-4o', 'anthropic/claude-3.5-sonnet',\n * 'meta-llama/llama-3.1-70b-instruct')\n * @param options - Optional configuration including API selection\n * @returns A model reference that can be passed to llm()\n */\n (modelId: string, options?: OpenRouterProviderOptions): ModelReference<OpenRouterProviderOptions>;\n\n /** Provider identifier. Always 'openrouter'. */\n readonly name: 'openrouter';\n\n /** Semantic version of this provider implementation. */\n readonly version: string;\n\n /**\n * Supported modalities for this provider.\n * OpenRouter currently only supports LLM (text generation).\n */\n readonly modalities: {\n llm: LLMHandler<OpenRouterLLMParamsUnion>;\n };\n}\n\n/**\n * Factory function to create the OpenRouter provider singleton.\n *\n * Creates both Completions and Responses API handlers and manages\n * API mode switching based on the options passed when creating model references.\n *\n * @returns A fully configured OpenRouter provider instance\n * @internal\n */\nfunction createOpenRouterProvider(): OpenRouterProvider {\n let currentApiMode: 'completions' | 'responses' = 'completions';\n\n const completionsHandler = createCompletionsLLMHandler();\n const responsesHandler = createResponsesLLMHandler();\n\n const fn = function (\n modelId: string,\n options?: OpenRouterProviderOptions\n ): ModelReference<OpenRouterProviderOptions> {\n const apiMode = options?.api ?? 'completions';\n currentApiMode = apiMode;\n return { modelId, provider };\n };\n\n const modalities = {\n get llm(): LLMHandler<OpenRouterLLMParamsUnion> {\n return currentApiMode === 'responses'\n ? (responsesHandler as unknown as LLMHandler<OpenRouterLLMParamsUnion>)\n : (completionsHandler as unknown as LLMHandler<OpenRouterLLMParamsUnion>);\n },\n };\n\n Object.defineProperties(fn, {\n name: {\n value: 'openrouter',\n writable: false,\n configurable: true,\n },\n version: {\n value: '1.0.0',\n writable: false,\n configurable: true,\n },\n modalities: {\n value: modalities,\n writable: false,\n configurable: true,\n },\n });\n\n const provider = fn as OpenRouterProvider;\n\n completionsHandler._setProvider?.(provider as unknown as LLMProvider<OpenRouterCompletionsParams>);\n responsesHandler._setProvider?.(provider as unknown as LLMProvider<OpenRouterResponsesParams>);\n\n return provider;\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 = createOpenRouterProvider();\n\nexport type {\n OpenRouterCompletionsParams,\n OpenRouterResponsesParams,\n OpenRouterConfig,\n OpenRouterAPIMode,\n OpenRouterModelOptions,\n OpenRouterModelReference,\n OpenRouterProviderPreferences,\n OpenRouterHeaders,\n} from './types.ts';\n"],"mappings":"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","names":["transformRequest","transformTool","transformMessage","filterValidContent","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState","OPENROUTER_CAPABILITIES","transformRequest","transformResponse","createStreamState","transformStreamEvent","buildResponseFromState"]}
|
|
@@ -261,6 +261,23 @@ interface ProviderConfig {
|
|
|
261
261
|
apiVersion?: string;
|
|
262
262
|
/** Retry strategy for handling failures and rate limits */
|
|
263
263
|
retryStrategy?: RetryStrategy;
|
|
264
|
+
/**
|
|
265
|
+
* Custom headers to include in API requests.
|
|
266
|
+
*
|
|
267
|
+
* Use this to pass provider-specific headers such as:
|
|
268
|
+
* - Anthropic: `anthropic-beta` for beta features
|
|
269
|
+
* - OpenAI: `OpenAI-Organization`, `OpenAI-Project`
|
|
270
|
+
* - OpenRouter: `HTTP-Referer`, `X-Title` for attribution
|
|
271
|
+
* - Ollama: Proxy authentication headers
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```typescript
|
|
275
|
+
* const config: ProviderConfig = {
|
|
276
|
+
* headers: { 'anthropic-beta': 'extended-cache-ttl-2025-04-11' }
|
|
277
|
+
* };
|
|
278
|
+
* ```
|
|
279
|
+
*/
|
|
280
|
+
headers?: Record<string, string | undefined>;
|
|
264
281
|
}
|
|
265
282
|
/**
|
|
266
283
|
* A reference to a model, created by a provider factory.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as KeyStrategy, P as ProviderConfig, d as Modality, R as RetryStrategy, U as UPPError } from './provider-
|
|
1
|
+
import { K as KeyStrategy, P as ProviderConfig, d as Modality, R as RetryStrategy, U as UPPError } from './provider-Bi0nyNhA.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* API key management strategies for load balancing and dynamic key selection.
|