You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@ai-sdk/google

Package Overview
Dependencies
Maintainers
3
Versions
395
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ai-sdk/google - npm Package Compare versions

Comparing version
3.0.38
to
3.0.39
+6
-0
CHANGELOG.md
# @ai-sdk/google
## 3.0.39
### Patch Changes
- 2565e70: feat(google): add support for image search, replace obsolete google_search_retrieval implementation
## 3.0.38

@@ -4,0 +10,0 @@

+16
-2

@@ -85,2 +85,3 @@ import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';

webSearchQueries?: string[] | null | undefined;
imageSearchQueries?: string[] | null | undefined;
retrievalQueries?: string[] | null | undefined;

@@ -95,2 +96,8 @@ searchEntryPoint?: {

} | null | undefined;
image?: {
sourceUri: string;
imageUri: string;
title?: string | null | undefined;
domain?: string | null | undefined;
} | null | undefined;
retrievedContext?: {

@@ -206,4 +213,11 @@ uri?: string | null | undefined;

googleSearch: _ai_sdk_provider_utils.ProviderToolFactory<{}, {
mode?: "MODE_DYNAMIC" | "MODE_UNSPECIFIED";
dynamicThreshold?: number;
[x: string]: unknown;
searchTypes?: {
webSearch?: Record<string, never> | undefined;
imageSearch?: Record<string, never> | undefined;
} | undefined;
timeRangeFilter?: {
startTime: string;
endTime: string;
} | undefined;
}>;

@@ -210,0 +224,0 @@ /**

@@ -85,2 +85,3 @@ import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';

webSearchQueries?: string[] | null | undefined;
imageSearchQueries?: string[] | null | undefined;
retrievalQueries?: string[] | null | undefined;

@@ -95,2 +96,8 @@ searchEntryPoint?: {

} | null | undefined;
image?: {
sourceUri: string;
imageUri: string;
title?: string | null | undefined;
domain?: string | null | undefined;
} | null | undefined;
retrievedContext?: {

@@ -206,4 +213,11 @@ uri?: string | null | undefined;

googleSearch: _ai_sdk_provider_utils.ProviderToolFactory<{}, {
mode?: "MODE_DYNAMIC" | "MODE_UNSPECIFIED";
dynamicThreshold?: number;
[x: string]: unknown;
searchTypes?: {
webSearch?: Record<string, never> | undefined;
imageSearch?: Record<string, never> | undefined;
} | undefined;
timeRangeFilter?: {
startTime: string;
endTime: string;
} | undefined;
}>;

@@ -210,0 +224,0 @@ /**

@@ -33,2 +33,3 @@ import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';

webSearchQueries: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
imageSearchQueries: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
retrievalQueries: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;

@@ -43,2 +44,8 @@ searchEntryPoint: z.ZodOptional<z.ZodNullable<z.ZodObject<{

}, z.core.$strip>>>;
image: z.ZodOptional<z.ZodNullable<z.ZodObject<{
sourceUri: z.ZodString;
imageUri: z.ZodString;
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
domain: z.ZodOptional<z.ZodNullable<z.ZodString>>;
}, z.core.$strip>>>;
retrievedContext: z.ZodOptional<z.ZodNullable<z.ZodObject<{

@@ -119,2 +126,3 @@ uri: z.ZodOptional<z.ZodNullable<z.ZodString>>;

webSearchQueries?: string[] | null | undefined;
imageSearchQueries?: string[] | null | undefined;
retrievalQueries?: string[] | null | undefined;

@@ -129,2 +137,8 @@ searchEntryPoint?: {

} | null | undefined;
image?: {
sourceUri: string;
imageUri: string;
title?: string | null | undefined;
domain?: string | null | undefined;
} | null | undefined;
retrievedContext?: {

@@ -196,4 +210,11 @@ uri?: string | null | undefined;

googleSearch: _ai_sdk_provider_utils.ProviderToolFactory<{}, {
mode?: "MODE_DYNAMIC" | "MODE_UNSPECIFIED";
dynamicThreshold?: number;
[x: string]: unknown;
searchTypes?: {
webSearch?: Record<string, never> | undefined;
imageSearch?: Record<string, never> | undefined;
} | undefined;
timeRangeFilter?: {
startTime: string;
endTime: string;
} | undefined;
}>;

@@ -200,0 +221,0 @@ /**

@@ -33,2 +33,3 @@ import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';

webSearchQueries: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
imageSearchQueries: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
retrievalQueries: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;

@@ -43,2 +44,8 @@ searchEntryPoint: z.ZodOptional<z.ZodNullable<z.ZodObject<{

}, z.core.$strip>>>;
image: z.ZodOptional<z.ZodNullable<z.ZodObject<{
sourceUri: z.ZodString;
imageUri: z.ZodString;
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
domain: z.ZodOptional<z.ZodNullable<z.ZodString>>;
}, z.core.$strip>>>;
retrievedContext: z.ZodOptional<z.ZodNullable<z.ZodObject<{

@@ -119,2 +126,3 @@ uri: z.ZodOptional<z.ZodNullable<z.ZodString>>;

webSearchQueries?: string[] | null | undefined;
imageSearchQueries?: string[] | null | undefined;
retrievalQueries?: string[] | null | undefined;

@@ -129,2 +137,8 @@ searchEntryPoint?: {

} | null | undefined;
image?: {
sourceUri: string;
imageUri: string;
title?: string | null | undefined;
domain?: string | null | undefined;
} | null | undefined;
retrievedContext?: {

@@ -196,4 +210,11 @@ uri?: string | null | undefined;

googleSearch: _ai_sdk_provider_utils.ProviderToolFactory<{}, {
mode?: "MODE_DYNAMIC" | "MODE_UNSPECIFIED";
dynamicThreshold?: number;
[x: string]: unknown;
searchTypes?: {
webSearch?: Record<string, never> | undefined;
imageSearch?: Record<string, never> | undefined;
} | undefined;
timeRangeFilter?: {
startTime: string;
endTime: string;
} | undefined;
}>;

@@ -200,0 +221,0 @@ /**

+48
-29

@@ -522,4 +522,3 @@ "use strict";

].some((id) => id === modelId);
const isGemini2orNewer = modelId.includes("gemini-2") || modelId.includes("gemini-3") || isLatest;
const supportsDynamicRetrieval = modelId.includes("gemini-1.5-flash") && !modelId.includes("-8b");
const isGemini2orNewer = modelId.includes("gemini-2") || modelId.includes("gemini-3") || modelId.includes("nano-banana") || isLatest;
const supportsFileSearch = modelId.includes("gemini-2.5") || modelId.includes("gemini-3");

@@ -544,14 +543,9 @@ if (tools == null) {

if (isGemini2orNewer) {
googleTools2.push({ googleSearch: {} });
} else if (supportsDynamicRetrieval) {
googleTools2.push({
googleSearchRetrieval: {
dynamicRetrievalConfig: {
mode: tool.args.mode,
dynamicThreshold: tool.args.dynamicThreshold
}
}
googleTools2.push({ googleSearch: { ...tool.args } });
} else {
toolWarnings.push({
type: "unsupported",
feature: `provider-defined tool ${tool.id}`,
details: "Google Search requires Gemini 2.0 or newer."
});
} else {
googleTools2.push({ googleSearchRetrieval: {} });
}

@@ -1273,3 +1267,3 @@ break;

}) {
var _a, _b, _c, _d, _e;
var _a, _b, _c, _d, _e, _f;
if (!(groundingMetadata == null ? void 0 : groundingMetadata.groundingChunks)) {

@@ -1288,2 +1282,12 @@ return void 0;

});
} else if (chunk.image != null) {
sources.push({
type: "source",
sourceType: "url",
id: generateId2(),
// Google requires attribution to the source URI, not the actual image URI.
// TODO: add another type in v7 to allow both the image and source URL to be included separately
url: chunk.image.sourceUri,
title: (_b = chunk.image.title) != null ? _b : void 0
});
} else if (chunk.retrievedContext != null) {

@@ -1298,6 +1302,6 @@ const uri = chunk.retrievedContext.uri;

url: uri,
title: (_b = chunk.retrievedContext.title) != null ? _b : void 0
title: (_c = chunk.retrievedContext.title) != null ? _c : void 0
});
} else if (uri) {
const title = (_c = chunk.retrievedContext.title) != null ? _c : "Unknown Document";
const title = (_d = chunk.retrievedContext.title) != null ? _d : "Unknown Document";
let mediaType = "application/octet-stream";

@@ -1332,3 +1336,3 @@ let filename = void 0;

} else if (fileSearchStore) {
const title = (_d = chunk.retrievedContext.title) != null ? _d : "Unknown Document";
const title = (_e = chunk.retrievedContext.title) != null ? _e : "Unknown Document";
sources.push({

@@ -1350,3 +1354,3 @@ type: "source",

url: chunk.maps.uri,
title: (_e = chunk.maps.title) != null ? _e : void 0
title: (_f = chunk.maps.title) != null ? _f : void 0
});

@@ -1360,2 +1364,3 @@ }

webSearchQueries: import_v43.z.array(import_v43.z.string()).nullish(),
imageSearchQueries: import_v43.z.array(import_v43.z.string()).nullish(),
retrievalQueries: import_v43.z.array(import_v43.z.string()).nullish(),

@@ -1366,2 +1371,8 @@ searchEntryPoint: import_v43.z.object({ renderedContent: import_v43.z.string() }).nullish(),

web: import_v43.z.object({ uri: import_v43.z.string(), title: import_v43.z.string().nullish() }).nullish(),
image: import_v43.z.object({
sourceUri: import_v43.z.string(),
imageUri: import_v43.z.string(),
title: import_v43.z.string().nullish(),
domain: import_v43.z.string().nullish()
}).nullish(),
retrievedContext: import_v43.z.object({

@@ -1563,13 +1574,21 @@ uri: import_v43.z.string().nullish(),

var import_v48 = require("zod/v4");
var googleSearch = (0, import_provider_utils9.createProviderToolFactory)({
id: "google.google_search",
inputSchema: (0, import_provider_utils9.lazySchema)(
() => (0, import_provider_utils9.zodSchema)(
import_v48.z.object({
mode: import_v48.z.enum(["MODE_DYNAMIC", "MODE_UNSPECIFIED"]).default("MODE_UNSPECIFIED"),
dynamicThreshold: import_v48.z.number().default(1)
})
)
)
});
var googleSearchToolArgsBaseSchema = import_v48.z.object({
searchTypes: import_v48.z.object({
webSearch: import_v48.z.object({}).optional(),
imageSearch: import_v48.z.object({}).optional()
}).optional(),
timeRangeFilter: import_v48.z.object({
startTime: import_v48.z.string(),
endTime: import_v48.z.string()
}).optional()
}).passthrough();
var googleSearchToolArgsSchema = (0, import_provider_utils9.lazySchema)(
() => (0, import_provider_utils9.zodSchema)(googleSearchToolArgsBaseSchema)
);
var googleSearch = (0, import_provider_utils9.createProviderToolFactory)(
{
id: "google.google_search",
inputSchema: googleSearchToolArgsSchema
}
);

@@ -1576,0 +1595,0 @@ // src/tool/url-context.ts

@@ -511,4 +511,3 @@ // src/google-generative-ai-language-model.ts

].some((id) => id === modelId);
const isGemini2orNewer = modelId.includes("gemini-2") || modelId.includes("gemini-3") || isLatest;
const supportsDynamicRetrieval = modelId.includes("gemini-1.5-flash") && !modelId.includes("-8b");
const isGemini2orNewer = modelId.includes("gemini-2") || modelId.includes("gemini-3") || modelId.includes("nano-banana") || isLatest;
const supportsFileSearch = modelId.includes("gemini-2.5") || modelId.includes("gemini-3");

@@ -533,14 +532,9 @@ if (tools == null) {

if (isGemini2orNewer) {
googleTools2.push({ googleSearch: {} });
} else if (supportsDynamicRetrieval) {
googleTools2.push({
googleSearchRetrieval: {
dynamicRetrievalConfig: {
mode: tool.args.mode,
dynamicThreshold: tool.args.dynamicThreshold
}
}
googleTools2.push({ googleSearch: { ...tool.args } });
} else {
toolWarnings.push({
type: "unsupported",
feature: `provider-defined tool ${tool.id}`,
details: "Google Search requires Gemini 2.0 or newer."
});
} else {
googleTools2.push({ googleSearchRetrieval: {} });
}

@@ -1262,3 +1256,3 @@ break;

}) {
var _a, _b, _c, _d, _e;
var _a, _b, _c, _d, _e, _f;
if (!(groundingMetadata == null ? void 0 : groundingMetadata.groundingChunks)) {

@@ -1277,2 +1271,12 @@ return void 0;

});
} else if (chunk.image != null) {
sources.push({
type: "source",
sourceType: "url",
id: generateId2(),
// Google requires attribution to the source URI, not the actual image URI.
// TODO: add another type in v7 to allow both the image and source URL to be included separately
url: chunk.image.sourceUri,
title: (_b = chunk.image.title) != null ? _b : void 0
});
} else if (chunk.retrievedContext != null) {

@@ -1287,6 +1291,6 @@ const uri = chunk.retrievedContext.uri;

url: uri,
title: (_b = chunk.retrievedContext.title) != null ? _b : void 0
title: (_c = chunk.retrievedContext.title) != null ? _c : void 0
});
} else if (uri) {
const title = (_c = chunk.retrievedContext.title) != null ? _c : "Unknown Document";
const title = (_d = chunk.retrievedContext.title) != null ? _d : "Unknown Document";
let mediaType = "application/octet-stream";

@@ -1321,3 +1325,3 @@ let filename = void 0;

} else if (fileSearchStore) {
const title = (_d = chunk.retrievedContext.title) != null ? _d : "Unknown Document";
const title = (_e = chunk.retrievedContext.title) != null ? _e : "Unknown Document";
sources.push({

@@ -1339,3 +1343,3 @@ type: "source",

url: chunk.maps.uri,
title: (_e = chunk.maps.title) != null ? _e : void 0
title: (_f = chunk.maps.title) != null ? _f : void 0
});

@@ -1349,2 +1353,3 @@ }

webSearchQueries: z3.array(z3.string()).nullish(),
imageSearchQueries: z3.array(z3.string()).nullish(),
retrievalQueries: z3.array(z3.string()).nullish(),

@@ -1355,2 +1360,8 @@ searchEntryPoint: z3.object({ renderedContent: z3.string() }).nullish(),

web: z3.object({ uri: z3.string(), title: z3.string().nullish() }).nullish(),
image: z3.object({
sourceUri: z3.string(),
imageUri: z3.string(),
title: z3.string().nullish(),
domain: z3.string().nullish()
}).nullish(),
retrievedContext: z3.object({

@@ -1568,13 +1579,21 @@ uri: z3.string().nullish(),

import { z as z8 } from "zod/v4";
var googleSearch = createProviderToolFactory4({
id: "google.google_search",
inputSchema: lazySchema7(
() => zodSchema7(
z8.object({
mode: z8.enum(["MODE_DYNAMIC", "MODE_UNSPECIFIED"]).default("MODE_UNSPECIFIED"),
dynamicThreshold: z8.number().default(1)
})
)
)
});
var googleSearchToolArgsBaseSchema = z8.object({
searchTypes: z8.object({
webSearch: z8.object({}).optional(),
imageSearch: z8.object({}).optional()
}).optional(),
timeRangeFilter: z8.object({
startTime: z8.string(),
endTime: z8.string()
}).optional()
}).passthrough();
var googleSearchToolArgsSchema = lazySchema7(
() => zodSchema7(googleSearchToolArgsBaseSchema)
);
var googleSearch = createProviderToolFactory4(
{
id: "google.google_search",
inputSchema: googleSearchToolArgsSchema
}
);

@@ -1581,0 +1600,0 @@ // src/tool/url-context.ts

{
"name": "@ai-sdk/google",
"version": "3.0.38",
"version": "3.0.39",
"license": "Apache-2.0",

@@ -5,0 +5,0 @@ "sideEffects": false,

@@ -757,2 +757,13 @@ import {

});
} else if (chunk.image != null) {
// Handle image chunks as image sources
sources.push({
type: 'source',
sourceType: 'url',
id: generateId(),
// Google requires attribution to the source URI, not the actual image URI.
// TODO: add another type in v7 to allow both the image and source URL to be included separately
url: chunk.image.sourceUri,
title: chunk.image.title ?? undefined,
});
} else if (chunk.retrievedContext != null) {

@@ -837,2 +848,3 @@ // Handle retrievedContext chunks from RAG operations

webSearchQueries: z.array(z.string()).nullish(),
imageSearchQueries: z.array(z.string()).nullish(),
retrievalQueries: z.array(z.string()).nullish(),

@@ -846,2 +858,10 @@ searchEntryPoint: z.object({ renderedContent: z.string() }).nullish(),

.nullish(),
image: z
.object({
sourceUri: z.string(),
imageUri: z.string(),
title: z.string().nullish(),
domain: z.string().nullish(),
})
.nullish(),
retrievedContext: z

@@ -848,0 +868,0 @@ .object({

@@ -53,5 +53,6 @@ import {

const isGemini2orNewer =
modelId.includes('gemini-2') || modelId.includes('gemini-3') || isLatest;
const supportsDynamicRetrieval =
modelId.includes('gemini-1.5-flash') && !modelId.includes('-8b');
modelId.includes('gemini-2') ||
modelId.includes('gemini-3') ||
modelId.includes('nano-banana') ||
isLatest;
const supportsFileSearch =

@@ -83,20 +84,9 @@ modelId.includes('gemini-2.5') || modelId.includes('gemini-3');

if (isGemini2orNewer) {
googleTools.push({ googleSearch: {} });
} else if (supportsDynamicRetrieval) {
// For non-Gemini-2 models that don't support dynamic retrieval, use basic googleSearchRetrieval
googleTools.push({
googleSearchRetrieval: {
dynamicRetrievalConfig: {
mode: tool.args.mode as
| 'MODE_DYNAMIC'
| 'MODE_UNSPECIFIED'
| undefined,
dynamicThreshold: tool.args.dynamicThreshold as
| number
| undefined,
},
},
googleTools.push({ googleSearch: { ...tool.args } });
} else {
toolWarnings.push({
type: 'unsupported',
feature: `provider-defined tool ${tool.id}`,
details: 'Google Search requires Gemini 2.0 or newer.',
});
} else {
googleTools.push({ googleSearchRetrieval: {} });
}

@@ -103,0 +93,0 @@ break;

@@ -12,30 +12,33 @@ import {

export const googleSearch = createProviderToolFactory<
{},
const googleSearchToolArgsBaseSchema = z
.object({
searchTypes: z
.object({
webSearch: z.object({}).optional(),
imageSearch: z.object({}).optional(),
})
.optional(),
timeRangeFilter: z
.object({
startTime: z.string(),
endTime: z.string(),
})
.optional(),
})
.passthrough();
export type GoogleSearchToolArgs = z.infer<
typeof googleSearchToolArgsBaseSchema
>;
const googleSearchToolArgsSchema = lazySchema(() =>
zodSchema(googleSearchToolArgsBaseSchema),
);
export const googleSearch = createProviderToolFactory<{}, GoogleSearchToolArgs>(
{
/**
* The mode of the predictor to be used in dynamic retrieval. The following modes are supported:
* - MODE_DYNAMIC: Run retrieval only when system decides it is necessary
* - MODE_UNSPECIFIED: Always trigger retrieval
* @default MODE_UNSPECIFIED
*/
mode?: 'MODE_DYNAMIC' | 'MODE_UNSPECIFIED';
/**
* The threshold to be used in dynamic retrieval (if not set, a system default value is used).
*/
dynamicThreshold?: number;
}
>({
id: 'google.google_search',
inputSchema: lazySchema(() =>
zodSchema(
z.object({
mode: z
.enum(['MODE_DYNAMIC', 'MODE_UNSPECIFIED'])
.default('MODE_UNSPECIFIED'),
dynamicThreshold: z.number().default(1),
}),
),
),
});
id: 'google.google_search',
inputSchema: googleSearchToolArgsSchema,
},
);

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet