@openrouter/ai-sdk-provider 6.0.0-alpha.0 → 6.0.0-alpha.1
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/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +17 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.d.mts
CHANGED
|
@@ -297,6 +297,13 @@ interface OpenRouterProvider extends ProviderV3 {
|
|
|
297
297
|
interface OpenRouterModelSettings {
|
|
298
298
|
apiKey: string;
|
|
299
299
|
baseURL: string;
|
|
300
|
+
/**
|
|
301
|
+
* User-Agent string used by `@openrouter/sdk`.
|
|
302
|
+
*
|
|
303
|
+
* Note: Setting a `User-Agent` header via `fetchOptions.headers` is ineffective because
|
|
304
|
+
* the SDK sets it after merging user headers.
|
|
305
|
+
*/
|
|
306
|
+
userAgent: string;
|
|
300
307
|
headers?: Record<string, string>;
|
|
301
308
|
fetch?: typeof globalThis.fetch;
|
|
302
309
|
extraBody?: Record<string, unknown>;
|
|
@@ -387,4 +394,4 @@ declare const VERSION = "6.0.0-alpha.0";
|
|
|
387
394
|
*/
|
|
388
395
|
declare const openrouter: OpenRouterProvider;
|
|
389
396
|
|
|
390
|
-
export { type OpenRouterModelOptions, type OpenRouterPluginConfig, type OpenRouterProvider, type OpenRouterProviderRoutingConfig, type OpenRouterProviderSettings, VERSION, createOpenRouter, openrouter };
|
|
397
|
+
export { type OpenRouterModelOptions, type OpenRouterModelSettings, type OpenRouterPluginConfig, type OpenRouterProvider, type OpenRouterProviderRoutingConfig, type OpenRouterProviderSettings, VERSION, createOpenRouter, openrouter };
|
package/dist/index.d.ts
CHANGED
|
@@ -297,6 +297,13 @@ interface OpenRouterProvider extends ProviderV3 {
|
|
|
297
297
|
interface OpenRouterModelSettings {
|
|
298
298
|
apiKey: string;
|
|
299
299
|
baseURL: string;
|
|
300
|
+
/**
|
|
301
|
+
* User-Agent string used by `@openrouter/sdk`.
|
|
302
|
+
*
|
|
303
|
+
* Note: Setting a `User-Agent` header via `fetchOptions.headers` is ineffective because
|
|
304
|
+
* the SDK sets it after merging user headers.
|
|
305
|
+
*/
|
|
306
|
+
userAgent: string;
|
|
300
307
|
headers?: Record<string, string>;
|
|
301
308
|
fetch?: typeof globalThis.fetch;
|
|
302
309
|
extraBody?: Record<string, unknown>;
|
|
@@ -387,4 +394,4 @@ declare const VERSION = "6.0.0-alpha.0";
|
|
|
387
394
|
*/
|
|
388
395
|
declare const openrouter: OpenRouterProvider;
|
|
389
396
|
|
|
390
|
-
export { type OpenRouterModelOptions, type OpenRouterPluginConfig, type OpenRouterProvider, type OpenRouterProviderRoutingConfig, type OpenRouterProviderSettings, VERSION, createOpenRouter, openrouter };
|
|
397
|
+
export { type OpenRouterModelOptions, type OpenRouterModelSettings, type OpenRouterPluginConfig, type OpenRouterProvider, type OpenRouterProviderRoutingConfig, type OpenRouterProviderSettings, VERSION, createOpenRouter, openrouter };
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
28
28
|
|
|
29
29
|
// src/openrouter-provider.ts
|
|
30
30
|
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
31
|
+
var import_sdk3 = require("@openrouter/sdk");
|
|
31
32
|
|
|
32
33
|
// src/chat/openrouter-chat-language-model.ts
|
|
33
34
|
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
@@ -516,7 +517,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
516
517
|
const warnings = [];
|
|
517
518
|
const client = new import_sdk.OpenRouter({
|
|
518
519
|
apiKey: this.settings.apiKey,
|
|
519
|
-
serverURL: this.settings.baseURL
|
|
520
|
+
serverURL: this.settings.baseURL,
|
|
521
|
+
userAgent: this.settings.userAgent
|
|
520
522
|
});
|
|
521
523
|
const openRouterInput = convertToOpenRouterMessages(options.prompt);
|
|
522
524
|
const tools = convertToolsToResponsesFormat(options.tools, warnings);
|
|
@@ -641,7 +643,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
641
643
|
const warnings = [];
|
|
642
644
|
const client = new import_sdk.OpenRouter({
|
|
643
645
|
apiKey: this.settings.apiKey,
|
|
644
|
-
serverURL: this.settings.baseURL
|
|
646
|
+
serverURL: this.settings.baseURL,
|
|
647
|
+
userAgent: this.settings.userAgent
|
|
645
648
|
});
|
|
646
649
|
const openRouterInput = convertToOpenRouterMessages(options.prompt);
|
|
647
650
|
const tools = convertToolsToResponsesFormat(options.tools, warnings);
|
|
@@ -1101,7 +1104,8 @@ var OpenRouterEmbeddingModel = class {
|
|
|
1101
1104
|
const warnings = [];
|
|
1102
1105
|
const client = new import_sdk2.OpenRouter({
|
|
1103
1106
|
apiKey: this.settings.apiKey,
|
|
1104
|
-
serverURL: this.settings.baseURL
|
|
1107
|
+
serverURL: this.settings.baseURL,
|
|
1108
|
+
userAgent: this.settings.userAgent
|
|
1105
1109
|
});
|
|
1106
1110
|
const requestParams = {
|
|
1107
1111
|
model: this.modelId,
|
|
@@ -1172,10 +1176,19 @@ function createOpenRouter(options = {}) {
|
|
|
1172
1176
|
environmentVariableName: "OPENROUTER_API_KEY",
|
|
1173
1177
|
description: "OpenRouter"
|
|
1174
1178
|
});
|
|
1179
|
+
const providerUserAgentPart = `ai-sdk-provider/${"6.0.0-alpha.1"}`;
|
|
1180
|
+
const baseUserAgent = options.headers?.["user-agent"] ?? options.headers?.["User-Agent"] ?? import_sdk3.SDK_METADATA.userAgent;
|
|
1181
|
+
const userAgent = baseUserAgent.includes("ai-sdk-provider/") ? baseUserAgent : `${baseUserAgent} ${providerUserAgentPart}`;
|
|
1182
|
+
const {
|
|
1183
|
+
"User-Agent": _ignoredUserAgent,
|
|
1184
|
+
"user-agent": _ignoredUserAgentLower,
|
|
1185
|
+
...forwardHeaders
|
|
1186
|
+
} = options.headers ?? {};
|
|
1175
1187
|
return {
|
|
1176
1188
|
apiKey,
|
|
1177
1189
|
baseURL,
|
|
1178
|
-
|
|
1190
|
+
userAgent,
|
|
1191
|
+
headers: Object.keys(forwardHeaders).length > 0 ? forwardHeaders : void 0,
|
|
1179
1192
|
fetch: options.fetch,
|
|
1180
1193
|
extraBody: options.extraBody,
|
|
1181
1194
|
modelOptions
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/openrouter-provider.ts","../src/chat/openrouter-chat-language-model.ts","../src/utils/build-provider-metadata.ts","../src/utils/build-usage.ts","../src/chat/convert-to-openrouter-messages.ts","../src/chat/extract-reasoning-details.ts","../src/chat/map-openrouter-finish-reason.ts","../src/embedding/openrouter-embedding-model.ts","../src/image/openrouter-image-model.ts","../src/version.ts"],"sourcesContent":["export { createOpenRouter, type OpenRouterProvider } from './openrouter-provider.js';\nexport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n OpenRouterPluginConfig,\n OpenRouterProviderRoutingConfig,\n} from './openrouter-config.js';\nexport { VERSION } from './version.js';\n\n// Default instance\nimport { createOpenRouter } from './openrouter-provider.js';\n\n/**\n * Default OpenRouter provider instance.\n *\n * Uses OPENROUTER_API_KEY environment variable for authentication.\n *\n * @example\n * ```ts\n * import { openrouter } from '@openrouter/ai-sdk-provider';\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n */\nexport const openrouter = createOpenRouter();\n","import type { ProviderV3 } from '@ai-sdk/provider';\nimport { loadApiKey, withoutTrailingSlash } from '@ai-sdk/provider-utils';\nimport { OpenRouterChatLanguageModel } from './chat/openrouter-chat-language-model.js';\nimport { OpenRouterEmbeddingModel } from './embedding/openrouter-embedding-model.js';\nimport { OpenRouterImageModel } from './image/openrouter-image-model.js';\nimport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n} from './openrouter-config.js';\n\n/**\n * OpenRouter provider interface extending the AI SDK V3 ProviderV3 interface.\n *\n * The provider is callable - calling it directly is equivalent to calling languageModel().\n */\nexport interface OpenRouterProvider extends ProviderV3 {\n /**\n * Create a language model by calling the provider directly.\n */\n (modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a language model.\n */\n languageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a chat model (alias for languageModel).\n */\n chat(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create an embedding model.\n */\n embeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create a text embedding model.\n * @deprecated Use embeddingModel instead.\n */\n textEmbeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create an image model.\n */\n imageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an image model (alias for imageModel).\n */\n image(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an embedding model (alias for embeddingModel).\n * @deprecated Use embeddingModel instead.\n */\n embedding(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n}\n\n/**\n * Internal settings passed to model constructors.\n * Contains resolved API key and normalized configuration.\n */\nexport interface OpenRouterModelSettings {\n apiKey: string;\n baseURL: string;\n headers?: Record<string, string>;\n fetch?: typeof globalThis.fetch;\n extraBody?: Record<string, unknown>;\n modelOptions?: OpenRouterModelOptions;\n}\n\n/**\n * Creates an OpenRouter provider instance for the AI SDK.\n *\n * @description\n * Factory function that creates an OpenRouter provider compatible with the AI SDK v3 provider\n * specification. The provider can create language models, embedding models, and image models\n * that route requests through OpenRouter to various AI providers (OpenAI, Anthropic, Google, etc.).\n *\n * The returned provider is callable - you can use it directly as a function to create language\n * models, or use its methods for specific model types.\n *\n * @param options - Provider settings including API key, base URL, headers, and fetch implementation.\n * If no API key is provided, it will be loaded from the OPENROUTER_API_KEY environment variable.\n * @returns An OpenRouter provider that can create language, embedding, and image models.\n *\n * @example Basic usage with environment variable\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * // Uses OPENROUTER_API_KEY from environment\n * const openrouter = createOpenRouter();\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example With explicit API key\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * const openrouter = createOpenRouter({\n * apiKey: process.env.OPENROUTER_API_KEY,\n * });\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example Creating different model types\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Language model (callable shorthand)\n * const chat = openrouter('anthropic/claude-3.5-sonnet');\n *\n * // Embedding model\n * const embeddings = openrouter.embeddingModel('openai/text-embedding-3-small');\n *\n * // Image model\n * const image = openrouter.imageModel('openai/dall-e-3');\n * ```\n *\n * @example Model variants\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Online search variant - model has web search capabilities\n * const online = openrouter('anthropic/claude-3.5-sonnet:online');\n *\n * // Nitro variant - faster inference\n * const nitro = openrouter('anthropic/claude-3.5-sonnet:nitro');\n *\n * // Floor pricing variant - routes to cheapest provider\n * const floor = openrouter('anthropic/claude-3.5-sonnet:floor');\n *\n * // Free tier variant\n * const free = openrouter('meta-llama/llama-3-8b-instruct:free');\n * ```\n */\nexport function createOpenRouter(\n options: OpenRouterProviderSettings = {}\n): OpenRouterProvider {\n // Normalize base URL: accept baseURL or baseUrl, strip trailing slash\n // The fallback ensures we always have a value, so the non-null assertion is safe\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? options.baseUrl ?? 'https://openrouter.ai/api/v1'\n )!;\n\n /**\n * Resolves model settings at model creation time.\n * API key is loaded here (not at provider creation or request time) per Decision 1 - Fail Fast.\n */\n const getModelSettings = (modelOptions?: OpenRouterModelOptions): OpenRouterModelSettings => {\n // Load API key at model creation time\n const apiKey = loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'OPENROUTER_API_KEY',\n description: 'OpenRouter',\n });\n\n return {\n apiKey,\n baseURL,\n headers: options.headers,\n fetch: options.fetch,\n extraBody: options.extraBody,\n modelOptions,\n };\n };\n\n /**\n * Create a language model.\n */\n const languageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterChatLanguageModel => {\n return new OpenRouterChatLanguageModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an embedding model.\n */\n const embeddingModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterEmbeddingModel => {\n return new OpenRouterEmbeddingModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an image model.\n */\n const imageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterImageModel => {\n return new OpenRouterImageModel(modelId, getModelSettings(modelOptions));\n };\n\n // Create the callable provider object\n const provider = Object.assign(\n // Make provider callable - calling it directly creates a language model\n (modelId: string, modelOptions?: OpenRouterModelOptions) => languageModel(modelId, modelOptions),\n {\n specificationVersion: 'v3' as const,\n languageModel,\n chat: languageModel,\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n imageModel,\n image: imageModel,\n embedding: embeddingModel,\n }\n );\n\n return provider;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FunctionTool,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3ToolChoice,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type {\n OpenResponsesRequest,\n OpenResponsesNonStreamingResponse,\n OpenResponsesStreamEvent,\n OpenResponsesRequestToolFunction,\n OpenAIResponsesToolChoiceUnion,\n} from '@openrouter/sdk/models';\nimport type { EventStream } from '@openrouter/sdk/lib/event-streams';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\nimport { buildProviderMetadata } from '../utils/build-provider-metadata.js';\nimport { buildUsage } from '../utils/build-usage.js';\nimport { convertToOpenRouterMessages } from './convert-to-openrouter-messages.js';\nimport {\n extractReasoningDetails,\n hasEncryptedReasoning,\n buildReasoningProviderMetadata,\n type ReasoningOutputItem,\n} from './extract-reasoning-details.js';\nimport { mapOpenRouterFinishReason } from './map-openrouter-finish-reason.js';\n\n/**\n * OpenRouter chat language model implementing AI SDK V3 LanguageModelV3 interface.\n *\n * Uses the OpenRouter Responses API for both streaming and non-streaming requests.\n */\nexport class OpenRouterChatLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Supported URL patterns by media type.\n * OpenRouter Chat API only supports image URLs natively.\n * PDF URLs are not supported - use PDF data URIs or the Responses API instead.\n */\n readonly supportedUrls: Record<string, RegExp[]> = {\n 'image/*': [/^https?:\\/\\/.*$/],\n };\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3GenerateResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (non-streaming)\n const requestParams: OpenResponsesRequest & { stream: false } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: false,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the non-streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as OpenResponsesNonStreamingResponse;\n\n // Build content array from Responses API output\n const content: LanguageModelV3Content[] = [];\n\n // Extract reasoning details for multi-turn conversation support\n // These must be preserved and sent back in subsequent turns for reasoning models\n const reasoningDetails = extractReasoningDetails(response);\n const reasoningMetadata = buildReasoningProviderMetadata(reasoningDetails);\n\n // Process output items\n for (const outputItem of response.output) {\n if (outputItem.type === 'reasoning') {\n // Extract reasoning text from content array or summary\n const reasoningItem = outputItem as ReasoningOutputItem;\n const reasoningText =\n reasoningItem.content\n ?.filter((c) => c.type === 'reasoning_text')\n .map((c) => c.text)\n .join('') ||\n reasoningItem.summary\n ?.filter((c) => c.type === 'summary_text')\n .map((c) => c.text)\n .join('') ||\n '';\n\n if (reasoningText) {\n // Attach reasoning_details to the reasoning part for multi-turn support\n content.push({\n type: 'reasoning',\n text: reasoningText,\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n } else if (outputItem.type === 'message') {\n // Extract text content from message\n const messageItem = outputItem as {\n type: 'message';\n content: Array<{ type: string; text?: string }>;\n };\n for (const contentItem of messageItem.content) {\n if (contentItem.type === 'output_text' && contentItem.text) {\n content.push({\n type: 'text',\n text: contentItem.text,\n });\n }\n }\n } else if (outputItem.type === 'function_call') {\n // Handle tool/function calls\n const functionCallItem = outputItem as {\n type: 'function_call';\n callId: string;\n name: string;\n arguments?: string;\n };\n // Attach reasoning_details to tool-call parts for multi-turn support\n // This is critical for Gemini 3 with thoughtSignature\n content.push({\n type: 'tool-call',\n toolCallId: functionCallItem.callId,\n toolName: functionCallItem.name,\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n input: functionCallItem.arguments || '{}',\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n }\n\n // Use outputText as fallback if no text content was extracted\n if (response.outputText && !content.some((c) => c.type === 'text')) {\n content.push({\n type: 'text',\n text: response.outputText,\n });\n }\n\n // Build finish reason based on response status\n let finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Gemini 3 thoughtSignature fix: when there are tool calls with encrypted\n // reasoning, the model returns 'completed' but expects continuation.\n // Override to 'tool-calls' so the AI SDK knows to continue the conversation.\n const hasToolCalls = content.some((c) => c.type === 'tool-call');\n if (\n hasToolCalls &&\n hasEncryptedReasoning(reasoningDetails) &&\n finishReason.unified === 'stop'\n ) {\n finishReason = { unified: 'tool-calls', raw: finishReason.raw };\n }\n\n // Build usage from Responses API format\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Note: The Responses API doesn't include 'provider' field directly\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider in response\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens: response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n return {\n content,\n finishReason,\n usage,\n warnings,\n providerMetadata,\n request: {\n body: requestParams,\n },\n response: {\n id: response.id,\n timestamp: new Date(response.createdAt * 1000),\n modelId: response.model,\n },\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3StreamResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (streaming)\n const requestParams: OpenResponsesRequest & { stream: true } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: true,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const eventStream = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as EventStream<OpenResponsesStreamEvent>;\n\n // Track state for stream transformation\n const state = createStreamState();\n\n // Transform the EventStream to AI SDK V3 stream parts\n const transformedStream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n // Emit stream-start first\n controller.enqueue({\n type: 'stream-start',\n warnings,\n });\n\n try {\n for await (const event of eventStream) {\n const parts = transformResponsesEvent(event, state);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n } catch (error) {\n controller.enqueue({\n type: 'error',\n error,\n });\n } finally {\n controller.close();\n }\n },\n });\n\n return {\n stream: transformedStream,\n request: {\n body: requestParams,\n },\n };\n }\n}\n\n/**\n * Stream state for tracking response metadata and content parts.\n */\ninterface StreamState {\n responseId: string | undefined;\n responseModel: string | undefined;\n responseCreated: number | undefined;\n textStarted: boolean;\n textId: string;\n reasoningStarted: boolean;\n reasoningId: string;\n textEnded: boolean;\n reasoningEnded: boolean;\n sourceIds: string[];\n toolCalls: Map<string, { name?: string; argumentsStarted: boolean }>;\n}\n\nfunction createStreamState(): StreamState {\n return {\n responseId: undefined,\n responseModel: undefined,\n responseCreated: undefined,\n textStarted: false,\n textId: 'text-0',\n reasoningStarted: false,\n reasoningId: 'reasoning-0',\n textEnded: false,\n reasoningEnded: false,\n sourceIds: [],\n toolCalls: new Map(),\n };\n}\n\n/**\n * Transform a Responses API stream event to AI SDK V3 stream parts.\n */\nfunction transformResponsesEvent(\n event: OpenResponsesStreamEvent,\n state: StreamState\n): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n\n switch (event.type) {\n // Response lifecycle events\n case 'response.created':\n case 'response.in_progress': {\n // Capture response metadata from initial events\n if (event.response) {\n state.responseId = event.response.id;\n state.responseModel = event.response.model;\n state.responseCreated = event.response.createdAt;\n }\n break;\n }\n\n // Text streaming\n case 'response.output_text.delta': {\n // Emit text-start if not started\n if (!state.textStarted) {\n state.textStarted = true;\n parts.push({\n type: 'text-start',\n id: state.textId,\n });\n }\n\n // Emit text-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'text-delta',\n id: state.textId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.output_text.done': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n break;\n }\n\n // Reasoning streaming\n case 'response.reasoning_text.delta': {\n // Emit reasoning-start if not started\n if (!state.reasoningStarted) {\n state.reasoningStarted = true;\n parts.push({\n type: 'reasoning-start',\n id: state.reasoningId,\n });\n }\n\n // Emit reasoning-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'reasoning-delta',\n id: state.reasoningId,\n delta: event.delta,\n });\n }\n break;\n }\n\n // Function call arguments streaming\n case 'response.function_call_arguments.delta': {\n const toolCallId = event.itemId;\n let toolState = state.toolCalls.get(toolCallId);\n\n if (!toolState) {\n toolState = { argumentsStarted: false };\n state.toolCalls.set(toolCallId, toolState);\n }\n\n // Emit tool-input-start if not started\n if (!toolState.argumentsStarted) {\n toolState.argumentsStarted = true;\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: toolState.name ?? '', // Will be filled in by output_item.added\n });\n }\n\n // Emit tool-input-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.function_call_arguments.done': {\n const toolCallId = event.itemId;\n const toolState = state.toolCalls.get(toolCallId);\n\n // If we haven't started tool call yet, emit start + delta with full args\n if (!toolState?.argumentsStarted) {\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: event.name,\n });\n // Default to empty object when arguments is undefined/empty\n const args = event.arguments || '{}';\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: args,\n });\n }\n\n // Emit tool-input-end\n parts.push({\n type: 'tool-input-end',\n id: toolCallId,\n });\n\n // Emit tool-call with complete tool call data\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n parts.push({\n type: 'tool-call',\n toolCallId,\n toolName: event.name,\n input: event.arguments || '{}',\n });\n break;\n }\n\n // Output item events (for function call metadata)\n case 'response.output_item.added': {\n if (event.item.type === 'function_call') {\n const funcItem = event.item as {\n type: 'function_call';\n callId?: string;\n name: string;\n };\n const toolCallId = funcItem.callId ?? `tool-${event.outputIndex}`;\n const toolState = state.toolCalls.get(toolCallId) ?? {\n argumentsStarted: false,\n };\n toolState.name = funcItem.name;\n state.toolCalls.set(toolCallId, toolState);\n }\n break;\n }\n\n // Annotation events (web search sources)\n case 'response.output_text.annotation.added': {\n const annotation = event.annotation;\n if (annotation.type === 'url_citation') {\n const urlAnnotation = annotation as {\n type: 'url_citation';\n url: string;\n title: string;\n };\n const sourceId = `source-${state.sourceIds.length}`;\n state.sourceIds.push(sourceId);\n parts.push({\n type: 'source',\n sourceType: 'url',\n id: sourceId,\n url: urlAnnotation.url,\n title: urlAnnotation.title,\n });\n }\n break;\n }\n\n // Response completed - extract final usage data\n case 'response.completed': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n\n // End reasoning if started and not ended\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n // Emit response-metadata\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Build finish reason based on response status\n const finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Build usage\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Response incomplete or failed\n case 'response.incomplete':\n case 'response.failed': {\n // End any open content parts\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Map finish reason\n const finishReason =\n event.type === 'response.failed'\n ? mapOpenRouterFinishReason('error')\n : mapOpenRouterFinishReason(response.status ?? 'incomplete');\n\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined,\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Error event\n case 'error': {\n const errorEvent = event as {\n type: 'error';\n error?: { message?: string };\n };\n parts.push({\n type: 'error',\n error: new Error(\n errorEvent.error?.message ?? 'Unknown streaming error'\n ),\n });\n break;\n }\n\n // Ignored events (handled implicitly or not needed)\n case 'response.output_item.done':\n case 'response.content_part.added':\n case 'response.content_part.done':\n case 'response.refusal.delta':\n case 'response.refusal.done':\n case 'response.reasoning_text.done':\n case 'response.reasoning_summary_part.added':\n case 'response.reasoning_summary_part.done':\n case 'response.reasoning_summary_text.delta':\n case 'response.reasoning_summary_text.done':\n case 'response.image_generation_call.in_progress':\n case 'response.image_generation_call.generating':\n case 'response.image_generation_call.partial_image':\n case 'response.image_generation_call.completed':\n // These events are either handled by other events or not relevant for AI SDK\n break;\n }\n\n return parts;\n}\n\n/**\n * Convert AI SDK tools to OpenRouter Responses API format.\n * Only 'function' type tools are supported.\n */\nfunction convertToolsToResponsesFormat(\n tools: LanguageModelV3CallOptions['tools'],\n warnings: SharedV3Warning[]\n): OpenResponsesRequestToolFunction[] {\n if (!tools || tools.length === 0) {\n return [];\n }\n\n return tools\n .map((tool): OpenResponsesRequestToolFunction | null => {\n if (tool.type !== 'function') {\n warnings.push({\n type: 'unsupported',\n feature: `tool type '${tool.type}'`,\n details: `Only 'function' type tools are supported. Tool '${(tool as { name?: string }).name ?? 'unknown'}' has type '${tool.type}'.`,\n });\n return null;\n }\n\n const functionTool = tool as LanguageModelV3FunctionTool;\n return {\n type: 'function',\n name: functionTool.name,\n description: functionTool.description ?? null,\n parameters: functionTool.inputSchema as { [k: string]: unknown } | null,\n };\n })\n .filter((tool): tool is OpenResponsesRequestToolFunction => tool !== null);\n}\n\n/**\n * Convert AI SDK toolChoice to OpenRouter Responses API format.\n *\n * Mapping:\n * - 'auto' -> 'auto'\n * - 'none' -> 'none'\n * - 'required' -> 'required'\n * - { type: 'tool', toolName } -> { type: 'function', name: toolName }\n */\nfunction convertToolChoiceToResponsesFormat(\n toolChoice: LanguageModelV3ToolChoice | undefined\n): OpenAIResponsesToolChoiceUnion | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return 'auto';\n case 'none':\n return 'none';\n case 'required':\n return 'required';\n case 'tool':\n return {\n type: 'function',\n name: toolChoice.toolName,\n };\n default:\n return undefined;\n }\n}\n\n/**\n * Convert AI SDK responseFormat to OpenRouter Responses API text.format.\n *\n * Mapping:\n * - { type: 'text' } -> { type: 'text' }\n * - { type: 'json' } -> { type: 'json_object' } (no schema)\n * - { type: 'json', schema, name } -> { type: 'json_schema', name, schema } (with schema)\n */\nfunction convertResponseFormatToText(\n responseFormat: LanguageModelV3CallOptions['responseFormat']\n): OpenResponsesRequest['text'] | undefined {\n if (!responseFormat) {\n return undefined;\n }\n\n if (responseFormat.type === 'text') {\n return {\n format: { type: 'text' },\n };\n }\n\n if (responseFormat.type === 'json') {\n // If a schema is provided, use json_schema format\n if (responseFormat.schema) {\n return {\n format: {\n type: 'json_schema',\n name: responseFormat.name ?? 'response',\n description: responseFormat.description,\n schema: responseFormat.schema as { [k: string]: unknown },\n },\n };\n }\n // No schema - use simple json_object format\n return {\n format: { type: 'json_object' },\n };\n }\n\n return undefined;\n}\n","import type { JSONObject } from '@ai-sdk/provider';\nimport type { ChatGenerationTokenUsage } from '@openrouter/sdk/models';\n\n/**\n * OpenRouter-specific provider metadata structure.\n */\nexport interface OpenRouterProviderMetadata {\n /**\n * The response ID from OpenRouter.\n */\n responseId?: string;\n\n /**\n * The upstream provider that served the request.\n */\n provider?: string;\n\n /**\n * Detailed usage information.\n */\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n promptTokensDetails?: {\n cachedTokens?: number;\n cacheWriteTokens?: number;\n audioTokens?: number;\n videoTokens?: number;\n };\n completionTokensDetails?: {\n reasoningTokens?: number;\n imageTokens?: number;\n };\n /**\n * Cost in USD (omit if unavailable).\n */\n cost?: number;\n /**\n * Whether the request used BYOK (Bring Your Own Key).\n */\n isByok?: boolean;\n /**\n * Detailed cost breakdown.\n */\n costDetails?: JSONObject;\n };\n}\n\n/**\n * Extended prompt tokens details with fields not in SDK types.\n */\nexport interface ExtendedPromptTokensDetails {\n cachedTokens?: number | null;\n cacheWriteTokens?: number | null;\n audioTokens?: number | null;\n videoTokens?: number | null;\n}\n\n/**\n * Extended completion tokens details with fields not in SDK types.\n */\nexport interface ExtendedCompletionTokensDetails {\n reasoningTokens?: number | null;\n imageTokens?: number | null;\n}\n\n/**\n * Extended usage type with additional fields from raw OpenRouter API response.\n * The SDK types don't include cost/is_byok but the API returns them.\n */\nexport interface OpenRouterUsageExtended extends Omit<ChatGenerationTokenUsage, 'promptTokensDetails' | 'completionTokensDetails'> {\n cost?: number;\n isByok?: boolean;\n costDetails?: JSONObject;\n promptTokensDetails?: ExtendedPromptTokensDetails | null;\n completionTokensDetails?: ExtendedCompletionTokensDetails | null;\n}\n\n/**\n * Response data from OpenRouter API used to build provider metadata.\n * Note: The SDK transforms snake_case to camelCase for all fields.\n * The `provider` field exists in raw API responses but isn't in SDK types.\n */\nexport interface OpenRouterResponseData {\n id?: string;\n /**\n * The upstream provider that served the request (e.g. \"Google\", \"Anthropic\").\n * This field exists in the raw API response but isn't in SDK TypeScript types.\n */\n provider?: string;\n /**\n * Usage data in camelCase (as transformed by SDK).\n */\n usage?: OpenRouterUsageExtended;\n}\n\n/**\n * Filters out undefined values from an object, returning only defined properties.\n * This ensures providerMetadata is valid JSON (undefined is not a valid JSON value).\n */\nfunction filterUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined)\n ) as Partial<T>;\n}\n\n/**\n * Builds provider metadata from OpenRouter API response data.\n *\n * @param response - The response data from OpenRouter API (with camelCase fields from SDK).\n * @returns Provider metadata in the format expected by AI SDK.\n */\nexport function buildProviderMetadata(\n response: OpenRouterResponseData | undefined\n): Record<string, JSONObject> | undefined {\n if (!response) {\n return undefined;\n }\n\n const usage = response.usage;\n const usageMetadata: OpenRouterProviderMetadata['usage'] | undefined = usage\n ? filterUndefined({\n promptTokens: usage.promptTokens,\n completionTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n ...(usage.promptTokensDetails && {\n promptTokensDetails: filterUndefined({\n cachedTokens: usage.promptTokensDetails.cachedTokens ?? undefined,\n cacheWriteTokens: usage.promptTokensDetails.cacheWriteTokens ?? undefined,\n audioTokens: usage.promptTokensDetails.audioTokens ?? undefined,\n videoTokens: usage.promptTokensDetails.videoTokens ?? undefined,\n }),\n }),\n ...(usage.completionTokensDetails && {\n completionTokensDetails: filterUndefined({\n reasoningTokens: usage.completionTokensDetails.reasoningTokens ?? undefined,\n imageTokens: usage.completionTokensDetails.imageTokens ?? undefined,\n }),\n }),\n cost: usage.cost,\n isByok: usage.isByok,\n costDetails: usage.costDetails,\n })\n : undefined;\n\n const metadata: OpenRouterProviderMetadata = filterUndefined({\n responseId: response.id,\n provider: response.provider,\n usage: usageMetadata,\n });\n\n return {\n openrouter: metadata as unknown as JSONObject,\n };\n}\n","import type { LanguageModelV3Usage, JSONObject } from '@ai-sdk/provider';\n\n/**\n * Raw usage data from OpenRouter API response.\n */\nexport interface OpenRouterRawUsage {\n inputTokens?: number;\n outputTokens?: number;\n inputTokensDetails?: {\n cachedTokens?: number;\n };\n outputTokensDetails?: {\n reasoningTokens?: number;\n };\n}\n\n/**\n * Builds a LanguageModelV3Usage object from OpenRouter API usage data.\n *\n * @param usage - The raw usage data from the OpenRouter API response.\n * @returns A LanguageModelV3Usage object with standardized token counts.\n */\nexport function buildUsage(usage: OpenRouterRawUsage | undefined): LanguageModelV3Usage {\n if (!usage) {\n return {\n inputTokens: {\n total: 0,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n }\n\n // Convert to JSONObject-compatible format for raw field\n const rawUsage: JSONObject = {\n inputTokens: usage.inputTokens ?? null,\n outputTokens: usage.outputTokens ?? null,\n ...(usage.inputTokensDetails && {\n inputTokensDetails: {\n cachedTokens: usage.inputTokensDetails.cachedTokens ?? null,\n },\n }),\n ...(usage.outputTokensDetails && {\n outputTokensDetails: {\n reasoningTokens: usage.outputTokensDetails.reasoningTokens ?? null,\n },\n }),\n };\n\n return {\n inputTokens: {\n total: usage.inputTokens ?? 0,\n noCache: undefined,\n cacheRead: usage.inputTokensDetails?.cachedTokens,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: usage.outputTokens ?? 0,\n text: undefined,\n reasoning: usage.outputTokensDetails?.reasoningTokens,\n },\n raw: rawUsage,\n };\n}\n","import type {\n LanguageModelV3Prompt,\n LanguageModelV3Message,\n LanguageModelV3TextPart,\n LanguageModelV3FilePart,\n LanguageModelV3ReasoningPart,\n LanguageModelV3ToolCallPart,\n LanguageModelV3ToolResultPart,\n LanguageModelV3ToolResultOutput,\n JSONValue,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter Responses API input item types.\n * These match the OpenResponsesEasyInputMessage format used by the Responses API.\n */\nexport type OpenRouterInputItem =\n | OpenRouterEasyInputMessage\n | OpenRouterFunctionCall\n | OpenRouterFunctionCallOutput;\n\n/**\n * Reasoning details item format for API requests.\n * Used to preserve reasoning context across multi-turn conversations.\n */\nexport interface OpenRouterReasoningDetailItem {\n type: 'reasoning.text' | 'reasoning.summary' | 'reasoning.encrypted';\n id?: string;\n format?: string | null;\n index: number;\n text?: string; // For reasoning.text\n signature?: string | null; // For reasoning.text (Claude)\n summary?: string; // For reasoning.summary\n data?: string; // For reasoning.encrypted (Gemini)\n}\n\n/**\n * Reasoning object for assistant messages.\n * Contains the reasoning details to send back to the API.\n */\nexport interface OpenRouterReasoning {\n text?: string;\n summary?: string;\n encrypted?: string;\n}\n\n/**\n * Easy input message format for Responses API.\n * Supports user, system, assistant, and developer roles.\n */\nexport interface OpenRouterEasyInputMessage {\n type?: 'message';\n role: 'user' | 'system' | 'assistant' | 'developer';\n content: string | OpenRouterInputContent[];\n reasoning?: OpenRouterReasoning;\n}\n\nexport interface OpenRouterFunctionCall {\n type: 'function_call';\n callId: string;\n name: string;\n arguments: string;\n}\n\nexport interface OpenRouterFunctionCallOutput {\n type: 'function_call_output';\n callId: string;\n output: string;\n status: 'completed' | 'incomplete';\n}\n\n/**\n * Input content types for Responses API.\n * Uses 'input_text', 'input_image', 'input_file' type prefixes.\n */\nexport type OpenRouterInputContent =\n | { type: 'input_text'; text: string }\n | { type: 'input_image'; imageUrl: string; detail?: 'auto' | 'low' | 'high' }\n | { type: 'input_file'; fileUrl: string; filename?: string };\n\n/**\n * Converts AI SDK V3 prompt format to OpenRouter Responses API input format.\n *\n * Mapping table:\n * - system { content } -> { role: 'system', content: string }\n * - user text -> { role: 'user', content: [{ type: 'input_text', text }] }\n * - user image -> { role: 'user', content: [{ type: 'input_image', imageUrl }] }\n * - user file -> { role: 'user', content: [{ type: 'input_file', fileUrl }] }\n * - assistant text -> { role: 'assistant', content: string }\n * - assistant tool-call -> { type: 'function_call', ... }\n * - tool result -> { type: 'function_call_output', ... }\n *\n * @param prompt - The AI SDK V3 prompt\n * @returns Array of input items in OpenRouter Responses API format\n */\nexport function convertToOpenRouterMessages(\n prompt: LanguageModelV3Prompt\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const message of prompt) {\n const converted = convertMessage(message);\n result.push(...converted);\n }\n\n return result;\n}\n\n/**\n * Convert a single V3 message to OpenRouter Responses API format.\n * May return multiple items (e.g., when assistant has text + tool calls).\n */\nfunction convertMessage(message: LanguageModelV3Message): OpenRouterInputItem[] {\n // Extract providerOptions from the message for reasoning_details\n const messageWithOptions = message as LanguageModelV3Message & {\n providerOptions?: Record<string, Record<string, unknown>>;\n providerMetadata?: Record<string, Record<string, unknown>>;\n };\n const providerOptions = messageWithOptions.providerOptions;\n const providerMetadata = messageWithOptions.providerMetadata;\n\n switch (message.role) {\n case 'system':\n return [{ role: 'system', content: message.content }];\n\n case 'user':\n return [convertUserMessage(message.content)];\n\n case 'assistant':\n return convertAssistantMessage(message.content, providerMetadata, providerOptions);\n\n case 'tool':\n return convertToolMessage(message.content);\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = message;\n throw new Error(`Unknown message role: ${(_exhaustive as { role: string }).role}`);\n }\n }\n}\n\n/**\n * Convert user message content parts to OpenRouter Responses API format.\n */\nfunction convertUserMessage(\n content: Array<LanguageModelV3TextPart | LanguageModelV3FilePart>\n): OpenRouterEasyInputMessage {\n const convertedContent: OpenRouterInputContent[] = [];\n\n for (const part of content) {\n switch (part.type) {\n case 'text': {\n convertedContent.push({ type: 'input_text', text: part.text });\n break;\n }\n\n case 'file':\n convertedContent.push(convertFilePart(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(`Unknown user content type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n }\n\n return { role: 'user', content: convertedContent };\n}\n\n/**\n * Convert a file part to the appropriate OpenRouter Responses API format.\n *\n * OpenRouter's Responses API uses 'input_image' for images and 'input_file' for other files.\n */\nfunction convertFilePart(part: LanguageModelV3FilePart): OpenRouterInputContent {\n const url = convertDataContent(part.data, part.mediaType);\n \n // Check if it's an image based on media type\n if (part.mediaType.startsWith('image/')) {\n return {\n type: 'input_image',\n imageUrl: url,\n detail: 'auto',\n };\n }\n \n // For other file types (PDF, etc.), use input_file\n return {\n type: 'input_file',\n fileUrl: url,\n };\n}\n\n/**\n * Convert data content (URL, string, or Uint8Array) to a string URL or data URI.\n */\nfunction convertDataContent(\n data: URL | string | Uint8Array,\n mediaType: string\n): string {\n if (data instanceof URL) {\n return data.toString();\n }\n\n if (data instanceof Uint8Array) {\n // Convert Uint8Array to base64 data URI\n const base64 = uint8ArrayToBase64(data);\n return `data:${mediaType};base64,${base64}`;\n }\n\n // String - could be URL or base64 data\n // If it starts with http(s) or data:, treat as URL/data URI\n if (data.startsWith('http://') || data.startsWith('https://') || data.startsWith('data:')) {\n return data;\n }\n\n // Otherwise assume it's base64 encoded data\n return `data:${mediaType};base64,${data}`;\n}\n\n/**\n * Convert Uint8Array to base64 string.\n */\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n // Use browser-compatible base64 encoding\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/**\n * SDK format for reasoning items returned from OpenRouter.\n * Used when extracting reasoning_details from providerMetadata.\n */\ninterface SdkReasoningItem {\n type?: string;\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n // Also support flattened API format\n text?: string;\n data?: string;\n index?: number;\n}\n\n/**\n * Extract reasoning_details from providerMetadata or providerOptions.\n * Checks multiple locations for backwards compatibility.\n */\nfunction extractReasoningDetails(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): JSONValue[] | undefined {\n // Check message-level metadata first\n const messageLevel =\n providerOptions?.openrouter?.reasoning_details ??\n providerMetadata?.openrouter?.reasoning_details;\n\n if (messageLevel && Array.isArray(messageLevel) && messageLevel.length > 0) {\n return messageLevel as JSONValue[];\n }\n\n // Check reasoning content parts for part-level metadata\n for (const part of content) {\n if (part.type === 'reasoning') {\n const partWithMeta = part as LanguageModelV3ReasoningPart & {\n providerMetadata?: Record<string, { reasoning_details?: JSONValue[] }>;\n providerOptions?: Record<string, { reasoning_details?: JSONValue[] }>;\n };\n const partLevel =\n partWithMeta.providerOptions?.openrouter?.reasoning_details ??\n partWithMeta.providerMetadata?.openrouter?.reasoning_details;\n if (partLevel && Array.isArray(partLevel) && partLevel.length > 0) {\n return partLevel as JSONValue[];\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Transform SDK reasoning format to API request format.\n * Flattens the structure for sending back to OpenRouter.\n */\nfunction transformReasoningToApiFormat(\n sdkItems: JSONValue[],\n): OpenRouterReasoningDetailItem[] {\n const apiItems: OpenRouterReasoningDetailItem[] = [];\n\n for (const rawItem of sdkItems) {\n if (typeof rawItem !== 'object' || rawItem === null) {\n continue;\n }\n const item = rawItem as SdkReasoningItem;\n\n const baseProps = {\n id: item.id,\n format: item.format ?? null,\n };\n\n let index = item.index ?? 0;\n\n // Handle already-flattened API format (reasoning.text, reasoning.summary, reasoning.encrypted)\n if (item.type === 'reasoning.text' && item.text !== undefined) {\n apiItems.push({\n type: 'reasoning.text',\n text: item.text,\n signature: item.signature ?? null,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.summary' && item.summary !== undefined) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: typeof item.summary === 'string' ? item.summary : '',\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.encrypted' && item.data !== undefined) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.data,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n // Handle SDK format (type: 'reasoning' with content/summary/encryptedContent)\n if (item.type === 'reasoning' || item.content || item.summary || item.encryptedContent) {\n // Transform content items to reasoning.text\n if (item.content && Array.isArray(item.content)) {\n for (const contentItem of item.content) {\n if (contentItem.type === 'reasoning_text' && contentItem.text) {\n apiItems.push({\n type: 'reasoning.text',\n text: contentItem.text,\n signature: item.signature ?? null,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform summary items to reasoning.summary\n if (item.summary && Array.isArray(item.summary)) {\n for (const summaryItem of item.summary) {\n if (summaryItem.type === 'summary_text' && summaryItem.text) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: summaryItem.text,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform encryptedContent to reasoning.encrypted (Gemini)\n if (item.encryptedContent) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.encryptedContent,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n return apiItems;\n}\n\n/**\n * Build OpenRouterReasoning object from reasoning detail items.\n * Combines all items into a single reasoning object for the API.\n */\nfunction buildReasoningFromDetails(\n items: OpenRouterReasoningDetailItem[],\n): OpenRouterReasoning | undefined {\n if (items.length === 0) {\n return undefined;\n }\n\n const reasoning: OpenRouterReasoning = {};\n\n // Collect all text items\n const textItems = items.filter((i) => i.type === 'reasoning.text' && i.text);\n if (textItems.length > 0) {\n reasoning.text = textItems.map((i) => i.text).join('');\n }\n\n // Collect all summary items\n const summaryItems = items.filter(\n (i) => i.type === 'reasoning.summary' && i.summary,\n );\n if (summaryItems.length > 0) {\n reasoning.summary = summaryItems.map((i) => i.summary).join('');\n }\n\n // Collect encrypted content (should be only one)\n const encryptedItem = items.find(\n (i) => i.type === 'reasoning.encrypted' && i.data,\n );\n if (encryptedItem?.data) {\n reasoning.encrypted = encryptedItem.data;\n }\n\n // Return undefined if no content\n if (!reasoning.text && !reasoning.summary && !reasoning.encrypted) {\n return undefined;\n }\n\n return reasoning;\n}\n\n/**\n * Convert assistant message content parts to OpenRouter Responses API format.\n * Tool calls become separate items in the output array.\n * Extracts reasoning_details from providerMetadata for multi-turn continuation.\n */\nfunction convertAssistantMessage(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n let textContent = '';\n\n // Extract reasoning details for multi-turn continuation\n const sdkReasoningDetails = extractReasoningDetails(\n content,\n providerMetadata,\n providerOptions,\n );\n const reasoningItems = sdkReasoningDetails\n ? transformReasoningToApiFormat(sdkReasoningDetails)\n : [];\n const reasoning = buildReasoningFromDetails(reasoningItems);\n\n for (const part of content) {\n switch (part.type) {\n case 'text':\n textContent += part.text;\n break;\n\n case 'reasoning':\n // Include reasoning as part of text\n textContent += part.text;\n break;\n\n case 'tool-call':\n // Tool calls are separate items in Responses API\n result.push({\n type: 'function_call',\n callId: part.toolCallId,\n name: part.toolName,\n arguments:\n typeof part.input === 'string'\n ? part.input\n : JSON.stringify(part.input),\n });\n break;\n\n case 'file':\n // Files in assistant messages - skip for now as they're typically for output\n break;\n\n case 'tool-result':\n // Tool results in assistant messages (provider-executed tools)\n result.push(convertToolResult(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(\n `Unknown assistant content type: ${(_exhaustive as { type: string }).type}`\n );\n }\n }\n }\n\n // If there's text content, add it as an assistant message first\n // Responses API uses simple string content for assistant messages\n if (textContent) {\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: textContent,\n };\n // Attach reasoning for multi-turn continuation\n if (reasoning) {\n assistantMessage.reasoning = reasoning;\n }\n result.unshift(assistantMessage);\n } else if (reasoning) {\n // Even without text, include reasoning if present (for tool-call only messages)\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: '',\n };\n assistantMessage.reasoning = reasoning;\n result.unshift(assistantMessage);\n }\n\n return result;\n}\n\n/**\n * Convert tool message content parts to OpenRouter Responses API format.\n */\nfunction convertToolMessage(\n content: Array<LanguageModelV3ToolResultPart | { type: 'tool-approval-response'; approvalId: string; approved: boolean; reason?: string }>\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const part of content) {\n if (part.type === 'tool-result') {\n result.push(convertToolResult(part));\n }\n // Skip tool-approval-response as it's not directly mapped to OpenRouter format\n }\n\n return result;\n}\n\n/**\n * Convert a tool result part to OpenRouter function_call_output format.\n */\nfunction convertToolResult(part: LanguageModelV3ToolResultPart): OpenRouterFunctionCallOutput {\n const output = convertToolResultOutput(part.output);\n\n return {\n type: 'function_call_output',\n callId: part.toolCallId,\n output: output.value,\n status: output.isError ? 'incomplete' : 'completed',\n };\n}\n\n/**\n * Convert tool result output to a string value.\n */\nfunction convertToolResultOutput(output: LanguageModelV3ToolResultOutput): {\n value: string;\n isError: boolean;\n} {\n switch (output.type) {\n case 'text':\n return { value: output.value, isError: false };\n\n case 'json':\n return { value: JSON.stringify(output.value), isError: false };\n\n case 'execution-denied':\n return {\n value: `Execution denied: ${output.reason ?? 'No reason provided'}`,\n isError: true,\n };\n\n case 'error-text':\n return { value: output.value, isError: true };\n\n case 'error-json':\n return { value: JSON.stringify(output.value), isError: true };\n\n case 'content': {\n // For content array, convert to string representation\n const textParts = output.value\n .filter((item): item is { type: 'text'; text: string } => item.type === 'text')\n .map((item) => item.text);\n return { value: textParts.join('\\n'), isError: false };\n }\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = output;\n throw new Error(`Unknown tool result output type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n}\n","/**\n * Reasoning details extraction for multi-turn conversations.\n *\n * WHY: Reasoning models (Claude, Gemini 3, o1) return encrypted/signed reasoning\n * content that MUST be sent back verbatim in subsequent turns. Without preserving\n * and re-sending reasoning_details, the model loses context about its previous\n * thought process, breaking extended reasoning chains.\n *\n * This module handles extraction from OpenRouter Responses API responses and\n * attachment to AI SDK content parts via providerMetadata.\n */\n\nimport type { JSONObject, JSONValue } from '@ai-sdk/provider';\nimport type {\n OpenResponsesNonStreamingResponse,\n OpenResponsesReasoning,\n} from '@openrouter/sdk/models';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Raw reasoning item from OpenRouter response output.\n */\nexport interface ReasoningOutputItem {\n type: 'reasoning';\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n}\n\n/**\n * Reasoning details in SDK format (as returned by OpenRouter).\n * This is the format we store in providerMetadata for round-tripping.\n */\nexport type ReasoningDetails = JSONValue[];\n\n// =============================================================================\n// Extraction Functions\n// =============================================================================\n\n/**\n * Extract reasoning details from a non-streaming OpenRouter Responses API response.\n *\n * Reasoning details can come from:\n * 1. Output items with type 'reasoning' (Responses API format)\n * 2. Message-level reasoning_details field (Chat Completions API format)\n *\n * @param response - The full OpenRouter Responses API response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetails(\n response: OpenResponsesNonStreamingResponse\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n // Extract from output items (Responses API format)\n for (const outputItem of response.output) {\n if ('type' in outputItem && outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as ReasoningOutputItem;\n\n // Store the full reasoning item structure for round-tripping\n // This preserves all provider-specific fields (signature, encryptedContent, etc.)\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n/**\n * Extract reasoning details from streaming response output items.\n *\n * Called at the end of streaming when we have the full response.\n *\n * @param outputItems - The output items from the completed stream response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetailsFromOutput(\n outputItems: Array<{ type: string; [key: string]: unknown }>\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n for (const outputItem of outputItems) {\n if (outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as unknown as ReasoningOutputItem;\n\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n// =============================================================================\n// Provider Detection\n// =============================================================================\n\n/**\n * Check if reasoning details contain encrypted content (Gemini thoughtSignature).\n *\n * This is important for Gemini 3 models which return 'completed' status\n * but expect continuation when tool calls exist with encrypted reasoning.\n *\n * @param reasoningDetails - The extracted reasoning details\n * @returns True if encrypted content is present\n */\nexport function hasEncryptedReasoning(\n reasoningDetails: ReasoningDetails | undefined\n): boolean {\n if (!reasoningDetails) {\n return false;\n }\n\n return reasoningDetails.some((d) => {\n if (typeof d === 'object' && d !== null) {\n const obj = d as Record<string, unknown>;\n return obj.encryptedContent != null || obj.type === 'reasoning.encrypted';\n }\n return false;\n });\n}\n\n/**\n * Build provider metadata object with reasoning details.\n *\n * @param reasoningDetails - The reasoning details to include\n * @returns Provider metadata object for attachment to content parts (SharedV3ProviderMetadata compatible)\n */\nexport function buildReasoningProviderMetadata(\n reasoningDetails: ReasoningDetails | undefined\n): Record<string, JSONObject> | undefined {\n if (!reasoningDetails || reasoningDetails.length === 0) {\n return undefined;\n }\n\n return {\n openrouter: {\n reasoning_details: reasoningDetails,\n } as JSONObject,\n };\n}\n\n// =============================================================================\n// Re-export types for convenience\n// =============================================================================\n\nexport type { OpenResponsesReasoning };\n","import type { LanguageModelV3FinishReason } from '@ai-sdk/provider';\n\n/**\n * Maps OpenRouter finish reasons to the AI SDK V3 unified format.\n *\n * Mapping table:\n * - 'end_turn', 'stop', 'stop_sequence' -> 'stop'\n * - 'max_tokens', 'length' -> 'length'\n * - 'tool_use', 'tool_calls' -> 'tool-calls'\n * - 'content_filter' -> 'content-filter'\n * - 'error' -> 'error'\n * - null/undefined/unknown -> 'other'\n *\n * @param finishReason - The finish reason from OpenRouter API response\n * @returns Object containing the unified finish reason and raw original value\n */\nexport function mapOpenRouterFinishReason(\n finishReason: string | null | undefined\n): LanguageModelV3FinishReason {\n // Handle null/undefined\n if (finishReason == null) {\n return { unified: 'other', raw: undefined };\n }\n\n // Map to unified format\n switch (finishReason) {\n case 'end_turn':\n case 'stop':\n case 'stop_sequence':\n return { unified: 'stop', raw: finishReason };\n\n case 'max_tokens':\n case 'length':\n return { unified: 'length', raw: finishReason };\n\n case 'tool_use':\n case 'tool_calls':\n return { unified: 'tool-calls', raw: finishReason };\n\n case 'content_filter':\n return { unified: 'content-filter', raw: finishReason };\n\n case 'error':\n return { unified: 'error', raw: finishReason };\n\n default:\n return { unified: 'other', raw: finishReason };\n }\n}\n","import type {\n EmbeddingModelV3,\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Result,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type { CreateEmbeddingsResponseBody } from '@openrouter/sdk/models/operations';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\n\n/**\n * OpenRouter embedding model implementing AI SDK V3 EmbeddingModelV3 interface.\n */\nexport class OpenRouterEmbeddingModel implements EmbeddingModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Maximum number of embeddings that can be generated in a single API call.\n * Set to 2048 as a reasonable default for most embedding models.\n */\n readonly maxEmbeddingsPerCall = 2048;\n\n /**\n * Whether the model supports parallel calls.\n */\n readonly supportsParallelCalls = true;\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doEmbed(options: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n });\n\n // Build request with provider routing options if configured\n const requestParams: {\n model: string;\n input: string[];\n user?: string;\n provider?: { order?: string[]; allowFallbacks?: boolean; requireParameters?: boolean };\n } = {\n model: this.modelId,\n input: options.values,\n };\n\n // Add provider routing options from model settings\n const modelOptions = this.settings.modelOptions;\n if (modelOptions?.user) {\n requestParams.user = modelOptions.user as string;\n }\n if (modelOptions?.provider) {\n requestParams.provider = modelOptions.provider;\n }\n\n // Make the embeddings request\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = await client.embeddings.generate(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n });\n\n // Handle string response (shouldn't happen in practice but type allows it)\n if (typeof response === 'string') {\n throw new Error(`Unexpected string response from embeddings API: ${response}`);\n }\n\n const responseBody = response as CreateEmbeddingsResponseBody;\n\n // Extract embeddings from response data\n // Sort by index to ensure correct order, then extract embedding vectors\n const sortedData = [...responseBody.data].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\n const embeddings = sortedData.map((item) => {\n // Embedding can be number[] or base64 string - we only support number[]\n if (typeof item.embedding === 'string') {\n throw new Error('Base64 encoded embeddings are not supported');\n }\n return item.embedding;\n });\n\n return {\n embeddings,\n usage: responseBody.usage\n ? { tokens: responseBody.usage.promptTokens }\n : undefined,\n warnings,\n };\n }\n}\n","import type {\n ImageModelV3,\n ImageModelV3CallOptions,\n SharedV3Warning,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter image model implementing AI SDK V3 ImageModelV3 interface.\n *\n * Note: Image generation is Tier 3 functionality. The doGenerate method\n * throws an error with guidance on tracking progress.\n */\nexport class OpenRouterImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n /**\n * Maximum number of images that can be generated in a single API call.\n */\n readonly maxImagesPerCall = 1;\n\n constructor(modelId: string, _settings: unknown) {\n this.modelId = modelId;\n }\n\n async doGenerate(_options: ImageModelV3CallOptions): Promise<{\n images: Array<string> | Array<Uint8Array>;\n warnings: Array<SharedV3Warning>;\n response: {\n timestamp: Date;\n modelId: string;\n headers: Record<string, string> | undefined;\n };\n }> {\n throw new Error(\n 'Image generation not yet supported. ' +\n 'See: https://github.com/OpenRouterTeam/ai-sdk-provider/issues/new?title=Image+generation+support'\n );\n }\n}\n","export const VERSION = '6.0.0-alpha.0';\n"],"mappings":"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","names":["import_provider_utils","extractReasoningDetails","extractReasoningDetails","import_provider_utils","import_sdk"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/openrouter-provider.ts","../src/chat/openrouter-chat-language-model.ts","../src/utils/build-provider-metadata.ts","../src/utils/build-usage.ts","../src/chat/convert-to-openrouter-messages.ts","../src/chat/extract-reasoning-details.ts","../src/chat/map-openrouter-finish-reason.ts","../src/embedding/openrouter-embedding-model.ts","../src/image/openrouter-image-model.ts","../src/version.ts"],"sourcesContent":["export {\n createOpenRouter,\n type OpenRouterProvider,\n type OpenRouterModelSettings,\n} from './openrouter-provider.js';\nexport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n OpenRouterPluginConfig,\n OpenRouterProviderRoutingConfig,\n} from './openrouter-config.js';\nexport { VERSION } from './version.js';\n\n// Default instance\nimport { createOpenRouter } from './openrouter-provider.js';\n\n/**\n * Default OpenRouter provider instance.\n *\n * Uses OPENROUTER_API_KEY environment variable for authentication.\n *\n * @example\n * ```ts\n * import { openrouter } from '@openrouter/ai-sdk-provider';\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n */\nexport const openrouter = createOpenRouter();\n","import type { ProviderV3 } from '@ai-sdk/provider';\nimport { loadApiKey, withoutTrailingSlash } from '@ai-sdk/provider-utils';\nimport { SDK_METADATA } from '@openrouter/sdk';\nimport { OpenRouterChatLanguageModel } from './chat/openrouter-chat-language-model.js';\nimport { OpenRouterEmbeddingModel } from './embedding/openrouter-embedding-model.js';\nimport { OpenRouterImageModel } from './image/openrouter-image-model.js';\nimport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n} from './openrouter-config.js';\n\ndeclare const __PACKAGE_VERSION__: string;\n\n/**\n * OpenRouter provider interface extending the AI SDK V3 ProviderV3 interface.\n *\n * The provider is callable - calling it directly is equivalent to calling languageModel().\n */\nexport interface OpenRouterProvider extends ProviderV3 {\n /**\n * Create a language model by calling the provider directly.\n */\n (modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a language model.\n */\n languageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a chat model (alias for languageModel).\n */\n chat(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create an embedding model.\n */\n embeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create a text embedding model.\n * @deprecated Use embeddingModel instead.\n */\n textEmbeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create an image model.\n */\n imageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an image model (alias for imageModel).\n */\n image(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an embedding model (alias for embeddingModel).\n * @deprecated Use embeddingModel instead.\n */\n embedding(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n}\n\n/**\n * Internal settings passed to model constructors.\n * Contains resolved API key and normalized configuration.\n */\nexport interface OpenRouterModelSettings {\n apiKey: string;\n baseURL: string;\n /**\n * User-Agent string used by `@openrouter/sdk`.\n *\n * Note: Setting a `User-Agent` header via `fetchOptions.headers` is ineffective because\n * the SDK sets it after merging user headers.\n */\n userAgent: string;\n headers?: Record<string, string>;\n fetch?: typeof globalThis.fetch;\n extraBody?: Record<string, unknown>;\n modelOptions?: OpenRouterModelOptions;\n}\n\n/**\n * Creates an OpenRouter provider instance for the AI SDK.\n *\n * @description\n * Factory function that creates an OpenRouter provider compatible with the AI SDK v3 provider\n * specification. The provider can create language models, embedding models, and image models\n * that route requests through OpenRouter to various AI providers (OpenAI, Anthropic, Google, etc.).\n *\n * The returned provider is callable - you can use it directly as a function to create language\n * models, or use its methods for specific model types.\n *\n * @param options - Provider settings including API key, base URL, headers, and fetch implementation.\n * If no API key is provided, it will be loaded from the OPENROUTER_API_KEY environment variable.\n * @returns An OpenRouter provider that can create language, embedding, and image models.\n *\n * @example Basic usage with environment variable\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * // Uses OPENROUTER_API_KEY from environment\n * const openrouter = createOpenRouter();\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example With explicit API key\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * const openrouter = createOpenRouter({\n * apiKey: process.env.OPENROUTER_API_KEY,\n * });\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example Creating different model types\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Language model (callable shorthand)\n * const chat = openrouter('anthropic/claude-3.5-sonnet');\n *\n * // Embedding model\n * const embeddings = openrouter.embeddingModel('openai/text-embedding-3-small');\n *\n * // Image model\n * const image = openrouter.imageModel('openai/dall-e-3');\n * ```\n *\n * @example Model variants\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Online search variant - model has web search capabilities\n * const online = openrouter('anthropic/claude-3.5-sonnet:online');\n *\n * // Nitro variant - faster inference\n * const nitro = openrouter('anthropic/claude-3.5-sonnet:nitro');\n *\n * // Floor pricing variant - routes to cheapest provider\n * const floor = openrouter('anthropic/claude-3.5-sonnet:floor');\n *\n * // Free tier variant\n * const free = openrouter('meta-llama/llama-3-8b-instruct:free');\n * ```\n */\nexport function createOpenRouter(\n options: OpenRouterProviderSettings = {}\n): OpenRouterProvider {\n // Normalize base URL: accept baseURL or baseUrl, strip trailing slash\n // The fallback ensures we always have a value, so the non-null assertion is safe\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? options.baseUrl ?? 'https://openrouter.ai/api/v1'\n )!;\n\n /**\n * Resolves model settings at model creation time.\n * API key is loaded here (not at provider creation or request time) per Decision 1 - Fail Fast.\n */\n const getModelSettings = (modelOptions?: OpenRouterModelOptions): OpenRouterModelSettings => {\n // Load API key at model creation time\n const apiKey = loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'OPENROUTER_API_KEY',\n description: 'OpenRouter',\n });\n\n const providerUserAgentPart = `ai-sdk-provider/${__PACKAGE_VERSION__}`;\n\n // Allow overriding the base UA via headers, but always append our provider token.\n const baseUserAgent =\n options.headers?.['user-agent'] ?? options.headers?.['User-Agent'] ?? SDK_METADATA.userAgent;\n\n const userAgent = baseUserAgent.includes('ai-sdk-provider/')\n ? baseUserAgent\n : `${baseUserAgent} ${providerUserAgentPart}`;\n\n const {\n 'User-Agent': _ignoredUserAgent,\n 'user-agent': _ignoredUserAgentLower,\n ...forwardHeaders\n } = options.headers ?? {};\n\n return {\n apiKey,\n baseURL,\n userAgent,\n headers: Object.keys(forwardHeaders).length > 0 ? forwardHeaders : undefined,\n fetch: options.fetch,\n extraBody: options.extraBody,\n modelOptions,\n };\n };\n\n /**\n * Create a language model.\n */\n const languageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterChatLanguageModel => {\n return new OpenRouterChatLanguageModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an embedding model.\n */\n const embeddingModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterEmbeddingModel => {\n return new OpenRouterEmbeddingModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an image model.\n */\n const imageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterImageModel => {\n return new OpenRouterImageModel(modelId, getModelSettings(modelOptions));\n };\n\n // Create the callable provider object\n const provider = Object.assign(\n // Make provider callable - calling it directly creates a language model\n (modelId: string, modelOptions?: OpenRouterModelOptions) => languageModel(modelId, modelOptions),\n {\n specificationVersion: 'v3' as const,\n languageModel,\n chat: languageModel,\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n imageModel,\n image: imageModel,\n embedding: embeddingModel,\n }\n );\n\n return provider;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FunctionTool,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3ToolChoice,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type {\n OpenResponsesRequest,\n OpenResponsesNonStreamingResponse,\n OpenResponsesStreamEvent,\n OpenResponsesRequestToolFunction,\n OpenAIResponsesToolChoiceUnion,\n} from '@openrouter/sdk/models';\nimport type { EventStream } from '@openrouter/sdk/lib/event-streams';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\nimport { buildProviderMetadata } from '../utils/build-provider-metadata.js';\nimport { buildUsage } from '../utils/build-usage.js';\nimport { convertToOpenRouterMessages } from './convert-to-openrouter-messages.js';\nimport {\n extractReasoningDetails,\n hasEncryptedReasoning,\n buildReasoningProviderMetadata,\n type ReasoningOutputItem,\n} from './extract-reasoning-details.js';\nimport { mapOpenRouterFinishReason } from './map-openrouter-finish-reason.js';\n\n/**\n * OpenRouter chat language model implementing AI SDK V3 LanguageModelV3 interface.\n *\n * Uses the OpenRouter Responses API for both streaming and non-streaming requests.\n */\nexport class OpenRouterChatLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Supported URL patterns by media type.\n * OpenRouter Chat API only supports image URLs natively.\n * PDF URLs are not supported - use PDF data URIs or the Responses API instead.\n */\n readonly supportedUrls: Record<string, RegExp[]> = {\n 'image/*': [/^https?:\\/\\/.*$/],\n };\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3GenerateResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n userAgent: this.settings.userAgent,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (non-streaming)\n const requestParams: OpenResponsesRequest & { stream: false } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: false,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the non-streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as OpenResponsesNonStreamingResponse;\n\n // Build content array from Responses API output\n const content: LanguageModelV3Content[] = [];\n\n // Extract reasoning details for multi-turn conversation support\n // These must be preserved and sent back in subsequent turns for reasoning models\n const reasoningDetails = extractReasoningDetails(response);\n const reasoningMetadata = buildReasoningProviderMetadata(reasoningDetails);\n\n // Process output items\n for (const outputItem of response.output) {\n if (outputItem.type === 'reasoning') {\n // Extract reasoning text from content array or summary\n const reasoningItem = outputItem as ReasoningOutputItem;\n const reasoningText =\n reasoningItem.content\n ?.filter((c) => c.type === 'reasoning_text')\n .map((c) => c.text)\n .join('') ||\n reasoningItem.summary\n ?.filter((c) => c.type === 'summary_text')\n .map((c) => c.text)\n .join('') ||\n '';\n\n if (reasoningText) {\n // Attach reasoning_details to the reasoning part for multi-turn support\n content.push({\n type: 'reasoning',\n text: reasoningText,\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n } else if (outputItem.type === 'message') {\n // Extract text content from message\n const messageItem = outputItem as {\n type: 'message';\n content: Array<{ type: string; text?: string }>;\n };\n for (const contentItem of messageItem.content) {\n if (contentItem.type === 'output_text' && contentItem.text) {\n content.push({\n type: 'text',\n text: contentItem.text,\n });\n }\n }\n } else if (outputItem.type === 'function_call') {\n // Handle tool/function calls\n const functionCallItem = outputItem as {\n type: 'function_call';\n callId: string;\n name: string;\n arguments?: string;\n };\n // Attach reasoning_details to tool-call parts for multi-turn support\n // This is critical for Gemini 3 with thoughtSignature\n content.push({\n type: 'tool-call',\n toolCallId: functionCallItem.callId,\n toolName: functionCallItem.name,\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n input: functionCallItem.arguments || '{}',\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n }\n\n // Use outputText as fallback if no text content was extracted\n if (response.outputText && !content.some((c) => c.type === 'text')) {\n content.push({\n type: 'text',\n text: response.outputText,\n });\n }\n\n // Build finish reason based on response status\n let finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Gemini 3 thoughtSignature fix: when there are tool calls with encrypted\n // reasoning, the model returns 'completed' but expects continuation.\n // Override to 'tool-calls' so the AI SDK knows to continue the conversation.\n const hasToolCalls = content.some((c) => c.type === 'tool-call');\n if (\n hasToolCalls &&\n hasEncryptedReasoning(reasoningDetails) &&\n finishReason.unified === 'stop'\n ) {\n finishReason = { unified: 'tool-calls', raw: finishReason.raw };\n }\n\n // Build usage from Responses API format\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Note: The Responses API doesn't include 'provider' field directly\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider in response\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens: response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n return {\n content,\n finishReason,\n usage,\n warnings,\n providerMetadata,\n request: {\n body: requestParams,\n },\n response: {\n id: response.id,\n timestamp: new Date(response.createdAt * 1000),\n modelId: response.model,\n },\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3StreamResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n userAgent: this.settings.userAgent,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (streaming)\n const requestParams: OpenResponsesRequest & { stream: true } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: true,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const eventStream = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as EventStream<OpenResponsesStreamEvent>;\n\n // Track state for stream transformation\n const state = createStreamState();\n\n // Transform the EventStream to AI SDK V3 stream parts\n const transformedStream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n // Emit stream-start first\n controller.enqueue({\n type: 'stream-start',\n warnings,\n });\n\n try {\n for await (const event of eventStream) {\n const parts = transformResponsesEvent(event, state);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n } catch (error) {\n controller.enqueue({\n type: 'error',\n error,\n });\n } finally {\n controller.close();\n }\n },\n });\n\n return {\n stream: transformedStream,\n request: {\n body: requestParams,\n },\n };\n }\n}\n\n/**\n * Stream state for tracking response metadata and content parts.\n */\ninterface StreamState {\n responseId: string | undefined;\n responseModel: string | undefined;\n responseCreated: number | undefined;\n textStarted: boolean;\n textId: string;\n reasoningStarted: boolean;\n reasoningId: string;\n textEnded: boolean;\n reasoningEnded: boolean;\n sourceIds: string[];\n toolCalls: Map<string, { name?: string; argumentsStarted: boolean }>;\n}\n\nfunction createStreamState(): StreamState {\n return {\n responseId: undefined,\n responseModel: undefined,\n responseCreated: undefined,\n textStarted: false,\n textId: 'text-0',\n reasoningStarted: false,\n reasoningId: 'reasoning-0',\n textEnded: false,\n reasoningEnded: false,\n sourceIds: [],\n toolCalls: new Map(),\n };\n}\n\n/**\n * Transform a Responses API stream event to AI SDK V3 stream parts.\n */\nfunction transformResponsesEvent(\n event: OpenResponsesStreamEvent,\n state: StreamState\n): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n\n switch (event.type) {\n // Response lifecycle events\n case 'response.created':\n case 'response.in_progress': {\n // Capture response metadata from initial events\n if (event.response) {\n state.responseId = event.response.id;\n state.responseModel = event.response.model;\n state.responseCreated = event.response.createdAt;\n }\n break;\n }\n\n // Text streaming\n case 'response.output_text.delta': {\n // Emit text-start if not started\n if (!state.textStarted) {\n state.textStarted = true;\n parts.push({\n type: 'text-start',\n id: state.textId,\n });\n }\n\n // Emit text-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'text-delta',\n id: state.textId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.output_text.done': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n break;\n }\n\n // Reasoning streaming\n case 'response.reasoning_text.delta': {\n // Emit reasoning-start if not started\n if (!state.reasoningStarted) {\n state.reasoningStarted = true;\n parts.push({\n type: 'reasoning-start',\n id: state.reasoningId,\n });\n }\n\n // Emit reasoning-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'reasoning-delta',\n id: state.reasoningId,\n delta: event.delta,\n });\n }\n break;\n }\n\n // Function call arguments streaming\n case 'response.function_call_arguments.delta': {\n const toolCallId = event.itemId;\n let toolState = state.toolCalls.get(toolCallId);\n\n if (!toolState) {\n toolState = { argumentsStarted: false };\n state.toolCalls.set(toolCallId, toolState);\n }\n\n // Emit tool-input-start if not started\n if (!toolState.argumentsStarted) {\n toolState.argumentsStarted = true;\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: toolState.name ?? '', // Will be filled in by output_item.added\n });\n }\n\n // Emit tool-input-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.function_call_arguments.done': {\n const toolCallId = event.itemId;\n const toolState = state.toolCalls.get(toolCallId);\n\n // If we haven't started tool call yet, emit start + delta with full args\n if (!toolState?.argumentsStarted) {\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: event.name,\n });\n // Default to empty object when arguments is undefined/empty\n const args = event.arguments || '{}';\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: args,\n });\n }\n\n // Emit tool-input-end\n parts.push({\n type: 'tool-input-end',\n id: toolCallId,\n });\n\n // Emit tool-call with complete tool call data\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n parts.push({\n type: 'tool-call',\n toolCallId,\n toolName: event.name,\n input: event.arguments || '{}',\n });\n break;\n }\n\n // Output item events (for function call metadata)\n case 'response.output_item.added': {\n if (event.item.type === 'function_call') {\n const funcItem = event.item as {\n type: 'function_call';\n callId?: string;\n name: string;\n };\n const toolCallId = funcItem.callId ?? `tool-${event.outputIndex}`;\n const toolState = state.toolCalls.get(toolCallId) ?? {\n argumentsStarted: false,\n };\n toolState.name = funcItem.name;\n state.toolCalls.set(toolCallId, toolState);\n }\n break;\n }\n\n // Annotation events (web search sources)\n case 'response.output_text.annotation.added': {\n const annotation = event.annotation;\n if (annotation.type === 'url_citation') {\n const urlAnnotation = annotation as {\n type: 'url_citation';\n url: string;\n title: string;\n };\n const sourceId = `source-${state.sourceIds.length}`;\n state.sourceIds.push(sourceId);\n parts.push({\n type: 'source',\n sourceType: 'url',\n id: sourceId,\n url: urlAnnotation.url,\n title: urlAnnotation.title,\n });\n }\n break;\n }\n\n // Response completed - extract final usage data\n case 'response.completed': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n\n // End reasoning if started and not ended\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n // Emit response-metadata\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Build finish reason based on response status\n const finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Build usage\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Response incomplete or failed\n case 'response.incomplete':\n case 'response.failed': {\n // End any open content parts\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Map finish reason\n const finishReason =\n event.type === 'response.failed'\n ? mapOpenRouterFinishReason('error')\n : mapOpenRouterFinishReason(response.status ?? 'incomplete');\n\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined,\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Error event\n case 'error': {\n const errorEvent = event as {\n type: 'error';\n error?: { message?: string };\n };\n parts.push({\n type: 'error',\n error: new Error(\n errorEvent.error?.message ?? 'Unknown streaming error'\n ),\n });\n break;\n }\n\n // Ignored events (handled implicitly or not needed)\n case 'response.output_item.done':\n case 'response.content_part.added':\n case 'response.content_part.done':\n case 'response.refusal.delta':\n case 'response.refusal.done':\n case 'response.reasoning_text.done':\n case 'response.reasoning_summary_part.added':\n case 'response.reasoning_summary_part.done':\n case 'response.reasoning_summary_text.delta':\n case 'response.reasoning_summary_text.done':\n case 'response.image_generation_call.in_progress':\n case 'response.image_generation_call.generating':\n case 'response.image_generation_call.partial_image':\n case 'response.image_generation_call.completed':\n // These events are either handled by other events or not relevant for AI SDK\n break;\n }\n\n return parts;\n}\n\n/**\n * Convert AI SDK tools to OpenRouter Responses API format.\n * Only 'function' type tools are supported.\n */\nfunction convertToolsToResponsesFormat(\n tools: LanguageModelV3CallOptions['tools'],\n warnings: SharedV3Warning[]\n): OpenResponsesRequestToolFunction[] {\n if (!tools || tools.length === 0) {\n return [];\n }\n\n return tools\n .map((tool): OpenResponsesRequestToolFunction | null => {\n if (tool.type !== 'function') {\n warnings.push({\n type: 'unsupported',\n feature: `tool type '${tool.type}'`,\n details: `Only 'function' type tools are supported. Tool '${(tool as { name?: string }).name ?? 'unknown'}' has type '${tool.type}'.`,\n });\n return null;\n }\n\n const functionTool = tool as LanguageModelV3FunctionTool;\n return {\n type: 'function',\n name: functionTool.name,\n description: functionTool.description ?? null,\n parameters: functionTool.inputSchema as { [k: string]: unknown } | null,\n };\n })\n .filter((tool): tool is OpenResponsesRequestToolFunction => tool !== null);\n}\n\n/**\n * Convert AI SDK toolChoice to OpenRouter Responses API format.\n *\n * Mapping:\n * - 'auto' -> 'auto'\n * - 'none' -> 'none'\n * - 'required' -> 'required'\n * - { type: 'tool', toolName } -> { type: 'function', name: toolName }\n */\nfunction convertToolChoiceToResponsesFormat(\n toolChoice: LanguageModelV3ToolChoice | undefined\n): OpenAIResponsesToolChoiceUnion | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return 'auto';\n case 'none':\n return 'none';\n case 'required':\n return 'required';\n case 'tool':\n return {\n type: 'function',\n name: toolChoice.toolName,\n };\n default:\n return undefined;\n }\n}\n\n/**\n * Convert AI SDK responseFormat to OpenRouter Responses API text.format.\n *\n * Mapping:\n * - { type: 'text' } -> { type: 'text' }\n * - { type: 'json' } -> { type: 'json_object' } (no schema)\n * - { type: 'json', schema, name } -> { type: 'json_schema', name, schema } (with schema)\n */\nfunction convertResponseFormatToText(\n responseFormat: LanguageModelV3CallOptions['responseFormat']\n): OpenResponsesRequest['text'] | undefined {\n if (!responseFormat) {\n return undefined;\n }\n\n if (responseFormat.type === 'text') {\n return {\n format: { type: 'text' },\n };\n }\n\n if (responseFormat.type === 'json') {\n // If a schema is provided, use json_schema format\n if (responseFormat.schema) {\n return {\n format: {\n type: 'json_schema',\n name: responseFormat.name ?? 'response',\n description: responseFormat.description,\n schema: responseFormat.schema as { [k: string]: unknown },\n },\n };\n }\n // No schema - use simple json_object format\n return {\n format: { type: 'json_object' },\n };\n }\n\n return undefined;\n}\n","import type { JSONObject } from '@ai-sdk/provider';\nimport type { ChatGenerationTokenUsage } from '@openrouter/sdk/models';\n\n/**\n * OpenRouter-specific provider metadata structure.\n */\nexport interface OpenRouterProviderMetadata {\n /**\n * The response ID from OpenRouter.\n */\n responseId?: string;\n\n /**\n * The upstream provider that served the request.\n */\n provider?: string;\n\n /**\n * Detailed usage information.\n */\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n promptTokensDetails?: {\n cachedTokens?: number;\n cacheWriteTokens?: number;\n audioTokens?: number;\n videoTokens?: number;\n };\n completionTokensDetails?: {\n reasoningTokens?: number;\n imageTokens?: number;\n };\n /**\n * Cost in USD (omit if unavailable).\n */\n cost?: number;\n /**\n * Whether the request used BYOK (Bring Your Own Key).\n */\n isByok?: boolean;\n /**\n * Detailed cost breakdown.\n */\n costDetails?: JSONObject;\n };\n}\n\n/**\n * Extended prompt tokens details with fields not in SDK types.\n */\nexport interface ExtendedPromptTokensDetails {\n cachedTokens?: number | null;\n cacheWriteTokens?: number | null;\n audioTokens?: number | null;\n videoTokens?: number | null;\n}\n\n/**\n * Extended completion tokens details with fields not in SDK types.\n */\nexport interface ExtendedCompletionTokensDetails {\n reasoningTokens?: number | null;\n imageTokens?: number | null;\n}\n\n/**\n * Extended usage type with additional fields from raw OpenRouter API response.\n * The SDK types don't include cost/is_byok but the API returns them.\n */\nexport interface OpenRouterUsageExtended extends Omit<ChatGenerationTokenUsage, 'promptTokensDetails' | 'completionTokensDetails'> {\n cost?: number;\n isByok?: boolean;\n costDetails?: JSONObject;\n promptTokensDetails?: ExtendedPromptTokensDetails | null;\n completionTokensDetails?: ExtendedCompletionTokensDetails | null;\n}\n\n/**\n * Response data from OpenRouter API used to build provider metadata.\n * Note: The SDK transforms snake_case to camelCase for all fields.\n * The `provider` field exists in raw API responses but isn't in SDK types.\n */\nexport interface OpenRouterResponseData {\n id?: string;\n /**\n * The upstream provider that served the request (e.g. \"Google\", \"Anthropic\").\n * This field exists in the raw API response but isn't in SDK TypeScript types.\n */\n provider?: string;\n /**\n * Usage data in camelCase (as transformed by SDK).\n */\n usage?: OpenRouterUsageExtended;\n}\n\n/**\n * Filters out undefined values from an object, returning only defined properties.\n * This ensures providerMetadata is valid JSON (undefined is not a valid JSON value).\n */\nfunction filterUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined)\n ) as Partial<T>;\n}\n\n/**\n * Builds provider metadata from OpenRouter API response data.\n *\n * @param response - The response data from OpenRouter API (with camelCase fields from SDK).\n * @returns Provider metadata in the format expected by AI SDK.\n */\nexport function buildProviderMetadata(\n response: OpenRouterResponseData | undefined\n): Record<string, JSONObject> | undefined {\n if (!response) {\n return undefined;\n }\n\n const usage = response.usage;\n const usageMetadata: OpenRouterProviderMetadata['usage'] | undefined = usage\n ? filterUndefined({\n promptTokens: usage.promptTokens,\n completionTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n ...(usage.promptTokensDetails && {\n promptTokensDetails: filterUndefined({\n cachedTokens: usage.promptTokensDetails.cachedTokens ?? undefined,\n cacheWriteTokens: usage.promptTokensDetails.cacheWriteTokens ?? undefined,\n audioTokens: usage.promptTokensDetails.audioTokens ?? undefined,\n videoTokens: usage.promptTokensDetails.videoTokens ?? undefined,\n }),\n }),\n ...(usage.completionTokensDetails && {\n completionTokensDetails: filterUndefined({\n reasoningTokens: usage.completionTokensDetails.reasoningTokens ?? undefined,\n imageTokens: usage.completionTokensDetails.imageTokens ?? undefined,\n }),\n }),\n cost: usage.cost,\n isByok: usage.isByok,\n costDetails: usage.costDetails,\n })\n : undefined;\n\n const metadata: OpenRouterProviderMetadata = filterUndefined({\n responseId: response.id,\n provider: response.provider,\n usage: usageMetadata,\n });\n\n return {\n openrouter: metadata as unknown as JSONObject,\n };\n}\n","import type { LanguageModelV3Usage, JSONObject } from '@ai-sdk/provider';\n\n/**\n * Raw usage data from OpenRouter API response.\n */\nexport interface OpenRouterRawUsage {\n inputTokens?: number;\n outputTokens?: number;\n inputTokensDetails?: {\n cachedTokens?: number;\n };\n outputTokensDetails?: {\n reasoningTokens?: number;\n };\n}\n\n/**\n * Builds a LanguageModelV3Usage object from OpenRouter API usage data.\n *\n * @param usage - The raw usage data from the OpenRouter API response.\n * @returns A LanguageModelV3Usage object with standardized token counts.\n */\nexport function buildUsage(usage: OpenRouterRawUsage | undefined): LanguageModelV3Usage {\n if (!usage) {\n return {\n inputTokens: {\n total: 0,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n }\n\n // Convert to JSONObject-compatible format for raw field\n const rawUsage: JSONObject = {\n inputTokens: usage.inputTokens ?? null,\n outputTokens: usage.outputTokens ?? null,\n ...(usage.inputTokensDetails && {\n inputTokensDetails: {\n cachedTokens: usage.inputTokensDetails.cachedTokens ?? null,\n },\n }),\n ...(usage.outputTokensDetails && {\n outputTokensDetails: {\n reasoningTokens: usage.outputTokensDetails.reasoningTokens ?? null,\n },\n }),\n };\n\n return {\n inputTokens: {\n total: usage.inputTokens ?? 0,\n noCache: undefined,\n cacheRead: usage.inputTokensDetails?.cachedTokens,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: usage.outputTokens ?? 0,\n text: undefined,\n reasoning: usage.outputTokensDetails?.reasoningTokens,\n },\n raw: rawUsage,\n };\n}\n","import type {\n LanguageModelV3Prompt,\n LanguageModelV3Message,\n LanguageModelV3TextPart,\n LanguageModelV3FilePart,\n LanguageModelV3ReasoningPart,\n LanguageModelV3ToolCallPart,\n LanguageModelV3ToolResultPart,\n LanguageModelV3ToolResultOutput,\n JSONValue,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter Responses API input item types.\n * These match the OpenResponsesEasyInputMessage format used by the Responses API.\n */\nexport type OpenRouterInputItem =\n | OpenRouterEasyInputMessage\n | OpenRouterFunctionCall\n | OpenRouterFunctionCallOutput;\n\n/**\n * Reasoning details item format for API requests.\n * Used to preserve reasoning context across multi-turn conversations.\n */\nexport interface OpenRouterReasoningDetailItem {\n type: 'reasoning.text' | 'reasoning.summary' | 'reasoning.encrypted';\n id?: string;\n format?: string | null;\n index: number;\n text?: string; // For reasoning.text\n signature?: string | null; // For reasoning.text (Claude)\n summary?: string; // For reasoning.summary\n data?: string; // For reasoning.encrypted (Gemini)\n}\n\n/**\n * Reasoning object for assistant messages.\n * Contains the reasoning details to send back to the API.\n */\nexport interface OpenRouterReasoning {\n text?: string;\n summary?: string;\n encrypted?: string;\n}\n\n/**\n * Easy input message format for Responses API.\n * Supports user, system, assistant, and developer roles.\n */\nexport interface OpenRouterEasyInputMessage {\n type?: 'message';\n role: 'user' | 'system' | 'assistant' | 'developer';\n content: string | OpenRouterInputContent[];\n reasoning?: OpenRouterReasoning;\n}\n\nexport interface OpenRouterFunctionCall {\n type: 'function_call';\n callId: string;\n name: string;\n arguments: string;\n}\n\nexport interface OpenRouterFunctionCallOutput {\n type: 'function_call_output';\n callId: string;\n output: string;\n status: 'completed' | 'incomplete';\n}\n\n/**\n * Input content types for Responses API.\n * Uses 'input_text', 'input_image', 'input_file' type prefixes.\n */\nexport type OpenRouterInputContent =\n | { type: 'input_text'; text: string }\n | { type: 'input_image'; imageUrl: string; detail?: 'auto' | 'low' | 'high' }\n | { type: 'input_file'; fileUrl: string; filename?: string };\n\n/**\n * Converts AI SDK V3 prompt format to OpenRouter Responses API input format.\n *\n * Mapping table:\n * - system { content } -> { role: 'system', content: string }\n * - user text -> { role: 'user', content: [{ type: 'input_text', text }] }\n * - user image -> { role: 'user', content: [{ type: 'input_image', imageUrl }] }\n * - user file -> { role: 'user', content: [{ type: 'input_file', fileUrl }] }\n * - assistant text -> { role: 'assistant', content: string }\n * - assistant tool-call -> { type: 'function_call', ... }\n * - tool result -> { type: 'function_call_output', ... }\n *\n * @param prompt - The AI SDK V3 prompt\n * @returns Array of input items in OpenRouter Responses API format\n */\nexport function convertToOpenRouterMessages(\n prompt: LanguageModelV3Prompt\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const message of prompt) {\n const converted = convertMessage(message);\n result.push(...converted);\n }\n\n return result;\n}\n\n/**\n * Convert a single V3 message to OpenRouter Responses API format.\n * May return multiple items (e.g., when assistant has text + tool calls).\n */\nfunction convertMessage(message: LanguageModelV3Message): OpenRouterInputItem[] {\n // Extract providerOptions from the message for reasoning_details\n const messageWithOptions = message as LanguageModelV3Message & {\n providerOptions?: Record<string, Record<string, unknown>>;\n providerMetadata?: Record<string, Record<string, unknown>>;\n };\n const providerOptions = messageWithOptions.providerOptions;\n const providerMetadata = messageWithOptions.providerMetadata;\n\n switch (message.role) {\n case 'system':\n return [{ role: 'system', content: message.content }];\n\n case 'user':\n return [convertUserMessage(message.content)];\n\n case 'assistant':\n return convertAssistantMessage(message.content, providerMetadata, providerOptions);\n\n case 'tool':\n return convertToolMessage(message.content);\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = message;\n throw new Error(`Unknown message role: ${(_exhaustive as { role: string }).role}`);\n }\n }\n}\n\n/**\n * Convert user message content parts to OpenRouter Responses API format.\n */\nfunction convertUserMessage(\n content: Array<LanguageModelV3TextPart | LanguageModelV3FilePart>\n): OpenRouterEasyInputMessage {\n const convertedContent: OpenRouterInputContent[] = [];\n\n for (const part of content) {\n switch (part.type) {\n case 'text': {\n convertedContent.push({ type: 'input_text', text: part.text });\n break;\n }\n\n case 'file':\n convertedContent.push(convertFilePart(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(`Unknown user content type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n }\n\n return { role: 'user', content: convertedContent };\n}\n\n/**\n * Convert a file part to the appropriate OpenRouter Responses API format.\n *\n * OpenRouter's Responses API uses 'input_image' for images and 'input_file' for other files.\n */\nfunction convertFilePart(part: LanguageModelV3FilePart): OpenRouterInputContent {\n const url = convertDataContent(part.data, part.mediaType);\n \n // Check if it's an image based on media type\n if (part.mediaType.startsWith('image/')) {\n return {\n type: 'input_image',\n imageUrl: url,\n detail: 'auto',\n };\n }\n \n // For other file types (PDF, etc.), use input_file\n return {\n type: 'input_file',\n fileUrl: url,\n };\n}\n\n/**\n * Convert data content (URL, string, or Uint8Array) to a string URL or data URI.\n */\nfunction convertDataContent(\n data: URL | string | Uint8Array,\n mediaType: string\n): string {\n if (data instanceof URL) {\n return data.toString();\n }\n\n if (data instanceof Uint8Array) {\n // Convert Uint8Array to base64 data URI\n const base64 = uint8ArrayToBase64(data);\n return `data:${mediaType};base64,${base64}`;\n }\n\n // String - could be URL or base64 data\n // If it starts with http(s) or data:, treat as URL/data URI\n if (data.startsWith('http://') || data.startsWith('https://') || data.startsWith('data:')) {\n return data;\n }\n\n // Otherwise assume it's base64 encoded data\n return `data:${mediaType};base64,${data}`;\n}\n\n/**\n * Convert Uint8Array to base64 string.\n */\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n // Use browser-compatible base64 encoding\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/**\n * SDK format for reasoning items returned from OpenRouter.\n * Used when extracting reasoning_details from providerMetadata.\n */\ninterface SdkReasoningItem {\n type?: string;\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n // Also support flattened API format\n text?: string;\n data?: string;\n index?: number;\n}\n\n/**\n * Extract reasoning_details from providerMetadata or providerOptions.\n * Checks multiple locations for backwards compatibility.\n */\nfunction extractReasoningDetails(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): JSONValue[] | undefined {\n // Check message-level metadata first\n const messageLevel =\n providerOptions?.openrouter?.reasoning_details ??\n providerMetadata?.openrouter?.reasoning_details;\n\n if (messageLevel && Array.isArray(messageLevel) && messageLevel.length > 0) {\n return messageLevel as JSONValue[];\n }\n\n // Check reasoning content parts for part-level metadata\n for (const part of content) {\n if (part.type === 'reasoning') {\n const partWithMeta = part as LanguageModelV3ReasoningPart & {\n providerMetadata?: Record<string, { reasoning_details?: JSONValue[] }>;\n providerOptions?: Record<string, { reasoning_details?: JSONValue[] }>;\n };\n const partLevel =\n partWithMeta.providerOptions?.openrouter?.reasoning_details ??\n partWithMeta.providerMetadata?.openrouter?.reasoning_details;\n if (partLevel && Array.isArray(partLevel) && partLevel.length > 0) {\n return partLevel as JSONValue[];\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Transform SDK reasoning format to API request format.\n * Flattens the structure for sending back to OpenRouter.\n */\nfunction transformReasoningToApiFormat(\n sdkItems: JSONValue[],\n): OpenRouterReasoningDetailItem[] {\n const apiItems: OpenRouterReasoningDetailItem[] = [];\n\n for (const rawItem of sdkItems) {\n if (typeof rawItem !== 'object' || rawItem === null) {\n continue;\n }\n const item = rawItem as SdkReasoningItem;\n\n const baseProps = {\n id: item.id,\n format: item.format ?? null,\n };\n\n let index = item.index ?? 0;\n\n // Handle already-flattened API format (reasoning.text, reasoning.summary, reasoning.encrypted)\n if (item.type === 'reasoning.text' && item.text !== undefined) {\n apiItems.push({\n type: 'reasoning.text',\n text: item.text,\n signature: item.signature ?? null,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.summary' && item.summary !== undefined) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: typeof item.summary === 'string' ? item.summary : '',\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.encrypted' && item.data !== undefined) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.data,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n // Handle SDK format (type: 'reasoning' with content/summary/encryptedContent)\n if (item.type === 'reasoning' || item.content || item.summary || item.encryptedContent) {\n // Transform content items to reasoning.text\n if (item.content && Array.isArray(item.content)) {\n for (const contentItem of item.content) {\n if (contentItem.type === 'reasoning_text' && contentItem.text) {\n apiItems.push({\n type: 'reasoning.text',\n text: contentItem.text,\n signature: item.signature ?? null,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform summary items to reasoning.summary\n if (item.summary && Array.isArray(item.summary)) {\n for (const summaryItem of item.summary) {\n if (summaryItem.type === 'summary_text' && summaryItem.text) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: summaryItem.text,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform encryptedContent to reasoning.encrypted (Gemini)\n if (item.encryptedContent) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.encryptedContent,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n return apiItems;\n}\n\n/**\n * Build OpenRouterReasoning object from reasoning detail items.\n * Combines all items into a single reasoning object for the API.\n */\nfunction buildReasoningFromDetails(\n items: OpenRouterReasoningDetailItem[],\n): OpenRouterReasoning | undefined {\n if (items.length === 0) {\n return undefined;\n }\n\n const reasoning: OpenRouterReasoning = {};\n\n // Collect all text items\n const textItems = items.filter((i) => i.type === 'reasoning.text' && i.text);\n if (textItems.length > 0) {\n reasoning.text = textItems.map((i) => i.text).join('');\n }\n\n // Collect all summary items\n const summaryItems = items.filter(\n (i) => i.type === 'reasoning.summary' && i.summary,\n );\n if (summaryItems.length > 0) {\n reasoning.summary = summaryItems.map((i) => i.summary).join('');\n }\n\n // Collect encrypted content (should be only one)\n const encryptedItem = items.find(\n (i) => i.type === 'reasoning.encrypted' && i.data,\n );\n if (encryptedItem?.data) {\n reasoning.encrypted = encryptedItem.data;\n }\n\n // Return undefined if no content\n if (!reasoning.text && !reasoning.summary && !reasoning.encrypted) {\n return undefined;\n }\n\n return reasoning;\n}\n\n/**\n * Convert assistant message content parts to OpenRouter Responses API format.\n * Tool calls become separate items in the output array.\n * Extracts reasoning_details from providerMetadata for multi-turn continuation.\n */\nfunction convertAssistantMessage(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n let textContent = '';\n\n // Extract reasoning details for multi-turn continuation\n const sdkReasoningDetails = extractReasoningDetails(\n content,\n providerMetadata,\n providerOptions,\n );\n const reasoningItems = sdkReasoningDetails\n ? transformReasoningToApiFormat(sdkReasoningDetails)\n : [];\n const reasoning = buildReasoningFromDetails(reasoningItems);\n\n for (const part of content) {\n switch (part.type) {\n case 'text':\n textContent += part.text;\n break;\n\n case 'reasoning':\n // Include reasoning as part of text\n textContent += part.text;\n break;\n\n case 'tool-call':\n // Tool calls are separate items in Responses API\n result.push({\n type: 'function_call',\n callId: part.toolCallId,\n name: part.toolName,\n arguments:\n typeof part.input === 'string'\n ? part.input\n : JSON.stringify(part.input),\n });\n break;\n\n case 'file':\n // Files in assistant messages - skip for now as they're typically for output\n break;\n\n case 'tool-result':\n // Tool results in assistant messages (provider-executed tools)\n result.push(convertToolResult(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(\n `Unknown assistant content type: ${(_exhaustive as { type: string }).type}`\n );\n }\n }\n }\n\n // If there's text content, add it as an assistant message first\n // Responses API uses simple string content for assistant messages\n if (textContent) {\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: textContent,\n };\n // Attach reasoning for multi-turn continuation\n if (reasoning) {\n assistantMessage.reasoning = reasoning;\n }\n result.unshift(assistantMessage);\n } else if (reasoning) {\n // Even without text, include reasoning if present (for tool-call only messages)\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: '',\n };\n assistantMessage.reasoning = reasoning;\n result.unshift(assistantMessage);\n }\n\n return result;\n}\n\n/**\n * Convert tool message content parts to OpenRouter Responses API format.\n */\nfunction convertToolMessage(\n content: Array<LanguageModelV3ToolResultPart | { type: 'tool-approval-response'; approvalId: string; approved: boolean; reason?: string }>\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const part of content) {\n if (part.type === 'tool-result') {\n result.push(convertToolResult(part));\n }\n // Skip tool-approval-response as it's not directly mapped to OpenRouter format\n }\n\n return result;\n}\n\n/**\n * Convert a tool result part to OpenRouter function_call_output format.\n */\nfunction convertToolResult(part: LanguageModelV3ToolResultPart): OpenRouterFunctionCallOutput {\n const output = convertToolResultOutput(part.output);\n\n return {\n type: 'function_call_output',\n callId: part.toolCallId,\n output: output.value,\n status: output.isError ? 'incomplete' : 'completed',\n };\n}\n\n/**\n * Convert tool result output to a string value.\n */\nfunction convertToolResultOutput(output: LanguageModelV3ToolResultOutput): {\n value: string;\n isError: boolean;\n} {\n switch (output.type) {\n case 'text':\n return { value: output.value, isError: false };\n\n case 'json':\n return { value: JSON.stringify(output.value), isError: false };\n\n case 'execution-denied':\n return {\n value: `Execution denied: ${output.reason ?? 'No reason provided'}`,\n isError: true,\n };\n\n case 'error-text':\n return { value: output.value, isError: true };\n\n case 'error-json':\n return { value: JSON.stringify(output.value), isError: true };\n\n case 'content': {\n // For content array, convert to string representation\n const textParts = output.value\n .filter((item): item is { type: 'text'; text: string } => item.type === 'text')\n .map((item) => item.text);\n return { value: textParts.join('\\n'), isError: false };\n }\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = output;\n throw new Error(`Unknown tool result output type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n}\n","/**\n * Reasoning details extraction for multi-turn conversations.\n *\n * WHY: Reasoning models (Claude, Gemini 3, o1) return encrypted/signed reasoning\n * content that MUST be sent back verbatim in subsequent turns. Without preserving\n * and re-sending reasoning_details, the model loses context about its previous\n * thought process, breaking extended reasoning chains.\n *\n * This module handles extraction from OpenRouter Responses API responses and\n * attachment to AI SDK content parts via providerMetadata.\n */\n\nimport type { JSONObject, JSONValue } from '@ai-sdk/provider';\nimport type {\n OpenResponsesNonStreamingResponse,\n OpenResponsesReasoning,\n} from '@openrouter/sdk/models';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Raw reasoning item from OpenRouter response output.\n */\nexport interface ReasoningOutputItem {\n type: 'reasoning';\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n}\n\n/**\n * Reasoning details in SDK format (as returned by OpenRouter).\n * This is the format we store in providerMetadata for round-tripping.\n */\nexport type ReasoningDetails = JSONValue[];\n\n// =============================================================================\n// Extraction Functions\n// =============================================================================\n\n/**\n * Extract reasoning details from a non-streaming OpenRouter Responses API response.\n *\n * Reasoning details can come from:\n * 1. Output items with type 'reasoning' (Responses API format)\n * 2. Message-level reasoning_details field (Chat Completions API format)\n *\n * @param response - The full OpenRouter Responses API response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetails(\n response: OpenResponsesNonStreamingResponse\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n // Extract from output items (Responses API format)\n for (const outputItem of response.output) {\n if ('type' in outputItem && outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as ReasoningOutputItem;\n\n // Store the full reasoning item structure for round-tripping\n // This preserves all provider-specific fields (signature, encryptedContent, etc.)\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n/**\n * Extract reasoning details from streaming response output items.\n *\n * Called at the end of streaming when we have the full response.\n *\n * @param outputItems - The output items from the completed stream response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetailsFromOutput(\n outputItems: Array<{ type: string; [key: string]: unknown }>\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n for (const outputItem of outputItems) {\n if (outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as unknown as ReasoningOutputItem;\n\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n// =============================================================================\n// Provider Detection\n// =============================================================================\n\n/**\n * Check if reasoning details contain encrypted content (Gemini thoughtSignature).\n *\n * This is important for Gemini 3 models which return 'completed' status\n * but expect continuation when tool calls exist with encrypted reasoning.\n *\n * @param reasoningDetails - The extracted reasoning details\n * @returns True if encrypted content is present\n */\nexport function hasEncryptedReasoning(\n reasoningDetails: ReasoningDetails | undefined\n): boolean {\n if (!reasoningDetails) {\n return false;\n }\n\n return reasoningDetails.some((d) => {\n if (typeof d === 'object' && d !== null) {\n const obj = d as Record<string, unknown>;\n return obj.encryptedContent != null || obj.type === 'reasoning.encrypted';\n }\n return false;\n });\n}\n\n/**\n * Build provider metadata object with reasoning details.\n *\n * @param reasoningDetails - The reasoning details to include\n * @returns Provider metadata object for attachment to content parts (SharedV3ProviderMetadata compatible)\n */\nexport function buildReasoningProviderMetadata(\n reasoningDetails: ReasoningDetails | undefined\n): Record<string, JSONObject> | undefined {\n if (!reasoningDetails || reasoningDetails.length === 0) {\n return undefined;\n }\n\n return {\n openrouter: {\n reasoning_details: reasoningDetails,\n } as JSONObject,\n };\n}\n\n// =============================================================================\n// Re-export types for convenience\n// =============================================================================\n\nexport type { OpenResponsesReasoning };\n","import type { LanguageModelV3FinishReason } from '@ai-sdk/provider';\n\n/**\n * Maps OpenRouter finish reasons to the AI SDK V3 unified format.\n *\n * Mapping table:\n * - 'end_turn', 'stop', 'stop_sequence' -> 'stop'\n * - 'max_tokens', 'length' -> 'length'\n * - 'tool_use', 'tool_calls' -> 'tool-calls'\n * - 'content_filter' -> 'content-filter'\n * - 'error' -> 'error'\n * - null/undefined/unknown -> 'other'\n *\n * @param finishReason - The finish reason from OpenRouter API response\n * @returns Object containing the unified finish reason and raw original value\n */\nexport function mapOpenRouterFinishReason(\n finishReason: string | null | undefined\n): LanguageModelV3FinishReason {\n // Handle null/undefined\n if (finishReason == null) {\n return { unified: 'other', raw: undefined };\n }\n\n // Map to unified format\n switch (finishReason) {\n case 'end_turn':\n case 'stop':\n case 'stop_sequence':\n return { unified: 'stop', raw: finishReason };\n\n case 'max_tokens':\n case 'length':\n return { unified: 'length', raw: finishReason };\n\n case 'tool_use':\n case 'tool_calls':\n return { unified: 'tool-calls', raw: finishReason };\n\n case 'content_filter':\n return { unified: 'content-filter', raw: finishReason };\n\n case 'error':\n return { unified: 'error', raw: finishReason };\n\n default:\n return { unified: 'other', raw: finishReason };\n }\n}\n","import type {\n EmbeddingModelV3,\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Result,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type { CreateEmbeddingsResponseBody } from '@openrouter/sdk/models/operations';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\n\n/**\n * OpenRouter embedding model implementing AI SDK V3 EmbeddingModelV3 interface.\n */\nexport class OpenRouterEmbeddingModel implements EmbeddingModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Maximum number of embeddings that can be generated in a single API call.\n * Set to 2048 as a reasonable default for most embedding models.\n */\n readonly maxEmbeddingsPerCall = 2048;\n\n /**\n * Whether the model supports parallel calls.\n */\n readonly supportsParallelCalls = true;\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doEmbed(options: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n userAgent: this.settings.userAgent,\n });\n\n // Build request with provider routing options if configured\n const requestParams: {\n model: string;\n input: string[];\n user?: string;\n provider?: { order?: string[]; allowFallbacks?: boolean; requireParameters?: boolean };\n } = {\n model: this.modelId,\n input: options.values,\n };\n\n // Add provider routing options from model settings\n const modelOptions = this.settings.modelOptions;\n if (modelOptions?.user) {\n requestParams.user = modelOptions.user as string;\n }\n if (modelOptions?.provider) {\n requestParams.provider = modelOptions.provider;\n }\n\n // Make the embeddings request\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = await client.embeddings.generate(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n });\n\n // Handle string response (shouldn't happen in practice but type allows it)\n if (typeof response === 'string') {\n throw new Error(`Unexpected string response from embeddings API: ${response}`);\n }\n\n const responseBody = response as CreateEmbeddingsResponseBody;\n\n // Extract embeddings from response data\n // Sort by index to ensure correct order, then extract embedding vectors\n const sortedData = [...responseBody.data].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\n const embeddings = sortedData.map((item) => {\n // Embedding can be number[] or base64 string - we only support number[]\n if (typeof item.embedding === 'string') {\n throw new Error('Base64 encoded embeddings are not supported');\n }\n return item.embedding;\n });\n\n return {\n embeddings,\n usage: responseBody.usage\n ? { tokens: responseBody.usage.promptTokens }\n : undefined,\n warnings,\n };\n }\n}\n","import type {\n ImageModelV3,\n ImageModelV3CallOptions,\n SharedV3Warning,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter image model implementing AI SDK V3 ImageModelV3 interface.\n *\n * Note: Image generation is Tier 3 functionality. The doGenerate method\n * throws an error with guidance on tracking progress.\n */\nexport class OpenRouterImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n /**\n * Maximum number of images that can be generated in a single API call.\n */\n readonly maxImagesPerCall = 1;\n\n constructor(modelId: string, _settings: unknown) {\n this.modelId = modelId;\n }\n\n async doGenerate(_options: ImageModelV3CallOptions): Promise<{\n images: Array<string> | Array<Uint8Array>;\n warnings: Array<SharedV3Warning>;\n response: {\n timestamp: Date;\n modelId: string;\n headers: Record<string, string> | undefined;\n };\n }> {\n throw new Error(\n 'Image generation not yet supported. ' +\n 'See: https://github.com/OpenRouterTeam/ai-sdk-provider/issues/new?title=Image+generation+support'\n );\n }\n}\n","export const VERSION = '6.0.0-alpha.0';\n"],"mappings":"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","names":["import_provider_utils","import_sdk","extractReasoningDetails","extractReasoningDetails","import_provider_utils","import_sdk"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/openrouter-provider.ts
|
|
2
2
|
import { loadApiKey, withoutTrailingSlash } from "@ai-sdk/provider-utils";
|
|
3
|
+
import { SDK_METADATA } from "@openrouter/sdk";
|
|
3
4
|
|
|
4
5
|
// src/chat/openrouter-chat-language-model.ts
|
|
5
6
|
import { combineHeaders, normalizeHeaders } from "@ai-sdk/provider-utils";
|
|
@@ -488,7 +489,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
488
489
|
const warnings = [];
|
|
489
490
|
const client = new OpenRouter({
|
|
490
491
|
apiKey: this.settings.apiKey,
|
|
491
|
-
serverURL: this.settings.baseURL
|
|
492
|
+
serverURL: this.settings.baseURL,
|
|
493
|
+
userAgent: this.settings.userAgent
|
|
492
494
|
});
|
|
493
495
|
const openRouterInput = convertToOpenRouterMessages(options.prompt);
|
|
494
496
|
const tools = convertToolsToResponsesFormat(options.tools, warnings);
|
|
@@ -613,7 +615,8 @@ var OpenRouterChatLanguageModel = class {
|
|
|
613
615
|
const warnings = [];
|
|
614
616
|
const client = new OpenRouter({
|
|
615
617
|
apiKey: this.settings.apiKey,
|
|
616
|
-
serverURL: this.settings.baseURL
|
|
618
|
+
serverURL: this.settings.baseURL,
|
|
619
|
+
userAgent: this.settings.userAgent
|
|
617
620
|
});
|
|
618
621
|
const openRouterInput = convertToOpenRouterMessages(options.prompt);
|
|
619
622
|
const tools = convertToolsToResponsesFormat(options.tools, warnings);
|
|
@@ -1073,7 +1076,8 @@ var OpenRouterEmbeddingModel = class {
|
|
|
1073
1076
|
const warnings = [];
|
|
1074
1077
|
const client = new OpenRouter2({
|
|
1075
1078
|
apiKey: this.settings.apiKey,
|
|
1076
|
-
serverURL: this.settings.baseURL
|
|
1079
|
+
serverURL: this.settings.baseURL,
|
|
1080
|
+
userAgent: this.settings.userAgent
|
|
1077
1081
|
});
|
|
1078
1082
|
const requestParams = {
|
|
1079
1083
|
model: this.modelId,
|
|
@@ -1144,10 +1148,19 @@ function createOpenRouter(options = {}) {
|
|
|
1144
1148
|
environmentVariableName: "OPENROUTER_API_KEY",
|
|
1145
1149
|
description: "OpenRouter"
|
|
1146
1150
|
});
|
|
1151
|
+
const providerUserAgentPart = `ai-sdk-provider/${"6.0.0-alpha.1"}`;
|
|
1152
|
+
const baseUserAgent = options.headers?.["user-agent"] ?? options.headers?.["User-Agent"] ?? SDK_METADATA.userAgent;
|
|
1153
|
+
const userAgent = baseUserAgent.includes("ai-sdk-provider/") ? baseUserAgent : `${baseUserAgent} ${providerUserAgentPart}`;
|
|
1154
|
+
const {
|
|
1155
|
+
"User-Agent": _ignoredUserAgent,
|
|
1156
|
+
"user-agent": _ignoredUserAgentLower,
|
|
1157
|
+
...forwardHeaders
|
|
1158
|
+
} = options.headers ?? {};
|
|
1147
1159
|
return {
|
|
1148
1160
|
apiKey,
|
|
1149
1161
|
baseURL,
|
|
1150
|
-
|
|
1162
|
+
userAgent,
|
|
1163
|
+
headers: Object.keys(forwardHeaders).length > 0 ? forwardHeaders : void 0,
|
|
1151
1164
|
fetch: options.fetch,
|
|
1152
1165
|
extraBody: options.extraBody,
|
|
1153
1166
|
modelOptions
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/openrouter-provider.ts","../src/chat/openrouter-chat-language-model.ts","../src/utils/build-provider-metadata.ts","../src/utils/build-usage.ts","../src/chat/convert-to-openrouter-messages.ts","../src/chat/extract-reasoning-details.ts","../src/chat/map-openrouter-finish-reason.ts","../src/embedding/openrouter-embedding-model.ts","../src/image/openrouter-image-model.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import type { ProviderV3 } from '@ai-sdk/provider';\nimport { loadApiKey, withoutTrailingSlash } from '@ai-sdk/provider-utils';\nimport { OpenRouterChatLanguageModel } from './chat/openrouter-chat-language-model.js';\nimport { OpenRouterEmbeddingModel } from './embedding/openrouter-embedding-model.js';\nimport { OpenRouterImageModel } from './image/openrouter-image-model.js';\nimport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n} from './openrouter-config.js';\n\n/**\n * OpenRouter provider interface extending the AI SDK V3 ProviderV3 interface.\n *\n * The provider is callable - calling it directly is equivalent to calling languageModel().\n */\nexport interface OpenRouterProvider extends ProviderV3 {\n /**\n * Create a language model by calling the provider directly.\n */\n (modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a language model.\n */\n languageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a chat model (alias for languageModel).\n */\n chat(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create an embedding model.\n */\n embeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create a text embedding model.\n * @deprecated Use embeddingModel instead.\n */\n textEmbeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create an image model.\n */\n imageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an image model (alias for imageModel).\n */\n image(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an embedding model (alias for embeddingModel).\n * @deprecated Use embeddingModel instead.\n */\n embedding(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n}\n\n/**\n * Internal settings passed to model constructors.\n * Contains resolved API key and normalized configuration.\n */\nexport interface OpenRouterModelSettings {\n apiKey: string;\n baseURL: string;\n headers?: Record<string, string>;\n fetch?: typeof globalThis.fetch;\n extraBody?: Record<string, unknown>;\n modelOptions?: OpenRouterModelOptions;\n}\n\n/**\n * Creates an OpenRouter provider instance for the AI SDK.\n *\n * @description\n * Factory function that creates an OpenRouter provider compatible with the AI SDK v3 provider\n * specification. The provider can create language models, embedding models, and image models\n * that route requests through OpenRouter to various AI providers (OpenAI, Anthropic, Google, etc.).\n *\n * The returned provider is callable - you can use it directly as a function to create language\n * models, or use its methods for specific model types.\n *\n * @param options - Provider settings including API key, base URL, headers, and fetch implementation.\n * If no API key is provided, it will be loaded from the OPENROUTER_API_KEY environment variable.\n * @returns An OpenRouter provider that can create language, embedding, and image models.\n *\n * @example Basic usage with environment variable\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * // Uses OPENROUTER_API_KEY from environment\n * const openrouter = createOpenRouter();\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example With explicit API key\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * const openrouter = createOpenRouter({\n * apiKey: process.env.OPENROUTER_API_KEY,\n * });\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example Creating different model types\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Language model (callable shorthand)\n * const chat = openrouter('anthropic/claude-3.5-sonnet');\n *\n * // Embedding model\n * const embeddings = openrouter.embeddingModel('openai/text-embedding-3-small');\n *\n * // Image model\n * const image = openrouter.imageModel('openai/dall-e-3');\n * ```\n *\n * @example Model variants\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Online search variant - model has web search capabilities\n * const online = openrouter('anthropic/claude-3.5-sonnet:online');\n *\n * // Nitro variant - faster inference\n * const nitro = openrouter('anthropic/claude-3.5-sonnet:nitro');\n *\n * // Floor pricing variant - routes to cheapest provider\n * const floor = openrouter('anthropic/claude-3.5-sonnet:floor');\n *\n * // Free tier variant\n * const free = openrouter('meta-llama/llama-3-8b-instruct:free');\n * ```\n */\nexport function createOpenRouter(\n options: OpenRouterProviderSettings = {}\n): OpenRouterProvider {\n // Normalize base URL: accept baseURL or baseUrl, strip trailing slash\n // The fallback ensures we always have a value, so the non-null assertion is safe\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? options.baseUrl ?? 'https://openrouter.ai/api/v1'\n )!;\n\n /**\n * Resolves model settings at model creation time.\n * API key is loaded here (not at provider creation or request time) per Decision 1 - Fail Fast.\n */\n const getModelSettings = (modelOptions?: OpenRouterModelOptions): OpenRouterModelSettings => {\n // Load API key at model creation time\n const apiKey = loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'OPENROUTER_API_KEY',\n description: 'OpenRouter',\n });\n\n return {\n apiKey,\n baseURL,\n headers: options.headers,\n fetch: options.fetch,\n extraBody: options.extraBody,\n modelOptions,\n };\n };\n\n /**\n * Create a language model.\n */\n const languageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterChatLanguageModel => {\n return new OpenRouterChatLanguageModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an embedding model.\n */\n const embeddingModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterEmbeddingModel => {\n return new OpenRouterEmbeddingModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an image model.\n */\n const imageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterImageModel => {\n return new OpenRouterImageModel(modelId, getModelSettings(modelOptions));\n };\n\n // Create the callable provider object\n const provider = Object.assign(\n // Make provider callable - calling it directly creates a language model\n (modelId: string, modelOptions?: OpenRouterModelOptions) => languageModel(modelId, modelOptions),\n {\n specificationVersion: 'v3' as const,\n languageModel,\n chat: languageModel,\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n imageModel,\n image: imageModel,\n embedding: embeddingModel,\n }\n );\n\n return provider;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FunctionTool,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3ToolChoice,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type {\n OpenResponsesRequest,\n OpenResponsesNonStreamingResponse,\n OpenResponsesStreamEvent,\n OpenResponsesRequestToolFunction,\n OpenAIResponsesToolChoiceUnion,\n} from '@openrouter/sdk/models';\nimport type { EventStream } from '@openrouter/sdk/lib/event-streams';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\nimport { buildProviderMetadata } from '../utils/build-provider-metadata.js';\nimport { buildUsage } from '../utils/build-usage.js';\nimport { convertToOpenRouterMessages } from './convert-to-openrouter-messages.js';\nimport {\n extractReasoningDetails,\n hasEncryptedReasoning,\n buildReasoningProviderMetadata,\n type ReasoningOutputItem,\n} from './extract-reasoning-details.js';\nimport { mapOpenRouterFinishReason } from './map-openrouter-finish-reason.js';\n\n/**\n * OpenRouter chat language model implementing AI SDK V3 LanguageModelV3 interface.\n *\n * Uses the OpenRouter Responses API for both streaming and non-streaming requests.\n */\nexport class OpenRouterChatLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Supported URL patterns by media type.\n * OpenRouter Chat API only supports image URLs natively.\n * PDF URLs are not supported - use PDF data URIs or the Responses API instead.\n */\n readonly supportedUrls: Record<string, RegExp[]> = {\n 'image/*': [/^https?:\\/\\/.*$/],\n };\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3GenerateResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (non-streaming)\n const requestParams: OpenResponsesRequest & { stream: false } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: false,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the non-streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as OpenResponsesNonStreamingResponse;\n\n // Build content array from Responses API output\n const content: LanguageModelV3Content[] = [];\n\n // Extract reasoning details for multi-turn conversation support\n // These must be preserved and sent back in subsequent turns for reasoning models\n const reasoningDetails = extractReasoningDetails(response);\n const reasoningMetadata = buildReasoningProviderMetadata(reasoningDetails);\n\n // Process output items\n for (const outputItem of response.output) {\n if (outputItem.type === 'reasoning') {\n // Extract reasoning text from content array or summary\n const reasoningItem = outputItem as ReasoningOutputItem;\n const reasoningText =\n reasoningItem.content\n ?.filter((c) => c.type === 'reasoning_text')\n .map((c) => c.text)\n .join('') ||\n reasoningItem.summary\n ?.filter((c) => c.type === 'summary_text')\n .map((c) => c.text)\n .join('') ||\n '';\n\n if (reasoningText) {\n // Attach reasoning_details to the reasoning part for multi-turn support\n content.push({\n type: 'reasoning',\n text: reasoningText,\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n } else if (outputItem.type === 'message') {\n // Extract text content from message\n const messageItem = outputItem as {\n type: 'message';\n content: Array<{ type: string; text?: string }>;\n };\n for (const contentItem of messageItem.content) {\n if (contentItem.type === 'output_text' && contentItem.text) {\n content.push({\n type: 'text',\n text: contentItem.text,\n });\n }\n }\n } else if (outputItem.type === 'function_call') {\n // Handle tool/function calls\n const functionCallItem = outputItem as {\n type: 'function_call';\n callId: string;\n name: string;\n arguments?: string;\n };\n // Attach reasoning_details to tool-call parts for multi-turn support\n // This is critical for Gemini 3 with thoughtSignature\n content.push({\n type: 'tool-call',\n toolCallId: functionCallItem.callId,\n toolName: functionCallItem.name,\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n input: functionCallItem.arguments || '{}',\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n }\n\n // Use outputText as fallback if no text content was extracted\n if (response.outputText && !content.some((c) => c.type === 'text')) {\n content.push({\n type: 'text',\n text: response.outputText,\n });\n }\n\n // Build finish reason based on response status\n let finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Gemini 3 thoughtSignature fix: when there are tool calls with encrypted\n // reasoning, the model returns 'completed' but expects continuation.\n // Override to 'tool-calls' so the AI SDK knows to continue the conversation.\n const hasToolCalls = content.some((c) => c.type === 'tool-call');\n if (\n hasToolCalls &&\n hasEncryptedReasoning(reasoningDetails) &&\n finishReason.unified === 'stop'\n ) {\n finishReason = { unified: 'tool-calls', raw: finishReason.raw };\n }\n\n // Build usage from Responses API format\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Note: The Responses API doesn't include 'provider' field directly\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider in response\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens: response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n return {\n content,\n finishReason,\n usage,\n warnings,\n providerMetadata,\n request: {\n body: requestParams,\n },\n response: {\n id: response.id,\n timestamp: new Date(response.createdAt * 1000),\n modelId: response.model,\n },\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3StreamResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (streaming)\n const requestParams: OpenResponsesRequest & { stream: true } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: true,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const eventStream = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as EventStream<OpenResponsesStreamEvent>;\n\n // Track state for stream transformation\n const state = createStreamState();\n\n // Transform the EventStream to AI SDK V3 stream parts\n const transformedStream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n // Emit stream-start first\n controller.enqueue({\n type: 'stream-start',\n warnings,\n });\n\n try {\n for await (const event of eventStream) {\n const parts = transformResponsesEvent(event, state);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n } catch (error) {\n controller.enqueue({\n type: 'error',\n error,\n });\n } finally {\n controller.close();\n }\n },\n });\n\n return {\n stream: transformedStream,\n request: {\n body: requestParams,\n },\n };\n }\n}\n\n/**\n * Stream state for tracking response metadata and content parts.\n */\ninterface StreamState {\n responseId: string | undefined;\n responseModel: string | undefined;\n responseCreated: number | undefined;\n textStarted: boolean;\n textId: string;\n reasoningStarted: boolean;\n reasoningId: string;\n textEnded: boolean;\n reasoningEnded: boolean;\n sourceIds: string[];\n toolCalls: Map<string, { name?: string; argumentsStarted: boolean }>;\n}\n\nfunction createStreamState(): StreamState {\n return {\n responseId: undefined,\n responseModel: undefined,\n responseCreated: undefined,\n textStarted: false,\n textId: 'text-0',\n reasoningStarted: false,\n reasoningId: 'reasoning-0',\n textEnded: false,\n reasoningEnded: false,\n sourceIds: [],\n toolCalls: new Map(),\n };\n}\n\n/**\n * Transform a Responses API stream event to AI SDK V3 stream parts.\n */\nfunction transformResponsesEvent(\n event: OpenResponsesStreamEvent,\n state: StreamState\n): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n\n switch (event.type) {\n // Response lifecycle events\n case 'response.created':\n case 'response.in_progress': {\n // Capture response metadata from initial events\n if (event.response) {\n state.responseId = event.response.id;\n state.responseModel = event.response.model;\n state.responseCreated = event.response.createdAt;\n }\n break;\n }\n\n // Text streaming\n case 'response.output_text.delta': {\n // Emit text-start if not started\n if (!state.textStarted) {\n state.textStarted = true;\n parts.push({\n type: 'text-start',\n id: state.textId,\n });\n }\n\n // Emit text-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'text-delta',\n id: state.textId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.output_text.done': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n break;\n }\n\n // Reasoning streaming\n case 'response.reasoning_text.delta': {\n // Emit reasoning-start if not started\n if (!state.reasoningStarted) {\n state.reasoningStarted = true;\n parts.push({\n type: 'reasoning-start',\n id: state.reasoningId,\n });\n }\n\n // Emit reasoning-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'reasoning-delta',\n id: state.reasoningId,\n delta: event.delta,\n });\n }\n break;\n }\n\n // Function call arguments streaming\n case 'response.function_call_arguments.delta': {\n const toolCallId = event.itemId;\n let toolState = state.toolCalls.get(toolCallId);\n\n if (!toolState) {\n toolState = { argumentsStarted: false };\n state.toolCalls.set(toolCallId, toolState);\n }\n\n // Emit tool-input-start if not started\n if (!toolState.argumentsStarted) {\n toolState.argumentsStarted = true;\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: toolState.name ?? '', // Will be filled in by output_item.added\n });\n }\n\n // Emit tool-input-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.function_call_arguments.done': {\n const toolCallId = event.itemId;\n const toolState = state.toolCalls.get(toolCallId);\n\n // If we haven't started tool call yet, emit start + delta with full args\n if (!toolState?.argumentsStarted) {\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: event.name,\n });\n // Default to empty object when arguments is undefined/empty\n const args = event.arguments || '{}';\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: args,\n });\n }\n\n // Emit tool-input-end\n parts.push({\n type: 'tool-input-end',\n id: toolCallId,\n });\n\n // Emit tool-call with complete tool call data\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n parts.push({\n type: 'tool-call',\n toolCallId,\n toolName: event.name,\n input: event.arguments || '{}',\n });\n break;\n }\n\n // Output item events (for function call metadata)\n case 'response.output_item.added': {\n if (event.item.type === 'function_call') {\n const funcItem = event.item as {\n type: 'function_call';\n callId?: string;\n name: string;\n };\n const toolCallId = funcItem.callId ?? `tool-${event.outputIndex}`;\n const toolState = state.toolCalls.get(toolCallId) ?? {\n argumentsStarted: false,\n };\n toolState.name = funcItem.name;\n state.toolCalls.set(toolCallId, toolState);\n }\n break;\n }\n\n // Annotation events (web search sources)\n case 'response.output_text.annotation.added': {\n const annotation = event.annotation;\n if (annotation.type === 'url_citation') {\n const urlAnnotation = annotation as {\n type: 'url_citation';\n url: string;\n title: string;\n };\n const sourceId = `source-${state.sourceIds.length}`;\n state.sourceIds.push(sourceId);\n parts.push({\n type: 'source',\n sourceType: 'url',\n id: sourceId,\n url: urlAnnotation.url,\n title: urlAnnotation.title,\n });\n }\n break;\n }\n\n // Response completed - extract final usage data\n case 'response.completed': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n\n // End reasoning if started and not ended\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n // Emit response-metadata\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Build finish reason based on response status\n const finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Build usage\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Response incomplete or failed\n case 'response.incomplete':\n case 'response.failed': {\n // End any open content parts\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Map finish reason\n const finishReason =\n event.type === 'response.failed'\n ? mapOpenRouterFinishReason('error')\n : mapOpenRouterFinishReason(response.status ?? 'incomplete');\n\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined,\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Error event\n case 'error': {\n const errorEvent = event as {\n type: 'error';\n error?: { message?: string };\n };\n parts.push({\n type: 'error',\n error: new Error(\n errorEvent.error?.message ?? 'Unknown streaming error'\n ),\n });\n break;\n }\n\n // Ignored events (handled implicitly or not needed)\n case 'response.output_item.done':\n case 'response.content_part.added':\n case 'response.content_part.done':\n case 'response.refusal.delta':\n case 'response.refusal.done':\n case 'response.reasoning_text.done':\n case 'response.reasoning_summary_part.added':\n case 'response.reasoning_summary_part.done':\n case 'response.reasoning_summary_text.delta':\n case 'response.reasoning_summary_text.done':\n case 'response.image_generation_call.in_progress':\n case 'response.image_generation_call.generating':\n case 'response.image_generation_call.partial_image':\n case 'response.image_generation_call.completed':\n // These events are either handled by other events or not relevant for AI SDK\n break;\n }\n\n return parts;\n}\n\n/**\n * Convert AI SDK tools to OpenRouter Responses API format.\n * Only 'function' type tools are supported.\n */\nfunction convertToolsToResponsesFormat(\n tools: LanguageModelV3CallOptions['tools'],\n warnings: SharedV3Warning[]\n): OpenResponsesRequestToolFunction[] {\n if (!tools || tools.length === 0) {\n return [];\n }\n\n return tools\n .map((tool): OpenResponsesRequestToolFunction | null => {\n if (tool.type !== 'function') {\n warnings.push({\n type: 'unsupported',\n feature: `tool type '${tool.type}'`,\n details: `Only 'function' type tools are supported. Tool '${(tool as { name?: string }).name ?? 'unknown'}' has type '${tool.type}'.`,\n });\n return null;\n }\n\n const functionTool = tool as LanguageModelV3FunctionTool;\n return {\n type: 'function',\n name: functionTool.name,\n description: functionTool.description ?? null,\n parameters: functionTool.inputSchema as { [k: string]: unknown } | null,\n };\n })\n .filter((tool): tool is OpenResponsesRequestToolFunction => tool !== null);\n}\n\n/**\n * Convert AI SDK toolChoice to OpenRouter Responses API format.\n *\n * Mapping:\n * - 'auto' -> 'auto'\n * - 'none' -> 'none'\n * - 'required' -> 'required'\n * - { type: 'tool', toolName } -> { type: 'function', name: toolName }\n */\nfunction convertToolChoiceToResponsesFormat(\n toolChoice: LanguageModelV3ToolChoice | undefined\n): OpenAIResponsesToolChoiceUnion | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return 'auto';\n case 'none':\n return 'none';\n case 'required':\n return 'required';\n case 'tool':\n return {\n type: 'function',\n name: toolChoice.toolName,\n };\n default:\n return undefined;\n }\n}\n\n/**\n * Convert AI SDK responseFormat to OpenRouter Responses API text.format.\n *\n * Mapping:\n * - { type: 'text' } -> { type: 'text' }\n * - { type: 'json' } -> { type: 'json_object' } (no schema)\n * - { type: 'json', schema, name } -> { type: 'json_schema', name, schema } (with schema)\n */\nfunction convertResponseFormatToText(\n responseFormat: LanguageModelV3CallOptions['responseFormat']\n): OpenResponsesRequest['text'] | undefined {\n if (!responseFormat) {\n return undefined;\n }\n\n if (responseFormat.type === 'text') {\n return {\n format: { type: 'text' },\n };\n }\n\n if (responseFormat.type === 'json') {\n // If a schema is provided, use json_schema format\n if (responseFormat.schema) {\n return {\n format: {\n type: 'json_schema',\n name: responseFormat.name ?? 'response',\n description: responseFormat.description,\n schema: responseFormat.schema as { [k: string]: unknown },\n },\n };\n }\n // No schema - use simple json_object format\n return {\n format: { type: 'json_object' },\n };\n }\n\n return undefined;\n}\n","import type { JSONObject } from '@ai-sdk/provider';\nimport type { ChatGenerationTokenUsage } from '@openrouter/sdk/models';\n\n/**\n * OpenRouter-specific provider metadata structure.\n */\nexport interface OpenRouterProviderMetadata {\n /**\n * The response ID from OpenRouter.\n */\n responseId?: string;\n\n /**\n * The upstream provider that served the request.\n */\n provider?: string;\n\n /**\n * Detailed usage information.\n */\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n promptTokensDetails?: {\n cachedTokens?: number;\n cacheWriteTokens?: number;\n audioTokens?: number;\n videoTokens?: number;\n };\n completionTokensDetails?: {\n reasoningTokens?: number;\n imageTokens?: number;\n };\n /**\n * Cost in USD (omit if unavailable).\n */\n cost?: number;\n /**\n * Whether the request used BYOK (Bring Your Own Key).\n */\n isByok?: boolean;\n /**\n * Detailed cost breakdown.\n */\n costDetails?: JSONObject;\n };\n}\n\n/**\n * Extended prompt tokens details with fields not in SDK types.\n */\nexport interface ExtendedPromptTokensDetails {\n cachedTokens?: number | null;\n cacheWriteTokens?: number | null;\n audioTokens?: number | null;\n videoTokens?: number | null;\n}\n\n/**\n * Extended completion tokens details with fields not in SDK types.\n */\nexport interface ExtendedCompletionTokensDetails {\n reasoningTokens?: number | null;\n imageTokens?: number | null;\n}\n\n/**\n * Extended usage type with additional fields from raw OpenRouter API response.\n * The SDK types don't include cost/is_byok but the API returns them.\n */\nexport interface OpenRouterUsageExtended extends Omit<ChatGenerationTokenUsage, 'promptTokensDetails' | 'completionTokensDetails'> {\n cost?: number;\n isByok?: boolean;\n costDetails?: JSONObject;\n promptTokensDetails?: ExtendedPromptTokensDetails | null;\n completionTokensDetails?: ExtendedCompletionTokensDetails | null;\n}\n\n/**\n * Response data from OpenRouter API used to build provider metadata.\n * Note: The SDK transforms snake_case to camelCase for all fields.\n * The `provider` field exists in raw API responses but isn't in SDK types.\n */\nexport interface OpenRouterResponseData {\n id?: string;\n /**\n * The upstream provider that served the request (e.g. \"Google\", \"Anthropic\").\n * This field exists in the raw API response but isn't in SDK TypeScript types.\n */\n provider?: string;\n /**\n * Usage data in camelCase (as transformed by SDK).\n */\n usage?: OpenRouterUsageExtended;\n}\n\n/**\n * Filters out undefined values from an object, returning only defined properties.\n * This ensures providerMetadata is valid JSON (undefined is not a valid JSON value).\n */\nfunction filterUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined)\n ) as Partial<T>;\n}\n\n/**\n * Builds provider metadata from OpenRouter API response data.\n *\n * @param response - The response data from OpenRouter API (with camelCase fields from SDK).\n * @returns Provider metadata in the format expected by AI SDK.\n */\nexport function buildProviderMetadata(\n response: OpenRouterResponseData | undefined\n): Record<string, JSONObject> | undefined {\n if (!response) {\n return undefined;\n }\n\n const usage = response.usage;\n const usageMetadata: OpenRouterProviderMetadata['usage'] | undefined = usage\n ? filterUndefined({\n promptTokens: usage.promptTokens,\n completionTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n ...(usage.promptTokensDetails && {\n promptTokensDetails: filterUndefined({\n cachedTokens: usage.promptTokensDetails.cachedTokens ?? undefined,\n cacheWriteTokens: usage.promptTokensDetails.cacheWriteTokens ?? undefined,\n audioTokens: usage.promptTokensDetails.audioTokens ?? undefined,\n videoTokens: usage.promptTokensDetails.videoTokens ?? undefined,\n }),\n }),\n ...(usage.completionTokensDetails && {\n completionTokensDetails: filterUndefined({\n reasoningTokens: usage.completionTokensDetails.reasoningTokens ?? undefined,\n imageTokens: usage.completionTokensDetails.imageTokens ?? undefined,\n }),\n }),\n cost: usage.cost,\n isByok: usage.isByok,\n costDetails: usage.costDetails,\n })\n : undefined;\n\n const metadata: OpenRouterProviderMetadata = filterUndefined({\n responseId: response.id,\n provider: response.provider,\n usage: usageMetadata,\n });\n\n return {\n openrouter: metadata as unknown as JSONObject,\n };\n}\n","import type { LanguageModelV3Usage, JSONObject } from '@ai-sdk/provider';\n\n/**\n * Raw usage data from OpenRouter API response.\n */\nexport interface OpenRouterRawUsage {\n inputTokens?: number;\n outputTokens?: number;\n inputTokensDetails?: {\n cachedTokens?: number;\n };\n outputTokensDetails?: {\n reasoningTokens?: number;\n };\n}\n\n/**\n * Builds a LanguageModelV3Usage object from OpenRouter API usage data.\n *\n * @param usage - The raw usage data from the OpenRouter API response.\n * @returns A LanguageModelV3Usage object with standardized token counts.\n */\nexport function buildUsage(usage: OpenRouterRawUsage | undefined): LanguageModelV3Usage {\n if (!usage) {\n return {\n inputTokens: {\n total: 0,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n }\n\n // Convert to JSONObject-compatible format for raw field\n const rawUsage: JSONObject = {\n inputTokens: usage.inputTokens ?? null,\n outputTokens: usage.outputTokens ?? null,\n ...(usage.inputTokensDetails && {\n inputTokensDetails: {\n cachedTokens: usage.inputTokensDetails.cachedTokens ?? null,\n },\n }),\n ...(usage.outputTokensDetails && {\n outputTokensDetails: {\n reasoningTokens: usage.outputTokensDetails.reasoningTokens ?? null,\n },\n }),\n };\n\n return {\n inputTokens: {\n total: usage.inputTokens ?? 0,\n noCache: undefined,\n cacheRead: usage.inputTokensDetails?.cachedTokens,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: usage.outputTokens ?? 0,\n text: undefined,\n reasoning: usage.outputTokensDetails?.reasoningTokens,\n },\n raw: rawUsage,\n };\n}\n","import type {\n LanguageModelV3Prompt,\n LanguageModelV3Message,\n LanguageModelV3TextPart,\n LanguageModelV3FilePart,\n LanguageModelV3ReasoningPart,\n LanguageModelV3ToolCallPart,\n LanguageModelV3ToolResultPart,\n LanguageModelV3ToolResultOutput,\n JSONValue,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter Responses API input item types.\n * These match the OpenResponsesEasyInputMessage format used by the Responses API.\n */\nexport type OpenRouterInputItem =\n | OpenRouterEasyInputMessage\n | OpenRouterFunctionCall\n | OpenRouterFunctionCallOutput;\n\n/**\n * Reasoning details item format for API requests.\n * Used to preserve reasoning context across multi-turn conversations.\n */\nexport interface OpenRouterReasoningDetailItem {\n type: 'reasoning.text' | 'reasoning.summary' | 'reasoning.encrypted';\n id?: string;\n format?: string | null;\n index: number;\n text?: string; // For reasoning.text\n signature?: string | null; // For reasoning.text (Claude)\n summary?: string; // For reasoning.summary\n data?: string; // For reasoning.encrypted (Gemini)\n}\n\n/**\n * Reasoning object for assistant messages.\n * Contains the reasoning details to send back to the API.\n */\nexport interface OpenRouterReasoning {\n text?: string;\n summary?: string;\n encrypted?: string;\n}\n\n/**\n * Easy input message format for Responses API.\n * Supports user, system, assistant, and developer roles.\n */\nexport interface OpenRouterEasyInputMessage {\n type?: 'message';\n role: 'user' | 'system' | 'assistant' | 'developer';\n content: string | OpenRouterInputContent[];\n reasoning?: OpenRouterReasoning;\n}\n\nexport interface OpenRouterFunctionCall {\n type: 'function_call';\n callId: string;\n name: string;\n arguments: string;\n}\n\nexport interface OpenRouterFunctionCallOutput {\n type: 'function_call_output';\n callId: string;\n output: string;\n status: 'completed' | 'incomplete';\n}\n\n/**\n * Input content types for Responses API.\n * Uses 'input_text', 'input_image', 'input_file' type prefixes.\n */\nexport type OpenRouterInputContent =\n | { type: 'input_text'; text: string }\n | { type: 'input_image'; imageUrl: string; detail?: 'auto' | 'low' | 'high' }\n | { type: 'input_file'; fileUrl: string; filename?: string };\n\n/**\n * Converts AI SDK V3 prompt format to OpenRouter Responses API input format.\n *\n * Mapping table:\n * - system { content } -> { role: 'system', content: string }\n * - user text -> { role: 'user', content: [{ type: 'input_text', text }] }\n * - user image -> { role: 'user', content: [{ type: 'input_image', imageUrl }] }\n * - user file -> { role: 'user', content: [{ type: 'input_file', fileUrl }] }\n * - assistant text -> { role: 'assistant', content: string }\n * - assistant tool-call -> { type: 'function_call', ... }\n * - tool result -> { type: 'function_call_output', ... }\n *\n * @param prompt - The AI SDK V3 prompt\n * @returns Array of input items in OpenRouter Responses API format\n */\nexport function convertToOpenRouterMessages(\n prompt: LanguageModelV3Prompt\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const message of prompt) {\n const converted = convertMessage(message);\n result.push(...converted);\n }\n\n return result;\n}\n\n/**\n * Convert a single V3 message to OpenRouter Responses API format.\n * May return multiple items (e.g., when assistant has text + tool calls).\n */\nfunction convertMessage(message: LanguageModelV3Message): OpenRouterInputItem[] {\n // Extract providerOptions from the message for reasoning_details\n const messageWithOptions = message as LanguageModelV3Message & {\n providerOptions?: Record<string, Record<string, unknown>>;\n providerMetadata?: Record<string, Record<string, unknown>>;\n };\n const providerOptions = messageWithOptions.providerOptions;\n const providerMetadata = messageWithOptions.providerMetadata;\n\n switch (message.role) {\n case 'system':\n return [{ role: 'system', content: message.content }];\n\n case 'user':\n return [convertUserMessage(message.content)];\n\n case 'assistant':\n return convertAssistantMessage(message.content, providerMetadata, providerOptions);\n\n case 'tool':\n return convertToolMessage(message.content);\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = message;\n throw new Error(`Unknown message role: ${(_exhaustive as { role: string }).role}`);\n }\n }\n}\n\n/**\n * Convert user message content parts to OpenRouter Responses API format.\n */\nfunction convertUserMessage(\n content: Array<LanguageModelV3TextPart | LanguageModelV3FilePart>\n): OpenRouterEasyInputMessage {\n const convertedContent: OpenRouterInputContent[] = [];\n\n for (const part of content) {\n switch (part.type) {\n case 'text': {\n convertedContent.push({ type: 'input_text', text: part.text });\n break;\n }\n\n case 'file':\n convertedContent.push(convertFilePart(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(`Unknown user content type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n }\n\n return { role: 'user', content: convertedContent };\n}\n\n/**\n * Convert a file part to the appropriate OpenRouter Responses API format.\n *\n * OpenRouter's Responses API uses 'input_image' for images and 'input_file' for other files.\n */\nfunction convertFilePart(part: LanguageModelV3FilePart): OpenRouterInputContent {\n const url = convertDataContent(part.data, part.mediaType);\n \n // Check if it's an image based on media type\n if (part.mediaType.startsWith('image/')) {\n return {\n type: 'input_image',\n imageUrl: url,\n detail: 'auto',\n };\n }\n \n // For other file types (PDF, etc.), use input_file\n return {\n type: 'input_file',\n fileUrl: url,\n };\n}\n\n/**\n * Convert data content (URL, string, or Uint8Array) to a string URL or data URI.\n */\nfunction convertDataContent(\n data: URL | string | Uint8Array,\n mediaType: string\n): string {\n if (data instanceof URL) {\n return data.toString();\n }\n\n if (data instanceof Uint8Array) {\n // Convert Uint8Array to base64 data URI\n const base64 = uint8ArrayToBase64(data);\n return `data:${mediaType};base64,${base64}`;\n }\n\n // String - could be URL or base64 data\n // If it starts with http(s) or data:, treat as URL/data URI\n if (data.startsWith('http://') || data.startsWith('https://') || data.startsWith('data:')) {\n return data;\n }\n\n // Otherwise assume it's base64 encoded data\n return `data:${mediaType};base64,${data}`;\n}\n\n/**\n * Convert Uint8Array to base64 string.\n */\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n // Use browser-compatible base64 encoding\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/**\n * SDK format for reasoning items returned from OpenRouter.\n * Used when extracting reasoning_details from providerMetadata.\n */\ninterface SdkReasoningItem {\n type?: string;\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n // Also support flattened API format\n text?: string;\n data?: string;\n index?: number;\n}\n\n/**\n * Extract reasoning_details from providerMetadata or providerOptions.\n * Checks multiple locations for backwards compatibility.\n */\nfunction extractReasoningDetails(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): JSONValue[] | undefined {\n // Check message-level metadata first\n const messageLevel =\n providerOptions?.openrouter?.reasoning_details ??\n providerMetadata?.openrouter?.reasoning_details;\n\n if (messageLevel && Array.isArray(messageLevel) && messageLevel.length > 0) {\n return messageLevel as JSONValue[];\n }\n\n // Check reasoning content parts for part-level metadata\n for (const part of content) {\n if (part.type === 'reasoning') {\n const partWithMeta = part as LanguageModelV3ReasoningPart & {\n providerMetadata?: Record<string, { reasoning_details?: JSONValue[] }>;\n providerOptions?: Record<string, { reasoning_details?: JSONValue[] }>;\n };\n const partLevel =\n partWithMeta.providerOptions?.openrouter?.reasoning_details ??\n partWithMeta.providerMetadata?.openrouter?.reasoning_details;\n if (partLevel && Array.isArray(partLevel) && partLevel.length > 0) {\n return partLevel as JSONValue[];\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Transform SDK reasoning format to API request format.\n * Flattens the structure for sending back to OpenRouter.\n */\nfunction transformReasoningToApiFormat(\n sdkItems: JSONValue[],\n): OpenRouterReasoningDetailItem[] {\n const apiItems: OpenRouterReasoningDetailItem[] = [];\n\n for (const rawItem of sdkItems) {\n if (typeof rawItem !== 'object' || rawItem === null) {\n continue;\n }\n const item = rawItem as SdkReasoningItem;\n\n const baseProps = {\n id: item.id,\n format: item.format ?? null,\n };\n\n let index = item.index ?? 0;\n\n // Handle already-flattened API format (reasoning.text, reasoning.summary, reasoning.encrypted)\n if (item.type === 'reasoning.text' && item.text !== undefined) {\n apiItems.push({\n type: 'reasoning.text',\n text: item.text,\n signature: item.signature ?? null,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.summary' && item.summary !== undefined) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: typeof item.summary === 'string' ? item.summary : '',\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.encrypted' && item.data !== undefined) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.data,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n // Handle SDK format (type: 'reasoning' with content/summary/encryptedContent)\n if (item.type === 'reasoning' || item.content || item.summary || item.encryptedContent) {\n // Transform content items to reasoning.text\n if (item.content && Array.isArray(item.content)) {\n for (const contentItem of item.content) {\n if (contentItem.type === 'reasoning_text' && contentItem.text) {\n apiItems.push({\n type: 'reasoning.text',\n text: contentItem.text,\n signature: item.signature ?? null,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform summary items to reasoning.summary\n if (item.summary && Array.isArray(item.summary)) {\n for (const summaryItem of item.summary) {\n if (summaryItem.type === 'summary_text' && summaryItem.text) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: summaryItem.text,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform encryptedContent to reasoning.encrypted (Gemini)\n if (item.encryptedContent) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.encryptedContent,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n return apiItems;\n}\n\n/**\n * Build OpenRouterReasoning object from reasoning detail items.\n * Combines all items into a single reasoning object for the API.\n */\nfunction buildReasoningFromDetails(\n items: OpenRouterReasoningDetailItem[],\n): OpenRouterReasoning | undefined {\n if (items.length === 0) {\n return undefined;\n }\n\n const reasoning: OpenRouterReasoning = {};\n\n // Collect all text items\n const textItems = items.filter((i) => i.type === 'reasoning.text' && i.text);\n if (textItems.length > 0) {\n reasoning.text = textItems.map((i) => i.text).join('');\n }\n\n // Collect all summary items\n const summaryItems = items.filter(\n (i) => i.type === 'reasoning.summary' && i.summary,\n );\n if (summaryItems.length > 0) {\n reasoning.summary = summaryItems.map((i) => i.summary).join('');\n }\n\n // Collect encrypted content (should be only one)\n const encryptedItem = items.find(\n (i) => i.type === 'reasoning.encrypted' && i.data,\n );\n if (encryptedItem?.data) {\n reasoning.encrypted = encryptedItem.data;\n }\n\n // Return undefined if no content\n if (!reasoning.text && !reasoning.summary && !reasoning.encrypted) {\n return undefined;\n }\n\n return reasoning;\n}\n\n/**\n * Convert assistant message content parts to OpenRouter Responses API format.\n * Tool calls become separate items in the output array.\n * Extracts reasoning_details from providerMetadata for multi-turn continuation.\n */\nfunction convertAssistantMessage(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n let textContent = '';\n\n // Extract reasoning details for multi-turn continuation\n const sdkReasoningDetails = extractReasoningDetails(\n content,\n providerMetadata,\n providerOptions,\n );\n const reasoningItems = sdkReasoningDetails\n ? transformReasoningToApiFormat(sdkReasoningDetails)\n : [];\n const reasoning = buildReasoningFromDetails(reasoningItems);\n\n for (const part of content) {\n switch (part.type) {\n case 'text':\n textContent += part.text;\n break;\n\n case 'reasoning':\n // Include reasoning as part of text\n textContent += part.text;\n break;\n\n case 'tool-call':\n // Tool calls are separate items in Responses API\n result.push({\n type: 'function_call',\n callId: part.toolCallId,\n name: part.toolName,\n arguments:\n typeof part.input === 'string'\n ? part.input\n : JSON.stringify(part.input),\n });\n break;\n\n case 'file':\n // Files in assistant messages - skip for now as they're typically for output\n break;\n\n case 'tool-result':\n // Tool results in assistant messages (provider-executed tools)\n result.push(convertToolResult(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(\n `Unknown assistant content type: ${(_exhaustive as { type: string }).type}`\n );\n }\n }\n }\n\n // If there's text content, add it as an assistant message first\n // Responses API uses simple string content for assistant messages\n if (textContent) {\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: textContent,\n };\n // Attach reasoning for multi-turn continuation\n if (reasoning) {\n assistantMessage.reasoning = reasoning;\n }\n result.unshift(assistantMessage);\n } else if (reasoning) {\n // Even without text, include reasoning if present (for tool-call only messages)\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: '',\n };\n assistantMessage.reasoning = reasoning;\n result.unshift(assistantMessage);\n }\n\n return result;\n}\n\n/**\n * Convert tool message content parts to OpenRouter Responses API format.\n */\nfunction convertToolMessage(\n content: Array<LanguageModelV3ToolResultPart | { type: 'tool-approval-response'; approvalId: string; approved: boolean; reason?: string }>\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const part of content) {\n if (part.type === 'tool-result') {\n result.push(convertToolResult(part));\n }\n // Skip tool-approval-response as it's not directly mapped to OpenRouter format\n }\n\n return result;\n}\n\n/**\n * Convert a tool result part to OpenRouter function_call_output format.\n */\nfunction convertToolResult(part: LanguageModelV3ToolResultPart): OpenRouterFunctionCallOutput {\n const output = convertToolResultOutput(part.output);\n\n return {\n type: 'function_call_output',\n callId: part.toolCallId,\n output: output.value,\n status: output.isError ? 'incomplete' : 'completed',\n };\n}\n\n/**\n * Convert tool result output to a string value.\n */\nfunction convertToolResultOutput(output: LanguageModelV3ToolResultOutput): {\n value: string;\n isError: boolean;\n} {\n switch (output.type) {\n case 'text':\n return { value: output.value, isError: false };\n\n case 'json':\n return { value: JSON.stringify(output.value), isError: false };\n\n case 'execution-denied':\n return {\n value: `Execution denied: ${output.reason ?? 'No reason provided'}`,\n isError: true,\n };\n\n case 'error-text':\n return { value: output.value, isError: true };\n\n case 'error-json':\n return { value: JSON.stringify(output.value), isError: true };\n\n case 'content': {\n // For content array, convert to string representation\n const textParts = output.value\n .filter((item): item is { type: 'text'; text: string } => item.type === 'text')\n .map((item) => item.text);\n return { value: textParts.join('\\n'), isError: false };\n }\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = output;\n throw new Error(`Unknown tool result output type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n}\n","/**\n * Reasoning details extraction for multi-turn conversations.\n *\n * WHY: Reasoning models (Claude, Gemini 3, o1) return encrypted/signed reasoning\n * content that MUST be sent back verbatim in subsequent turns. Without preserving\n * and re-sending reasoning_details, the model loses context about its previous\n * thought process, breaking extended reasoning chains.\n *\n * This module handles extraction from OpenRouter Responses API responses and\n * attachment to AI SDK content parts via providerMetadata.\n */\n\nimport type { JSONObject, JSONValue } from '@ai-sdk/provider';\nimport type {\n OpenResponsesNonStreamingResponse,\n OpenResponsesReasoning,\n} from '@openrouter/sdk/models';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Raw reasoning item from OpenRouter response output.\n */\nexport interface ReasoningOutputItem {\n type: 'reasoning';\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n}\n\n/**\n * Reasoning details in SDK format (as returned by OpenRouter).\n * This is the format we store in providerMetadata for round-tripping.\n */\nexport type ReasoningDetails = JSONValue[];\n\n// =============================================================================\n// Extraction Functions\n// =============================================================================\n\n/**\n * Extract reasoning details from a non-streaming OpenRouter Responses API response.\n *\n * Reasoning details can come from:\n * 1. Output items with type 'reasoning' (Responses API format)\n * 2. Message-level reasoning_details field (Chat Completions API format)\n *\n * @param response - The full OpenRouter Responses API response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetails(\n response: OpenResponsesNonStreamingResponse\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n // Extract from output items (Responses API format)\n for (const outputItem of response.output) {\n if ('type' in outputItem && outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as ReasoningOutputItem;\n\n // Store the full reasoning item structure for round-tripping\n // This preserves all provider-specific fields (signature, encryptedContent, etc.)\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n/**\n * Extract reasoning details from streaming response output items.\n *\n * Called at the end of streaming when we have the full response.\n *\n * @param outputItems - The output items from the completed stream response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetailsFromOutput(\n outputItems: Array<{ type: string; [key: string]: unknown }>\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n for (const outputItem of outputItems) {\n if (outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as unknown as ReasoningOutputItem;\n\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n// =============================================================================\n// Provider Detection\n// =============================================================================\n\n/**\n * Check if reasoning details contain encrypted content (Gemini thoughtSignature).\n *\n * This is important for Gemini 3 models which return 'completed' status\n * but expect continuation when tool calls exist with encrypted reasoning.\n *\n * @param reasoningDetails - The extracted reasoning details\n * @returns True if encrypted content is present\n */\nexport function hasEncryptedReasoning(\n reasoningDetails: ReasoningDetails | undefined\n): boolean {\n if (!reasoningDetails) {\n return false;\n }\n\n return reasoningDetails.some((d) => {\n if (typeof d === 'object' && d !== null) {\n const obj = d as Record<string, unknown>;\n return obj.encryptedContent != null || obj.type === 'reasoning.encrypted';\n }\n return false;\n });\n}\n\n/**\n * Build provider metadata object with reasoning details.\n *\n * @param reasoningDetails - The reasoning details to include\n * @returns Provider metadata object for attachment to content parts (SharedV3ProviderMetadata compatible)\n */\nexport function buildReasoningProviderMetadata(\n reasoningDetails: ReasoningDetails | undefined\n): Record<string, JSONObject> | undefined {\n if (!reasoningDetails || reasoningDetails.length === 0) {\n return undefined;\n }\n\n return {\n openrouter: {\n reasoning_details: reasoningDetails,\n } as JSONObject,\n };\n}\n\n// =============================================================================\n// Re-export types for convenience\n// =============================================================================\n\nexport type { OpenResponsesReasoning };\n","import type { LanguageModelV3FinishReason } from '@ai-sdk/provider';\n\n/**\n * Maps OpenRouter finish reasons to the AI SDK V3 unified format.\n *\n * Mapping table:\n * - 'end_turn', 'stop', 'stop_sequence' -> 'stop'\n * - 'max_tokens', 'length' -> 'length'\n * - 'tool_use', 'tool_calls' -> 'tool-calls'\n * - 'content_filter' -> 'content-filter'\n * - 'error' -> 'error'\n * - null/undefined/unknown -> 'other'\n *\n * @param finishReason - The finish reason from OpenRouter API response\n * @returns Object containing the unified finish reason and raw original value\n */\nexport function mapOpenRouterFinishReason(\n finishReason: string | null | undefined\n): LanguageModelV3FinishReason {\n // Handle null/undefined\n if (finishReason == null) {\n return { unified: 'other', raw: undefined };\n }\n\n // Map to unified format\n switch (finishReason) {\n case 'end_turn':\n case 'stop':\n case 'stop_sequence':\n return { unified: 'stop', raw: finishReason };\n\n case 'max_tokens':\n case 'length':\n return { unified: 'length', raw: finishReason };\n\n case 'tool_use':\n case 'tool_calls':\n return { unified: 'tool-calls', raw: finishReason };\n\n case 'content_filter':\n return { unified: 'content-filter', raw: finishReason };\n\n case 'error':\n return { unified: 'error', raw: finishReason };\n\n default:\n return { unified: 'other', raw: finishReason };\n }\n}\n","import type {\n EmbeddingModelV3,\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Result,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type { CreateEmbeddingsResponseBody } from '@openrouter/sdk/models/operations';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\n\n/**\n * OpenRouter embedding model implementing AI SDK V3 EmbeddingModelV3 interface.\n */\nexport class OpenRouterEmbeddingModel implements EmbeddingModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Maximum number of embeddings that can be generated in a single API call.\n * Set to 2048 as a reasonable default for most embedding models.\n */\n readonly maxEmbeddingsPerCall = 2048;\n\n /**\n * Whether the model supports parallel calls.\n */\n readonly supportsParallelCalls = true;\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doEmbed(options: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n });\n\n // Build request with provider routing options if configured\n const requestParams: {\n model: string;\n input: string[];\n user?: string;\n provider?: { order?: string[]; allowFallbacks?: boolean; requireParameters?: boolean };\n } = {\n model: this.modelId,\n input: options.values,\n };\n\n // Add provider routing options from model settings\n const modelOptions = this.settings.modelOptions;\n if (modelOptions?.user) {\n requestParams.user = modelOptions.user as string;\n }\n if (modelOptions?.provider) {\n requestParams.provider = modelOptions.provider;\n }\n\n // Make the embeddings request\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = await client.embeddings.generate(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n });\n\n // Handle string response (shouldn't happen in practice but type allows it)\n if (typeof response === 'string') {\n throw new Error(`Unexpected string response from embeddings API: ${response}`);\n }\n\n const responseBody = response as CreateEmbeddingsResponseBody;\n\n // Extract embeddings from response data\n // Sort by index to ensure correct order, then extract embedding vectors\n const sortedData = [...responseBody.data].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\n const embeddings = sortedData.map((item) => {\n // Embedding can be number[] or base64 string - we only support number[]\n if (typeof item.embedding === 'string') {\n throw new Error('Base64 encoded embeddings are not supported');\n }\n return item.embedding;\n });\n\n return {\n embeddings,\n usage: responseBody.usage\n ? { tokens: responseBody.usage.promptTokens }\n : undefined,\n warnings,\n };\n }\n}\n","import type {\n ImageModelV3,\n ImageModelV3CallOptions,\n SharedV3Warning,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter image model implementing AI SDK V3 ImageModelV3 interface.\n *\n * Note: Image generation is Tier 3 functionality. The doGenerate method\n * throws an error with guidance on tracking progress.\n */\nexport class OpenRouterImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n /**\n * Maximum number of images that can be generated in a single API call.\n */\n readonly maxImagesPerCall = 1;\n\n constructor(modelId: string, _settings: unknown) {\n this.modelId = modelId;\n }\n\n async doGenerate(_options: ImageModelV3CallOptions): Promise<{\n images: Array<string> | Array<Uint8Array>;\n warnings: Array<SharedV3Warning>;\n response: {\n timestamp: Date;\n modelId: string;\n headers: Record<string, string> | undefined;\n };\n }> {\n throw new Error(\n 'Image generation not yet supported. ' +\n 'See: https://github.com/OpenRouterTeam/ai-sdk-provider/issues/new?title=Image+generation+support'\n );\n }\n}\n","export const VERSION = '6.0.0-alpha.0';\n","export { createOpenRouter, type OpenRouterProvider } from './openrouter-provider.js';\nexport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n OpenRouterPluginConfig,\n OpenRouterProviderRoutingConfig,\n} from './openrouter-config.js';\nexport { VERSION } from './version.js';\n\n// Default instance\nimport { createOpenRouter } from './openrouter-provider.js';\n\n/**\n * Default OpenRouter provider instance.\n *\n * Uses OPENROUTER_API_KEY environment variable for authentication.\n *\n * @example\n * ```ts\n * import { openrouter } from '@openrouter/ai-sdk-provider';\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n */\nexport const openrouter = createOpenRouter();\n"],"mappings":"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","names":["extractReasoningDetails","extractReasoningDetails","combineHeaders","normalizeHeaders","OpenRouter"]}
|
|
1
|
+
{"version":3,"sources":["../src/openrouter-provider.ts","../src/chat/openrouter-chat-language-model.ts","../src/utils/build-provider-metadata.ts","../src/utils/build-usage.ts","../src/chat/convert-to-openrouter-messages.ts","../src/chat/extract-reasoning-details.ts","../src/chat/map-openrouter-finish-reason.ts","../src/embedding/openrouter-embedding-model.ts","../src/image/openrouter-image-model.ts","../src/version.ts","../src/index.ts"],"sourcesContent":["import type { ProviderV3 } from '@ai-sdk/provider';\nimport { loadApiKey, withoutTrailingSlash } from '@ai-sdk/provider-utils';\nimport { SDK_METADATA } from '@openrouter/sdk';\nimport { OpenRouterChatLanguageModel } from './chat/openrouter-chat-language-model.js';\nimport { OpenRouterEmbeddingModel } from './embedding/openrouter-embedding-model.js';\nimport { OpenRouterImageModel } from './image/openrouter-image-model.js';\nimport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n} from './openrouter-config.js';\n\ndeclare const __PACKAGE_VERSION__: string;\n\n/**\n * OpenRouter provider interface extending the AI SDK V3 ProviderV3 interface.\n *\n * The provider is callable - calling it directly is equivalent to calling languageModel().\n */\nexport interface OpenRouterProvider extends ProviderV3 {\n /**\n * Create a language model by calling the provider directly.\n */\n (modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a language model.\n */\n languageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create a chat model (alias for languageModel).\n */\n chat(modelId: string, settings?: OpenRouterModelOptions): OpenRouterChatLanguageModel;\n\n /**\n * Create an embedding model.\n */\n embeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create a text embedding model.\n * @deprecated Use embeddingModel instead.\n */\n textEmbeddingModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n\n /**\n * Create an image model.\n */\n imageModel(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an image model (alias for imageModel).\n */\n image(modelId: string, settings?: OpenRouterModelOptions): OpenRouterImageModel;\n\n /**\n * Create an embedding model (alias for embeddingModel).\n * @deprecated Use embeddingModel instead.\n */\n embedding(modelId: string, settings?: OpenRouterModelOptions): OpenRouterEmbeddingModel;\n}\n\n/**\n * Internal settings passed to model constructors.\n * Contains resolved API key and normalized configuration.\n */\nexport interface OpenRouterModelSettings {\n apiKey: string;\n baseURL: string;\n /**\n * User-Agent string used by `@openrouter/sdk`.\n *\n * Note: Setting a `User-Agent` header via `fetchOptions.headers` is ineffective because\n * the SDK sets it after merging user headers.\n */\n userAgent: string;\n headers?: Record<string, string>;\n fetch?: typeof globalThis.fetch;\n extraBody?: Record<string, unknown>;\n modelOptions?: OpenRouterModelOptions;\n}\n\n/**\n * Creates an OpenRouter provider instance for the AI SDK.\n *\n * @description\n * Factory function that creates an OpenRouter provider compatible with the AI SDK v3 provider\n * specification. The provider can create language models, embedding models, and image models\n * that route requests through OpenRouter to various AI providers (OpenAI, Anthropic, Google, etc.).\n *\n * The returned provider is callable - you can use it directly as a function to create language\n * models, or use its methods for specific model types.\n *\n * @param options - Provider settings including API key, base URL, headers, and fetch implementation.\n * If no API key is provided, it will be loaded from the OPENROUTER_API_KEY environment variable.\n * @returns An OpenRouter provider that can create language, embedding, and image models.\n *\n * @example Basic usage with environment variable\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * // Uses OPENROUTER_API_KEY from environment\n * const openrouter = createOpenRouter();\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example With explicit API key\n * ```ts\n * import { createOpenRouter } from '@openrouter/ai-sdk-provider';\n *\n * const openrouter = createOpenRouter({\n * apiKey: process.env.OPENROUTER_API_KEY,\n * });\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n *\n * @example Creating different model types\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Language model (callable shorthand)\n * const chat = openrouter('anthropic/claude-3.5-sonnet');\n *\n * // Embedding model\n * const embeddings = openrouter.embeddingModel('openai/text-embedding-3-small');\n *\n * // Image model\n * const image = openrouter.imageModel('openai/dall-e-3');\n * ```\n *\n * @example Model variants\n * ```ts\n * const openrouter = createOpenRouter();\n *\n * // Online search variant - model has web search capabilities\n * const online = openrouter('anthropic/claude-3.5-sonnet:online');\n *\n * // Nitro variant - faster inference\n * const nitro = openrouter('anthropic/claude-3.5-sonnet:nitro');\n *\n * // Floor pricing variant - routes to cheapest provider\n * const floor = openrouter('anthropic/claude-3.5-sonnet:floor');\n *\n * // Free tier variant\n * const free = openrouter('meta-llama/llama-3-8b-instruct:free');\n * ```\n */\nexport function createOpenRouter(\n options: OpenRouterProviderSettings = {}\n): OpenRouterProvider {\n // Normalize base URL: accept baseURL or baseUrl, strip trailing slash\n // The fallback ensures we always have a value, so the non-null assertion is safe\n const baseURL = withoutTrailingSlash(\n options.baseURL ?? options.baseUrl ?? 'https://openrouter.ai/api/v1'\n )!;\n\n /**\n * Resolves model settings at model creation time.\n * API key is loaded here (not at provider creation or request time) per Decision 1 - Fail Fast.\n */\n const getModelSettings = (modelOptions?: OpenRouterModelOptions): OpenRouterModelSettings => {\n // Load API key at model creation time\n const apiKey = loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'OPENROUTER_API_KEY',\n description: 'OpenRouter',\n });\n\n const providerUserAgentPart = `ai-sdk-provider/${__PACKAGE_VERSION__}`;\n\n // Allow overriding the base UA via headers, but always append our provider token.\n const baseUserAgent =\n options.headers?.['user-agent'] ?? options.headers?.['User-Agent'] ?? SDK_METADATA.userAgent;\n\n const userAgent = baseUserAgent.includes('ai-sdk-provider/')\n ? baseUserAgent\n : `${baseUserAgent} ${providerUserAgentPart}`;\n\n const {\n 'User-Agent': _ignoredUserAgent,\n 'user-agent': _ignoredUserAgentLower,\n ...forwardHeaders\n } = options.headers ?? {};\n\n return {\n apiKey,\n baseURL,\n userAgent,\n headers: Object.keys(forwardHeaders).length > 0 ? forwardHeaders : undefined,\n fetch: options.fetch,\n extraBody: options.extraBody,\n modelOptions,\n };\n };\n\n /**\n * Create a language model.\n */\n const languageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterChatLanguageModel => {\n return new OpenRouterChatLanguageModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an embedding model.\n */\n const embeddingModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterEmbeddingModel => {\n return new OpenRouterEmbeddingModel(modelId, getModelSettings(modelOptions));\n };\n\n /**\n * Create an image model.\n */\n const imageModel = (\n modelId: string,\n modelOptions?: OpenRouterModelOptions\n ): OpenRouterImageModel => {\n return new OpenRouterImageModel(modelId, getModelSettings(modelOptions));\n };\n\n // Create the callable provider object\n const provider = Object.assign(\n // Make provider callable - calling it directly creates a language model\n (modelId: string, modelOptions?: OpenRouterModelOptions) => languageModel(modelId, modelOptions),\n {\n specificationVersion: 'v3' as const,\n languageModel,\n chat: languageModel,\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n imageModel,\n image: imageModel,\n embedding: embeddingModel,\n }\n );\n\n return provider;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FunctionTool,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3ToolChoice,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type {\n OpenResponsesRequest,\n OpenResponsesNonStreamingResponse,\n OpenResponsesStreamEvent,\n OpenResponsesRequestToolFunction,\n OpenAIResponsesToolChoiceUnion,\n} from '@openrouter/sdk/models';\nimport type { EventStream } from '@openrouter/sdk/lib/event-streams';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\nimport { buildProviderMetadata } from '../utils/build-provider-metadata.js';\nimport { buildUsage } from '../utils/build-usage.js';\nimport { convertToOpenRouterMessages } from './convert-to-openrouter-messages.js';\nimport {\n extractReasoningDetails,\n hasEncryptedReasoning,\n buildReasoningProviderMetadata,\n type ReasoningOutputItem,\n} from './extract-reasoning-details.js';\nimport { mapOpenRouterFinishReason } from './map-openrouter-finish-reason.js';\n\n/**\n * OpenRouter chat language model implementing AI SDK V3 LanguageModelV3 interface.\n *\n * Uses the OpenRouter Responses API for both streaming and non-streaming requests.\n */\nexport class OpenRouterChatLanguageModel implements LanguageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Supported URL patterns by media type.\n * OpenRouter Chat API only supports image URLs natively.\n * PDF URLs are not supported - use PDF data URIs or the Responses API instead.\n */\n readonly supportedUrls: Record<string, RegExp[]> = {\n 'image/*': [/^https?:\\/\\/.*$/],\n };\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doGenerate(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3GenerateResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n userAgent: this.settings.userAgent,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (non-streaming)\n const requestParams: OpenResponsesRequest & { stream: false } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: false,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the non-streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as OpenResponsesNonStreamingResponse;\n\n // Build content array from Responses API output\n const content: LanguageModelV3Content[] = [];\n\n // Extract reasoning details for multi-turn conversation support\n // These must be preserved and sent back in subsequent turns for reasoning models\n const reasoningDetails = extractReasoningDetails(response);\n const reasoningMetadata = buildReasoningProviderMetadata(reasoningDetails);\n\n // Process output items\n for (const outputItem of response.output) {\n if (outputItem.type === 'reasoning') {\n // Extract reasoning text from content array or summary\n const reasoningItem = outputItem as ReasoningOutputItem;\n const reasoningText =\n reasoningItem.content\n ?.filter((c) => c.type === 'reasoning_text')\n .map((c) => c.text)\n .join('') ||\n reasoningItem.summary\n ?.filter((c) => c.type === 'summary_text')\n .map((c) => c.text)\n .join('') ||\n '';\n\n if (reasoningText) {\n // Attach reasoning_details to the reasoning part for multi-turn support\n content.push({\n type: 'reasoning',\n text: reasoningText,\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n } else if (outputItem.type === 'message') {\n // Extract text content from message\n const messageItem = outputItem as {\n type: 'message';\n content: Array<{ type: string; text?: string }>;\n };\n for (const contentItem of messageItem.content) {\n if (contentItem.type === 'output_text' && contentItem.text) {\n content.push({\n type: 'text',\n text: contentItem.text,\n });\n }\n }\n } else if (outputItem.type === 'function_call') {\n // Handle tool/function calls\n const functionCallItem = outputItem as {\n type: 'function_call';\n callId: string;\n name: string;\n arguments?: string;\n };\n // Attach reasoning_details to tool-call parts for multi-turn support\n // This is critical for Gemini 3 with thoughtSignature\n content.push({\n type: 'tool-call',\n toolCallId: functionCallItem.callId,\n toolName: functionCallItem.name,\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n input: functionCallItem.arguments || '{}',\n ...(reasoningMetadata && { providerMetadata: reasoningMetadata }),\n });\n }\n }\n\n // Use outputText as fallback if no text content was extracted\n if (response.outputText && !content.some((c) => c.type === 'text')) {\n content.push({\n type: 'text',\n text: response.outputText,\n });\n }\n\n // Build finish reason based on response status\n let finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Gemini 3 thoughtSignature fix: when there are tool calls with encrypted\n // reasoning, the model returns 'completed' but expects continuation.\n // Override to 'tool-calls' so the AI SDK knows to continue the conversation.\n const hasToolCalls = content.some((c) => c.type === 'tool-call');\n if (\n hasToolCalls &&\n hasEncryptedReasoning(reasoningDetails) &&\n finishReason.unified === 'stop'\n ) {\n finishReason = { unified: 'tool-calls', raw: finishReason.raw };\n }\n\n // Build usage from Responses API format\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Note: The Responses API doesn't include 'provider' field directly\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider in response\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens: response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n return {\n content,\n finishReason,\n usage,\n warnings,\n providerMetadata,\n request: {\n body: requestParams,\n },\n response: {\n id: response.id,\n timestamp: new Date(response.createdAt * 1000),\n modelId: response.model,\n },\n };\n }\n\n async doStream(\n options: LanguageModelV3CallOptions\n ): Promise<LanguageModelV3StreamResult> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n userAgent: this.settings.userAgent,\n });\n\n // Convert messages to OpenRouter Responses API format\n const openRouterInput = convertToOpenRouterMessages(options.prompt);\n\n // Convert tools to Responses API format\n const tools = convertToolsToResponsesFormat(options.tools, warnings);\n\n // Convert toolChoice to Responses API format\n const toolChoice = convertToolChoiceToResponsesFormat(options.toolChoice);\n\n // Convert responseFormat to Responses API text.format\n const text = convertResponseFormatToText(options.responseFormat);\n\n // Build request parameters for Responses API (streaming)\n const requestParams: OpenResponsesRequest & { stream: true } = {\n model: this.modelId,\n input: openRouterInput as OpenResponsesRequest['input'],\n stream: true,\n ...(options.maxOutputTokens !== undefined && {\n maxOutputTokens: options.maxOutputTokens,\n }),\n ...(options.temperature !== undefined && {\n temperature: options.temperature,\n }),\n ...(options.topP !== undefined && { topP: options.topP }),\n ...(tools.length > 0 && { tools }),\n ...(toolChoice !== undefined && { toolChoice }),\n ...(text !== undefined && { text }),\n };\n\n // Make the streaming request using Responses API\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const eventStream = (await client.beta.responses.send(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n })) as EventStream<OpenResponsesStreamEvent>;\n\n // Track state for stream transformation\n const state = createStreamState();\n\n // Transform the EventStream to AI SDK V3 stream parts\n const transformedStream = new ReadableStream<LanguageModelV3StreamPart>({\n async start(controller) {\n // Emit stream-start first\n controller.enqueue({\n type: 'stream-start',\n warnings,\n });\n\n try {\n for await (const event of eventStream) {\n const parts = transformResponsesEvent(event, state);\n for (const part of parts) {\n controller.enqueue(part);\n }\n }\n } catch (error) {\n controller.enqueue({\n type: 'error',\n error,\n });\n } finally {\n controller.close();\n }\n },\n });\n\n return {\n stream: transformedStream,\n request: {\n body: requestParams,\n },\n };\n }\n}\n\n/**\n * Stream state for tracking response metadata and content parts.\n */\ninterface StreamState {\n responseId: string | undefined;\n responseModel: string | undefined;\n responseCreated: number | undefined;\n textStarted: boolean;\n textId: string;\n reasoningStarted: boolean;\n reasoningId: string;\n textEnded: boolean;\n reasoningEnded: boolean;\n sourceIds: string[];\n toolCalls: Map<string, { name?: string; argumentsStarted: boolean }>;\n}\n\nfunction createStreamState(): StreamState {\n return {\n responseId: undefined,\n responseModel: undefined,\n responseCreated: undefined,\n textStarted: false,\n textId: 'text-0',\n reasoningStarted: false,\n reasoningId: 'reasoning-0',\n textEnded: false,\n reasoningEnded: false,\n sourceIds: [],\n toolCalls: new Map(),\n };\n}\n\n/**\n * Transform a Responses API stream event to AI SDK V3 stream parts.\n */\nfunction transformResponsesEvent(\n event: OpenResponsesStreamEvent,\n state: StreamState\n): LanguageModelV3StreamPart[] {\n const parts: LanguageModelV3StreamPart[] = [];\n\n switch (event.type) {\n // Response lifecycle events\n case 'response.created':\n case 'response.in_progress': {\n // Capture response metadata from initial events\n if (event.response) {\n state.responseId = event.response.id;\n state.responseModel = event.response.model;\n state.responseCreated = event.response.createdAt;\n }\n break;\n }\n\n // Text streaming\n case 'response.output_text.delta': {\n // Emit text-start if not started\n if (!state.textStarted) {\n state.textStarted = true;\n parts.push({\n type: 'text-start',\n id: state.textId,\n });\n }\n\n // Emit text-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'text-delta',\n id: state.textId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.output_text.done': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n break;\n }\n\n // Reasoning streaming\n case 'response.reasoning_text.delta': {\n // Emit reasoning-start if not started\n if (!state.reasoningStarted) {\n state.reasoningStarted = true;\n parts.push({\n type: 'reasoning-start',\n id: state.reasoningId,\n });\n }\n\n // Emit reasoning-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'reasoning-delta',\n id: state.reasoningId,\n delta: event.delta,\n });\n }\n break;\n }\n\n // Function call arguments streaming\n case 'response.function_call_arguments.delta': {\n const toolCallId = event.itemId;\n let toolState = state.toolCalls.get(toolCallId);\n\n if (!toolState) {\n toolState = { argumentsStarted: false };\n state.toolCalls.set(toolCallId, toolState);\n }\n\n // Emit tool-input-start if not started\n if (!toolState.argumentsStarted) {\n toolState.argumentsStarted = true;\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: toolState.name ?? '', // Will be filled in by output_item.added\n });\n }\n\n // Emit tool-input-delta\n if (event.delta && event.delta.length > 0) {\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: event.delta,\n });\n }\n break;\n }\n\n case 'response.function_call_arguments.done': {\n const toolCallId = event.itemId;\n const toolState = state.toolCalls.get(toolCallId);\n\n // If we haven't started tool call yet, emit start + delta with full args\n if (!toolState?.argumentsStarted) {\n parts.push({\n type: 'tool-input-start',\n id: toolCallId,\n toolName: event.name,\n });\n // Default to empty object when arguments is undefined/empty\n const args = event.arguments || '{}';\n parts.push({\n type: 'tool-input-delta',\n id: toolCallId,\n delta: args,\n });\n }\n\n // Emit tool-input-end\n parts.push({\n type: 'tool-input-end',\n id: toolCallId,\n });\n\n // Emit tool-call with complete tool call data\n // Default to empty object when arguments is undefined/empty\n // (some providers omit arguments for tools with no parameters)\n parts.push({\n type: 'tool-call',\n toolCallId,\n toolName: event.name,\n input: event.arguments || '{}',\n });\n break;\n }\n\n // Output item events (for function call metadata)\n case 'response.output_item.added': {\n if (event.item.type === 'function_call') {\n const funcItem = event.item as {\n type: 'function_call';\n callId?: string;\n name: string;\n };\n const toolCallId = funcItem.callId ?? `tool-${event.outputIndex}`;\n const toolState = state.toolCalls.get(toolCallId) ?? {\n argumentsStarted: false,\n };\n toolState.name = funcItem.name;\n state.toolCalls.set(toolCallId, toolState);\n }\n break;\n }\n\n // Annotation events (web search sources)\n case 'response.output_text.annotation.added': {\n const annotation = event.annotation;\n if (annotation.type === 'url_citation') {\n const urlAnnotation = annotation as {\n type: 'url_citation';\n url: string;\n title: string;\n };\n const sourceId = `source-${state.sourceIds.length}`;\n state.sourceIds.push(sourceId);\n parts.push({\n type: 'source',\n sourceType: 'url',\n id: sourceId,\n url: urlAnnotation.url,\n title: urlAnnotation.title,\n });\n }\n break;\n }\n\n // Response completed - extract final usage data\n case 'response.completed': {\n // End text if started and not ended\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n\n // End reasoning if started and not ended\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n // Emit response-metadata\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Build finish reason based on response status\n const finishReason = mapOpenRouterFinishReason(\n response.status === 'completed' ? 'stop' : response.status ?? 'stop'\n );\n\n // Build usage\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n // Build provider metadata\n // Map Responses API field names to Chat Completions API names\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined, // Responses API doesn't expose provider\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Response incomplete or failed\n case 'response.incomplete':\n case 'response.failed': {\n // End any open content parts\n if (state.textStarted && !state.textEnded) {\n state.textEnded = true;\n parts.push({\n type: 'text-end',\n id: state.textId,\n });\n }\n if (state.reasoningStarted && !state.reasoningEnded) {\n state.reasoningEnded = true;\n parts.push({\n type: 'reasoning-end',\n id: state.reasoningId,\n });\n }\n\n const response = event.response;\n parts.push({\n type: 'response-metadata',\n id: response.id,\n timestamp: response.createdAt\n ? new Date(response.createdAt * 1000)\n : undefined,\n modelId: response.model,\n });\n\n // Map finish reason\n const finishReason =\n event.type === 'response.failed'\n ? mapOpenRouterFinishReason('error')\n : mapOpenRouterFinishReason(response.status ?? 'incomplete');\n\n const usage = buildUsage(\n response.usage\n ? {\n inputTokens: response.usage.inputTokens,\n outputTokens: response.usage.outputTokens,\n }\n : undefined\n );\n\n const providerMetadata = buildProviderMetadata({\n id: response.id,\n provider: undefined,\n usage: response.usage\n ? {\n promptTokens: response.usage.inputTokens,\n completionTokens: response.usage.outputTokens,\n totalTokens: response.usage.totalTokens,\n cost: response.usage.cost ?? undefined,\n // Map inputTokensDetails -> promptTokensDetails\n promptTokensDetails: response.usage.inputTokensDetails\n ? {\n cachedTokens:\n response.usage.inputTokensDetails.cachedTokens,\n }\n : undefined,\n // Map outputTokensDetails -> completionTokensDetails\n completionTokensDetails: response.usage.outputTokensDetails\n ? {\n reasoningTokens:\n response.usage.outputTokensDetails.reasoningTokens,\n }\n : undefined,\n }\n : undefined,\n });\n\n parts.push({\n type: 'finish',\n finishReason,\n usage,\n providerMetadata,\n });\n break;\n }\n\n // Error event\n case 'error': {\n const errorEvent = event as {\n type: 'error';\n error?: { message?: string };\n };\n parts.push({\n type: 'error',\n error: new Error(\n errorEvent.error?.message ?? 'Unknown streaming error'\n ),\n });\n break;\n }\n\n // Ignored events (handled implicitly or not needed)\n case 'response.output_item.done':\n case 'response.content_part.added':\n case 'response.content_part.done':\n case 'response.refusal.delta':\n case 'response.refusal.done':\n case 'response.reasoning_text.done':\n case 'response.reasoning_summary_part.added':\n case 'response.reasoning_summary_part.done':\n case 'response.reasoning_summary_text.delta':\n case 'response.reasoning_summary_text.done':\n case 'response.image_generation_call.in_progress':\n case 'response.image_generation_call.generating':\n case 'response.image_generation_call.partial_image':\n case 'response.image_generation_call.completed':\n // These events are either handled by other events or not relevant for AI SDK\n break;\n }\n\n return parts;\n}\n\n/**\n * Convert AI SDK tools to OpenRouter Responses API format.\n * Only 'function' type tools are supported.\n */\nfunction convertToolsToResponsesFormat(\n tools: LanguageModelV3CallOptions['tools'],\n warnings: SharedV3Warning[]\n): OpenResponsesRequestToolFunction[] {\n if (!tools || tools.length === 0) {\n return [];\n }\n\n return tools\n .map((tool): OpenResponsesRequestToolFunction | null => {\n if (tool.type !== 'function') {\n warnings.push({\n type: 'unsupported',\n feature: `tool type '${tool.type}'`,\n details: `Only 'function' type tools are supported. Tool '${(tool as { name?: string }).name ?? 'unknown'}' has type '${tool.type}'.`,\n });\n return null;\n }\n\n const functionTool = tool as LanguageModelV3FunctionTool;\n return {\n type: 'function',\n name: functionTool.name,\n description: functionTool.description ?? null,\n parameters: functionTool.inputSchema as { [k: string]: unknown } | null,\n };\n })\n .filter((tool): tool is OpenResponsesRequestToolFunction => tool !== null);\n}\n\n/**\n * Convert AI SDK toolChoice to OpenRouter Responses API format.\n *\n * Mapping:\n * - 'auto' -> 'auto'\n * - 'none' -> 'none'\n * - 'required' -> 'required'\n * - { type: 'tool', toolName } -> { type: 'function', name: toolName }\n */\nfunction convertToolChoiceToResponsesFormat(\n toolChoice: LanguageModelV3ToolChoice | undefined\n): OpenAIResponsesToolChoiceUnion | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case 'auto':\n return 'auto';\n case 'none':\n return 'none';\n case 'required':\n return 'required';\n case 'tool':\n return {\n type: 'function',\n name: toolChoice.toolName,\n };\n default:\n return undefined;\n }\n}\n\n/**\n * Convert AI SDK responseFormat to OpenRouter Responses API text.format.\n *\n * Mapping:\n * - { type: 'text' } -> { type: 'text' }\n * - { type: 'json' } -> { type: 'json_object' } (no schema)\n * - { type: 'json', schema, name } -> { type: 'json_schema', name, schema } (with schema)\n */\nfunction convertResponseFormatToText(\n responseFormat: LanguageModelV3CallOptions['responseFormat']\n): OpenResponsesRequest['text'] | undefined {\n if (!responseFormat) {\n return undefined;\n }\n\n if (responseFormat.type === 'text') {\n return {\n format: { type: 'text' },\n };\n }\n\n if (responseFormat.type === 'json') {\n // If a schema is provided, use json_schema format\n if (responseFormat.schema) {\n return {\n format: {\n type: 'json_schema',\n name: responseFormat.name ?? 'response',\n description: responseFormat.description,\n schema: responseFormat.schema as { [k: string]: unknown },\n },\n };\n }\n // No schema - use simple json_object format\n return {\n format: { type: 'json_object' },\n };\n }\n\n return undefined;\n}\n","import type { JSONObject } from '@ai-sdk/provider';\nimport type { ChatGenerationTokenUsage } from '@openrouter/sdk/models';\n\n/**\n * OpenRouter-specific provider metadata structure.\n */\nexport interface OpenRouterProviderMetadata {\n /**\n * The response ID from OpenRouter.\n */\n responseId?: string;\n\n /**\n * The upstream provider that served the request.\n */\n provider?: string;\n\n /**\n * Detailed usage information.\n */\n usage?: {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n promptTokensDetails?: {\n cachedTokens?: number;\n cacheWriteTokens?: number;\n audioTokens?: number;\n videoTokens?: number;\n };\n completionTokensDetails?: {\n reasoningTokens?: number;\n imageTokens?: number;\n };\n /**\n * Cost in USD (omit if unavailable).\n */\n cost?: number;\n /**\n * Whether the request used BYOK (Bring Your Own Key).\n */\n isByok?: boolean;\n /**\n * Detailed cost breakdown.\n */\n costDetails?: JSONObject;\n };\n}\n\n/**\n * Extended prompt tokens details with fields not in SDK types.\n */\nexport interface ExtendedPromptTokensDetails {\n cachedTokens?: number | null;\n cacheWriteTokens?: number | null;\n audioTokens?: number | null;\n videoTokens?: number | null;\n}\n\n/**\n * Extended completion tokens details with fields not in SDK types.\n */\nexport interface ExtendedCompletionTokensDetails {\n reasoningTokens?: number | null;\n imageTokens?: number | null;\n}\n\n/**\n * Extended usage type with additional fields from raw OpenRouter API response.\n * The SDK types don't include cost/is_byok but the API returns them.\n */\nexport interface OpenRouterUsageExtended extends Omit<ChatGenerationTokenUsage, 'promptTokensDetails' | 'completionTokensDetails'> {\n cost?: number;\n isByok?: boolean;\n costDetails?: JSONObject;\n promptTokensDetails?: ExtendedPromptTokensDetails | null;\n completionTokensDetails?: ExtendedCompletionTokensDetails | null;\n}\n\n/**\n * Response data from OpenRouter API used to build provider metadata.\n * Note: The SDK transforms snake_case to camelCase for all fields.\n * The `provider` field exists in raw API responses but isn't in SDK types.\n */\nexport interface OpenRouterResponseData {\n id?: string;\n /**\n * The upstream provider that served the request (e.g. \"Google\", \"Anthropic\").\n * This field exists in the raw API response but isn't in SDK TypeScript types.\n */\n provider?: string;\n /**\n * Usage data in camelCase (as transformed by SDK).\n */\n usage?: OpenRouterUsageExtended;\n}\n\n/**\n * Filters out undefined values from an object, returning only defined properties.\n * This ensures providerMetadata is valid JSON (undefined is not a valid JSON value).\n */\nfunction filterUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined)\n ) as Partial<T>;\n}\n\n/**\n * Builds provider metadata from OpenRouter API response data.\n *\n * @param response - The response data from OpenRouter API (with camelCase fields from SDK).\n * @returns Provider metadata in the format expected by AI SDK.\n */\nexport function buildProviderMetadata(\n response: OpenRouterResponseData | undefined\n): Record<string, JSONObject> | undefined {\n if (!response) {\n return undefined;\n }\n\n const usage = response.usage;\n const usageMetadata: OpenRouterProviderMetadata['usage'] | undefined = usage\n ? filterUndefined({\n promptTokens: usage.promptTokens,\n completionTokens: usage.completionTokens,\n totalTokens: usage.totalTokens,\n ...(usage.promptTokensDetails && {\n promptTokensDetails: filterUndefined({\n cachedTokens: usage.promptTokensDetails.cachedTokens ?? undefined,\n cacheWriteTokens: usage.promptTokensDetails.cacheWriteTokens ?? undefined,\n audioTokens: usage.promptTokensDetails.audioTokens ?? undefined,\n videoTokens: usage.promptTokensDetails.videoTokens ?? undefined,\n }),\n }),\n ...(usage.completionTokensDetails && {\n completionTokensDetails: filterUndefined({\n reasoningTokens: usage.completionTokensDetails.reasoningTokens ?? undefined,\n imageTokens: usage.completionTokensDetails.imageTokens ?? undefined,\n }),\n }),\n cost: usage.cost,\n isByok: usage.isByok,\n costDetails: usage.costDetails,\n })\n : undefined;\n\n const metadata: OpenRouterProviderMetadata = filterUndefined({\n responseId: response.id,\n provider: response.provider,\n usage: usageMetadata,\n });\n\n return {\n openrouter: metadata as unknown as JSONObject,\n };\n}\n","import type { LanguageModelV3Usage, JSONObject } from '@ai-sdk/provider';\n\n/**\n * Raw usage data from OpenRouter API response.\n */\nexport interface OpenRouterRawUsage {\n inputTokens?: number;\n outputTokens?: number;\n inputTokensDetails?: {\n cachedTokens?: number;\n };\n outputTokensDetails?: {\n reasoningTokens?: number;\n };\n}\n\n/**\n * Builds a LanguageModelV3Usage object from OpenRouter API usage data.\n *\n * @param usage - The raw usage data from the OpenRouter API response.\n * @returns A LanguageModelV3Usage object with standardized token counts.\n */\nexport function buildUsage(usage: OpenRouterRawUsage | undefined): LanguageModelV3Usage {\n if (!usage) {\n return {\n inputTokens: {\n total: 0,\n noCache: undefined,\n cacheRead: undefined,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: 0,\n text: undefined,\n reasoning: undefined,\n },\n raw: undefined,\n };\n }\n\n // Convert to JSONObject-compatible format for raw field\n const rawUsage: JSONObject = {\n inputTokens: usage.inputTokens ?? null,\n outputTokens: usage.outputTokens ?? null,\n ...(usage.inputTokensDetails && {\n inputTokensDetails: {\n cachedTokens: usage.inputTokensDetails.cachedTokens ?? null,\n },\n }),\n ...(usage.outputTokensDetails && {\n outputTokensDetails: {\n reasoningTokens: usage.outputTokensDetails.reasoningTokens ?? null,\n },\n }),\n };\n\n return {\n inputTokens: {\n total: usage.inputTokens ?? 0,\n noCache: undefined,\n cacheRead: usage.inputTokensDetails?.cachedTokens,\n cacheWrite: undefined,\n },\n outputTokens: {\n total: usage.outputTokens ?? 0,\n text: undefined,\n reasoning: usage.outputTokensDetails?.reasoningTokens,\n },\n raw: rawUsage,\n };\n}\n","import type {\n LanguageModelV3Prompt,\n LanguageModelV3Message,\n LanguageModelV3TextPart,\n LanguageModelV3FilePart,\n LanguageModelV3ReasoningPart,\n LanguageModelV3ToolCallPart,\n LanguageModelV3ToolResultPart,\n LanguageModelV3ToolResultOutput,\n JSONValue,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter Responses API input item types.\n * These match the OpenResponsesEasyInputMessage format used by the Responses API.\n */\nexport type OpenRouterInputItem =\n | OpenRouterEasyInputMessage\n | OpenRouterFunctionCall\n | OpenRouterFunctionCallOutput;\n\n/**\n * Reasoning details item format for API requests.\n * Used to preserve reasoning context across multi-turn conversations.\n */\nexport interface OpenRouterReasoningDetailItem {\n type: 'reasoning.text' | 'reasoning.summary' | 'reasoning.encrypted';\n id?: string;\n format?: string | null;\n index: number;\n text?: string; // For reasoning.text\n signature?: string | null; // For reasoning.text (Claude)\n summary?: string; // For reasoning.summary\n data?: string; // For reasoning.encrypted (Gemini)\n}\n\n/**\n * Reasoning object for assistant messages.\n * Contains the reasoning details to send back to the API.\n */\nexport interface OpenRouterReasoning {\n text?: string;\n summary?: string;\n encrypted?: string;\n}\n\n/**\n * Easy input message format for Responses API.\n * Supports user, system, assistant, and developer roles.\n */\nexport interface OpenRouterEasyInputMessage {\n type?: 'message';\n role: 'user' | 'system' | 'assistant' | 'developer';\n content: string | OpenRouterInputContent[];\n reasoning?: OpenRouterReasoning;\n}\n\nexport interface OpenRouterFunctionCall {\n type: 'function_call';\n callId: string;\n name: string;\n arguments: string;\n}\n\nexport interface OpenRouterFunctionCallOutput {\n type: 'function_call_output';\n callId: string;\n output: string;\n status: 'completed' | 'incomplete';\n}\n\n/**\n * Input content types for Responses API.\n * Uses 'input_text', 'input_image', 'input_file' type prefixes.\n */\nexport type OpenRouterInputContent =\n | { type: 'input_text'; text: string }\n | { type: 'input_image'; imageUrl: string; detail?: 'auto' | 'low' | 'high' }\n | { type: 'input_file'; fileUrl: string; filename?: string };\n\n/**\n * Converts AI SDK V3 prompt format to OpenRouter Responses API input format.\n *\n * Mapping table:\n * - system { content } -> { role: 'system', content: string }\n * - user text -> { role: 'user', content: [{ type: 'input_text', text }] }\n * - user image -> { role: 'user', content: [{ type: 'input_image', imageUrl }] }\n * - user file -> { role: 'user', content: [{ type: 'input_file', fileUrl }] }\n * - assistant text -> { role: 'assistant', content: string }\n * - assistant tool-call -> { type: 'function_call', ... }\n * - tool result -> { type: 'function_call_output', ... }\n *\n * @param prompt - The AI SDK V3 prompt\n * @returns Array of input items in OpenRouter Responses API format\n */\nexport function convertToOpenRouterMessages(\n prompt: LanguageModelV3Prompt\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const message of prompt) {\n const converted = convertMessage(message);\n result.push(...converted);\n }\n\n return result;\n}\n\n/**\n * Convert a single V3 message to OpenRouter Responses API format.\n * May return multiple items (e.g., when assistant has text + tool calls).\n */\nfunction convertMessage(message: LanguageModelV3Message): OpenRouterInputItem[] {\n // Extract providerOptions from the message for reasoning_details\n const messageWithOptions = message as LanguageModelV3Message & {\n providerOptions?: Record<string, Record<string, unknown>>;\n providerMetadata?: Record<string, Record<string, unknown>>;\n };\n const providerOptions = messageWithOptions.providerOptions;\n const providerMetadata = messageWithOptions.providerMetadata;\n\n switch (message.role) {\n case 'system':\n return [{ role: 'system', content: message.content }];\n\n case 'user':\n return [convertUserMessage(message.content)];\n\n case 'assistant':\n return convertAssistantMessage(message.content, providerMetadata, providerOptions);\n\n case 'tool':\n return convertToolMessage(message.content);\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = message;\n throw new Error(`Unknown message role: ${(_exhaustive as { role: string }).role}`);\n }\n }\n}\n\n/**\n * Convert user message content parts to OpenRouter Responses API format.\n */\nfunction convertUserMessage(\n content: Array<LanguageModelV3TextPart | LanguageModelV3FilePart>\n): OpenRouterEasyInputMessage {\n const convertedContent: OpenRouterInputContent[] = [];\n\n for (const part of content) {\n switch (part.type) {\n case 'text': {\n convertedContent.push({ type: 'input_text', text: part.text });\n break;\n }\n\n case 'file':\n convertedContent.push(convertFilePart(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(`Unknown user content type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n }\n\n return { role: 'user', content: convertedContent };\n}\n\n/**\n * Convert a file part to the appropriate OpenRouter Responses API format.\n *\n * OpenRouter's Responses API uses 'input_image' for images and 'input_file' for other files.\n */\nfunction convertFilePart(part: LanguageModelV3FilePart): OpenRouterInputContent {\n const url = convertDataContent(part.data, part.mediaType);\n \n // Check if it's an image based on media type\n if (part.mediaType.startsWith('image/')) {\n return {\n type: 'input_image',\n imageUrl: url,\n detail: 'auto',\n };\n }\n \n // For other file types (PDF, etc.), use input_file\n return {\n type: 'input_file',\n fileUrl: url,\n };\n}\n\n/**\n * Convert data content (URL, string, or Uint8Array) to a string URL or data URI.\n */\nfunction convertDataContent(\n data: URL | string | Uint8Array,\n mediaType: string\n): string {\n if (data instanceof URL) {\n return data.toString();\n }\n\n if (data instanceof Uint8Array) {\n // Convert Uint8Array to base64 data URI\n const base64 = uint8ArrayToBase64(data);\n return `data:${mediaType};base64,${base64}`;\n }\n\n // String - could be URL or base64 data\n // If it starts with http(s) or data:, treat as URL/data URI\n if (data.startsWith('http://') || data.startsWith('https://') || data.startsWith('data:')) {\n return data;\n }\n\n // Otherwise assume it's base64 encoded data\n return `data:${mediaType};base64,${data}`;\n}\n\n/**\n * Convert Uint8Array to base64 string.\n */\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n // Use browser-compatible base64 encoding\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary);\n}\n\n/**\n * SDK format for reasoning items returned from OpenRouter.\n * Used when extracting reasoning_details from providerMetadata.\n */\ninterface SdkReasoningItem {\n type?: string;\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n // Also support flattened API format\n text?: string;\n data?: string;\n index?: number;\n}\n\n/**\n * Extract reasoning_details from providerMetadata or providerOptions.\n * Checks multiple locations for backwards compatibility.\n */\nfunction extractReasoningDetails(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): JSONValue[] | undefined {\n // Check message-level metadata first\n const messageLevel =\n providerOptions?.openrouter?.reasoning_details ??\n providerMetadata?.openrouter?.reasoning_details;\n\n if (messageLevel && Array.isArray(messageLevel) && messageLevel.length > 0) {\n return messageLevel as JSONValue[];\n }\n\n // Check reasoning content parts for part-level metadata\n for (const part of content) {\n if (part.type === 'reasoning') {\n const partWithMeta = part as LanguageModelV3ReasoningPart & {\n providerMetadata?: Record<string, { reasoning_details?: JSONValue[] }>;\n providerOptions?: Record<string, { reasoning_details?: JSONValue[] }>;\n };\n const partLevel =\n partWithMeta.providerOptions?.openrouter?.reasoning_details ??\n partWithMeta.providerMetadata?.openrouter?.reasoning_details;\n if (partLevel && Array.isArray(partLevel) && partLevel.length > 0) {\n return partLevel as JSONValue[];\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Transform SDK reasoning format to API request format.\n * Flattens the structure for sending back to OpenRouter.\n */\nfunction transformReasoningToApiFormat(\n sdkItems: JSONValue[],\n): OpenRouterReasoningDetailItem[] {\n const apiItems: OpenRouterReasoningDetailItem[] = [];\n\n for (const rawItem of sdkItems) {\n if (typeof rawItem !== 'object' || rawItem === null) {\n continue;\n }\n const item = rawItem as SdkReasoningItem;\n\n const baseProps = {\n id: item.id,\n format: item.format ?? null,\n };\n\n let index = item.index ?? 0;\n\n // Handle already-flattened API format (reasoning.text, reasoning.summary, reasoning.encrypted)\n if (item.type === 'reasoning.text' && item.text !== undefined) {\n apiItems.push({\n type: 'reasoning.text',\n text: item.text,\n signature: item.signature ?? null,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.summary' && item.summary !== undefined) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: typeof item.summary === 'string' ? item.summary : '',\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n if (item.type === 'reasoning.encrypted' && item.data !== undefined) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.data,\n index: index,\n ...baseProps,\n });\n continue;\n }\n\n // Handle SDK format (type: 'reasoning' with content/summary/encryptedContent)\n if (item.type === 'reasoning' || item.content || item.summary || item.encryptedContent) {\n // Transform content items to reasoning.text\n if (item.content && Array.isArray(item.content)) {\n for (const contentItem of item.content) {\n if (contentItem.type === 'reasoning_text' && contentItem.text) {\n apiItems.push({\n type: 'reasoning.text',\n text: contentItem.text,\n signature: item.signature ?? null,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform summary items to reasoning.summary\n if (item.summary && Array.isArray(item.summary)) {\n for (const summaryItem of item.summary) {\n if (summaryItem.type === 'summary_text' && summaryItem.text) {\n apiItems.push({\n type: 'reasoning.summary',\n summary: summaryItem.text,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n // Transform encryptedContent to reasoning.encrypted (Gemini)\n if (item.encryptedContent) {\n apiItems.push({\n type: 'reasoning.encrypted',\n data: item.encryptedContent,\n index: index++,\n ...baseProps,\n });\n }\n }\n }\n\n return apiItems;\n}\n\n/**\n * Build OpenRouterReasoning object from reasoning detail items.\n * Combines all items into a single reasoning object for the API.\n */\nfunction buildReasoningFromDetails(\n items: OpenRouterReasoningDetailItem[],\n): OpenRouterReasoning | undefined {\n if (items.length === 0) {\n return undefined;\n }\n\n const reasoning: OpenRouterReasoning = {};\n\n // Collect all text items\n const textItems = items.filter((i) => i.type === 'reasoning.text' && i.text);\n if (textItems.length > 0) {\n reasoning.text = textItems.map((i) => i.text).join('');\n }\n\n // Collect all summary items\n const summaryItems = items.filter(\n (i) => i.type === 'reasoning.summary' && i.summary,\n );\n if (summaryItems.length > 0) {\n reasoning.summary = summaryItems.map((i) => i.summary).join('');\n }\n\n // Collect encrypted content (should be only one)\n const encryptedItem = items.find(\n (i) => i.type === 'reasoning.encrypted' && i.data,\n );\n if (encryptedItem?.data) {\n reasoning.encrypted = encryptedItem.data;\n }\n\n // Return undefined if no content\n if (!reasoning.text && !reasoning.summary && !reasoning.encrypted) {\n return undefined;\n }\n\n return reasoning;\n}\n\n/**\n * Convert assistant message content parts to OpenRouter Responses API format.\n * Tool calls become separate items in the output array.\n * Extracts reasoning_details from providerMetadata for multi-turn continuation.\n */\nfunction convertAssistantMessage(\n content: Array<\n | LanguageModelV3TextPart\n | LanguageModelV3FilePart\n | LanguageModelV3ReasoningPart\n | LanguageModelV3ToolCallPart\n | LanguageModelV3ToolResultPart\n >,\n providerMetadata?: Record<string, Record<string, unknown>>,\n providerOptions?: Record<string, Record<string, unknown>>,\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n let textContent = '';\n\n // Extract reasoning details for multi-turn continuation\n const sdkReasoningDetails = extractReasoningDetails(\n content,\n providerMetadata,\n providerOptions,\n );\n const reasoningItems = sdkReasoningDetails\n ? transformReasoningToApiFormat(sdkReasoningDetails)\n : [];\n const reasoning = buildReasoningFromDetails(reasoningItems);\n\n for (const part of content) {\n switch (part.type) {\n case 'text':\n textContent += part.text;\n break;\n\n case 'reasoning':\n // Include reasoning as part of text\n textContent += part.text;\n break;\n\n case 'tool-call':\n // Tool calls are separate items in Responses API\n result.push({\n type: 'function_call',\n callId: part.toolCallId,\n name: part.toolName,\n arguments:\n typeof part.input === 'string'\n ? part.input\n : JSON.stringify(part.input),\n });\n break;\n\n case 'file':\n // Files in assistant messages - skip for now as they're typically for output\n break;\n\n case 'tool-result':\n // Tool results in assistant messages (provider-executed tools)\n result.push(convertToolResult(part));\n break;\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = part;\n throw new Error(\n `Unknown assistant content type: ${(_exhaustive as { type: string }).type}`\n );\n }\n }\n }\n\n // If there's text content, add it as an assistant message first\n // Responses API uses simple string content for assistant messages\n if (textContent) {\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: textContent,\n };\n // Attach reasoning for multi-turn continuation\n if (reasoning) {\n assistantMessage.reasoning = reasoning;\n }\n result.unshift(assistantMessage);\n } else if (reasoning) {\n // Even without text, include reasoning if present (for tool-call only messages)\n const assistantMessage: OpenRouterEasyInputMessage = {\n role: 'assistant',\n content: '',\n };\n assistantMessage.reasoning = reasoning;\n result.unshift(assistantMessage);\n }\n\n return result;\n}\n\n/**\n * Convert tool message content parts to OpenRouter Responses API format.\n */\nfunction convertToolMessage(\n content: Array<LanguageModelV3ToolResultPart | { type: 'tool-approval-response'; approvalId: string; approved: boolean; reason?: string }>\n): OpenRouterInputItem[] {\n const result: OpenRouterInputItem[] = [];\n\n for (const part of content) {\n if (part.type === 'tool-result') {\n result.push(convertToolResult(part));\n }\n // Skip tool-approval-response as it's not directly mapped to OpenRouter format\n }\n\n return result;\n}\n\n/**\n * Convert a tool result part to OpenRouter function_call_output format.\n */\nfunction convertToolResult(part: LanguageModelV3ToolResultPart): OpenRouterFunctionCallOutput {\n const output = convertToolResultOutput(part.output);\n\n return {\n type: 'function_call_output',\n callId: part.toolCallId,\n output: output.value,\n status: output.isError ? 'incomplete' : 'completed',\n };\n}\n\n/**\n * Convert tool result output to a string value.\n */\nfunction convertToolResultOutput(output: LanguageModelV3ToolResultOutput): {\n value: string;\n isError: boolean;\n} {\n switch (output.type) {\n case 'text':\n return { value: output.value, isError: false };\n\n case 'json':\n return { value: JSON.stringify(output.value), isError: false };\n\n case 'execution-denied':\n return {\n value: `Execution denied: ${output.reason ?? 'No reason provided'}`,\n isError: true,\n };\n\n case 'error-text':\n return { value: output.value, isError: true };\n\n case 'error-json':\n return { value: JSON.stringify(output.value), isError: true };\n\n case 'content': {\n // For content array, convert to string representation\n const textParts = output.value\n .filter((item): item is { type: 'text'; text: string } => item.type === 'text')\n .map((item) => item.text);\n return { value: textParts.join('\\n'), isError: false };\n }\n\n default: {\n // TypeScript exhaustiveness check\n const _exhaustive: never = output;\n throw new Error(`Unknown tool result output type: ${(_exhaustive as { type: string }).type}`);\n }\n }\n}\n","/**\n * Reasoning details extraction for multi-turn conversations.\n *\n * WHY: Reasoning models (Claude, Gemini 3, o1) return encrypted/signed reasoning\n * content that MUST be sent back verbatim in subsequent turns. Without preserving\n * and re-sending reasoning_details, the model loses context about its previous\n * thought process, breaking extended reasoning chains.\n *\n * This module handles extraction from OpenRouter Responses API responses and\n * attachment to AI SDK content parts via providerMetadata.\n */\n\nimport type { JSONObject, JSONValue } from '@ai-sdk/provider';\nimport type {\n OpenResponsesNonStreamingResponse,\n OpenResponsesReasoning,\n} from '@openrouter/sdk/models';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * Raw reasoning item from OpenRouter response output.\n */\nexport interface ReasoningOutputItem {\n type: 'reasoning';\n id?: string;\n format?: string | null;\n signature?: string | null;\n content?: Array<{ type: string; text: string }>;\n summary?: Array<{ type: string; text: string }>;\n encryptedContent?: string;\n}\n\n/**\n * Reasoning details in SDK format (as returned by OpenRouter).\n * This is the format we store in providerMetadata for round-tripping.\n */\nexport type ReasoningDetails = JSONValue[];\n\n// =============================================================================\n// Extraction Functions\n// =============================================================================\n\n/**\n * Extract reasoning details from a non-streaming OpenRouter Responses API response.\n *\n * Reasoning details can come from:\n * 1. Output items with type 'reasoning' (Responses API format)\n * 2. Message-level reasoning_details field (Chat Completions API format)\n *\n * @param response - The full OpenRouter Responses API response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetails(\n response: OpenResponsesNonStreamingResponse\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n // Extract from output items (Responses API format)\n for (const outputItem of response.output) {\n if ('type' in outputItem && outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as ReasoningOutputItem;\n\n // Store the full reasoning item structure for round-tripping\n // This preserves all provider-specific fields (signature, encryptedContent, etc.)\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n/**\n * Extract reasoning details from streaming response output items.\n *\n * Called at the end of streaming when we have the full response.\n *\n * @param outputItems - The output items from the completed stream response\n * @returns Reasoning details array, or undefined if none found\n */\nexport function extractReasoningDetailsFromOutput(\n outputItems: Array<{ type: string; [key: string]: unknown }>\n): ReasoningDetails | undefined {\n const extractedDetails: JSONValue[] = [];\n\n for (const outputItem of outputItems) {\n if (outputItem.type === 'reasoning') {\n const reasoningItem = outputItem as unknown as ReasoningOutputItem;\n\n extractedDetails.push({\n type: 'reasoning',\n id: reasoningItem.id,\n content: reasoningItem.content,\n summary: reasoningItem.summary,\n encryptedContent: reasoningItem.encryptedContent,\n signature: reasoningItem.signature,\n format: reasoningItem.format,\n } as JSONValue);\n }\n }\n\n return extractedDetails.length > 0 ? extractedDetails : undefined;\n}\n\n// =============================================================================\n// Provider Detection\n// =============================================================================\n\n/**\n * Check if reasoning details contain encrypted content (Gemini thoughtSignature).\n *\n * This is important for Gemini 3 models which return 'completed' status\n * but expect continuation when tool calls exist with encrypted reasoning.\n *\n * @param reasoningDetails - The extracted reasoning details\n * @returns True if encrypted content is present\n */\nexport function hasEncryptedReasoning(\n reasoningDetails: ReasoningDetails | undefined\n): boolean {\n if (!reasoningDetails) {\n return false;\n }\n\n return reasoningDetails.some((d) => {\n if (typeof d === 'object' && d !== null) {\n const obj = d as Record<string, unknown>;\n return obj.encryptedContent != null || obj.type === 'reasoning.encrypted';\n }\n return false;\n });\n}\n\n/**\n * Build provider metadata object with reasoning details.\n *\n * @param reasoningDetails - The reasoning details to include\n * @returns Provider metadata object for attachment to content parts (SharedV3ProviderMetadata compatible)\n */\nexport function buildReasoningProviderMetadata(\n reasoningDetails: ReasoningDetails | undefined\n): Record<string, JSONObject> | undefined {\n if (!reasoningDetails || reasoningDetails.length === 0) {\n return undefined;\n }\n\n return {\n openrouter: {\n reasoning_details: reasoningDetails,\n } as JSONObject,\n };\n}\n\n// =============================================================================\n// Re-export types for convenience\n// =============================================================================\n\nexport type { OpenResponsesReasoning };\n","import type { LanguageModelV3FinishReason } from '@ai-sdk/provider';\n\n/**\n * Maps OpenRouter finish reasons to the AI SDK V3 unified format.\n *\n * Mapping table:\n * - 'end_turn', 'stop', 'stop_sequence' -> 'stop'\n * - 'max_tokens', 'length' -> 'length'\n * - 'tool_use', 'tool_calls' -> 'tool-calls'\n * - 'content_filter' -> 'content-filter'\n * - 'error' -> 'error'\n * - null/undefined/unknown -> 'other'\n *\n * @param finishReason - The finish reason from OpenRouter API response\n * @returns Object containing the unified finish reason and raw original value\n */\nexport function mapOpenRouterFinishReason(\n finishReason: string | null | undefined\n): LanguageModelV3FinishReason {\n // Handle null/undefined\n if (finishReason == null) {\n return { unified: 'other', raw: undefined };\n }\n\n // Map to unified format\n switch (finishReason) {\n case 'end_turn':\n case 'stop':\n case 'stop_sequence':\n return { unified: 'stop', raw: finishReason };\n\n case 'max_tokens':\n case 'length':\n return { unified: 'length', raw: finishReason };\n\n case 'tool_use':\n case 'tool_calls':\n return { unified: 'tool-calls', raw: finishReason };\n\n case 'content_filter':\n return { unified: 'content-filter', raw: finishReason };\n\n case 'error':\n return { unified: 'error', raw: finishReason };\n\n default:\n return { unified: 'other', raw: finishReason };\n }\n}\n","import type {\n EmbeddingModelV3,\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Result,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { combineHeaders, normalizeHeaders } from '@ai-sdk/provider-utils';\nimport { OpenRouter } from '@openrouter/sdk';\nimport type { CreateEmbeddingsResponseBody } from '@openrouter/sdk/models/operations';\n\nimport type { OpenRouterModelSettings } from '../openrouter-provider.js';\n\n/**\n * OpenRouter embedding model implementing AI SDK V3 EmbeddingModelV3 interface.\n */\nexport class OpenRouterEmbeddingModel implements EmbeddingModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n private readonly settings: OpenRouterModelSettings;\n\n /**\n * Maximum number of embeddings that can be generated in a single API call.\n * Set to 2048 as a reasonable default for most embedding models.\n */\n readonly maxEmbeddingsPerCall = 2048;\n\n /**\n * Whether the model supports parallel calls.\n */\n readonly supportsParallelCalls = true;\n\n constructor(modelId: string, settings: OpenRouterModelSettings) {\n this.modelId = modelId;\n this.settings = settings;\n }\n\n async doEmbed(options: EmbeddingModelV3CallOptions): Promise<EmbeddingModelV3Result> {\n const warnings: SharedV3Warning[] = [];\n\n // Create OpenRouter client\n const client = new OpenRouter({\n apiKey: this.settings.apiKey,\n serverURL: this.settings.baseURL,\n userAgent: this.settings.userAgent,\n });\n\n // Build request with provider routing options if configured\n const requestParams: {\n model: string;\n input: string[];\n user?: string;\n provider?: { order?: string[]; allowFallbacks?: boolean; requireParameters?: boolean };\n } = {\n model: this.modelId,\n input: options.values,\n };\n\n // Add provider routing options from model settings\n const modelOptions = this.settings.modelOptions;\n if (modelOptions?.user) {\n requestParams.user = modelOptions.user as string;\n }\n if (modelOptions?.provider) {\n requestParams.provider = modelOptions.provider;\n }\n\n // Make the embeddings request\n const combinedHeaders = normalizeHeaders(\n combineHeaders(this.settings.headers, options.headers)\n );\n\n const response = await client.embeddings.generate(requestParams, {\n fetchOptions: {\n signal: options.abortSignal,\n headers: combinedHeaders,\n },\n });\n\n // Handle string response (shouldn't happen in practice but type allows it)\n if (typeof response === 'string') {\n throw new Error(`Unexpected string response from embeddings API: ${response}`);\n }\n\n const responseBody = response as CreateEmbeddingsResponseBody;\n\n // Extract embeddings from response data\n // Sort by index to ensure correct order, then extract embedding vectors\n const sortedData = [...responseBody.data].sort((a, b) => (a.index ?? 0) - (b.index ?? 0));\n const embeddings = sortedData.map((item) => {\n // Embedding can be number[] or base64 string - we only support number[]\n if (typeof item.embedding === 'string') {\n throw new Error('Base64 encoded embeddings are not supported');\n }\n return item.embedding;\n });\n\n return {\n embeddings,\n usage: responseBody.usage\n ? { tokens: responseBody.usage.promptTokens }\n : undefined,\n warnings,\n };\n }\n}\n","import type {\n ImageModelV3,\n ImageModelV3CallOptions,\n SharedV3Warning,\n} from '@ai-sdk/provider';\n\n/**\n * OpenRouter image model implementing AI SDK V3 ImageModelV3 interface.\n *\n * Note: Image generation is Tier 3 functionality. The doGenerate method\n * throws an error with guidance on tracking progress.\n */\nexport class OpenRouterImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3' as const;\n readonly provider = 'openrouter';\n readonly modelId: string;\n\n /**\n * Maximum number of images that can be generated in a single API call.\n */\n readonly maxImagesPerCall = 1;\n\n constructor(modelId: string, _settings: unknown) {\n this.modelId = modelId;\n }\n\n async doGenerate(_options: ImageModelV3CallOptions): Promise<{\n images: Array<string> | Array<Uint8Array>;\n warnings: Array<SharedV3Warning>;\n response: {\n timestamp: Date;\n modelId: string;\n headers: Record<string, string> | undefined;\n };\n }> {\n throw new Error(\n 'Image generation not yet supported. ' +\n 'See: https://github.com/OpenRouterTeam/ai-sdk-provider/issues/new?title=Image+generation+support'\n );\n }\n}\n","export const VERSION = '6.0.0-alpha.0';\n","export {\n createOpenRouter,\n type OpenRouterProvider,\n type OpenRouterModelSettings,\n} from './openrouter-provider.js';\nexport type {\n OpenRouterProviderSettings,\n OpenRouterModelOptions,\n OpenRouterPluginConfig,\n OpenRouterProviderRoutingConfig,\n} from './openrouter-config.js';\nexport { VERSION } from './version.js';\n\n// Default instance\nimport { createOpenRouter } from './openrouter-provider.js';\n\n/**\n * Default OpenRouter provider instance.\n *\n * Uses OPENROUTER_API_KEY environment variable for authentication.\n *\n * @example\n * ```ts\n * import { openrouter } from '@openrouter/ai-sdk-provider';\n *\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n * ```\n */\nexport const openrouter = createOpenRouter();\n"],"mappings":"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","names":["extractReasoningDetails","extractReasoningDetails","combineHeaders","normalizeHeaders","OpenRouter"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openrouter/ai-sdk-provider",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"test:e2e": "vitest --config vitest.e2e.config.ts --run",
|
|
25
25
|
"changeset": "changeset",
|
|
26
26
|
"changeset-version": "changeset version",
|
|
27
|
-
"changeset-publish": "bun run build && bun run test && changeset publish --provenance"
|
|
27
|
+
"changeset-publish": "bun run build && bun run test && changeset publish --provenance",
|
|
28
|
+
"bunp": "bun run scripts/bunp.ts"
|
|
28
29
|
},
|
|
29
30
|
"exports": {
|
|
30
31
|
"./package.json": "./package.json",
|