@ai-sdk/google 3.0.37 → 3.0.39
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.d.mts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +70 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +70 -31
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.d.mts +23 -2
- package/dist/internal/index.d.ts +23 -2
- package/dist/internal/index.js +69 -30
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +69 -30
- package/dist/internal/index.mjs.map +1 -1
- package/docs/15-google-generative-ai.mdx +22 -10
- package/package.json +1 -1
- package/src/google-generative-ai-language-model.ts +45 -0
- package/src/google-prepare-tools.ts +10 -20
- package/src/tool/google-search.ts +31 -28
|
@@ -564,11 +564,36 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
|
|
|
564
564
|
});
|
|
565
565
|
}
|
|
566
566
|
} else if ('inlineData' in part) {
|
|
567
|
+
// End any active text or reasoning block before starting file output.
|
|
568
|
+
// Relevant for multimodal output models.
|
|
569
|
+
if (currentTextBlockId !== null) {
|
|
570
|
+
controller.enqueue({
|
|
571
|
+
type: 'text-end',
|
|
572
|
+
id: currentTextBlockId,
|
|
573
|
+
});
|
|
574
|
+
currentTextBlockId = null;
|
|
575
|
+
}
|
|
576
|
+
if (currentReasoningBlockId !== null) {
|
|
577
|
+
controller.enqueue({
|
|
578
|
+
type: 'reasoning-end',
|
|
579
|
+
id: currentReasoningBlockId,
|
|
580
|
+
});
|
|
581
|
+
currentReasoningBlockId = null;
|
|
582
|
+
}
|
|
583
|
+
|
|
567
584
|
// Process file parts inline to preserve order with text
|
|
585
|
+
const thoughtSignatureMetadata = part.thoughtSignature
|
|
586
|
+
? {
|
|
587
|
+
[providerOptionsName]: {
|
|
588
|
+
thoughtSignature: part.thoughtSignature,
|
|
589
|
+
},
|
|
590
|
+
}
|
|
591
|
+
: undefined;
|
|
568
592
|
controller.enqueue({
|
|
569
593
|
type: 'file',
|
|
570
594
|
mediaType: part.inlineData.mimeType,
|
|
571
595
|
data: part.inlineData.data,
|
|
596
|
+
providerMetadata: thoughtSignatureMetadata,
|
|
572
597
|
});
|
|
573
598
|
}
|
|
574
599
|
}
|
|
@@ -729,6 +754,17 @@ function extractSources({
|
|
|
729
754
|
url: chunk.web.uri,
|
|
730
755
|
title: chunk.web.title ?? undefined,
|
|
731
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
|
+
});
|
|
732
768
|
} else if (chunk.retrievedContext != null) {
|
|
733
769
|
// Handle retrievedContext chunks from RAG operations
|
|
734
770
|
const uri = chunk.retrievedContext.uri;
|
|
@@ -808,6 +844,7 @@ function extractSources({
|
|
|
808
844
|
export const getGroundingMetadataSchema = () =>
|
|
809
845
|
z.object({
|
|
810
846
|
webSearchQueries: z.array(z.string()).nullish(),
|
|
847
|
+
imageSearchQueries: z.array(z.string()).nullish(),
|
|
811
848
|
retrievalQueries: z.array(z.string()).nullish(),
|
|
812
849
|
searchEntryPoint: z.object({ renderedContent: z.string() }).nullish(),
|
|
813
850
|
groundingChunks: z
|
|
@@ -816,6 +853,14 @@ export const getGroundingMetadataSchema = () =>
|
|
|
816
853
|
web: z
|
|
817
854
|
.object({ uri: z.string(), title: z.string().nullish() })
|
|
818
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(),
|
|
819
864
|
retrievedContext: z
|
|
820
865
|
.object({
|
|
821
866
|
uri: z.string().nullish(),
|
|
@@ -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') ||
|
|
54
|
-
|
|
55
|
-
modelId.includes('
|
|
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
|
-
|
|
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
|
-
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
+
);
|