@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/CHANGELOG.md +26 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +238 -81
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +226 -68
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +23 -11
- package/package.json +3 -3
- package/src/convert-to-google-messages.ts +61 -7
- package/src/google-batch.ts +3 -4
- package/src/google-embedding-model.ts +2 -1
- package/src/google-error.ts +37 -0
- package/src/google-files.ts +7 -7
- package/src/google-language-model.ts +43 -92
- package/src/google-model-capabilities.ts +7 -40
- package/src/google-model-catalog.ts +319 -0
- package/src/google-provider.ts +15 -11
- package/src/interactions/cancel-google-interaction.ts +7 -2
- package/src/interactions/google-interactions-language-model.ts +8 -12
- package/src/interactions/poll-google-interactions.ts +4 -2
- package/src/interactions/stream-google-interactions.ts +4 -7
- package/src/realtime/google-realtime-model.ts +7 -3
- package/src/speech-translation/google-speech-translation-model.ts +7 -2
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.
|
|
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 (
|
|
374
|
-
if (
|
|
375
|
-
|
|
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
|
-
|
|
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-
|
|
1077
|
+
//#region src/google-model-catalog.ts
|
|
1034
1078
|
const gemini1ModelPattern = /(^|[/.])gemini-1(?:[.-]|$)/i;
|
|
1035
1079
|
const gemini2ModelPattern = /(^|[/.])gemini-2(?:[.-]|$)/i;
|
|
1036
|
-
const gemini25ModelPattern
|
|
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
|
|
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
|
|
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
|
|
1626
|
-
const
|
|
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
|
|
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") &&
|
|
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
|
|
1892
|
-
const generateContent = (body) => postJsonToApi({
|
|
2077
|
+
const generateContent = async (body) => postJsonToApi({
|
|
1893
2078
|
url: `${this.config.baseURL}/${getModelPath(this.modelId)}:generateContent`,
|
|
1894
|
-
headers:
|
|
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
|
|
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
|
|
2080
|
-
isRetryable:
|
|
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 (
|
|
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 =
|
|
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
|
|
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:
|
|
2474
|
-
maxReasoningBudget:
|
|
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
|
|
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
|
-
...
|
|
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:
|
|
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:
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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,
|