[Feature]: Add Gemini (Google Search grounding) as web_search provider (#13075)

* feat: add Gemini (Google Search grounding) as web_search provider

Add Gemini as a fourth web search provider alongside Brave, Perplexity,
and Grok. Uses Gemini's built-in Google Search grounding tool to return
search results with citations.

- Add runGeminiSearch() with Google Search grounding via tools API
- Resolve Gemini's grounding redirect URLs to direct URLs via parallel
  HEAD requests (5s timeout, graceful fallback)
- Add Gemini config block (apiKey, model) with env var fallback
- Default model: gemini-2.5-flash (fast, cheap, grounding-capable)
- Strip API key from error messages for security
- Add config validation tests for Gemini provider
- Update docs/tools/web.md with Gemini provider documentation

Closes #13074

* feat: auto-detect search provider from available API keys

When no explicit provider is configured, resolveSearchProvider now
checks for available API keys in priority order (Brave → Gemini →
Perplexity → Grok) and selects the first provider with a valid key.

- Add auto-detection logic using existing resolve*ApiKey functions
- Export resolveSearchProvider via __testing_provider for tests
- Add 8 tests covering auto-detection, priority order, and explicit override
- Update docs/tools/web.md with auto-detection documentation

* fix: merge __testing exports, downgrade auto-detect log to debug

* fix: use defaultRuntime.log instead of .debug (not in RuntimeEnv type)

* fix: mark gemini apiKey as sensitive in zod schema

* fix: address Greptile review — add externalContent to Gemini payload, add Gemini/Grok entries to schema labels/help, remove dead schema-fields.ts

* fix(web-search): add JSON parse guard for Gemini API responses

Addresses Greptile review comment: add try/catch to handle non-JSON
responses from Gemini API gracefully, preventing runtime errors on
malformed responses.

Note: FIELD_HELP entries for gemini.apiKey and gemini.model were
already present in schema.help.ts, and gemini.apiKey was already
marked as sensitive in zod-schema.agent-runtime.ts (both fixed in
earlier commits).

* fix: use structured readResponseText result in Gemini error path

readResponseText returns { text, truncated, bytesRead }, not a string.
The Gemini error handler was using the result object directly, which
would always be truthy and never fall through to res.statusText.
Align with Perplexity/xAI/Brave error patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style: fix import order and formatting after rebase onto main

* Web search: send Gemini API key via header

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
This commit is contained in:
AkosCz
2026-02-23 08:30:51 -06:00
committed by GitHub
parent 3f03cdea56
commit 3a3c2da916
8 changed files with 466 additions and 11 deletions

View File

@@ -430,8 +430,8 @@ export type ToolsConfig = {
search?: {
/** Enable web search tool (default: true when API key is present). */
enabled?: boolean;
/** Search provider ("brave", "perplexity", or "grok"). */
provider?: "brave" | "perplexity" | "grok";
/** Search provider ("brave", "perplexity", "grok", or "gemini"). */
provider?: "brave" | "perplexity" | "grok" | "gemini";
/** Brave Search API key (optional; defaults to BRAVE_API_KEY env var). */
apiKey?: string;
/** Default search results count (1-10). */
@@ -458,6 +458,13 @@ export type ToolsConfig = {
/** Include inline citations in response text as markdown links (default: false). */
inlineCitations?: boolean;
};
/** Gemini-specific configuration (used when provider="gemini"). */
gemini?: {
/** Gemini API key (defaults to GEMINI_API_KEY env var). */
apiKey?: string;
/** Model to use for grounded search (defaults to "gemini-2.5-flash"). */
model?: string;
};
};
fetch?: {
/** Enable web fetch tool (default: true). */