@ai-sdk/google 3.0.38 → 3.0.40

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.
@@ -754,6 +754,17 @@ function extractSources({
754
754
  url: chunk.web.uri,
755
755
  title: chunk.web.title ?? undefined,
756
756
  });
757
+ } else if (chunk.image != null) {
758
+ // Handle image chunks as image sources
759
+ sources.push({
760
+ type: 'source',
761
+ sourceType: 'url',
762
+ id: generateId(),
763
+ // Google requires attribution to the source URI, not the actual image URI.
764
+ // TODO: add another type in v7 to allow both the image and source URL to be included separately
765
+ url: chunk.image.sourceUri,
766
+ title: chunk.image.title ?? undefined,
767
+ });
757
768
  } else if (chunk.retrievedContext != null) {
758
769
  // Handle retrievedContext chunks from RAG operations
759
770
  const uri = chunk.retrievedContext.uri;
@@ -833,6 +844,7 @@ function extractSources({
833
844
  export const getGroundingMetadataSchema = () =>
834
845
  z.object({
835
846
  webSearchQueries: z.array(z.string()).nullish(),
847
+ imageSearchQueries: z.array(z.string()).nullish(),
836
848
  retrievalQueries: z.array(z.string()).nullish(),
837
849
  searchEntryPoint: z.object({ renderedContent: z.string() }).nullish(),
838
850
  groundingChunks: z
@@ -841,6 +853,14 @@ export const getGroundingMetadataSchema = () =>
841
853
  web: z
842
854
  .object({ uri: z.string(), title: z.string().nullish() })
843
855
  .nullish(),
856
+ image: z
857
+ .object({
858
+ sourceUri: z.string(),
859
+ imageUri: z.string(),
860
+ title: z.string().nullish(),
861
+ domain: z.string().nullish(),
862
+ })
863
+ .nullish(),
844
864
  retrievedContext: z
845
865
  .object({
846
866
  uri: z.string().nullish(),
@@ -954,12 +974,14 @@ const usageSchema = z.object({
954
974
  // https://ai.google.dev/api/generate-content#UrlRetrievalMetadata
955
975
  export const getUrlContextMetadataSchema = () =>
956
976
  z.object({
957
- urlMetadata: z.array(
958
- z.object({
959
- retrievedUrl: z.string(),
960
- urlRetrievalStatus: z.string(),
961
- }),
962
- ),
977
+ urlMetadata: z
978
+ .array(
979
+ z.object({
980
+ retrievedUrl: z.string(),
981
+ urlRetrievalStatus: z.string(),
982
+ }),
983
+ )
984
+ .nullish(),
963
985
  });
964
986
 
965
987
  const responseSchema = lazySchema(() =>
@@ -50,9 +50,10 @@ export function prepareTools({
50
50
  ] as const satisfies GoogleGenerativeAIModelId[]
51
51
  ).some(id => id === modelId);
52
52
  const isGemini2orNewer =
53
- modelId.includes('gemini-2') || modelId.includes('gemini-3') || isLatest;
54
- const supportsDynamicRetrieval =
55
- modelId.includes('gemini-1.5-flash') && !modelId.includes('-8b');
53
+ modelId.includes('gemini-2') ||
54
+ modelId.includes('gemini-3') ||
55
+ modelId.includes('nano-banana') ||
56
+ isLatest;
56
57
  const supportsFileSearch =
57
58
  modelId.includes('gemini-2.5') || modelId.includes('gemini-3');
58
59
 
@@ -79,24 +80,13 @@ export function prepareTools({
79
80
  switch (tool.id) {
80
81
  case 'google.google_search':
81
82
  if (isGemini2orNewer) {
82
- googleTools.push({ googleSearch: {} });
83
- } else if (supportsDynamicRetrieval) {
84
- // For non-Gemini-2 models that don't support dynamic retrieval, use basic googleSearchRetrieval
85
- googleTools.push({
86
- googleSearchRetrieval: {
87
- dynamicRetrievalConfig: {
88
- mode: tool.args.mode as
89
- | 'MODE_DYNAMIC'
90
- | 'MODE_UNSPECIFIED'
91
- | undefined,
92
- dynamicThreshold: tool.args.dynamicThreshold as
93
- | number
94
- | undefined,
95
- },
96
- },
97
- });
83
+ googleTools.push({ googleSearch: { ...tool.args } });
98
84
  } else {
99
- googleTools.push({ googleSearchRetrieval: {} });
85
+ toolWarnings.push({
86
+ type: 'unsupported',
87
+ feature: `provider-defined tool ${tool.id}`,
88
+ details: 'Google Search requires Gemini 2.0 or newer.',
89
+ });
100
90
  }
101
91
  break;
102
92
  case 'google.enterprise_web_search':
@@ -9,32 +9,35 @@ import { z } from 'zod/v4';
9
9
  // https://ai.google.dev/api/generate-content#GroundingSupport
10
10
  // https://cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-google-search
11
11
 
12
- export const googleSearch = createProviderToolFactory<
13
- {},
14
- {
15
- /**
16
- * The mode of the predictor to be used in dynamic retrieval. The following modes are supported:
17
- * - MODE_DYNAMIC: Run retrieval only when system decides it is necessary
18
- * - MODE_UNSPECIFIED: Always trigger retrieval
19
- * @default MODE_UNSPECIFIED
20
- */
21
- mode?: 'MODE_DYNAMIC' | 'MODE_UNSPECIFIED';
12
+ const googleSearchToolArgsBaseSchema = z
13
+ .object({
14
+ searchTypes: z
15
+ .object({
16
+ webSearch: z.object({}).optional(),
17
+ imageSearch: z.object({}).optional(),
18
+ })
19
+ .optional(),
20
+
21
+ timeRangeFilter: z
22
+ .object({
23
+ startTime: z.string(),
24
+ endTime: z.string(),
25
+ })
26
+ .optional(),
27
+ })
28
+ .passthrough();
29
+
30
+ export type GoogleSearchToolArgs = z.infer<
31
+ typeof googleSearchToolArgsBaseSchema
32
+ >;
22
33
 
23
- /**
24
- * The threshold to be used in dynamic retrieval (if not set, a system default value is used).
25
- */
26
- dynamicThreshold?: number;
27
- }
28
- >({
29
- id: 'google.google_search',
30
- inputSchema: lazySchema(() =>
31
- zodSchema(
32
- z.object({
33
- mode: z
34
- .enum(['MODE_DYNAMIC', 'MODE_UNSPECIFIED'])
35
- .default('MODE_UNSPECIFIED'),
36
- dynamicThreshold: z.number().default(1),
37
- }),
38
- ),
39
- ),
40
- });
34
+ const googleSearchToolArgsSchema = lazySchema(() =>
35
+ zodSchema(googleSearchToolArgsBaseSchema),
36
+ );
37
+
38
+ export const googleSearch = createProviderToolFactory<{}, GoogleSearchToolArgs>(
39
+ {
40
+ id: 'google.google_search',
41
+ inputSchema: googleSearchToolArgsSchema,
42
+ },
43
+ );