@ai-sdk/google 4.0.107 → 4.0.109

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/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertJsonResponseToolStream, convertToBase64, convertUint8ArrayToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createNullLanguageModelUsage, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, delay, detectMediaType, downloadBlob, encodePathSegment, generateId, getFromApi, getRuntimeEnvironmentUserAgent, getTopLevelMediaType, isAbortError, isCustomReasoning, isFullMediaType, isRecord, isSameOrigin, isUrlSupported, lazySchema, loadApiKey, mapReasoningToProviderBudget, mapReasoningToProviderEffort, normalizeBatchRequestCounts, parseProviderOptions, postJsonToApi, postToApi, resolve, resolveFullMediaType, resolveProviderReference, safeParseJSON, safeValidateTypes, secureJsonParse, serializeModelOptions, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
1
+ import { EXPERIMENTAL_EMBEDDING_MODEL_PROVIDER_OPTIONS_TRANSFORMER, WORKFLOW_DESERIALIZE, WORKFLOW_SERIALIZE, combineHeaders, connectToWebSocket, convertAsyncIteratorToReadableStream, convertBase64ToUint8Array, convertInlineFileDataToUint8Array, convertJsonResponseToolStream, convertToBase64, convertUint8ArrayToBase64, createEventSourceResponseHandler, createJsonErrorResponseHandler, createJsonLinesResponseHandler, createJsonResponseHandler, createNullLanguageModelUsage, createProviderExecutedToolFactory, createProviderStreamError, createToolNameMapping, delay, detectMediaType, downloadBlob, encodePathSegment, generateId, getFromApi, getRuntimeEnvironmentUserAgent, getTopLevelMediaType, isAbortError, isCustomReasoning, isFullMediaType, isRecord, isSameOrigin, isUrlSupported, lazySchema, loadApiKey, mapReasoningToProviderBudget, mapReasoningToProviderEffort, normalizeBatchRequestCounts, parseProviderOptions, postJsonToApi, postToApi, resolve, resolveFullMediaType, resolveProviderReference, resolveWith, safeParseJSON, safeValidateTypes, secureJsonParse, serializeModelOptions, waitForWebSocketBufferDrain, withUserAgentSuffix, withoutTrailingSlash, zodSchema } from "@ai-sdk/provider-utils";
2
2
  import { Experimental_DecisionLanguageModel } from "@ai-sdk/provider-utils/experimental-decision";
3
3
  import { AISDKError, InvalidArgumentError, InvalidResponseDataError, TooManyEmbeddingValuesForCallError, UnsupportedFunctionalityError } from "@ai-sdk/provider";
4
4
  import { z } from "zod/v4";
5
5
  //#region src/version.ts
6
- const VERSION = "4.0.107";
6
+ const VERSION = "4.0.109";
7
7
  //#endregion
8
8
  //#region src/google-error.ts
9
9
  const getGoogleErrorSchema = () => z.object({
@@ -310,6 +310,16 @@ function addTokenDetails(a, b) {
310
310
  }));
311
311
  }
312
312
  //#endregion
313
+ //#region src/google-prompt.ts
314
+ const googleVideoMetadataSchema = z.object({
315
+ /** Start offset as a duration in seconds, e.g. `'3.5s'`. */
316
+ startOffset: z.string().optional(),
317
+ /** End offset as a duration in seconds, e.g. `'10s'`. */
318
+ endOffset: z.string().optional(),
319
+ /** Frames per second in the range (0, 24]. Defaults to 1. */
320
+ fps: z.number().gt(0).max(24).optional()
321
+ });
322
+ //#endregion
313
323
  //#region src/tool/code-execution.ts
