@ai-sdk/google 3.0.99 → 3.0.101

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.
@@ -105,6 +105,16 @@ Google Generative AI language models can also be used in the `streamText` functi
105
105
  and support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output)
106
106
  (see [AI SDK Core](/docs/ai-sdk-core)).
107
107
 
108
+ <Note>
109
+ To remain forward-compatible, the provider treats unrecognized `gemini-*`
110
+ model IDs and `-latest` aliases like the newest supported Gemini generation.
111
+ Currently, this means Gemini 3 request behavior for provider-defined and mixed
112
+ tools, `thinkingLevel` reasoning, multimodal function responses, and thought
113
+ signatures. Known legacy Gemini model IDs keep their generation-specific
114
+ request behavior. This SDK default controls request serialization; the
115
+ selected model must still support each feature in the Google API.
116
+ </Note>
117
+
108
118
  Google Generative AI also supports some model specific settings that are not part of the [standard call settings](/docs/ai-sdk-core/settings).
109
119
  You can pass them as an options argument:
110
120
 
@@ -181,7 +191,7 @@ The following optional provider options are available for Google Generative AI m
181
191
 
182
192
  - **thinkingLevel** _'minimal' | 'low' | 'medium' | 'high'_
183
193
 
184
- 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'. Only supported by Gemini 3 models.
194
+ 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'.
185
195
 
186
196
  - **thinkingBudget** _number_
187
197
 
