@providerprotocol/ai 0.0.13 → 0.0.14

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.
@@ -1,4 +1,4 @@
1
- import { b as Provider } from '../provider-mKkz7Q9U.js';
1
+ import { b as Provider } from '../provider-Bi0nyNhA.js';
2
2
 
3
3
  /**
4
4
  * @fileoverview Anthropic API type definitions.
@@ -395,15 +395,23 @@ function createLLMHandler() {
395
395
  );
396
396
  const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;
397
397
  const body = transformRequest(request, modelId);
398
+ const headers = {
399
+ "Content-Type": "application/json",
400
+ "x-api-key": apiKey,
401
+ "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
402
+ };
403
+ if (request.config.headers) {
404
+ for (const [key, value] of Object.entries(request.config.headers)) {
405
+ if (value !== void 0) {
406
+ headers[key] = value;
407
+ }
408
+ }
409
+ }
398
410
  const response = await doFetch(
399
411
  baseUrl,
400
412
  {
401
413
  method: "POST",
402
- headers: {
403
- "Content-Type": "application/json",
404
- "x-api-key": apiKey,
405
- "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
406
- },
414
+ headers,
407
415
  body: JSON.stringify(body),
408
416
  signal: request.signal
409
417
  },
@@ -433,15 +441,23 @@ function createLLMHandler() {
433
441
  const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;
434
442
  const body = transformRequest(request, modelId);
435
443
  body.stream = true;
444
+ const headers = {
445
+ "Content-Type": "application/json",
446
+ "x-api-key": apiKey,
447
+ "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
448
+ };
449
+ if (request.config.headers) {
450
+ for (const [key, value] of Object.entries(request.config.headers)) {
451
+ if (value !== void 0) {
452
+ headers[key] = value;
453
+ }
454
+ }
455
+ }
436
456
  const response = await doStreamFetch(
437
457
  baseUrl,
438
458
  {
439
459
  method: "POST",
440
- headers: {
441
- "Content-Type": "application/json",
442
- "x-api-key": apiKey,
443
- "anthropic-version": request.config.apiVersion ?? ANTHROPIC_VERSION
444
- },
460
+ headers,
445
461
  body: JSON.stringify(body),
446
462
  signal: request.signal
447
463
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/anthropic/transform.ts","../../src/providers/anthropic/llm.ts","../../src/providers/anthropic/index.ts"],"sourcesContent":["/**\n * @fileoverview UPP to Anthropic message transformation utilities.\n *\n * This module handles bidirectional conversion between Universal Provider Protocol\n * message formats and Anthropic's native API structures. It supports:\n * - Request transformation (UPP -> Anthropic)\n * - Response transformation (Anthropic -> UPP)\n * - Stream event transformation for real-time responses\n * - Tool call and structured output handling\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n AnthropicLLMParams,\n AnthropicRequest,\n AnthropicMessage,\n AnthropicContent,\n AnthropicTool,\n AnthropicResponse,\n AnthropicStreamEvent,\n AnthropicCacheControl,\n AnthropicSystemContent,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request to Anthropic's native API format.\n *\n * Handles conversion of messages, system prompts, tools, and structured output\n * configuration. Parameters are spread directly to enable pass-through of any\n * Anthropic API fields, even those not explicitly defined in our types.\n *\n * @typeParam TParams - Anthropic-specific parameters extending AnthropicLLMParams\n * @param request - The UPP-formatted LLM request\n * @param modelId - The Anthropic model identifier (e.g., 'claude-sonnet-4-20250514')\n * @returns An AnthropicRequest ready for the Messages API\n *\n * @example\n * ```typescript\n * const anthropicRequest = transformRequest({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: 'sk-...' },\n * params: { max_tokens: 1024, temperature: 0.7 },\n * }, 'claude-sonnet-4-20250514');\n * ```\n *\n * @see {@link transformResponse} for the reverse transformation\n */\nexport function transformRequest<TParams extends AnthropicLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): AnthropicRequest {\n const params = (request.params ?? {}) as AnthropicLLMParams;\n\n const anthropicRequest: AnthropicRequest = {\n ...params,\n model: modelId,\n messages: request.messages.map(transformMessage),\n };\n\n if (request.system) {\n // Pass through directly - accepts string or array of AnthropicSystemContent\n // Array format enables cache_control: [{type: 'text', text: '...', cache_control: {...}}]\n anthropicRequest.system = request.system as string | AnthropicSystemContent[];\n }\n\n if (request.tools && request.tools.length > 0) {\n // For tool caching, use params.tools directly with native Anthropic format\n anthropicRequest.tools = request.tools.map(transformTool);\n anthropicRequest.tool_choice = { type: 'auto' };\n }\n\n if (request.structure) {\n const structuredTool: AnthropicTool = {\n name: 'json_response',\n description: 'Return the response in the specified JSON format. You MUST use this tool to provide your response.',\n input_schema: {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n },\n };\n\n anthropicRequest.tools = [...(anthropicRequest.tools ?? []), structuredTool];\n anthropicRequest.tool_choice = { type: 'tool', name: 'json_response' };\n }\n\n return anthropicRequest;\n}\n\n/**\n * Filters content blocks to include only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with a string type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Extracts cache control configuration from message metadata.\n *\n * @param message - The message to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractCacheControl(message: Message): AnthropicCacheControl | undefined {\n const anthropicMeta = message.metadata?.anthropic as\n | { cache_control?: AnthropicCacheControl }\n | undefined;\n return anthropicMeta?.cache_control;\n}\n\n/**\n * Transforms a UPP Message to Anthropic's message format.\n *\n * Handles three message types:\n * - UserMessage: Converted with content blocks\n * - AssistantMessage: Includes text and tool_use blocks\n * - ToolResultMessage: Converted to user role with tool_result content\n *\n * Cache control can be specified via message metadata:\n * ```typescript\n * new UserMessage(content, {\n * metadata: { anthropic: { cache_control: { type: \"ephemeral\" } } }\n * })\n * ```\n *\n * @param message - The UPP message to transform\n * @returns An AnthropicMessage with the appropriate role and content\n * @throws Error if the message type is unknown\n */\nfunction transformMessage(message: Message): AnthropicMessage {\n const cacheControl = extractCacheControl(message);\n\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n const contentBlocks = validContent.map((block, index, arr) =>\n transformContentBlock(block, index === arr.length - 1 ? cacheControl : undefined)\n );\n return {\n role: 'user',\n content: contentBlocks,\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const content: AnthropicContent[] = validContent.map((block, index, arr) =>\n transformContentBlock(block, index === arr.length - 1 && !message.toolCalls?.length ? cacheControl : undefined)\n );\n\n if (message.toolCalls) {\n for (let i = 0; i < message.toolCalls.length; i++) {\n const call = message.toolCalls[i]!;\n const isLast = i === message.toolCalls.length - 1;\n content.push({\n type: 'tool_use',\n id: call.toolCallId,\n name: call.toolName,\n input: call.arguments,\n ...(isLast && cacheControl ? { cache_control: cacheControl } : {}),\n });\n }\n }\n\n return {\n role: 'assistant',\n content,\n };\n }\n\n if (isToolResultMessage(message)) {\n return {\n role: 'user',\n content: message.results.map((result, index, arr) => ({\n type: 'tool_result' as const,\n tool_use_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n is_error: result.isError,\n ...(index === arr.length - 1 && cacheControl ? { cache_control: cacheControl } : {}),\n })),\n };\n }\n\n throw new Error(`Unknown message type: ${message.type}`);\n}\n\n/**\n * Transforms a UPP ContentBlock to Anthropic's content format.\n *\n * Supports text and image content types. Image blocks can be provided\n * as base64, URL, or raw bytes (which are converted to base64).\n *\n * @param block - The UPP content block to transform\n * @param cacheControl - Optional cache control to apply to the block\n * @returns An AnthropicContent object\n * @throws Error if the content type or image source type is unsupported\n */\nfunction transformContentBlock(\n block: ContentBlock,\n cacheControl?: AnthropicCacheControl\n): AnthropicContent {\n switch (block.type) {\n case 'text':\n return {\n type: 'text',\n text: block.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: imageBlock.source.data,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n if (imageBlock.source.type === 'url') {\n return {\n type: 'image',\n source: {\n type: 'url',\n url: imageBlock.source.url,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: base64,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n throw new Error(`Unknown image source type`);\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts cache control configuration from tool metadata.\n *\n * @param tool - The tool to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractToolCacheControl(tool: Tool): AnthropicCacheControl | undefined {\n const anthropicMeta = tool.metadata?.anthropic as\n | { cache_control?: AnthropicCacheControl }\n | undefined;\n return anthropicMeta?.cache_control;\n}\n\n/**\n * Transforms a UPP Tool definition to Anthropic's tool format.\n *\n * Cache control can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'search_docs',\n * description: 'Search documentation',\n * parameters: {...},\n * metadata: { anthropic: { cache_control: { type: 'ephemeral' } } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns An AnthropicTool with the appropriate input schema\n */\nfunction transformTool(tool: Tool): AnthropicTool {\n const cacheControl = extractToolCacheControl(tool);\n\n return {\n name: tool.name,\n description: tool.description,\n input_schema: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n}\n\n/**\n * Transforms an Anthropic API response to UPP's LLMResponse format.\n *\n * Extracts text content, tool calls, and structured output data from\n * Anthropic's response. The json_response tool is treated specially\n * for structured output extraction.\n *\n * @param data - The raw Anthropic API response\n * @returns A UPP LLMResponse with message, usage, and optional structured data\n *\n * @see {@link transformRequest} for the request transformation\n */\nexport function transformResponse(data: AnthropicResponse): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of data.content) {\n if (block.type === 'text') {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use') {\n if (block.name === 'json_response') {\n structuredData = block.input;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: block.input,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n anthropic: {\n stop_reason: data.stop_reason,\n stop_sequence: data.stop_sequence,\n model: data.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n cacheReadTokens: data.usage.cache_read_input_tokens ?? 0,\n cacheWriteTokens: data.usage.cache_creation_input_tokens ?? 0,\n };\n\n return {\n message,\n usage,\n stopReason: data.stop_reason ?? 'end_turn',\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating streamed response data.\n *\n * Used during streaming to collect content blocks, token counts, and\n * metadata as events arrive from the Anthropic API.\n */\nexport interface StreamState {\n /** Unique identifier for the message being streamed. */\n messageId: string;\n /** The model that generated this response. */\n model: string;\n /** Accumulated content blocks indexed by their stream position. */\n content: Array<{ type: string; text?: string; id?: string; name?: string; input?: string }>;\n /** The reason the response ended, if completed. */\n stopReason: string | null;\n /** Number of input tokens consumed. */\n inputTokens: number;\n /** Number of output tokens generated. */\n outputTokens: number;\n /** Number of tokens read from cache (cache hits). */\n cacheReadTokens: number;\n /** Number of tokens written to cache. */\n cacheWriteTokens: number;\n}\n\n/**\n * Creates an initialized StreamState for accumulating streaming responses.\n *\n * @returns A fresh StreamState with empty/default values\n */\nexport function createStreamState(): StreamState {\n return {\n messageId: '',\n model: '',\n content: [],\n stopReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n}\n\n/**\n * Transforms an Anthropic streaming event to a UPP StreamEvent.\n *\n * Updates the provided state object as a side effect to accumulate\n * response data across multiple events. Returns null for events that\n * don't produce corresponding UPP events (e.g., ping, message_delta).\n *\n * @param event - The Anthropic SSE event to transform\n * @param state - Mutable state object to update with accumulated data\n * @returns A UPP StreamEvent, or null if no event should be emitted\n *\n * @example\n * ```typescript\n * const state = createStreamState();\n * for await (const event of parseSSEStream(response.body)) {\n * const uppEvent = transformStreamEvent(event, state);\n * if (uppEvent) {\n * yield uppEvent;\n * }\n * }\n * const finalResponse = buildResponseFromState(state);\n * ```\n */\nexport function transformStreamEvent(\n event: AnthropicStreamEvent,\n state: StreamState\n): StreamEvent | null {\n switch (event.type) {\n case 'message_start':\n state.messageId = event.message.id;\n state.model = event.message.model;\n state.inputTokens = event.message.usage.input_tokens;\n state.cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;\n state.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;\n return { type: 'message_start', index: 0, delta: {} };\n\n case 'content_block_start':\n if (event.content_block.type === 'text') {\n state.content[event.index] = { type: 'text', text: '' };\n } else if (event.content_block.type === 'tool_use') {\n state.content[event.index] = {\n type: 'tool_use',\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n };\n }\n return { type: 'content_block_start', index: event.index, delta: {} };\n\n case 'content_block_delta': {\n const delta = event.delta;\n if (delta.type === 'text_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.text =\n (state.content[event.index]!.text ?? '') + delta.text;\n }\n return {\n type: 'text_delta',\n index: event.index,\n delta: { text: delta.text },\n };\n }\n if (delta.type === 'input_json_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.input =\n (state.content[event.index]!.input ?? '') + delta.partial_json;\n }\n return {\n type: 'tool_call_delta',\n index: event.index,\n delta: {\n argumentsJson: delta.partial_json,\n toolCallId: state.content[event.index]?.id,\n toolName: state.content[event.index]?.name,\n },\n };\n }\n if (delta.type === 'thinking_delta') {\n return {\n type: 'reasoning_delta',\n index: event.index,\n delta: { text: delta.thinking },\n };\n }\n return null;\n }\n\n case 'content_block_stop':\n return { type: 'content_block_stop', index: event.index, delta: {} };\n\n case 'message_delta':\n state.stopReason = event.delta.stop_reason;\n state.outputTokens = event.usage.output_tokens;\n return null;\n\n case 'message_stop':\n return { type: 'message_stop', index: 0, delta: {} };\n\n case 'ping':\n case 'error':\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Builds a complete LLMResponse from accumulated stream state.\n *\n * Call this after all stream events have been processed to construct\n * the final response. Parses accumulated JSON for tool call arguments\n * and extracts structured output data.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n *\n * @see {@link createStreamState} for initializing state\n * @see {@link transformStreamEvent} for populating state from events\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of state.content) {\n if (block.type === 'text' && block.text) {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use' && block.id && block.name) {\n let args: Record<string, unknown> = {};\n if (block.input) {\n try {\n args = JSON.parse(block.input);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n if (block.name === 'json_response') {\n structuredData = args;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.messageId,\n metadata: {\n anthropic: {\n stop_reason: state.stopReason,\n model: state.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: state.cacheWriteTokens,\n };\n\n return {\n message,\n usage,\n stopReason: state.stopReason ?? 'end_turn',\n data: structuredData,\n };\n}\n","/**\n * @fileoverview Anthropic LLM handler implementation.\n *\n * This module provides the core LLM handler for Anthropic's Claude models,\n * implementing both synchronous completion and streaming capabilities.\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { AnthropicLLMParams, AnthropicResponse, AnthropicStreamEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for the Anthropic Messages API. */\nconst ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';\n\n/** Default Anthropic API version header value. */\nconst ANTHROPIC_VERSION = '2023-06-01';\n\n/**\n * Capability flags for Anthropic Claude models.\n *\n * Defines what features are supported by the Anthropic provider:\n * - streaming: Real-time token generation via SSE\n * - tools: Function calling / tool use\n * - structuredOutput: JSON schema-constrained responses (via tool forcing)\n * - imageInput: Vision capabilities for image analysis\n */\nconst ANTHROPIC_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an Anthropic LLM handler for the Universal Provider Protocol.\n *\n * The handler provides methods to bind specific Claude models and make\n * completion requests. It handles API authentication, request transformation,\n * and response parsing.\n *\n * @returns An LLMHandler configured for Anthropic's Messages API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('claude-sonnet-4-20250514');\n *\n * const response = await model.complete({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: process.env.ANTHROPIC_API_KEY },\n * });\n * ```\n */\nexport function createLLMHandler(): LLMHandler<AnthropicLLMParams> {\n let providerRef: LLMProvider<AnthropicLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<AnthropicLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<AnthropicLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'anthropic',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<AnthropicLLMParams> = {\n modelId,\n capabilities: ANTHROPIC_CAPABILITIES,\n\n get provider(): LLMProvider<AnthropicLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<AnthropicLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n const data = (await response.json()) as AnthropicResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<AnthropicLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'anthropic', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (typeof data === 'object' && data !== null && 'type' in data) {\n const event = data as AnthropicStreamEvent;\n\n if (event.type === 'error') {\n const error = new UPPError(\n event.error.message,\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvent = transformStreamEvent(event, state);\n if (uppEvent) {\n yield uppEvent;\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Anthropic provider instance for the Universal Provider Protocol.\n *\n * Provides access to Claude language models through a unified interface.\n * Currently supports the LLM modality with full streaming, tool use,\n * structured output, and image input capabilities.\n *\n * @example\n * ```typescript\n * import { anthropic } from './providers/anthropic';\n *\n * const claude = anthropic.llm.bind('claude-sonnet-4-20250514');\n * const response = await claude.complete({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: 'sk-...' },\n * });\n * ```\n *\n * @see {@link AnthropicLLMParams} for provider-specific parameters\n */\nexport const anthropic = createProvider({\n name: 'anthropic',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\nexport type { AnthropicLLMParams } from './types.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA0DO,SAAS,iBACd,SACA,SACkB;AAClB,QAAM,SAAU,QAAQ,UAAU,CAAC;AAEnC,QAAM,mBAAqC;AAAA,IACzC,GAAG;AAAA,IACH,OAAO;AAAA,IACP,UAAU,QAAQ,SAAS,IAAI,gBAAgB;AAAA,EACjD;AAEA,MAAI,QAAQ,QAAQ;AAGlB,qBAAiB,SAAS,QAAQ;AAAA,EACpC;AAEA,MAAI,QAAQ,SAAS,QAAQ,MAAM,SAAS,GAAG;AAE7C,qBAAiB,QAAQ,QAAQ,MAAM,IAAI,aAAa;AACxD,qBAAiB,cAAc,EAAE,MAAM,OAAO;AAAA,EAChD;AAEA,MAAI,QAAQ,WAAW;AACrB,UAAM,iBAAgC;AAAA,MACpC,MAAM;AAAA,MACN,aAAa;AAAA,MACb,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,YAAY,QAAQ,UAAU;AAAA,QAC9B,UAAU,QAAQ,UAAU;AAAA,MAC9B;AAAA,IACF;AAEA,qBAAiB,QAAQ,CAAC,GAAI,iBAAiB,SAAS,CAAC,GAAI,cAAc;AAC3E,qBAAiB,cAAc,EAAE,MAAM,QAAQ,MAAM,gBAAgB;AAAA,EACvE;AAEA,SAAO;AACT;AAQA,SAAS,mBAAgD,SAAmB;AAC1E,SAAO,QAAQ,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AAC9D;AAQA,SAAS,oBAAoB,SAAqD;AAChF,QAAM,gBAAgB,QAAQ,UAAU;AAGxC,SAAO,eAAe;AACxB;AAqBA,SAAS,iBAAiB,SAAoC;AAC5D,QAAM,eAAe,oBAAoB,OAAO;AAEhD,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,eAAe,mBAAmB,QAAQ,OAAO;AACvD,UAAM,gBAAgB,aAAa;AAAA,MAAI,CAAC,OAAO,OAAO,QACpD,sBAAsB,OAAO,UAAU,IAAI,SAAS,IAAI,eAAe,MAAS;AAAA,IAClF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,mBAAmB,OAAO,GAAG;AAC/B,UAAM,eAAe,mBAAmB,QAAQ,OAAO;AACvD,UAAM,UAA8B,aAAa;AAAA,MAAI,CAAC,OAAO,OAAO,QAClE,sBAAsB,OAAO,UAAU,IAAI,SAAS,KAAK,CAAC,QAAQ,WAAW,SAAS,eAAe,MAAS;AAAA,IAChH;AAEA,QAAI,QAAQ,WAAW;AACrB,eAAS,IAAI,GAAG,IAAI,QAAQ,UAAU,QAAQ,KAAK;AACjD,cAAM,OAAO,QAAQ,UAAU,CAAC;AAChC,cAAM,SAAS,MAAM,QAAQ,UAAU,SAAS;AAChD,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN,IAAI,KAAK;AAAA,UACT,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,GAAI,UAAU,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,QAClE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,MAAI,oBAAoB,OAAO,GAAG;AAChC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,QAAQ,QAAQ,IAAI,CAAC,QAAQ,OAAO,SAAS;AAAA,QACpD,MAAM;AAAA,QACN,aAAa,OAAO;AAAA,QACpB,SACE,OAAO,OAAO,WAAW,WACrB,OAAO,SACP,KAAK,UAAU,OAAO,MAAM;AAAA,QAClC,UAAU,OAAO;AAAA,QACjB,GAAI,UAAU,IAAI,SAAS,KAAK,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,MACpF,EAAE;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,yBAAyB,QAAQ,IAAI,EAAE;AACzD;AAaA,SAAS,sBACP,OACA,cACkB;AAClB,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,MAAM;AAAA,QACZ,GAAI,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,MACxD;AAAA,IAEF,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,UAAI,WAAW,OAAO,SAAS,UAAU;AACvC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,YAAY,WAAW;AAAA,YACvB,MAAM,WAAW,OAAO;AAAA,UAC1B;AAAA,UACA,GAAI,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,QACxD;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS,OAAO;AACpC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,KAAK,WAAW,OAAO;AAAA,UACzB;AAAA,UACA,GAAI,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,QACxD;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS,SAAS;AACtC,cAAM,SAAS;AAAA,UACb,MAAM,KAAK,WAAW,OAAO,IAAI,EAC9B,IAAI,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC,EACjC,KAAK,EAAE;AAAA,QACZ;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,YAAY,WAAW;AAAA,YACvB,MAAM;AAAA,UACR;AAAA,UACA,GAAI,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,QACxD;AAAA,MACF;AACA,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAAA,IAEA;AACE,YAAM,IAAI,MAAM,6BAA6B,MAAM,IAAI,EAAE;AAAA,EAC7D;AACF;AAQA,SAAS,wBAAwB,MAA+C;AAC9E,QAAM,gBAAgB,KAAK,UAAU;AAGrC,SAAO,eAAe;AACxB;AAmBA,SAAS,cAAc,MAA2B;AAChD,QAAM,eAAe,wBAAwB,IAAI;AAEjD,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,YAAY,KAAK,WAAW;AAAA,MAC5B,UAAU,KAAK,WAAW;AAAA,IAC5B;AAAA,IACA,GAAI,eAAe,EAAE,eAAe,aAAa,IAAI,CAAC;AAAA,EACxD;AACF;AAcO,SAAS,kBAAkB,MAAsC;AACtE,QAAM,cAA2B,CAAC;AAClC,QAAM,YAAwB,CAAC;AAC/B,MAAI;AAEJ,aAAW,SAAS,KAAK,SAAS;AAChC,QAAI,MAAM,SAAS,QAAQ;AACzB,kBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC;AAAA,IACrD,WAAW,MAAM,SAAS,YAAY;AACpC,UAAI,MAAM,SAAS,iBAAiB;AAClC,yBAAiB,MAAM;AAAA,MACzB;AACA,gBAAU,KAAK;AAAA,QACb,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI,KAAK;AAAA,MACT,UAAU;AAAA,QACR,WAAW;AAAA,UACT,aAAa,KAAK;AAAA,UAClB,eAAe,KAAK;AAAA,UACpB,OAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,KAAK,MAAM;AAAA,IACxB,cAAc,KAAK,MAAM;AAAA,IACzB,aAAa,KAAK,MAAM,eAAe,KAAK,MAAM;AAAA,IAClD,iBAAiB,KAAK,MAAM,2BAA2B;AAAA,IACvD,kBAAkB,KAAK,MAAM,+BAA+B;AAAA,EAC9D;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,KAAK,eAAe;AAAA,IAChC,MAAM;AAAA,EACR;AACF;AAgCO,SAAS,oBAAiC;AAC/C,SAAO;AAAA,IACL,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS,CAAC;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,EACpB;AACF;AAyBO,SAAS,qBACd,OACA,OACoB;AACpB,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,YAAM,YAAY,MAAM,QAAQ;AAChC,YAAM,QAAQ,MAAM,QAAQ;AAC5B,YAAM,cAAc,MAAM,QAAQ,MAAM;AACxC,YAAM,kBAAkB,MAAM,QAAQ,MAAM,2BAA2B;AACvE,YAAM,mBAAmB,MAAM,QAAQ,MAAM,+BAA+B;AAC5E,aAAO,EAAE,MAAM,iBAAiB,OAAO,GAAG,OAAO,CAAC,EAAE;AAAA,IAEtD,KAAK;AACH,UAAI,MAAM,cAAc,SAAS,QAAQ;AACvC,cAAM,QAAQ,MAAM,KAAK,IAAI,EAAE,MAAM,QAAQ,MAAM,GAAG;AAAA,MACxD,WAAW,MAAM,cAAc,SAAS,YAAY;AAClD,cAAM,QAAQ,MAAM,KAAK,IAAI;AAAA,UAC3B,MAAM;AAAA,UACN,IAAI,MAAM,cAAc;AAAA,UACxB,MAAM,MAAM,cAAc;AAAA,UAC1B,OAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO,EAAE,MAAM,uBAAuB,OAAO,MAAM,OAAO,OAAO,CAAC,EAAE;AAAA,IAEtE,KAAK,uBAAuB;AAC1B,YAAM,QAAQ,MAAM;AACpB,UAAI,MAAM,SAAS,cAAc;AAC/B,YAAI,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC9B,gBAAM,QAAQ,MAAM,KAAK,EAAG,QACzB,MAAM,QAAQ,MAAM,KAAK,EAAG,QAAQ,MAAM,MAAM;AAAA,QACrD;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,OAAO,EAAE,MAAM,MAAM,KAAK;AAAA,QAC5B;AAAA,MACF;AACA,UAAI,MAAM,SAAS,oBAAoB;AACrC,YAAI,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC9B,gBAAM,QAAQ,MAAM,KAAK,EAAG,SACzB,MAAM,QAAQ,MAAM,KAAK,EAAG,SAAS,MAAM,MAAM;AAAA,QACtD;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,OAAO;AAAA,YACL,eAAe,MAAM;AAAA,YACrB,YAAY,MAAM,QAAQ,MAAM,KAAK,GAAG;AAAA,YACxC,UAAU,MAAM,QAAQ,MAAM,KAAK,GAAG;AAAA,UACxC;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,SAAS,kBAAkB;AACnC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,OAAO,EAAE,MAAM,MAAM,SAAS;AAAA,QAChC;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IAEA,KAAK;AACH,aAAO,EAAE,MAAM,sBAAsB,OAAO,MAAM,OAAO,OAAO,CAAC,EAAE;AAAA,IAErE,KAAK;AACH,YAAM,aAAa,MAAM,MAAM;AAC/B,YAAM,eAAe,MAAM,MAAM;AACjC,aAAO;AAAA,IAET,KAAK;AACH,aAAO,EAAE,MAAM,gBAAgB,OAAO,GAAG,OAAO,CAAC,EAAE;AAAA,IAErD,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET;AACE,aAAO;AAAA,EACX;AACF;AAeO,SAAS,uBAAuB,OAAiC;AACtE,QAAM,cAA2B,CAAC;AAClC,QAAM,YAAwB,CAAC;AAC/B,MAAI;AAEJ,aAAW,SAAS,MAAM,SAAS;AACjC,QAAI,MAAM,SAAS,UAAU,MAAM,MAAM;AACvC,kBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC;AAAA,IACrD,WAAW,MAAM,SAAS,cAAc,MAAM,MAAM,MAAM,MAAM;AAC9D,UAAI,OAAgC,CAAC;AACrC,UAAI,MAAM,OAAO;AACf,YAAI;AACF,iBAAO,KAAK,MAAM,MAAM,KAAK;AAAA,QAC/B,QAAQ;AAAA,QAER;AAAA,MACF;AACA,UAAI,MAAM,SAAS,iBAAiB;AAClC,yBAAiB;AAAA,MACnB;AACA,gBAAU,KAAK;AAAA,QACb,YAAY,MAAM;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,IAAI,MAAM;AAAA,MACV,UAAU;AAAA,QACR,WAAW;AAAA,UACT,aAAa,MAAM;AAAA,UACnB,OAAO,MAAM;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM,cAAc,MAAM;AAAA,IACvC,iBAAiB,MAAM;AAAA,IACvB,kBAAkB,MAAM;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM,cAAc;AAAA,IAChC,MAAM;AAAA,EACR;AACF;;;AC7jBA,IAAM,oBAAoB;AAG1B,IAAM,oBAAoB;AAW1B,IAAM,yBAA0C;AAAA,EAC9C,WAAW;AAAA,EACX,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AACd;AAsBO,SAAS,mBAAmD;AACjE,MAAI,cAAsD;AAE1D,SAAO;AAAA,IACL,aAAa,UAA2C;AACtD,oBAAc;AAAA,IAChB;AAAA,IAEA,KAAK,SAAoD;AACvD,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAA2C;AAAA,QAC/C;AAAA,QACA,cAAc;AAAA,QAEd,IAAI,WAA4C;AAC9C,iBAAO;AAAA,QACT;AAAA,QAEA,MAAM,SAAS,SAA+D;AAC5E,gBAAM,SAAS,MAAM;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,UAAU,QAAQ,OAAO,WAAW;AAC1C,gBAAM,OAAO,iBAAiB,SAAS,OAAO;AAE9C,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,cACE,QAAQ;AAAA,cACR,SAAS;AAAA,gBACP,gBAAgB;AAAA,gBAChB,aAAa;AAAA,gBACb,qBAAqB,QAAQ,OAAO,cAAc;AAAA,cACpD;AAAA,cACA,MAAM,KAAK,UAAU,IAAI;AAAA,cACzB,QAAQ,QAAQ;AAAA,YAClB;AAAA,YACA,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,iBAAO,kBAAkB,IAAI;AAAA,QAC/B;AAAA,QAEA,OAAO,SAA0D;AAC/D,gBAAM,QAAQ,kBAAkB;AAChC,cAAI;AACJ,cAAI;AAEJ,gBAAM,kBAAkB,IAAI,QAAqB,CAAC,SAAS,WAAW;AACpE,8BAAkB;AAClB,6BAAiB;AAAA,UACnB,CAAC;AAED,0BAAgB,iBAA6D;AAC3E,gBAAI;AACF,oBAAM,SAAS,MAAM;AAAA,gBACnB,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAEA,oBAAM,UAAU,QAAQ,OAAO,WAAW;AAC1C,oBAAM,OAAO,iBAAiB,SAAS,OAAO;AAC9C,mBAAK,SAAS;AAEd,oBAAM,WAAW,MAAM;AAAA,gBACrB;AAAA,gBACA;AAAA,kBACE,QAAQ;AAAA,kBACR,SAAS;AAAA,oBACP,gBAAgB;AAAA,oBAChB,aAAa;AAAA,oBACb,qBAAqB,QAAQ,OAAO,cAAc;AAAA,kBACpD;AAAA,kBACA,MAAM,KAAK,UAAU,IAAI;AAAA,kBACzB,QAAQ,QAAQ;AAAA,gBAClB;AAAA,gBACA,QAAQ;AAAA,gBACR;AAAA,gBACA;AAAA,cACF;AAEA,kBAAI,CAAC,SAAS,IAAI;AAChB,sBAAM,QAAQ,MAAM,mBAAmB,UAAU,aAAa,KAAK;AACnE,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,kBAAI,CAAC,SAAS,MAAM;AAClB,sBAAM,QAAQ,IAAI;AAAA,kBAChB;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AACA,+BAAe,KAAK;AACpB,sBAAM;AAAA,cACR;AAEA,+BAAiB,QAAQ,eAAe,SAAS,IAAI,GAAG;AACtD,oBAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU,MAAM;AAC/D,wBAAM,QAAQ;AAEd,sBAAI,MAAM,SAAS,SAAS;AAC1B,0BAAM,QAAQ,IAAI;AAAA,sBAChB,MAAM,MAAM;AAAA,sBACZ;AAAA,sBACA;AAAA,sBACA;AAAA,oBACF;AACA,mCAAe,KAAK;AACpB,0BAAM;AAAA,kBACR;AAEA,wBAAM,WAAW,qBAAqB,OAAO,KAAK;AAClD,sBAAI,UAAU;AACZ,0BAAM;AAAA,kBACR;AAAA,gBACF;AAAA,cACF;AAEA,8BAAgB,uBAAuB,KAAK,CAAC;AAAA,YAC/C,SAAS,OAAO;AACd,6BAAe,KAAc;AAC7B,oBAAM;AAAA,YACR;AAAA,UACF;AAEA,iBAAO;AAAA,YACL,CAAC,OAAO,aAAa,IAAI;AACvB,qBAAO,eAAe;AAAA,YACxB;AAAA,YACA,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;ACzMO,IAAM,YAAY,eAAe;AAAA,EACtC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,YAAY;AAAA,IACV,KAAK,iBAAiB;AAAA,EACxB;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/providers/anthropic/transform.ts","../../src/providers/anthropic/llm.ts","../../src/providers/anthropic/index.ts"],"sourcesContent":["/**\n * @fileoverview UPP to Anthropic message transformation utilities.\n *\n * This module handles bidirectional conversion between Universal Provider Protocol\n * message formats and Anthropic's native API structures. It supports:\n * - Request transformation (UPP -> Anthropic)\n * - Response transformation (Anthropic -> UPP)\n * - Stream event transformation for real-time responses\n * - Tool call and structured output handling\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n AnthropicLLMParams,\n AnthropicRequest,\n AnthropicMessage,\n AnthropicContent,\n AnthropicTool,\n AnthropicResponse,\n AnthropicStreamEvent,\n AnthropicCacheControl,\n AnthropicSystemContent,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request to Anthropic's native API format.\n *\n * Handles conversion of messages, system prompts, tools, and structured output\n * configuration. Parameters are spread directly to enable pass-through of any\n * Anthropic API fields, even those not explicitly defined in our types.\n *\n * @typeParam TParams - Anthropic-specific parameters extending AnthropicLLMParams\n * @param request - The UPP-formatted LLM request\n * @param modelId - The Anthropic model identifier (e.g., 'claude-sonnet-4-20250514')\n * @returns An AnthropicRequest ready for the Messages API\n *\n * @example\n * ```typescript\n * const anthropicRequest = transformRequest({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: 'sk-...' },\n * params: { max_tokens: 1024, temperature: 0.7 },\n * }, 'claude-sonnet-4-20250514');\n * ```\n *\n * @see {@link transformResponse} for the reverse transformation\n */\nexport function transformRequest<TParams extends AnthropicLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): AnthropicRequest {\n const params = (request.params ?? {}) as AnthropicLLMParams;\n\n const anthropicRequest: AnthropicRequest = {\n ...params,\n model: modelId,\n messages: request.messages.map(transformMessage),\n };\n\n if (request.system) {\n // Pass through directly - accepts string or array of AnthropicSystemContent\n // Array format enables cache_control: [{type: 'text', text: '...', cache_control: {...}}]\n anthropicRequest.system = request.system as string | AnthropicSystemContent[];\n }\n\n if (request.tools && request.tools.length > 0) {\n // For tool caching, use params.tools directly with native Anthropic format\n anthropicRequest.tools = request.tools.map(transformTool);\n anthropicRequest.tool_choice = { type: 'auto' };\n }\n\n if (request.structure) {\n const structuredTool: AnthropicTool = {\n name: 'json_response',\n description: 'Return the response in the specified JSON format. You MUST use this tool to provide your response.',\n input_schema: {\n type: 'object',\n properties: request.structure.properties,\n required: request.structure.required,\n },\n };\n\n anthropicRequest.tools = [...(anthropicRequest.tools ?? []), structuredTool];\n anthropicRequest.tool_choice = { type: 'tool', name: 'json_response' };\n }\n\n return anthropicRequest;\n}\n\n/**\n * Filters content blocks to include only those with a valid type property.\n *\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with a string type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Extracts cache control configuration from message metadata.\n *\n * @param message - The message to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractCacheControl(message: Message): AnthropicCacheControl | undefined {\n const anthropicMeta = message.metadata?.anthropic as\n | { cache_control?: AnthropicCacheControl }\n | undefined;\n return anthropicMeta?.cache_control;\n}\n\n/**\n * Transforms a UPP Message to Anthropic's message format.\n *\n * Handles three message types:\n * - UserMessage: Converted with content blocks\n * - AssistantMessage: Includes text and tool_use blocks\n * - ToolResultMessage: Converted to user role with tool_result content\n *\n * Cache control can be specified via message metadata:\n * ```typescript\n * new UserMessage(content, {\n * metadata: { anthropic: { cache_control: { type: \"ephemeral\" } } }\n * })\n * ```\n *\n * @param message - The UPP message to transform\n * @returns An AnthropicMessage with the appropriate role and content\n * @throws Error if the message type is unknown\n */\nfunction transformMessage(message: Message): AnthropicMessage {\n const cacheControl = extractCacheControl(message);\n\n if (isUserMessage(message)) {\n const validContent = filterValidContent(message.content);\n const contentBlocks = validContent.map((block, index, arr) =>\n transformContentBlock(block, index === arr.length - 1 ? cacheControl : undefined)\n );\n return {\n role: 'user',\n content: contentBlocks,\n };\n }\n\n if (isAssistantMessage(message)) {\n const validContent = filterValidContent(message.content);\n const content: AnthropicContent[] = validContent.map((block, index, arr) =>\n transformContentBlock(block, index === arr.length - 1 && !message.toolCalls?.length ? cacheControl : undefined)\n );\n\n if (message.toolCalls) {\n for (let i = 0; i < message.toolCalls.length; i++) {\n const call = message.toolCalls[i]!;\n const isLast = i === message.toolCalls.length - 1;\n content.push({\n type: 'tool_use',\n id: call.toolCallId,\n name: call.toolName,\n input: call.arguments,\n ...(isLast && cacheControl ? { cache_control: cacheControl } : {}),\n });\n }\n }\n\n return {\n role: 'assistant',\n content,\n };\n }\n\n if (isToolResultMessage(message)) {\n return {\n role: 'user',\n content: message.results.map((result, index, arr) => ({\n type: 'tool_result' as const,\n tool_use_id: result.toolCallId,\n content:\n typeof result.result === 'string'\n ? result.result\n : JSON.stringify(result.result),\n is_error: result.isError,\n ...(index === arr.length - 1 && cacheControl ? { cache_control: cacheControl } : {}),\n })),\n };\n }\n\n throw new Error(`Unknown message type: ${message.type}`);\n}\n\n/**\n * Transforms a UPP ContentBlock to Anthropic's content format.\n *\n * Supports text and image content types. Image blocks can be provided\n * as base64, URL, or raw bytes (which are converted to base64).\n *\n * @param block - The UPP content block to transform\n * @param cacheControl - Optional cache control to apply to the block\n * @returns An AnthropicContent object\n * @throws Error if the content type or image source type is unsupported\n */\nfunction transformContentBlock(\n block: ContentBlock,\n cacheControl?: AnthropicCacheControl\n): AnthropicContent {\n switch (block.type) {\n case 'text':\n return {\n type: 'text',\n text: block.text,\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n if (imageBlock.source.type === 'base64') {\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: imageBlock.source.data,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n if (imageBlock.source.type === 'url') {\n return {\n type: 'image',\n source: {\n type: 'url',\n url: imageBlock.source.url,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n if (imageBlock.source.type === 'bytes') {\n const base64 = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n return {\n type: 'image',\n source: {\n type: 'base64',\n media_type: imageBlock.mimeType,\n data: base64,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n }\n throw new Error(`Unknown image source type`);\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Extracts cache control configuration from tool metadata.\n *\n * @param tool - The tool to extract cache control from\n * @returns The cache control configuration if present, undefined otherwise\n */\nfunction extractToolCacheControl(tool: Tool): AnthropicCacheControl | undefined {\n const anthropicMeta = tool.metadata?.anthropic as\n | { cache_control?: AnthropicCacheControl }\n | undefined;\n return anthropicMeta?.cache_control;\n}\n\n/**\n * Transforms a UPP Tool definition to Anthropic's tool format.\n *\n * Cache control can be specified via tool metadata:\n * ```typescript\n * const tool: Tool = {\n * name: 'search_docs',\n * description: 'Search documentation',\n * parameters: {...},\n * metadata: { anthropic: { cache_control: { type: 'ephemeral' } } },\n * run: async (params) => {...}\n * };\n * ```\n *\n * @param tool - The UPP tool definition\n * @returns An AnthropicTool with the appropriate input schema\n */\nfunction transformTool(tool: Tool): AnthropicTool {\n const cacheControl = extractToolCacheControl(tool);\n\n return {\n name: tool.name,\n description: tool.description,\n input_schema: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n };\n}\n\n/**\n * Transforms an Anthropic API response to UPP's LLMResponse format.\n *\n * Extracts text content, tool calls, and structured output data from\n * Anthropic's response. The json_response tool is treated specially\n * for structured output extraction.\n *\n * @param data - The raw Anthropic API response\n * @returns A UPP LLMResponse with message, usage, and optional structured data\n *\n * @see {@link transformRequest} for the request transformation\n */\nexport function transformResponse(data: AnthropicResponse): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of data.content) {\n if (block.type === 'text') {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use') {\n if (block.name === 'json_response') {\n structuredData = block.input;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: block.input,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: data.id,\n metadata: {\n anthropic: {\n stop_reason: data.stop_reason,\n stop_sequence: data.stop_sequence,\n model: data.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.input_tokens + data.usage.output_tokens,\n cacheReadTokens: data.usage.cache_read_input_tokens ?? 0,\n cacheWriteTokens: data.usage.cache_creation_input_tokens ?? 0,\n };\n\n return {\n message,\n usage,\n stopReason: data.stop_reason ?? 'end_turn',\n data: structuredData,\n };\n}\n\n/**\n * Mutable state object for accumulating streamed response data.\n *\n * Used during streaming to collect content blocks, token counts, and\n * metadata as events arrive from the Anthropic API.\n */\nexport interface StreamState {\n /** Unique identifier for the message being streamed. */\n messageId: string;\n /** The model that generated this response. */\n model: string;\n /** Accumulated content blocks indexed by their stream position. */\n content: Array<{ type: string; text?: string; id?: string; name?: string; input?: string }>;\n /** The reason the response ended, if completed. */\n stopReason: string | null;\n /** Number of input tokens consumed. */\n inputTokens: number;\n /** Number of output tokens generated. */\n outputTokens: number;\n /** Number of tokens read from cache (cache hits). */\n cacheReadTokens: number;\n /** Number of tokens written to cache. */\n cacheWriteTokens: number;\n}\n\n/**\n * Creates an initialized StreamState for accumulating streaming responses.\n *\n * @returns A fresh StreamState with empty/default values\n */\nexport function createStreamState(): StreamState {\n return {\n messageId: '',\n model: '',\n content: [],\n stopReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheWriteTokens: 0,\n };\n}\n\n/**\n * Transforms an Anthropic streaming event to a UPP StreamEvent.\n *\n * Updates the provided state object as a side effect to accumulate\n * response data across multiple events. Returns null for events that\n * don't produce corresponding UPP events (e.g., ping, message_delta).\n *\n * @param event - The Anthropic SSE event to transform\n * @param state - Mutable state object to update with accumulated data\n * @returns A UPP StreamEvent, or null if no event should be emitted\n *\n * @example\n * ```typescript\n * const state = createStreamState();\n * for await (const event of parseSSEStream(response.body)) {\n * const uppEvent = transformStreamEvent(event, state);\n * if (uppEvent) {\n * yield uppEvent;\n * }\n * }\n * const finalResponse = buildResponseFromState(state);\n * ```\n */\nexport function transformStreamEvent(\n event: AnthropicStreamEvent,\n state: StreamState\n): StreamEvent | null {\n switch (event.type) {\n case 'message_start':\n state.messageId = event.message.id;\n state.model = event.message.model;\n state.inputTokens = event.message.usage.input_tokens;\n state.cacheReadTokens = event.message.usage.cache_read_input_tokens ?? 0;\n state.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;\n return { type: 'message_start', index: 0, delta: {} };\n\n case 'content_block_start':\n if (event.content_block.type === 'text') {\n state.content[event.index] = { type: 'text', text: '' };\n } else if (event.content_block.type === 'tool_use') {\n state.content[event.index] = {\n type: 'tool_use',\n id: event.content_block.id,\n name: event.content_block.name,\n input: '',\n };\n }\n return { type: 'content_block_start', index: event.index, delta: {} };\n\n case 'content_block_delta': {\n const delta = event.delta;\n if (delta.type === 'text_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.text =\n (state.content[event.index]!.text ?? '') + delta.text;\n }\n return {\n type: 'text_delta',\n index: event.index,\n delta: { text: delta.text },\n };\n }\n if (delta.type === 'input_json_delta') {\n if (state.content[event.index]) {\n state.content[event.index]!.input =\n (state.content[event.index]!.input ?? '') + delta.partial_json;\n }\n return {\n type: 'tool_call_delta',\n index: event.index,\n delta: {\n argumentsJson: delta.partial_json,\n toolCallId: state.content[event.index]?.id,\n toolName: state.content[event.index]?.name,\n },\n };\n }\n if (delta.type === 'thinking_delta') {\n return {\n type: 'reasoning_delta',\n index: event.index,\n delta: { text: delta.thinking },\n };\n }\n return null;\n }\n\n case 'content_block_stop':\n return { type: 'content_block_stop', index: event.index, delta: {} };\n\n case 'message_delta':\n state.stopReason = event.delta.stop_reason;\n state.outputTokens = event.usage.output_tokens;\n return null;\n\n case 'message_stop':\n return { type: 'message_stop', index: 0, delta: {} };\n\n case 'ping':\n case 'error':\n return null;\n\n default:\n return null;\n }\n}\n\n/**\n * Builds a complete LLMResponse from accumulated stream state.\n *\n * Call this after all stream events have been processed to construct\n * the final response. Parses accumulated JSON for tool call arguments\n * and extracts structured output data.\n *\n * @param state - The accumulated stream state\n * @returns A complete UPP LLMResponse\n *\n * @see {@link createStreamState} for initializing state\n * @see {@link transformStreamEvent} for populating state from events\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n\n for (const block of state.content) {\n if (block.type === 'text' && block.text) {\n textContent.push({ type: 'text', text: block.text });\n } else if (block.type === 'tool_use' && block.id && block.name) {\n let args: Record<string, unknown> = {};\n if (block.input) {\n try {\n args = JSON.parse(block.input);\n } catch {\n // Invalid JSON - use empty object\n }\n }\n if (block.name === 'json_response') {\n structuredData = args;\n }\n toolCalls.push({\n toolCallId: block.id,\n toolName: block.name,\n arguments: args,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n id: state.messageId,\n metadata: {\n anthropic: {\n stop_reason: state.stopReason,\n model: state.model,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: state.cacheWriteTokens,\n };\n\n return {\n message,\n usage,\n stopReason: state.stopReason ?? 'end_turn',\n data: structuredData,\n };\n}\n","/**\n * @fileoverview Anthropic LLM handler implementation.\n *\n * This module provides the core LLM handler for Anthropic's Claude models,\n * implementing both synchronous completion and streaming capabilities.\n */\n\nimport type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { AnthropicLLMParams, AnthropicResponse, AnthropicStreamEvent } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamEvent,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for the Anthropic Messages API. */\nconst ANTHROPIC_API_URL = 'https://api.anthropic.com/v1/messages';\n\n/** Default Anthropic API version header value. */\nconst ANTHROPIC_VERSION = '2023-06-01';\n\n/**\n * Capability flags for Anthropic Claude models.\n *\n * Defines what features are supported by the Anthropic provider:\n * - streaming: Real-time token generation via SSE\n * - tools: Function calling / tool use\n * - structuredOutput: JSON schema-constrained responses (via tool forcing)\n * - imageInput: Vision capabilities for image analysis\n */\nconst ANTHROPIC_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: false,\n audioInput: false,\n};\n\n/**\n * Creates an Anthropic LLM handler for the Universal Provider Protocol.\n *\n * The handler provides methods to bind specific Claude models and make\n * completion requests. It handles API authentication, request transformation,\n * and response parsing.\n *\n * @returns An LLMHandler configured for Anthropic's Messages API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('claude-sonnet-4-20250514');\n *\n * const response = await model.complete({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: process.env.ANTHROPIC_API_KEY },\n * });\n * ```\n */\nexport function createLLMHandler(): LLMHandler<AnthropicLLMParams> {\n let providerRef: LLMProvider<AnthropicLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<AnthropicLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<AnthropicLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'anthropic',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<AnthropicLLMParams> = {\n modelId,\n capabilities: ANTHROPIC_CAPABILITIES,\n\n get provider(): LLMProvider<AnthropicLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<AnthropicLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n const data = (await response.json()) as AnthropicResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<AnthropicLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'ANTHROPIC_API_KEY',\n 'anthropic',\n 'llm'\n );\n\n const baseUrl = request.config.baseUrl ?? ANTHROPIC_API_URL;\n const body = transformRequest(request, modelId);\n body.stream = true;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'anthropic-version': request.config.apiVersion ?? ANTHROPIC_VERSION,\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n baseUrl,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'anthropic',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'anthropic', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (typeof data === 'object' && data !== null && 'type' in data) {\n const event = data as AnthropicStreamEvent;\n\n if (event.type === 'error') {\n const error = new UPPError(\n event.error.message,\n 'PROVIDER_ERROR',\n 'anthropic',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const uppEvent = transformStreamEvent(event, state);\n if (uppEvent) {\n yield uppEvent;\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Anthropic provider instance for the Universal Provider Protocol.\n *\n * Provides access to Claude language models through a unified interface.\n * Currently supports the LLM modality with full streaming, tool use,\n * structured output, and image input capabilities.\n *\n * @example\n * ```typescript\n * import { anthropic } from './providers/anthropic';\n *\n * const claude = anthropic.llm.bind('claude-sonnet-4-20250514');\n * const response = await claude.complete({\n * messages: [new UserMessage([{ type: 'text', text: 'Hello!' }])],\n * config: { apiKey: 'sk-...' },\n * });\n * ```\n *\n * @see {@link AnthropicLLMParams} for provider-specific parameters\n */\nexport const anthropic = createProvider({\n name: 'anthropic',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\nexport type { AnthropicLLMParams, AnthropicHeaders } from './types.ts';\n"],"mappings":"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","names":[]}
@@ -1,4 +1,4 @@
1
- import { b as Provider } from '../provider-mKkz7Q9U.js';
1
+ import { b as Provider } from '../provider-Bi0nyNhA.js';
2
2
 
3
3
  /**
4
4
  * Provider-specific parameters for Google Gemini API requests.
@@ -250,7 +250,7 @@ interface GoogleCacheListResponse {
250
250
  interface CacheCreateOptions {
251
251
  /** API key for authentication */
252
252
  apiKey: string;
253
- /** Model to associate with this cache (e.g., "gemini-1.5-flash-001") */
253
+ /** Model to associate with this cache (e.g., "gemini-3-flash-preview") */
254
254
  model: string;
255
255
  /** Optional display name for the cache (max 128 chars) */
256
256
  displayName?: string;
@@ -293,7 +293,7 @@ interface CacheListOptions {
293
293
  * // Create a cache with system instruction and large context
294
294
  * const cache = await google.cache.create({
295
295
  * apiKey: process.env.GOOGLE_API_KEY,
296
- * model: 'gemini-1.5-flash-001',
296
+ * model: 'gemini-3-flash-preview',
297
297
  * displayName: 'Code Review Context',
298
298
  * systemInstruction: 'You are an expert code reviewer...',
299
299
  * contents: [
@@ -404,7 +404,7 @@ declare function update(name: string, updateRequest: GoogleCacheUpdateRequest, a
404
404
  * // Create a cache for repeated context
405
405
  * const cacheEntry = await google.cache.create({
406
406
  * apiKey: process.env.GOOGLE_API_KEY,
407
- * model: 'gemini-1.5-flash-001',
407
+ * model: 'gemini-3-flash-preview',
408
408
  * systemInstruction: 'You are an expert code reviewer...',
409
409
  * contents: [{ role: 'user', parts: [{ text: largeCodebase }] }],
410
410
  * ttl: '3600s',
@@ -372,13 +372,21 @@ function createLLMHandler() {
372
372
  );
373
373
  const url = request.config.baseUrl ? `${request.config.baseUrl}/models/${modelId}:generateContent?key=${apiKey}` : buildUrl(modelId, "generateContent", apiKey);
374
374
  const body = transformRequest(request, modelId);
375
+ const headers = {
376
+ "Content-Type": "application/json"
377
+ };
378
+ if (request.config.headers) {
379
+ for (const [key, value] of Object.entries(request.config.headers)) {
380
+ if (value !== void 0) {
381
+ headers[key] = value;
382
+ }
383
+ }
384
+ }
375
385
  const response = await doFetch(
376
386
  url,
377
387
  {
378
388
  method: "POST",
379
- headers: {
380
- "Content-Type": "application/json"
381
- },
389
+ headers,
382
390
  body: JSON.stringify(body),
383
391
  signal: request.signal
384
392
  },
@@ -407,13 +415,21 @@ function createLLMHandler() {
407
415
  );
408
416
  const url = request.config.baseUrl ? `${request.config.baseUrl}/models/${modelId}:streamGenerateContent?alt=sse&key=${apiKey}` : `${buildUrl(modelId, "streamGenerateContent", apiKey)}&alt=sse`;
409
417
  const body = transformRequest(request, modelId);
418
+ const headers = {
419
+ "Content-Type": "application/json"
420
+ };
421
+ if (request.config.headers) {
422
+ for (const [key, value] of Object.entries(request.config.headers)) {
423
+ if (value !== void 0) {
424
+ headers[key] = value;
425
+ }
426
+ }
427
+ }
410
428
  const response = await doStreamFetch(
411
429
  url,
412
430
  {
413
431
  method: "POST",
414
- headers: {
415
- "Content-Type": "application/json"
416
- },
432
+ headers,
417
433
  body: JSON.stringify(body),
418
434
  signal: request.signal
419
435
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/google/transform.ts","../../src/providers/google/llm.ts","../../src/providers/google/cache.ts","../../src/providers/google/index.ts"],"sourcesContent":["/**\n * @fileoverview Transformation functions between UPP format and Google Gemini API format.\n *\n * This module handles the bidirectional conversion of requests, responses, and\n * streaming chunks between the Unified Provider Protocol (UPP) format and\n * Google's Generative Language API format.\n *\n * Key transformations:\n * - UPP messages with content blocks to Google's parts-based content structure\n * - UPP tools to Google's functionDeclarations format\n * - Google responses back to UPP LLMResponse with proper message types\n * - Streaming chunks to UPP StreamEvents\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n GoogleLLMParams,\n GoogleRequest,\n GoogleContent,\n GooglePart,\n GoogleTool,\n GoogleResponse,\n GoogleStreamChunk,\n GoogleFunctionCallPart,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request into Google Gemini API format.\n *\n * Converts the UPP message structure, system prompt, tools, and generation\n * parameters into Google's expected request body format. Provider-specific\n * parameters are passed through to `generationConfig` to support new API\n * features without library updates.\n *\n * @typeParam TParams - Type extending GoogleLLMParams for provider-specific options\n * @param request - The UPP-formatted LLM request\n * @param modelId - The target Gemini model identifier\n * @returns Google API request body ready for submission\n *\n * @example\n * ```typescript\n * const googleRequest = transformRequest({\n * messages: [{ role: 'user', content: [{ type: 'text', text: 'Hello' }] }],\n * system: 'You are a helpful assistant',\n * params: { temperature: 0.7 },\n * config: { apiKey: '...' },\n * }, 'gemini-1.5-pro');\n * ```\n */\nexport function transformRequest<TParams extends GoogleLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): GoogleRequest {\n const params = (request.params ?? {}) as GoogleLLMParams;\n const { cachedContent, ...generationParams } = params;\n\n const googleRequest: GoogleRequest = {\n contents: transformMessages(request.messages),\n };\n\n if (request.system) {\n if (typeof request.system === 'string') {\n googleRequest.systemInstruction = {\n parts: [{ text: request.system }],\n };\n } else {\n // Array format - pass through as parts: [{text: '...'}, {text: '...'}]\n googleRequest.systemInstruction = {\n parts: request.system as GooglePart[],\n };\n }\n }\n\n const generationConfig: NonNullable<GoogleRequest['generationConfig']> = {\n ...generationParams,\n };\n\n if (request.structure) {\n generationConfig.responseMimeType = 'application/json';\n generationConfig.responseSchema = request.structure as unknown as Record<string, unknown>;\n }\n\n if (Object.keys(generationConfig).length > 0) {\n googleRequest.generationConfig = generationConfig;\n }\n\n if (request.tools && request.tools.length > 0) {\n googleRequest.tools = [\n {\n functionDeclarations: request.tools.map(transformTool),\n },\n ];\n }\n\n if (cachedContent) {\n googleRequest.cachedContent = cachedContent;\n }\n\n return googleRequest;\n}\n\n/**\n * Filters content blocks to only those with a valid type property.\n *\n * @typeParam T - Content block type with optional type property\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with string type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms UPP message array to Google's content format.\n *\n * Handles the conversion of user messages, assistant messages (including\n * tool calls), and tool result messages to Google's role-based content\n * structure with parts arrays.\n *\n * @param messages - Array of UPP-formatted messages\n * @returns Array of Google content objects with role and parts\n */\nfunction transformMessages(messages: Message[]): GoogleContent[] {\n const contents: GoogleContent[] = [];\n\n for (const msg of messages) {\n if (isUserMessage(msg)) {\n const validContent = filterValidContent(msg.content);\n const parts = validContent.map(transformContentBlock);\n if (parts.length === 0) {\n parts.push({ text: '' });\n }\n contents.push({\n role: 'user',\n parts,\n });\n } else if (isAssistantMessage(msg)) {\n const validContent = filterValidContent(msg.content);\n const parts: GooglePart[] = validContent.map(transformContentBlock);\n\n const googleMeta = msg.metadata?.google as {\n functionCallParts?: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }>;\n } | undefined;\n\n if (googleMeta?.functionCallParts && googleMeta.functionCallParts.length > 0) {\n for (const fc of googleMeta.functionCallParts) {\n const part: GoogleFunctionCallPart = {\n functionCall: {\n name: fc.name,\n args: fc.args,\n },\n };\n if (fc.thoughtSignature) {\n part.thoughtSignature = fc.thoughtSignature;\n }\n parts.push(part);\n }\n } else if (msg.toolCalls) {\n for (const call of msg.toolCalls) {\n parts.push({\n functionCall: {\n name: call.toolName,\n args: call.arguments,\n },\n });\n }\n }\n\n if (parts.length === 0) {\n parts.push({ text: '' });\n }\n\n contents.push({\n role: 'model',\n parts,\n });\n } else if (isToolResultMessage(msg)) {\n contents.push({\n role: 'user',\n parts: msg.results.map((result) => ({\n functionResponse: {\n name: result.toolCallId,\n response:\n typeof result.result === 'object'\n ? (result.result as Record<string, unknown>)\n : { result: result.result },\n },\n })),\n });\n }\n }\n\n return contents;\n}\n\n/**\n * Transforms a UPP content block to a Google part.\n *\n * Supports text and image content types. Images must be base64 or bytes\n * encoded; URL sources are not supported by Google's API directly.\n *\n * @param block - The UPP content block to transform\n * @returns Google-formatted part object\n * @throws Error if the content type is unsupported or if an image uses URL source\n */\nfunction transformContentBlock(block: ContentBlock): GooglePart {\n switch (block.type) {\n case 'text':\n return { text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let data: string;\n\n if (imageBlock.source.type === 'base64') {\n data = imageBlock.source.data;\n } else if (imageBlock.source.type === 'bytes') {\n data = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n } else {\n throw new Error('Google API does not support URL image sources directly');\n }\n\n return {\n inlineData: {\n mimeType: imageBlock.mimeType,\n data,\n },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transforms a UPP tool definition to Google's function declaration format.\n *\n * @param tool - The UPP tool definition with name, description, and parameters\n * @returns Google function declaration object\n */\nfunction transformTool(tool: Tool): GoogleTool['functionDeclarations'][0] {\n return {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n };\n}\n\n/**\n * Transforms a Google API response to UPP LLMResponse format.\n *\n * Extracts text content, tool calls, structured data, and usage metadata\n * from Google's response format. Preserves Google-specific metadata like\n * finish reason, safety ratings, and thought signatures for multi-turn\n * tool call conversations.\n *\n * @param data - The raw Google API response\n * @returns Normalized UPP LLMResponse with message, usage, and stop reason\n * @throws Error if response contains no candidates\n *\n * @example\n * ```typescript\n * const response = await fetch(googleApiUrl, options);\n * const data = await response.json();\n * const uppResponse = transformResponse(data);\n * console.log(uppResponse.message.content);\n * ```\n */\nexport function transformResponse(data: GoogleResponse): LLMResponse {\n const candidate = data.candidates?.[0];\n if (!candidate) {\n throw new Error('No candidates in Google response');\n }\n\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n const functionCallParts: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }> = [];\n\n for (const part of candidate.content.parts) {\n if ('text' in part) {\n textContent.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not JSON - may not be structured output\n }\n }\n } else if ('functionCall' in part) {\n const fc = part as GoogleFunctionCallPart;\n toolCalls.push({\n toolCallId: fc.functionCall.name,\n toolName: fc.functionCall.name,\n arguments: fc.functionCall.args,\n });\n functionCallParts.push({\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n thoughtSignature: fc.thoughtSignature,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n metadata: {\n google: {\n finishReason: candidate.finishReason,\n safetyRatings: candidate.safetyRatings,\n functionCallParts: functionCallParts.length > 0 ? functionCallParts : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n totalTokens: data.usageMetadata?.totalTokenCount ?? 0,\n cacheReadTokens: data.usageMetadata?.cachedContentTokenCount ?? 0,\n cacheWriteTokens: 0,\n };\n\n return {\n message,\n usage,\n stopReason: candidate.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n\n/**\n * Accumulator state for streaming responses.\n *\n * Tracks partial content, tool calls, token counts, and stream lifecycle\n * as chunks arrive from the Google streaming API.\n */\nexport interface StreamState {\n /** Accumulated text content from all chunks. */\n content: string;\n /** Accumulated tool calls with their arguments and optional thought signatures. */\n toolCalls: Array<{ name: string; args: Record<string, unknown>; thoughtSignature?: string }>;\n /** The finish reason from the final chunk, if received. */\n finishReason: string | null;\n /** Total input tokens reported by the API. */\n inputTokens: number;\n /** Total output tokens reported by the API. */\n outputTokens: number;\n /** Number of tokens read from cached content. */\n cacheReadTokens: number;\n /** Flag indicating whether this is the first chunk (for message_start event). */\n isFirstChunk: boolean;\n}\n\n/**\n * Creates a fresh stream state for accumulating streaming responses.\n *\n * @returns Initialized StreamState with empty content and default values\n */\nexport function createStreamState(): StreamState {\n return {\n content: '',\n toolCalls: [],\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n isFirstChunk: true,\n };\n}\n\n/**\n * Transforms a Google streaming chunk to UPP StreamEvent array.\n *\n * Processes each streaming chunk, updating the accumulator state and\n * generating appropriate stream events for text deltas, tool calls,\n * and message lifecycle (start/stop).\n *\n * @param chunk - The Google streaming response chunk\n * @param state - Mutable accumulator state updated by this function\n * @returns Array of UPP StreamEvents generated from this chunk\n */\nexport function transformStreamChunk(\n chunk: GoogleStreamChunk,\n state: StreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (state.isFirstChunk) {\n events.push({ type: 'message_start', index: 0, delta: {} });\n state.isFirstChunk = false;\n }\n\n if (chunk.usageMetadata) {\n state.inputTokens = chunk.usageMetadata.promptTokenCount;\n state.outputTokens = chunk.usageMetadata.candidatesTokenCount;\n state.cacheReadTokens = chunk.usageMetadata.cachedContentTokenCount ?? 0;\n }\n\n const candidate = chunk.candidates?.[0];\n if (!candidate) {\n return events;\n }\n\n for (const part of candidate.content?.parts ?? []) {\n if ('text' in part) {\n state.content += part.text;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: part.text },\n });\n } else if ('functionCall' in part) {\n const fc = part as GoogleFunctionCallPart;\n state.toolCalls.push({\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n thoughtSignature: fc.thoughtSignature,\n });\n events.push({\n type: 'tool_call_delta',\n index: state.toolCalls.length - 1,\n delta: {\n toolCallId: fc.functionCall.name,\n toolName: fc.functionCall.name,\n argumentsJson: JSON.stringify(fc.functionCall.args),\n },\n });\n }\n }\n\n if (candidate.finishReason) {\n state.finishReason = candidate.finishReason;\n events.push({ type: 'message_stop', index: 0, delta: {} });\n }\n\n return events;\n}\n\n/**\n * Constructs a complete LLMResponse from accumulated stream state.\n *\n * Called after streaming completes to build the final response object\n * with all accumulated content, tool calls, usage statistics, and metadata.\n *\n * @param state - The final accumulated stream state\n * @returns Complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n const functionCallParts: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }> = [];\n\n if (state.content) {\n textContent.push({ type: 'text', text: state.content });\n try {\n structuredData = JSON.parse(state.content);\n } catch {\n // Not JSON - may not be structured output\n }\n }\n\n for (const tc of state.toolCalls) {\n toolCalls.push({\n toolCallId: tc.name,\n toolName: tc.name,\n arguments: tc.args,\n });\n functionCallParts.push({\n name: tc.name,\n args: tc.args,\n thoughtSignature: tc.thoughtSignature,\n });\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n metadata: {\n google: {\n finishReason: state.finishReason,\n functionCallParts: functionCallParts.length > 0 ? functionCallParts : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n return {\n message,\n usage,\n stopReason: state.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n","import type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { GoogleLLMParams, GoogleResponse, GoogleStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamChunk,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for the Google Generative Language API (v1beta). */\nconst GOOGLE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta';\n\n/**\n * Capability flags for the Google Gemini API.\n *\n * Gemini models support streaming responses, function/tool calling,\n * structured JSON output, and multimodal inputs including images,\n * video, and audio.\n */\nconst GOOGLE_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Constructs the Google API endpoint URL for a specific model and action.\n *\n * @param modelId - The Gemini model identifier (e.g., 'gemini-1.5-pro')\n * @param action - The API action to perform\n * @param apiKey - The Google API key for authentication\n * @returns Fully qualified URL with API key as query parameter\n */\nfunction buildUrl(modelId: string, action: 'generateContent' | 'streamGenerateContent', apiKey: string): string {\n const base = `${GOOGLE_API_BASE}/models/${modelId}:${action}`;\n return `${base}?key=${apiKey}`;\n}\n\n/**\n * Creates an LLM handler for Google Gemini models.\n *\n * The handler implements the UPP LLMHandler interface, providing `bind()`\n * to create model instances that support both synchronous completion and\n * streaming responses.\n *\n * @returns An LLMHandler configured for Google Gemini API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('gemini-1.5-pro');\n *\n * const response = await model.complete({\n * messages: [...],\n * config: { apiKey: 'your-api-key' },\n * });\n * ```\n */\nexport function createLLMHandler(): LLMHandler<GoogleLLMParams> {\n let providerRef: LLMProvider<GoogleLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<GoogleLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<GoogleLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'google',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<GoogleLLMParams> = {\n modelId,\n capabilities: GOOGLE_CAPABILITIES,\n\n get provider(): LLMProvider<GoogleLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<GoogleLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'GOOGLE_API_KEY',\n 'google',\n 'llm'\n );\n\n const url = request.config.baseUrl\n ? `${request.config.baseUrl}/models/${modelId}:generateContent?key=${apiKey}`\n : buildUrl(modelId, 'generateContent', apiKey);\n\n const body = transformRequest(request, modelId);\n\n const response = await doFetch(\n url,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'google',\n 'llm'\n );\n\n const data = (await response.json()) as GoogleResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<GoogleLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'GOOGLE_API_KEY',\n 'google',\n 'llm'\n );\n\n const url = request.config.baseUrl\n ? `${request.config.baseUrl}/models/${modelId}:streamGenerateContent?alt=sse&key=${apiKey}`\n : `${buildUrl(modelId, 'streamGenerateContent', apiKey)}&alt=sse`;\n\n const body = transformRequest(request, modelId);\n\n const response = await doStreamFetch(\n url,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'google',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'google', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'google',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (typeof data === 'object' && data !== null) {\n const chunk = data as GoogleStreamChunk;\n\n if ('error' in chunk) {\n const error = new UPPError(\n (chunk as any).error.message,\n 'PROVIDER_ERROR',\n 'google',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const events = transformStreamChunk(chunk, state);\n for (const event of events) {\n yield event;\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview Google Gemini caching utilities.\n *\n * Provides functions for creating and managing cached content entries\n * that can be reused across multiple Gemini API requests to reduce\n * costs and latency for repeated context.\n *\n * @see {@link https://ai.google.dev/api/caching Google Caching API docs}\n * @module providers/google/cache\n */\n\nimport type {\n GoogleCacheCreateRequest,\n GoogleCacheResponse,\n GoogleCacheUpdateRequest,\n GoogleCacheListResponse,\n GoogleContent,\n GoogleTool,\n} from './types.ts';\n\nconst CACHE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta/cachedContents';\n\n/**\n * Options for creating a cached content entry.\n */\nexport interface CacheCreateOptions {\n /** API key for authentication */\n apiKey: string;\n /** Model to associate with this cache (e.g., \"gemini-1.5-flash-001\") */\n model: string;\n /** Optional display name for the cache (max 128 chars) */\n displayName?: string;\n /** Content messages to cache */\n contents?: GoogleContent[];\n /** System instruction text to cache */\n systemInstruction?: string;\n /** Tool declarations to cache */\n tools?: GoogleTool[];\n /** Time-to-live duration (e.g., \"3600s\" for 1 hour) */\n ttl?: string;\n /** Absolute expiration time (RFC 3339 format, alternative to ttl) */\n expireTime?: string;\n}\n\n/**\n * Options for listing cached content entries.\n */\nexport interface CacheListOptions {\n /** API key for authentication */\n apiKey: string;\n /** Maximum number of caches to return per page */\n pageSize?: number;\n /** Token for fetching the next page of results */\n pageToken?: string;\n}\n\n/**\n * Creates a new cached content entry.\n *\n * Caches can contain system instructions, conversation content, and tool\n * declarations that are reused across multiple requests. This reduces\n * token costs and processing time for repeated context.\n *\n * @param options - Cache creation options\n * @returns The created cache entry with its name/ID for use in requests\n *\n * @example\n * ```typescript\n * import { google } from '@anthropic/provider-protocol';\n *\n * // Create a cache with system instruction and large context\n * const cache = await google.cache.create({\n * apiKey: process.env.GOOGLE_API_KEY,\n * model: 'gemini-1.5-flash-001',\n * displayName: 'Code Review Context',\n * systemInstruction: 'You are an expert code reviewer...',\n * contents: [\n * { role: 'user', parts: [{ text: largeCodebaseContent }] }\n * ],\n * ttl: '3600s', // 1 hour\n * });\n *\n * // Use the cache in subsequent requests\n * const response = await model.complete({\n * messages: [userMessage('Review this function')],\n * params: { cachedContent: cache.name },\n * });\n * ```\n */\nexport async function create(options: CacheCreateOptions): Promise<GoogleCacheResponse> {\n const {\n apiKey,\n model,\n displayName,\n contents,\n systemInstruction,\n tools,\n ttl,\n expireTime,\n } = options;\n\n const requestBody: GoogleCacheCreateRequest = {\n model: model.startsWith('models/') ? model : `models/${model}`,\n };\n\n if (displayName) {\n requestBody.displayName = displayName;\n }\n\n if (contents && contents.length > 0) {\n requestBody.contents = contents;\n }\n\n if (systemInstruction) {\n requestBody.systemInstruction = {\n parts: [{ text: systemInstruction }],\n };\n }\n\n if (tools && tools.length > 0) {\n requestBody.tools = tools;\n }\n\n if (ttl) {\n requestBody.ttl = ttl;\n } else if (expireTime) {\n requestBody.expireTime = expireTime;\n }\n\n const response = await fetch(`${CACHE_API_BASE}?key=${apiKey}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to create cache: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheResponse>;\n}\n\n/**\n * Retrieves a cached content entry by name.\n *\n * @param name - The cache name (format: \"cachedContents/{id}\")\n * @param apiKey - API key for authentication\n * @returns The cache entry details\n *\n * @example\n * ```typescript\n * const cache = await google.cache.get('cachedContents/abc123', apiKey);\n * console.log(`Cache expires at: ${cache.expireTime}`);\n * ```\n */\nexport async function get(name: string, apiKey: string): Promise<GoogleCacheResponse> {\n const cacheName = name.startsWith('cachedContents/') ? name : `cachedContents/${name}`;\n const url = `https://generativelanguage.googleapis.com/v1beta/${cacheName}?key=${apiKey}`;\n\n const response = await fetch(url, { method: 'GET' });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to get cache: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheResponse>;\n}\n\n/**\n * Lists all cached content entries.\n *\n * @param options - List options including API key and pagination\n * @returns Array of cache entries and optional next page token\n *\n * @example\n * ```typescript\n * const { cachedContents, nextPageToken } = await google.cache.list({\n * apiKey: process.env.GOOGLE_API_KEY,\n * pageSize: 10,\n * });\n *\n * for (const cache of cachedContents ?? []) {\n * console.log(`${cache.displayName}: ${cache.name}`);\n * }\n * ```\n */\nexport async function list(options: CacheListOptions): Promise<GoogleCacheListResponse> {\n const { apiKey, pageSize, pageToken } = options;\n\n const params = new URLSearchParams({ key: apiKey });\n if (pageSize) params.set('pageSize', String(pageSize));\n if (pageToken) params.set('pageToken', pageToken);\n\n const response = await fetch(`${CACHE_API_BASE}?${params}`, { method: 'GET' });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to list caches: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheListResponse>;\n}\n\n/**\n * Updates a cached content entry's expiration time.\n *\n * Only the expiration time can be updated; all other fields\n * (contents, systemInstruction, tools) are immutable after creation.\n *\n * @param name - The cache name (format: \"cachedContents/{id}\")\n * @param update - The update to apply (ttl or expireTime)\n * @param apiKey - API key for authentication\n * @returns The updated cache entry\n *\n * @example\n * ```typescript\n * // Extend cache expiration by 2 hours\n * const updated = await google.cache.update(\n * 'cachedContents/abc123',\n * { ttl: '7200s' },\n * apiKey\n * );\n * ```\n */\nexport async function update(\n name: string,\n updateRequest: GoogleCacheUpdateRequest,\n apiKey: string\n): Promise<GoogleCacheResponse> {\n const cacheName = name.startsWith('cachedContents/') ? name : `cachedContents/${name}`;\n const url = `https://generativelanguage.googleapis.com/v1beta/${cacheName}?key=${apiKey}`;\n\n const response = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(updateRequest),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to update cache: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheResponse>;\n}\n\n/**\n * Deletes a cached content entry.\n *\n * @param name - The cache name (format: \"cachedContents/{id}\")\n * @param apiKey - API key for authentication\n *\n * @example\n * ```typescript\n * await google.cache.delete('cachedContents/abc123', apiKey);\n * ```\n */\nasync function deleteCache(name: string, apiKey: string): Promise<void> {\n const cacheName = name.startsWith('cachedContents/') ? name : `cachedContents/${name}`;\n const url = `https://generativelanguage.googleapis.com/v1beta/${cacheName}?key=${apiKey}`;\n\n const response = await fetch(url, { method: 'DELETE' });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to delete cache: ${response.status} ${error}`);\n }\n}\n\n/**\n * Cache utilities namespace.\n *\n * Provides functions for creating and managing Google Gemini cached content\n * entries. Use cached content to reduce costs and latency when repeatedly\n * sending the same context (system instructions, large documents, etc.)\n * across multiple requests.\n *\n * @example\n * ```typescript\n * import { google } from '@anthropic/provider-protocol';\n *\n * // Create a cache\n * const cache = await google.cache.create({\n * apiKey: process.env.GOOGLE_API_KEY,\n * model: 'gemini-1.5-flash-001',\n * systemInstruction: 'You are an expert assistant...',\n * contents: [{ role: 'user', parts: [{ text: largeDocument }] }],\n * ttl: '3600s',\n * });\n *\n * // Use cache.name in requests via params.cachedContent\n * const response = await model.complete({\n * messages: [userMessage('Summarize the document')],\n * params: { cachedContent: cache.name },\n * });\n *\n * // Manage caches\n * const caches = await google.cache.list({ apiKey });\n * await google.cache.update(cache.name, { ttl: '7200s' }, apiKey);\n * await google.cache.delete(cache.name, apiKey);\n * ```\n */\nexport const cache = {\n create,\n get,\n list,\n update,\n delete: deleteCache,\n};\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\nimport { cache } from './cache.ts';\n\nconst baseProvider = createProvider({\n name: 'google',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\n/**\n * Google Gemini provider for the Unified Provider Protocol (UPP).\n *\n * Provides access to Google's Gemini family of large language models through\n * a standardized interface. Supports text generation, multimodal inputs\n * (images, video, audio), tool/function calling, and structured output.\n *\n * @example\n * ```typescript\n * import { google } from './providers/google';\n *\n * // Create a model instance\n * const gemini = google.llm.bind('gemini-1.5-pro');\n *\n * // Simple completion\n * const response = await gemini.complete({\n * messages: [{ role: 'user', content: [{ type: 'text', text: 'Hello!' }] }],\n * config: { apiKey: process.env.GOOGLE_API_KEY },\n * });\n *\n * // Streaming completion\n * const stream = gemini.stream({\n * messages: [{ role: 'user', content: [{ type: 'text', text: 'Tell me a story' }] }],\n * config: { apiKey: process.env.GOOGLE_API_KEY },\n * });\n *\n * for await (const event of stream) {\n * if (event.type === 'text_delta') {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n *\n * @example Caching\n * ```typescript\n * // Create a cache for repeated context\n * const cacheEntry = await google.cache.create({\n * apiKey: process.env.GOOGLE_API_KEY,\n * model: 'gemini-1.5-flash-001',\n * systemInstruction: 'You are an expert code reviewer...',\n * contents: [{ role: 'user', parts: [{ text: largeCodebase }] }],\n * ttl: '3600s',\n * });\n *\n * // Use cache in requests\n * const response = await gemini.complete({\n * messages: [userMessage('Review this function')],\n * config: { apiKey: process.env.GOOGLE_API_KEY },\n * params: { cachedContent: cacheEntry.name },\n * });\n *\n * // Manage caches\n * await google.cache.update(cacheEntry.name, { ttl: '7200s' }, apiKey);\n * await google.cache.delete(cacheEntry.name, apiKey);\n * ```\n *\n * @see {@link GoogleLLMParams} for provider-specific configuration options\n * @see {@link cache} for caching utilities\n */\nexport const google = Object.assign(baseProvider, { cache });\n\nexport { cache } from './cache.ts';\nexport type { CacheCreateOptions, CacheListOptions } from './cache.ts';\nexport type {\n GoogleLLMParams,\n GoogleCacheCreateRequest,\n GoogleCacheResponse,\n GoogleCacheUpdateRequest,\n GoogleCacheListResponse,\n} from './types.ts';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/providers/google/transform.ts","../../src/providers/google/llm.ts","../../src/providers/google/cache.ts","../../src/providers/google/index.ts"],"sourcesContent":["/**\n * @fileoverview Transformation functions between UPP format and Google Gemini API format.\n *\n * This module handles the bidirectional conversion of requests, responses, and\n * streaming chunks between the Unified Provider Protocol (UPP) format and\n * Google's Generative Language API format.\n *\n * Key transformations:\n * - UPP messages with content blocks to Google's parts-based content structure\n * - UPP tools to Google's functionDeclarations format\n * - Google responses back to UPP LLMResponse with proper message types\n * - Streaming chunks to UPP StreamEvents\n */\n\nimport type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n GoogleLLMParams,\n GoogleRequest,\n GoogleContent,\n GooglePart,\n GoogleTool,\n GoogleResponse,\n GoogleStreamChunk,\n GoogleFunctionCallPart,\n} from './types.ts';\n\n/**\n * Transforms a UPP LLM request into Google Gemini API format.\n *\n * Converts the UPP message structure, system prompt, tools, and generation\n * parameters into Google's expected request body format. Provider-specific\n * parameters are passed through to `generationConfig` to support new API\n * features without library updates.\n *\n * @typeParam TParams - Type extending GoogleLLMParams for provider-specific options\n * @param request - The UPP-formatted LLM request\n * @param modelId - The target Gemini model identifier\n * @returns Google API request body ready for submission\n *\n * @example\n * ```typescript\n * const googleRequest = transformRequest({\n * messages: [{ role: 'user', content: [{ type: 'text', text: 'Hello' }] }],\n * system: 'You are a helpful assistant',\n * params: { temperature: 0.7 },\n * config: { apiKey: '...' },\n * }, 'gemini-1.5-pro');\n * ```\n */\nexport function transformRequest<TParams extends GoogleLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): GoogleRequest {\n const params = (request.params ?? {}) as GoogleLLMParams;\n const { cachedContent, ...generationParams } = params;\n\n const googleRequest: GoogleRequest = {\n contents: transformMessages(request.messages),\n };\n\n if (request.system) {\n if (typeof request.system === 'string') {\n googleRequest.systemInstruction = {\n parts: [{ text: request.system }],\n };\n } else {\n // Array format - pass through as parts: [{text: '...'}, {text: '...'}]\n googleRequest.systemInstruction = {\n parts: request.system as GooglePart[],\n };\n }\n }\n\n const generationConfig: NonNullable<GoogleRequest['generationConfig']> = {\n ...generationParams,\n };\n\n if (request.structure) {\n generationConfig.responseMimeType = 'application/json';\n generationConfig.responseSchema = request.structure as unknown as Record<string, unknown>;\n }\n\n if (Object.keys(generationConfig).length > 0) {\n googleRequest.generationConfig = generationConfig;\n }\n\n if (request.tools && request.tools.length > 0) {\n googleRequest.tools = [\n {\n functionDeclarations: request.tools.map(transformTool),\n },\n ];\n }\n\n if (cachedContent) {\n googleRequest.cachedContent = cachedContent;\n }\n\n return googleRequest;\n}\n\n/**\n * Filters content blocks to only those with a valid type property.\n *\n * @typeParam T - Content block type with optional type property\n * @param content - Array of content blocks to filter\n * @returns Filtered array containing only blocks with string type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transforms UPP message array to Google's content format.\n *\n * Handles the conversion of user messages, assistant messages (including\n * tool calls), and tool result messages to Google's role-based content\n * structure with parts arrays.\n *\n * @param messages - Array of UPP-formatted messages\n * @returns Array of Google content objects with role and parts\n */\nfunction transformMessages(messages: Message[]): GoogleContent[] {\n const contents: GoogleContent[] = [];\n\n for (const msg of messages) {\n if (isUserMessage(msg)) {\n const validContent = filterValidContent(msg.content);\n const parts = validContent.map(transformContentBlock);\n if (parts.length === 0) {\n parts.push({ text: '' });\n }\n contents.push({\n role: 'user',\n parts,\n });\n } else if (isAssistantMessage(msg)) {\n const validContent = filterValidContent(msg.content);\n const parts: GooglePart[] = validContent.map(transformContentBlock);\n\n const googleMeta = msg.metadata?.google as {\n functionCallParts?: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }>;\n } | undefined;\n\n if (googleMeta?.functionCallParts && googleMeta.functionCallParts.length > 0) {\n for (const fc of googleMeta.functionCallParts) {\n const part: GoogleFunctionCallPart = {\n functionCall: {\n name: fc.name,\n args: fc.args,\n },\n };\n if (fc.thoughtSignature) {\n part.thoughtSignature = fc.thoughtSignature;\n }\n parts.push(part);\n }\n } else if (msg.toolCalls) {\n for (const call of msg.toolCalls) {\n parts.push({\n functionCall: {\n name: call.toolName,\n args: call.arguments,\n },\n });\n }\n }\n\n if (parts.length === 0) {\n parts.push({ text: '' });\n }\n\n contents.push({\n role: 'model',\n parts,\n });\n } else if (isToolResultMessage(msg)) {\n contents.push({\n role: 'user',\n parts: msg.results.map((result) => ({\n functionResponse: {\n name: result.toolCallId,\n response:\n typeof result.result === 'object'\n ? (result.result as Record<string, unknown>)\n : { result: result.result },\n },\n })),\n });\n }\n }\n\n return contents;\n}\n\n/**\n * Transforms a UPP content block to a Google part.\n *\n * Supports text and image content types. Images must be base64 or bytes\n * encoded; URL sources are not supported by Google's API directly.\n *\n * @param block - The UPP content block to transform\n * @returns Google-formatted part object\n * @throws Error if the content type is unsupported or if an image uses URL source\n */\nfunction transformContentBlock(block: ContentBlock): GooglePart {\n switch (block.type) {\n case 'text':\n return { text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let data: string;\n\n if (imageBlock.source.type === 'base64') {\n data = imageBlock.source.data;\n } else if (imageBlock.source.type === 'bytes') {\n data = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n } else {\n throw new Error('Google API does not support URL image sources directly');\n }\n\n return {\n inlineData: {\n mimeType: imageBlock.mimeType,\n data,\n },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transforms a UPP tool definition to Google's function declaration format.\n *\n * @param tool - The UPP tool definition with name, description, and parameters\n * @returns Google function declaration object\n */\nfunction transformTool(tool: Tool): GoogleTool['functionDeclarations'][0] {\n return {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n };\n}\n\n/**\n * Transforms a Google API response to UPP LLMResponse format.\n *\n * Extracts text content, tool calls, structured data, and usage metadata\n * from Google's response format. Preserves Google-specific metadata like\n * finish reason, safety ratings, and thought signatures for multi-turn\n * tool call conversations.\n *\n * @param data - The raw Google API response\n * @returns Normalized UPP LLMResponse with message, usage, and stop reason\n * @throws Error if response contains no candidates\n *\n * @example\n * ```typescript\n * const response = await fetch(googleApiUrl, options);\n * const data = await response.json();\n * const uppResponse = transformResponse(data);\n * console.log(uppResponse.message.content);\n * ```\n */\nexport function transformResponse(data: GoogleResponse): LLMResponse {\n const candidate = data.candidates?.[0];\n if (!candidate) {\n throw new Error('No candidates in Google response');\n }\n\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n const functionCallParts: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }> = [];\n\n for (const part of candidate.content.parts) {\n if ('text' in part) {\n textContent.push({ type: 'text', text: part.text });\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not JSON - may not be structured output\n }\n }\n } else if ('functionCall' in part) {\n const fc = part as GoogleFunctionCallPart;\n toolCalls.push({\n toolCallId: fc.functionCall.name,\n toolName: fc.functionCall.name,\n arguments: fc.functionCall.args,\n });\n functionCallParts.push({\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n thoughtSignature: fc.thoughtSignature,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n metadata: {\n google: {\n finishReason: candidate.finishReason,\n safetyRatings: candidate.safetyRatings,\n functionCallParts: functionCallParts.length > 0 ? functionCallParts : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n totalTokens: data.usageMetadata?.totalTokenCount ?? 0,\n cacheReadTokens: data.usageMetadata?.cachedContentTokenCount ?? 0,\n cacheWriteTokens: 0,\n };\n\n return {\n message,\n usage,\n stopReason: candidate.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n\n/**\n * Accumulator state for streaming responses.\n *\n * Tracks partial content, tool calls, token counts, and stream lifecycle\n * as chunks arrive from the Google streaming API.\n */\nexport interface StreamState {\n /** Accumulated text content from all chunks. */\n content: string;\n /** Accumulated tool calls with their arguments and optional thought signatures. */\n toolCalls: Array<{ name: string; args: Record<string, unknown>; thoughtSignature?: string }>;\n /** The finish reason from the final chunk, if received. */\n finishReason: string | null;\n /** Total input tokens reported by the API. */\n inputTokens: number;\n /** Total output tokens reported by the API. */\n outputTokens: number;\n /** Number of tokens read from cached content. */\n cacheReadTokens: number;\n /** Flag indicating whether this is the first chunk (for message_start event). */\n isFirstChunk: boolean;\n}\n\n/**\n * Creates a fresh stream state for accumulating streaming responses.\n *\n * @returns Initialized StreamState with empty content and default values\n */\nexport function createStreamState(): StreamState {\n return {\n content: '',\n toolCalls: [],\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n isFirstChunk: true,\n };\n}\n\n/**\n * Transforms a Google streaming chunk to UPP StreamEvent array.\n *\n * Processes each streaming chunk, updating the accumulator state and\n * generating appropriate stream events for text deltas, tool calls,\n * and message lifecycle (start/stop).\n *\n * @param chunk - The Google streaming response chunk\n * @param state - Mutable accumulator state updated by this function\n * @returns Array of UPP StreamEvents generated from this chunk\n */\nexport function transformStreamChunk(\n chunk: GoogleStreamChunk,\n state: StreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n if (state.isFirstChunk) {\n events.push({ type: 'message_start', index: 0, delta: {} });\n state.isFirstChunk = false;\n }\n\n if (chunk.usageMetadata) {\n state.inputTokens = chunk.usageMetadata.promptTokenCount;\n state.outputTokens = chunk.usageMetadata.candidatesTokenCount;\n state.cacheReadTokens = chunk.usageMetadata.cachedContentTokenCount ?? 0;\n }\n\n const candidate = chunk.candidates?.[0];\n if (!candidate) {\n return events;\n }\n\n for (const part of candidate.content?.parts ?? []) {\n if ('text' in part) {\n state.content += part.text;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: part.text },\n });\n } else if ('functionCall' in part) {\n const fc = part as GoogleFunctionCallPart;\n state.toolCalls.push({\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n thoughtSignature: fc.thoughtSignature,\n });\n events.push({\n type: 'tool_call_delta',\n index: state.toolCalls.length - 1,\n delta: {\n toolCallId: fc.functionCall.name,\n toolName: fc.functionCall.name,\n argumentsJson: JSON.stringify(fc.functionCall.args),\n },\n });\n }\n }\n\n if (candidate.finishReason) {\n state.finishReason = candidate.finishReason;\n events.push({ type: 'message_stop', index: 0, delta: {} });\n }\n\n return events;\n}\n\n/**\n * Constructs a complete LLMResponse from accumulated stream state.\n *\n * Called after streaming completes to build the final response object\n * with all accumulated content, tool calls, usage statistics, and metadata.\n *\n * @param state - The final accumulated stream state\n * @returns Complete UPP LLMResponse\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n const functionCallParts: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }> = [];\n\n if (state.content) {\n textContent.push({ type: 'text', text: state.content });\n try {\n structuredData = JSON.parse(state.content);\n } catch {\n // Not JSON - may not be structured output\n }\n }\n\n for (const tc of state.toolCalls) {\n toolCalls.push({\n toolCallId: tc.name,\n toolName: tc.name,\n arguments: tc.args,\n });\n functionCallParts.push({\n name: tc.name,\n args: tc.args,\n thoughtSignature: tc.thoughtSignature,\n });\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n metadata: {\n google: {\n finishReason: state.finishReason,\n functionCallParts: functionCallParts.length > 0 ? functionCallParts : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n cacheReadTokens: state.cacheReadTokens,\n cacheWriteTokens: 0,\n };\n\n return {\n message,\n usage,\n stopReason: state.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n","import type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { GoogleLLMParams, GoogleResponse, GoogleStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamChunk,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\n/** Base URL for the Google Generative Language API (v1beta). */\nconst GOOGLE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta';\n\n/**\n * Capability flags for the Google Gemini API.\n *\n * Gemini models support streaming responses, function/tool calling,\n * structured JSON output, and multimodal inputs including images,\n * video, and audio.\n */\nconst GOOGLE_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Constructs the Google API endpoint URL for a specific model and action.\n *\n * @param modelId - The Gemini model identifier (e.g., 'gemini-1.5-pro')\n * @param action - The API action to perform\n * @param apiKey - The Google API key for authentication\n * @returns Fully qualified URL with API key as query parameter\n */\nfunction buildUrl(modelId: string, action: 'generateContent' | 'streamGenerateContent', apiKey: string): string {\n const base = `${GOOGLE_API_BASE}/models/${modelId}:${action}`;\n return `${base}?key=${apiKey}`;\n}\n\n/**\n * Creates an LLM handler for Google Gemini models.\n *\n * The handler implements the UPP LLMHandler interface, providing `bind()`\n * to create model instances that support both synchronous completion and\n * streaming responses.\n *\n * @returns An LLMHandler configured for Google Gemini API\n *\n * @example\n * ```typescript\n * const handler = createLLMHandler();\n * const model = handler.bind('gemini-1.5-pro');\n *\n * const response = await model.complete({\n * messages: [...],\n * config: { apiKey: 'your-api-key' },\n * });\n * ```\n */\nexport function createLLMHandler(): LLMHandler<GoogleLLMParams> {\n let providerRef: LLMProvider<GoogleLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<GoogleLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<GoogleLLMParams> {\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'google',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<GoogleLLMParams> = {\n modelId,\n capabilities: GOOGLE_CAPABILITIES,\n\n get provider(): LLMProvider<GoogleLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<GoogleLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'GOOGLE_API_KEY',\n 'google',\n 'llm'\n );\n\n const url = request.config.baseUrl\n ? `${request.config.baseUrl}/models/${modelId}:generateContent?key=${apiKey}`\n : buildUrl(modelId, 'generateContent', apiKey);\n\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doFetch(\n url,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'google',\n 'llm'\n );\n\n const data = (await response.json()) as GoogleResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<GoogleLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'GOOGLE_API_KEY',\n 'google',\n 'llm'\n );\n\n const url = request.config.baseUrl\n ? `${request.config.baseUrl}/models/${modelId}:streamGenerateContent?alt=sse&key=${apiKey}`\n : `${buildUrl(modelId, 'streamGenerateContent', apiKey)}&alt=sse`;\n\n const body = transformRequest(request, modelId);\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (request.config.headers) {\n for (const [key, value] of Object.entries(request.config.headers)) {\n if (value !== undefined) {\n headers[key] = value;\n }\n }\n }\n\n const response = await doStreamFetch(\n url,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'google',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'google', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'google',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (typeof data === 'object' && data !== null) {\n const chunk = data as GoogleStreamChunk;\n\n if ('error' in chunk) {\n const error = new UPPError(\n (chunk as any).error.message,\n 'PROVIDER_ERROR',\n 'google',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const events = transformStreamChunk(chunk, state);\n for (const event of events) {\n yield event;\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","/**\n * @fileoverview Google Gemini caching utilities.\n *\n * Provides functions for creating and managing cached content entries\n * that can be reused across multiple Gemini API requests to reduce\n * costs and latency for repeated context.\n *\n * @see {@link https://ai.google.dev/api/caching Google Caching API docs}\n * @module providers/google/cache\n */\n\nimport type {\n GoogleCacheCreateRequest,\n GoogleCacheResponse,\n GoogleCacheUpdateRequest,\n GoogleCacheListResponse,\n GoogleContent,\n GoogleTool,\n} from './types.ts';\n\nconst CACHE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta/cachedContents';\n\n/**\n * Options for creating a cached content entry.\n */\nexport interface CacheCreateOptions {\n /** API key for authentication */\n apiKey: string;\n /** Model to associate with this cache (e.g., \"gemini-3-flash-preview\") */\n model: string;\n /** Optional display name for the cache (max 128 chars) */\n displayName?: string;\n /** Content messages to cache */\n contents?: GoogleContent[];\n /** System instruction text to cache */\n systemInstruction?: string;\n /** Tool declarations to cache */\n tools?: GoogleTool[];\n /** Time-to-live duration (e.g., \"3600s\" for 1 hour) */\n ttl?: string;\n /** Absolute expiration time (RFC 3339 format, alternative to ttl) */\n expireTime?: string;\n}\n\n/**\n * Options for listing cached content entries.\n */\nexport interface CacheListOptions {\n /** API key for authentication */\n apiKey: string;\n /** Maximum number of caches to return per page */\n pageSize?: number;\n /** Token for fetching the next page of results */\n pageToken?: string;\n}\n\n/**\n * Creates a new cached content entry.\n *\n * Caches can contain system instructions, conversation content, and tool\n * declarations that are reused across multiple requests. This reduces\n * token costs and processing time for repeated context.\n *\n * @param options - Cache creation options\n * @returns The created cache entry with its name/ID for use in requests\n *\n * @example\n * ```typescript\n * import { google } from '@anthropic/provider-protocol';\n *\n * // Create a cache with system instruction and large context\n * const cache = await google.cache.create({\n * apiKey: process.env.GOOGLE_API_KEY,\n * model: 'gemini-3-flash-preview',\n * displayName: 'Code Review Context',\n * systemInstruction: 'You are an expert code reviewer...',\n * contents: [\n * { role: 'user', parts: [{ text: largeCodebaseContent }] }\n * ],\n * ttl: '3600s', // 1 hour\n * });\n *\n * // Use the cache in subsequent requests\n * const response = await model.complete({\n * messages: [userMessage('Review this function')],\n * params: { cachedContent: cache.name },\n * });\n * ```\n */\nexport async function create(options: CacheCreateOptions): Promise<GoogleCacheResponse> {\n const {\n apiKey,\n model,\n displayName,\n contents,\n systemInstruction,\n tools,\n ttl,\n expireTime,\n } = options;\n\n const requestBody: GoogleCacheCreateRequest = {\n model: model.startsWith('models/') ? model : `models/${model}`,\n };\n\n if (displayName) {\n requestBody.displayName = displayName;\n }\n\n if (contents && contents.length > 0) {\n requestBody.contents = contents;\n }\n\n if (systemInstruction) {\n requestBody.systemInstruction = {\n parts: [{ text: systemInstruction }],\n };\n }\n\n if (tools && tools.length > 0) {\n requestBody.tools = tools;\n }\n\n if (ttl) {\n requestBody.ttl = ttl;\n } else if (expireTime) {\n requestBody.expireTime = expireTime;\n }\n\n const response = await fetch(`${CACHE_API_BASE}?key=${apiKey}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(requestBody),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to create cache: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheResponse>;\n}\n\n/**\n * Retrieves a cached content entry by name.\n *\n * @param name - The cache name (format: \"cachedContents/{id}\")\n * @param apiKey - API key for authentication\n * @returns The cache entry details\n *\n * @example\n * ```typescript\n * const cache = await google.cache.get('cachedContents/abc123', apiKey);\n * console.log(`Cache expires at: ${cache.expireTime}`);\n * ```\n */\nexport async function get(name: string, apiKey: string): Promise<GoogleCacheResponse> {\n const cacheName = name.startsWith('cachedContents/') ? name : `cachedContents/${name}`;\n const url = `https://generativelanguage.googleapis.com/v1beta/${cacheName}?key=${apiKey}`;\n\n const response = await fetch(url, { method: 'GET' });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to get cache: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheResponse>;\n}\n\n/**\n * Lists all cached content entries.\n *\n * @param options - List options including API key and pagination\n * @returns Array of cache entries and optional next page token\n *\n * @example\n * ```typescript\n * const { cachedContents, nextPageToken } = await google.cache.list({\n * apiKey: process.env.GOOGLE_API_KEY,\n * pageSize: 10,\n * });\n *\n * for (const cache of cachedContents ?? []) {\n * console.log(`${cache.displayName}: ${cache.name}`);\n * }\n * ```\n */\nexport async function list(options: CacheListOptions): Promise<GoogleCacheListResponse> {\n const { apiKey, pageSize, pageToken } = options;\n\n const params = new URLSearchParams({ key: apiKey });\n if (pageSize) params.set('pageSize', String(pageSize));\n if (pageToken) params.set('pageToken', pageToken);\n\n const response = await fetch(`${CACHE_API_BASE}?${params}`, { method: 'GET' });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to list caches: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheListResponse>;\n}\n\n/**\n * Updates a cached content entry's expiration time.\n *\n * Only the expiration time can be updated; all other fields\n * (contents, systemInstruction, tools) are immutable after creation.\n *\n * @param name - The cache name (format: \"cachedContents/{id}\")\n * @param update - The update to apply (ttl or expireTime)\n * @param apiKey - API key for authentication\n * @returns The updated cache entry\n *\n * @example\n * ```typescript\n * // Extend cache expiration by 2 hours\n * const updated = await google.cache.update(\n * 'cachedContents/abc123',\n * { ttl: '7200s' },\n * apiKey\n * );\n * ```\n */\nexport async function update(\n name: string,\n updateRequest: GoogleCacheUpdateRequest,\n apiKey: string\n): Promise<GoogleCacheResponse> {\n const cacheName = name.startsWith('cachedContents/') ? name : `cachedContents/${name}`;\n const url = `https://generativelanguage.googleapis.com/v1beta/${cacheName}?key=${apiKey}`;\n\n const response = await fetch(url, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(updateRequest),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to update cache: ${response.status} ${error}`);\n }\n\n return response.json() as Promise<GoogleCacheResponse>;\n}\n\n/**\n * Deletes a cached content entry.\n *\n * @param name - The cache name (format: \"cachedContents/{id}\")\n * @param apiKey - API key for authentication\n *\n * @example\n * ```typescript\n * await google.cache.delete('cachedContents/abc123', apiKey);\n * ```\n */\nasync function deleteCache(name: string, apiKey: string): Promise<void> {\n const cacheName = name.startsWith('cachedContents/') ? name : `cachedContents/${name}`;\n const url = `https://generativelanguage.googleapis.com/v1beta/${cacheName}?key=${apiKey}`;\n\n const response = await fetch(url, { method: 'DELETE' });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to delete cache: ${response.status} ${error}`);\n }\n}\n\n/**\n * Cache utilities namespace.\n *\n * Provides functions for creating and managing Google Gemini cached content\n * entries. Use cached content to reduce costs and latency when repeatedly\n * sending the same context (system instructions, large documents, etc.)\n * across multiple requests.\n *\n * @example\n * ```typescript\n * import { google } from '@anthropic/provider-protocol';\n *\n * // Create a cache\n * const cache = await google.cache.create({\n * apiKey: process.env.GOOGLE_API_KEY,\n * model: 'gemini-3-flash-preview',\n * systemInstruction: 'You are an expert assistant...',\n * contents: [{ role: 'user', parts: [{ text: largeDocument }] }],\n * ttl: '3600s',\n * });\n *\n * // Use cache.name in requests via params.cachedContent\n * const response = await model.complete({\n * messages: [userMessage('Summarize the document')],\n * params: { cachedContent: cache.name },\n * });\n *\n * // Manage caches\n * const caches = await google.cache.list({ apiKey });\n * await google.cache.update(cache.name, { ttl: '7200s' }, apiKey);\n * await google.cache.delete(cache.name, apiKey);\n * ```\n */\nexport const cache = {\n create,\n get,\n list,\n update,\n delete: deleteCache,\n};\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\nimport { cache } from './cache.ts';\n\nconst baseProvider = createProvider({\n name: 'google',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\n/**\n * Google Gemini provider for the Unified Provider Protocol (UPP).\n *\n * Provides access to Google's Gemini family of large language models through\n * a standardized interface. Supports text generation, multimodal inputs\n * (images, video, audio), tool/function calling, and structured output.\n *\n * @example\n * ```typescript\n * import { google } from './providers/google';\n *\n * // Create a model instance\n * const gemini = google.llm.bind('gemini-1.5-pro');\n *\n * // Simple completion\n * const response = await gemini.complete({\n * messages: [{ role: 'user', content: [{ type: 'text', text: 'Hello!' }] }],\n * config: { apiKey: process.env.GOOGLE_API_KEY },\n * });\n *\n * // Streaming completion\n * const stream = gemini.stream({\n * messages: [{ role: 'user', content: [{ type: 'text', text: 'Tell me a story' }] }],\n * config: { apiKey: process.env.GOOGLE_API_KEY },\n * });\n *\n * for await (const event of stream) {\n * if (event.type === 'text_delta') {\n * process.stdout.write(event.delta.text);\n * }\n * }\n * ```\n *\n * @example Caching\n * ```typescript\n * // Create a cache for repeated context\n * const cacheEntry = await google.cache.create({\n * apiKey: process.env.GOOGLE_API_KEY,\n * model: 'gemini-3-flash-preview',\n * systemInstruction: 'You are an expert code reviewer...',\n * contents: [{ role: 'user', parts: [{ text: largeCodebase }] }],\n * ttl: '3600s',\n * });\n *\n * // Use cache in requests\n * const response = await gemini.complete({\n * messages: [userMessage('Review this function')],\n * config: { apiKey: process.env.GOOGLE_API_KEY },\n * params: { cachedContent: cacheEntry.name },\n * });\n *\n * // Manage caches\n * await google.cache.update(cacheEntry.name, { ttl: '7200s' }, apiKey);\n * await google.cache.delete(cacheEntry.name, apiKey);\n * ```\n *\n * @see {@link GoogleLLMParams} for provider-specific configuration options\n * @see {@link cache} for caching utilities\n */\nexport const google = Object.assign(baseProvider, { cache });\n\nexport { cache } from './cache.ts';\nexport type { CacheCreateOptions, CacheListOptions } from './cache.ts';\nexport type {\n GoogleLLMParams,\n GoogleCacheCreateRequest,\n GoogleCacheResponse,\n GoogleCacheUpdateRequest,\n GoogleCacheListResponse,\n GoogleHeaders,\n} from './types.ts';\n"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
- export { D as DynamicKey, E as ExponentialBackoff, L as LinearBackoff, N as NoRetry, a as RetryAfterStrategy, R as RoundRobinKeys, T as TokenBucket, W as WeightedKeys, r as resolveApiKey } from '../retry-Dh70lgr0.js';
2
- import { P as ProviderConfig, d as Modality, U as UPPError, c as ErrorCode } from '../provider-mKkz7Q9U.js';
1
+ export { D as DynamicKey, E as ExponentialBackoff, L as LinearBackoff, N as NoRetry, a as RetryAfterStrategy, R as RoundRobinKeys, T as TokenBucket, W as WeightedKeys, r as resolveApiKey } from '../retry-BatS2hjD.js';
2
+ import { P as ProviderConfig, d as Modality, U as UPPError, c as ErrorCode } from '../provider-Bi0nyNhA.js';
3
3
 
4
4
  /**
5
5
  * HTTP fetch utilities with retry, timeout, and error normalization.