@yourgpt/llm-sdk 2.1.4-alpha.2 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/index.d.mts +3 -2
- package/dist/adapters/index.d.ts +3 -2
- package/dist/{types-DoZX2k3v.d.mts → base-5n-UuPfS.d.mts} +1 -353
- package/dist/{types-DtPQaoJi.d.ts → base-Di31iy_8.d.ts} +1 -353
- package/dist/fallback/index.d.mts +96 -0
- package/dist/fallback/index.d.ts +96 -0
- package/dist/fallback/index.js +284 -0
- package/dist/fallback/index.mjs +280 -0
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/providers/anthropic/index.d.mts +2 -1
- package/dist/providers/anthropic/index.d.ts +2 -1
- package/dist/providers/azure/index.d.mts +2 -1
- package/dist/providers/azure/index.d.ts +2 -1
- package/dist/providers/google/index.d.mts +2 -1
- package/dist/providers/google/index.d.ts +2 -1
- package/dist/providers/ollama/index.d.mts +3 -2
- package/dist/providers/ollama/index.d.ts +3 -2
- package/dist/providers/openai/index.d.mts +2 -1
- package/dist/providers/openai/index.d.ts +2 -1
- package/dist/providers/openrouter/index.d.mts +2 -1
- package/dist/providers/openrouter/index.d.ts +2 -1
- package/dist/providers/xai/index.d.mts +2 -1
- package/dist/providers/xai/index.d.ts +2 -1
- package/dist/types-BQl1suAv.d.mts +212 -0
- package/dist/types-C0vLXzuw.d.ts +355 -0
- package/dist/types-CNL8ZRne.d.ts +212 -0
- package/dist/types-VDgiUvH2.d.mts +355 -0
- package/package.json +7 -1
- package/dist/adapters/index.js.map +0 -1
- package/dist/adapters/index.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/providers/anthropic/index.js.map +0 -1
- package/dist/providers/anthropic/index.mjs.map +0 -1
- package/dist/providers/azure/index.js.map +0 -1
- package/dist/providers/azure/index.mjs.map +0 -1
- package/dist/providers/google/index.js.map +0 -1
- package/dist/providers/google/index.mjs.map +0 -1
- package/dist/providers/ollama/index.js.map +0 -1
- package/dist/providers/ollama/index.mjs.map +0 -1
- package/dist/providers/openai/index.js.map +0 -1
- package/dist/providers/openai/index.mjs.map +0 -1
- package/dist/providers/openrouter/index.js.map +0 -1
- package/dist/providers/openrouter/index.mjs.map +0 -1
- package/dist/providers/xai/index.js.map +0 -1
- package/dist/providers/xai/index.mjs.map +0 -1
- package/dist/yourgpt/index.js.map +0 -1
- package/dist/yourgpt/index.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/utils.ts","../../../src/adapters/base.ts","../../../src/adapters/azure.ts","../../../src/providers/types.ts","../../../src/providers/azure/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\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 ToolDefinition,\n WebSearchConfig,\n ProviderToolRuntimeOptions,\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 /** Full tool definitions for provider-native tool search / deferred loading paths. */\n toolDefinitions?: ToolDefinition[];\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 /** Optional provider-specific tool policy hints derived from runtime selection. */\n providerToolOptions?: ProviderToolRuntimeOptions;\n /** Enable adapter-level provider payload logging. */\n debug?: boolean;\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\nfunction stringifyForDebug(value: unknown): string {\n return JSON.stringify(\n value,\n (_key, currentValue) => {\n if (typeof currentValue === \"bigint\") {\n return currentValue.toString();\n }\n if (currentValue instanceof Error) {\n return {\n name: currentValue.name,\n message: currentValue.message,\n stack: currentValue.stack,\n };\n }\n return currentValue;\n },\n 2,\n );\n}\n\nexport function logProviderPayload(\n provider: string,\n label: string,\n payload: unknown,\n enabled?: boolean,\n): void {\n if (!enabled) {\n return;\n }\n\n // Stream chunks/events are too noisy for regular debug output and can flood\n // terminal context. Keep request/response payload logging, but suppress the\n // per-event stream logs unless we add a separate verbose flag later.\n if (label.toLowerCase().includes(\"stream \")) {\n return;\n }\n\n try {\n console.log(\n `[llm-sdk:${provider}] ${label}\\n${stringifyForDebug(payload)}`,\n );\n } catch (error) {\n console.log(\n `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,\n error,\n );\n }\n}\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 schema.additionalProperties = false;\n }\n\n return schema;\n}\n\nexport function normalizeObjectJsonSchema(\n schema: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n if (!schema || typeof schema !== \"object\") {\n return {\n type: \"object\",\n properties: {},\n required: [],\n additionalProperties: false,\n };\n }\n\n const normalized: Record<string, unknown> = { ...schema };\n const type = normalized.type;\n\n if (type === \"object\") {\n const properties =\n normalized.properties &&\n typeof normalized.properties === \"object\" &&\n !Array.isArray(normalized.properties)\n ? (normalized.properties as Record<string, unknown>)\n : {};\n\n normalized.properties = Object.fromEntries(\n Object.entries(properties).map(([key, value]) => [\n key,\n normalizeObjectJsonSchema(value as Record<string, unknown>),\n ]),\n );\n\n const propertyKeys = Object.keys(properties);\n const required = Array.isArray(normalized.required)\n ? normalized.required.filter(\n (value): value is string => typeof value === \"string\",\n )\n : [];\n normalized.required = Array.from(new Set([...required, ...propertyKeys]));\n\n if (normalized.additionalProperties === undefined) {\n normalized.additionalProperties = false;\n }\n } else if (\n type === \"array\" &&\n normalized.items &&\n typeof normalized.items === \"object\"\n ) {\n normalized.items = normalizeObjectJsonSchema(\n normalized.items as Record<string, unknown>,\n );\n }\n\n return normalized;\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 additionalProperties: false,\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","/**\n * Azure OpenAI LLM Adapter\n *\n * Azure OpenAI uses Microsoft's cloud infrastructure with\n * different authentication and URL patterns than standard OpenAI.\n *\n * Supports: Any OpenAI model deployed on Azure (GPT-4, GPT-4o, etc.)\n * Features: Vision, Tools/Function Calling (depends on deployed model)\n */\n\nimport type { LLMConfig, StreamEvent } from \"../core/stream-events\";\nimport { generateMessageId, generateToolCallId } from \"../core/utils\";\nimport type {\n LLMAdapter,\n ChatCompletionRequest,\n CompletionResult,\n} from \"./base\";\nimport {\n formatMessagesForOpenAI,\n formatTools,\n logProviderPayload,\n} from \"./base\";\n\n// ============================================\n// Types\n// ============================================\n\n/**\n * Azure OpenAI adapter configuration\n */\nexport interface AzureAdapterConfig {\n /** Azure OpenAI API key */\n apiKey: string;\n /** Azure resource name (e.g., 'my-resource') */\n resourceName: string;\n /** Azure deployment name (e.g., 'gpt-4o-deployment') */\n deploymentName: string;\n /** API version (default: 2024-08-01-preview) */\n apiVersion?: string;\n temperature?: number;\n maxTokens?: number;\n /** Custom endpoint URL (optional, overrides resourceName) */\n baseUrl?: string;\n}\n\n// Default Azure API version\nconst DEFAULT_API_VERSION = \"2024-08-01-preview\";\n\n/**\n * Build Azure OpenAI endpoint URL\n */\nfunction buildAzureEndpoint(\n resourceName: string,\n deploymentName: string,\n apiVersion: string,\n): string {\n return `https://${resourceName}.openai.azure.com/openai/deployments/${deploymentName}`;\n}\n\n// ============================================\n// Adapter Implementation\n// ============================================\n\n/**\n * Azure OpenAI LLM Adapter\n *\n * Uses Azure's OpenAI service with Azure-specific authentication\n */\nexport class AzureAdapter implements LLMAdapter {\n readonly provider = \"azure\";\n readonly model: string;\n\n private client: any; // OpenAI client (lazy loaded)\n private config: AzureAdapterConfig;\n\n constructor(config: AzureAdapterConfig) {\n this.config = config;\n this.model = config.deploymentName;\n }\n\n private async getClient() {\n if (!this.client) {\n // Use OpenAI SDK with Azure configuration\n const { AzureOpenAI } = await import(\"openai\");\n\n const apiVersion = this.config.apiVersion || DEFAULT_API_VERSION;\n const endpoint =\n this.config.baseUrl ||\n buildAzureEndpoint(\n this.config.resourceName,\n this.config.deploymentName,\n apiVersion,\n );\n\n this.client = new AzureOpenAI({\n apiKey: this.config.apiKey,\n endpoint,\n apiVersion,\n deployment: this.config.deploymentName,\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 mimeType?: string;\n }>) {\n if (attachment.type === \"image\") {\n // Convert to OpenAI image_url format\n let imageUrl = attachment.data;\n if (!imageUrl.startsWith(\"data:\")) {\n imageUrl = `data:${attachment.mimeType || \"image/png\"};base64,${attachment.data}`;\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 payload = {\n // Azure uses deployment name, not model name\n model: this.config.deploymentName,\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 };\n logProviderPayload(\"azure\", \"request payload\", payload, request.debug);\n const stream = await client.chat.completions.create(payload);\n\n let currentToolCall: {\n id: string;\n name: string;\n arguments: string;\n } | null = null;\n\n for await (const chunk of stream) {\n logProviderPayload(\"azure\", \"stream chunk\", chunk, request.debug);\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 // 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\" };\n } catch (error) {\n yield {\n type: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n code: \"AZURE_ERROR\",\n };\n }\n }\n\n /**\n * Non-streaming completion (optional, for debugging)\n */\n async complete(request: ChatCompletionRequest): Promise<CompletionResult> {\n const client = await this.getClient();\n\n let messages: Array<Record<string, unknown>>;\n if (request.rawMessages && request.rawMessages.length > 0) {\n messages = request.rawMessages as Array<Record<string, unknown>>;\n if (request.systemPrompt) {\n const hasSystem = messages.some((m) => m.role === \"system\");\n if (!hasSystem) {\n messages = [\n { role: \"system\", content: request.systemPrompt },\n ...messages,\n ];\n }\n }\n } else {\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 payload = {\n model: this.config.deploymentName,\n messages,\n tools,\n temperature: request.config?.temperature ?? this.config.temperature,\n max_tokens: request.config?.maxTokens ?? this.config.maxTokens,\n };\n logProviderPayload(\"azure\", \"request payload\", payload, request.debug);\n const response = await client.chat.completions.create(payload);\n logProviderPayload(\"azure\", \"response payload\", response, request.debug);\n\n const choice = response.choices[0];\n const message = choice?.message;\n\n const toolCalls = (message?.tool_calls || []).map((tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n args: JSON.parse(tc.function.arguments || \"{}\"),\n }));\n\n return {\n content: message?.content || \"\",\n toolCalls,\n rawResponse: response as Record<string, unknown>,\n };\n }\n}\n\n/**\n * Create Azure OpenAI adapter\n */\nexport function createAzureAdapter(config: AzureAdapterConfig): AzureAdapter {\n return new AzureAdapter(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 * Azure OpenAI Provider\n *\n * Wraps the AzureAdapter with provider interface.\n * Azure OpenAI provides enterprise-grade OpenAI models with Azure security.\n *\n * Features:\n * - Vision (for supported deployments)\n * - Tools/Function calling\n * - Enterprise security & compliance\n * - Private networking options\n *\n * Note: Capabilities depend on which model is deployed, not a model ID.\n * The provider attempts to detect capabilities from the deployment name.\n */\n\nimport { createAzureAdapter } from \"../../adapters/azure\";\nimport {\n createCallableProvider,\n type AIProvider,\n type ProviderCapabilities,\n type AzureProviderConfig,\n} from \"../types\";\n\n// ============================================\n// Model Capability Patterns\n// ============================================\n\n/**\n * Detect model capabilities from deployment name\n * Azure deployments are user-named, so we look for common patterns\n */\nfunction detectCapabilitiesFromDeployment(deploymentName: string): {\n vision: boolean;\n tools: boolean;\n maxTokens: number;\n} {\n const name = deploymentName.toLowerCase();\n\n // GPT-4o variants (vision, tools, 128k context)\n if (name.includes(\"gpt-4o\") || name.includes(\"gpt4o\")) {\n return { vision: true, tools: true, maxTokens: 128000 };\n }\n\n // GPT-4 Turbo with vision\n if (\n (name.includes(\"gpt-4\") || name.includes(\"gpt4\")) &&\n (name.includes(\"turbo\") || name.includes(\"vision\"))\n ) {\n return { vision: true, tools: true, maxTokens: 128000 };\n }\n\n // GPT-4 base\n if (name.includes(\"gpt-4\") || name.includes(\"gpt4\")) {\n return { vision: false, tools: true, maxTokens: 8192 };\n }\n\n // GPT-3.5 Turbo\n if (\n name.includes(\"gpt-35\") ||\n name.includes(\"gpt-3.5\") ||\n name.includes(\"gpt35\")\n ) {\n return { vision: false, tools: true, maxTokens: 16385 };\n }\n\n // o1 reasoning models\n if (name.includes(\"o1\")) {\n return { vision: true, tools: false, maxTokens: 128000 };\n }\n\n // Default fallback\n return { vision: false, tools: true, maxTokens: 8192 };\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create an Azure OpenAI provider (callable, Vercel AI SDK style)\n *\n * @example\n * ```typescript\n * const azure = createAzure({\n * apiKey: '...',\n * resourceName: 'my-azure-resource',\n * deploymentName: 'gpt-4o-deployment',\n * });\n *\n * // Callable - Vercel AI SDK style\n * const model = azure('gpt-4o-deployment');\n *\n * // Also supports method call (backward compatible)\n * const model2 = azure.languageModel('gpt-4o-deployment');\n * ```\n */\nexport function createAzure(config: AzureProviderConfig): AIProvider {\n const apiKey = config.apiKey ?? process.env.AZURE_OPENAI_API_KEY ?? \"\";\n const resourceName =\n config.resourceName ?? process.env.AZURE_OPENAI_RESOURCE ?? \"\";\n const defaultDeployment =\n config.deploymentName ?? process.env.AZURE_OPENAI_DEPLOYMENT ?? \"\";\n\n // For Azure, the \"supported models\" are actually deployment names\n const supportedModels = defaultDeployment ? [defaultDeployment] : [];\n\n // Create the callable function\n const providerFn = (deploymentName: string) => {\n return createAzureAdapter({\n apiKey,\n resourceName,\n deploymentName: deploymentName || defaultDeployment,\n apiVersion: config.apiVersion,\n baseUrl: config.baseUrl,\n });\n };\n\n // Get capabilities helper\n const getCapabilities = (deploymentName: string): ProviderCapabilities => {\n const detected = detectCapabilitiesFromDeployment(\n deploymentName || defaultDeployment,\n );\n\n return {\n supportsVision: detected.vision,\n supportsTools: detected.tools,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: false,\n supportsAudio: false,\n supportsVideo: false,\n maxTokens: detected.maxTokens,\n supportedImageTypes: detected.vision\n ? [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]\n : [],\n supportsJsonMode: true,\n supportsSystemMessages: true,\n };\n };\n\n return createCallableProvider(providerFn, {\n name: \"azure\",\n supportedModels,\n getCapabilities,\n });\n}\n\n// Alias for consistency\nexport const createAzureProvider = createAzure;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/utils.ts","../../../src/adapters/base.ts","../../../src/adapters/azure.ts","../../../src/providers/types.ts","../../../src/providers/azure/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\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 ToolDefinition,\n WebSearchConfig,\n ProviderToolRuntimeOptions,\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 /** Full tool definitions for provider-native tool search / deferred loading paths. */\n toolDefinitions?: ToolDefinition[];\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 /** Optional provider-specific tool policy hints derived from runtime selection. */\n providerToolOptions?: ProviderToolRuntimeOptions;\n /** Enable adapter-level provider payload logging. */\n debug?: boolean;\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\nfunction stringifyForDebug(value: unknown): string {\n return JSON.stringify(\n value,\n (_key, currentValue) => {\n if (typeof currentValue === \"bigint\") {\n return currentValue.toString();\n }\n if (currentValue instanceof Error) {\n return {\n name: currentValue.name,\n message: currentValue.message,\n stack: currentValue.stack,\n };\n }\n return currentValue;\n },\n 2,\n );\n}\n\nexport function logProviderPayload(\n provider: string,\n label: string,\n payload: unknown,\n enabled?: boolean,\n): void {\n if (!enabled) {\n return;\n }\n\n // Stream chunks/events are too noisy for regular debug output and can flood\n // terminal context. Keep request/response payload logging, but suppress the\n // per-event stream logs unless we add a separate verbose flag later.\n if (label.toLowerCase().includes(\"stream \")) {\n return;\n }\n\n try {\n console.log(\n `[llm-sdk:${provider}] ${label}\\n${stringifyForDebug(payload)}`,\n );\n } catch (error) {\n console.log(\n `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,\n error,\n );\n }\n}\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 schema.additionalProperties = false;\n }\n\n return schema;\n}\n\nexport function normalizeObjectJsonSchema(\n schema: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n if (!schema || typeof schema !== \"object\") {\n return {\n type: \"object\",\n properties: {},\n required: [],\n additionalProperties: false,\n };\n }\n\n const normalized: Record<string, unknown> = { ...schema };\n const type = normalized.type;\n\n if (type === \"object\") {\n const properties =\n normalized.properties &&\n typeof normalized.properties === \"object\" &&\n !Array.isArray(normalized.properties)\n ? (normalized.properties as Record<string, unknown>)\n : {};\n\n normalized.properties = Object.fromEntries(\n Object.entries(properties).map(([key, value]) => [\n key,\n normalizeObjectJsonSchema(value as Record<string, unknown>),\n ]),\n );\n\n const propertyKeys = Object.keys(properties);\n const required = Array.isArray(normalized.required)\n ? normalized.required.filter(\n (value): value is string => typeof value === \"string\",\n )\n : [];\n normalized.required = Array.from(new Set([...required, ...propertyKeys]));\n\n if (normalized.additionalProperties === undefined) {\n normalized.additionalProperties = false;\n }\n } else if (\n type === \"array\" &&\n normalized.items &&\n typeof normalized.items === \"object\"\n ) {\n normalized.items = normalizeObjectJsonSchema(\n normalized.items as Record<string, unknown>,\n );\n }\n\n return normalized;\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 additionalProperties: false,\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","/**\n * Azure OpenAI LLM Adapter\n *\n * Azure OpenAI uses Microsoft's cloud infrastructure with\n * different authentication and URL patterns than standard OpenAI.\n *\n * Supports: Any OpenAI model deployed on Azure (GPT-4, GPT-4o, etc.)\n * Features: Vision, Tools/Function Calling (depends on deployed model)\n */\n\nimport type { LLMConfig, StreamEvent } from \"../core/stream-events\";\nimport { generateMessageId, generateToolCallId } from \"../core/utils\";\nimport type {\n LLMAdapter,\n ChatCompletionRequest,\n CompletionResult,\n} from \"./base\";\nimport {\n formatMessagesForOpenAI,\n formatTools,\n logProviderPayload,\n} from \"./base\";\n\n// ============================================\n// Types\n// ============================================\n\n/**\n * Azure OpenAI adapter configuration\n */\nexport interface AzureAdapterConfig {\n /** Azure OpenAI API key */\n apiKey: string;\n /** Azure resource name (e.g., 'my-resource') */\n resourceName: string;\n /** Azure deployment name (e.g., 'gpt-4o-deployment') */\n deploymentName: string;\n /** API version (default: 2024-08-01-preview) */\n apiVersion?: string;\n temperature?: number;\n maxTokens?: number;\n /** Custom endpoint URL (optional, overrides resourceName) */\n baseUrl?: string;\n}\n\n// Default Azure API version\nconst DEFAULT_API_VERSION = \"2024-08-01-preview\";\n\n/**\n * Build Azure OpenAI endpoint URL\n */\nfunction buildAzureEndpoint(\n resourceName: string,\n deploymentName: string,\n apiVersion: string,\n): string {\n return `https://${resourceName}.openai.azure.com/openai/deployments/${deploymentName}`;\n}\n\n// ============================================\n// Adapter Implementation\n// ============================================\n\n/**\n * Azure OpenAI LLM Adapter\n *\n * Uses Azure's OpenAI service with Azure-specific authentication\n */\nexport class AzureAdapter implements LLMAdapter {\n readonly provider = \"azure\";\n readonly model: string;\n\n private client: any; // OpenAI client (lazy loaded)\n private config: AzureAdapterConfig;\n\n constructor(config: AzureAdapterConfig) {\n this.config = config;\n this.model = config.deploymentName;\n }\n\n private async getClient() {\n if (!this.client) {\n // Use OpenAI SDK with Azure configuration\n const { AzureOpenAI } = await import(\"openai\");\n\n const apiVersion = this.config.apiVersion || DEFAULT_API_VERSION;\n const endpoint =\n this.config.baseUrl ||\n buildAzureEndpoint(\n this.config.resourceName,\n this.config.deploymentName,\n apiVersion,\n );\n\n this.client = new AzureOpenAI({\n apiKey: this.config.apiKey,\n endpoint,\n apiVersion,\n deployment: this.config.deploymentName,\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 mimeType?: string;\n }>) {\n if (attachment.type === \"image\") {\n // Convert to OpenAI image_url format\n let imageUrl = attachment.data;\n if (!imageUrl.startsWith(\"data:\")) {\n imageUrl = `data:${attachment.mimeType || \"image/png\"};base64,${attachment.data}`;\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 payload = {\n // Azure uses deployment name, not model name\n model: this.config.deploymentName,\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 };\n logProviderPayload(\"azure\", \"request payload\", payload, request.debug);\n const stream = await client.chat.completions.create(payload);\n\n let currentToolCall: {\n id: string;\n name: string;\n arguments: string;\n } | null = null;\n\n for await (const chunk of stream) {\n logProviderPayload(\"azure\", \"stream chunk\", chunk, request.debug);\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 // 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\" };\n } catch (error) {\n yield {\n type: \"error\",\n message: error instanceof Error ? error.message : \"Unknown error\",\n code: \"AZURE_ERROR\",\n };\n }\n }\n\n /**\n * Non-streaming completion (optional, for debugging)\n */\n async complete(request: ChatCompletionRequest): Promise<CompletionResult> {\n const client = await this.getClient();\n\n let messages: Array<Record<string, unknown>>;\n if (request.rawMessages && request.rawMessages.length > 0) {\n messages = request.rawMessages as Array<Record<string, unknown>>;\n if (request.systemPrompt) {\n const hasSystem = messages.some((m) => m.role === \"system\");\n if (!hasSystem) {\n messages = [\n { role: \"system\", content: request.systemPrompt },\n ...messages,\n ];\n }\n }\n } else {\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 payload = {\n model: this.config.deploymentName,\n messages,\n tools,\n temperature: request.config?.temperature ?? this.config.temperature,\n max_tokens: request.config?.maxTokens ?? this.config.maxTokens,\n };\n logProviderPayload(\"azure\", \"request payload\", payload, request.debug);\n const response = await client.chat.completions.create(payload);\n logProviderPayload(\"azure\", \"response payload\", response, request.debug);\n\n const choice = response.choices[0];\n const message = choice?.message;\n\n const toolCalls = (message?.tool_calls || []).map((tc: any) => ({\n id: tc.id,\n name: tc.function.name,\n args: JSON.parse(tc.function.arguments || \"{}\"),\n }));\n\n return {\n content: message?.content || \"\",\n toolCalls,\n rawResponse: response as Record<string, unknown>,\n };\n }\n}\n\n/**\n * Create Azure OpenAI adapter\n */\nexport function createAzureAdapter(config: AzureAdapterConfig): AzureAdapter {\n return new AzureAdapter(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 * Azure OpenAI Provider\n *\n * Wraps the AzureAdapter with provider interface.\n * Azure OpenAI provides enterprise-grade OpenAI models with Azure security.\n *\n * Features:\n * - Vision (for supported deployments)\n * - Tools/Function calling\n * - Enterprise security & compliance\n * - Private networking options\n *\n * Note: Capabilities depend on which model is deployed, not a model ID.\n * The provider attempts to detect capabilities from the deployment name.\n */\n\nimport { createAzureAdapter } from \"../../adapters/azure\";\nimport {\n createCallableProvider,\n type AIProvider,\n type ProviderCapabilities,\n type AzureProviderConfig,\n} from \"../types\";\n\n// ============================================\n// Model Capability Patterns\n// ============================================\n\n/**\n * Detect model capabilities from deployment name\n * Azure deployments are user-named, so we look for common patterns\n */\nfunction detectCapabilitiesFromDeployment(deploymentName: string): {\n vision: boolean;\n tools: boolean;\n maxTokens: number;\n} {\n const name = deploymentName.toLowerCase();\n\n // GPT-4o variants (vision, tools, 128k context)\n if (name.includes(\"gpt-4o\") || name.includes(\"gpt4o\")) {\n return { vision: true, tools: true, maxTokens: 128000 };\n }\n\n // GPT-4 Turbo with vision\n if (\n (name.includes(\"gpt-4\") || name.includes(\"gpt4\")) &&\n (name.includes(\"turbo\") || name.includes(\"vision\"))\n ) {\n return { vision: true, tools: true, maxTokens: 128000 };\n }\n\n // GPT-4 base\n if (name.includes(\"gpt-4\") || name.includes(\"gpt4\")) {\n return { vision: false, tools: true, maxTokens: 8192 };\n }\n\n // GPT-3.5 Turbo\n if (\n name.includes(\"gpt-35\") ||\n name.includes(\"gpt-3.5\") ||\n name.includes(\"gpt35\")\n ) {\n return { vision: false, tools: true, maxTokens: 16385 };\n }\n\n // o1 reasoning models\n if (name.includes(\"o1\")) {\n return { vision: true, tools: false, maxTokens: 128000 };\n }\n\n // Default fallback\n return { vision: false, tools: true, maxTokens: 8192 };\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create an Azure OpenAI provider (callable, Vercel AI SDK style)\n *\n * @example\n * ```typescript\n * const azure = createAzure({\n * apiKey: '...',\n * resourceName: 'my-azure-resource',\n * deploymentName: 'gpt-4o-deployment',\n * });\n *\n * // Callable - Vercel AI SDK style\n * const model = azure('gpt-4o-deployment');\n *\n * // Also supports method call (backward compatible)\n * const model2 = azure.languageModel('gpt-4o-deployment');\n * ```\n */\nexport function createAzure(config: AzureProviderConfig): AIProvider {\n const apiKey = config.apiKey ?? process.env.AZURE_OPENAI_API_KEY ?? \"\";\n const resourceName =\n config.resourceName ?? process.env.AZURE_OPENAI_RESOURCE ?? \"\";\n const defaultDeployment =\n config.deploymentName ?? process.env.AZURE_OPENAI_DEPLOYMENT ?? \"\";\n\n // For Azure, the \"supported models\" are actually deployment names\n const supportedModels = defaultDeployment ? [defaultDeployment] : [];\n\n // Create the callable function\n const providerFn = (deploymentName: string) => {\n return createAzureAdapter({\n apiKey,\n resourceName,\n deploymentName: deploymentName || defaultDeployment,\n apiVersion: config.apiVersion,\n baseUrl: config.baseUrl,\n });\n };\n\n // Get capabilities helper\n const getCapabilities = (deploymentName: string): ProviderCapabilities => {\n const detected = detectCapabilitiesFromDeployment(\n deploymentName || defaultDeployment,\n );\n\n return {\n supportsVision: detected.vision,\n supportsTools: detected.tools,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: false,\n supportsAudio: false,\n supportsVideo: false,\n maxTokens: detected.maxTokens,\n supportedImageTypes: detected.vision\n ? [\"image/png\", \"image/jpeg\", \"image/gif\", \"image/webp\"]\n : [],\n supportsJsonMode: true,\n supportsSystemMessages: true,\n };\n };\n\n return createCallableProvider(providerFn, {\n name: \"azure\",\n supportedModels,\n getCapabilities,\n });\n}\n\n// Alias for consistency\nexport const createAzureProvider = createAzure;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/providers/google/provider.ts","../../../src/core/utils.ts","../../../src/adapters/base.ts","../../../src/adapters/google.ts","../../../src/providers/types.ts","../../../src/providers/google/index.ts"],"names":["client","chunk","GOOGLE_MODELS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Google Provider - OpenAI-Compatible\n *\n * Uses OpenAI SDK with Google's OpenAI-compatible endpoint.\n * BaseURL: https://generativelanguage.googleapis.com/v1beta/openai/\n *\n * @example\n * ```ts\n * import { google } from '@yourgpt/llm-sdk/google';\n * import { generateText } from '@yourgpt/llm-sdk';\n *\n * const result = await generateText({\n * model: google('gemini-2.0-flash'),\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 Definitions\n// ============================================\n\ninterface GoogleModelConfig {\n vision: boolean;\n tools: boolean;\n audio: boolean;\n video: boolean;\n maxTokens: number;\n}\n\nconst GOOGLE_MODELS: Record<string, GoogleModelConfig> = {\n // Gemini 2.5 (Experimental)\n \"gemini-2.5-pro-preview-05-06\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 1048576,\n },\n \"gemini-2.5-flash-preview-05-20\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 1048576,\n },\n\n // Gemini 2.0\n \"gemini-2.0-flash\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 1048576,\n },\n \"gemini-2.0-flash-exp\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 1048576,\n },\n \"gemini-2.0-flash-lite\": {\n vision: true,\n tools: true,\n audio: false,\n video: false,\n maxTokens: 1048576,\n },\n \"gemini-2.0-flash-thinking-exp\": {\n vision: true,\n tools: false,\n audio: false,\n video: false,\n maxTokens: 32767,\n },\n\n // Gemini 1.5\n \"gemini-1.5-pro\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 2097152,\n },\n \"gemini-1.5-pro-latest\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 2097152,\n },\n \"gemini-1.5-flash\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 1048576,\n },\n \"gemini-1.5-flash-latest\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n maxTokens: 1048576,\n },\n \"gemini-1.5-flash-8b\": {\n vision: true,\n tools: true,\n audio: false,\n video: false,\n maxTokens: 1048576,\n },\n};\n\n// ============================================\n// Provider Options\n// ============================================\n\nexport interface GoogleProviderOptions {\n /** API key (defaults to GOOGLE_API_KEY or GEMINI_API_KEY env var) */\n apiKey?: string;\n /** Base URL for API (defaults to Google's OpenAI-compatible endpoint) */\n baseURL?: string;\n}\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create a Google Gemini language model using OpenAI-compatible API\n *\n * @param modelId - Model ID (e.g., 'gemini-2.0-flash', 'gemini-1.5-pro')\n * @param options - Provider options\n * @returns LanguageModel instance\n *\n * @example\n * ```ts\n * // Basic usage\n * const model = google('gemini-2.0-flash');\n *\n * // With custom options\n * const model = google('gemini-1.5-pro', {\n * apiKey: 'your-api-key',\n * });\n * ```\n */\nexport function google(\n modelId: string,\n options: GoogleProviderOptions = {},\n): LanguageModel {\n const apiKey =\n options.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;\n const baseURL =\n options.baseURL ??\n \"https://generativelanguage.googleapis.com/v1beta/openai/\";\n\n // Lazy-load OpenAI client (Google 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 });\n }\n return client;\n }\n\n // Get model config\n const modelConfig =\n GOOGLE_MODELS[modelId] ?? GOOGLE_MODELS[\"gemini-2.0-flash\"];\n\n return {\n provider: \"google\",\n modelId,\n\n capabilities: {\n supportsVision: modelConfig.vision,\n supportsTools: modelConfig.tools,\n supportsStreaming: true,\n supportsJsonMode: true,\n supportsThinking: modelId.includes(\"thinking\"),\n supportsPDF: true,\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 = formatMessagesForGoogle(params.messages);\n\n const response = await client.chat.completions.create({\n model: modelId,\n messages,\n tools: params.tools as any,\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n });\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 = formatMessagesForGoogle(params.messages);\n\n const stream = await client.chat.completions.create({\n model: modelId,\n messages,\n tools: params.tools as any,\n temperature: params.temperature,\n max_tokens: params.maxTokens,\n stream: true,\n });\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 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 Google's OpenAI-compatible API\n */\nfunction formatMessagesForGoogle(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 createGoogle for backward compatibility\nexport { google as createGoogle };\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 ToolDefinition,\n WebSearchConfig,\n ProviderToolRuntimeOptions,\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 /** Full tool definitions for provider-native tool search / deferred loading paths. */\n toolDefinitions?: ToolDefinition[];\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 /** Optional provider-specific tool policy hints derived from runtime selection. */\n providerToolOptions?: ProviderToolRuntimeOptions;\n /** Enable adapter-level provider payload logging. */\n debug?: boolean;\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\nfunction stringifyForDebug(value: unknown): string {\n return JSON.stringify(\n value,\n (_key, currentValue) => {\n if (typeof currentValue === \"bigint\") {\n return currentValue.toString();\n }\n if (currentValue instanceof Error) {\n return {\n name: currentValue.name,\n message: currentValue.message,\n stack: currentValue.stack,\n };\n }\n return currentValue;\n },\n 2,\n );\n}\n\nexport function logProviderPayload(\n provider: string,\n label: string,\n payload: unknown,\n enabled?: boolean,\n): void {\n if (!enabled) {\n return;\n }\n\n // Stream chunks/events are too noisy for regular debug output and can flood\n // terminal context. Keep request/response payload logging, but suppress the\n // per-event stream logs unless we add a separate verbose flag later.\n if (label.toLowerCase().includes(\"stream \")) {\n return;\n }\n\n try {\n console.log(\n `[llm-sdk:${provider}] ${label}\\n${stringifyForDebug(payload)}`,\n );\n } catch (error) {\n console.log(\n `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,\n error,\n );\n }\n}\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 schema.additionalProperties = false;\n }\n\n return schema;\n}\n\nexport function normalizeObjectJsonSchema(\n schema: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n if (!schema || typeof schema !== \"object\") {\n return {\n type: \"object\",\n properties: {},\n required: [],\n additionalProperties: false,\n };\n }\n\n const normalized: Record<string, unknown> = { ...schema };\n const type = normalized.type;\n\n if (type === \"object\") {\n const properties =\n normalized.properties &&\n typeof normalized.properties === \"object\" &&\n !Array.isArray(normalized.properties)\n ? (normalized.properties as Record<string, unknown>)\n : {};\n\n normalized.properties = Object.fromEntries(\n Object.entries(properties).map(([key, value]) => [\n key,\n normalizeObjectJsonSchema(value as Record<string, unknown>),\n ]),\n );\n\n const propertyKeys = Object.keys(properties);\n const required = Array.isArray(normalized.required)\n ? normalized.required.filter(\n (value): value is string => typeof value === \"string\",\n )\n : [];\n normalized.required = Array.from(new Set([...required, ...propertyKeys]));\n\n if (normalized.additionalProperties === undefined) {\n normalized.additionalProperties = false;\n }\n } else if (\n type === \"array\" &&\n normalized.items &&\n typeof normalized.items === \"object\"\n ) {\n normalized.items = normalizeObjectJsonSchema(\n normalized.items as Record<string, unknown>,\n );\n }\n\n return normalized;\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 additionalProperties: false,\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","/**\n * Google Gemini LLM Adapter\n *\n * Supports: Gemini 2.0, 1.5 Pro, 1.5 Flash, etc.\n * Features: Vision, Audio, Video, PDF, Tools/Function Calling, Google Search Grounding\n */\n\nimport type {\n LLMConfig,\n StreamEvent,\n Message,\n WebSearchConfig,\n Citation,\n} from \"../core/stream-events\";\nimport { generateMessageId, generateToolCallId } from \"../core/utils\";\nimport type {\n LLMAdapter,\n ChatCompletionRequest,\n CompletionResult,\n} from \"./base\";\nimport { formatTools, logProviderPayload } from \"./base\";\n\n// ============================================\n// Types\n// ============================================\n\n/**\n * Google adapter configuration\n */\nexport interface GoogleAdapterConfig {\n apiKey: string;\n model?: string;\n baseUrl?: string;\n temperature?: number;\n maxTokens?: number;\n /** Safety settings */\n safetySettings?: Array<{\n category: string;\n threshold: string;\n }>;\n /**\n * Enable native Google Search grounding for Gemini.\n * When true, Gemini can search Google to answer questions.\n */\n webSearch?: boolean | WebSearchConfig;\n}\n\n/**\n * Gemini content part types\n */\ntype GeminiPart =\n | { text: string }\n | { inlineData: { mimeType: string; data: string } }\n | { functionCall: { name: string; args: Record<string, unknown> } }\n | { functionResponse: { name: string; response: Record<string, unknown> } };\n\n/**\n * Gemini message format\n */\ninterface GeminiContent {\n role: \"user\" | \"model\";\n parts: GeminiPart[];\n}\n\n/**\n * Gemini tool format\n */\ninterface GeminiFunctionDeclaration {\n name: string;\n description: string;\n parameters?: {\n type: string;\n properties?: Record<string, unknown>;\n required?: string[];\n };\n}\n\n// ============================================\n// Content Conversion\n// ============================================\n\n/**\n * Convert attachment to Gemini inline data part\n * Note: Gemini requires base64 data for inline images. URL-based attachments\n * are not directly supported and will be skipped.\n */\nfunction attachmentToGeminiPart(attachment: {\n type: string;\n data?: string;\n url?: string;\n mimeType?: string;\n}): GeminiPart | null {\n // Gemini requires base64 data - URL-based attachments not supported\n if (!attachment.data) {\n // TODO: Could fetch URL and convert to base64, but that adds latency\n console.warn(\n \"Gemini adapter: URL-based attachments not supported, skipping\",\n );\n return null;\n }\n\n if (attachment.type === \"image\") {\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 inlineData: {\n mimeType: attachment.mimeType || \"image/png\",\n data: base64Data,\n },\n };\n }\n\n // Support for audio/video if present\n if (attachment.type === \"audio\" || attachment.type === \"video\") {\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 inlineData: {\n mimeType:\n attachment.mimeType ||\n (attachment.type === \"audio\" ? \"audio/mp3\" : \"video/mp4\"),\n data: base64Data,\n },\n };\n }\n\n return null;\n}\n\n/**\n * Convert Message to Gemini content format\n */\nfunction messageToGeminiContent(msg: Message): GeminiContent | null {\n // Skip system messages (handled separately)\n if (msg.role === \"system\") return null;\n\n const parts: GeminiPart[] = [];\n\n // Handle tool messages - convert to function response\n if (msg.role === \"tool\" && msg.tool_call_id) {\n // Tool results need to be sent as functionResponse\n let responseData: Record<string, unknown>;\n try {\n responseData = JSON.parse(msg.content || \"{}\");\n } catch {\n responseData = { result: msg.content || \"\" };\n }\n\n // Need to get the tool name from somewhere - use tool_call_id as fallback\n // In practice, we'd need to track the mapping\n const toolName =\n (msg.metadata as { toolName?: string })?.toolName || \"tool\";\n\n parts.push({\n functionResponse: {\n name: toolName,\n response: responseData,\n },\n });\n\n return { role: \"user\", parts };\n }\n\n // Add text content\n if (msg.content) {\n parts.push({ text: msg.content });\n }\n\n // Add attachments (images, audio, video)\n const attachments = msg.metadata?.attachments;\n if (attachments && Array.isArray(attachments)) {\n for (const attachment of attachments) {\n const part = attachmentToGeminiPart(attachment);\n if (part) {\n parts.push(part);\n }\n }\n }\n\n // Handle assistant messages with tool_calls\n if (msg.role === \"assistant\" && msg.tool_calls && msg.tool_calls.length > 0) {\n for (const tc of msg.tool_calls) {\n let args: Record<string, unknown> = {};\n try {\n args = JSON.parse(tc.function.arguments);\n } catch {\n // Keep empty args\n }\n parts.push({\n functionCall: {\n name: tc.function.name,\n args,\n },\n });\n }\n }\n\n if (parts.length === 0) return null;\n\n return {\n role: msg.role === \"assistant\" ? \"model\" : \"user\",\n parts,\n };\n}\n\n/**\n * Convert tools to Gemini function declarations\n */\nfunction formatToolsForGemini(\n actions: ChatCompletionRequest[\"actions\"],\n): { functionDeclarations: GeminiFunctionDeclaration[] } | undefined {\n if (!actions || actions.length === 0) return undefined;\n\n return {\n functionDeclarations: actions.map((action) => ({\n name: action.name,\n description: action.description,\n parameters: action.parameters\n ? {\n type: \"object\",\n properties: Object.fromEntries(\n Object.entries(action.parameters).map(([key, param]) => [\n key,\n {\n type: param.type,\n description: param.description,\n enum: param.enum,\n },\n ]),\n ),\n required: Object.entries(action.parameters)\n .filter(([, param]) => param.required)\n .map(([key]) => key),\n }\n : undefined,\n })),\n };\n}\n\n// ============================================\n// Adapter Implementation\n// ============================================\n\n/**\n * Google Gemini LLM Adapter\n */\nexport class GoogleAdapter implements LLMAdapter {\n readonly provider = \"google\";\n readonly model: string;\n\n private client: any; // GoogleGenerativeAI client (lazy loaded)\n private config: GoogleAdapterConfig;\n\n constructor(config: GoogleAdapterConfig) {\n this.config = config;\n this.model = config.model || \"gemini-2.0-flash\";\n }\n\n private async getClient() {\n if (!this.client) {\n // Dynamic import to make @google/generative-ai optional\n const { GoogleGenerativeAI } = await import(\"@google/generative-ai\");\n this.client = new GoogleGenerativeAI(this.config.apiKey);\n }\n return this.client;\n }\n\n async *stream(request: ChatCompletionRequest): AsyncGenerator<StreamEvent> {\n const client = await this.getClient();\n const modelId = request.config?.model || this.model;\n\n // Check for web search configuration (from request or adapter config)\n const webSearchConfig = request.webSearch ?? this.config.webSearch;\n\n // Get the generative model\n const model = client.getGenerativeModel({\n model: modelId,\n safetySettings: this.config.safetySettings,\n });\n\n // Build contents array\n let contents: GeminiContent[] = [];\n let systemInstruction: string | undefined;\n\n // Handle raw messages (for agent loop)\n if (request.rawMessages && request.rawMessages.length > 0) {\n // Process raw messages\n for (const msg of request.rawMessages) {\n if (msg.role === \"system\") {\n systemInstruction = (systemInstruction || \"\") + (msg.content || \"\");\n continue;\n }\n\n const content = messageToGeminiContent(msg as unknown as Message);\n if (content) {\n contents.push(content);\n }\n }\n\n // Add system prompt if provided\n if (request.systemPrompt && !systemInstruction) {\n systemInstruction = request.systemPrompt;\n }\n } else {\n // Format from Message[]\n for (const msg of request.messages) {\n if (msg.role === \"system\") {\n systemInstruction = (systemInstruction || \"\") + (msg.content || \"\");\n continue;\n }\n\n const content = messageToGeminiContent(msg);\n if (content) {\n contents.push(content);\n }\n }\n\n if (request.systemPrompt) {\n systemInstruction = request.systemPrompt;\n }\n }\n\n // Ensure conversation starts with user\n if (contents.length === 0 || contents[0].role !== \"user\") {\n // Add an empty user message if needed\n contents = [{ role: \"user\", parts: [{ text: \"\" }] }, ...contents];\n }\n\n // Merge consecutive same-role messages (Gemini requires alternating roles)\n const mergedContents: GeminiContent[] = [];\n for (const content of contents) {\n const last = mergedContents[mergedContents.length - 1];\n if (last && last.role === content.role) {\n last.parts.push(...content.parts);\n } else {\n mergedContents.push({ ...content, parts: [...content.parts] });\n }\n }\n\n // Prepare tools\n const functionTools = formatToolsForGemini(request.actions);\n\n // Build tools array - combine function declarations with google search if enabled\n const toolsArray: Array<Record<string, unknown>> = [];\n\n if (functionTools) {\n toolsArray.push(functionTools);\n }\n\n // Add Google Search grounding if enabled\n if (webSearchConfig) {\n toolsArray.push({\n google_search: {},\n });\n }\n\n const messageId = generateMessageId();\n\n // Emit message start\n yield { type: \"message:start\", id: messageId };\n\n try {\n logProviderPayload(\n \"google\",\n \"request payload\",\n {\n model: modelId,\n history: mergedContents.slice(0, -1),\n systemInstruction: systemInstruction\n ? { parts: [{ text: systemInstruction }] }\n : undefined,\n tools: toolsArray.length > 0 ? toolsArray : undefined,\n generationConfig: {\n temperature: request.config?.temperature ?? this.config.temperature,\n maxOutputTokens: request.config?.maxTokens ?? this.config.maxTokens,\n },\n messageParts: mergedContents[mergedContents.length - 1]?.parts,\n },\n request.debug,\n );\n // Start chat session with system instruction\n const chat = model.startChat({\n history: mergedContents.slice(0, -1), // All but the last message\n systemInstruction: systemInstruction\n ? { parts: [{ text: systemInstruction }] }\n : undefined,\n tools: toolsArray.length > 0 ? toolsArray : undefined,\n generationConfig: {\n temperature: request.config?.temperature ?? this.config.temperature,\n maxOutputTokens: request.config?.maxTokens ?? this.config.maxTokens,\n },\n });\n\n // Get the last message content\n const lastMessage = mergedContents[mergedContents.length - 1];\n\n // Stream response\n const result = await chat.sendMessageStream(lastMessage.parts);\n\n let currentToolCall: {\n id: string;\n name: string;\n args: Record<string, unknown>;\n } | null = null;\n\n // Track citations from grounding metadata\n const collectedCitations: Citation[] = [];\n\n for await (const chunk of result.stream) {\n logProviderPayload(\"google\", \"stream chunk\", chunk, request.debug);\n // Check for abort\n if (request.signal?.aborted) {\n break;\n }\n\n const candidate = chunk.candidates?.[0];\n if (!candidate?.content?.parts) continue;\n\n for (const part of candidate.content.parts) {\n // Handle text content\n if (\"text\" in part && part.text) {\n yield { type: \"message:delta\", content: part.text };\n }\n\n // Handle function calls\n if (\"functionCall\" in part && part.functionCall) {\n const fc = part.functionCall;\n const toolId = generateToolCallId();\n\n // Complete previous tool call if any\n if (currentToolCall) {\n yield {\n type: \"action:args\",\n id: currentToolCall.id,\n args: JSON.stringify(currentToolCall.args),\n };\n }\n\n currentToolCall = {\n id: toolId,\n name: fc.name,\n args: fc.args || {},\n };\n\n yield {\n type: \"action:start\",\n id: toolId,\n name: fc.name,\n };\n }\n }\n\n // Check for finish reason\n if (candidate.finishReason) {\n // Complete any pending tool call\n if (currentToolCall) {\n yield {\n type: \"action:args\",\n id: currentToolCall.id,\n args: JSON.stringify(currentToolCall.args),\n };\n }\n }\n\n // Extract grounding metadata (citations) from candidate\n const groundingMetadata = (\n candidate as {\n groundingMetadata?: {\n groundingChunks?: Array<{\n web?: { uri: string; title?: string };\n }>;\n searchEntryPoint?: { renderedContent?: string };\n };\n }\n )?.groundingMetadata;\n\n if (groundingMetadata?.groundingChunks) {\n for (const chunk of groundingMetadata.groundingChunks) {\n if (chunk.web?.uri) {\n const url = chunk.web.uri;\n const domain = extractDomain(url);\n // Check if we already have this citation\n if (!collectedCitations.some((c) => c.url === url)) {\n collectedCitations.push({\n index: collectedCitations.length + 1,\n url,\n title: chunk.web.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 }\n\n // Get usage from the final response\n let usage:\n | {\n prompt_tokens: number;\n completion_tokens: number;\n total_tokens: number;\n }\n | undefined;\n\n try {\n const response = await result.response;\n logProviderPayload(\n \"google\",\n \"response payload\",\n response,\n request.debug,\n );\n if (response.usageMetadata) {\n usage = {\n prompt_tokens: response.usageMetadata.promptTokenCount || 0,\n completion_tokens: response.usageMetadata.candidatesTokenCount || 0,\n total_tokens: response.usageMetadata.totalTokenCount || 0,\n };\n }\n\n // Also check final response for grounding metadata\n const finalCandidate = response.candidates?.[0];\n const finalGrounding = (\n finalCandidate as {\n groundingMetadata?: {\n groundingChunks?: Array<{\n web?: { uri: string; title?: string };\n }>;\n };\n }\n )?.groundingMetadata;\n\n if (finalGrounding?.groundingChunks) {\n for (const chunk of finalGrounding.groundingChunks) {\n if (chunk.web?.uri) {\n const url = chunk.web.uri;\n const domain = extractDomain(url);\n if (!collectedCitations.some((c) => c.url === url)) {\n collectedCitations.push({\n index: collectedCitations.length + 1,\n url,\n title: chunk.web.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 } catch {\n // Ignore usage retrieval errors\n }\n\n // Emit citations if we collected any\n if (collectedCitations.length > 0) {\n yield { type: \"citation\", citations: collectedCitations };\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: \"GOOGLE_ERROR\",\n };\n }\n }\n\n /**\n * Non-streaming completion (optional, for debugging)\n */\n async complete(request: ChatCompletionRequest): Promise<CompletionResult> {\n const client = await this.getClient();\n const modelId = request.config?.model || this.model;\n\n const model = client.getGenerativeModel({\n model: modelId,\n safetySettings: this.config.safetySettings,\n });\n\n // Build contents (same as stream)\n let contents: GeminiContent[] = [];\n let systemInstruction: string | undefined;\n\n for (const msg of request.messages) {\n if (msg.role === \"system\") {\n systemInstruction = (systemInstruction || \"\") + (msg.content || \"\");\n continue;\n }\n\n const content = messageToGeminiContent(msg);\n if (content) {\n contents.push(content);\n }\n }\n\n if (request.systemPrompt) {\n systemInstruction = request.systemPrompt;\n }\n\n // Ensure conversation starts with user\n if (contents.length === 0 || contents[0].role !== \"user\") {\n contents = [{ role: \"user\", parts: [{ text: \"\" }] }, ...contents];\n }\n\n // Merge consecutive same-role messages\n const mergedContents: GeminiContent[] = [];\n for (const content of contents) {\n const last = mergedContents[mergedContents.length - 1];\n if (last && last.role === content.role) {\n last.parts.push(...content.parts);\n } else {\n mergedContents.push({ ...content, parts: [...content.parts] });\n }\n }\n\n const tools = formatToolsForGemini(request.actions);\n\n const payload = {\n model: modelId,\n history: mergedContents.slice(0, -1),\n systemInstruction: systemInstruction\n ? { parts: [{ text: systemInstruction }] }\n : undefined,\n tools: tools ? [tools] : undefined,\n generationConfig: {\n temperature: request.config?.temperature ?? this.config.temperature,\n maxOutputTokens: request.config?.maxTokens ?? this.config.maxTokens,\n },\n messageParts: mergedContents[mergedContents.length - 1]?.parts,\n };\n logProviderPayload(\"google\", \"request payload\", payload, request.debug);\n const chat = model.startChat({\n history: mergedContents.slice(0, -1),\n systemInstruction: systemInstruction\n ? { parts: [{ text: systemInstruction }] }\n : undefined,\n tools: tools ? [tools] : undefined,\n generationConfig: {\n temperature: request.config?.temperature ?? this.config.temperature,\n maxOutputTokens: request.config?.maxTokens ?? this.config.maxTokens,\n },\n });\n\n const lastMessage = mergedContents[mergedContents.length - 1];\n const result = await chat.sendMessage(lastMessage.parts);\n const response = result.response;\n logProviderPayload(\"google\", \"response payload\", response, request.debug);\n\n // Extract content and tool calls\n let textContent = \"\";\n const toolCalls: CompletionResult[\"toolCalls\"] = [];\n\n const candidate = response.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (\"text\" in part && part.text) {\n textContent += part.text;\n }\n if (\"functionCall\" in part && part.functionCall) {\n toolCalls.push({\n id: generateToolCallId(),\n name: part.functionCall.name,\n args: part.functionCall.args || {},\n });\n }\n }\n }\n\n return {\n content: textContent,\n toolCalls,\n rawResponse: response as Record<string, unknown>,\n };\n }\n}\n\n/**\n * Create Google Gemini adapter\n */\nexport function createGoogleAdapter(\n config: GoogleAdapterConfig,\n): GoogleAdapter {\n return new GoogleAdapter(config);\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 * 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 * Google Provider\n *\n * Modern pattern: google('gemini-2.0-flash') returns a LanguageModel\n * Legacy pattern: createGoogle({ apiKey }) returns an AIProvider\n *\n * Features:\n * - Vision (images)\n * - Audio input\n * - Video input\n * - PDF documents\n * - Tools/Function calling\n * - Massive context windows (up to 2M tokens)\n */\n\n// NEW: Modern pattern - google() function\nexport { google, createGoogle as createGoogleModel } from \"./provider\";\nexport type { GoogleProviderOptions } from \"./provider\";\n\nimport { createGoogleAdapter } from \"../../adapters/google\";\nimport {\n createCallableProvider,\n type AIProvider,\n type ProviderCapabilities,\n type GoogleProviderConfig,\n} from \"../types\";\n\n// ============================================\n// Model Definitions\n// ============================================\n\ninterface ModelCapabilities {\n vision: boolean;\n tools: boolean;\n audio: boolean;\n video: boolean;\n pdf: boolean;\n maxTokens: number;\n outputTokens: number;\n}\n\nconst GOOGLE_MODELS: Record<string, ModelCapabilities> = {\n // Gemini 2.0 series (latest)\n \"gemini-2.0-flash\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 8192,\n },\n \"gemini-2.0-flash-lite\": {\n vision: true,\n tools: true,\n audio: false,\n video: false,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 8192,\n },\n\n // Gemini 2.5 series (experimental)\n \"gemini-2.5-pro-preview-05-06\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 65536,\n },\n \"gemini-2.5-flash-preview-05-20\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 65536,\n },\n\n // Gemini 1.5 series\n \"gemini-1.5-pro\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 2000000,\n outputTokens: 8192,\n },\n \"gemini-1.5-pro-latest\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 2000000,\n outputTokens: 8192,\n },\n \"gemini-1.5-flash\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 8192,\n },\n \"gemini-1.5-flash-latest\": {\n vision: true,\n tools: true,\n audio: true,\n video: true,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 8192,\n },\n \"gemini-1.5-flash-8b\": {\n vision: true,\n tools: true,\n audio: false,\n video: false,\n pdf: true,\n maxTokens: 1000000,\n outputTokens: 8192,\n },\n\n // Gemini 1.0 series (legacy)\n \"gemini-1.0-pro\": {\n vision: false,\n tools: true,\n audio: false,\n video: false,\n pdf: false,\n maxTokens: 30720,\n outputTokens: 2048,\n },\n};\n\n// ============================================\n// Provider Implementation\n// ============================================\n\n/**\n * Create a Google provider (callable, Vercel AI SDK style)\n *\n * @example\n * ```typescript\n * const google = createGoogle({ apiKey: '...' });\n *\n * // Callable - Vercel AI SDK style\n * const model = google('gemini-2.0-flash');\n *\n * // Also supports method call (backward compatible)\n * const model2 = google.languageModel('gemini-2.0-flash');\n *\n * // Check capabilities\n * const caps = google.getCapabilities('gemini-2.0-flash');\n * if (caps.supportsVideo) {\n * // Show video upload button\n * }\n * ```\n */\nexport function createGoogle(config: GoogleProviderConfig = {}): AIProvider {\n const apiKey = config.apiKey ?? process.env.GOOGLE_API_KEY ?? \"\";\n\n // Create the callable function\n const providerFn = (modelId: string) => {\n return createGoogleAdapter({\n apiKey,\n model: modelId,\n baseUrl: config.baseUrl,\n safetySettings: config.safetySettings,\n });\n };\n\n // Get capabilities helper\n const getCapabilities = (modelId: string): ProviderCapabilities => {\n const model = GOOGLE_MODELS[modelId] ?? GOOGLE_MODELS[\"gemini-2.0-flash\"];\n\n return {\n supportsVision: model.vision,\n supportsTools: model.tools,\n supportsThinking: false,\n supportsStreaming: true,\n supportsPDF: model.pdf,\n supportsAudio: model.audio,\n supportsVideo: model.video,\n maxTokens: model.maxTokens,\n supportedImageTypes: model.vision\n ? [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"image/heic\",\n \"image/heif\",\n ]\n : [],\n supportedAudioTypes: model.audio\n ? [\n \"audio/mp3\",\n \"audio/wav\",\n \"audio/aiff\",\n \"audio/aac\",\n \"audio/ogg\",\n \"audio/flac\",\n ]\n : [],\n supportedVideoTypes: model.video\n ? [\n \"video/mp4\",\n \"video/mpeg\",\n \"video/mov\",\n \"video/avi\",\n \"video/webm\",\n \"video/mkv\",\n ]\n : [],\n supportsJsonMode: true,\n supportsSystemMessages: true,\n };\n };\n\n return createCallableProvider(providerFn, {\n name: \"google\",\n supportedModels: Object.keys(GOOGLE_MODELS),\n getCapabilities,\n });\n}\n\n// Alias for consistency\nexport const createGoogleProvider = createGoogle;\n"]}
|