fix: prevent gemini-3-pro-preview from using Google Search grounding

- Added supportsGrounding capability flag to ModelInfo type
- Set supportsGrounding to false for gemini-3-pro-preview
- Set supportsGrounding to true for all other Gemini models
- Updated GeminiHandler to check supportsGrounding before enabling Google Search
- Added tests to verify the fix

Fixes #9520
This commit is contained in:
Roo Code 2025-11-23 18:28:13 +00:00
parent 98b06d84be
commit 4ca407cb68
4 changed files with 50 additions and 2 deletions

View file

@ -109,6 +109,8 @@ export const modelInfoSchema = z.object({
isFree: z.boolean().optional(),
// Flag to indicate if the model supports native tool calling (OpenAI-style function calling)
supportsNativeTools: z.boolean().optional(),
// Flag to indicate if the model supports Google Search grounding
supportsGrounding: z.boolean().optional(),
// Default tool protocol preferred by this model (if not specified, falls back to capability/provider defaults)
defaultToolProtocol: z.enum(["xml", "native"]).optional(),
/**

View file

@ -12,6 +12,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: false, // Does not support Google Search grounding
supportsReasoningEffort: ["low", "high"],
reasoningEffort: "low",
supportsTemperature: true,
@ -38,6 +39,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 2.5, // This is the pricing for prompts above 200k tokens.
outputPrice: 15,
cacheReadsPrice: 0.625,
@ -66,6 +68,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 2.5, // This is the pricing for prompts above 200k tokens.
outputPrice: 15,
cacheReadsPrice: 0.625,
@ -93,6 +96,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 2.5, // This is the pricing for prompts above 200k tokens.
outputPrice: 15,
cacheReadsPrice: 0.625,
@ -118,6 +122,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 2.5, // This is the pricing for prompts above 200k tokens.
outputPrice: 15,
cacheReadsPrice: 0.625,
@ -147,6 +152,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 0.3,
outputPrice: 2.5,
cacheReadsPrice: 0.075,
@ -160,6 +166,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 0.3,
outputPrice: 2.5,
cacheReadsPrice: 0.075,
@ -173,6 +180,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 0.3,
outputPrice: 2.5,
cacheReadsPrice: 0.075,
@ -188,6 +196,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 0.1,
outputPrice: 0.4,
cacheReadsPrice: 0.025,
@ -201,6 +210,7 @@ export const geminiModels = {
supportsImages: true,
supportsNativeTools: true,
supportsPromptCache: true,
supportsGrounding: true,
inputPrice: 0.1,
outputPrice: 0.4,
cacheReadsPrice: 0.025,

View file

@ -19,6 +19,40 @@ describe("GeminiHandler backend support", () => {
expect(config.tools).toEqual([{ urlContext: {} }, { googleSearch: {} }])
})
it("should not enable Google Search for gemini-3-pro-preview even when enableGrounding is true", async () => {
const options = {
apiProvider: "gemini",
apiModelId: "gemini-3-pro-preview",
enableUrlContext: false,
enableGrounding: true,
} as ApiHandlerOptions
const handler = new GeminiHandler(options)
const stub = vi.fn().mockReturnValue((async function* () {})())
// @ts-ignore access private client
handler["client"].models.generateContentStream = stub
await handler.createMessage("instr", [] as any).next()
const config = stub.mock.calls[0][0].config
// Should not include googleSearch since model doesn't support it
expect(config.tools).toBeUndefined()
})
it("should enable Google Search for models that support grounding", async () => {
const options = {
apiProvider: "gemini",
apiModelId: "gemini-2.5-pro",
enableUrlContext: false,
enableGrounding: true,
} as ApiHandlerOptions
const handler = new GeminiHandler(options)
const stub = vi.fn().mockReturnValue((async function* () {})())
// @ts-ignore access private client
handler["client"].models.generateContentStream = stub
await handler.createMessage("instr", [] as any).next()
const config = stub.mock.calls[0][0].config
// Should include googleSearch for models that support it
expect(config.tools).toEqual([{ googleSearch: {} }])
})
it("completePrompt passes config overrides without tools when URL context and grounding disabled", async () => {
const options = {
apiProvider: "gemini",

View file

@ -140,7 +140,8 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
tools.push({ urlContext: {} })
}
if (this.options.enableGrounding) {
// Only enable Google Search if the model supports grounding
if (this.options.enableGrounding && info.supportsGrounding) {
tools.push({ googleSearch: {} })
}
}
@ -368,7 +369,8 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
if (this.options.enableUrlContext) {
tools.push({ urlContext: {} })
}
if (this.options.enableGrounding) {
// Only enable Google Search if the model supports grounding
if (this.options.enableGrounding && info.supportsGrounding) {
tools.push({ googleSearch: {} })
}