@yourgpt/llm-sdk 2.0.1 → 2.0.2-beta.2

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.
Files changed (55) hide show
  1. package/dist/adapters/index.d.mts +27 -4
  2. package/dist/adapters/index.d.ts +27 -4
  3. package/dist/adapters/index.js +395 -25
  4. package/dist/adapters/index.js.map +1 -1
  5. package/dist/adapters/index.mjs +395 -25
  6. package/dist/adapters/index.mjs.map +1 -1
  7. package/dist/index.d.mts +24 -5
  8. package/dist/index.d.ts +24 -5
  9. package/dist/index.js +20 -4
  10. package/dist/index.js.map +1 -1
  11. package/dist/index.mjs +20 -4
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/providers/anthropic/index.d.mts +1 -2
  14. package/dist/providers/anthropic/index.d.ts +1 -2
  15. package/dist/providers/anthropic/index.js +108 -12
  16. package/dist/providers/anthropic/index.js.map +1 -1
  17. package/dist/providers/anthropic/index.mjs +108 -12
  18. package/dist/providers/anthropic/index.mjs.map +1 -1
  19. package/dist/providers/azure/index.d.mts +1 -2
  20. package/dist/providers/azure/index.d.ts +1 -2
  21. package/dist/providers/azure/index.js.map +1 -1
  22. package/dist/providers/azure/index.mjs.map +1 -1
  23. package/dist/providers/google/index.d.mts +1 -2
  24. package/dist/providers/google/index.d.ts +1 -2
  25. package/dist/providers/google/index.js +61 -2
  26. package/dist/providers/google/index.js.map +1 -1
  27. package/dist/providers/google/index.mjs +61 -2
  28. package/dist/providers/google/index.mjs.map +1 -1
  29. package/dist/providers/ollama/index.d.mts +8 -3
  30. package/dist/providers/ollama/index.d.ts +8 -3
  31. package/dist/providers/ollama/index.js +227 -17
  32. package/dist/providers/ollama/index.js.map +1 -1
  33. package/dist/providers/ollama/index.mjs +227 -17
  34. package/dist/providers/ollama/index.mjs.map +1 -1
  35. package/dist/providers/openai/index.d.mts +1 -2
  36. package/dist/providers/openai/index.d.ts +1 -2
  37. package/dist/providers/openai/index.js +57 -3
  38. package/dist/providers/openai/index.js.map +1 -1
  39. package/dist/providers/openai/index.mjs +57 -3
  40. package/dist/providers/openai/index.mjs.map +1 -1
  41. package/dist/providers/openrouter/index.d.mts +56 -3
  42. package/dist/providers/openrouter/index.d.ts +56 -3
  43. package/dist/providers/openrouter/index.js +90 -276
  44. package/dist/providers/openrouter/index.js.map +1 -1
  45. package/dist/providers/openrouter/index.mjs +89 -277
  46. package/dist/providers/openrouter/index.mjs.map +1 -1
  47. package/dist/providers/xai/index.d.mts +1 -2
  48. package/dist/providers/xai/index.d.ts +1 -2
  49. package/dist/providers/xai/index.js.map +1 -1
  50. package/dist/providers/xai/index.mjs.map +1 -1
  51. package/dist/{base-DdxolpKP.d.mts → types-C_f95PKp.d.mts} +434 -3
  52. package/dist/{base-DdxolpKP.d.ts → types-C_f95PKp.d.ts} +434 -3
  53. package/package.json +1 -1
  54. package/dist/types-Ck25ZYma.d.mts +0 -323
  55. package/dist/types-Dsz8SpdB.d.ts +0 -323
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/providers/openrouter/provider.ts","../../../src/core/utils.ts","../../../src/adapters/base.ts","../../../src/adapters/openai.ts","../../../src/providers/types.ts","../../../src/providers/openrouter/index.ts"],"names":["client","OPENROUTER_MODELS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * OpenRouter Provider - Modern Pattern\n *\n * OpenRouter provides a unified API to access 500+ AI models from 60+ providers\n * (OpenAI, Anthropic, Google, Meta, Mistral, etc.) through a single endpoint.\n *\n * @example\n * ```ts\n * import { openrouter } from '@yourgpt/llm-sdk/openrouter';\n * import { generateText } from '@yourgpt/llm-sdk';\n *\n * const result = await generateText({\n * model: openrouter('anthropic/claude-3.5-sonnet'),\n * prompt: 'Hello!',\n * });\n * ```\n */\n\nimport type {\n LanguageModel,\n DoGenerateParams,\n DoGenerateResult,\n StreamChunk,\n ToolCall,\n FinishReason,\n CoreMessage,\n} from \"../../core/types\";\n\n// ============================================\n// Popular Models (subset - OpenRouter has 500+)\n// ============================================\n\ninterface OpenRouterModelConfig {\n vision: boolean;\n tools: boolean;\n jsonMode: boolean;\n maxTokens: number;\n}\n\n/**\n * Popular OpenRouter models with known capabilities.\n * OpenRouter supports 500+ models - any model ID will work,\n * but these have pre-configured capabilities.\n */\nconst OPENROUTER_MODELS: Record<string, OpenRouterModelConfig> = {\n // OpenAI\n \"openai/gpt-4o\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"openai/gpt-4o-mini\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"openai/gpt-4-turbo\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"openai/o1\": {\n vision: true,\n tools: false,\n jsonMode: false,\n maxTokens: 128000,\n },\n \"openai/o1-mini\": {\n vision: true,\n tools: false,\n jsonMode: false,\n maxTokens: 128000,\n },\n\n // Anthropic\n \"anthropic/claude-3.5-sonnet\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3.5-sonnet-20241022\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3-opus\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3-sonnet\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3-haiku\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n\n // Google\n \"google/gemini-pro-1.5\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 1000000,\n },\n \"google/gemini-flash-1.5\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 1000000,\n },\n \"google/gemini-2.0-flash-exp\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 1000000,\n },\n\n // Meta Llama\n \"meta-llama/llama-3.1-405b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n \"meta-llama/llama-3.1-70b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n \"meta-llama/llama-3.1-8b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n \"meta-llama/llama-3.2-90b-vision-instruct\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n\n // Mistral\n \"mistralai/mistral-large\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"mistralai/mixtral-8x7b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 32768,\n },\n \"mistralai/mistral-nemo\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n\n // DeepSeek\n \"deepseek/deepseek-chat\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 64000,\n },\n \"deepseek/deepseek-coder\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 64000,\n },\n\n // Qwen\n \"qwen/qwen-2.5-72b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n \"qwen/qwen-2-vl-72b-instruct\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 32768,\n },\n\n // OpenRouter Auto (magic model)\n \"openrouter/auto\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n};\n\n// Default config for unknown models\nconst DEFAULT_MODEL_CONFIG: OpenRouterModelConfig = {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n};\n\n// ============================================\n// Provider Options\n// ============================================\n\nexport interface OpenRouterProviderOptions {\n /** API key (defaults to OPENROUTER_API_KEY env var) */\n apiKey?: string;\n /** Base URL for API (defaults to https://openrouter.ai/api/v1) */\n baseURL?: string;\n /** Your site URL for OpenRouter rankings (HTTP-Referer header) */\n siteUrl?: string;\n /** Your app name for OpenRouter rankings (X-Title header) */\n appName?: string;\n /** Provider preferences for routing */\n providerPreferences?: {\n /** Preferred providers (e.g., ['anthropic', 'openai']) */\n allow?: string[];\n /** Blocked providers */\n deny?: string[];\n /** Order preference: 'price' | 'latency' | 'throughput' */\n order?: \"price\" | \"latency\" | \"throughput\";\n };\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create an OpenRouter language model\n *\n * OpenRouter provides access to 500+ models through a single API.\n * Model IDs follow the format: provider/model-name\n *\n * @param modelId - Model ID (e.g., 'anthropic/claude-3.5-sonnet', 'openai/gpt-4o')\n * @param options - Provider options\n * @returns LanguageModel instance\n *\n * @example\n * ```ts\n * // Basic usage\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n *\n * // With custom options\n * const model = openrouter('openai/gpt-4o', {\n * apiKey: 'sk-or-...',\n * siteUrl: 'https://myapp.com',\n * appName: 'My App',\n * });\n *\n * // Use auto model selection\n * const model = openrouter('openrouter/auto');\n * ```\n */\nexport function openrouter(\n modelId: string,\n options: OpenRouterProviderOptions = {},\n): LanguageModel {\n const apiKey = options.apiKey ?? process.env.OPENROUTER_API_KEY;\n const baseURL = options.baseURL ?? \"https://openrouter.ai/api/v1\";\n\n // Build headers\n const headers: Record<string, string> = {};\n if (options.siteUrl) {\n headers[\"HTTP-Referer\"] = options.siteUrl;\n }\n if (options.appName) {\n headers[\"X-Title\"] = options.appName;\n }\n\n // Lazy-load OpenAI client (OpenRouter uses OpenAI-compatible API)\n let client: any = null;\n async function getClient(): Promise<any> {\n if (!client) {\n const { default: OpenAI } = await import(\"openai\");\n client = new OpenAI({\n apiKey,\n baseURL,\n defaultHeaders: headers,\n });\n }\n return client;\n }\n\n // Get model config (use default for unknown models)\n const modelConfig = OPENROUTER_MODELS[modelId] ?? DEFAULT_MODEL_CONFIG;\n\n return {\n provider: \"openrouter\",\n modelId,\n\n capabilities: {\n supportsVision: modelConfig.vision,\n supportsTools: modelConfig.tools,\n supportsStreaming: true,\n supportsJsonMode: modelConfig.jsonMode,\n supportsThinking: false,\n supportsPDF: false,\n maxTokens: modelConfig.maxTokens,\n supportedImageTypes: modelConfig.vision\n ? [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]\n : [],\n },\n\n async doGenerate(params: DoGenerateParams): Promise<DoGenerateResult> {\n const client = await getClient();\n\n const messages = formatMessagesForOpenRouter(params.messages);\n\n // Build request body\n const requestBody: any = {\n model: modelId,\n messages,\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n };\n\n // Add tools if provided\n if (params.tools) {\n requestBody.tools = params.tools;\n }\n\n // Add provider preferences if configured\n if (options.providerPreferences) {\n requestBody.provider = options.providerPreferences;\n }\n\n const response = await client.chat.completions.create(requestBody);\n\n const choice = response.choices[0];\n const message = choice.message;\n\n // Parse tool calls\n const toolCalls: ToolCall[] = (message.tool_calls ?? []).map(\n (tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n args: JSON.parse(tc.function.arguments || \"{}\"),\n }),\n );\n\n return {\n text: message.content ?? \"\",\n toolCalls,\n finishReason: mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: response.usage?.prompt_tokens ?? 0,\n completionTokens: response.usage?.completion_tokens ?? 0,\n totalTokens: response.usage?.total_tokens ?? 0,\n },\n rawResponse: response,\n };\n },\n\n async *doStream(params: DoGenerateParams): AsyncGenerator<StreamChunk> {\n const client = await getClient();\n\n const messages = formatMessagesForOpenRouter(params.messages);\n\n // Build request body\n const requestBody: any = {\n model: modelId,\n messages,\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n stream: true,\n };\n\n // Add tools if provided\n if (params.tools) {\n requestBody.tools = params.tools;\n }\n\n // Add provider preferences if configured\n if (options.providerPreferences) {\n requestBody.provider = options.providerPreferences;\n }\n\n const stream = await client.chat.completions.create(requestBody);\n\n // Track current tool call being built\n let currentToolCall: {\n id: string;\n name: string;\n arguments: string;\n } | null = null;\n\n let totalPromptTokens = 0;\n let totalCompletionTokens = 0;\n\n for await (const chunk of stream) {\n // Check abort\n if (params.signal?.aborted) {\n yield { type: \"error\", error: new Error(\"Aborted\") };\n return;\n }\n\n const choice = chunk.choices[0];\n const delta = choice?.delta;\n\n // Text content\n if (delta?.content) {\n yield { type: \"text-delta\", text: delta.content };\n }\n\n // Tool calls\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls) {\n if (tc.id) {\n // New tool call - emit previous if exists\n if (currentToolCall) {\n yield {\n type: \"tool-call\",\n toolCall: {\n id: currentToolCall.id,\n name: currentToolCall.name,\n args: JSON.parse(currentToolCall.arguments || \"{}\"),\n },\n };\n }\n currentToolCall = {\n id: tc.id,\n name: tc.function?.name ?? \"\",\n arguments: tc.function?.arguments ?? \"\",\n };\n } else if (currentToolCall && tc.function?.arguments) {\n // Append arguments\n currentToolCall.arguments += tc.function.arguments;\n }\n }\n }\n\n // Finish reason\n if (choice?.finish_reason) {\n // Emit pending tool call\n if (currentToolCall) {\n yield {\n type: \"tool-call\",\n toolCall: {\n id: currentToolCall.id,\n name: currentToolCall.name,\n args: JSON.parse(currentToolCall.arguments || \"{}\"),\n },\n };\n currentToolCall = null;\n }\n\n // Usage from final chunk (if available)\n if (chunk.usage) {\n totalPromptTokens = chunk.usage.prompt_tokens;\n totalCompletionTokens = chunk.usage.completion_tokens;\n }\n\n yield {\n type: \"finish\",\n finishReason: mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: totalPromptTokens,\n completionTokens: totalCompletionTokens,\n totalTokens: totalPromptTokens + totalCompletionTokens,\n },\n };\n }\n }\n },\n };\n}\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Map OpenRouter finish reason to our FinishReason type\n */\nfunction mapFinishReason(reason: string | null): FinishReason {\n switch (reason) {\n case \"stop\":\n return \"stop\";\n case \"length\":\n return \"length\";\n case \"tool_calls\":\n case \"function_call\":\n return \"tool-calls\";\n case \"content_filter\":\n return \"content-filter\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Format CoreMessage[] for OpenRouter API (OpenAI-compatible)\n */\nfunction formatMessagesForOpenRouter(messages: CoreMessage[]): any[] {\n return messages.map((msg) => {\n switch (msg.role) {\n case \"system\":\n return { role: \"system\", content: msg.content };\n\n case \"user\":\n if (typeof msg.content === \"string\") {\n return { role: \"user\", content: msg.content };\n }\n // Handle multimodal content\n return {\n role: \"user\",\n content: msg.content.map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text };\n }\n if (part.type === \"image\") {\n const imageData =\n typeof part.image === \"string\"\n ? part.image\n : Buffer.from(part.image).toString(\"base64\");\n const url = imageData.startsWith(\"data:\")\n ? imageData\n : `data:${part.mimeType ?? \"image/png\"};base64,${imageData}`;\n return { type: \"image_url\", image_url: { url, detail: \"auto\" } };\n }\n return { type: \"text\", text: \"\" };\n }),\n };\n\n case \"assistant\":\n const assistantMsg: any = {\n role: \"assistant\",\n content: msg.content,\n };\n if (msg.toolCalls && msg.toolCalls.length > 0) {\n assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: JSON.stringify(tc.args),\n },\n }));\n }\n return assistantMsg;\n\n case \"tool\":\n return {\n role: \"tool\",\n tool_call_id: msg.toolCallId,\n content: msg.content,\n };\n\n default:\n return msg;\n }\n });\n}\n\n// Also export as createOpenRouter for backward compatibility\nexport { openrouter as createOpenRouter };\n","/**\n * Utility functions for llm-sdk\n */\n\n/**\n * Generate a unique ID with optional prefix\n */\nexport function generateId(prefix = \"id\"): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Generate a message ID\n */\nexport function generateMessageId(): string {\n return generateId(\"msg\");\n}\n\n/**\n * Generate a conversation/thread ID\n */\nexport function generateThreadId(): string {\n return generateId(\"thread\");\n}\n\n/**\n * Generate a tool call ID\n */\nexport function generateToolCallId(): string {\n return generateId(\"call\");\n}\n","import type {\n Message,\n MessageAttachment,\n ActionDefinition,\n StreamEvent,\n LLMConfig,\n} from \"../core/stream-events\";\nimport type { TokenUsage } from \"../core/types\";\n\n/**\n * Request-level LLM configuration overrides\n */\nexport interface RequestLLMConfig {\n model?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/**\n * Chat completion request\n */\nexport interface ChatCompletionRequest {\n /** Conversation messages */\n messages: Message[];\n /**\n * Raw provider-formatted messages (for agent loop with tool calls)\n * When provided, these are used instead of converting from Message[]\n * This allows passing messages with tool_calls and tool role\n */\n rawMessages?: Array<Record<string, unknown>>;\n /** Available actions/tools */\n actions?: ActionDefinition[];\n /** System prompt */\n systemPrompt?: string;\n /** LLM configuration overrides */\n config?: RequestLLMConfig;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n}\n\n/**\n * Non-streaming completion result\n */\nexport interface CompletionResult {\n /** Text content */\n content: string;\n /** Tool calls */\n toolCalls: Array<{ id: string; name: string; args: Record<string, unknown> }>;\n /** Thinking content (if extended thinking enabled) */\n thinking?: string;\n /** Token usage for billing/tracking */\n usage?: TokenUsage;\n /** Raw provider response for debugging */\n rawResponse: Record<string, unknown>;\n}\n\n/**\n * Base LLM adapter interface\n */\nexport interface LLMAdapter {\n /** Provider name */\n readonly provider: string;\n\n /** Model name */\n readonly model: string;\n\n /**\n * Stream a chat completion\n */\n stream(request: ChatCompletionRequest): AsyncGenerator<StreamEvent>;\n\n /**\n * Non-streaming chat completion (for debugging/comparison)\n */\n complete?(request: ChatCompletionRequest): Promise<CompletionResult>;\n}\n\n/**\n * Adapter factory function type\n */\nexport type AdapterFactory = (config: LLMConfig) => LLMAdapter;\n\n/**\n * Convert messages to provider format (simple text only)\n */\nexport function formatMessages(\n messages: Message[],\n systemPrompt?: string,\n): Array<{ role: string; content: string }> {\n const formatted: Array<{ role: string; content: string }> = [];\n\n // Add system prompt if provided\n if (systemPrompt) {\n formatted.push({ role: \"system\", content: systemPrompt });\n }\n\n // Add conversation messages\n for (const msg of messages) {\n formatted.push({\n role: msg.role,\n content: msg.content ?? \"\",\n });\n }\n\n return formatted;\n}\n\n/**\n * Convert ActionParameter to JSON Schema format recursively\n */\nfunction parameterToJsonSchema(param: {\n type: string;\n description?: string;\n enum?: string[];\n items?: unknown;\n properties?: Record<string, unknown>;\n}): Record<string, unknown> {\n const schema: Record<string, unknown> = {\n type: param.type,\n };\n\n if (param.description) {\n schema.description = param.description;\n }\n\n if (param.enum) {\n schema.enum = param.enum;\n }\n\n // Handle array items\n if (param.type === \"array\" && param.items) {\n schema.items = parameterToJsonSchema(\n param.items as {\n type: string;\n description?: string;\n enum?: string[];\n items?: unknown;\n properties?: Record<string, unknown>;\n },\n );\n }\n\n // Handle nested object properties\n if (param.type === \"object\" && param.properties) {\n schema.properties = Object.fromEntries(\n Object.entries(param.properties).map(([key, prop]) => [\n key,\n parameterToJsonSchema(\n prop as {\n type: string;\n description?: string;\n enum?: string[];\n items?: unknown;\n properties?: Record<string, unknown>;\n },\n ),\n ]),\n );\n }\n\n return schema;\n}\n\n/**\n * Convert actions to OpenAI tool format\n */\nexport function formatTools(actions: ActionDefinition[]): Array<{\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: object;\n };\n}> {\n return actions.map((action) => ({\n type: \"function\" as const,\n function: {\n name: action.name,\n description: action.description,\n parameters: {\n type: \"object\",\n properties: action.parameters\n ? Object.fromEntries(\n Object.entries(action.parameters).map(([key, param]) => [\n key,\n parameterToJsonSchema(param),\n ]),\n )\n : {},\n required: action.parameters\n ? Object.entries(action.parameters)\n .filter(([, param]) => param.required)\n .map(([key]) => key)\n : [],\n },\n },\n }));\n}\n\n// ============================================\n// Vision/Multimodal Support\n// ============================================\n\n/**\n * Content block types for multimodal messages\n */\nexport type AnthropicContentBlock =\n | { type: \"text\"; text: string }\n | {\n type: \"image\";\n source:\n | {\n type: \"base64\";\n media_type: string;\n data: string;\n }\n | {\n type: \"url\";\n url: string;\n };\n }\n | {\n type: \"document\";\n source:\n | {\n type: \"base64\";\n media_type: string;\n data: string;\n }\n | {\n type: \"url\";\n url: string;\n };\n };\n\nexport type OpenAIContentBlock =\n | { type: \"text\"; text: string }\n | {\n type: \"image_url\";\n image_url: {\n url: string;\n detail?: \"low\" | \"high\" | \"auto\";\n };\n };\n\n/**\n * Check if a message has image attachments\n * Supports both new format (metadata.attachments) and legacy (attachments)\n */\nexport function hasImageAttachments(message: Message): boolean {\n const attachments = message.metadata?.attachments;\n return attachments?.some((a) => a.type === \"image\") ?? false;\n}\n\n/**\n * Check if a message has media attachments (images or PDFs)\n */\nexport function hasMediaAttachments(message: Message): boolean {\n const attachments = message.metadata?.attachments;\n return (\n attachments?.some(\n (a) =>\n a.type === \"image\" ||\n (a.type === \"file\" && a.mimeType === \"application/pdf\"),\n ) ?? false\n );\n}\n\n/**\n * Convert MessageAttachment to Anthropic image content block\n *\n * Anthropic format:\n * {\n * type: \"image\",\n * source: {\n * type: \"base64\",\n * media_type: \"image/png\",\n * data: \"base64data...\"\n * }\n * }\n */\nexport function attachmentToAnthropicImage(\n attachment: MessageAttachment,\n): AnthropicContentBlock | null {\n if (attachment.type !== \"image\") return null;\n\n // Use URL if available (cloud storage)\n if (attachment.url) {\n return {\n type: \"image\",\n source: {\n type: \"url\",\n url: attachment.url,\n },\n };\n }\n\n // Fall back to base64 data\n if (!attachment.data) return null;\n\n // Extract base64 data (remove data URI prefix if present)\n let base64Data = attachment.data;\n if (base64Data.startsWith(\"data:\")) {\n const commaIndex = base64Data.indexOf(\",\");\n if (commaIndex !== -1) {\n base64Data = base64Data.slice(commaIndex + 1);\n }\n }\n\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: attachment.mimeType || \"image/png\",\n data: base64Data,\n },\n };\n}\n\n/**\n * Convert MessageAttachment to OpenAI image_url content block\n *\n * OpenAI format:\n * {\n * type: \"image_url\",\n * image_url: {\n * url: \"data:image/png;base64,...\"\n * }\n * }\n */\nexport function attachmentToOpenAIImage(\n attachment: MessageAttachment,\n): OpenAIContentBlock | null {\n if (attachment.type !== \"image\") return null;\n\n let imageUrl: string;\n\n // Use URL if available (cloud storage)\n if (attachment.url) {\n imageUrl = attachment.url;\n } else if (attachment.data) {\n // Build data URI if not already one\n imageUrl = attachment.data.startsWith(\"data:\")\n ? attachment.data\n : `data:${attachment.mimeType || \"image/png\"};base64,${attachment.data}`;\n } else {\n return null;\n }\n\n return {\n type: \"image_url\",\n image_url: {\n url: imageUrl,\n detail: \"auto\",\n },\n };\n}\n\n/**\n * Convert MessageAttachment (PDF) to Anthropic document content block\n *\n * Anthropic format:\n * {\n * type: \"document\",\n * source: {\n * type: \"base64\",\n * media_type: \"application/pdf\",\n * data: \"base64data...\"\n * }\n * }\n */\nexport function attachmentToAnthropicDocument(\n attachment: MessageAttachment,\n): AnthropicContentBlock | null {\n // Only handle PDF files\n if (attachment.type !== \"file\" || attachment.mimeType !== \"application/pdf\") {\n return null;\n }\n\n // Use URL if available (cloud storage)\n if (attachment.url) {\n return {\n type: \"document\",\n source: {\n type: \"url\",\n url: attachment.url,\n },\n };\n }\n\n // Fall back to base64 data\n if (!attachment.data) return null;\n\n // Extract base64 data (remove data URI prefix if present)\n let base64Data = attachment.data;\n if (base64Data.startsWith(\"data:\")) {\n const commaIndex = base64Data.indexOf(\",\");\n if (commaIndex !== -1) {\n base64Data = base64Data.slice(commaIndex + 1);\n }\n }\n\n return {\n type: \"document\",\n source: {\n type: \"base64\",\n media_type: \"application/pdf\",\n data: base64Data,\n },\n };\n}\n\n/**\n * Convert a Message to Anthropic multimodal content blocks\n */\nexport function messageToAnthropicContent(\n message: Message,\n): string | AnthropicContentBlock[] {\n const attachments = message.metadata?.attachments;\n const content = message.content ?? \"\";\n\n // If no media attachments (images or PDFs), return simple string\n if (!hasMediaAttachments(message)) {\n return content;\n }\n\n // Build content blocks array\n const blocks: AnthropicContentBlock[] = [];\n\n // Add media attachments first (Claude recommends media before text)\n if (attachments) {\n for (const attachment of attachments) {\n // Try image first\n const imageBlock = attachmentToAnthropicImage(attachment);\n if (imageBlock) {\n blocks.push(imageBlock);\n continue;\n }\n // Try document (PDF)\n const docBlock = attachmentToAnthropicDocument(attachment);\n if (docBlock) {\n blocks.push(docBlock);\n }\n }\n }\n\n // Add text content\n if (content) {\n blocks.push({ type: \"text\", text: content });\n }\n\n return blocks;\n}\n\n/**\n * Convert a Message to OpenAI multimodal content blocks\n */\nexport function messageToOpenAIContent(\n message: Message,\n): string | OpenAIContentBlock[] {\n const attachments = message.metadata?.attachments;\n const content = message.content ?? \"\";\n\n // If no image attachments, return simple string\n if (!hasImageAttachments(message)) {\n return content;\n }\n\n // Build content blocks array\n const blocks: OpenAIContentBlock[] = [];\n\n // Add text content first\n if (content) {\n blocks.push({ type: \"text\", text: content });\n }\n\n // Add image attachments\n if (attachments) {\n for (const attachment of attachments) {\n const imageBlock = attachmentToOpenAIImage(attachment);\n if (imageBlock) {\n blocks.push(imageBlock);\n }\n }\n }\n\n return blocks;\n}\n\n/**\n * Anthropic content block types (extended for tools)\n */\nexport type AnthropicToolUseBlock = {\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, unknown>;\n};\n\nexport type AnthropicToolResultBlock = {\n type: \"tool_result\";\n tool_use_id: string;\n content: string;\n};\n\nexport type AnthropicMessageContent =\n | string\n | Array<\n AnthropicContentBlock | AnthropicToolUseBlock | AnthropicToolResultBlock\n >;\n\n/**\n * Format messages for Anthropic with full tool support\n * Handles: text, images, tool_use, and tool_result\n *\n * Key differences from OpenAI:\n * - tool_calls become tool_use blocks in assistant content\n * - tool results become tool_result blocks in user content\n */\nexport function formatMessagesForAnthropic(\n messages: Message[],\n systemPrompt?: string,\n): {\n system: string;\n messages: Array<{\n role: \"user\" | \"assistant\";\n content: AnthropicMessageContent;\n }>;\n} {\n const formatted: Array<{\n role: \"user\" | \"assistant\";\n content: AnthropicMessageContent;\n }> = [];\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n\n if (msg.role === \"system\") continue; // System handled separately\n\n if (msg.role === \"assistant\") {\n // Build content array for assistant\n const content: Array<AnthropicContentBlock | AnthropicToolUseBlock> = [];\n\n // Add text content if present\n if (msg.content) {\n content.push({ type: \"text\", text: msg.content });\n }\n\n // Convert tool_calls to tool_use blocks\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n for (const tc of msg.tool_calls) {\n content.push({\n type: \"tool_use\",\n id: tc.id,\n name: tc.function.name,\n input: JSON.parse(tc.function.arguments),\n });\n }\n }\n\n formatted.push({\n role: \"assistant\",\n content:\n content.length === 1 && content[0].type === \"text\"\n ? (content[0] as { type: \"text\"; text: string }).text\n : content,\n });\n } else if (msg.role === \"tool\" && msg.tool_call_id) {\n // Tool results go in user message as tool_result blocks\n // Group consecutive tool messages together\n const toolResults: AnthropicToolResultBlock[] = [\n {\n type: \"tool_result\",\n tool_use_id: msg.tool_call_id,\n content: msg.content ?? \"\",\n },\n ];\n\n // Look ahead for more consecutive tool messages\n while (i + 1 < messages.length && messages[i + 1].role === \"tool\") {\n i++;\n const nextTool = messages[i];\n if (nextTool.tool_call_id) {\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: nextTool.tool_call_id,\n content: nextTool.content ?? \"\",\n });\n }\n }\n\n formatted.push({\n role: \"user\",\n content: toolResults,\n });\n } else if (msg.role === \"user\") {\n formatted.push({\n role: \"user\",\n content: messageToAnthropicContent(msg),\n });\n }\n }\n\n return {\n system: systemPrompt || \"\",\n messages: formatted,\n };\n}\n\n/**\n * OpenAI message format with tool support\n */\nexport type OpenAIMessage =\n | { role: \"system\"; content: string }\n | { role: \"user\"; content: string | OpenAIContentBlock[] }\n | {\n role: \"assistant\";\n content: string | null;\n tool_calls?: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }>;\n }\n | { role: \"tool\"; content: string; tool_call_id: string };\n\n/**\n * Format messages for OpenAI with full tool support\n * Handles: text, images, tool_calls, and tool results\n */\nexport function formatMessagesForOpenAI(\n messages: Message[],\n systemPrompt?: string,\n): OpenAIMessage[] {\n const formatted: OpenAIMessage[] = [];\n\n // Add system prompt if provided\n if (systemPrompt) {\n formatted.push({ role: \"system\", content: systemPrompt });\n }\n\n for (const msg of messages) {\n if (msg.role === \"system\") {\n formatted.push({ role: \"system\", content: msg.content ?? \"\" });\n } else if (msg.role === \"user\") {\n formatted.push({\n role: \"user\",\n content: messageToOpenAIContent(msg),\n });\n } else if (msg.role === \"assistant\") {\n const assistantMsg: OpenAIMessage = {\n role: \"assistant\",\n content: msg.content,\n };\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n (assistantMsg as { tool_calls: typeof msg.tool_calls }).tool_calls =\n msg.tool_calls;\n }\n formatted.push(assistantMsg);\n } else if (msg.role === \"tool\" && msg.tool_call_id) {\n formatted.push({\n role: \"tool\",\n content: msg.content ?? \"\",\n tool_call_id: msg.tool_call_id,\n });\n }\n }\n\n return formatted;\n}\n","import type { LLMConfig, StreamEvent } from \"../core/stream-events\";\nimport { generateMessageId, generateToolCallId } from \"../core/utils\";\nimport type { LLMAdapter, ChatCompletionRequest } from \"./base\";\nimport { formatMessagesForOpenAI, formatTools } from \"./base\";\n\n/**\n * OpenAI adapter configuration\n */\nexport interface OpenAIAdapterConfig {\n apiKey: string;\n model?: string;\n baseUrl?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/**\n * OpenAI LLM Adapter\n *\n * Supports: GPT-4, GPT-4o, GPT-3.5-turbo, etc.\n */\nexport class OpenAIAdapter implements LLMAdapter {\n readonly provider = \"openai\";\n readonly model: string;\n\n private client: any; // OpenAI client (lazy loaded)\n private config: OpenAIAdapterConfig;\n\n constructor(config: OpenAIAdapterConfig) {\n this.config = config;\n this.model = config.model || \"gpt-4o\";\n }\n\n private async getClient() {\n if (!this.client) {\n // Dynamic import to make openai optional\n const { default: OpenAI } = await import(\"openai\");\n this.client = new OpenAI({\n apiKey: this.config.apiKey,\n baseURL: this.config.baseUrl,\n });\n }\n return this.client;\n }\n\n async *stream(request: ChatCompletionRequest): AsyncGenerator<StreamEvent> {\n const client = await this.getClient();\n\n // Use raw messages if provided (for agent loop with tool calls), otherwise format from Message[]\n let messages: Array<Record<string, unknown>>;\n if (request.rawMessages && request.rawMessages.length > 0) {\n // Process raw messages - convert any attachments to OpenAI vision format\n const processedMessages = request.rawMessages.map((msg) => {\n // Check if message has attachments (images)\n const hasAttachments =\n msg.attachments &&\n Array.isArray(msg.attachments) &&\n msg.attachments.length > 0;\n\n if (hasAttachments) {\n // Convert to OpenAI multimodal content format\n const content: Array<Record<string, unknown>> = [];\n\n // Add text content if present\n if (msg.content) {\n content.push({ type: \"text\", text: msg.content });\n }\n\n // Add image attachments\n for (const attachment of msg.attachments as Array<{\n type: string;\n data?: string;\n url?: string;\n mimeType?: string;\n }>) {\n if (attachment.type === \"image\") {\n let imageUrl: string;\n\n if (attachment.url) {\n // Use URL directly (cloud storage)\n imageUrl = attachment.url;\n } else if (attachment.data) {\n // Use base64 data\n imageUrl = attachment.data.startsWith(\"data:\")\n ? attachment.data\n : `data:${attachment.mimeType || \"image/png\"};base64,${attachment.data}`;\n } else {\n continue; // Skip if no data or URL\n }\n\n content.push({\n type: \"image_url\",\n image_url: { url: imageUrl, detail: \"auto\" },\n });\n }\n }\n\n return { ...msg, content, attachments: undefined };\n }\n return msg;\n });\n\n // Add system prompt at the start if provided and not already present\n if (request.systemPrompt) {\n const hasSystem = processedMessages.some((m) => m.role === \"system\");\n if (!hasSystem) {\n messages = [\n { role: \"system\", content: request.systemPrompt },\n ...processedMessages,\n ];\n } else {\n messages = processedMessages;\n }\n } else {\n messages = processedMessages;\n }\n } else {\n // Format from Message[] with multimodal support (images, attachments)\n messages = formatMessagesForOpenAI(\n request.messages,\n request.systemPrompt,\n ) as Array<Record<string, unknown>>;\n }\n\n const tools = request.actions?.length\n ? formatTools(request.actions)\n : undefined;\n\n const messageId = generateMessageId();\n\n // Emit message start\n yield { type: \"message:start\", id: messageId };\n\n try {\n const stream = await client.chat.completions.create({\n model: request.config?.model || this.model,\n messages,\n tools,\n temperature: request.config?.temperature ?? this.config.temperature,\n max_tokens: request.config?.maxTokens ?? this.config.maxTokens,\n stream: true,\n stream_options: { include_usage: true },\n });\n\n let currentToolCall: {\n id: string;\n name: string;\n arguments: string;\n } | null = null;\n\n let usage:\n | {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n }\n | undefined;\n\n for await (const chunk of stream) {\n // Check for abort\n if (request.signal?.aborted) {\n break;\n }\n\n const delta = chunk.choices[0]?.delta;\n\n // Handle content\n if (delta?.content) {\n yield { type: \"message:delta\", content: delta.content };\n }\n\n // Handle tool calls\n if (delta?.tool_calls) {\n for (const toolCall of delta.tool_calls) {\n // New tool call\n if (toolCall.id) {\n // End previous tool call if any\n if (currentToolCall) {\n yield {\n type: \"action:args\",\n id: currentToolCall.id,\n args: currentToolCall.arguments,\n };\n }\n\n currentToolCall = {\n id: toolCall.id,\n name: toolCall.function?.name || \"\",\n arguments: toolCall.function?.arguments || \"\",\n };\n\n yield {\n type: \"action:start\",\n id: currentToolCall.id,\n name: currentToolCall.name,\n };\n } else if (currentToolCall && toolCall.function?.arguments) {\n // Append to current tool call arguments\n currentToolCall.arguments += toolCall.function.arguments;\n }\n }\n }\n\n // Capture usage from final chunk (OpenAI sends it with stream_options.include_usage)\n if (chunk.usage) {\n usage = {\n prompt_tokens: chunk.usage.prompt_tokens,\n completion_tokens: chunk.usage.completion_tokens,\n total_tokens: chunk.usage.total_tokens,\n };\n }\n\n // Check for finish\n if (chunk.choices[0]?.finish_reason) {\n // Complete any pending tool call\n if (currentToolCall) {\n yield {\n type: \"action:args\",\n id: currentToolCall.id,\n args: currentToolCall.arguments,\n };\n }\n }\n }\n\n // Emit message end\n yield { type: \"message:end\" };\n yield { type: \"done\", usage };\n } catch (error) {\n yield {\n type: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n code: \"OPENAI_ERROR\",\n };\n }\n }\n}\n\n/**\n * Create OpenAI adapter\n */\nexport function createOpenAIAdapter(\n config: OpenAIAdapterConfig,\n): OpenAIAdapter {\n return new OpenAIAdapter(config);\n}\n","/**\n * Provider Types\n *\n * Defines interfaces for:\n * 1. Provider Formatters (for tool transformations in agent loop)\n * 2. Multi-provider architecture (AIProvider, capabilities, configs)\n */\n\nimport type {\n ToolDefinition,\n UnifiedToolCall,\n UnifiedToolResult,\n} from \"../core/stream-events\";\nimport type { LLMAdapter } from \"../adapters/base\";\n\n// ============================================\n// Provider Formatter Types (for agent loop)\n// ============================================\n\n/**\n * Provider formatter interface\n *\n * Each provider implements this interface to handle:\n * - Tool definition transformation\n * - Tool call parsing from responses\n * - Tool result formatting\n * - Stop reason detection\n */\nexport interface ProviderFormatter {\n /**\n * Transform unified tool definitions to provider format\n */\n transformTools(tools: ToolDefinition[]): unknown[];\n\n /**\n * Parse tool calls from provider response\n */\n parseToolCalls(response: unknown): UnifiedToolCall[];\n\n /**\n * Format tool results for provider\n */\n formatToolResults(results: UnifiedToolResult[]): unknown[];\n\n /**\n * Check if response indicates tool use is requested\n */\n isToolUseStop(response: unknown): boolean;\n\n /**\n * Check if response indicates end of turn\n */\n isEndTurnStop(response: unknown): boolean;\n\n /**\n * Get stop reason string from response\n */\n getStopReason(response: unknown): string;\n\n /**\n * Extract text content from response\n */\n extractTextContent(response: unknown): string;\n\n /**\n * Build assistant message with tool calls for conversation history\n */\n buildAssistantToolMessage(\n toolCalls: UnifiedToolCall[],\n textContent?: string,\n ): unknown;\n\n /**\n * Build user message with tool results for conversation history\n */\n buildToolResultMessage(results: UnifiedToolResult[]): unknown;\n}\n\n// ============================================\n// Anthropic Tool Types\n// ============================================\n\n/**\n * Anthropic tool definition format\n */\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\n/**\n * Anthropic tool_use block from response\n */\nexport interface AnthropicToolUse {\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\n/**\n * Anthropic tool_result block\n */\nexport interface AnthropicToolResult {\n type: \"tool_result\";\n tool_use_id: string;\n content: string;\n}\n\n// ============================================\n// OpenAI Tool Types\n// ============================================\n\n/**\n * OpenAI tool definition format\n */\nexport interface OpenAITool {\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n };\n}\n\n/**\n * OpenAI tool call from response\n */\nexport interface OpenAIToolCall {\n id: string;\n type: \"function\";\n function: {\n name: string;\n arguments: string; // JSON string\n };\n}\n\n/**\n * OpenAI tool result message\n */\nexport interface OpenAIToolResult {\n role: \"tool\";\n tool_call_id: string;\n content: string;\n}\n\n// ============================================\n// Gemini Tool Types\n// ============================================\n\n/**\n * Google Gemini function declaration\n */\nexport interface GeminiFunctionDeclaration {\n name: string;\n description: string;\n parameters?: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\n/**\n * Gemini function call from response\n */\nexport interface GeminiFunctionCall {\n name: string;\n args: Record<string, unknown>;\n}\n\n/**\n * Gemini function response\n */\nexport interface GeminiFunctionResponse {\n name: string;\n response: Record<string, unknown>;\n}\n\n// ============================================\n// Provider Capabilities (for UI feature flags)\n// ============================================\n\n/**\n * Capabilities of a model for UI feature flags\n * UI components can use this to enable/disable features\n */\nexport interface ProviderCapabilities {\n /** Supports image inputs */\n supportsVision: boolean;\n /** Supports tool/function calling */\n supportsTools: boolean;\n /** Supports extended thinking (Claude, DeepSeek) */\n supportsThinking: boolean;\n /** Supports streaming responses */\n supportsStreaming: boolean;\n /** Supports PDF document inputs */\n supportsPDF: boolean;\n /** Supports audio inputs */\n supportsAudio: boolean;\n /** Supports video inputs */\n supportsVideo: boolean;\n /** Maximum context tokens */\n maxTokens: number;\n /** Supported image MIME types */\n supportedImageTypes: string[];\n /** Supported audio MIME types */\n supportedAudioTypes?: string[];\n /** Supported video MIME types */\n supportedVideoTypes?: string[];\n /** Supports JSON mode / structured output */\n supportsJsonMode?: boolean;\n /** Supports system messages */\n supportsSystemMessages?: boolean;\n}\n\n// ============================================\n// AI Provider Interface\n// ============================================\n\n/**\n * AI Provider interface (object form)\n *\n * Wraps existing LLMAdapter with additional metadata:\n * - Supported models list\n * - Per-model capabilities\n * - Provider name\n */\nexport interface AIProviderObject {\n /** Provider name (e.g., 'openai', 'anthropic') */\n readonly name: string;\n\n /** List of supported model IDs */\n readonly supportedModels: string[];\n\n /**\n * Get a language model adapter for the given model ID\n * Returns the existing LLMAdapter interface - no breaking changes\n */\n languageModel(modelId: string): LLMAdapter;\n\n /**\n * Get capabilities for a specific model\n * UI components use this to enable/disable features\n */\n getCapabilities(modelId: string): ProviderCapabilities;\n\n /**\n * Optional: Get an embedding model (future expansion)\n */\n embeddingModel?(modelId: string): EmbeddingModel;\n}\n\n/**\n * Callable AI Provider (Vercel AI SDK style)\n *\n * A function that returns a LanguageModel when called with a model ID,\n * but also has properties for provider metadata and methods.\n *\n * @example\n * ```typescript\n * const openai = createOpenAI({ apiKey: '...' });\n *\n * // Callable - returns LanguageModel directly (Vercel AI SDK style)\n * const model = openai('gpt-4o');\n *\n * // Also supports method calls (backward compatible)\n * const model2 = openai.languageModel('gpt-4o');\n *\n * // Check capabilities\n * const caps = openai.getCapabilities('gpt-4o');\n * if (caps.supportsVision) {\n * // Show image upload button\n * }\n * ```\n */\nexport interface AIProvider extends AIProviderObject {\n /**\n * Call the provider directly with a model ID to get a LanguageModel\n * This is the Vercel AI SDK style pattern\n */\n (modelId: string): LLMAdapter;\n}\n\n/**\n * Helper to create a callable AIProvider\n * Combines a callable function with AIProvider properties\n */\nexport function createCallableProvider(\n providerFn: (modelId: string) => LLMAdapter,\n properties: Omit<AIProviderObject, \"languageModel\">,\n): AIProvider {\n // Define 'name' property using defineProperty since it's read-only on functions\n Object.defineProperty(providerFn, \"name\", {\n value: properties.name,\n writable: false,\n configurable: true,\n });\n\n // Assign other properties\n Object.assign(providerFn, {\n supportedModels: properties.supportedModels,\n languageModel: providerFn,\n getCapabilities: properties.getCapabilities,\n embeddingModel: properties.embeddingModel,\n });\n\n return providerFn as AIProvider;\n}\n\n/**\n * Embedding model interface (for future expansion)\n */\nexport interface EmbeddingModel {\n readonly provider: string;\n readonly modelId: string;\n embed(texts: string[]): Promise<number[][]>;\n}\n\n// ============================================\n// Provider-Specific Configurations\n// ============================================\n\n/**\n * Base provider configuration\n */\nexport interface BaseProviderConfig {\n /** API key (falls back to environment variable) */\n apiKey?: string;\n /** Custom base URL */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Custom headers to include */\n headers?: Record<string, string>;\n}\n\n/**\n * OpenAI provider configuration\n */\nexport interface OpenAIProviderConfig extends BaseProviderConfig {\n /** OpenAI organization ID */\n organization?: string;\n /** OpenAI project ID */\n project?: string;\n /** Vision detail level for images */\n imageDetail?: \"auto\" | \"low\" | \"high\";\n}\n\n/**\n * Anthropic provider configuration\n */\nexport interface AnthropicProviderConfig extends BaseProviderConfig {\n /** Extended thinking budget in tokens (minimum 1024) */\n thinkingBudget?: number;\n /** Enable prompt caching */\n cacheControl?: boolean;\n}\n\n/**\n * Google provider configuration\n */\nexport interface GoogleProviderConfig extends BaseProviderConfig {\n /** Safety settings */\n safetySettings?: GoogleSafetySetting[];\n /** Grounding configuration (for web search) */\n groundingConfig?: GoogleGroundingConfig;\n}\n\n/**\n * Google safety setting\n */\nexport interface GoogleSafetySetting {\n category:\n | \"HARM_CATEGORY_HARASSMENT\"\n | \"HARM_CATEGORY_HATE_SPEECH\"\n | \"HARM_CATEGORY_SEXUALLY_EXPLICIT\"\n | \"HARM_CATEGORY_DANGEROUS_CONTENT\";\n threshold:\n | \"BLOCK_NONE\"\n | \"BLOCK_LOW_AND_ABOVE\"\n | \"BLOCK_MEDIUM_AND_ABOVE\"\n | \"BLOCK_HIGH_AND_ABOVE\";\n}\n\n/**\n * Google grounding configuration\n */\nexport interface GoogleGroundingConfig {\n /** Enable Google Search grounding */\n googleSearchRetrieval?: boolean;\n}\n\n/**\n * xAI provider configuration\n */\nexport interface XAIProviderConfig extends BaseProviderConfig {\n // xAI uses OpenAI-compatible API, no extra config needed\n}\n\n/**\n * Azure OpenAI provider configuration\n */\nexport interface AzureProviderConfig extends BaseProviderConfig {\n /** Azure resource name */\n resourceName: string;\n /** Deployment name */\n deploymentName: string;\n /** API version (default: 2024-02-15-preview) */\n apiVersion?: string;\n}\n\n/**\n * Ollama provider configuration\n */\nexport interface OllamaProviderConfig extends BaseProviderConfig {\n // baseUrl defaults to http://localhost:11434\n}\n\n// ============================================\n// Model Information\n// ============================================\n\n/**\n * Model information for a provider\n */\nexport interface ModelInfo {\n /** Model ID */\n id: string;\n /** Display name */\n name: string;\n /** Description */\n description?: string;\n /** Capabilities */\n capabilities: ProviderCapabilities;\n /** Context window size */\n contextWindow: number;\n /** Pricing info (optional) */\n pricing?: {\n inputPerMillion?: number;\n outputPerMillion?: number;\n };\n}\n\n// ============================================\n// Default Capabilities\n// ============================================\n\n/**\n * Default capabilities for unknown models\n */\nexport const DEFAULT_CAPABILITIES: ProviderCapabilities = {\n supportsVision: false,\n supportsTools: true,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: false,\n supportsAudio: false,\n supportsVideo: false,\n maxTokens: 8192,\n supportedImageTypes: [],\n supportsJsonMode: false,\n supportsSystemMessages: true,\n};\n","/**\n * OpenRouter Provider\n *\n * OpenRouter is a unified API gateway that provides access to 500+ AI models\n * from 60+ providers (OpenAI, Anthropic, Google, Meta, Mistral, etc.)\n * through a single endpoint.\n *\n * Features:\n * - Single API key for all models\n * - Automatic fallbacks and routing\n * - Cost optimization\n * - Provider preferences\n * - OpenAI-compatible API\n *\n * @see https://openrouter.ai/docs\n */\n\n// NEW: Modern pattern - openrouter() function\nexport {\n openrouter,\n createOpenRouter as createOpenRouterModel,\n} from \"./provider\";\nexport type { OpenRouterProviderOptions } from \"./provider\";\n\nimport { createOpenAIAdapter } from \"../../adapters/openai\";\nimport {\n createCallableProvider,\n type AIProvider,\n type ProviderCapabilities,\n} from \"../types\";\n\n// ============================================\n// Model Definitions\n// ============================================\n\ninterface ModelCapabilities {\n vision: boolean;\n tools: boolean;\n jsonMode: boolean;\n maxTokens: number;\n}\n\n/**\n * Popular OpenRouter models with known capabilities.\n * OpenRouter supports 500+ models - use any valid model ID.\n */\nconst OPENROUTER_MODELS: Record<string, ModelCapabilities> = {\n // OpenAI\n \"openai/gpt-4o\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"openai/gpt-4o-mini\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"openai/gpt-4-turbo\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"openai/o1\": {\n vision: true,\n tools: false,\n jsonMode: false,\n maxTokens: 128000,\n },\n\n // Anthropic\n \"anthropic/claude-3.5-sonnet\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3.5-sonnet-20241022\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3-opus\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n \"anthropic/claude-3-haiku\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 200000,\n },\n\n // Google\n \"google/gemini-pro-1.5\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 1000000,\n },\n \"google/gemini-flash-1.5\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 1000000,\n },\n\n // Meta Llama\n \"meta-llama/llama-3.1-405b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n \"meta-llama/llama-3.1-70b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 131072,\n },\n\n // Mistral\n \"mistralai/mistral-large\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n \"mistralai/mixtral-8x7b-instruct\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 32768,\n },\n\n // DeepSeek\n \"deepseek/deepseek-chat\": {\n vision: false,\n tools: true,\n jsonMode: true,\n maxTokens: 64000,\n },\n\n // OpenRouter Auto (magic model - picks best for your prompt)\n \"openrouter/auto\": {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n },\n};\n\n// Default for unknown models\nconst DEFAULT_CAPABILITIES: ModelCapabilities = {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n};\n\n// ============================================\n// Provider Config\n// ============================================\n\nexport interface OpenRouterProviderConfig {\n /** API key (defaults to OPENROUTER_API_KEY env var) */\n apiKey?: string;\n /** Base URL for API */\n baseUrl?: string;\n /** Your site URL for OpenRouter rankings */\n siteUrl?: string;\n /** Your app name for OpenRouter rankings */\n appName?: string;\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create an OpenRouter provider (callable, Vercel AI SDK style)\n *\n * @example\n * ```typescript\n * const or = createOpenRouter({ apiKey: '...' });\n *\n * // Callable - Vercel AI SDK style\n * const model = or('anthropic/claude-3.5-sonnet');\n *\n * // Also supports method call (backward compatible)\n * const model2 = or.languageModel('openai/gpt-4o');\n *\n * // Check capabilities\n * const caps = or.getCapabilities('anthropic/claude-3.5-sonnet');\n * ```\n */\nexport function createOpenRouter(\n config: OpenRouterProviderConfig = {},\n): AIProvider {\n const apiKey = config.apiKey ?? process.env.OPENROUTER_API_KEY ?? \"\";\n const baseUrl = config.baseUrl ?? \"https://openrouter.ai/api/v1\";\n\n // Create the callable function - uses OpenAI adapter since OpenRouter is OpenAI-compatible\n const providerFn = (modelId: string) => {\n return createOpenAIAdapter({\n apiKey,\n model: modelId,\n baseUrl,\n });\n };\n\n // Get capabilities helper\n const getCapabilities = (modelId: string): ProviderCapabilities => {\n const model = OPENROUTER_MODELS[modelId] ?? DEFAULT_CAPABILITIES;\n\n return {\n supportsVision: model.vision,\n supportsTools: model.tools,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: false,\n supportsAudio: false,\n supportsVideo: false,\n maxTokens: model.maxTokens,\n supportedImageTypes: model.vision\n ? [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]\n : [],\n supportsJsonMode: model.jsonMode,\n supportsSystemMessages: true,\n };\n };\n\n return createCallableProvider(providerFn, {\n name: \"openrouter\",\n supportedModels: Object.keys(OPENROUTER_MODELS),\n getCapabilities,\n });\n}\n\n// Alias for consistency\nexport const createOpenRouterProvider = createOpenRouter;\n"]}
1
+ {"version":3,"sources":["../../../src/providers/openrouter/provider.ts","../../../src/core/utils.ts","../../../src/adapters/base.ts","../../../src/adapters/openai.ts","../../../src/providers/types.ts","../../../src/providers/openrouter/index.ts"],"names":["client"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * OpenRouter Provider - Modern Pattern\n *\n * OpenRouter provides a unified API to access 500+ AI models from 60+ providers\n * (OpenAI, Anthropic, Google, Meta, Mistral, etc.) through a single endpoint.\n *\n * @example\n * ```ts\n * import { openrouter } from '@yourgpt/llm-sdk/openrouter';\n * import { generateText } from '@yourgpt/llm-sdk';\n *\n * const result = await generateText({\n * model: openrouter('anthropic/claude-3.5-sonnet'),\n * prompt: 'Hello!',\n * });\n * ```\n */\n\nimport type {\n LanguageModel,\n DoGenerateParams,\n DoGenerateResult,\n StreamChunk,\n ToolCall,\n FinishReason,\n CoreMessage,\n} from \"../../core/types\";\n\n// ============================================\n// Model Configuration\n// ============================================\n\n/**\n * OpenRouter supports 500+ models dynamically.\n * Use fetchOpenRouterModels() to get live model list with accurate capabilities.\n * This default config is used as fallback for all models.\n */\nconst DEFAULT_MODEL_CONFIG = {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n};\n\n// ============================================\n// Provider Options\n// ============================================\n\nexport interface OpenRouterProviderOptions {\n /** API key (defaults to OPENROUTER_API_KEY env var) */\n apiKey?: string;\n /** Base URL for API (defaults to https://openrouter.ai/api/v1) */\n baseURL?: string;\n /** Your site URL for OpenRouter rankings (HTTP-Referer header) */\n siteUrl?: string;\n /** Your app name for OpenRouter rankings (X-Title header) */\n appName?: string;\n /** Provider preferences for routing */\n providerPreferences?: {\n /** Preferred providers (e.g., ['anthropic', 'openai']) */\n allow?: string[];\n /** Blocked providers */\n deny?: string[];\n /** Order preference: 'price' | 'latency' | 'throughput' */\n order?: \"price\" | \"latency\" | \"throughput\";\n };\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create an OpenRouter language model\n *\n * OpenRouter provides access to 500+ models through a single API.\n * Model IDs follow the format: provider/model-name\n *\n * @param modelId - Model ID (e.g., 'anthropic/claude-3.5-sonnet', 'openai/gpt-4o')\n * @param options - Provider options\n * @returns LanguageModel instance\n *\n * @example\n * ```ts\n * // Basic usage\n * const model = openrouter('anthropic/claude-3.5-sonnet');\n *\n * // With custom options\n * const model = openrouter('openai/gpt-4o', {\n * apiKey: 'sk-or-...',\n * siteUrl: 'https://myapp.com',\n * appName: 'My App',\n * });\n *\n * // Use auto model selection\n * const model = openrouter('openrouter/auto');\n * ```\n */\nexport function openrouter(\n modelId: string,\n options: OpenRouterProviderOptions = {},\n): LanguageModel {\n const apiKey = options.apiKey ?? process.env.OPENROUTER_API_KEY;\n const baseURL = options.baseURL ?? \"https://openrouter.ai/api/v1\";\n\n // Build headers\n const headers: Record<string, string> = {};\n if (options.siteUrl) {\n headers[\"HTTP-Referer\"] = options.siteUrl;\n }\n if (options.appName) {\n headers[\"X-Title\"] = options.appName;\n }\n\n // Lazy-load OpenAI client (OpenRouter uses OpenAI-compatible API)\n let client: any = null;\n async function getClient(): Promise<any> {\n if (!client) {\n const { default: OpenAI } = await import(\"openai\");\n client = new OpenAI({\n apiKey,\n baseURL,\n defaultHeaders: headers,\n });\n }\n return client;\n }\n\n // Use default config for all models\n // Use fetchOpenRouterModels() to get accurate model-specific capabilities\n const modelConfig = DEFAULT_MODEL_CONFIG;\n\n return {\n provider: \"openrouter\",\n modelId,\n\n capabilities: {\n supportsVision: modelConfig.vision,\n supportsTools: modelConfig.tools,\n supportsStreaming: true,\n supportsJsonMode: modelConfig.jsonMode,\n supportsThinking: false,\n supportsPDF: false,\n maxTokens: modelConfig.maxTokens,\n supportedImageTypes: modelConfig.vision\n ? [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]\n : [],\n },\n\n async doGenerate(params: DoGenerateParams): Promise<DoGenerateResult> {\n const client = await getClient();\n\n const messages = formatMessagesForOpenRouter(params.messages);\n\n // Build request body\n const requestBody: any = {\n model: modelId,\n messages,\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n };\n\n // Add tools if provided\n if (params.tools) {\n requestBody.tools = params.tools;\n }\n\n // Add provider preferences if configured\n if (options.providerPreferences) {\n requestBody.provider = options.providerPreferences;\n }\n\n const response = await client.chat.completions.create(requestBody);\n\n const choice = response.choices[0];\n const message = choice.message;\n\n // Parse tool calls\n const toolCalls: ToolCall[] = (message.tool_calls ?? []).map(\n (tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n args: JSON.parse(tc.function.arguments || \"{}\"),\n }),\n );\n\n return {\n text: message.content ?? \"\",\n toolCalls,\n finishReason: mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: response.usage?.prompt_tokens ?? 0,\n completionTokens: response.usage?.completion_tokens ?? 0,\n totalTokens: response.usage?.total_tokens ?? 0,\n },\n rawResponse: response,\n };\n },\n\n async *doStream(params: DoGenerateParams): AsyncGenerator<StreamChunk> {\n const client = await getClient();\n\n const messages = formatMessagesForOpenRouter(params.messages);\n\n // Build request body\n const requestBody: any = {\n model: modelId,\n messages,\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n stream: true,\n };\n\n // Add tools if provided\n if (params.tools) {\n requestBody.tools = params.tools;\n }\n\n // Add provider preferences if configured\n if (options.providerPreferences) {\n requestBody.provider = options.providerPreferences;\n }\n\n const stream = await client.chat.completions.create(requestBody);\n\n // Track current tool call being built\n let currentToolCall: {\n id: string;\n name: string;\n arguments: string;\n } | null = null;\n\n let totalPromptTokens = 0;\n let totalCompletionTokens = 0;\n\n for await (const chunk of stream) {\n // Check abort\n if (params.signal?.aborted) {\n yield { type: \"error\", error: new Error(\"Aborted\") };\n return;\n }\n\n const choice = chunk.choices[0];\n const delta = choice?.delta;\n\n // Text content\n if (delta?.content) {\n yield { type: \"text-delta\", text: delta.content };\n }\n\n // Tool calls\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls) {\n if (tc.id) {\n // New tool call - emit previous if exists\n if (currentToolCall) {\n yield {\n type: \"tool-call\",\n toolCall: {\n id: currentToolCall.id,\n name: currentToolCall.name,\n args: JSON.parse(currentToolCall.arguments || \"{}\"),\n },\n };\n }\n currentToolCall = {\n id: tc.id,\n name: tc.function?.name ?? \"\",\n arguments: tc.function?.arguments ?? \"\",\n };\n } else if (currentToolCall && tc.function?.arguments) {\n // Append arguments\n currentToolCall.arguments += tc.function.arguments;\n }\n }\n }\n\n // Finish reason\n if (choice?.finish_reason) {\n // Emit pending tool call\n if (currentToolCall) {\n yield {\n type: \"tool-call\",\n toolCall: {\n id: currentToolCall.id,\n name: currentToolCall.name,\n args: JSON.parse(currentToolCall.arguments || \"{}\"),\n },\n };\n currentToolCall = null;\n }\n\n // Usage from final chunk (if available)\n if (chunk.usage) {\n totalPromptTokens = chunk.usage.prompt_tokens;\n totalCompletionTokens = chunk.usage.completion_tokens;\n }\n\n yield {\n type: \"finish\",\n finishReason: mapFinishReason(choice.finish_reason),\n usage: {\n promptTokens: totalPromptTokens,\n completionTokens: totalCompletionTokens,\n totalTokens: totalPromptTokens + totalCompletionTokens,\n },\n };\n }\n }\n },\n };\n}\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Map OpenRouter finish reason to our FinishReason type\n */\nfunction mapFinishReason(reason: string | null): FinishReason {\n switch (reason) {\n case \"stop\":\n return \"stop\";\n case \"length\":\n return \"length\";\n case \"tool_calls\":\n case \"function_call\":\n return \"tool-calls\";\n case \"content_filter\":\n return \"content-filter\";\n default:\n return \"unknown\";\n }\n}\n\n/**\n * Format CoreMessage[] for OpenRouter API (OpenAI-compatible)\n */\nfunction formatMessagesForOpenRouter(messages: CoreMessage[]): any[] {\n return messages.map((msg) => {\n switch (msg.role) {\n case \"system\":\n return { role: \"system\", content: msg.content };\n\n case \"user\":\n if (typeof msg.content === \"string\") {\n return { role: \"user\", content: msg.content };\n }\n // Handle multimodal content\n return {\n role: \"user\",\n content: msg.content.map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\", text: part.text };\n }\n if (part.type === \"image\") {\n const imageData =\n typeof part.image === \"string\"\n ? part.image\n : Buffer.from(part.image).toString(\"base64\");\n const url = imageData.startsWith(\"data:\")\n ? imageData\n : `data:${part.mimeType ?? \"image/png\"};base64,${imageData}`;\n return { type: \"image_url\", image_url: { url, detail: \"auto\" } };\n }\n return { type: \"text\", text: \"\" };\n }),\n };\n\n case \"assistant\":\n const assistantMsg: any = {\n role: \"assistant\",\n content: msg.content,\n };\n if (msg.toolCalls && msg.toolCalls.length > 0) {\n assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({\n id: tc.id,\n type: \"function\",\n function: {\n name: tc.name,\n arguments: JSON.stringify(tc.args),\n },\n }));\n }\n return assistantMsg;\n\n case \"tool\":\n return {\n role: \"tool\",\n tool_call_id: msg.toolCallId,\n content: msg.content,\n };\n\n default:\n return msg;\n }\n });\n}\n\n// ============================================\n// Models API - Fetch available models\n// ============================================\n\n/**\n * OpenRouter model information from the API\n */\nexport interface OpenRouterModel {\n id: string;\n name: string;\n description?: string;\n pricing: {\n prompt: string;\n completion: string;\n };\n context_length: number;\n architecture?: {\n modality?: string;\n tokenizer?: string;\n instruct_type?: string | null;\n };\n top_provider?: {\n context_length: number;\n max_completion_tokens: number;\n is_moderated: boolean;\n };\n per_request_limits?: {\n prompt_tokens?: string;\n completion_tokens?: string;\n };\n}\n\n/**\n * Fetch available models from OpenRouter API\n *\n * @param apiKey - Optional API key (not required for listing models)\n * @returns Array of available models\n *\n * @example\n * ```ts\n * const models = await fetchOpenRouterModels();\n * console.log(models.map(m => m.id));\n * ```\n */\nexport async function fetchOpenRouterModels(\n apiKey?: string,\n): Promise<OpenRouterModel[]> {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n\n if (apiKey) {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n\n const response = await fetch(\"https://openrouter.ai/api/v1/models\", {\n headers,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch models: ${response.statusText}`);\n }\n\n const data = (await response.json()) as { data?: OpenRouterModel[] };\n return data.data || [];\n}\n\n/**\n * Search OpenRouter models by name, ID, or provider\n *\n * @param query - Search query\n * @param apiKey - Optional API key\n * @returns Filtered models matching the query\n *\n * @example\n * ```ts\n * const claudeModels = await searchOpenRouterModels('claude');\n * const gptModels = await searchOpenRouterModels('gpt');\n * ```\n */\nexport async function searchOpenRouterModels(\n query: string,\n apiKey?: string,\n): Promise<OpenRouterModel[]> {\n const models = await fetchOpenRouterModels(apiKey);\n const lowerQuery = query.toLowerCase();\n\n return models.filter(\n (model) =>\n model.id.toLowerCase().includes(lowerQuery) ||\n model.name.toLowerCase().includes(lowerQuery),\n );\n}\n\n// Also export as createOpenRouter for backward compatibility\nexport { openrouter as createOpenRouter };\n","/**\n * Utility functions for llm-sdk\n */\n\n/**\n * Generate a unique ID with optional prefix\n */\nexport function generateId(prefix = \"id\"): string {\n return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Generate a message ID\n */\nexport function generateMessageId(): string {\n return generateId(\"msg\");\n}\n\n/**\n * Generate a conversation/thread ID\n */\nexport function generateThreadId(): string {\n return generateId(\"thread\");\n}\n\n/**\n * Generate a tool call ID\n */\nexport function generateToolCallId(): string {\n return generateId(\"call\");\n}\n","import type {\n Message,\n MessageAttachment,\n ActionDefinition,\n StreamEvent,\n LLMConfig,\n WebSearchConfig,\n} from \"../core/stream-events\";\nimport type { TokenUsage } from \"../core/types\";\n\n/**\n * Request-level LLM configuration overrides\n */\nexport interface RequestLLMConfig {\n model?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/**\n * Chat completion request\n */\nexport interface ChatCompletionRequest {\n /** Conversation messages */\n messages: Message[];\n /**\n * Raw provider-formatted messages (for agent loop with tool calls)\n * When provided, these are used instead of converting from Message[]\n * This allows passing messages with tool_calls and tool role\n */\n rawMessages?: Array<Record<string, unknown>>;\n /** Available actions/tools */\n actions?: ActionDefinition[];\n /** System prompt */\n systemPrompt?: string;\n /** LLM configuration overrides */\n config?: RequestLLMConfig;\n /** Abort signal for cancellation */\n signal?: AbortSignal;\n /**\n * Enable native web search for the provider.\n * When true or configured, the provider's native search is enabled.\n */\n webSearch?: boolean | WebSearchConfig;\n}\n\n/**\n * Non-streaming completion result\n */\nexport interface CompletionResult {\n /** Text content */\n content: string;\n /** Tool calls */\n toolCalls: Array<{ id: string; name: string; args: Record<string, unknown> }>;\n /** Thinking content (if extended thinking enabled) */\n thinking?: string;\n /** Token usage for billing/tracking */\n usage?: TokenUsage;\n /** Raw provider response for debugging */\n rawResponse: Record<string, unknown>;\n}\n\n/**\n * Base LLM adapter interface\n */\nexport interface LLMAdapter {\n /** Provider name */\n readonly provider: string;\n\n /** Model name */\n readonly model: string;\n\n /**\n * Stream a chat completion\n */\n stream(request: ChatCompletionRequest): AsyncGenerator<StreamEvent>;\n\n /**\n * Non-streaming chat completion (for debugging/comparison)\n */\n complete?(request: ChatCompletionRequest): Promise<CompletionResult>;\n}\n\n/**\n * Adapter factory function type\n */\nexport type AdapterFactory = (config: LLMConfig) => LLMAdapter;\n\n/**\n * Convert messages to provider format (simple text only)\n */\nexport function formatMessages(\n messages: Message[],\n systemPrompt?: string,\n): Array<{ role: string; content: string }> {\n const formatted: Array<{ role: string; content: string }> = [];\n\n // Add system prompt if provided\n if (systemPrompt) {\n formatted.push({ role: \"system\", content: systemPrompt });\n }\n\n // Add conversation messages\n for (const msg of messages) {\n formatted.push({\n role: msg.role,\n content: msg.content ?? \"\",\n });\n }\n\n return formatted;\n}\n\n/**\n * Convert ActionParameter to JSON Schema format recursively\n */\nfunction parameterToJsonSchema(param: {\n type: string;\n description?: string;\n enum?: string[];\n items?: unknown;\n properties?: Record<string, unknown>;\n}): Record<string, unknown> {\n const schema: Record<string, unknown> = {\n type: param.type,\n };\n\n if (param.description) {\n schema.description = param.description;\n }\n\n if (param.enum) {\n schema.enum = param.enum;\n }\n\n // Handle array items\n if (param.type === \"array\" && param.items) {\n schema.items = parameterToJsonSchema(\n param.items as {\n type: string;\n description?: string;\n enum?: string[];\n items?: unknown;\n properties?: Record<string, unknown>;\n },\n );\n }\n\n // Handle nested object properties\n if (param.type === \"object\" && param.properties) {\n schema.properties = Object.fromEntries(\n Object.entries(param.properties).map(([key, prop]) => [\n key,\n parameterToJsonSchema(\n prop as {\n type: string;\n description?: string;\n enum?: string[];\n items?: unknown;\n properties?: Record<string, unknown>;\n },\n ),\n ]),\n );\n }\n\n return schema;\n}\n\n/**\n * Convert actions to OpenAI tool format\n */\nexport function formatTools(actions: ActionDefinition[]): Array<{\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: object;\n };\n}> {\n return actions.map((action) => ({\n type: \"function\" as const,\n function: {\n name: action.name,\n description: action.description,\n parameters: {\n type: \"object\",\n properties: action.parameters\n ? Object.fromEntries(\n Object.entries(action.parameters).map(([key, param]) => [\n key,\n parameterToJsonSchema(param),\n ]),\n )\n : {},\n required: action.parameters\n ? Object.entries(action.parameters)\n .filter(([, param]) => param.required)\n .map(([key]) => key)\n : [],\n },\n },\n }));\n}\n\n// ============================================\n// Vision/Multimodal Support\n// ============================================\n\n/**\n * Content block types for multimodal messages\n */\nexport type AnthropicContentBlock =\n | { type: \"text\"; text: string }\n | {\n type: \"image\";\n source:\n | {\n type: \"base64\";\n media_type: string;\n data: string;\n }\n | {\n type: \"url\";\n url: string;\n };\n }\n | {\n type: \"document\";\n source:\n | {\n type: \"base64\";\n media_type: string;\n data: string;\n }\n | {\n type: \"url\";\n url: string;\n };\n };\n\nexport type OpenAIContentBlock =\n | { type: \"text\"; text: string }\n | {\n type: \"image_url\";\n image_url: {\n url: string;\n detail?: \"low\" | \"high\" | \"auto\";\n };\n };\n\n/**\n * Check if a message has image attachments\n * Supports both new format (metadata.attachments) and legacy (attachments)\n */\nexport function hasImageAttachments(message: Message): boolean {\n const attachments = message.metadata?.attachments;\n return attachments?.some((a) => a.type === \"image\") ?? false;\n}\n\n/**\n * Check if a message has media attachments (images or PDFs)\n */\nexport function hasMediaAttachments(message: Message): boolean {\n const attachments = message.metadata?.attachments;\n return (\n attachments?.some(\n (a) =>\n a.type === \"image\" ||\n (a.type === \"file\" && a.mimeType === \"application/pdf\"),\n ) ?? false\n );\n}\n\n/**\n * Convert MessageAttachment to Anthropic image content block\n *\n * Anthropic format:\n * {\n * type: \"image\",\n * source: {\n * type: \"base64\",\n * media_type: \"image/png\",\n * data: \"base64data...\"\n * }\n * }\n */\nexport function attachmentToAnthropicImage(\n attachment: MessageAttachment,\n): AnthropicContentBlock | null {\n if (attachment.type !== \"image\") return null;\n\n // Use URL if available (cloud storage)\n if (attachment.url) {\n return {\n type: \"image\",\n source: {\n type: \"url\",\n url: attachment.url,\n },\n };\n }\n\n // Fall back to base64 data\n if (!attachment.data) return null;\n\n // Extract base64 data (remove data URI prefix if present)\n let base64Data = attachment.data;\n if (base64Data.startsWith(\"data:\")) {\n const commaIndex = base64Data.indexOf(\",\");\n if (commaIndex !== -1) {\n base64Data = base64Data.slice(commaIndex + 1);\n }\n }\n\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: attachment.mimeType || \"image/png\",\n data: base64Data,\n },\n };\n}\n\n/**\n * Convert MessageAttachment to OpenAI image_url content block\n *\n * OpenAI format:\n * {\n * type: \"image_url\",\n * image_url: {\n * url: \"data:image/png;base64,...\"\n * }\n * }\n */\nexport function attachmentToOpenAIImage(\n attachment: MessageAttachment,\n): OpenAIContentBlock | null {\n if (attachment.type !== \"image\") return null;\n\n let imageUrl: string;\n\n // Use URL if available (cloud storage)\n if (attachment.url) {\n imageUrl = attachment.url;\n } else if (attachment.data) {\n // Build data URI if not already one\n imageUrl = attachment.data.startsWith(\"data:\")\n ? attachment.data\n : `data:${attachment.mimeType || \"image/png\"};base64,${attachment.data}`;\n } else {\n return null;\n }\n\n return {\n type: \"image_url\",\n image_url: {\n url: imageUrl,\n detail: \"auto\",\n },\n };\n}\n\n/**\n * Convert MessageAttachment (PDF) to Anthropic document content block\n *\n * Anthropic format:\n * {\n * type: \"document\",\n * source: {\n * type: \"base64\",\n * media_type: \"application/pdf\",\n * data: \"base64data...\"\n * }\n * }\n */\nexport function attachmentToAnthropicDocument(\n attachment: MessageAttachment,\n): AnthropicContentBlock | null {\n // Only handle PDF files\n if (attachment.type !== \"file\" || attachment.mimeType !== \"application/pdf\") {\n return null;\n }\n\n // Use URL if available (cloud storage)\n if (attachment.url) {\n return {\n type: \"document\",\n source: {\n type: \"url\",\n url: attachment.url,\n },\n };\n }\n\n // Fall back to base64 data\n if (!attachment.data) return null;\n\n // Extract base64 data (remove data URI prefix if present)\n let base64Data = attachment.data;\n if (base64Data.startsWith(\"data:\")) {\n const commaIndex = base64Data.indexOf(\",\");\n if (commaIndex !== -1) {\n base64Data = base64Data.slice(commaIndex + 1);\n }\n }\n\n return {\n type: \"document\",\n source: {\n type: \"base64\",\n media_type: \"application/pdf\",\n data: base64Data,\n },\n };\n}\n\n/**\n * Convert a Message to Anthropic multimodal content blocks\n */\nexport function messageToAnthropicContent(\n message: Message,\n): string | AnthropicContentBlock[] {\n const attachments = message.metadata?.attachments;\n const content = message.content ?? \"\";\n\n // If no media attachments (images or PDFs), return simple string\n if (!hasMediaAttachments(message)) {\n return content;\n }\n\n // Build content blocks array\n const blocks: AnthropicContentBlock[] = [];\n\n // Add media attachments first (Claude recommends media before text)\n if (attachments) {\n for (const attachment of attachments) {\n // Try image first\n const imageBlock = attachmentToAnthropicImage(attachment);\n if (imageBlock) {\n blocks.push(imageBlock);\n continue;\n }\n // Try document (PDF)\n const docBlock = attachmentToAnthropicDocument(attachment);\n if (docBlock) {\n blocks.push(docBlock);\n }\n }\n }\n\n // Add text content\n if (content) {\n blocks.push({ type: \"text\", text: content });\n }\n\n return blocks;\n}\n\n/**\n * Convert a Message to OpenAI multimodal content blocks\n */\nexport function messageToOpenAIContent(\n message: Message,\n): string | OpenAIContentBlock[] {\n const attachments = message.metadata?.attachments;\n const content = message.content ?? \"\";\n\n // If no image attachments, return simple string\n if (!hasImageAttachments(message)) {\n return content;\n }\n\n // Build content blocks array\n const blocks: OpenAIContentBlock[] = [];\n\n // Add text content first\n if (content) {\n blocks.push({ type: \"text\", text: content });\n }\n\n // Add image attachments\n if (attachments) {\n for (const attachment of attachments) {\n const imageBlock = attachmentToOpenAIImage(attachment);\n if (imageBlock) {\n blocks.push(imageBlock);\n }\n }\n }\n\n return blocks;\n}\n\n/**\n * Anthropic content block types (extended for tools)\n */\nexport type AnthropicToolUseBlock = {\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, unknown>;\n};\n\nexport type AnthropicToolResultBlock = {\n type: \"tool_result\";\n tool_use_id: string;\n content: string;\n};\n\nexport type AnthropicMessageContent =\n | string\n | Array<\n AnthropicContentBlock | AnthropicToolUseBlock | AnthropicToolResultBlock\n >;\n\n/**\n * Format messages for Anthropic with full tool support\n * Handles: text, images, tool_use, and tool_result\n *\n * Key differences from OpenAI:\n * - tool_calls become tool_use blocks in assistant content\n * - tool results become tool_result blocks in user content\n */\nexport function formatMessagesForAnthropic(\n messages: Message[],\n systemPrompt?: string,\n): {\n system: string;\n messages: Array<{\n role: \"user\" | \"assistant\";\n content: AnthropicMessageContent;\n }>;\n} {\n const formatted: Array<{\n role: \"user\" | \"assistant\";\n content: AnthropicMessageContent;\n }> = [];\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n\n if (msg.role === \"system\") continue; // System handled separately\n\n if (msg.role === \"assistant\") {\n // Build content array for assistant\n const content: Array<AnthropicContentBlock | AnthropicToolUseBlock> = [];\n\n // Add text content if present\n if (msg.content) {\n content.push({ type: \"text\", text: msg.content });\n }\n\n // Convert tool_calls to tool_use blocks\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n for (const tc of msg.tool_calls) {\n content.push({\n type: \"tool_use\",\n id: tc.id,\n name: tc.function.name,\n input: JSON.parse(tc.function.arguments),\n });\n }\n }\n\n formatted.push({\n role: \"assistant\",\n content:\n content.length === 1 && content[0].type === \"text\"\n ? (content[0] as { type: \"text\"; text: string }).text\n : content,\n });\n } else if (msg.role === \"tool\" && msg.tool_call_id) {\n // Tool results go in user message as tool_result blocks\n // Group consecutive tool messages together\n const toolResults: AnthropicToolResultBlock[] = [\n {\n type: \"tool_result\",\n tool_use_id: msg.tool_call_id,\n content: msg.content ?? \"\",\n },\n ];\n\n // Look ahead for more consecutive tool messages\n while (i + 1 < messages.length && messages[i + 1].role === \"tool\") {\n i++;\n const nextTool = messages[i];\n if (nextTool.tool_call_id) {\n toolResults.push({\n type: \"tool_result\",\n tool_use_id: nextTool.tool_call_id,\n content: nextTool.content ?? \"\",\n });\n }\n }\n\n formatted.push({\n role: \"user\",\n content: toolResults,\n });\n } else if (msg.role === \"user\") {\n formatted.push({\n role: \"user\",\n content: messageToAnthropicContent(msg),\n });\n }\n }\n\n return {\n system: systemPrompt || \"\",\n messages: formatted,\n };\n}\n\n/**\n * OpenAI message format with tool support\n */\nexport type OpenAIMessage =\n | { role: \"system\"; content: string }\n | { role: \"user\"; content: string | OpenAIContentBlock[] }\n | {\n role: \"assistant\";\n content: string | null;\n tool_calls?: Array<{\n id: string;\n type: \"function\";\n function: { name: string; arguments: string };\n }>;\n }\n | { role: \"tool\"; content: string; tool_call_id: string };\n\n/**\n * Format messages for OpenAI with full tool support\n * Handles: text, images, tool_calls, and tool results\n */\nexport function formatMessagesForOpenAI(\n messages: Message[],\n systemPrompt?: string,\n): OpenAIMessage[] {\n const formatted: OpenAIMessage[] = [];\n\n // Add system prompt if provided\n if (systemPrompt) {\n formatted.push({ role: \"system\", content: systemPrompt });\n }\n\n for (const msg of messages) {\n if (msg.role === \"system\") {\n formatted.push({ role: \"system\", content: msg.content ?? \"\" });\n } else if (msg.role === \"user\") {\n formatted.push({\n role: \"user\",\n content: messageToOpenAIContent(msg),\n });\n } else if (msg.role === \"assistant\") {\n const assistantMsg: OpenAIMessage = {\n role: \"assistant\",\n content: msg.content,\n };\n if (msg.tool_calls && msg.tool_calls.length > 0) {\n (assistantMsg as { tool_calls: typeof msg.tool_calls }).tool_calls =\n msg.tool_calls;\n }\n formatted.push(assistantMsg);\n } else if (msg.role === \"tool\" && msg.tool_call_id) {\n formatted.push({\n role: \"tool\",\n content: msg.content ?? \"\",\n tool_call_id: msg.tool_call_id,\n });\n }\n }\n\n return formatted;\n}\n","import type {\n LLMConfig,\n StreamEvent,\n WebSearchConfig,\n Citation,\n} from \"../core/stream-events\";\nimport { generateMessageId, generateToolCallId } from \"../core/utils\";\nimport type { LLMAdapter, ChatCompletionRequest } from \"./base\";\nimport { formatMessagesForOpenAI, formatTools } from \"./base\";\n\n/**\n * OpenAI adapter configuration\n */\nexport interface OpenAIAdapterConfig {\n apiKey: string;\n model?: string;\n baseUrl?: string;\n temperature?: number;\n maxTokens?: number;\n /**\n * Enable native web search for GPT models.\n * Uses OpenAI's web_search_preview tool.\n */\n webSearch?: boolean | WebSearchConfig;\n}\n\n/**\n * OpenAI LLM Adapter\n *\n * Supports: GPT-4, GPT-4o, GPT-3.5-turbo, etc.\n */\nexport class OpenAIAdapter implements LLMAdapter {\n readonly provider = \"openai\";\n readonly model: string;\n\n private client: any; // OpenAI client (lazy loaded)\n private config: OpenAIAdapterConfig;\n\n constructor(config: OpenAIAdapterConfig) {\n this.config = config;\n this.model = config.model || \"gpt-4o\";\n }\n\n private async getClient() {\n if (!this.client) {\n // Dynamic import to make openai optional\n const { default: OpenAI } = await import(\"openai\");\n this.client = new OpenAI({\n apiKey: this.config.apiKey,\n baseURL: this.config.baseUrl,\n });\n }\n return this.client;\n }\n\n async *stream(request: ChatCompletionRequest): AsyncGenerator<StreamEvent> {\n const client = await this.getClient();\n\n // Use raw messages if provided (for agent loop with tool calls), otherwise format from Message[]\n let messages: Array<Record<string, unknown>>;\n if (request.rawMessages && request.rawMessages.length > 0) {\n // Process raw messages - convert any attachments to OpenAI vision format\n const processedMessages = request.rawMessages.map((msg) => {\n // Check if message has attachments (images)\n const hasAttachments =\n msg.attachments &&\n Array.isArray(msg.attachments) &&\n msg.attachments.length > 0;\n\n if (hasAttachments) {\n // Convert to OpenAI multimodal content format\n const content: Array<Record<string, unknown>> = [];\n\n // Add text content if present\n if (msg.content) {\n content.push({ type: \"text\", text: msg.content });\n }\n\n // Add image attachments\n for (const attachment of msg.attachments as Array<{\n type: string;\n data?: string;\n url?: string;\n mimeType?: string;\n }>) {\n if (attachment.type === \"image\") {\n let imageUrl: string;\n\n if (attachment.url) {\n // Use URL directly (cloud storage)\n imageUrl = attachment.url;\n } else if (attachment.data) {\n // Use base64 data\n imageUrl = attachment.data.startsWith(\"data:\")\n ? attachment.data\n : `data:${attachment.mimeType || \"image/png\"};base64,${attachment.data}`;\n } else {\n continue; // Skip if no data or URL\n }\n\n content.push({\n type: \"image_url\",\n image_url: { url: imageUrl, detail: \"auto\" },\n });\n }\n }\n\n return { ...msg, content, attachments: undefined };\n }\n return msg;\n });\n\n // Add system prompt at the start if provided and not already present\n if (request.systemPrompt) {\n const hasSystem = processedMessages.some((m) => m.role === \"system\");\n if (!hasSystem) {\n messages = [\n { role: \"system\", content: request.systemPrompt },\n ...processedMessages,\n ];\n } else {\n messages = processedMessages;\n }\n } else {\n messages = processedMessages;\n }\n } else {\n // Format from Message[] with multimodal support (images, attachments)\n messages = formatMessagesForOpenAI(\n request.messages,\n request.systemPrompt,\n ) as Array<Record<string, unknown>>;\n }\n\n // Build tools array\n const tools: Array<Record<string, unknown>> = request.actions?.length\n ? formatTools(request.actions)\n : [];\n\n // Check for web search configuration (from request or adapter config)\n const webSearchConfig = request.webSearch ?? this.config.webSearch;\n\n if (webSearchConfig) {\n // Add web_search_preview tool for OpenAI\n const webSearchTool: Record<string, unknown> = {\n type: \"web_search_preview\",\n };\n\n // Add search context config if provided\n const wsConfig =\n typeof webSearchConfig === \"object\" ? webSearchConfig : {};\n\n if (wsConfig.userLocation) {\n webSearchTool.search_context_size = \"medium\"; // OpenAI uses size, not location\n }\n\n tools.push(webSearchTool);\n }\n\n const messageId = generateMessageId();\n\n // Emit message start\n yield { type: \"message:start\", id: messageId };\n\n try {\n const stream = await client.chat.completions.create({\n model: request.config?.model || this.model,\n messages,\n tools: tools.length > 0 ? tools : undefined,\n temperature: request.config?.temperature ?? this.config.temperature,\n max_tokens: request.config?.maxTokens ?? this.config.maxTokens,\n stream: true,\n stream_options: { include_usage: true },\n });\n\n let currentToolCall: {\n id: string;\n name: string;\n arguments: string;\n } | null = null;\n\n // Track citations from web search\n const collectedCitations: Citation[] = [];\n let citationIndex = 0;\n\n let usage:\n | {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n }\n | undefined;\n\n for await (const chunk of stream) {\n // Check for abort\n if (request.signal?.aborted) {\n break;\n }\n\n const delta = chunk.choices[0]?.delta;\n const choice = chunk.choices[0];\n\n // Handle content\n if (delta?.content) {\n yield { type: \"message:delta\", content: delta.content };\n }\n\n // Handle annotations (citations from web search) - OpenAI includes these in delta\n const annotations = (\n delta as {\n annotations?: Array<{\n type: string;\n url_citation?: { url: string; title?: string };\n }>;\n }\n )?.annotations;\n\n if (annotations && annotations.length > 0) {\n for (const annotation of annotations) {\n if (\n annotation.type === \"url_citation\" &&\n annotation.url_citation?.url\n ) {\n citationIndex++;\n const url = annotation.url_citation.url;\n const domain = extractDomain(url);\n collectedCitations.push({\n index: citationIndex,\n url,\n title: annotation.url_citation.title || domain,\n domain,\n favicon: domain\n ? `https://www.google.com/s2/favicons?domain=${domain}&sz=32`\n : undefined,\n });\n }\n }\n }\n\n // Handle tool calls\n if (delta?.tool_calls) {\n for (const toolCall of delta.tool_calls) {\n // New tool call\n if (toolCall.id) {\n // End previous tool call if any\n if (currentToolCall) {\n yield {\n type: \"action:args\",\n id: currentToolCall.id,\n args: currentToolCall.arguments,\n };\n }\n\n currentToolCall = {\n id: toolCall.id,\n name: toolCall.function?.name || \"\",\n arguments: toolCall.function?.arguments || \"\",\n };\n\n yield {\n type: \"action:start\",\n id: currentToolCall.id,\n name: currentToolCall.name,\n };\n } else if (currentToolCall && toolCall.function?.arguments) {\n // Append to current tool call arguments\n currentToolCall.arguments += toolCall.function.arguments;\n }\n }\n }\n\n // Capture usage from final chunk (OpenAI sends it with stream_options.include_usage)\n if (chunk.usage) {\n usage = {\n prompt_tokens: chunk.usage.prompt_tokens,\n completion_tokens: chunk.usage.completion_tokens,\n total_tokens: chunk.usage.total_tokens,\n };\n }\n\n // Check for finish\n if (choice?.finish_reason) {\n // Complete any pending tool call\n if (currentToolCall) {\n yield {\n type: \"action:args\",\n id: currentToolCall.id,\n args: currentToolCall.arguments,\n };\n }\n }\n }\n\n // Emit citations if we collected any\n if (collectedCitations.length > 0) {\n const uniqueCitations = deduplicateCitations(collectedCitations);\n yield { type: \"citation\", citations: uniqueCitations };\n }\n\n // Emit message end\n yield { type: \"message:end\" };\n yield { type: \"done\", usage };\n } catch (error) {\n yield {\n type: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n code: \"OPENAI_ERROR\",\n };\n }\n }\n}\n\n/**\n * Extract domain from URL\n */\nfunction extractDomain(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.hostname;\n } catch {\n return \"\";\n }\n}\n\n/**\n * Deduplicate citations by URL\n */\nfunction deduplicateCitations(citations: Citation[]): Citation[] {\n const seen = new Map<string, Citation>();\n let index = 0;\n for (const citation of citations) {\n if (!seen.has(citation.url)) {\n index++;\n seen.set(citation.url, { ...citation, index });\n }\n }\n return Array.from(seen.values());\n}\n\n/**\n * Create OpenAI adapter\n */\nexport function createOpenAIAdapter(\n config: OpenAIAdapterConfig,\n): OpenAIAdapter {\n return new OpenAIAdapter(config);\n}\n","/**\n * Provider Types\n *\n * Defines interfaces for:\n * 1. Provider Formatters (for tool transformations in agent loop)\n * 2. Multi-provider architecture (AIProvider, capabilities, configs)\n */\n\nimport type {\n ToolDefinition,\n UnifiedToolCall,\n UnifiedToolResult,\n} from \"../core/stream-events\";\nimport type { LLMAdapter } from \"../adapters/base\";\n\n// ============================================\n// Provider Formatter Types (for agent loop)\n// ============================================\n\n/**\n * Provider formatter interface\n *\n * Each provider implements this interface to handle:\n * - Tool definition transformation\n * - Tool call parsing from responses\n * - Tool result formatting\n * - Stop reason detection\n */\nexport interface ProviderFormatter {\n /**\n * Transform unified tool definitions to provider format\n */\n transformTools(tools: ToolDefinition[]): unknown[];\n\n /**\n * Parse tool calls from provider response\n */\n parseToolCalls(response: unknown): UnifiedToolCall[];\n\n /**\n * Format tool results for provider\n */\n formatToolResults(results: UnifiedToolResult[]): unknown[];\n\n /**\n * Check if response indicates tool use is requested\n */\n isToolUseStop(response: unknown): boolean;\n\n /**\n * Check if response indicates end of turn\n */\n isEndTurnStop(response: unknown): boolean;\n\n /**\n * Get stop reason string from response\n */\n getStopReason(response: unknown): string;\n\n /**\n * Extract text content from response\n */\n extractTextContent(response: unknown): string;\n\n /**\n * Build assistant message with tool calls for conversation history\n */\n buildAssistantToolMessage(\n toolCalls: UnifiedToolCall[],\n textContent?: string,\n ): unknown;\n\n /**\n * Build user message with tool results for conversation history\n */\n buildToolResultMessage(results: UnifiedToolResult[]): unknown;\n}\n\n// ============================================\n// Anthropic Tool Types\n// ============================================\n\n/**\n * Anthropic tool definition format\n */\nexport interface AnthropicTool {\n name: string;\n description: string;\n input_schema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\n/**\n * Anthropic tool_use block from response\n */\nexport interface AnthropicToolUse {\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\n/**\n * Anthropic tool_result block\n */\nexport interface AnthropicToolResult {\n type: \"tool_result\";\n tool_use_id: string;\n content: string;\n}\n\n// ============================================\n// OpenAI Tool Types\n// ============================================\n\n/**\n * OpenAI tool definition format\n */\nexport interface OpenAITool {\n type: \"function\";\n function: {\n name: string;\n description: string;\n parameters: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n };\n}\n\n/**\n * OpenAI tool call from response\n */\nexport interface OpenAIToolCall {\n id: string;\n type: \"function\";\n function: {\n name: string;\n arguments: string; // JSON string\n };\n}\n\n/**\n * OpenAI tool result message\n */\nexport interface OpenAIToolResult {\n role: \"tool\";\n tool_call_id: string;\n content: string;\n}\n\n// ============================================\n// Gemini Tool Types\n// ============================================\n\n/**\n * Google Gemini function declaration\n */\nexport interface GeminiFunctionDeclaration {\n name: string;\n description: string;\n parameters?: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\n/**\n * Gemini function call from response\n */\nexport interface GeminiFunctionCall {\n name: string;\n args: Record<string, unknown>;\n}\n\n/**\n * Gemini function response\n */\nexport interface GeminiFunctionResponse {\n name: string;\n response: Record<string, unknown>;\n}\n\n// ============================================\n// Provider Capabilities (for UI feature flags)\n// ============================================\n\n/**\n * Capabilities of a model for UI feature flags\n * UI components can use this to enable/disable features\n */\nexport interface ProviderCapabilities {\n /** Supports image inputs */\n supportsVision: boolean;\n /** Supports tool/function calling */\n supportsTools: boolean;\n /** Supports extended thinking (Claude, DeepSeek) */\n supportsThinking: boolean;\n /** Supports streaming responses */\n supportsStreaming: boolean;\n /** Supports PDF document inputs */\n supportsPDF: boolean;\n /** Supports audio inputs */\n supportsAudio: boolean;\n /** Supports video inputs */\n supportsVideo: boolean;\n /** Maximum context tokens */\n maxTokens: number;\n /** Supported image MIME types */\n supportedImageTypes: string[];\n /** Supported audio MIME types */\n supportedAudioTypes?: string[];\n /** Supported video MIME types */\n supportedVideoTypes?: string[];\n /** Supports JSON mode / structured output */\n supportsJsonMode?: boolean;\n /** Supports system messages */\n supportsSystemMessages?: boolean;\n}\n\n// ============================================\n// AI Provider Interface\n// ============================================\n\n/**\n * AI Provider interface (object form)\n *\n * Wraps existing LLMAdapter with additional metadata:\n * - Supported models list\n * - Per-model capabilities\n * - Provider name\n */\nexport interface AIProviderObject {\n /** Provider name (e.g., 'openai', 'anthropic') */\n readonly name: string;\n\n /** List of supported model IDs */\n readonly supportedModels: string[];\n\n /**\n * Get a language model adapter for the given model ID\n * Returns the existing LLMAdapter interface - no breaking changes\n */\n languageModel(modelId: string): LLMAdapter;\n\n /**\n * Get capabilities for a specific model\n * UI components use this to enable/disable features\n */\n getCapabilities(modelId: string): ProviderCapabilities;\n\n /**\n * Optional: Get an embedding model (future expansion)\n */\n embeddingModel?(modelId: string): EmbeddingModel;\n}\n\n/**\n * Callable AI Provider (Vercel AI SDK style)\n *\n * A function that returns a LanguageModel when called with a model ID,\n * but also has properties for provider metadata and methods.\n *\n * @example\n * ```typescript\n * const openai = createOpenAI({ apiKey: '...' });\n *\n * // Callable - returns LanguageModel directly (Vercel AI SDK style)\n * const model = openai('gpt-4o');\n *\n * // Also supports method calls (backward compatible)\n * const model2 = openai.languageModel('gpt-4o');\n *\n * // Check capabilities\n * const caps = openai.getCapabilities('gpt-4o');\n * if (caps.supportsVision) {\n * // Show image upload button\n * }\n * ```\n */\nexport interface AIProvider extends AIProviderObject {\n /**\n * Call the provider directly with a model ID to get a LanguageModel\n * This is the Vercel AI SDK style pattern\n */\n (modelId: string): LLMAdapter;\n}\n\n/**\n * Helper to create a callable AIProvider\n * Combines a callable function with AIProvider properties\n */\nexport function createCallableProvider(\n providerFn: (modelId: string) => LLMAdapter,\n properties: Omit<AIProviderObject, \"languageModel\">,\n): AIProvider {\n // Define 'name' property using defineProperty since it's read-only on functions\n Object.defineProperty(providerFn, \"name\", {\n value: properties.name,\n writable: false,\n configurable: true,\n });\n\n // Assign other properties\n Object.assign(providerFn, {\n supportedModels: properties.supportedModels,\n languageModel: providerFn,\n getCapabilities: properties.getCapabilities,\n embeddingModel: properties.embeddingModel,\n });\n\n return providerFn as AIProvider;\n}\n\n/**\n * Embedding model interface (for future expansion)\n */\nexport interface EmbeddingModel {\n readonly provider: string;\n readonly modelId: string;\n embed(texts: string[]): Promise<number[][]>;\n}\n\n// ============================================\n// Provider-Specific Configurations\n// ============================================\n\n/**\n * Base provider configuration\n */\nexport interface BaseProviderConfig {\n /** API key (falls back to environment variable) */\n apiKey?: string;\n /** Custom base URL */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n /** Custom headers to include */\n headers?: Record<string, string>;\n}\n\n/**\n * OpenAI provider configuration\n */\nexport interface OpenAIProviderConfig extends BaseProviderConfig {\n /** OpenAI organization ID */\n organization?: string;\n /** OpenAI project ID */\n project?: string;\n /** Vision detail level for images */\n imageDetail?: \"auto\" | \"low\" | \"high\";\n}\n\n/**\n * Anthropic provider configuration\n */\nexport interface AnthropicProviderConfig extends BaseProviderConfig {\n /** Extended thinking budget in tokens (minimum 1024) */\n thinkingBudget?: number;\n /** Enable prompt caching */\n cacheControl?: boolean;\n}\n\n/**\n * Google provider configuration\n */\nexport interface GoogleProviderConfig extends BaseProviderConfig {\n /** Safety settings */\n safetySettings?: GoogleSafetySetting[];\n /** Grounding configuration (for web search) */\n groundingConfig?: GoogleGroundingConfig;\n}\n\n/**\n * Google safety setting\n */\nexport interface GoogleSafetySetting {\n category:\n | \"HARM_CATEGORY_HARASSMENT\"\n | \"HARM_CATEGORY_HATE_SPEECH\"\n | \"HARM_CATEGORY_SEXUALLY_EXPLICIT\"\n | \"HARM_CATEGORY_DANGEROUS_CONTENT\";\n threshold:\n | \"BLOCK_NONE\"\n | \"BLOCK_LOW_AND_ABOVE\"\n | \"BLOCK_MEDIUM_AND_ABOVE\"\n | \"BLOCK_HIGH_AND_ABOVE\";\n}\n\n/**\n * Google grounding configuration\n */\nexport interface GoogleGroundingConfig {\n /** Enable Google Search grounding */\n googleSearchRetrieval?: boolean;\n}\n\n/**\n * xAI provider configuration\n */\nexport interface XAIProviderConfig extends BaseProviderConfig {\n // xAI uses OpenAI-compatible API, no extra config needed\n}\n\n/**\n * Azure OpenAI provider configuration\n */\nexport interface AzureProviderConfig extends BaseProviderConfig {\n /** Azure resource name */\n resourceName: string;\n /** Deployment name */\n deploymentName: string;\n /** API version (default: 2024-02-15-preview) */\n apiVersion?: string;\n}\n\n/**\n * Ollama model-specific options\n * These map to Ollama's native API options\n */\nexport interface OllamaModelOptions {\n /** Context window size (default varies by model) */\n num_ctx?: number;\n /** Max tokens to predict (-1 = infinite, -2 = fill context) */\n num_predict?: number;\n /** Mirostat sampling (0 = disabled, 1 = Mirostat, 2 = Mirostat 2.0) */\n mirostat?: 0 | 1 | 2;\n /** Mirostat learning rate (default: 0.1) */\n mirostat_eta?: number;\n /** Mirostat target entropy (default: 5.0) */\n mirostat_tau?: number;\n /** Repeat penalty (default: 1.1) */\n repeat_penalty?: number;\n /** Random seed for reproducibility (-1 = random) */\n seed?: number;\n /** Top-k sampling (default: 40) */\n top_k?: number;\n /** Top-p (nucleus) sampling (default: 0.9) */\n top_p?: number;\n /** Min-p sampling (default: 0.0) */\n min_p?: number;\n /** Stop sequences */\n stop?: string[];\n /** Temperature override (also available in config) */\n temperature?: number;\n}\n\n/**\n * Ollama provider configuration\n */\nexport interface OllamaProviderConfig extends BaseProviderConfig {\n /** Default Ollama-specific model options */\n options?: OllamaModelOptions;\n}\n\n// ============================================\n// Model Information\n// ============================================\n\n/**\n * Model information for a provider\n */\nexport interface ModelInfo {\n /** Model ID */\n id: string;\n /** Display name */\n name: string;\n /** Description */\n description?: string;\n /** Capabilities */\n capabilities: ProviderCapabilities;\n /** Context window size */\n contextWindow: number;\n /** Pricing info (optional) */\n pricing?: {\n inputPerMillion?: number;\n outputPerMillion?: number;\n };\n}\n\n// ============================================\n// Default Capabilities\n// ============================================\n\n/**\n * Default capabilities for unknown models\n */\nexport const DEFAULT_CAPABILITIES: ProviderCapabilities = {\n supportsVision: false,\n supportsTools: true,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: false,\n supportsAudio: false,\n supportsVideo: false,\n maxTokens: 8192,\n supportedImageTypes: [],\n supportsJsonMode: false,\n supportsSystemMessages: true,\n};\n","/**\n * OpenRouter Provider\n *\n * OpenRouter is a unified API gateway that provides access to 500+ AI models\n * from 60+ providers (OpenAI, Anthropic, Google, Meta, Mistral, etc.)\n * through a single endpoint.\n *\n * Features:\n * - Single API key for all models\n * - Automatic fallbacks and routing\n * - Cost optimization\n * - Provider preferences\n * - OpenAI-compatible API\n *\n * @see https://openrouter.ai/docs\n */\n\n// NEW: Modern pattern - openrouter() function\nexport {\n openrouter,\n createOpenRouter as createOpenRouterModel,\n fetchOpenRouterModels,\n searchOpenRouterModels,\n} from \"./provider\";\nexport type { OpenRouterProviderOptions, OpenRouterModel } from \"./provider\";\n\nimport { createOpenAIAdapter } from \"../../adapters/openai\";\nimport {\n createCallableProvider,\n type AIProvider,\n type ProviderCapabilities,\n} from \"../types\";\n\n// ============================================\n// Model Capabilities\n// ============================================\n\n/**\n * OpenRouter supports 500+ models dynamically.\n * Use fetchOpenRouterModels() to get live model list with accurate capabilities.\n * This default is used as fallback for all models.\n */\nconst DEFAULT_CAPABILITIES = {\n vision: true,\n tools: true,\n jsonMode: true,\n maxTokens: 128000,\n};\n\n// ============================================\n// Provider Config\n// ============================================\n\nexport interface OpenRouterProviderConfig {\n /** API key (defaults to OPENROUTER_API_KEY env var) */\n apiKey?: string;\n /** Base URL for API */\n baseUrl?: string;\n /** Your site URL for OpenRouter rankings */\n siteUrl?: string;\n /** Your app name for OpenRouter rankings */\n appName?: string;\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create an OpenRouter provider (callable, Vercel AI SDK style)\n *\n * @example\n * ```typescript\n * const or = createOpenRouter({ apiKey: '...' });\n *\n * // Callable - Vercel AI SDK style\n * const model = or('anthropic/claude-3.5-sonnet');\n *\n * // Also supports method call (backward compatible)\n * const model2 = or.languageModel('openai/gpt-4o');\n *\n * // Check capabilities\n * const caps = or.getCapabilities('anthropic/claude-3.5-sonnet');\n * ```\n */\nexport function createOpenRouter(\n config: OpenRouterProviderConfig = {},\n): AIProvider {\n const apiKey = config.apiKey ?? process.env.OPENROUTER_API_KEY ?? \"\";\n const baseUrl = config.baseUrl ?? \"https://openrouter.ai/api/v1\";\n\n // Create the callable function - uses OpenAI adapter since OpenRouter is OpenAI-compatible\n const providerFn = (modelId: string) => {\n return createOpenAIAdapter({\n apiKey,\n model: modelId,\n baseUrl,\n });\n };\n\n // Get capabilities helper - uses default capabilities for all models\n // Use fetchOpenRouterModels() to get accurate model-specific capabilities\n const getCapabilities = (modelId: string): ProviderCapabilities => {\n return {\n supportsVision: DEFAULT_CAPABILITIES.vision,\n supportsTools: DEFAULT_CAPABILITIES.tools,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: false,\n supportsAudio: false,\n supportsVideo: false,\n maxTokens: DEFAULT_CAPABILITIES.maxTokens,\n supportedImageTypes: DEFAULT_CAPABILITIES.vision\n ? [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]\n : [],\n supportsJsonMode: DEFAULT_CAPABILITIES.jsonMode,\n supportsSystemMessages: true,\n };\n };\n\n return createCallableProvider(providerFn, {\n name: \"openrouter\",\n supportedModels: [], // Use fetchOpenRouterModels() to get live model list\n getCapabilities,\n });\n}\n\n// Alias for consistency\nexport const createOpenRouterProvider = createOpenRouter;\n"]}