@@ -189,7 +199,7 @@ The following optional provider options are available for Google Generative AI m
189
199
  For more information about the possible value ranges for each model see [Google Generative AI thinking documentation](https://ai.google.dev/gemini-api/docs/thinking#set-budget).
190
200
 
191
201
  <Note>
192
- This option is for Gemini 2.5 models. Gemini 3 models should use
202
+ This option is for Gemini 2.5 models. Gemini 3 and later models should use
193
203
  `thinkingLevel` instead.
194
204
  </Note>
195
205
 
@@ -264,11 +274,11 @@ The following optional provider options are available for Google Generative AI m
264
274
 
265
275
  ### Thinking
266
276
 
267
- 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 Generative AI thinking documentation](https://ai.google.dev/gemini-api/docs/thinking).
277
+ 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 Generative AI thinking documentation](https://ai.google.dev/gemini-api/docs/thinking).
268
278
 
269
- #### Gemini 3 Models
279
+ #### Gemini 3 and Later Models
270
280
 
271
- For Gemini 3 models, use the `thinkingLevel` parameter to control the depth of reasoning:
281
+ For Gemini 3 and later models, use the `thinkingLevel` parameter to control the depth of reasoning:
272
282
 
273
283
  ```ts
274
284
  import { google, GoogleLanguageModelOptions } from '@ai-sdk/google';
@@ -656,7 +666,7 @@ Enterprise Web Search provides the following benefits:
656
666
 
657
667
  ### File Search
658
668
 
659
- 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. Only Gemini 2.5 and Gemini 3 models support this feature.
669
+ 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.
660
670
 
661
671
  ```ts highlight="9-13"
662
672
  import { google } from '@ai-sdk/google';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/google",
3
- "version": "3.0.99",
3
+ "version": "3.0.101",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -101,6 +101,7 @@ function appendToolResultParts(
101
101
  [key: string]: unknown;
102
102
  }>,
103
103
  toolCallId?: string,
104
+ includeFunctionCallIds = true,
104
105
  ): void {
105
106
  const functionResponseParts: GoogleGenerativeAIFunctionResponsePart[] = [];
106
107
  const responseTextParts: string[] = [];
@@ -143,7 +144,9 @@ function appendToolResultParts(
143
144
 
144
145
  parts.push({
145
146
  functionResponse: {
146
- ...(toolCallId != null ? { id: toolCallId } : {}),
147
+ ...(includeFunctionCallIds && toolCallId != null
148
+ ? { id: toolCallId }
149
+ : {}),
147
150
  name: toolName,
148
151
  response: {
149
152
  name: toolName,
@@ -172,13 +175,16 @@ function appendLegacyToolResultParts(
172
175
  [key: string]: unknown;
173
176
  }>,
174
177
  toolCallId?: string,
178
+ includeFunctionCallIds = true,
175
179
  ): void {
176
180
  for (const contentPart of outputValue) {
177
181
  switch (contentPart.type) {
178
182
  case 'text':
179
183
  parts.push({
180
184
  functionResponse: {
181
- ...(toolCallId != null ? { id: toolCallId } : {}),
185
+ ...(includeFunctionCallIds && toolCallId != null
186
+ ? { id: toolCallId }
187
+ : {}),
182
188
  name: toolName,
183
189
  response: {
184
190
  name: toolName,
@@ -234,6 +240,7 @@ export function convertToGoogleGenerativeAIMessages(
234
240
  * injected.
235
241
  */
236
242
  onWarning?: (warning: SharedV3Warning) => void;
243
+ includeFunctionCallIds?: boolean;
237
244
  },
238
245
  ): GoogleGenerativeAIPrompt {
239
246
  const systemInstructionParts: Array<{ text: string }> = [];
@@ -245,6 +252,7 @@ export function convertToGoogleGenerativeAIMessages(
245
252
  const supportsFunctionResponseParts =
246
253
  options?.supportsFunctionResponseParts ?? true;
247
254
  const onWarning = options?.onWarning;
255
+ const includeFunctionCallIds = options?.includeFunctionCallIds ?? true;
248
256
 
249
257
  let sentinelInjected = false;
250
258
  const missingSignatureToolNames: string[] = [];
@@ -413,7 +421,7 @@ export function convertToGoogleGenerativeAIMessages(
413
421
 
414
422
  return {
415
423
  functionCall: {
416
- ...(part.toolCallId != null
424
+ ...(includeFunctionCallIds && part.toolCallId != null
417
425
  ? { id: part.toolCallId }
418
426
  : {}),
419
427
  name: part.toolName,
@@ -510,6 +518,7 @@ export function convertToGoogleGenerativeAIMessages(
510
518
  part.toolName,
511
519
  output.value,
512
520
  part.toolCallId,
521
+ includeFunctionCallIds,
513
522
  );
514
523
  } else {
515
524
  appendLegacyToolResultParts(
@@ -517,12 +526,15 @@ export function convertToGoogleGenerativeAIMessages(
517
526
  part.toolName,
518
527
  output.value,
519
528
  part.toolCallId,
529
+ includeFunctionCallIds,
520
530
  );
521
531
  }
522
532
  } else {
523
533
  parts.push({
524
534
  functionResponse: {
525
- ...(part.toolCallId != null ? { id: part.toolCallId } : {}),
535
+ ...(includeFunctionCallIds && part.toolCallId != null
536
+ ? { id: part.toolCallId }
537
+ : {}),
526
538
  name: part.toolName,
527
539
  response: {
528
540
  name: part.toolName,
@@ -39,6 +39,7 @@ import {
39
39
  googleLanguageModelOptions,
40
40
  type GoogleGenerativeAIModelId,
41
41
  } from './google-generative-ai-options';
42
+ import { getGoogleModelCapabilities } from './google-model-capabilities';
42
43
  import type {
43
44
  GoogleGenerativeAIContentPart,
44
45
  GoogleGenerativeAIProviderMetadata,
@@ -229,17 +230,17 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
229
230
  }
230
231
 
231
232
  const isGemmaModel = this.modelId.toLowerCase().startsWith('gemma-');
232
- const isGemini3Model = /^gemini-3[.-]/.test(this.modelId);
233
- const supportsFunctionResponseParts = isGemini3Model;
233
+ const { usesGemini3Features } = getGoogleModelCapabilities(this.modelId);
234
234
 
235
235
  const { contents, systemInstruction } = convertToGoogleGenerativeAIMessages(
236
236
  prompt,
237
237
  {
238
238
  isGemmaModel,
239
- isGemini3Model,
239
+ isGemini3Model: usesGemini3Features,
240
240
  providerOptionsName,
241
- supportsFunctionResponseParts,
241
+ supportsFunctionResponseParts: usesGemini3Features,
242
242
  onWarning: warning => warnings.push(warning),
243
+ includeFunctionCallIds: !isVertexProvider,
243
244
  },
244
245
  );
245
246
 
@@ -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 { GoogleGenerativeAIModelId } from './google-generative-ai-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: SharedV3Warning[] = [];
48
49
 
49
- const isLatest = (
50
- [
51
- 'gemini-flash-latest',
52
- 'gemini-flash-lite-latest',
53
- 'gemini-pro-latest',
54
- ] as const satisfies GoogleGenerativeAIModelId[]
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 && !isGemini3orNewer) {
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 (isGemini2orNewer) {
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 (isGemini2orNewer) {
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 (isGemini2orNewer) {
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 (isGemini2orNewer) {
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 (isGemini2orNewer) {
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 (isGemini2orNewer) {
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 && isGemini3orNewer && googleTools.length > 0) {
174
+ if (hasFunctionTools && usesGemini3Features && googleTools.length > 0) {
187
175
  const functionDeclarations: Array<{
188
176
  name: string;
189
177
  description: string;