@ai-sdk/google 4.0.108 → 4.0.110

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, stringifyWithBigIntAndCycles, 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.108";
6
+ const VERSION = "4.0.110";
7
7
  //#endregion
8
8
  //#region src/google-error.ts
9
9
  const getGoogleErrorSchema = () => z.object({
@@ -17,6 +17,27 @@ const googleFailedResponseHandler = createJsonErrorResponseHandler({
17
17
  errorSchema: googleErrorDataSchema,
18
18
  errorToMessage: (data) => data.error.message
19
19
  });
20
+ function mapGoogleErrorStatusToHttpStatusCode(status) {
21
+ switch (status) {
22
+ case "CANCELLED": return 499;
23
+ case "INVALID_ARGUMENT":
24
+ case "FAILED_PRECONDITION":
25
+ case "OUT_OF_RANGE": return 400;
26
+ case "DEADLINE_EXCEEDED": return 504;
27
+ case "NOT_FOUND": return 404;
28
+ case "ALREADY_EXISTS":
29
+ case "ABORTED": return 409;
30
+ case "PERMISSION_DENIED": return 403;
31
+ case "UNAUTHENTICATED": return 401;
32
+ case "RESOURCE_EXHAUSTED": return 429;
33
+ case "UNIMPLEMENTED": return 501;
34
+ case "UNKNOWN":
35
+ case "INTERNAL":
36
+ case "DATA_LOSS": return 500;
37
+ case "UNAVAILABLE": return 503;
38
+ default: return;
39
+ }
40
+ }
20
41
  //#endregion
21
42
  //#region src/google-embedding-model-options.ts
22
43
  const googleEmbeddingContentPartSchema = () => z.union([
@@ -369,13 +390,28 @@ function convertUrlToolResultPart(url) {
369
390
  data: parsedDataUrl.data
370
391
  } };
371
392
  }
372
- function containsJSONSchemaReference(value) {
373
- if (Array.isArray(value)) return value.some(containsJSONSchemaReference);
374
- if (typeof value !== "object" || value === null) return false;
375
- return Object.entries(value).some(([key, nestedValue]) => key === "$ref" || containsJSONSchemaReference(nestedValue));
393
+ function containsJSONSchemaReference(value, seen = /* @__PURE__ */ new WeakSet()) {
394
+ if (value === null || typeof value !== "object") return false;
395
+ if (seen.has(value)) return false;
396
+ seen.add(value);
397
+ if (Array.isArray(value)) return value.some((item) => containsJSONSchemaReference(item, seen));
398
+ return Object.entries(value).some(([key, nestedValue]) => key === "$ref" || containsJSONSchemaReference(nestedValue, seen));
376
399
  }
377
400
  function serializeFunctionResponseContent(value) {
378
- return containsJSONSchemaReference(value) ? JSON.stringify(value) : value;
401
+ if (containsJSONSchemaReference(value)) return stringifyWithBigIntAndCycles(value);
402
+ return containsNonJsonValue(value) ? secureJsonParse(stringifyWithBigIntAndCycles(value)) : value;
403
+ }
404
+ function containsNonJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
405
+ if (typeof value === "bigint") return true;
406
+ if (typeof value !== "object" || value === null) return false;
407
+ if (typeof value.toJSON === "function") return true;
408
+ if (ancestors.has(value)) return true;
409
+ ancestors.add(value);
410
+ try {
411
+ return Object.values(value).some((item) => containsNonJsonValue(item, ancestors));
412
+ } finally {
413
+ ancestors.delete(value);
414
+ }
379
415
  }
380
416
  function appendToolResultParts(parts, toolName, outputValue, toolCallId, includeFunctionCallIds = true, supportedUrls = {}) {
381
417
  const functionResponseParts = [];
@@ -616,7 +652,7 @@ function convertToGoogleMessages(prompt, options) {
616
652
  functionCall: {
617
653
  ...includeFunctionCallIds && part.toolCallId != null ? { id: part.toolCallId } : {},
618
654
  name: part.toolName,
619
- args: part.input
655
+ args: parseToolCallInput(part.input)
620
656
  },
621
657
  thoughtSignature: effectiveThoughtSignature
622
658
  };
@@ -704,6 +740,14 @@ function convertToGoogleMessages(prompt, options) {
704
740
  contents
705
741
  };
706
742
  }
743
+ function parseToolCallInput(input) {
744
+ if (typeof input !== "string") return input;
745
+ try {
746
+ return secureJsonParse(input);
747
+ } catch {
748
+ return input;
749
+ }
750
+ }
707
751
  //#endregion
708
752
  //#region src/download-tool-result-files.ts
709
753
  /**
@@ -1030,11 +1074,129 @@ const googleLanguageModelOptions = lazySchema(() => zodSchema(z.object({
1030
1074
  requestType: z.enum(["shared"]).optional()
1031
1075
  })));
1032
1076
  //#endregion
1033
- //#region src/google-model-capabilities.ts
1077
+ //#region src/google-model-catalog.ts
1034
1078
  const gemini1ModelPattern = /(^|[/.])gemini-1(?:[.-]|$)/i;
1035
1079
  const gemini2ModelPattern = /(^|[/.])gemini-2(?:[.-]|$)/i;
1036
- const gemini25ModelPattern$1 = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
1080
+ const gemini25ModelPattern = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
1037
1081
  const geminiModelPattern = /(^|[/.])gemini-/i;
1082
+ /** Options accepted under providerOptions.google (or googleVertex on Vertex). */
1083
+ const googleProviderOptions = { language: {
1084
+ responseModalities: { description: "Response modalities to generate." },
1085
+ thinkingConfig: { description: "Thinking budget, level, and thought output." },
1086
+ cachedContent: { description: "Cached content to use as request context." },
1087
+ structuredOutputs: { description: "Whether to send the JSON response schema." },
1088
+ safetySettings: { description: "Safety settings for the request." },
1089
+ threshold: { description: "Default threshold for configurable safety categories." },
1090
+ audioTimestamp: { description: "Enable timestamp understanding for audio." },
1091
+ labels: { description: "Billing labels. Vertex AI only." },
1092
+ mediaResolution: { description: "Resolution used to process media inputs." },
1093
+ imageConfig: { description: "Image generation configuration." },
1094
+ retrievalConfig: { description: "Retrieval configuration for tools." },
1095
+ streamFunctionCallArguments: { description: "Stream function arguments. Vertex AI only." },
1096
+ serviceTier: { description: "Service tier. Gemini API only." },
1097
+ continuationToken: { description: "Resume a response using its continuation token." },
1098
+ sharedRequestType: { description: "Shared PayGo tier. Vertex AI only." },
1099
+ requestType: { description: "Request routing type. Vertex AI only." }
1100
+ } };
1101
+ const standard = {
1102
+ image: true,
1103
+ objectGeneration: true,
1104
+ tools: true,
1105
+ streaming: true,
1106
+ googleSearch: true,
1107
+ urlContext: true
1108
+ };
1109
+ const googleModelCatalog = Object.fromEntries(Object.entries({
1110
+ "gemini-nano-banana-2.1": {
1111
+ image: true,
1112
+ objectGeneration: false,
1113
+ tools: false,
1114
+ streaming: false,
1115
+ googleSearch: true,
1116
+ urlContext: false
1117
+ },
1118
+ "gemini-4-argon": standard,
1119
+ "gemini-3.8-flash": standard,
1120
+ "gemini-3.7-flash": standard,
1121
+ "gemini-3.6-flash": standard,
1122
+ "gemini-3.5-flash": standard,
1123
+ "gemini-3.5-flash-lite": standard,
1124
+ "gemini-3.1-pro-preview": standard,
1125
+ "gemini-3.1-flash-image-preview": standard,
1126
+ "gemini-3.1-flash-lite-preview": standard,
1127
+ "gemini-3-pro-preview": standard,
1128
+ "gemini-3-pro-image-preview": standard,
1129
+ "gemini-3-flash-preview": standard,
1130
+ "gemini-2.5-pro": standard,
1131
+ "gemini-2.5-flash": standard,
1132
+ "gemini-2.5-flash-lite": standard,
1133
+ "gemini-2.5-flash-lite-preview-06-17": standard,
1134
+ "gemini-2.0-flash": standard
1135
+ }).map(([modelId, documented]) => [modelId, createGoogleLanguageModelEntry(modelId, documented)]));
1136
+ function getGoogleLanguageModelEntry(modelId) {
1137
+ return Object.prototype.hasOwnProperty.call(googleModelCatalog, modelId) ? googleModelCatalog[modelId] : createGoogleLanguageModelEntry(modelId);
1138
+ }
1139
+ function createGoogleLanguageModelEntry(modelId, documented) {
1140
+ const runtime = resolveRuntimeDefinition(modelId);
1141
+ const declared = documented != null;
1142
+ const id = modelId.toLowerCase();
1143
+ const thinkingFormat = runtime.usesGemini3Features && !modelId.includes("gemini-3-pro-image") ? "level" : "budget";
1144
+ const minLevel = getMinimumThinkingLevelForGemini3Model(modelId);
1145
+ return {
1146
+ capabilities: { language: {
1147
+ inputs: {
1148
+ image: documented?.image ?? "unknown",
1149
+ audio: "unknown"
1150
+ },
1151
+ objectGeneration: documented?.objectGeneration ?? "unknown",
1152
+ tools: {
1153
+ usage: documented?.tools ?? "unknown",
1154
+ streaming: documented?.streaming ?? "unknown",
1155
+ gemini2: runtime.supportsGemini2Tools,
1156
+ googleSearch: documented?.googleSearch ?? "unknown",
1157
+ urlContext: documented?.urlContext ?? "unknown",
1158
+ fileSearch: runtime.supportsFileSearch,
1159
+ mixed: runtime.usesGemini3Features,
1160
+ functionResponseParts: runtime.usesGemini3Features
1161
+ },
1162
+ reasoning: {
1163
+ support: "unknown",
1164
+ efforts: thinkingFormat === "level" ? [
1165
+ ...minLevel === "minimal" ? ["minimal"] : [],
1166
+ "low",
1167
+ "medium",
1168
+ "high"
1169
+ ] : void 0,
1170
+ minBudget: id.includes("2.5-pro") ? 128 : 0,
1171
+ maxBudget: id.includes("2.5-pro") || id.includes("gemini-3-pro-image") ? 32768 : 24576
1172
+ },
1173
+ sampling: {
1174
+ temperature: "unknown",
1175
+ topP: "unknown",
1176
+ topK: "unknown",
1177
+ logprobs: false,
1178
+ penalties: gemini25ModelPattern.test(modelId) ? { condition: "Only supported on the Vertex AI API." } : true
1179
+ },
1180
+ structuredOutput: { withFunctionTools: runtime.usesGemini3Features }
1181
+ } },
1182
+ providerOptions: { language: declareProviderOptions(declared ? true : "unknown", {
1183
+ labels: { condition: "Only supported on the Vertex AI API." },
1184
+ sharedRequestType: { condition: "Only supported on the Vertex AI API." },
1185
+ requestType: { condition: "Only supported on the Vertex AI API." },
1186
+ serviceTier: { condition: "Only supported on the Gemini API." },
1187
+ streamFunctionCallArguments: { condition: "Only supported for streaming requests on the Vertex AI API with Gemini 3 or newer." }
1188
+ }) },
1189
+ requestConfig: { language: {
1190
+ systemInstruction: id.startsWith("gemma-") ? "user" : "system",
1191
+ thinkingFormat,
1192
+ reasoningMaxOutputTokens: 65536,
1193
+ jsonResponseTool: /(^|\/)gemini-/i.test(modelId)
1194
+ } }
1195
+ };
1196
+ }
1197
+ function declareProviderOptions(support, exceptions) {
1198
+ return Object.fromEntries(Object.keys(googleProviderOptions.language).map((option) => [option, exceptions[option] ?? support]));
1199
+ }
1038
1200
  function isKnownPreGemini2Model(modelId) {
1039
1201
  return gemini1ModelPattern.test(modelId) || /(^|[/.])gemini-pro(?:-vision)?$/i.test(modelId) || /(^|[/.])gemini-robotics-er-1\.5(?:[.-]|$)/i.test(modelId);
1040
1202
  }
@@ -1045,17 +1207,39 @@ function isKnownPreGemini2Model(modelId) {
1045
1207
  * intentionally inherit the newest supported behavior. Add exceptions here
1046
1208
  * only when a model is known to require a legacy request shape.
1047
1209
  */
1048
- function getGoogleModelCapabilities(modelId) {
1210
+ function resolveRuntimeDefinition(modelId) {
1049
1211
  const isGeminiModel = geminiModelPattern.test(modelId);
1050
1212
  const isGemini2Model = gemini2ModelPattern.test(modelId);
1051
1213
  const isKnownPreGemini2 = isKnownPreGemini2Model(modelId);
1052
1214
  const usesGemini3Features = isGeminiModel && !(isKnownPreGemini2 || isGemini2Model);
1053
1215
  return {
1054
1216
  supportsGemini2Tools: isGeminiModel && !isKnownPreGemini2 || modelId.toLowerCase().includes("nano-banana"),
1055
- supportsFileSearch: gemini25ModelPattern$1.test(modelId) || usesGemini3Features,
1217
+ supportsFileSearch: gemini25ModelPattern.test(modelId) || usesGemini3Features,
1056
1218
  usesGemini3Features
1057
1219
  };
1058
1220
  }
1221
+ function getMinimumThinkingLevelForGemini3Model(modelId) {
1222
+ const modelName = /(?:^|[/.])(gemini-[^/]*)$/i.exec(modelId)?.[1].toLowerCase();
1223
+ if (modelName === "gemini-flash-latest") return "low";
1224
+ const proVersionMatch = /^gemini-(\d+)(?:\.\d+)?-pro(?:$|-)/.exec(modelName ?? "");
1225
+ if (Number(proVersionMatch?.[1]) >= 3) return "low";
1226
+ const versionMatch = /^gemini-(\d+)\.(\d+)-flash(?:$|-(?!lite(?:-|$)))/.exec(modelName ?? "");
1227
+ if (versionMatch == null) return "minimal";
1228
+ const majorVersion = Number(versionMatch[1]);
1229
+ const minorVersion = Number(versionMatch[2]);
1230
+ return majorVersion > 3 || majorVersion === 3 && minorVersion >= 7 ? "low" : "minimal";
1231
+ }
1232
+ //#endregion
1233
+ //#region src/google-model-capabilities.ts
1234
+ /** Compatibility projection of the resolved catalog for existing request code. */
1235
+ function getGoogleModelCapabilities(modelId) {
1236
+ const { tools } = getGoogleLanguageModelEntry(modelId).capabilities.language;
1237
+ return {
1238
+ supportsGemini2Tools: tools.gemini2,
1239
+ supportsFileSearch: tools.fileSearch,
1240
+ usesGemini3Features: tools.mixed
1241
+ };
1242
+ }
1059
1243
  //#endregion
1060
1244
  //#region src/google-prepare-tools.ts
1061
1245
  function prepareTools({ tools, toolChoice, modelId, isVertexProvider = false }) {
@@ -1537,7 +1721,6 @@ const configurableSafetySettingCategories = [
1537
1721
  "HARM_CATEGORY_HARASSMENT",
1538
1722
  "HARM_CATEGORY_SEXUALLY_EXPLICIT"
1539
1723
  ];
1540
- const gemini25ModelPattern = /(^|[/.])gemini-2\.5(?:[.-]|$)/i;
1541
1724
  const googleCloudStorageFunctionResponseUrls = {
1542
1725
  "image/png": [/^gs:\/\/.*$/],
1543
1726
  "image/jpeg": [/^gs:\/\/.*$/],
@@ -1622,8 +1805,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1622
1805
  imageConfig = geminiApiImageConfig;
1623
1806
  }
1624
1807
  }
1625
- const isGemmaModel = modelId.toLowerCase().startsWith("gemma-");
1626
- const isGemini25DeveloperApiModel = !isVertexProvider && gemini25ModelPattern.test(modelId);
1808
+ const entry = getGoogleLanguageModelEntry(modelId);
1809
+ const isGemmaModel = entry.requestConfig.language.systemInstruction === "user";
1810
+ const isGemini25DeveloperApiModel = !isVertexProvider && entry.capabilities.language.sampling.penalties !== true;
1627
1811
  if (isGemini25DeveloperApiModel && frequencyPenalty != null) warnings.push({
1628
1812
  type: "unsupported",
1629
1813
  feature: "frequencyPenalty"
@@ -1632,7 +1816,7 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1632
1816
  type: "unsupported",
1633
1817
  feature: "presencePenalty"
1634
1818
  });
1635
- const { usesGemini3Features } = getGoogleModelCapabilities(modelId);
1819
+ const usesGemini3Features = entry.capabilities.language.tools.functionResponseParts;
1636
1820
  const supportedFunctionResponseUrls = usesGemini3Features && config.downloadToolResultFiles?.supportsGoogleCloudStorageUrls ? googleCloudStorageFunctionResponseUrls : void 0;
1637
1821
  const { contents, systemInstruction } = convertToGoogleMessages(config.downloadToolResultFiles ? await downloadToolResultFiles(prompt, {
1638
1822
  abortSignal,
@@ -1717,8 +1901,10 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1717
1901
  }
1718
1902
  async getArgs(options, { isStreaming = false } = {}) {
1719
1903
  const { responseFormat, tools, toolChoice } = options;
1904
+ const entry = getGoogleLanguageModelEntry(this.modelId);
1905
+ const { structuredOutput } = entry.capabilities.language;
1720
1906
  let jsonResponseTool;
1721
- 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")) {
1907
+ 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")) {
1722
1908
  let name = "json";
1723
1909
  for (let suffix = 1; tools.some((tool) => tool.name === name); suffix++) name = `json_${suffix}`;
1724
1910
  jsonResponseTool = {
@@ -1888,10 +2074,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1888
2074
  }
1889
2075
  async doGenerate(options) {
1890
2076
  const { args, warnings, providerOptionsNames, extraHeaders, toolNameMapping, jsonResponseToolName } = await this.getArgs(options);
1891
- const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers, extraHeaders);
1892
- const generateContent = (body) => postJsonToApi({
2077
+ const generateContent = async (body) => postJsonToApi({
1893
2078
  url: `${this.config.baseURL}/${getModelPath(this.modelId)}:generateContent`,
1894
- headers: mergedHeaders,
2079
+ headers: combineHeaders(await resolve(this.config.headers), options.headers, extraHeaders),
1895
2080
  body,
1896
2081
  failedResponseHandler: googleFailedResponseHandler,
1897
2082
  successfulResponseHandler: createJsonResponseHandler(responseSchema),
@@ -1954,10 +2139,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
1954
2139
  async doStream(options) {
1955
2140
  const { args, warnings, providerOptionsNames, extraHeaders, toolNameMapping, jsonResponseToolName } = await this.getArgs(options, { isStreaming: true });
1956
2141
  const wrapProviderMetadata = (payload) => Object.fromEntries(providerOptionsNames.map((name) => [name, payload]));
1957
- const headers = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers, extraHeaders);
1958
- const streamGenerateContent = (body) => postJsonToApi({
2142
+ const streamGenerateContent = async (body) => postJsonToApi({
1959
2143
  url: `${this.config.baseURL}/${getModelPath(this.modelId)}:streamGenerateContent?alt=sse`,
1960
- headers,
2144
+ headers: combineHeaders(await resolve(this.config.headers), options.headers, extraHeaders),
1961
2145
  body,
1962
2146
  failedResponseHandler: googleFailedResponseHandler,
1963
2147
  successfulResponseHandler: createEventSourceResponseHandler(chunkSchema),
@@ -2070,14 +2254,15 @@ var GoogleLanguageModel = class GoogleLanguageModel {
2070
2254
  raw: void 0
2071
2255
  };
2072
2256
  const error = value.error;
2257
+ const statusCode = error.code ?? mapGoogleErrorStatusToHttpStatusCode(error.status);
2073
2258
  controller.enqueue({
2074
2259
  type: "error",
2075
2260
  error: createProviderStreamError({
2076
2261
  message: error.message,
2077
2262
  type: error.status,
2078
2263
  code: error.code ?? void 0,
2079
- statusCode: error.code ?? void 0,
2080
- isRetryable: error.code != null && (error.code === 408 || error.code === 409 || error.code === 429 || error.code >= 500),
2264
+ statusCode,
2265
+ isRetryable: statusCode != null && (statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500),
2081
2266
  data: error
2082
2267
  })
2083
2268
  });
@@ -2410,25 +2595,9 @@ var GoogleLanguageModel = class GoogleLanguageModel {
2410
2595
  };
2411
2596
  }
2412
2597
  };
2413
- function getMaxOutputTokensForGemini25Model() {
2414
- return 65536;
2415
- }
2416
- function getMaxThinkingTokensForGemini25Model(modelId) {
2417
- const id = modelId.toLowerCase();
2418
- if (id.includes("2.5-pro") || id.includes("gemini-3-pro-image")) return 32768;
2419
- return 24576;
2420
- }
2421
- /**
2422
- * Gemini 2.5 Pro cannot disable thinking and requires a thinking budget of at
2423
- * least 128 tokens. Other Gemini 2.5 models can disable thinking with a budget
2424
- * of 0.
2425
- */
2426
- function getMinThinkingTokensForGemini25Model(modelId) {
2427
- return modelId.toLowerCase().includes("2.5-pro") ? 128 : 0;
2428
- }
2429
2598
  function resolveThinkingConfig({ reasoning, modelId, warnings }) {
2430
2599
  if (!isCustomReasoning(reasoning)) return;
2431
- if (getGoogleModelCapabilities(modelId).usesGemini3Features && !modelId.includes("gemini-3-pro-image")) return resolveGemini3ThinkingConfig({
2600
+ if (getGoogleLanguageModelEntry(modelId).requestConfig.language.thinkingFormat === "level") return resolveGemini3ThinkingConfig({
2432
2601
  reasoning,
2433
2602
  modelId,
2434
2603
  warnings
@@ -2440,7 +2609,7 @@ function resolveThinkingConfig({ reasoning, modelId, warnings }) {
2440
2609
  });
2441
2610
  }
2442
2611
  function resolveGemini3ThinkingConfig({ reasoning, modelId, warnings }) {
2443
- const minimumThinkingLevel = getMinimumThinkingLevelForGemini3Model(modelId);
2612
+ const minimumThinkingLevel = getGoogleLanguageModelEntry(modelId).capabilities.language.reasoning.efforts?.[0];
2444
2613
  const thinkingLevel = mapReasoningToProviderEffort({
2445
2614
  reasoning,
2446
2615
  effortMap: {
@@ -2454,24 +2623,14 @@ function resolveGemini3ThinkingConfig({ reasoning, modelId, warnings }) {
2454
2623
  if (thinkingLevel == null) return;
2455
2624
  return { thinkingLevel };
2456
2625
  }
2457
- function getMinimumThinkingLevelForGemini3Model(modelId) {
2458
- const modelName = /(?:^|[/.])(gemini-[^/]*)$/i.exec(modelId)?.[1].toLowerCase();
2459
- if (modelName === "gemini-flash-latest") return "low";
2460
- const proVersionMatch = /^gemini-(\d+)(?:\.\d+)?-pro(?:$|-)/.exec(modelName ?? "");
2461
- if (Number(proVersionMatch?.[1]) >= 3) return "low";
2462
- const versionMatch = /^gemini-(\d+)\.(\d+)-flash(?:$|-(?!lite(?:-|$)))/.exec(modelName ?? "");
2463
- if (versionMatch == null) return "minimal";
2464
- const majorVersion = Number(versionMatch[1]);
2465
- const minorVersion = Number(versionMatch[2]);
2466
- return majorVersion > 3 || majorVersion === 3 && minorVersion >= 7 ? "low" : "minimal";
2467
- }
2468
2626
  function resolveGemini25ThinkingConfig({ reasoning, modelId, warnings }) {
2469
- const minThinkingBudget = getMinThinkingTokensForGemini25Model(modelId);
2627
+ const entry = getGoogleLanguageModelEntry(modelId);
2628
+ const minThinkingBudget = entry.capabilities.language.reasoning.minBudget;
2470
2629
  if (reasoning === "none" && minThinkingBudget === 0) return { thinkingBudget: 0 };
2471
2630
  return { thinkingBudget: mapReasoningToProviderBudget({
2472
2631
  reasoning,
2473
- maxOutputTokens: getMaxOutputTokensForGemini25Model(),
2474
- maxReasoningBudget: getMaxThinkingTokensForGemini25Model(modelId),
2632
+ maxOutputTokens: entry.requestConfig.language.reasoningMaxOutputTokens,
2633
+ maxReasoningBudget: entry.capabilities.language.reasoning.maxBudget,
2475
2634
  minReasoningBudget: minThinkingBudget,
2476
2635
  warnings
2477
2636
  }) };
@@ -2887,12 +3046,11 @@ var GoogleBatch = class {
2887
3046
  warning
2888
3047
  });
2889
3048
  }
2890
- const headers = await this.getHeaders(options.headers);
2891
3049
  const createUrl = `${this.batchConfig.baseURL}/${getModelPath(modelId)}:batchGenerateContent`;
2892
3050
  if (fileParts == null) {
2893
3051
  const { value: operation } = await postJsonToApi({
2894
3052
  url: createUrl,
2895
- headers,
3053
+ headers: await this.getHeaders(options.headers),
2896
3054
  body: inlineBatchBody,
2897
3055
  failedResponseHandler: googleFailedResponseHandler,
2898
3056
  successfulResponseHandler: createJsonResponseHandler(googleBatchOperationSchema),
@@ -2913,7 +3071,7 @@ var GoogleBatch = class {
2913
3071
  });
2914
3072
  const { value: uploadUrl } = await postJsonToApi({
2915
3073
  url: `${this.getBaseOrigin()}/upload/v1beta/files`,
2916
- headers: combineHeaders(headers, {
3074
+ headers: combineHeaders(await this.getHeaders(options.headers), {
2917
3075
  "X-Goog-Upload-Protocol": "resumable",
2918
3076
  "X-Goog-Upload-Command": "start",
2919
3077
  "X-Goog-Upload-Header-Content-Length": String(inputFile.size),
@@ -2946,7 +3104,7 @@ var GoogleBatch = class {
2946
3104
  });
2947
3105
  const { value: operation } = await postJsonToApi({
2948
3106
  url: createUrl,
2949
- headers,
3107
+ headers: await this.getHeaders(options.headers),
2950
3108
  body: { batch: {
2951
3109
  displayName,
2952
3110
  ...options.webhookUrl != null && { webhookConfig: { uris: [options.webhookUrl] } },
@@ -3568,7 +3726,7 @@ var GoogleFiles = class {
3568
3726
  providerOptions: options.providerOptions,
3569
3727
  schema: googleFilesUploadOptionsSchema
3570
3728
  });
3571
- const resolvedHeaders = combineHeaders(this.config.headers(), options.headers);
3729
+ const getHeaders = async () => combineHeaders(await resolve(this.config.headers), options.headers);
3572
3730
  const fetchFn = this.config.fetch ?? globalThis.fetch;
3573
3731
  const warnings = [];
3574
3732
  if (options.filename != null) warnings.push({
@@ -3581,7 +3739,7 @@ var GoogleFiles = class {
3581
3739
  const initResponse = await fetchFn(`${this.config.baseURL.replace(/\/v1beta$/, "")}/upload/v1beta/files`, {
3582
3740
  method: "POST",
3583
3741
  headers: {
3584
- ...resolvedHeaders,
3742
+ ...await getHeaders(),
3585
3743
  "X-Goog-Upload-Protocol": "resumable",
3586
3744
  "X-Goog-Upload-Command": "start",
3587
3745
  "X-Goog-Upload-Header-Content-Length": String(fileBytes.length),
@@ -3634,7 +3792,7 @@ var GoogleFiles = class {
3634
3792
  const { value: fileStatus } = await getFromApi({
3635
3793
  url: `${this.config.baseURL}/${filePath}`,
3636
3794
  validateUrl: false,
3637
- headers: combineHeaders(resolvedHeaders),
3795
+ headers: await getHeaders(),
3638
3796
  successfulResponseHandler: createJsonResponseHandler(googleFileResponseSchema),
3639
3797
  failedResponseHandler: googleFailedResponseHandler,
3640
3798
  abortSignal: options.abortSignal,
@@ -6148,7 +6306,7 @@ async function cancelGoogleInteraction({ baseURL, interactionId, headers, fetch
6148
6306
  try {
6149
6307
  const response = await fetch(url, {
6150
6308
  method: "POST",
6151
- headers: withUserAgentSuffix(combineHeaders({ "Content-Type": "application/json" }, headers), getRuntimeEnvironmentUserAgent()),
6309
+ headers: withUserAgentSuffix(combineHeaders({ "Content-Type": "application/json" }, await resolve(headers)), getRuntimeEnvironmentUserAgent()),
6152
6310
  body: "{}"
6153
6311
  });
6154
6312
  try {
@@ -6198,7 +6356,7 @@ async function pollGoogleInteractionUntilTerminal({ baseURL, interactionId, head
6198
6356
  const { value: response, rawValue: rawResponse, responseHeaders } = await getFromApi({
6199
6357
  url,
6200
6358
  validateUrl: false,
6201
- headers,
6359
+ headers: await resolve(headers),
6202
6360
  failedResponseHandler: googleFailedResponseHandler,
6203
6361
  successfulResponseHandler: createJsonResponseHandler(googleInteractionsResponseSchema),
6204
6362
  abortSignal,
@@ -6393,10 +6551,6 @@ const DEFAULT_RETRY_DELAY_MS = 500;
6393
6551
  */
6394
6552
  function streamGoogleInteractionEvents({ baseURL, interactionId, headers, fetch, abortSignal, maxRetries = DEFAULT_MAX_RETRIES, retryDelayMs = DEFAULT_RETRY_DELAY_MS }) {
6395
6553
  if (interactionId.length === 0) throw new Error("google.interactions: cannot stream a background interaction without an id.");
6396
- const eventSourceHeaders = {
6397
- ...headers,
6398
- accept: "text/event-stream"
6399
- };
6400
6554
  let lastEventId;
6401
6555
  let complete = false;
6402
6556
  let attempt = 0;
@@ -6419,7 +6573,10 @@ function streamGoogleInteractionEvents({ baseURL, interactionId, headers, fetch,
6419
6573
  const { value: stream } = await getFromApi({
6420
6574
  url: buildUrl(),
6421
6575
  validateUrl: false,
6422
- headers: eventSourceHeaders,
6576
+ headers: {
6577
+ ...await resolve(headers),
6578
+ accept: "text/event-stream"
6579
+ },
6423
6580
  failedResponseHandler: googleFailedResponseHandler,
6424
6581
  successfulResponseHandler: createEventSourceResponseHandler(googleInteractionsEventSchema),
6425
6582
  abortSignal: effectiveSignal,
@@ -6890,10 +7047,10 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6890
7047
  async doGenerate(options) {
6891
7048
  const { args, warnings, isAgent, isBackground, pollingTimeoutMs } = await this.getArgs(options);
6892
7049
  const url = `${this.config.baseURL}/interactions`;
6893
- const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers);
7050
+ const mergedHeaders = async () => combineHeaders(await resolve(this.config.headers), options.headers);
6894
7051
  let { responseHeaders, value: response, rawValue: rawResponse } = await postJsonToApi({
6895
7052
  url,
6896
- headers: mergedHeaders,
7053
+ headers: await resolve(mergedHeaders),
6897
7054
  body: args,
6898
7055
  failedResponseHandler: googleFailedResponseHandler,
6899
7056
  successfulResponseHandler: createJsonResponseHandler(googleInteractionsResponseSchema),
@@ -6957,7 +7114,7 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6957
7114
  async doStream(options) {
6958
7115
  const { args, warnings, isBackground, pollingTimeoutMs } = await this.getArgs(options);
6959
7116
  const url = `${this.config.baseURL}/interactions`;
6960
- const mergedHeaders = combineHeaders(this.config.headers ? await resolve(this.config.headers) : void 0, options.headers);
7117
+ const mergedHeaders = async () => combineHeaders(await resolve(this.config.headers), options.headers);
6961
7118
  if (isBackground) return this.doStreamBackground({
6962
7119
  args,
6963
7120
  warnings,
@@ -6972,7 +7129,7 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6972
7129
  };
6973
7130
  const { responseHeaders, value: response } = await postJsonToApi({
6974
7131
  url,
6975
- headers: mergedHeaders,
7132
+ headers: await resolve(mergedHeaders),
6976
7133
  body,
6977
7134
  failedResponseHandler: googleFailedResponseHandler,
6978
7135
  successfulResponseHandler: createEventSourceResponseHandler(googleInteractionsEventSchema),
@@ -6995,7 +7152,7 @@ var GoogleInteractionsLanguageModel = class GoogleInteractionsLanguageModel {
6995
7152
  async doStreamBackground({ args, warnings, url, mergedHeaders, options, pollingTimeoutMs }) {
6996
7153
  const { responseHeaders: postHeaders, value: postResponse } = await postJsonToApi({
6997
7154
  url,
6998
- headers: mergedHeaders,
7155
+ headers: await resolve(mergedHeaders),
6999
7156
  body: args,
7000
7157
  failedResponseHandler: googleFailedResponseHandler,
7001
7158
  successfulResponseHandler: createJsonResponseHandler(googleInteractionsResponseSchema),
@@ -7429,7 +7586,7 @@ var GoogleRealtimeModel = class {
7429
7586
  }
7430
7587
  async doCreateClientSecret(options) {
7431
7588
  const fetchFn = this.config.fetch ?? fetch;
7432
- const apiKey = this.config.headers()["x-goog-api-key"];
7589
+ const apiKey = (await resolve(this.config.headers))["x-goog-api-key"];
7433
7590
  if (!apiKey) throw new Error("Google Generative AI API key is required for realtime token creation.");
7434
7591
  const now = Date.now();
7435
7592
  const openWindowMs = (options.expiresAfterSeconds ?? 60) * 1e3;
@@ -7954,7 +8111,7 @@ var GoogleSpeechTranslationModel = class GoogleSpeechTranslationModel {
7954
8111
  feature: "outputAudioFormat",
7955
8112
  details: "The Gemini Live API always outputs 24kHz 16-bit PCM audio and does not accept an output audio format."
7956
8113
  });
7957
- const headers = combineHeaders(this.config.headers(), options.headers);
8114
+ const headers = combineHeaders(await resolve(this.config.headers), options.headers);
7958
8115
  let apiKey;
7959
8116
  for (const [key, value] of Object.entries(headers)) if (key.toLowerCase() === "x-goog-api-key" && value != null) apiKey = value;
7960
8117
  if (apiKey == null) throw new Error("Google Generative AI API key is required for streaming translation.");
@@ -8270,14 +8427,14 @@ function supportsExternalFileUrls(modelId) {
8270
8427
  function createGoogle(options = {}) {
8271
8428
  const baseURL = withoutTrailingSlash(options.baseURL) ?? DEFAULT_BASE_URL;
8272
8429
  const providerName = options.name ?? "google.generative-ai";
8273
- const getHeaders = () => withUserAgentSuffix({
8430
+ const getHeaders = () => resolveWith(options.apiKey, (apiKey) => withUserAgentSuffix({
8274
8431
  "x-goog-api-key": loadApiKey({
8275
- apiKey: options.apiKey,
8432
+ apiKey,
8276
8433
  environmentVariableName: "GOOGLE_GENERATIVE_AI_API_KEY",
8277
8434
  description: "Google Generative AI"
8278
8435
  }),
8279
8436
  ...options.headers
8280
- }, `ai-sdk-google/${VERSION}`);
8437
+ }, `ai-sdk-google/${VERSION}`));
8281
8438
  const getSupportedUrls = (modelId, includeExternalUrls = modelId == null || supportsExternalFileUrls(modelId)) => ({
8282
8439
  "*": [
8283
8440
  googleFilesUrlPattern,