@providerprotocol/ai 0.0.12 → 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.
- package/dist/anthropic/index.d.ts +51 -15
- package/dist/anthropic/index.js +80 -29
- package/dist/anthropic/index.js.map +1 -1
- package/dist/{chunk-SUNYWHTH.js → chunk-MOU4U3PO.js} +55 -3
- package/dist/chunk-MOU4U3PO.js.map +1 -0
- package/dist/{chunk-Y6Q7JCNP.js → chunk-MSR5P65T.js} +1 -1
- package/dist/chunk-MSR5P65T.js.map +1 -0
- package/dist/{chunk-W4BB4BG2.js → chunk-SVYROCLD.js} +31 -11
- package/dist/chunk-SVYROCLD.js.map +1 -0
- package/dist/chunk-U4JJC2YX.js +234 -0
- package/dist/chunk-U4JJC2YX.js.map +1 -0
- package/dist/{chunk-X5G4EHL7.js → chunk-Z7RBRCRN.js} +1 -1
- package/dist/chunk-Z7RBRCRN.js.map +1 -0
- package/dist/google/index.d.ts +376 -7
- package/dist/google/index.js +149 -21
- package/dist/google/index.js.map +1 -1
- package/dist/http/index.d.ts +222 -25
- package/dist/http/index.js +3 -3
- package/dist/index.d.ts +1484 -198
- package/dist/index.js +233 -47
- package/dist/index.js.map +1 -1
- package/dist/ollama/index.d.ts +92 -20
- package/dist/ollama/index.js +31 -7
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +340 -61
- package/dist/openai/index.js +105 -31
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +107 -51
- package/dist/openrouter/index.js +84 -24
- package/dist/openrouter/index.js.map +1 -1
- package/dist/provider-Bi0nyNhA.d.ts +505 -0
- package/dist/retry-BatS2hjD.d.ts +508 -0
- package/dist/xai/index.d.ts +97 -22
- package/dist/xai/index.js +129 -45
- package/dist/xai/index.js.map +1 -1
- package/package.json +8 -3
- package/dist/chunk-CUCRF5W6.js +0 -136
- package/dist/chunk-CUCRF5W6.js.map +0 -1
- package/dist/chunk-SUNYWHTH.js.map +0 -1
- package/dist/chunk-W4BB4BG2.js.map +0 -1
- package/dist/chunk-X5G4EHL7.js.map +0 -1
- package/dist/chunk-Y6Q7JCNP.js.map +0 -1
- package/dist/provider-CUJWjgNl.d.ts +0 -192
- package/dist/retry-I2661_rv.d.ts +0 -118
package/dist/google/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/providers/google/transform.ts","../../src/providers/google/llm.ts","../../src/providers/google/index.ts"],"sourcesContent":["import 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 * Transform UPP request to Google format\n *\n * Params are spread into generationConfig to allow pass-through of any Google API fields,\n * even those not explicitly defined in our type. This enables developers to\n * use new API features without waiting for library updates.\n */\nexport function transformRequest<TParams extends GoogleLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): GoogleRequest {\n const params = (request.params ?? {}) as GoogleLLMParams;\n\n const googleRequest: GoogleRequest = {\n contents: transformMessages(request.messages),\n };\n\n // System instruction (separate from contents in Google)\n if (request.system) {\n googleRequest.systemInstruction = {\n parts: [{ text: request.system }],\n };\n }\n\n // Spread params into generationConfig to pass through all fields\n const generationConfig: NonNullable<GoogleRequest['generationConfig']> = {\n ...params,\n };\n\n // Protocol-level structured output (overrides provider-specific settings)\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 // Tools come from request, not params\n if (request.tools && request.tools.length > 0) {\n googleRequest.tools = [\n {\n functionDeclarations: request.tools.map(transformTool),\n },\n ];\n }\n\n return googleRequest;\n}\n\n/**\n * Filter to only valid content blocks with a 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 * Transform UPP Messages to Google contents\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 // Google requires at least one part - add placeholder if empty\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 // Add function calls - use stored parts with thought signatures if available\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 // Use stored function call parts with thought signatures\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 // Fallback: reconstruct from tool calls (no thought signatures)\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 // Google requires at least one part - add placeholder if empty\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 // Function results are sent as user messages in Google\n contents.push({\n role: 'user',\n parts: msg.results.map((result) => ({\n functionResponse: {\n name: result.toolCallId, // Google uses the function name, but we store it in 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 * Transform a content block to Google format\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 * Transform a UPP Tool to Google format\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 * Transform Google response to UPP LLMResponse\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 // Store original function call parts with thought signatures for echoing back\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 // Try to parse as JSON for structured output (native JSON mode)\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not valid JSON - that's fine, might 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, // Google doesn't have call IDs, use name\n toolName: fc.functionCall.name,\n arguments: fc.functionCall.args,\n });\n // Store the full part including thought signature\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 // Store function call parts with thought signatures for multi-turn\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 };\n\n return {\n message,\n usage,\n stopReason: candidate.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n\n/**\n * State for accumulating streaming response\n */\nexport interface StreamState {\n content: string;\n toolCalls: Array<{ name: string; args: Record<string, unknown>; thoughtSignature?: string }>;\n finishReason: string | null;\n inputTokens: number;\n outputTokens: number;\n isFirstChunk: boolean;\n}\n\n/**\n * Create initial stream state\n */\nexport function createStreamState(): StreamState {\n return {\n content: '',\n toolCalls: [],\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n isFirstChunk: true,\n };\n}\n\n/**\n * Transform Google stream chunk to UPP StreamEvents\n */\nexport function transformStreamChunk(\n chunk: GoogleStreamChunk,\n state: StreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n // First chunk - emit message start\n if (state.isFirstChunk) {\n events.push({ type: 'message_start', index: 0, delta: {} });\n state.isFirstChunk = false;\n }\n\n // Usage metadata\n if (chunk.usageMetadata) {\n state.inputTokens = chunk.usageMetadata.promptTokenCount;\n state.outputTokens = chunk.usageMetadata.candidatesTokenCount;\n }\n\n const candidate = chunk.candidates?.[0];\n if (!candidate) {\n return events;\n }\n\n // Process parts\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 // Store with thought signature for echoing back\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 // Finish reason\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 * Build LLMResponse from accumulated stream state\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 to parse as JSON for structured output (native JSON mode)\n try {\n structuredData = JSON.parse(state.content);\n } catch {\n // Not valid JSON - that's fine, might 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 // Store function call parts with thought signatures for multi-turn\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 };\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\nconst GOOGLE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta';\n\n/**\n * Google API capabilities\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 * Build Google API URL for a model\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 * Create Google LLM handler\n */\nexport function createLLMHandler(): LLMHandler<GoogleLLMParams> {\n // Provider reference injected by createProvider() after construction\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 // Use the injected provider reference (set by createProvider)\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 // Check for error\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","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Google Gemini provider\n * Supports LLM modality with Gemini models\n */\nexport const google = createProvider({\n name: 'google',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\n// Re-export types\nexport type { GoogleLLMParams } from './types.ts';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8BO,SAAS,iBACd,SACA,SACe;AACf,QAAM,SAAU,QAAQ,UAAU,CAAC;AAEnC,QAAM,gBAA+B;AAAA,IACnC,UAAU,kBAAkB,QAAQ,QAAQ;AAAA,EAC9C;AAGA,MAAI,QAAQ,QAAQ;AAClB,kBAAc,oBAAoB;AAAA,MAChC,OAAO,CAAC,EAAE,MAAM,QAAQ,OAAO,CAAC;AAAA,IAClC;AAAA,EACF;AAGA,QAAM,mBAAmE;AAAA,IACvE,GAAG;AAAA,EACL;AAGA,MAAI,QAAQ,WAAW;AACrB,qBAAiB,mBAAmB;AACpC,qBAAiB,iBAAiB,QAAQ;AAAA,EAC5C;AAEA,MAAI,OAAO,KAAK,gBAAgB,EAAE,SAAS,GAAG;AAC5C,kBAAc,mBAAmB;AAAA,EACnC;AAGA,MAAI,QAAQ,SAAS,QAAQ,MAAM,SAAS,GAAG;AAC7C,kBAAc,QAAQ;AAAA,MACpB;AAAA,QACE,sBAAsB,QAAQ,MAAM,IAAI,aAAa;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,mBAAgD,SAAmB;AAC1E,SAAO,QAAQ,OAAO,CAAC,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ;AAC9D;AAKA,SAAS,kBAAkB,UAAsC;AAC/D,QAAM,WAA4B,CAAC;AAEnC,aAAW,OAAO,UAAU;AAC1B,QAAI,cAAc,GAAG,GAAG;AACtB,YAAM,eAAe,mBAAmB,IAAI,OAAO;AACnD,YAAM,QAAQ,aAAa,IAAI,qBAAqB;AAEpD,UAAI,MAAM,WAAW,GAAG;AACtB,cAAM,KAAK,EAAE,MAAM,GAAG,CAAC;AAAA,MACzB;AACA,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH,WAAW,mBAAmB,GAAG,GAAG;AAClC,YAAM,eAAe,mBAAmB,IAAI,OAAO;AACnD,YAAM,QAAsB,aAAa,IAAI,qBAAqB;AAGlE,YAAM,aAAa,IAAI,UAAU;AAQjC,UAAI,YAAY,qBAAqB,WAAW,kBAAkB,SAAS,GAAG;AAE5E,mBAAW,MAAM,WAAW,mBAAmB;AAC7C,gBAAM,OAA+B;AAAA,YACnC,cAAc;AAAA,cACZ,MAAM,GAAG;AAAA,cACT,MAAM,GAAG;AAAA,YACX;AAAA,UACF;AACA,cAAI,GAAG,kBAAkB;AACvB,iBAAK,mBAAmB,GAAG;AAAA,UAC7B;AACA,gBAAM,KAAK,IAAI;AAAA,QACjB;AAAA,MACF,WAAW,IAAI,WAAW;AAExB,mBAAW,QAAQ,IAAI,WAAW;AAChC,gBAAM,KAAK;AAAA,YACT,cAAc;AAAA,cACZ,MAAM,KAAK;AAAA,cACX,MAAM,KAAK;AAAA,YACb;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,MAAM,WAAW,GAAG;AACtB,cAAM,KAAK,EAAE,MAAM,GAAG,CAAC;AAAA,MACzB;AAEA,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH,WAAW,oBAAoB,GAAG,GAAG;AAEnC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,OAAO,IAAI,QAAQ,IAAI,CAAC,YAAY;AAAA,UAClC,kBAAkB;AAAA,YAChB,MAAM,OAAO;AAAA;AAAA,YACb,UACE,OAAO,OAAO,WAAW,WACpB,OAAO,SACR,EAAE,QAAQ,OAAO,OAAO;AAAA,UAChC;AAAA,QACF,EAAE;AAAA,MACJ,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,sBAAsB,OAAiC;AAC9D,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO,EAAE,MAAM,MAAM,KAAK;AAAA,IAE5B,KAAK,SAAS;AACZ,YAAM,aAAa;AACnB,UAAI;AAEJ,UAAI,WAAW,OAAO,SAAS,UAAU;AACvC,eAAO,WAAW,OAAO;AAAA,MAC3B,WAAW,WAAW,OAAO,SAAS,SAAS;AAC7C,eAAO;AAAA,UACL,MAAM,KAAK,WAAW,OAAO,IAAI,EAC9B,IAAI,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC,EACjC,KAAK,EAAE;AAAA,QACZ;AAAA,MACF,OAAO;AACL,cAAM,IAAI,MAAM,wDAAwD;AAAA,MAC1E;AAEA,aAAO;AAAA,QACL,YAAY;AAAA,UACV,UAAU,WAAW;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA;AACE,YAAM,IAAI,MAAM,6BAA6B,MAAM,IAAI,EAAE;AAAA,EAC7D;AACF;AAKA,SAAS,cAAc,MAAmD;AACxE,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY,KAAK,WAAW;AAAA,MAC5B,UAAU,KAAK,WAAW;AAAA,IAC5B;AAAA,EACF;AACF;AAKO,SAAS,kBAAkB,MAAmC;AACnE,QAAM,YAAY,KAAK,aAAa,CAAC;AACrC,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,QAAM,cAA2B,CAAC;AAClC,QAAM,YAAwB,CAAC;AAC/B,MAAI;AAEJ,QAAM,oBAID,CAAC;AAEN,aAAW,QAAQ,UAAU,QAAQ,OAAO;AAC1C,QAAI,UAAU,MAAM;AAClB,kBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC;AAElD,UAAI,mBAAmB,QAAW;AAChC,YAAI;AACF,2BAAiB,KAAK,MAAM,KAAK,IAAI;AAAA,QACvC,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF,WAAW,kBAAkB,MAAM;AACjC,YAAM,KAAK;AACX,gBAAU,KAAK;AAAA,QACb,YAAY,GAAG,aAAa;AAAA;AAAA,QAC5B,UAAU,GAAG,aAAa;AAAA,QAC1B,WAAW,GAAG,aAAa;AAAA,MAC7B,CAAC;AAED,wBAAkB,KAAK;AAAA,QACrB,MAAM,GAAG,aAAa;AAAA,QACtB,MAAM,GAAG,aAAa;AAAA,QACtB,kBAAkB,GAAG;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,cAAc,UAAU;AAAA,UACxB,eAAe,UAAU;AAAA;AAAA,UAEzB,mBAAmB,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,QACxE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,KAAK,eAAe,oBAAoB;AAAA,IACrD,cAAc,KAAK,eAAe,wBAAwB;AAAA,IAC1D,aAAa,KAAK,eAAe,mBAAmB;AAAA,EACtD;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,UAAU,gBAAgB;AAAA,IACtC,MAAM;AAAA,EACR;AACF;AAiBO,SAAS,oBAAiC;AAC/C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,WAAW,CAAC;AAAA,IACZ,cAAc;AAAA,IACd,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc;AAAA,EAChB;AACF;AAKO,SAAS,qBACd,OACA,OACe;AACf,QAAM,SAAwB,CAAC;AAG/B,MAAI,MAAM,cAAc;AACtB,WAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AAC1D,UAAM,eAAe;AAAA,EACvB;AAGA,MAAI,MAAM,eAAe;AACvB,UAAM,cAAc,MAAM,cAAc;AACxC,UAAM,eAAe,MAAM,cAAc;AAAA,EAC3C;AAEA,QAAM,YAAY,MAAM,aAAa,CAAC;AACtC,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAGA,aAAW,QAAQ,UAAU,SAAS,SAAS,CAAC,GAAG;AACjD,QAAI,UAAU,MAAM;AAClB,YAAM,WAAW,KAAK;AACtB,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO,EAAE,MAAM,KAAK,KAAK;AAAA,MAC3B,CAAC;AAAA,IACH,WAAW,kBAAkB,MAAM;AACjC,YAAM,KAAK;AAEX,YAAM,UAAU,KAAK;AAAA,QACnB,MAAM,GAAG,aAAa;AAAA,QACtB,MAAM,GAAG,aAAa;AAAA,QACtB,kBAAkB,GAAG;AAAA,MACvB,CAAC;AACD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,MAAM,UAAU,SAAS;AAAA,QAChC,OAAO;AAAA,UACL,YAAY,GAAG,aAAa;AAAA,UAC5B,UAAU,GAAG,aAAa;AAAA,UAC1B,eAAe,KAAK,UAAU,GAAG,aAAa,IAAI;AAAA,QACpD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,UAAU,cAAc;AAC1B,UAAM,eAAe,UAAU;AAC/B,WAAO,KAAK,EAAE,MAAM,gBAAgB,OAAO,GAAG,OAAO,CAAC,EAAE,CAAC;AAAA,EAC3D;AAEA,SAAO;AACT;AAKO,SAAS,uBAAuB,OAAiC;AACtE,QAAM,cAA2B,CAAC;AAClC,QAAM,YAAwB,CAAC;AAC/B,MAAI;AACJ,QAAM,oBAID,CAAC;AAEN,MAAI,MAAM,SAAS;AACjB,gBAAY,KAAK,EAAE,MAAM,QAAQ,MAAM,MAAM,QAAQ,CAAC;AAEtD,QAAI;AACF,uBAAiB,KAAK,MAAM,MAAM,OAAO;AAAA,IAC3C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,aAAW,MAAM,MAAM,WAAW;AAChC,cAAU,KAAK;AAAA,MACb,YAAY,GAAG;AAAA,MACf,UAAU,GAAG;AAAA,MACb,WAAW,GAAG;AAAA,IAChB,CAAC;AACD,sBAAkB,KAAK;AAAA,MACrB,MAAM,GAAG;AAAA,MACT,MAAM,GAAG;AAAA,MACT,kBAAkB,GAAG;AAAA,IACvB,CAAC;AAAA,EACH;AAEA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA,UAAU,SAAS,IAAI,YAAY;AAAA,IACnC;AAAA,MACE,UAAU;AAAA,QACR,QAAQ;AAAA,UACN,cAAc,MAAM;AAAA;AAAA,UAEpB,mBAAmB,kBAAkB,SAAS,IAAI,oBAAoB;AAAA,QACxE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAoB;AAAA,IACxB,aAAa,MAAM;AAAA,IACnB,cAAc,MAAM;AAAA,IACpB,aAAa,MAAM,cAAc,MAAM;AAAA,EACzC;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,YAAY,MAAM,gBAAgB;AAAA,IAClC,MAAM;AAAA,EACR;AACF;;;AC7aA,IAAM,kBAAkB;AAKxB,IAAM,sBAAuC;AAAA,EAC3C,WAAW;AAAA,EACX,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,YAAY;AACd;AAKA,SAAS,SAAS,SAAiB,QAAqD,QAAwB;AAC9G,QAAM,OAAO,GAAG,eAAe,WAAW,OAAO,IAAI,MAAM;AAC3D,SAAO,GAAG,IAAI,QAAQ,MAAM;AAC9B;AAKO,SAAS,mBAAgD;AAE9D,MAAI,cAAmD;AAEvD,SAAO;AAAA,IACL,aAAa,UAAwC;AACnD,oBAAc;AAAA,IAChB;AAAA,IAEA,KAAK,SAAiD;AAEpD,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,YAAM,QAAwC;AAAA,QAC5C;AAAA,QACA,cAAc;AAAA,QAEd,IAAI,WAAyC;AAC3C,iBAAO;AAAA,QACT;AAAA,QAEA,MAAM,SAAS,SAA4D;AACzE,gBAAM,SAAS,MAAM;AAAA,YACnB,QAAQ;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,gBAAM,MAAM,QAAQ,OAAO,UACvB,GAAG,QAAQ,OAAO,OAAO,WAAW,OAAO,wBAAwB,MAAM,KACzE,SAAS,SAAS,mBAAmB,MAAM;AAE/C,gBAAM,OAAO,iBAAiB,SAAS,OAAO;AAE9C,gBAAM,WAAW,MAAM;AAAA,YACrB;AAAA,YACA;AAAA,cACE,QAAQ;AAAA,cACR,SAAS;AAAA,gBACP,gBAAgB;AAAA,cAClB;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,SAAuD;AAC5D,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,MAAM,QAAQ,OAAO,UACvB,GAAG,QAAQ,OAAO,OAAO,WAAW,OAAO,sCAAsC,MAAM,KACvF,GAAG,SAAS,SAAS,yBAAyB,MAAM,CAAC;AAEzD,oBAAM,OAAO,iBAAiB,SAAS,OAAO;AAE9C,oBAAM,WAAW,MAAM;AAAA,gBACrB;AAAA,gBACA;AAAA,kBACE,QAAQ;AAAA,kBACR,SAAS;AAAA,oBACP,gBAAgB;AAAA,kBAClB;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,UAAU,KAAK;AAChE,+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,MAAM;AAC7C,wBAAM,QAAQ;AAGd,sBAAI,WAAW,OAAO;AACpB,0BAAM,QAAQ,IAAI;AAAA,sBACf,MAAc,MAAM;AAAA,sBACrB;AAAA,sBACA;AAAA,sBACA;AAAA,oBACF;AACA,mCAAe,KAAK;AACpB,0BAAM;AAAA,kBACR;AAEA,wBAAM,SAAS,qBAAqB,OAAO,KAAK;AAChD,6BAAW,SAAS,QAAQ;AAC1B,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;;;ACnMO,IAAM,SAAS,eAAe;AAAA,EACnC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,YAAY;AAAA,IACV,KAAK,iBAAiB;AAAA,EACxB;AACF,CAAC;","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":[]}
|
package/dist/http/index.d.ts
CHANGED
|
@@ -1,60 +1,257 @@
|
|
|
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-
|
|
2
|
-
import { P as ProviderConfig, d as Modality, U as UPPError, c as ErrorCode } from '../provider-
|
|
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.
|
|
6
|
+
* @module http/fetch
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Executes an HTTP fetch request with automatic retry, timeout handling, and error normalization.
|
|
11
|
+
*
|
|
12
|
+
* This function wraps the standard fetch API with additional capabilities:
|
|
13
|
+
* - Configurable timeout with automatic request cancellation
|
|
14
|
+
* - Retry strategy support (exponential backoff, linear, token bucket, etc.)
|
|
15
|
+
* - Pre-request delay support for rate limiting strategies
|
|
16
|
+
* - Automatic Retry-After header parsing and handling
|
|
17
|
+
* - Error normalization to UPPError format
|
|
18
|
+
*
|
|
19
|
+
* @param url - The URL to fetch
|
|
20
|
+
* @param init - Standard fetch RequestInit options (method, headers, body, etc.)
|
|
21
|
+
* @param config - Provider configuration containing fetch customization, timeout, and retry strategy
|
|
22
|
+
* @param provider - Provider identifier for error context (e.g., 'openai', 'anthropic')
|
|
23
|
+
* @param modality - Request modality for error context (e.g., 'llm', 'embedding', 'image')
|
|
24
|
+
* @returns The successful Response object
|
|
6
25
|
*
|
|
7
|
-
* @
|
|
8
|
-
* @
|
|
9
|
-
* @
|
|
10
|
-
* @
|
|
11
|
-
* @
|
|
26
|
+
* @throws {UPPError} RATE_LIMITED - When rate limited and retries exhausted
|
|
27
|
+
* @throws {UPPError} NETWORK_ERROR - When a network failure occurs
|
|
28
|
+
* @throws {UPPError} TIMEOUT - When the request times out
|
|
29
|
+
* @throws {UPPError} CANCELLED - When the request is aborted via signal
|
|
30
|
+
* @throws {UPPError} Various codes based on HTTP status (see statusToErrorCode)
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const response = await doFetch(
|
|
35
|
+
* 'https://api.openai.com/v1/chat/completions',
|
|
36
|
+
* {
|
|
37
|
+
* method: 'POST',
|
|
38
|
+
* headers: { 'Authorization': 'Bearer sk-...' },
|
|
39
|
+
* body: JSON.stringify({ model: 'gpt-4', messages: [] })
|
|
40
|
+
* },
|
|
41
|
+
* { timeout: 30000, retryStrategy: new ExponentialBackoff() },
|
|
42
|
+
* 'openai',
|
|
43
|
+
* 'llm'
|
|
44
|
+
* );
|
|
45
|
+
* ```
|
|
12
46
|
*/
|
|
13
47
|
declare function doFetch(url: string, init: RequestInit, config: ProviderConfig, provider: string, modality: Modality): Promise<Response>;
|
|
14
48
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
49
|
+
* Executes an HTTP fetch request for streaming responses.
|
|
50
|
+
*
|
|
51
|
+
* Unlike {@link doFetch}, this function returns the response immediately without
|
|
52
|
+
* checking the HTTP status. This is necessary for Server-Sent Events (SSE) and
|
|
53
|
+
* other streaming protocols where error information may be embedded in the stream.
|
|
54
|
+
*
|
|
55
|
+
* The caller is responsible for:
|
|
56
|
+
* - Checking response.ok and handling HTTP errors
|
|
57
|
+
* - Parsing the response stream (e.g., using parseSSEStream)
|
|
58
|
+
* - Handling stream-specific error conditions
|
|
59
|
+
*
|
|
60
|
+
* Retries are not performed for streaming requests since partial data may have
|
|
61
|
+
* already been consumed by the caller.
|
|
62
|
+
*
|
|
63
|
+
* @param url - The URL to fetch
|
|
64
|
+
* @param init - Standard fetch RequestInit options
|
|
65
|
+
* @param config - Provider configuration containing fetch customization and timeout
|
|
66
|
+
* @param provider - Provider identifier for error context
|
|
67
|
+
* @param modality - Request modality for error context
|
|
68
|
+
* @returns The Response object (may have non-2xx status)
|
|
69
|
+
*
|
|
70
|
+
* @throws {UPPError} NETWORK_ERROR - When a network failure occurs
|
|
71
|
+
* @throws {UPPError} TIMEOUT - When the request times out
|
|
72
|
+
* @throws {UPPError} CANCELLED - When the request is aborted via signal
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const response = await doStreamFetch(
|
|
77
|
+
* 'https://api.openai.com/v1/chat/completions',
|
|
78
|
+
* {
|
|
79
|
+
* method: 'POST',
|
|
80
|
+
* headers: { 'Authorization': 'Bearer sk-...' },
|
|
81
|
+
* body: JSON.stringify({ model: 'gpt-4', messages: [], stream: true })
|
|
82
|
+
* },
|
|
83
|
+
* { timeout: 120000 },
|
|
84
|
+
* 'openai',
|
|
85
|
+
* 'llm'
|
|
86
|
+
* );
|
|
87
|
+
*
|
|
88
|
+
* if (!response.ok) {
|
|
89
|
+
* throw await normalizeHttpError(response, 'openai', 'llm');
|
|
90
|
+
* }
|
|
91
|
+
*
|
|
92
|
+
* for await (const event of parseSSEStream(response.body!)) {
|
|
93
|
+
* console.log(event);
|
|
94
|
+
* }
|
|
95
|
+
* ```
|
|
17
96
|
*/
|
|
18
97
|
declare function doStreamFetch(url: string, init: RequestInit, config: ProviderConfig, provider: string, modality: Modality): Promise<Response>;
|
|
19
98
|
|
|
20
99
|
/**
|
|
21
|
-
* Server-Sent Events (SSE) stream
|
|
100
|
+
* Server-Sent Events (SSE) stream parsing utilities.
|
|
101
|
+
* @module http/sse
|
|
22
102
|
*/
|
|
23
103
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
104
|
+
* Parses a Server-Sent Events stream into JSON objects.
|
|
105
|
+
*
|
|
106
|
+
* This async generator handles the standard SSE wire format:
|
|
107
|
+
* - Lines prefixed with "data:" contain event data
|
|
108
|
+
* - Lines prefixed with "event:" specify event types
|
|
109
|
+
* - Lines prefixed with ":" are comments (used for keep-alive)
|
|
110
|
+
* - Events are separated by double newlines
|
|
111
|
+
* - Stream terminates on "[DONE]" message (OpenAI convention)
|
|
28
112
|
*
|
|
29
|
-
*
|
|
113
|
+
* Also handles non-standard formats used by some providers:
|
|
114
|
+
* - Raw JSON without "data:" prefix (Google)
|
|
115
|
+
* - Multi-line data fields
|
|
116
|
+
*
|
|
117
|
+
* @param body - ReadableStream from fetch response body
|
|
118
|
+
* @yields Parsed JSON objects from each SSE event
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```typescript
|
|
122
|
+
* const response = await doStreamFetch(url, init, config, 'openai', 'llm');
|
|
123
|
+
*
|
|
124
|
+
* for await (const event of parseSSEStream(response.body!)) {
|
|
125
|
+
* // event is parsed JSON from each SSE data field
|
|
126
|
+
* const chunk = event as OpenAIStreamChunk;
|
|
127
|
+
* const delta = chunk.choices[0]?.delta?.content;
|
|
128
|
+
* if (delta) {
|
|
129
|
+
* process.stdout.write(delta);
|
|
130
|
+
* }
|
|
131
|
+
* }
|
|
132
|
+
* ```
|
|
30
133
|
*/
|
|
31
134
|
declare function parseSSEStream(body: ReadableStream<Uint8Array>): AsyncGenerator<unknown, void, unknown>;
|
|
32
135
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
136
|
+
* Parses a simple text stream without SSE formatting.
|
|
137
|
+
*
|
|
138
|
+
* This is a simpler alternative to {@link parseSSEStream} for providers
|
|
139
|
+
* that stream raw text deltas without SSE event wrappers. Each chunk
|
|
140
|
+
* from the response body is decoded and yielded as-is.
|
|
141
|
+
*
|
|
142
|
+
* Use this for:
|
|
143
|
+
* - Plain text streaming responses
|
|
144
|
+
* - Providers with custom streaming formats
|
|
145
|
+
* - Testing and debugging stream handling
|
|
146
|
+
*
|
|
147
|
+
* @param body - ReadableStream from fetch response body
|
|
148
|
+
* @yields Decoded text strings from each stream chunk
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* const response = await doStreamFetch(url, init, config, 'custom', 'llm');
|
|
153
|
+
*
|
|
154
|
+
* for await (const text of parseSimpleTextStream(response.body!)) {
|
|
155
|
+
* process.stdout.write(text);
|
|
156
|
+
* }
|
|
157
|
+
* ```
|
|
35
158
|
*/
|
|
36
159
|
declare function parseSimpleTextStream(body: ReadableStream<Uint8Array>): AsyncGenerator<string, void, unknown>;
|
|
37
160
|
|
|
38
161
|
/**
|
|
39
|
-
*
|
|
162
|
+
* HTTP error handling and normalization utilities.
|
|
163
|
+
* @module http/errors
|
|
164
|
+
*/
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Maps HTTP status codes to standardized UPP error codes.
|
|
168
|
+
*
|
|
169
|
+
* This function provides consistent error categorization across all providers:
|
|
170
|
+
* - 400 -> INVALID_REQUEST (bad request format or parameters)
|
|
171
|
+
* - 401, 403 -> AUTHENTICATION_FAILED (invalid or missing credentials)
|
|
172
|
+
* - 404 -> MODEL_NOT_FOUND (requested model does not exist)
|
|
173
|
+
* - 408 -> TIMEOUT (request timed out)
|
|
174
|
+
* - 413 -> CONTEXT_LENGTH_EXCEEDED (input too long)
|
|
175
|
+
* - 429 -> RATE_LIMITED (too many requests)
|
|
176
|
+
* - 5xx -> PROVIDER_ERROR (server-side issues)
|
|
177
|
+
*
|
|
178
|
+
* @param status - HTTP status code from the response
|
|
179
|
+
* @returns The corresponding UPP ErrorCode
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* const errorCode = statusToErrorCode(429);
|
|
184
|
+
* // Returns 'RATE_LIMITED'
|
|
185
|
+
*
|
|
186
|
+
* const serverError = statusToErrorCode(503);
|
|
187
|
+
* // Returns 'PROVIDER_ERROR'
|
|
188
|
+
* ```
|
|
40
189
|
*/
|
|
41
190
|
declare function statusToErrorCode(status: number): ErrorCode;
|
|
42
191
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
192
|
+
* Normalizes HTTP error responses into standardized UPPError objects.
|
|
193
|
+
*
|
|
194
|
+
* This function performs several operations:
|
|
195
|
+
* 1. Maps the HTTP status code to an appropriate ErrorCode
|
|
196
|
+
* 2. Attempts to extract a meaningful error message from the response body
|
|
197
|
+
* 3. Handles various provider-specific error response formats
|
|
198
|
+
*
|
|
199
|
+
* Supported error message formats:
|
|
200
|
+
* - `{ error: { message: "..." } }` (OpenAI, Anthropic)
|
|
201
|
+
* - `{ message: "..." }` (simple format)
|
|
202
|
+
* - `{ error: { error: { message: "..." } } }` (nested format)
|
|
203
|
+
* - `{ detail: "..." }` (FastAPI style)
|
|
204
|
+
* - Plain text body (if under 200 characters)
|
|
205
|
+
*
|
|
206
|
+
* @param response - The HTTP Response object with non-2xx status
|
|
207
|
+
* @param provider - Provider identifier for error context
|
|
208
|
+
* @param modality - Request modality for error context
|
|
209
|
+
* @returns A UPPError with normalized code and message
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* if (!response.ok) {
|
|
214
|
+
* const error = await normalizeHttpError(response, 'openai', 'llm');
|
|
215
|
+
* // error.code might be 'RATE_LIMITED' for 429
|
|
216
|
+
* // error.message contains provider's error message
|
|
217
|
+
* throw error;
|
|
218
|
+
* }
|
|
219
|
+
* ```
|
|
46
220
|
*/
|
|
47
221
|
declare function normalizeHttpError(response: Response, provider: string, modality: Modality): Promise<UPPError>;
|
|
48
222
|
/**
|
|
49
|
-
*
|
|
223
|
+
* Creates a UPPError for network failures (DNS, connection, etc.).
|
|
224
|
+
*
|
|
225
|
+
* Use this when the request fails before receiving any HTTP response,
|
|
226
|
+
* such as DNS resolution failures, connection refused, or network unreachable.
|
|
227
|
+
*
|
|
228
|
+
* @param error - The underlying Error that caused the failure
|
|
229
|
+
* @param provider - Provider identifier for error context
|
|
230
|
+
* @param modality - Request modality for error context
|
|
231
|
+
* @returns A UPPError with NETWORK_ERROR code and the original error attached
|
|
50
232
|
*/
|
|
51
233
|
declare function networkError(error: Error, provider: string, modality: Modality): UPPError;
|
|
52
234
|
/**
|
|
53
|
-
*
|
|
235
|
+
* Creates a UPPError for request timeout.
|
|
236
|
+
*
|
|
237
|
+
* Use this when the request exceeds the configured timeout duration
|
|
238
|
+
* and is aborted by the AbortController.
|
|
239
|
+
*
|
|
240
|
+
* @param timeout - The timeout duration in milliseconds that was exceeded
|
|
241
|
+
* @param provider - Provider identifier for error context
|
|
242
|
+
* @param modality - Request modality for error context
|
|
243
|
+
* @returns A UPPError with TIMEOUT code
|
|
54
244
|
*/
|
|
55
245
|
declare function timeoutError(timeout: number, provider: string, modality: Modality): UPPError;
|
|
56
246
|
/**
|
|
57
|
-
*
|
|
247
|
+
* Creates a UPPError for user-initiated request cancellation.
|
|
248
|
+
*
|
|
249
|
+
* Use this when the request is aborted via a user-provided AbortSignal,
|
|
250
|
+
* distinct from timeout-based cancellation.
|
|
251
|
+
*
|
|
252
|
+
* @param provider - Provider identifier for error context
|
|
253
|
+
* @param modality - Request modality for error context
|
|
254
|
+
* @returns A UPPError with CANCELLED code
|
|
58
255
|
*/
|
|
59
256
|
declare function cancelledError(provider: string, modality: Modality): UPPError;
|
|
60
257
|
|
package/dist/http/index.js
CHANGED
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
NoRetry,
|
|
5
5
|
RetryAfterStrategy,
|
|
6
6
|
TokenBucket
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-U4JJC2YX.js";
|
|
8
8
|
import {
|
|
9
9
|
parseSSEStream,
|
|
10
10
|
parseSimpleTextStream
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-Z7RBRCRN.js";
|
|
12
12
|
import {
|
|
13
13
|
DynamicKey,
|
|
14
14
|
RoundRobinKeys,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
resolveApiKey,
|
|
22
22
|
statusToErrorCode,
|
|
23
23
|
timeoutError
|
|
24
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-MOU4U3PO.js";
|
|
25
25
|
export {
|
|
26
26
|
DynamicKey,
|
|
27
27
|
ExponentialBackoff,
|