314
324
  const codeExecutionInputSchema = z.object({
315
325
  language: z.string().describe("The programming language of the code."),
@@ -470,33 +480,50 @@ function convertToGoogleMessages(prompt, options) {
470
480
  case "text":
471
481
  parts.push({ text: part.text });
472
482
  break;
473
- case "file": switch (part.data.type) {
474
- case "url":
475
- parts.push({ fileData: {
476
- mimeType: resolveFullMediaType({ part }),
477
- fileUri: part.data.url.protocol === "gs:" && part.data.originalUrl != null ? part.data.originalUrl : part.data.url.toString()
478
- } });
479
- break;
480
- case "reference":
481
- if (isVertexLike) throw new UnsupportedFunctionalityError({ functionality: "file parts with provider references" });
482
- parts.push({ fileData: {
483
- mimeType: resolveFullMediaType({ part }),
484
- fileUri: resolveProviderReference({
485
- reference: part.data.reference,
486
- provider: "google"
487
- })
488
- } });
489
- break;
490
- case "text":
491
- parts.push({ inlineData: {
492
- mimeType: isFullMediaType(part.mediaType) ? part.mediaType : "text/plain",
493
- data: convertToBase64(new TextEncoder().encode(part.data.text))
494
- } });
495
- break;
496
- case "data": parts.push({ inlineData: {
497
- mimeType: resolveFullMediaType({ part }),
498
- data: convertToBase64(part.data.data)
499
- } });
483
+ case "file": {
484
+ const rawVideoMetadata = readProviderOpts(part)?.videoMetadata;
485
+ const videoMetadata = rawVideoMetadata == null ? void 0 : googleVideoMetadataSchema.parse(rawVideoMetadata);
486
+ switch (part.data.type) {
487
+ case "url":
488
+ parts.push({
489
+ fileData: {
490
+ mimeType: resolveFullMediaType({ part }),
491
+ fileUri: part.data.url.protocol === "gs:" && part.data.originalUrl != null ? part.data.originalUrl : part.data.url.toString()
492
+ },
493
+ ...videoMetadata != null ? { videoMetadata } : {}
494
+ });
495
+ break;
496
+ case "reference":
497
+ if (isVertexLike) throw new UnsupportedFunctionalityError({ functionality: "file parts with provider references" });
498
+ parts.push({
499
+ fileData: {
500
+ mimeType: resolveFullMediaType({ part }),
501
+ fileUri: resolveProviderReference({
502
+ reference: part.data.reference,
503
+ provider: "google"
504
+ })
505
+ },
506
+ ...videoMetadata != null ? { videoMetadata } : {}
507
+ });
508
+ break;
509
+ case "text":
510
+ parts.push({
511
+ inlineData: {
512
+ mimeType: isFullMediaType(part.mediaType) ? part.mediaType : "text/plain",
513
+ data: convertToBase64(new TextEncoder().encode(part.data.text))
514
+ },
515
+ ...videoMetadata != null ? { videoMetadata } : {}
516
+ });
517
+ break;
518
+ case "data": parts.push({
519
+ inlineData: {
520
+ mimeType: resolveFullMediaType({ part }),
521
+ data: convertToBase64(part.data.data)
522
+ },
523
+ ...videoMetadata != null ? { videoMetadata } : {}
524
+ });
525
+ }
526
+ break;
500
527
  }
501
528
  }
502
529
  contents.push({
@@ -1003,11 +1030,129 @@ const googleLanguageModelOptions = lazySchema(() => zodSchema(z.object({
1003
1030
  requestType: z.enum(["shared"]).optional()
1004
1031
  })));
1005
1032
  //#endregion
1006
- //#region src/google-model-capabilities.ts
1033
+ //#region src/google-model-catalog.ts
1007
1034
  const gemini1ModelPattern = /(^|[/.])gemini-1(?:[.-]|$)/i;
1008
1035
  const gemini2ModelPattern = /(^|[/.])gemini-2(?:[.-]|$)/i;
1009
- const gemini25ModelPattern$1 = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
1036
+ const gemini25ModelPattern = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
1010
1037
  const geminiModelPattern = /(^|[/.])gemini-/i;
1038
+ /** Options accepted under providerOptions.google (or googleVertex on Vertex). */
1039
+ const googleProviderOptions = { language: {
1040
+ responseModalities: { description: "Response modalities to generate." },
1041
+ thinkingConfig: { description: "Thinking budget, level, and thought output." },
1042
+ cachedContent: { description: "Cached content to use as request context." },
1043
+ structuredOutputs: { description: "Whether to send the JSON response schema." },
1044
+ safetySettings: { description: "Safety settings for the request." },
1045
+ threshold: { description: "Default threshold for configurable safety categories." },
1046
+ audioTimestamp: { description: "Enable timestamp understanding for audio." },
1047
+ labels: { description: "Billing labels. Vertex AI only." },
1048
+ mediaResolution: { description: "Resolution used to process media inputs." },
1049
+ imageConfig: { description: "Image generation configuration." },
1050
+ retrievalConfig: { description: "Retrieval configuration for tools." },
1051
+ streamFunctionCallArguments: { description: "Stream function arguments. Vertex AI only." },
1052
+ serviceTier: { description: "Service tier. Gemini API only." },
1053
+ continuationToken: { description: "Resume a response using its continuation token." },
1054
+ sharedRequestType: { description: "Shared PayGo tier. Vertex AI only." },
1055
+ requestType: { description: "Request routing type. Vertex AI only." }
1056
+ } };
1057
+ const standard = {
1058
+ image: true,
1059
+ objectGeneration: true,
1060
+ tools: true,
1061
+ streaming: true,
1062
+ googleSearch: true,
1063
+ urlContext: true
1064
+ };
1065
+ const googleModelCatalog = Object.fromEntries(Object.entries({
1066
+ "gemini-nano-banana-2.1": {
1067
+ image: true,
1068
+ objectGeneration: false,
1069
+ tools: false,
1070
+ streaming: false,
1071
+ googleSearch: true,
1072
+ urlContext: false
1073
+ },
1074
+ "gemini-4-argon": standard,
1075
+ "gemini-3.8-flash": standard,
1076
+ "gemini-3.7-flash": standard,
1077
+ "gemini-3.6-flash": standard,
1078
+ "gemini-3.5-flash": standard,
1079
+ "gemini-3.5-flash-lite": standard,
1080
+ "gemini-3.1-pro-preview": standard,
1081
+ "gemini-3.1-flash-image-preview": standard,
1082
+ "gemini-3.1-flash-lite-preview": standard,
1083
+ "gemini-3-pro-preview": standard,
1084
+ "gemini-3-pro-image-preview": standard,
1085
+ "gemini-3-flash-preview": standard,
1086
+ "gemini-2.5-pro": standard,
1087
+ "gemini-2.5-flash": standard,
1088
+ "gemini-2.5-flash-lite": standard,
1089
+ "gemini-2.5-flash-lite-preview-06-17": standard,
1090
+ "gemini-2.0-flash": standard
1091
+ }).map(([modelId, documented]) => [modelId, createGoogleLanguageModelEntry(modelId, documented)]));
1092
+ function getGoogleLanguageModelEntry(modelId) {
1093
+ return Object.prototype.hasOwnProperty.call(googleModelCatalog, modelId) ? googleModelCatalog[modelId] : createGoogleLanguageModelEntry(modelId);
1094
+ }
1095
+ function createGoogleLanguageModelEntry(modelId, documented) {
1096
+ const runtime = resolveRuntimeDefinition(modelId);
1097
+ const declared = documented != null;
1098
+ const id = modelId.toLowerCase();
1099
+ const thinkingFormat = runtime.usesGemini3Features && !modelId.includes("gemini-3-pro-image") ? "level" : "budget";
1100
+ const minLevel = getMinimumThinkingLevelForGemini3Model(modelId);
1101
+ return {
1102
+ capabilities: { language: {
1103
+ inputs: {
1104
+ image: documented?.image ?? "unknown",
1105
+ audio: "unknown"
1106
+ },
1107
+ objectGeneration: documented?.objectGeneration ?? "unknown",
1108
+ tools: {
1109
+ usage: documented?.tools ?? "unknown",
1110
+ streaming: documented?.streaming ?? "unknown",
1111
+ gemini2: runtime.supportsGemini2Tools,
1112
+ googleSearch: documented?.googleSearch ?? "unknown",
1113
+ urlContext: documented?.urlContext ?? "unknown",
1114
+ fileSearch: runtime.supportsFileSearch,
1115
+ mixed: runtime.usesGemini3Features,
1116
+ functionResponseParts: runtime.usesGemini3Features
1117
+ },
1118
+ reasoning: {
1119
+ support: "unknown",
1120
+ efforts: thinkingFormat === "level" ? [
1121
+ ...minLevel === "minimal" ? ["minimal"] : [],
1122
+ "low",
1123
+ "medium",
1124
+ "high"
1125
+ ] : void 0,
1126
+ minBudget: id.includes("2.5-pro") ? 128 : 0,
1127
+ maxBudget: id.includes("2.5-pro") || id.includes("gemini-3-pro-image") ? 32768 : 24576
1128
+ },
1129
+ sampling: {
1130
+ temperature: "unknown",
1131
+ topP: "unknown",
1132
+ topK: "unknown",
1133
+ logprobs: false,
1134
+ penalties: gemini25ModelPattern.test(modelId) ? { condition: "Only supported on the Vertex AI API." } : true
1135
+ },
1136
+ structuredOutput: { withFunctionTools: runtime.usesGemini3Features }
1137
+ } },
1138
+ providerOptions: { language: declareProviderOptions(declared ? true : "unknown", {
1139
+ labels: { condition: "Only supported on the Vertex AI API." },
1140
+ sharedRequestType: { condition: "Only supported on the Vertex AI API." },
1141
+ requestType: { condition: "Only supported on the Vertex AI API." },
1142
+ serviceTier: { condition: "Only supported on the Gemini API." },
1143
+ streamFunctionCallArguments: { condition: "Only supported for streaming requests on the Vertex AI API with Gemini 3 or newer." }
1144
+ }) },
1145
+ requestConfig: { language: {
1146
+ systemInstruction: id.startsWith("gemma-") ? "user" : "system",
1147
+ thinkingFormat,
1148
+ reasoningMaxOutputTokens: 65536,
1149
+ jsonResponseTool: /(^|\/)gemini-/i.test(modelId)
1150
+ } }
1151
+ };
1152
+ }
1153
+ function declareProviderOptions(support, exceptions) {
1154
+ return Object.fromEntries(Object.keys(googleProviderOptions.language).map((option) => [option, exceptions[option] ?? support]));
1155
+ }
1011
1156
  function isKnownPreGemini2Model(modelId) {
1012
1157
  return gemini1ModelPattern.test(modelId) || /(^|[/.])gemini-pro(?:-vision)?$/i.test(modelId) || /(^|[/.])gemini-robotics-er-1\.5(?:[.-]|$)/i.test(modelId);
1013
1158
  }
@@ -1018,17 +1163,39 @@ function isKnownPreGemini2Model(modelId) {
1018
1163
  * intentionally inherit the newest supported behavior. Add exceptions here
1019
1164
  * only when a model is known to require a legacy request shape.
1020
1165
  */
1021
- function getGoogleModelCapabilities(modelId) {
1166
+ function resolveRuntimeDefinition(modelId) {
1022
1167
  const isGeminiModel = geminiModelPattern.test(modelId);
1023
1168
  const isGemini2Model = gemini2ModelPattern.test(modelId);
1024
1169
  const isKnownPreGemini2 = isKnownPreGemini2Model(modelId);
1025
1170
  const usesGemini3Features = isGeminiModel && !(isKnownPreGemini2 || isGemini2Model);
1026
1171
  return {
1027
1172
  supportsGemini2Tools: isGeminiModel && !isKnownPreGemini2 || modelId.toLowerCase().includes("nano-banana"),
1028
- supportsFileSearch: gemini25ModelPattern$1.test(modelId) || usesGemini3Features,
1173
+ supportsFileSearch: gemini25ModelPattern.test(modelId) || usesGemini3Features,
1029
1174
  usesGemini3Features
1030
1175
  };
1031
1176
  }
1177
+ function getMinimumThinkingLevelForGemini3Model(modelId) {
1178
+ const modelName = /(?:^|[/.])(gemini-[^/]*)$/i.exec(modelId)?.[1].toLowerCase();
1179
+ if (modelName === "gemini-flash-latest") return "low";
1180
+ const proVersionMatch = /^gemini-(\d+)(?:\.\d+)?-pro(?:$|-)/.exec(modelName ?? "");
1181
+ if (Number(proVersionMatch?.[1]) >= 3) return "low";
1182
+ const versionMatch = /^gemini-(\d+)\.(\d+)-flash(?:$|-(?!lite(?:-|$)))/.exec(modelName ?? "");
1183
+ if (versionMatch == null) return "minimal";
1184
+ const majorVersion = Number(versionMatch[1]);
1185
+ const minorVersion = Number(versionMatch[2]);
1186
+ return majorVersion > 3 || majorVersion === 3 && minorVersion >= 7 ? "low" : "minimal";
1187
+ }
1188
+ //#endregion
1189
+ //#region src/google-model-capabilities.ts
1190
+ /** Compatibility projection of the resolved catalog for existing request code. */
1191
+ function getGoogleModelCapabilities(modelId) {
1192
+ const { tools } = getGoogleLanguageModelEntry(modelId).capabilities.language;
1193
+ return {
1194
+ supportsGemini2Tools: tools.gemini2,
1195
+ supportsFileSearch: tools.fileSearch,
1196
+ usesGemini3Features: tools.mixed
1197
+ };
1198
+ }
1032
1199
  //#endregion
1033
1200
  //#region src/google-prepare-tools.ts
1034
1201
  function prepareTools({ tools, toolChoice, modelId, isVertexProvider = false }) {
@@ -1233,11 +1400,16 @@ var GoogleJSONAccumulator = class {
1233
1400
  const escaped = JSON.stringify(arg.stringValue).slice(1, -1);
1234
1401
  setNestedValue(this.accumulatedArgs, segments, existingValue + arg.stringValue);
1235
1402
  delta += escaped;
1403
+ if (arg.willContinue !== true) delta += this.closeOpenString();
1236
1404
  continue;
1237
1405
  }
1238
1406
  const resolved = resolvePartialArgValue(arg);
1239
1407
  if (resolved == null) {
1240
- if (existingValue !== void 0 || arg.willContinue === true) continue;
1408
+ if (existingValue !== void 0) {
1409
+ if (typeof existingValue === "string" && arg.willContinue !== true) delta += this.closeOpenString();
1410
+ continue;
1411
+ }
1412
+ if (arg.willContinue === true) continue;
1241
1413
  setNestedValue(this.accumulatedArgs, segments, isArrayTerminator ? [] : {});
1242
1414
  delta += this.emitContainer(segments, isArrayTerminator);
1243
1415
  continue;
@@ -1263,6 +1435,15 @@ var GoogleJSONAccumulator = class {
1263
1435
  };
1264
1436
  }
1265
1437
  /**
1438
+ * Input: stringOpen=true
1439
+ * Output: '"' (and stringOpen=false), or '' when no string is open
1440
+ */
1441
+ closeOpenString() {
1442
+ if (!this.stringOpen) return "";
1443
+ this.stringOpen = false;
1444
+ return "\"";
1445
+ }
1446
+ /**
1266
1447
  * Input: pathStack=[] (first call) or pathStack=[root,...] (subsequent calls)
1267
1448
  * Output: '{' (first call) or '' (subsequent calls)
1268
1449
  */
@@ -1285,11 +1466,7 @@ var GoogleJSONAccumulator = class {
1285
1466
  * Output: '{"recipe":{"name":"Lasagna"'
1286
1467
  */
1287
1468
  emitNavigationTo(targetSegments, arg, valueJson) {
1288
- let fragment = "";
1289
- if (this.stringOpen) {
1290
- fragment += "\"";
1291
- this.stringOpen = false;
1292
- }
1469
+ let fragment = this.closeOpenString();
1293
1470
  fragment += this.ensureRoot();
1294
1471
  const targetContainerSegments = targetSegments.slice(0, -1);
1295
1472
  const leafSegment = targetSegments[targetSegments.length - 1];
@@ -1308,11 +1485,7 @@ var GoogleJSONAccumulator = class {
1308
1485
  * Output: '{"nested":{"tags":['
1309
1486
  */
1310
1487
  emitContainer(targetSegments, isArray) {
1311
- let fragment = "";
1312
- if (this.stringOpen) {
1313
- fragment += "\"";
1314
- this.stringOpen = false;
1315
- }
1488
+ let fragment = this.closeOpenString();
1316
1489
  fragment += this.ensureRoot();
1317
1490
  const commonDepth = this.findCommonStackDepth(targetSegments);
1318
1491
  fragment += this.closeDownTo(commonDepth);
@@ -1504,7 +1677,6 @@ const configurableSafetySettingCategories = [
1504
1677
  "HARM_CATEGORY_HARASSMENT",
1505
1678
  "HARM_CATEGORY_SEXUALLY_EXPLICIT"
1506
1679
  ];
1507
- const gemini25ModelPattern = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
1508
1680
  const googleCloudStorageFunctionResponseUrls = {
1509
1681
  "image/png": [/^gs:\/\/.*$/],
1510
1682
  "image/jpeg": [/^gs:\/\/.*$/],
@@ -1589,8 +1761,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1589
1761
  imageConfig = geminiApiImageConfig;
1590
1762
  }
1591
1763
  }
1592
- const isGemmaModel = modelId.toLowerCase().startsWith("gemma-");
1593
- const isGemini25DeveloperApiModel = !isVertexProvider && gemini25ModelPattern.test(modelId);
1764
+ const entry = getGoogleLanguageModelEntry(modelId);
1765
+ const isGemmaModel = entry.requestConfig.language.systemInstruction === "user";
1766
+ const isGemini25DeveloperApiModel = !isVertexProvider && entry.capabilities.language.sampling.penalties !== true;
1594
1767
  if (isGemini25DeveloperApiModel && frequencyPenalty != null) warnings.push({
1595
1768
  type: "unsupported",
1596
1769
  feature: "frequencyPenalty"
@@ -1599,7 +1772,7 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1599
1772
  type: "unsupported",
1600
1773
  feature: "presencePenalty"
1601
1774
  });
1602
- const { usesGemini3Features } = getGoogleModelCapabilities(modelId);
1775
+ const usesGemini3Features = entry.capabilities.language.tools.functionResponseParts;
1603
1776
  const supportedFunctionResponseUrls = usesGemini3Features && config.downloadToolResultFiles?.supportsGoogleCloudStorageUrls ? googleCloudStorageFunctionResponseUrls : void 0;
1604
1777
  const { contents, systemInstruction } = convertToGoogleMessages(config.downloadToolResultFiles ? await downloadToolResultFiles(prompt, {
1605
1778
  abortSignal,
@@ -1684,8 +1857,10 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1684
1857
  }
1685
1858
  async getArgs(options, { isStreaming = false } = {}) {
1686
1859
  const { responseFormat, tools, toolChoice } = options;
1860
+ const entry = getGoogleLanguageModelEntry(this.modelId);
1861
+ const { structuredOutput } = entry.capabilities.language;
1687
1862
  let jsonResponseTool;
1688
- if (responseFormat?.type === "json" && responseFormat.schema != null && tools?.some((tool) => tool.type === "function") && /(^|\/)gemini-/i.test(this.modelId) && (!getGoogleModelCapabilities(this.modelId).usesGemini3Features || toolChoice?.type === "required" || toolChoice?.type === "tool")) {
1863
+ if (responseFormat?.type === "json" && responseFormat.schema != null && tools?.some((tool) => tool.type === "function") && entry.requestConfig.language.jsonResponseTool && (!structuredOutput.withFunctionTools || toolChoice?.type === "required" || toolChoice?.type === "tool")) {
1689
1864
  let name = "json";
1690
1865
  for (let suffix = 1; tools.some((tool) => tool.name === name); suffix++) name = `json_${suffix}`;
1691
1866
  jsonResponseTool = {
@@ -1855,10 +2030,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1855
2030
  }
1856
2031
  async doGenerate(options) {
1857
2032
  const { args, warnings, providerOptionsNames, extraHeaders, toolNameMapping, jsonResponseToolName } = await this.getArgs(options);
1858
- const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers, extraHeaders);
1859
- const generateContent = (body) => postJsonToApi({
2033
+ const generateContent = async (body) => postJsonToApi({
1860
2034
  url: `${this.config.baseURL}/${getModelPath(this.modelId)}:generateContent`,
1861
- headers: mergedHeaders,
2035
+ headers: combineHeaders(await resolve(this.config.headers), options.headers, extraHeaders),
1862
2036
  body,
1863
2037
  failedResponseHandler: googleFailedResponseHandler,
1864
2038
  successfulResponseHandler: createJsonResponseHandler(responseSchema),
@@ -1921,10 +2095,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1921
2095
  async doStream(options) {
1922
2096
  const { args, warnings, providerOptionsNames, extraHeaders, toolNameMapping, jsonResponseToolName } = await this.getArgs(options, { isStreaming: true });
1923
2097
  const wrapProviderMetadata = (payload) => Object.fromEntries(providerOptionsNames.map((name) => [name, payload]));
1924
- const headers = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers, extraHeaders);
1925
- const streamGenerateContent = (body) => postJsonToApi({
2098
+ const streamGenerateContent = async (body) => postJsonToApi({
1926
2099
  url: `${this.config.baseURL}/${getModelPath(this.modelId)}:streamGenerateContent?alt=sse`,
1927
- headers,
2100
+ headers: combineHeaders(await resolve(this.config.headers), options.headers, extraHeaders),
1928
2101
  body,
1929
2102
  failedResponseHandler: googleFailedResponseHandler,
1930
2103
  successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
@@ -2377,17 +2550,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
2377
2550
  };
2378
2551
  }
2379
2552
  };
2380
- function getMaxOutputTokensForGemini25Model() {
2381
- return 65536;
2382
- }
2383
- function getMaxThinkingTokensForGemini25Model(modelId) {
2384
- const id = modelId.toLowerCase();
2385
- if (id.includes("2.5-pro") || id.includes("gemini-3-pro-image")) return 32768;
2386
- return 24576;
2387
- }
2388
2553
  function resolveThinkingConfig({ reasoning, modelId, warnings }) {
2389
2554
  if (!isCustomReasoning(reasoning)) return;
2390
- if (getGoogleModelCapabilities(modelId).usesGemini3Features && !modelId.includes("gemini-3-pro-image")) return resolveGemini3ThinkingConfig({
2555
+ if (getGoogleLanguageModelEntry(modelId).requestConfig.language.thinkingFormat === "level") return resolveGemini3ThinkingConfig({
2391
2556
  reasoning,
2392
2557
  modelId,
2393
2558
  warnings
@@ -2399,45 +2564,31 @@ function resolveThinkingConfig({ reasoning, modelId, warnings }) {
2399
2564
  });
2400
2565
  }
2401
2566
  function resolveGemini3ThinkingConfig({ reasoning, modelId, warnings }) {
2402
- const minimumThinkingLevel = getMinimumThinkingLevelForGemini3Model(modelId);
2403
- if (reasoning === "none") return { thinkingLevel: minimumThinkingLevel };
2567
+ const minimumThinkingLevel = getGoogleLanguageModelEntry(modelId).capabilities.language.reasoning.efforts?.[0];
2404
2568
  const thinkingLevel = mapReasoningToProviderEffort({
2405
2569
  reasoning,
2406
2570
  effortMap: {
2407
- minimal: minimumThinkingLevel,
2571
+ ...minimumThinkingLevel === "minimal" && { minimal: "minimal" },
2408
2572
  low: "low",
2409
2573
  medium: "medium",
2410
- high: "high",
2411
- xhigh: "high",
2412
- max: "high"
2574
+ high: "high"
2413
2575
  },
2414
2576
  warnings
2415
2577
  });
2416
2578
  if (thinkingLevel == null) return;
2417
2579
  return { thinkingLevel };
2418
2580
  }
2419
- function getMinimumThinkingLevelForGemini3Model(modelId) {
2420
- const modelName = /(?:^|[/.])(gemini-[^/]*)$/i.exec(modelId)?.[1].toLowerCase();
2421
- if (modelName === "gemini-flash-latest") return "low";
2422
- const proVersionMatch = /^gemini-(\d+)(?:\.\d+)?-pro(?:$|-)/.exec(modelName ?? "");
2423
- if (Number(proVersionMatch?.[1]) >= 3) return "low";
2424
- const versionMatch = /^gemini-(\d+)\.(\d+)-flash(?:$|-(?!lite(?:-|$)))/.exec(modelName ?? "");
2425
- if (versionMatch == null) return "minimal";
2426
- const majorVersion = Number(versionMatch[1]);
2427
- const minorVersion = Number(versionMatch[2]);
2428
- return majorVersion > 3 || majorVersion === 3 && minorVersion >= 7 ? "low" : "minimal";
2429
- }
2430
2581
  function resolveGemini25ThinkingConfig({ reasoning, modelId, warnings }) {
2431
- if (reasoning === "none") return { thinkingBudget: 0 };
2432
- const thinkingBudget = mapReasoningToProviderBudget({
2582
+ const entry = getGoogleLanguageModelEntry(modelId);
2583
+ const minThinkingBudget = entry.capabilities.language.reasoning.minBudget;
2584
+ if (reasoning === "none" && minThinkingBudget === 0) return { thinkingBudget: 0 };
2585
+ return { thinkingBudget: mapReasoningToProviderBudget({
2433
2586
  reasoning,
2434
- maxOutputTokens: getMaxOutputTokensForGemini25Model(),
2435
- maxReasoningBudget: getMaxThinkingTokensForGemini25Model(modelId),
2436
- minReasoningBudget: 0,
2587
+ maxOutputTokens: entry.requestConfig.language.reasoningMaxOutputTokens,
2588
+ maxReasoningBudget: entry.capabilities.language.reasoning.maxBudget,
2589
+ minReasoningBudget: minThinkingBudget,
2437
2590
  warnings
2438
- });
2439
- if (thinkingBudget == null) return;
2440
- return { thinkingBudget };
2591
+ }) };
2441
2592
  }
2442
2593
  function extractSources({ groundingMetadata, generateId }) {
2443
2594
  if (!groundingMetadata?.groundingChunks) return;
@@ -2850,12 +3001,11 @@ var GoogleBatch = class {
2850
3001
  warning
2851
3002
  });
2852
3003
  }
2853
- const headers = await this.getHeaders(options.headers);
2854
3004
  const createUrl = `${this.batchConfig.baseURL}/${getModelPath(modelId)}:batchGenerateContent`;
2855
3005
  if (fileParts == null) {
2856
3006
  const { value: operation } = await postJsonToApi({
2857
3007
  url: createUrl,
2858
- headers,
3008
+ headers: await this.getHeaders(options.headers),
2859
3009
  body: inlineBatchBody,
2860
3010
  failedResponseHandler: googleFailedResponseHandler,
2861
3011
  successfulResponseHandler: createJsonResponseHandler(googleBatchOperationSchema),
@@ -2876,7 +3026,7 @@ var GoogleBatch = class {
2876
3026
  });
2877
3027
  const { value: uploadUrl } = await postJsonToApi({
2878
3028
  url: `${this.getBaseOrigin()}/upload/v1beta/files`,
2879
- headers: combineHeaders(headers, {
3029
+ headers: combineHeaders(await this.getHeaders(options.headers), {
2880
3030
  "X-Goog-Upload-Protocol": "resumable",
2881
3031
  "X-Goog-Upload-Command": "start",
2882
3032
  "X-Goog-Upload-Header-Content-Length": String(inputFile.size),
@@ -2909,7 +3059,7 @@ var GoogleBatch = class {
2909
3059
  });
2910
3060
  const { value: operation } = await postJsonToApi({
2911
3061
  url: createUrl,
2912
- headers,
3062
+ headers: await this.getHeaders(options.headers),
2913
3063
  body: { batch: {
2914
3064
  displayName,
2915
3065
  ...options.webhookUrl != null && { webhookConfig: { uris: [options.webhookUrl] } },
@@ -3531,7 +3681,7 @@ var GoogleFiles = class {
3531
3681
  providerOptions: options.providerOptions,
3532
3682
  schema: googleFilesUploadOptionsSchema
3533
3683
  });
3534
- const resolvedHeaders = combineHeaders(this.config.headers(), options.headers);
3684
+ const getHeaders = async () => combineHeaders(await resolve(this.config.headers), options.headers);
3535
3685
  const fetchFn = this.config.fetch ?? globalThis.fetch;
3536
3686
  const warnings = [];
3537
3687
  if (options.filename != null) warnings.push({
@@ -3544,7 +3694,7 @@ var GoogleFiles = class {
3544
3694
  const initResponse = await fetchFn(`${this.config.baseURL.replace(/\/v1beta$/, "")}/upload/v1beta/files`, {
3545
3695
  method: "POST",
3546
3696
  headers: {
3547
- ...resolvedHeaders,
3697
+ ...await getHeaders(),
3548
3698
  "X-Goog-Upload-Protocol": "resumable",
3549
3699
  "X-Goog-Upload-Command": "start",
3550
3700
  "X-Goog-Upload-Header-Content-Length": String(fileBytes.length),
@@ -3597,7 +3747,7 @@ var GoogleFiles = class {
3597
3747
  const { value: fileStatus } = await getFromApi({
3598
3748
  url: `${this.config.baseURL}/${filePath}`,
3599
3749
  validateUrl: false,
3600
- headers: combineHeaders(resolvedHeaders),
3750
+ headers: await getHeaders(),
3601
3751
  successfulResponseHandler: createJsonResponseHandler(googleFileResponseSchema),
3602
3752
  failedResponseHandler: googleFailedResponseHandler,
3603
3753
  abortSignal: options.abortSignal,
@@ -6111,7 +6261,7 @@ async function cancelGoogleInteraction({ baseURL, interactionId, headers, fetch
6111
6261
  try {
6112
6262
  const response = await fetch(url, {
6113
6263
  method: "POST",
6114
- headers: withUserAgentSuffix(combineHeaders({ "Content-Type": "application/json" }, headers), getRuntimeEnvironmentUserAgent()),
6264
+ headers: withUserAgentSuffix(combineHeaders({ "Content-Type": "application/json" }, await resolve(headers)), getRuntimeEnvironmentUserAgent()),
6115
6265
  body: "{}"
6116
6266
  });
6117
6267
  try {
@@ -6161,7 +6311,7 @@ async function pollGoogleInteractionUntilTerminal({ baseURL, interactionId, head
6161
6311
  const { value: response, rawValue: rawResponse, responseHeaders } = await getFromApi({
6162
6312
  url,
6163
6313
  validateUrl: false,
6164
- headers,
6314
+ headers: await resolve(headers),
6165
6315
  failedResponseHandler: googleFailedResponseHandler,
6166
6316
  successfulResponseHandler: createJsonResponseHandler(googleInteractionsResponseSchema),
6167
6317
  abortSignal,
@@ -6356,10 +6506,6 @@ const DEFAULT_RETRY_DELAY_MS = 500;
6356
6506
  */
6357
6507
  function streamGoogleInteractionEvents({ baseURL, interactionId, headers, fetch, abortSignal, maxRetries = DEFAULT_MAX_RETRIES, retryDelayMs = DEFAULT_RETRY_DELAY_MS }) {
6358
6508
  if (interactionId.length === 0) throw new Error("google.interactions: cannot stream a background interaction without an id.");
6359
- const eventSourceHeaders = {
6360
- ...headers,
6361
- accept: "text/event-stream"
6362
- };
6363
6509
  let lastEventId;
6364
6510
  let complete = false;
6365
6511
  let attempt = 0;
@@ -6382,7 +6528,10 @@ function streamGoogleInteractionEvents({ baseURL, interactionId, headers, fetch,
6382
6528
  const { value: stream } = await getFromApi({
6383
6529
  url: buildUrl(),
6384
6530
  validateUrl: false,
6385
- headers: eventSourceHeaders,
6531
+ headers: {
6532
+ ...await resolve(headers),
6533
+ accept: "text/event-stream"
6534
+ },
6386
6535
  failedResponseHandler: googleFailedResponseHandler,
6387
6536
  successfulResponseHandler: createEventSourceResponseHandler(googleInteractionsEventSchema),
6388
6537
  abortSignal: effectiveSignal,
@@ -6853,10 +7002,10 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6853
7002
  async doGenerate(options) {
6854
7003
  const { args, warnings, isAgent, isBackground, pollingTimeoutMs } = await this.getArgs(options);
6855
7004
  const url = `${this.config.baseURL}/interactions`;
6856
- const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers);
7005
+ const mergedHeaders = async () => combineHeaders(await resolve(this.config.headers), options.headers);
6857
7006
  let { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({
6858
7007
  url,
6859
- headers: mergedHeaders,
7008
+ headers: await resolve(mergedHeaders),
6860
7009
  body: args,
6861
7010
  failedResponseHandler: googleFailedResponseHandler,
6862
7011
  successfulResponseHandler: createJsonResponseHandler(googleInteractionsResponseSchema),
@@ -6920,7 +7069,7 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6920
7069
  async doStream(options) {
6921
7070
  const { args, warnings, isBackground, pollingTimeoutMs } = await this.getArgs(options);
6922
7071
  const url = `${this.config.baseURL}/interactions`;
6923
- const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers);
7072
+ const mergedHeaders = async () => combineHeaders(await resolve(this.config.headers), options.headers);
6924
7073
  if (isBackground) return this.doStreamBackground({
6925
7074
  args,
6926
7075
  warnings,
@@ -6935,7 +7084,7 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6935
7084
  };
6936
7085
  const { responseHeaders, value: response } = await postJsonToApi({
6937
7086
  url,
6938
- headers: mergedHeaders,
7087
+ headers: await resolve(mergedHeaders),
6939
7088
  body,
6940
7089
  failedResponseHandler: googleFailedResponseHandler,
6941
7090
  successfulResponseHandler: createEventSourceResponseHandler(googleInteractionsEventSchema),
@@ -6958,7 +7107,7 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6958
7107
  async doStreamBackground({ args, warnings, url, mergedHeaders, options, pollingTimeoutMs }) {
6959
7108
  const { responseHeaders: postHeaders, value: postResponse } = await postJsonToApi({
6960
7109
  url,
6961
- headers: mergedHeaders,
7110
+ headers: await resolve(mergedHeaders),
6962
7111
  body: args,
6963
7112
  failedResponseHandler: googleFailedResponseHandler,
6964
7113
  successfulResponseHandler: createJsonResponseHandler(googleInteractionsResponseSchema),
@@ -7392,7 +7541,7 @@ var GoogleRealtimeModel = class {
7392
7541
  }
7393
7542
  async doCreateClientSecret(options) {
7394
7543
  const fetchFn = this.config.fetch ?? fetch;
7395
- const apiKey = this.config.headers()["x-goog-api-key"];
7544
+ const apiKey = (await resolve(this.config.headers))["x-goog-api-key"];
7396
7545
  if (!apiKey) throw new Error("Google Generative AI API key is required for realtime token creation.");
7397
7546
  const now = Date.now();
7398
7547
  const openWindowMs = (options.expiresAfterSeconds ?? 60) * 1e3;
@@ -7917,7 +8066,7 @@ var GoogleSpeechTranslationModel = class GoogleSpeechTranslationModel {
7917
8066
  feature: "outputAudioFormat",
7918
8067
  details: "The Gemini Live API always outputs 24kHz 16-bit PCM audio and does not accept an output audio format."
7919
8068
  });
7920
- const headers = combineHeaders(this.config.headers(), options.headers);
8069
+ const headers = combineHeaders(await resolve(this.config.headers), options.headers);
7921
8070
  let apiKey;
7922
8071
  for (const [key, value] of Object.entries(headers)) if (key.toLowerCase() === "x-goog-api-key" && value != null) apiKey = value;
7923
8072
  if (apiKey == null) throw new Error("Google Generative AI API key is required for streaming translation.");
@@ -8233,14 +8382,14 @@ function supportsExternalFileUrls(modelId) {
8233
8382
  function createGoogle(options = {}) {
8234
8383
  const baseURL = withoutTrailingSlash(options.baseURL) ?? DEFAULT_BASE_URL;
8235
8384
  const providerName = options.name ?? "google.generative-ai";
8236
- const getHeaders = () => withUserAgentSuffix({
8385
+ const getHeaders = () => resolveWith(options.apiKey, (apiKey) => withUserAgentSuffix({
8237
8386
  "x-goog-api-key": loadApiKey({
8238
- apiKey: options.apiKey,
8387
+ apiKey,
8239
8388
  environmentVariableName: "GOOGLE_GENERATIVE_AI_API_KEY",
8240
8389
  description: "Google Generative AI"
8241
8390
  }),
8242
8391
  ...options.headers
8243
- }, `ai-sdk-google/${VERSION}`);
8392
+ }, `ai-sdk-google/${VERSION}`));
8244
8393
  const getSupportedUrls = (modelId, includeExternalUrls = modelId == null || supportsExternalFileUrls(modelId)) => ({
8245
8394
  "*": [
8246
8395
  googleFilesUrlPattern,