@ai-sdk/google 4.0.22 → 4.0.24
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 +12 -0
- package/dist/index.js +51 -37
- package/dist/index.js.map +1 -1
- package/dist/internal/index.js +50 -36
- package/dist/internal/index.js.map +1 -1
- package/docs/15-google.mdx +16 -6
- package/package.json +1 -1
- package/src/convert-to-google-messages.ts +16 -4
- package/src/google-language-model.ts +9 -9
- package/src/google-model-capabilities.ts +44 -0
- package/src/google-prepare-tools.ts +11 -23
package/docs/15-google.mdx
CHANGED
|
@@ -91,6 +91,16 @@ Google language models can also be used in the `streamText` function
|
|
|
91
91
|
and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output)
|
|
92
92
|
(see [AI SDK Core](/docs/ai-sdk-core)).
|
|
93
93
|
|
|
94
|
+
<Note>
|
|
95
|
+
To remain forward-compatible, the provider treats unrecognized `gemini-*`
|
|
96
|
+
model IDs and `-latest` aliases like the newest supported Gemini generation.
|
|
97
|
+
Currently, this means Gemini 3 request behavior for provider-defined and mixed
|
|
98
|
+
tools, `thinkingLevel` reasoning, multimodal function responses, and thought
|
|
99
|
+
signatures. Known legacy Gemini model IDs keep their generation-specific
|
|
100
|
+
request behavior. This SDK default controls request serialization; the
|
|
101
|
+
selected model must still support each feature in the Google API.
|
|
102
|
+
</Note>
|
|
103
|
+
|
|
94
104
|
Google also supports some model specific settings that are not part of the [standard call settings](/docs/ai-sdk-core/settings).
|
|
95
105
|
You can pass them as an options argument:
|
|
96
106
|
|
|
@@ -163,7 +173,7 @@ The following optional provider options are available for Google models:
|
|
|
163
173
|
Optional. Configuration for the model's thinking process. Only supported by specific [Google models](https://ai.google.dev/gemini-api/docs/thinking).
|
|
164
174
|
- **thinkingLevel** _'minimal' | 'low' | 'medium' | 'high'_
|
|
165
175
|
|
|
166
|
-
Optional. Controls the thinking depth for Gemini 3 models. Gemini 3.1 Pro supports 'low', 'medium', and 'high', Gemini 3 Pro supports 'low' and 'high', while Gemini 3 Flash supports all four levels: 'minimal', 'low', 'medium', and 'high'.
|
|
176
|
+
Optional. Controls the thinking depth for Gemini 3 and later models. Gemini 3.1 Pro supports 'low', 'medium', and 'high', Gemini 3 Pro supports 'low' and 'high', while Gemini 3 Flash supports all four levels: 'minimal', 'low', 'medium', and 'high'.
|
|
167
177
|
|
|
168
178
|
- **thinkingBudget** _number_
|
|
169
179
|
|
|
@@ -171,7 +181,7 @@ The following optional provider options are available for Google models:
|
|
|
171
181
|
For more information about the possible value ranges for each model see [Google thinking documentation](https://ai.google.dev/gemini-api/docs/thinking#set-budget).
|
|
172
182
|
|
|
173
183
|
<Note>
|
|
174
|
-
This option is for Gemini 2.5 models. Gemini 3 models should use
|
|
184
|
+
This option is for Gemini 2.5 models. Gemini 3 and later models should use
|
|
175
185
|
`thinkingLevel` instead.
|
|
176
186
|
</Note>
|
|
177
187
|
|
|
@@ -242,11 +252,11 @@ The following optional provider options are available for Google models:
|
|
|
242
252
|
|
|
243
253
|
### Thinking
|
|
244
254
|
|
|
245
|
-
The Gemini 2.5 and Gemini 3 series models use an internal "thinking process" that significantly improves their reasoning and multi-step planning abilities, making them highly effective for complex tasks such as coding, advanced mathematics, and data analysis. For more information see [Google thinking documentation](https://ai.google.dev/gemini-api/docs/thinking).
|
|
255
|
+
The Gemini 2.5 and Gemini 3-and-later series models use an internal "thinking process" that significantly improves their reasoning and multi-step planning abilities, making them highly effective for complex tasks such as coding, advanced mathematics, and data analysis. For more information see [Google thinking documentation](https://ai.google.dev/gemini-api/docs/thinking).
|
|
246
256
|
|
|
247
|
-
#### Gemini 3 Models
|
|
257
|
+
#### Gemini 3 and Later Models
|
|
248
258
|
|
|
249
|
-
For Gemini 3 models, use the `thinkingLevel` parameter to control the depth of reasoning:
|
|
259
|
+
For Gemini 3 and later models, use the `thinkingLevel` parameter to control the depth of reasoning:
|
|
250
260
|
|
|
251
261
|
```ts
|
|
252
262
|
import { google, GoogleLanguageModelOptions } from '@ai-sdk/google';
|
|
@@ -628,7 +638,7 @@ Enterprise Web Search provides the following benefits:
|
|
|
628
638
|
|
|
629
639
|
### File Search
|
|
630
640
|
|
|
631
|
-
The [File Search tool](https://ai.google.dev/gemini-api/docs/file-search) lets Gemini retrieve context from your own documents that you have indexed in File Search stores.
|
|
641
|
+
The [File Search tool](https://ai.google.dev/gemini-api/docs/file-search) lets Gemini retrieve context from your own documents that you have indexed in File Search stores. The provider enables this tool for Gemini 2.5 and Gemini 3-and-later model IDs, including unrecognized future Gemini IDs.
|
|
632
642
|
|
|
633
643
|
```ts highlight="9-13"
|
|
634
644
|
import { google } from '@ai-sdk/google';
|
package/package.json
CHANGED
|
@@ -76,6 +76,7 @@ function appendToolResultParts(
|
|
|
76
76
|
{ type: 'content' }
|
|
77
77
|
>['value'],
|
|
78
78
|
toolCallId?: string,
|
|
79
|
+
includeFunctionCallIds = true,
|
|
79
80
|
): void {
|
|
80
81
|
const functionResponseParts: GoogleFunctionResponsePart[] = [];
|
|
81
82
|
const responseTextParts: string[] = [];
|
|
@@ -118,7 +119,9 @@ function appendToolResultParts(
|
|
|
118
119
|
|
|
119
120
|
parts.push({
|
|
120
121
|
functionResponse: {
|
|
121
|
-
...(toolCallId != null
|
|
122
|
+
...(includeFunctionCallIds && toolCallId != null
|
|
123
|
+
? { id: toolCallId }
|
|
124
|
+
: {}),
|
|
122
125
|
name: toolName,
|
|
123
126
|
response: {
|
|
124
127
|
name: toolName,
|
|
@@ -147,13 +150,16 @@ function appendLegacyToolResultParts(
|
|
|
147
150
|
{ type: 'content' }
|
|
148
151
|
>['value'],
|
|
149
152
|
toolCallId?: string,
|
|
153
|
+
includeFunctionCallIds = true,
|
|
150
154
|
): void {
|
|
151
155
|
for (const contentPart of outputValue) {
|
|
152
156
|
switch (contentPart.type) {
|
|
153
157
|
case 'text':
|
|
154
158
|
parts.push({
|
|
155
159
|
functionResponse: {
|
|
156
|
-
...(toolCallId != null
|
|
160
|
+
...(includeFunctionCallIds && toolCallId != null
|
|
161
|
+
? { id: toolCallId }
|
|
162
|
+
: {}),
|
|
157
163
|
name: toolName,
|
|
158
164
|
response: {
|
|
159
165
|
name: toolName,
|
|
@@ -206,6 +212,7 @@ export function convertToGoogleMessages(
|
|
|
206
212
|
*/
|
|
207
213
|
providerOptionsNames?: readonly string[];
|
|
208
214
|
supportsFunctionResponseParts?: boolean;
|
|
215
|
+
includeFunctionCallIds?: boolean;
|
|
209
216
|
},
|
|
210
217
|
): GooglePrompt {
|
|
211
218
|
const systemInstructionParts: Array<{ text: string }> = [];
|
|
@@ -218,6 +225,7 @@ export function convertToGoogleMessages(
|
|
|
218
225
|
const isVertexLike = !providerOptionsNames.includes('google');
|
|
219
226
|
const supportsFunctionResponseParts =
|
|
220
227
|
options?.supportsFunctionResponseParts ?? true;
|
|
228
|
+
const includeFunctionCallIds = options?.includeFunctionCallIds ?? true;
|
|
221
229
|
|
|
222
230
|
let sentinelInjected = false;
|
|
223
231
|
const missingSignatureToolNames: string[] = [];
|
|
@@ -497,7 +505,7 @@ export function convertToGoogleMessages(
|
|
|
497
505
|
|
|
498
506
|
return {
|
|
499
507
|
functionCall: {
|
|
500
|
-
...(part.toolCallId != null
|
|
508
|
+
...(includeFunctionCallIds && part.toolCallId != null
|
|
501
509
|
? { id: part.toolCallId }
|
|
502
510
|
: {}),
|
|
503
511
|
name: part.toolName,
|
|
@@ -591,6 +599,7 @@ export function convertToGoogleMessages(
|
|
|
591
599
|
part.toolName,
|
|
592
600
|
output.value,
|
|
593
601
|
part.toolCallId,
|
|
602
|
+
includeFunctionCallIds,
|
|
594
603
|
);
|
|
595
604
|
} else {
|
|
596
605
|
appendLegacyToolResultParts(
|
|
@@ -598,12 +607,15 @@ export function convertToGoogleMessages(
|
|
|
598
607
|
part.toolName,
|
|
599
608
|
output.value,
|
|
600
609
|
part.toolCallId,
|
|
610
|
+
includeFunctionCallIds,
|
|
601
611
|
);
|
|
602
612
|
}
|
|
603
613
|
} else {
|
|
604
614
|
parts.push({
|
|
605
615
|
functionResponse: {
|
|
606
|
-
...(part.toolCallId != null
|
|
616
|
+
...(includeFunctionCallIds && part.toolCallId != null
|
|
617
|
+
? { id: part.toolCallId }
|
|
618
|
+
: {}),
|
|
607
619
|
name: part.toolName,
|
|
608
620
|
response: {
|
|
609
621
|
name: part.toolName,
|
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
type GoogleLanguageModelOptions,
|
|
47
47
|
type GoogleModelId,
|
|
48
48
|
} from './google-language-model-options';
|
|
49
|
+
import { getGoogleModelCapabilities } from './google-model-capabilities';
|
|
49
50
|
import type { GoogleProviderMetadata } from './google-prompt';
|
|
50
51
|
import { prepareTools } from './google-prepare-tools';
|
|
51
52
|
import {
|
|
@@ -257,15 +258,15 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
257
258
|
}
|
|
258
259
|
|
|
259
260
|
const isGemmaModel = this.modelId.toLowerCase().startsWith('gemma-');
|
|
260
|
-
const
|
|
261
|
-
const supportsFunctionResponseParts = isGemini3Model;
|
|
261
|
+
const { usesGemini3Features } = getGoogleModelCapabilities(this.modelId);
|
|
262
262
|
|
|
263
263
|
const { contents, systemInstruction } = convertToGoogleMessages(prompt, {
|
|
264
264
|
isGemmaModel,
|
|
265
|
-
isGemini3Model,
|
|
265
|
+
isGemini3Model: usesGemini3Features,
|
|
266
266
|
onWarning: warning => warnings.push(warning),
|
|
267
267
|
providerOptionsNames,
|
|
268
|
-
supportsFunctionResponseParts,
|
|
268
|
+
supportsFunctionResponseParts: usesGemini3Features,
|
|
269
|
+
includeFunctionCallIds: !isVertexProvider,
|
|
269
270
|
});
|
|
270
271
|
|
|
271
272
|
const {
|
|
@@ -1136,10 +1137,6 @@ export class GoogleLanguageModel implements LanguageModelV4 {
|
|
|
1136
1137
|
}
|
|
1137
1138
|
}
|
|
1138
1139
|
|
|
1139
|
-
function isGemini3Model(modelId: string): boolean {
|
|
1140
|
-
return /gemini-3[\.\-]/i.test(modelId) || /gemini-3$/i.test(modelId);
|
|
1141
|
-
}
|
|
1142
|
-
|
|
1143
1140
|
function getMaxOutputTokensForGemini25Model(): number {
|
|
1144
1141
|
return 65536;
|
|
1145
1142
|
}
|
|
@@ -1169,7 +1166,10 @@ function resolveThinkingConfig({
|
|
|
1169
1166
|
return undefined;
|
|
1170
1167
|
}
|
|
1171
1168
|
|
|
1172
|
-
if (
|
|
1169
|
+
if (
|
|
1170
|
+
getGoogleModelCapabilities(modelId).usesGemini3Features &&
|
|
1171
|
+
!modelId.includes('gemini-3-pro-image')
|
|
1172
|
+
) {
|
|
1173
1173
|
return resolveGemini3ThinkingConfig({ reasoning, warnings });
|
|
1174
1174
|
}
|
|
1175
1175
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
type GoogleModelCapabilities = {
|
|
2
|
+
supportsGemini2Tools: boolean;
|
|
3
|
+
supportsFileSearch: boolean;
|
|
4
|
+
usesGemini3Features: boolean;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const gemini1ModelPattern = /(^|\/)gemini-1(?:[.-]|$)/i;
|
|
8
|
+
const gemini2ModelPattern = /(^|\/)gemini-2(?:[.-]|$)/i;
|
|
9
|
+
const gemini25ModelPattern = /(^|\/)gemini-2\.5(?:[.-]|$)/i;
|
|
10
|
+
const geminiModelPattern = /(^|\/)gemini-/i;
|
|
11
|
+
|
|
12
|
+
function isKnownPreGemini2Model(modelId: string): boolean {
|
|
13
|
+
return (
|
|
14
|
+
gemini1ModelPattern.test(modelId) ||
|
|
15
|
+
/(^|\/)gemini-pro(?:-vision)?$/i.test(modelId) ||
|
|
16
|
+
/(^|\/)gemini-robotics-er-1\.5(?:[.-]|$)/i.test(modelId)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Classifies Gemini capabilities by excluding known older generations.
|
|
22
|
+
*
|
|
23
|
+
* Google model IDs are open-ended, so unrecognized Gemini IDs and aliases
|
|
24
|
+
* intentionally inherit the newest supported behavior. Add exceptions here
|
|
25
|
+
* only when a model is known to require a legacy request shape.
|
|
26
|
+
*/
|
|
27
|
+
export function getGoogleModelCapabilities(
|
|
28
|
+
modelId: string,
|
|
29
|
+
): GoogleModelCapabilities {
|
|
30
|
+
const isGeminiModel = geminiModelPattern.test(modelId);
|
|
31
|
+
const isGemini2Model = gemini2ModelPattern.test(modelId);
|
|
32
|
+
const isKnownPreGemini2 = isKnownPreGemini2Model(modelId);
|
|
33
|
+
const isKnownOlderModel = isKnownPreGemini2 || isGemini2Model;
|
|
34
|
+
const usesGemini3Features = isGeminiModel && !isKnownOlderModel;
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
supportsGemini2Tools:
|
|
38
|
+
(isGeminiModel && !isKnownPreGemini2) ||
|
|
39
|
+
modelId.toLowerCase().includes('nano-banana'),
|
|
40
|
+
supportsFileSearch:
|
|
41
|
+
gemini25ModelPattern.test(modelId) || usesGemini3Features,
|
|
42
|
+
usesGemini3Features,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import { convertJSONSchemaToOpenAPISchema } from './convert-json-schema-to-openapi-schema';
|
|
7
7
|
import type { GoogleModelId } from './google-language-model-options';
|
|
8
|
+
import { getGoogleModelCapabilities } from './google-model-capabilities';
|
|
8
9
|
|
|
9
10
|
export function prepareTools({
|
|
10
11
|
tools,
|
|
@@ -46,21 +47,8 @@ export function prepareTools({
|
|
|
46
47
|
|
|
47
48
|
const toolWarnings: SharedV4Warning[] = [];
|
|
48
49
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
'gemini-flash-latest',
|
|
52
|
-
'gemini-flash-lite-latest',
|
|
53
|
-
'gemini-pro-latest',
|
|
54
|
-
] as const satisfies GoogleModelId[]
|
|
55
|
-
).some(id => id === modelId);
|
|
56
|
-
const isGemini2orNewer =
|
|
57
|
-
modelId.includes('gemini-2') ||
|
|
58
|
-
modelId.includes('gemini-3') ||
|
|
59
|
-
modelId.includes('nano-banana') ||
|
|
60
|
-
isLatest;
|
|
61
|
-
const isGemini3orNewer = modelId.includes('gemini-3');
|
|
62
|
-
const supportsFileSearch =
|
|
63
|
-
modelId.includes('gemini-2.5') || modelId.includes('gemini-3');
|
|
50
|
+
const { supportsGemini2Tools, supportsFileSearch, usesGemini3Features } =
|
|
51
|
+
getGoogleModelCapabilities(modelId);
|
|
64
52
|
|
|
65
53
|
if (tools == null) {
|
|
66
54
|
return { tools: undefined, toolConfig: undefined, toolWarnings };
|
|
@@ -70,7 +58,7 @@ export function prepareTools({
|
|
|
70
58
|
const hasFunctionTools = tools.some(tool => tool.type === 'function');
|
|
71
59
|
const hasProviderTools = tools.some(tool => tool.type === 'provider');
|
|
72
60
|
|
|
73
|
-
if (hasFunctionTools && hasProviderTools && !
|
|
61
|
+
if (hasFunctionTools && hasProviderTools && !usesGemini3Features) {
|
|
74
62
|
toolWarnings.push({
|
|
75
63
|
type: 'unsupported',
|
|
76
64
|
feature: `combination of function and provider-defined tools`,
|
|
@@ -84,7 +72,7 @@ export function prepareTools({
|
|
|
84
72
|
ProviderTools.forEach(tool => {
|
|
85
73
|
switch (tool.id) {
|
|
86
74
|
case 'google.google_search':
|
|
87
|
-
if (
|
|
75
|
+
if (supportsGemini2Tools) {
|
|
88
76
|
googleTools.push({ googleSearch: { ...tool.args } });
|
|
89
77
|
} else {
|
|
90
78
|
toolWarnings.push({
|
|
@@ -95,7 +83,7 @@ export function prepareTools({
|
|
|
95
83
|
}
|
|
96
84
|
break;
|
|
97
85
|
case 'google.enterprise_web_search':
|
|
98
|
-
if (
|
|
86
|
+
if (supportsGemini2Tools) {
|
|
99
87
|
googleTools.push({ enterpriseWebSearch: {} });
|
|
100
88
|
} else {
|
|
101
89
|
toolWarnings.push({
|
|
@@ -106,7 +94,7 @@ export function prepareTools({
|
|
|
106
94
|
}
|
|
107
95
|
break;
|
|
108
96
|
case 'google.url_context':
|
|
109
|
-
if (
|
|
97
|
+
if (supportsGemini2Tools) {
|
|
110
98
|
googleTools.push({ urlContext: {} });
|
|
111
99
|
} else {
|
|
112
100
|
toolWarnings.push({
|
|
@@ -118,7 +106,7 @@ export function prepareTools({
|
|
|
118
106
|
}
|
|
119
107
|
break;
|
|
120
108
|
case 'google.code_execution':
|
|
121
|
-
if (
|
|
109
|
+
if (supportsGemini2Tools) {
|
|
122
110
|
googleTools.push({ codeExecution: {} });
|
|
123
111
|
} else {
|
|
124
112
|
toolWarnings.push({
|
|
@@ -142,7 +130,7 @@ export function prepareTools({
|
|
|
142
130
|
}
|
|
143
131
|
break;
|
|
144
132
|
case 'google.vertex_rag_store':
|
|
145
|
-
if (
|
|
133
|
+
if (supportsGemini2Tools) {
|
|
146
134
|
googleTools.push({
|
|
147
135
|
retrieval: {
|
|
148
136
|
vertex_rag_store: {
|
|
@@ -163,7 +151,7 @@ export function prepareTools({
|
|
|
163
151
|
}
|
|
164
152
|
break;
|
|
165
153
|
case 'google.google_maps':
|
|
166
|
-
if (
|
|
154
|
+
if (supportsGemini2Tools) {
|
|
167
155
|
googleTools.push({ googleMaps: {} });
|
|
168
156
|
} else {
|
|
169
157
|
toolWarnings.push({
|
|
@@ -183,7 +171,7 @@ export function prepareTools({
|
|
|
183
171
|
}
|
|
184
172
|
});
|
|
185
173
|
|
|
186
|
-
if (hasFunctionTools &&
|
|
174
|
+
if (hasFunctionTools && usesGemini3Features && googleTools.length > 0) {
|
|
187
175
|
const functionDeclarations: Array<{
|
|
188
176
|
name: string;
|
|
189
177
|
description: string;
|