UNPKG

@ai-sdk/google

Version:

The **[Google Generative AI provider](https://ai-sdk.dev/providers/ai-sdk-providers/google-generative-ai)** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for the [Google Generative AI](https://ai.google/discover/generativeai/)

1,438 lines (1,421 loc) 225 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { VERSION: () => VERSION, createGoogleGenerativeAI: () => createGoogleGenerativeAI, google: () => google }); module.exports = __toCommonJS(index_exports); // src/google-provider.ts var import_provider_utils23 = require("@ai-sdk/provider-utils"); // src/version.ts var VERSION = true ? "3.0.79" : "0.0.0-test"; // src/google-generative-ai-embedding-model.ts var import_provider = require("@ai-sdk/provider"); var import_provider_utils3 = require("@ai-sdk/provider-utils"); var import_v43 = require("zod/v4"); // src/google-error.ts var import_provider_utils = require("@ai-sdk/provider-utils"); var import_v4 = require("zod/v4"); var googleErrorDataSchema = (0, import_provider_utils.lazySchema)( () => (0, import_provider_utils.zodSchema)( import_v4.z.object({ error: import_v4.z.object({ code: import_v4.z.number().nullable(), message: import_v4.z.string(), status: import_v4.z.string() }) }) ) ); var googleFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({ errorSchema: googleErrorDataSchema, errorToMessage: (data) => data.error.message }); // src/google-generative-ai-embedding-options.ts var import_provider_utils2 = require("@ai-sdk/provider-utils"); var import_v42 = require("zod/v4"); var googleEmbeddingContentPartSchema = import_v42.z.union([ import_v42.z.object({ text: import_v42.z.string() }), import_v42.z.object({ inlineData: import_v42.z.object({ mimeType: import_v42.z.string(), data: import_v42.z.string() }) }), import_v42.z.object({ fileData: import_v42.z.object({ fileUri: import_v42.z.string(), mimeType: import_v42.z.string() }) }) ]); var googleEmbeddingModelOptions = (0, import_provider_utils2.lazySchema)( () => (0, import_provider_utils2.zodSchema)( import_v42.z.object({ /** * Optional. Optional reduced dimension for the output embedding. * If set, excessive values in the output embedding are truncated from the end. */ outputDimensionality: import_v42.z.number().optional(), /** * Optional. Specifies the task type for generating embeddings. * Supported task types: * - SEMANTIC_SIMILARITY: Optimized for text similarity. * - CLASSIFICATION: Optimized for text classification. * - CLUSTERING: Optimized for clustering texts based on similarity. * - RETRIEVAL_DOCUMENT: Optimized for document retrieval. * - RETRIEVAL_QUERY: Optimized for query-based retrieval. * - QUESTION_ANSWERING: Optimized for answering questions. * - FACT_VERIFICATION: Optimized for verifying factual information. * - CODE_RETRIEVAL_QUERY: Optimized for retrieving code blocks based on natural language queries. */ taskType: import_v42.z.enum([ "SEMANTIC_SIMILARITY", "CLASSIFICATION", "CLUSTERING", "RETRIEVAL_DOCUMENT", "RETRIEVAL_QUERY", "QUESTION_ANSWERING", "FACT_VERIFICATION", "CODE_RETRIEVAL_QUERY" ]).optional(), /** * Optional. Per-value multimodal content parts for embedding non-text * content (images, video, PDF, audio). Each entry corresponds to the * embedding value at the same index and its parts are merged with the * text value in the request. Use `null` for entries that are text-only. * * The array length must match the number of values being embedded. In * the case of a single embedding, the array length must be 1. */ content: import_v42.z.array(import_v42.z.array(googleEmbeddingContentPartSchema).min(1).nullable()).optional() }) ) ); // src/google-generative-ai-embedding-model.ts var GoogleGenerativeAIEmbeddingModel = class { constructor(modelId, config) { this.specificationVersion = "v3"; this.maxEmbeddingsPerCall = 2048; this.supportsParallelCalls = true; this.modelId = modelId; this.config = config; } get provider() { return this.config.provider; } async doEmbed({ values, headers, abortSignal, providerOptions }) { const googleOptions = await (0, import_provider_utils3.parseProviderOptions)({ provider: "google", providerOptions, schema: googleEmbeddingModelOptions }); if (values.length > this.maxEmbeddingsPerCall) { throw new import_provider.TooManyEmbeddingValuesForCallError({ provider: this.provider, modelId: this.modelId, maxEmbeddingsPerCall: this.maxEmbeddingsPerCall, values }); } const mergedHeaders = (0, import_provider_utils3.combineHeaders)( await (0, import_provider_utils3.resolve)(this.config.headers), headers ); const multimodalContent = googleOptions == null ? void 0 : googleOptions.content; if (multimodalContent != null && multimodalContent.length !== values.length) { throw new Error( `The number of multimodal content entries (${multimodalContent.length}) must match the number of values (${values.length}).` ); } if (values.length === 1) { const valueParts = multimodalContent == null ? void 0 : multimodalContent[0]; const textPart = values[0] ? [{ text: values[0] }] : []; const parts = valueParts != null ? [...textPart, ...valueParts] : [{ text: values[0] }]; const { responseHeaders: responseHeaders2, value: response2, rawValue: rawValue2 } = await (0, import_provider_utils3.postJsonToApi)({ url: `${this.config.baseURL}/models/${this.modelId}:embedContent`, headers: mergedHeaders, body: { model: `models/${this.modelId}`, content: { parts }, outputDimensionality: googleOptions == null ? void 0 : googleOptions.outputDimensionality, taskType: googleOptions == null ? void 0 : googleOptions.taskType }, failedResponseHandler: googleFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)( googleGenerativeAISingleEmbeddingResponseSchema ), abortSignal, fetch: this.config.fetch }); return { warnings: [], embeddings: [response2.embedding.values], usage: void 0, response: { headers: responseHeaders2, body: rawValue2 } }; } const { responseHeaders, value: response, rawValue } = await (0, import_provider_utils3.postJsonToApi)({ url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`, headers: mergedHeaders, body: { requests: values.map((value, index) => { const valueParts = multimodalContent == null ? void 0 : multimodalContent[index]; const textPart = value ? [{ text: value }] : []; return { model: `models/${this.modelId}`, content: { role: "user", parts: valueParts != null ? [...textPart, ...valueParts] : [{ text: value }] }, outputDimensionality: googleOptions == null ? void 0 : googleOptions.outputDimensionality, taskType: googleOptions == null ? void 0 : googleOptions.taskType }; }) }, failedResponseHandler: googleFailedResponseHandler, successfulResponseHandler: (0, import_provider_utils3.createJsonResponseHandler)( googleGenerativeAITextEmbeddingResponseSchema ), abortSignal, fetch: this.config.fetch }); return { warnings: [], embeddings: response.embeddings.map((item) => item.values), usage: void 0, response: { headers: responseHeaders, body: rawValue } }; } }; var googleGenerativeAITextEmbeddingResponseSchema = (0, import_provider_utils3.lazySchema)( () => (0, import_provider_utils3.zodSchema)( import_v43.z.object({ embeddings: import_v43.z.array(import_v43.z.object({ values: import_v43.z.array(import_v43.z.number()) })) }) ) ); var googleGenerativeAISingleEmbeddingResponseSchema = (0, import_provider_utils3.lazySchema)( () => (0, import_provider_utils3.zodSchema)( import_v43.z.object({ embedding: import_v43.z.object({ values: import_v43.z.array(import_v43.z.number()) }) }) ) ); // src/google-generative-ai-language-model.ts var import_provider_utils6 = require("@ai-sdk/provider-utils"); var import_v45 = require("zod/v4"); // src/convert-google-generative-ai-usage.ts function convertGoogleGenerativeAIUsage(usage) { var _a, _b, _c, _d; if (usage == null) { return { inputTokens: { total: void 0, noCache: void 0, cacheRead: void 0, cacheWrite: void 0 }, outputTokens: { total: void 0, text: void 0, reasoning: void 0 }, raw: void 0 }; } const promptTokens = (_a = usage.promptTokenCount) != null ? _a : 0; const candidatesTokens = (_b = usage.candidatesTokenCount) != null ? _b : 0; const cachedContentTokens = (_c = usage.cachedContentTokenCount) != null ? _c : 0; const thoughtsTokens = (_d = usage.thoughtsTokenCount) != null ? _d : 0; return { inputTokens: { total: promptTokens, noCache: promptTokens - cachedContentTokens, cacheRead: cachedContentTokens, cacheWrite: void 0 }, outputTokens: { total: candidatesTokens + thoughtsTokens, text: candidatesTokens, reasoning: thoughtsTokens }, raw: usage }; } // src/convert-json-schema-to-openapi-schema.ts function convertJSONSchemaToOpenAPISchema(jsonSchema, isRoot = true) { if (jsonSchema == null) { return void 0; } if (isEmptyObjectSchema(jsonSchema)) { if (isRoot) { return void 0; } if (typeof jsonSchema === "object" && jsonSchema.description) { return { type: "object", description: jsonSchema.description }; } return { type: "object" }; } if (typeof jsonSchema === "boolean") { return { type: "boolean", properties: {} }; } const { type, description, required, properties, items, allOf, anyOf, oneOf, format, const: constValue, minLength, enum: enumValues } = jsonSchema; const result = {}; if (description) result.description = description; if (required) result.required = required; if (format) result.format = format; if (constValue !== void 0) { result.enum = [constValue]; } if (type) { if (Array.isArray(type)) { const hasNull = type.includes("null"); const nonNullTypes = type.filter((t) => t !== "null"); if (nonNullTypes.length === 0) { result.type = "null"; } else { result.anyOf = nonNullTypes.map((t) => ({ type: t })); if (hasNull) { result.nullable = true; } } } else { result.type = type; } } if (enumValues !== void 0) { result.enum = enumValues; } if (properties != null) { result.properties = Object.entries(properties).reduce( (acc, [key, value]) => { acc[key] = convertJSONSchemaToOpenAPISchema(value, false); return acc; }, {} ); } if (items) { result.items = Array.isArray(items) ? items.map((item) => convertJSONSchemaToOpenAPISchema(item, false)) : convertJSONSchemaToOpenAPISchema(items, false); } if (allOf) { result.allOf = allOf.map( (item) => convertJSONSchemaToOpenAPISchema(item, false) ); } if (anyOf) { if (anyOf.some( (schema) => typeof schema === "object" && (schema == null ? void 0 : schema.type) === "null" )) { const nonNullSchemas = anyOf.filter( (schema) => !(typeof schema === "object" && (schema == null ? void 0 : schema.type) === "null") ); if (nonNullSchemas.length === 1) { const converted = convertJSONSchemaToOpenAPISchema( nonNullSchemas[0], false ); if (typeof converted === "object") { result.nullable = true; Object.assign(result, converted); } } else { result.anyOf = nonNullSchemas.map( (item) => convertJSONSchemaToOpenAPISchema(item, false) ); result.nullable = true; } } else { result.anyOf = anyOf.map( (item) => convertJSONSchemaToOpenAPISchema(item, false) ); } } if (oneOf) { result.oneOf = oneOf.map( (item) => convertJSONSchemaToOpenAPISchema(item, false) ); } if (minLength !== void 0) { result.minLength = minLength; } return result; } function isEmptyObjectSchema(jsonSchema) { return jsonSchema != null && typeof jsonSchema === "object" && jsonSchema.type === "object" && (jsonSchema.properties == null || Object.keys(jsonSchema.properties).length === 0) && !jsonSchema.additionalProperties; } // src/convert-to-google-generative-ai-messages.ts var import_provider2 = require("@ai-sdk/provider"); var import_provider_utils4 = require("@ai-sdk/provider-utils"); var dataUrlRegex = /^data:([^;,]+);base64,(.+)$/s; function parseBase64DataUrl(value) { const match = dataUrlRegex.exec(value); if (match == null) { return void 0; } return { mediaType: match[1], data: match[2] }; } function convertUrlToolResultPart(url) { const parsedDataUrl = parseBase64DataUrl(url); if (parsedDataUrl == null) { return void 0; } return { inlineData: { mimeType: parsedDataUrl.mediaType, data: parsedDataUrl.data } }; } function appendToolResultParts(parts, toolName, outputValue, toolCallId) { const functionResponseParts = []; const responseTextParts = []; for (const contentPart of outputValue) { switch (contentPart.type) { case "text": { responseTextParts.push(contentPart.text); break; } case "image-data": case "file-data": { functionResponseParts.push({ inlineData: { mimeType: contentPart.mediaType, data: contentPart.data } }); break; } case "image-url": case "file-url": { const functionResponsePart = convertUrlToolResultPart( contentPart.url ); if (functionResponsePart != null) { functionResponseParts.push(functionResponsePart); } else { responseTextParts.push(JSON.stringify(contentPart)); } break; } default: { responseTextParts.push(JSON.stringify(contentPart)); break; } } } parts.push({ functionResponse: { ...toolCallId != null ? { id: toolCallId } : {}, name: toolName, response: { name: toolName, content: responseTextParts.length > 0 ? responseTextParts.join("\n") : "Tool executed successfully." }, ...functionResponseParts.length > 0 ? { parts: functionResponseParts } : {} } }); } function appendLegacyToolResultParts(parts, toolName, outputValue, toolCallId) { for (const contentPart of outputValue) { switch (contentPart.type) { case "text": parts.push({ functionResponse: { ...toolCallId != null ? { id: toolCallId } : {}, name: toolName, response: { name: toolName, content: contentPart.text } } }); break; case "image-data": parts.push( { inlineData: { mimeType: String(contentPart.mediaType), data: String(contentPart.data) } }, { text: "Tool executed successfully and returned this image as a response" } ); break; default: parts.push({ text: JSON.stringify(contentPart) }); break; } } } function convertToGoogleGenerativeAIMessages(prompt, options) { var _a, _b, _c, _d, _e, _f, _g, _h; const systemInstructionParts = []; const contents = []; let systemMessagesAllowed = true; const isGemmaModel = (_a = options == null ? void 0 : options.isGemmaModel) != null ? _a : false; const providerOptionsName = (_b = options == null ? void 0 : options.providerOptionsName) != null ? _b : "google"; const supportsFunctionResponseParts = (_c = options == null ? void 0 : options.supportsFunctionResponseParts) != null ? _c : true; for (const { role, content } of prompt) { switch (role) { case "system": { if (!systemMessagesAllowed) { throw new import_provider2.UnsupportedFunctionalityError({ functionality: "system messages are only supported at the beginning of the conversation" }); } systemInstructionParts.push({ text: content }); break; } case "user": { systemMessagesAllowed = false; const parts = []; for (const part of content) { switch (part.type) { case "text": { parts.push({ text: part.text }); break; } case "file": { const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType; parts.push( part.data instanceof URL ? { fileData: { mimeType: mediaType, fileUri: part.data.toString() } } : { inlineData: { mimeType: mediaType, data: (0, import_provider_utils4.convertToBase64)(part.data) } } ); break; } } } contents.push({ role: "user", parts }); break; } case "assistant": { systemMessagesAllowed = false; contents.push({ role: "model", parts: content.map((part) => { var _a2, _b2, _c2, _d2; const providerOpts = (_d2 = (_a2 = part.providerOptions) == null ? void 0 : _a2[providerOptionsName]) != null ? _d2 : providerOptionsName !== "google" ? (_b2 = part.providerOptions) == null ? void 0 : _b2.google : (_c2 = part.providerOptions) == null ? void 0 : _c2.vertex; const thoughtSignature = (providerOpts == null ? void 0 : providerOpts.thoughtSignature) != null ? String(providerOpts.thoughtSignature) : void 0; switch (part.type) { case "text": { return part.text.length === 0 ? void 0 : { text: part.text, thoughtSignature }; } case "reasoning": { return part.text.length === 0 ? void 0 : { text: part.text, thought: true, thoughtSignature }; } case "file": { if (part.data instanceof URL) { throw new import_provider2.UnsupportedFunctionalityError({ functionality: "File data URLs in assistant messages are not supported" }); } return { inlineData: { mimeType: part.mediaType, data: (0, import_provider_utils4.convertToBase64)(part.data) }, ...(providerOpts == null ? void 0 : providerOpts.thought) === true ? { thought: true } : {}, thoughtSignature }; } case "tool-call": { const serverToolCallId = (providerOpts == null ? void 0 : providerOpts.serverToolCallId) != null ? String(providerOpts.serverToolCallId) : void 0; const serverToolType = (providerOpts == null ? void 0 : providerOpts.serverToolType) != null ? String(providerOpts.serverToolType) : void 0; if (serverToolCallId && serverToolType) { return { toolCall: { toolType: serverToolType, args: typeof part.input === "string" ? JSON.parse(part.input) : part.input, id: serverToolCallId }, thoughtSignature }; } return { functionCall: { ...part.toolCallId != null ? { id: part.toolCallId } : {}, name: part.toolName, args: part.input }, thoughtSignature }; } case "tool-result": { const serverToolCallId = (providerOpts == null ? void 0 : providerOpts.serverToolCallId) != null ? String(providerOpts.serverToolCallId) : void 0; const serverToolType = (providerOpts == null ? void 0 : providerOpts.serverToolType) != null ? String(providerOpts.serverToolType) : void 0; if (serverToolCallId && serverToolType) { return { toolResponse: { toolType: serverToolType, response: part.output.type === "json" ? part.output.value : {}, id: serverToolCallId }, thoughtSignature }; } return void 0; } } }).filter((part) => part !== void 0) }); break; } case "tool": { systemMessagesAllowed = false; const parts = []; for (const part of content) { if (part.type === "tool-approval-response") { continue; } const partProviderOpts = (_g = (_d = part.providerOptions) == null ? void 0 : _d[providerOptionsName]) != null ? _g : providerOptionsName !== "google" ? (_e = part.providerOptions) == null ? void 0 : _e.google : (_f = part.providerOptions) == null ? void 0 : _f.vertex; const serverToolCallId = (partProviderOpts == null ? void 0 : partProviderOpts.serverToolCallId) != null ? String(partProviderOpts.serverToolCallId) : void 0; const serverToolType = (partProviderOpts == null ? void 0 : partProviderOpts.serverToolType) != null ? String(partProviderOpts.serverToolType) : void 0; if (serverToolCallId && serverToolType) { const serverThoughtSignature = (partProviderOpts == null ? void 0 : partProviderOpts.thoughtSignature) != null ? String(partProviderOpts.thoughtSignature) : void 0; if (contents.length > 0) { const lastContent = contents[contents.length - 1]; if (lastContent.role === "model") { lastContent.parts.push({ toolResponse: { toolType: serverToolType, response: part.output.type === "json" ? part.output.value : {}, id: serverToolCallId }, thoughtSignature: serverThoughtSignature }); continue; } } } const output = part.output; if (output.type === "content") { if (supportsFunctionResponseParts) { appendToolResultParts( parts, part.toolName, output.value, part.toolCallId ); } else { appendLegacyToolResultParts( parts, part.toolName, output.value, part.toolCallId ); } } else { parts.push({ functionResponse: { ...part.toolCallId != null ? { id: part.toolCallId } : {}, name: part.toolName, response: { name: part.toolName, content: output.type === "execution-denied" ? (_h = output.reason) != null ? _h : "Tool execution denied." : output.value } } }); } } contents.push({ role: "user", parts }); break; } } } if (isGemmaModel && systemInstructionParts.length > 0 && contents.length > 0 && contents[0].role === "user") { const systemText = systemInstructionParts.map((part) => part.text).join("\n\n"); contents[0].parts.unshift({ text: systemText + "\n\n" }); } return { systemInstruction: systemInstructionParts.length > 0 && !isGemmaModel ? { parts: systemInstructionParts } : void 0, contents }; } // src/get-model-path.ts function getModelPath(modelId) { return modelId.includes("/") ? modelId : `models/${modelId}`; } // src/google-generative-ai-options.ts var import_provider_utils5 = require("@ai-sdk/provider-utils"); var import_v44 = require("zod/v4"); var googleLanguageModelOptions = (0, import_provider_utils5.lazySchema)( () => (0, import_provider_utils5.zodSchema)( import_v44.z.object({ responseModalities: import_v44.z.array(import_v44.z.enum(["TEXT", "IMAGE"])).optional(), thinkingConfig: import_v44.z.object({ thinkingBudget: import_v44.z.number().optional(), includeThoughts: import_v44.z.boolean().optional(), // https://ai.google.dev/gemini-api/docs/gemini-3?thinking=high#thinking_level thinkingLevel: import_v44.z.enum(["minimal", "low", "medium", "high"]).optional() }).optional(), /** * Optional. * The name of the cached content used as context to serve the prediction. * Format: cachedContents/{cachedContent} */ cachedContent: import_v44.z.string().optional(), /** * Optional. Enable structured output. Default is true. * * This is useful when the JSON Schema contains elements that are * not supported by the OpenAPI schema version that * Google Generative AI uses. You can use this to disable * structured outputs if you need to. */ structuredOutputs: import_v44.z.boolean().optional(), /** * Optional. A list of unique safety settings for blocking unsafe content. */ safetySettings: import_v44.z.array( import_v44.z.object({ category: import_v44.z.enum([ "HARM_CATEGORY_UNSPECIFIED", "HARM_CATEGORY_HATE_SPEECH", "HARM_CATEGORY_DANGEROUS_CONTENT", "HARM_CATEGORY_HARASSMENT", "HARM_CATEGORY_SEXUALLY_EXPLICIT", "HARM_CATEGORY_CIVIC_INTEGRITY" ]), threshold: import_v44.z.enum([ "HARM_BLOCK_THRESHOLD_UNSPECIFIED", "BLOCK_LOW_AND_ABOVE", "BLOCK_MEDIUM_AND_ABOVE", "BLOCK_ONLY_HIGH", "BLOCK_NONE", "OFF" ]) }) ).optional(), threshold: import_v44.z.enum([ "HARM_BLOCK_THRESHOLD_UNSPECIFIED", "BLOCK_LOW_AND_ABOVE", "BLOCK_MEDIUM_AND_ABOVE", "BLOCK_ONLY_HIGH", "BLOCK_NONE", "OFF" ]).optional(), /** * Optional. Enables timestamp understanding for audio-only files. * * https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/audio-understanding */ audioTimestamp: import_v44.z.boolean().optional(), /** * Optional. Defines labels used in billing reports. Available on Vertex AI only. * * https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/add-labels-to-api-calls */ labels: import_v44.z.record(import_v44.z.string(), import_v44.z.string()).optional(), /** * Optional. If specified, the media resolution specified will be used. * * https://ai.google.dev/api/generate-content#MediaResolution */ mediaResolution: import_v44.z.enum([ "MEDIA_RESOLUTION_UNSPECIFIED", "MEDIA_RESOLUTION_LOW", "MEDIA_RESOLUTION_MEDIUM", "MEDIA_RESOLUTION_HIGH" ]).optional(), /** * Optional. Configures the image generation aspect ratio for Gemini models. * * https://ai.google.dev/gemini-api/docs/image-generation#aspect_ratios */ imageConfig: import_v44.z.object({ aspectRatio: import_v44.z.enum([ "1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9", "1:8", "8:1", "1:4", "4:1" ]).optional(), imageSize: import_v44.z.enum(["1K", "2K", "4K", "512"]).optional() }).optional(), /** * Optional. Configuration for grounding retrieval. * Used to provide location context for Google Maps and Google Search grounding. * * https://cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-google-maps */ retrievalConfig: import_v44.z.object({ latLng: import_v44.z.object({ latitude: import_v44.z.number(), longitude: import_v44.z.number() }).optional() }).optional(), /** * Optional. When set to true, function call arguments will be streamed * incrementally via partialArgs in streaming responses. Only supported * on the Vertex AI API (not the Gemini API) and only for Gemini 3+ * models. * * @default false * * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#streaming-fc */ streamFunctionCallArguments: import_v44.z.boolean().optional(), /** * Optional. The service tier to use for the request. Sent as the * `serviceTier` body field. Gemini API only. */ serviceTier: import_v44.z.enum(["standard", "flex", "priority"]).optional(), /** * Optional. Vertex AI only. Sent as the * `X-Vertex-AI-LLM-Shared-Request-Type` request header to select a * shared (PayGo) tier. With Provisioned Throughput allocated and * `requestType` unset, the request falls back to this tier only if * PT capacity is exhausted. * * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/priority-paygo * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/flex-paygo */ sharedRequestType: import_v44.z.enum(["priority", "flex", "standard"]).optional(), /** * Optional. Vertex AI only. Sent as the `X-Vertex-AI-LLM-Request-Type` * request header. Set to `'shared'` together with `sharedRequestType` * to bypass Provisioned Throughput entirely. * * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/priority-paygo */ requestType: import_v44.z.enum(["shared"]).optional() }) ) ); // src/google-prepare-tools.ts var import_provider3 = require("@ai-sdk/provider"); function prepareTools({ tools, toolChoice, modelId, isVertexProvider = false }) { var _a, _b; tools = (tools == null ? void 0 : tools.length) ? tools : void 0; const toolWarnings = []; const isLatest = [ "gemini-flash-latest", "gemini-flash-lite-latest", "gemini-pro-latest" ].some((id) => id === modelId); const isGemini2orNewer = modelId.includes("gemini-2") || modelId.includes("gemini-3") || modelId.includes("nano-banana") || isLatest; const isGemini3orNewer = modelId.includes("gemini-3"); const supportsFileSearch = modelId.includes("gemini-2.5") || modelId.includes("gemini-3"); if (tools == null) { return { tools: void 0, toolConfig: void 0, toolWarnings }; } const hasFunctionTools = tools.some((tool) => tool.type === "function"); const hasProviderTools = tools.some((tool) => tool.type === "provider"); if (hasFunctionTools && hasProviderTools && !isGemini3orNewer) { toolWarnings.push({ type: "unsupported", feature: `combination of function and provider-defined tools` }); } if (hasProviderTools) { const googleTools2 = []; const ProviderTools = tools.filter((tool) => tool.type === "provider"); ProviderTools.forEach((tool) => { switch (tool.id) { case "google.google_search": if (isGemini2orNewer) { googleTools2.push({ googleSearch: { ...tool.args } }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "Google Search requires Gemini 2.0 or newer." }); } break; case "google.enterprise_web_search": if (isGemini2orNewer) { googleTools2.push({ enterpriseWebSearch: {} }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "Enterprise Web Search requires Gemini 2.0 or newer." }); } break; case "google.url_context": if (isGemini2orNewer) { googleTools2.push({ urlContext: {} }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "The URL context tool is not supported with other Gemini models than Gemini 2." }); } break; case "google.code_execution": if (isGemini2orNewer) { googleTools2.push({ codeExecution: {} }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "The code execution tool is not supported with other Gemini models than Gemini 2." }); } break; case "google.file_search": if (supportsFileSearch) { googleTools2.push({ fileSearch: { ...tool.args } }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "The file search tool is only supported with Gemini 2.5 models and Gemini 3 models." }); } break; case "google.vertex_rag_store": if (isGemini2orNewer) { googleTools2.push({ retrieval: { vertex_rag_store: { rag_resources: { rag_corpus: tool.args.ragCorpus }, similarity_top_k: tool.args.topK } } }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "The RAG store tool is not supported with other Gemini models than Gemini 2." }); } break; case "google.google_maps": if (isGemini2orNewer) { googleTools2.push({ googleMaps: {} }); } else { toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}`, details: "The Google Maps grounding tool is not supported with Gemini models other than Gemini 2 or newer." }); } break; default: toolWarnings.push({ type: "unsupported", feature: `provider-defined tool ${tool.id}` }); break; } }); if (hasFunctionTools && isGemini3orNewer && googleTools2.length > 0) { const functionDeclarations2 = []; for (const tool of tools) { if (tool.type === "function") { functionDeclarations2.push({ name: tool.name, description: (_a = tool.description) != null ? _a : "", parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema) }); } } const combinedToolConfig = { functionCallingConfig: { mode: "VALIDATED" }, ...!isVertexProvider && { includeServerSideToolInvocations: true } }; if (toolChoice != null) { switch (toolChoice.type) { case "auto": break; case "none": combinedToolConfig.functionCallingConfig = { mode: "NONE" }; break; case "required": combinedToolConfig.functionCallingConfig = { mode: "ANY" }; break; case "tool": combinedToolConfig.functionCallingConfig = { mode: "ANY", allowedFunctionNames: [toolChoice.toolName] }; break; } } return { tools: [...googleTools2, { functionDeclarations: functionDeclarations2 }], toolConfig: combinedToolConfig, toolWarnings }; } return { tools: googleTools2.length > 0 ? googleTools2 : void 0, toolConfig: void 0, toolWarnings }; } const functionDeclarations = []; let hasStrictTools = false; for (const tool of tools) { switch (tool.type) { case "function": functionDeclarations.push({ name: tool.name, description: (_b = tool.description) != null ? _b : "", parameters: convertJSONSchemaToOpenAPISchema(tool.inputSchema) }); if (tool.strict === true) { hasStrictTools = true; } break; default: toolWarnings.push({ type: "unsupported", feature: `function tool ${tool.name}` }); break; } } if (toolChoice == null) { return { tools: [{ functionDeclarations }], toolConfig: hasStrictTools ? { functionCallingConfig: { mode: "VALIDATED" } } : void 0, toolWarnings }; } const type = toolChoice.type; switch (type) { case "auto": return { tools: [{ functionDeclarations }], toolConfig: { functionCallingConfig: { mode: hasStrictTools ? "VALIDATED" : "AUTO" } }, toolWarnings }; case "none": return { tools: [{ functionDeclarations }], toolConfig: { functionCallingConfig: { mode: "NONE" } }, toolWarnings }; case "required": return { tools: [{ functionDeclarations }], toolConfig: { functionCallingConfig: { mode: hasStrictTools ? "VALIDATED" : "ANY" } }, toolWarnings }; case "tool": return { tools: [{ functionDeclarations }], toolConfig: { functionCallingConfig: { mode: hasStrictTools ? "VALIDATED" : "ANY", allowedFunctionNames: [toolChoice.toolName] } }, toolWarnings }; default: { const _exhaustiveCheck = type; throw new import_provider3.UnsupportedFunctionalityError({ functionality: `tool choice type: ${_exhaustiveCheck}` }); } } } // src/google-json-accumulator.ts var GoogleJSONAccumulator = class { constructor() { this.accumulatedArgs = {}; this.jsonText = ""; /** * Stack representing the currently "open" containers in the JSON output. * Entry 0 is always the root `{` object once the first value is written. */ this.pathStack = []; /** * Whether a string value is currently "open" (willContinue was true), * meaning the closing quote has not yet been emitted. */ this.stringOpen = false; } /** * Input: [{jsonPath:"$.brightness",numberValue:50}] * Output: { currentJSON:{brightness:50}, textDelta:'{"brightness":50' } */ processPartialArgs(partialArgs) { let delta = ""; for (const arg of partialArgs) { const rawPath = arg.jsonPath.replace(/^\$\./, ""); if (!rawPath) continue; const segments = parsePath(rawPath); const existingValue = getNestedValue(this.accumulatedArgs, segments); const isStringContinuation = arg.stringValue != null && existingValue !== void 0; if (isStringContinuation) { const escaped = JSON.stringify(arg.stringValue).slice(1, -1); setNestedValue( this.accumulatedArgs, segments, existingValue + arg.stringValue ); delta += escaped; continue; } const resolved = resolvePartialArgValue(arg); if (resolved == null) continue; setNestedValue(this.accumulatedArgs, segments, resolved.value); delta += this.emitNavigationTo(segments, arg, resolved.json); } this.jsonText += delta; return { currentJSON: this.accumulatedArgs, textDelta: delta }; } /** * Input: jsonText='{"brightness":50', accumulatedArgs={brightness:50} * Output: { finalJSON:'{"brightness":50}', closingDelta:'}' } */ finalize() { const finalArgs = JSON.stringify(this.accumulatedArgs); const closingDelta = finalArgs.slice(this.jsonText.length); return { finalJSON: finalArgs, closingDelta }; } /** * Input: pathStack=[] (first call) or pathStack=[root,...] (subsequent calls) * Output: '{' (first call) or '' (subsequent calls) */ ensureRoot() { if (this.pathStack.length === 0) { this.pathStack.push({ segment: "", isArray: false, childCount: 0 }); return "{"; } return ""; } /** * Emits the JSON text fragment needed to navigate from the current open * path to the new leaf at `targetSegments`, then writes the value. * * Input: targetSegments=["recipe","name"], arg={jsonPath:"$.recipe.name",stringValue:"Lasagna"}, valueJson='"Lasagna"' * Output: '{"recipe":{"name":"Lasagna"' */ emitNavigationTo(targetSegments, arg, valueJson) { let fragment = ""; if (this.stringOpen) { fragment += '"'; this.stringOpen = false; } fragment += this.ensureRoot(); const targetContainerSegments = targetSegments.slice(0, -1); const leafSegment = targetSegments[targetSegments.length - 1]; const commonDepth = this.findCommonStackDepth(targetContainerSegments); fragment += this.closeDownTo(commonDepth); fragment += this.openDownTo(targetContainerSegments, leafSegment); fragment += this.emitLeaf(leafSegment, arg, valueJson); return fragment; } /** * Returns the stack depth to preserve when navigating to a new target * container path. Always >= 1 (the root is never popped). * * Input: stack=[root,"recipe","ingredients",0], target=["recipe","ingredients",1] * Output: 3 (keep root+"recipe"+"ingredients") */ findCommonStackDepth(targetContainer) { const maxDepth = Math.min( this.pathStack.length - 1, targetContainer.length ); let common = 0; for (let i = 0; i < maxDepth; i++) { if (this.pathStack[i + 1].segment === targetContainer[i]) { common++; } else { break; } } return common + 1; } /** * Closes containers from the current stack depth back down to `targetDepth`. * * Input: this.pathStack=[root,"recipe","ingredients",0], targetDepth=3 * Output: '}' */ closeDownTo(targetDepth) { let fragment = ""; while (this.pathStack.length > targetDepth) { const entry = this.pathStack.pop(); fragment += entry.isArray ? "]" : "}"; } return fragment; } /** * Opens containers from the current stack depth down to the full target * container path, emitting opening `{`, `[`, keys, and commas as needed. * `leafSegment` is used to determine if the innermost container is an array. * * Input: this.pathStack=[root], targetContainer=["recipe","ingredients"], leafSegment=0 * Output: '"recipe":{"ingredients":[' */ openDownTo(targetContainer, leafSegment) { let fragment = ""; const startIdx = this.pathStack.length - 1; for (let i = startIdx; i < targetContainer.length; i++) { const seg = targetContainer[i]; const parentEntry = this.pathStack[this.pathStack.length - 1]; if (parentEntry.childCount > 0) { fragment += ","; } parentEntry.childCount++; if (typeof seg === "string") { fragment += `${JSON.stringify(seg)}:`; } const childSeg = i + 1 < targetContainer.length ? targetContainer[i + 1] : leafSegment; const isArray = typeof childSeg === "number"; fragment += isArray ? "[" : "{"; this.pathStack.push({ segment: seg, isArray, childCount: 0 }); } return fragment; } /** * Emits the comma, key, and value for a leaf entry in the current container. * * Input: leafSegment="name", arg={stringValue:"Lasagna"}, valueJson='"Lasagna"' * Output: '"name":"Lasagna"' (or ',"name":"Lasagna"' if container.childCount > 0) */ emitLeaf(leafSegment, arg, valueJson) { let fragment = ""; const container = this.pathStack[this.pathStack.length - 1]; if (container.childCount > 0) { fragment += ","; } container.childCount++; if (typeof leafSegment === "string") { fragment += `${JSON.stringify(leafSegment)}:`; } if (arg.stringValue != null && arg.willContinue) { fragment += valueJson.slice(0, -1); this.stringOpen = true; } else { fragment += valueJson; } return fragment; } }; function parsePath(rawPath) { const segments = []; for (const part of rawPath.split(".")) { const bracketIdx = part.indexOf("["); if (bracketIdx === -1) { segments.push(part); } else { if (bracketIdx > 0) segments.push(part.slice(0, bracketIdx)); for (const m of part.matchAll(/\[(\d+)\]/g)) { segments.push(parseInt(m[1], 10)); } } } return segments; } function getNestedValue(obj, segments) { let current = obj; for (const seg of segments) { if (current == null || typeof current !== "object") return void 0; current = current[seg]; } return current; } function setNestedValue(obj, segments, value) { let current = obj; for (let i = 0; i < segments.length - 1; i++) { const seg = segments[i]; const nextSeg = segments[i + 1]; if (current[seg] == null) { current[seg] = typeof nextSeg === "number" ? [] : {}; } current = current[seg]; } current[segments[segments.length - 1]] = value; } function resolvePartialArgValue(arg) { var _a, _b; const value = (_b = (_a = arg.stringValue) != null ? _a : arg.numberValue) != null ? _b : arg.boolValue; if (value != null) return { value, json: JSON.stringify(value) }; if ("nullValue" in arg) return { value: null, json: "null" }; return void 0; } // src/map-google-generative-ai-finish-reason.ts function mapGoogleGenerativeAIFinishReason({ finishReason, hasToolCalls }) { switch (finishReason) { case "STOP": return hasToolCalls ? "tool-calls" : "stop"; case "MAX_TOKENS": return "length"; case "IMAGE_SAFETY": case "RECITATION": case "SAFETY": case "BLOCKLIST": case "PROHIBITED_CONTENT": case "SPII": return "content-filter"; case "MALFORMED_FUNCTION_CALL": return "error"; case "FINISH_REASON_UNSPECIFIED": case "OTHER": default: return "other"; } } // src/google-generative-ai-language-model.ts var GoogleGenerativeAILanguageModel = class { constructor(modelId, config) { this.specificationVersion = "v3"; var _a; this.modelId = modelId; this.config = config; this.generateId = (_a = config.generateId) != null ? _a : import_provider_utils6.generateId; } get provider() { return this.config.provider; } get supportedUrls() { var _a, _b, _c; return (_c = (_b = (_a = this.config).supportedUrls) == null ? void 0 : _b.call(_a)) != null ? _c : {}; } async getArgs({ prompt, maxOutputTokens, temperature, topP, topK, frequencyPenalty, presencePenalty, stopSequences, responseFormat, seed, tools, toolChoice, providerOptions }, { isStreaming = false } = {}) { var _a, _b; const warnings = []; const providerOptionsName = this.config.provider.includes("vertex") ? "vertex" : "google"; let googleOptions = await (0, import_provider_utils6.parseProviderOptions)({ provider: providerOptionsName, providerOptions, schema: googleLanguageModelOptions }); if (googleOptions == null && providerOptionsName !== "google") { googleOptions = await (0, import_provider_utils6.parseProviderOptions)({ provider: "google", providerOptions, schema: googleLanguageModelOptions }); } const isVertexProvider = this.config.provider.startsWith("google.vertex."); if ((tools == null ? void 0 : tools.some( (tool) => tool.type === "provider" && tool.id === "google.vertex_rag_store" )) && !isVertexProvider) { warnings.push({ type: "other", message: `The 'vertex_rag_store' tool is only supported with the Google Vertex provider and might not be supported or could behave unexpectedly with the current Google provider (${this.config.provider}).` }); } if ((googleOptions == null