Skip to content

Conversation

@cjangrist
Copy link

@cjangrist cjangrist commented Feb 10, 2026

Summary

  • Pass through Google Search grounding_metadata from Gemini responses to all output formats
  • Preserve web_search_20250305 built-in tools through request translation (OpenAI, Responses, Gemini → Claude)
  • Surface web_search_tool_result and citations_delta in streaming + non-streaming output for OpenAI Chat Completions, OpenAI Responses, and Gemini formats
  • Reset accumulator state on message_start to prevent cross-message leaks
  • 11 unit tests covering all Claude web_search code paths

Test plan

  • 11 unit tests pass (go test ./test/ -v)
  • Full suite go test ./... — zero regressions
  • 25/25 live e2e tests across 5 Claude models (haiku, sonnet-4.5, sonnet-4, 3.5-haiku, opus-4.6)

Generated with Claude Code

Add google_search, code_execution, and url_context tool passthrough in
request translators and grounding_metadata response passthrough across
all provider/format combinations. Streaming paths compact raw JSON to
prevent SSE newline framing issues.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @cjangrist, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the proxy's capability to integrate with Gemini's advanced features by enabling the seamless use of Google Search grounding, code execution, and URL context tools. It ensures that requests containing these tools are correctly translated and forwarded to Gemini, and critically, that the rich grounding metadata returned by Gemini is accurately propagated back to the client across various API formats and streaming/non-streaming scenarios. This broadens the functionality available to users and improves the fidelity of responses by providing crucial context from the model's grounding process.

Highlights

  • Google Search Grounding Tools Passthrough: Implemented passthrough for google_search, code_execution, and url_context tools from Claude and OpenAI Responses API requests to Gemini, allowing Gemini to receive them as native tools.
  • Grounding Metadata Passthrough: Enabled the passthrough of groundingMetadata from Gemini responses as grounding_metadata across all 7 streaming and 6 non-streaming response translators (OpenAI chat-completions, OpenAI Responses, Claude formats for gemini, gemini-cli, and antigravity providers).
  • Streaming JSON Compaction: Compacted raw grounding JSON in all streaming paths to prevent Server-Sent Events (SSE) newline framing issues, ensuring proper data transmission.
  • Documentation Updates: Updated both English and Chinese README files to reflect the new support for Google Search grounding, including usage examples and response metadata structure.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • README.md
    • Added 'Google Search grounding, code execution, and URL context tool passthrough' to the features list.
    • Introduced a new section 'Google Search Grounding' detailing how to enable Google Search and the structure of grounding_metadata in OpenAI Chat Completions, Claude Messages, and OpenAI Responses.
  • README_CN.md
    • Added 'Google 搜索 grounding、代码执行、URL 上下文工具透传' to the features list (Chinese translation).
    • Introduced a new section 'Google 搜索 Grounding' detailing how to enable Google Search and the structure of grounding_metadata in OpenAI Chat Completions, Claude Messages, and OpenAI Responses (Chinese translation).
  • internal/translator/antigravity/claude/antigravity_claude_request.go
    • Modified tool parsing logic to pass through google_search, code_execution, and url_context tools to Antigravity.
    • Adjusted the construction of the toolsJSON array to include these new tool types alongside function declarations.
    • Updated the hasTools check to correctly account for the presence of the newly supported tool types.
  • internal/translator/antigravity/claude/antigravity_claude_response.go
    • Added GroundingMetadataRaw field to the Params struct for caching raw grounding metadata.
    • Extracted and cached groundingMetadata from Antigravity responses, compacting it for streaming to prevent SSE newline issues.
    • Attached the cached grounding_metadata to the message_delta event for streaming responses.
    • Attached grounding_metadata to the top-level response object for non-streaming responses.
  • internal/translator/antigravity/openai/chat-completions/antigravity_openai_response.go
    • Extracted and attached groundingMetadata from Antigravity responses to choices.0.grounding_metadata, compacting it for streaming.
  • internal/translator/gemini-cli/claude/gemini-cli_claude_request.go
    • Modified tool parsing logic to pass through google_search, code_execution, and url_context tools to Gemini CLI.
    • Adjusted the construction of the tools array to include these new tool types alongside function declarations.
  • internal/translator/gemini-cli/claude/gemini-cli_claude_response.go
    • Attached groundingMetadata from Gemini CLI responses to the grounding_metadata field in streaming responses, compacting it.
    • Attached grounding_metadata to the top-level response object for non-streaming responses.
  • internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_response.go
    • Extracted and attached groundingMetadata from Gemini CLI responses to choices.0.grounding_metadata, compacting it for streaming.
  • internal/translator/gemini/claude/gemini_claude_request.go
    • Modified tool parsing logic to pass through google_search, code_execution, and url_context tools to Gemini.
    • Adjusted the construction of the tools array to include these new tool types alongside function declarations.
  • internal/translator/gemini/claude/gemini_claude_response.go
    • Attached groundingMetadata from Gemini responses to the grounding_metadata field in streaming responses, compacting it.
    • Attached grounding_metadata to the top-level response object for non-streaming responses.
  • internal/translator/gemini/openai/chat-completions/gemini_openai_response.go
    • Extracted and attached groundingMetadata from Gemini responses to choices.0.grounding_metadata, compacting it for streaming.
    • Extracted and attached groundingMetadata from Gemini responses to grounding_metadata for non-streaming responses.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_request.go
    • Modified tool parsing logic to pass through google_search, code_execution, and url_context tools to Gemini.
    • Adjusted the construction of the tools array to include these new tool types alongside function declarations.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_response.go
    • Extracted and attached groundingMetadata from Gemini responses to response.grounding_metadata in streaming responses, compacting it.
    • Extracted and attached groundingMetadata from Gemini responses to grounding_metadata for non-streaming responses.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for Google Search grounding by passing through google_search, code_execution, and url_context tools in request translators, and groundingMetadata in response translators. The changes are applied consistently across numerous translators for various API formats (OpenAI, Claude) and providers (Antigravity, Gemini CLI, Gemini API). While the implementation appears correct, there is significant code duplication in handling the passthrough tools and in compacting JSON for streaming responses. I've added a few comments with suggestions to refactor this duplicated logic into shared utility functions to enhance maintainability.

Comment on lines +322 to +339
// Handle google_search passthrough
if gs := toolResult.Get("google_search"); gs.Exists() {
node, _ := sjson.SetRaw(`{}`, "googleSearch", gs.Raw)
extraToolNodes = append(extraToolNodes, node)
continue
}
// Handle code_execution passthrough
if ce := toolResult.Get("code_execution"); ce.Exists() {
node, _ := sjson.SetRaw(`{}`, "codeExecution", ce.Raw)
extraToolNodes = append(extraToolNodes, node)
continue
}
// Handle url_context passthrough
if uc := toolResult.Get("url_context"); uc.Exists() {
node, _ := sjson.SetRaw(`{}`, "urlContext", uc.Raw)
extraToolNodes = append(extraToolNodes, node)
continue
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for handling passthrough tools (google_search, code_execution, url_context) consists of repeated blocks of if/continue. This pattern is also duplicated across other request translator files (e.g., gemini-cli_claude_request.go, gemini_claude_request.go). This can be refactored to be more concise and data-driven, improving readability and maintainability.

Consider using a map to define the passthrough tools and iterating over it. This would also make it easier to add more passthrough tools in the future.

Suggested change
// Handle google_search passthrough
if gs := toolResult.Get("google_search"); gs.Exists() {
node, _ := sjson.SetRaw(`{}`, "googleSearch", gs.Raw)
extraToolNodes = append(extraToolNodes, node)
continue
}
// Handle code_execution passthrough
if ce := toolResult.Get("code_execution"); ce.Exists() {
node, _ := sjson.SetRaw(`{}`, "codeExecution", ce.Raw)
extraToolNodes = append(extraToolNodes, node)
continue
}
// Handle url_context passthrough
if uc := toolResult.Get("url_context"); uc.Exists() {
node, _ := sjson.SetRaw(`{}`, "urlContext", uc.Raw)
extraToolNodes = append(extraToolNodes, node)
continue
}
passthroughTools := map[string]string{
"google_search": "googleSearch",
"code_execution": "codeExecution",
"url_context": "urlContext",
}
isPassthrough := false
for claudeName, geminiName := range passthroughTools {
if tool := toolResult.Get(claudeName); tool.Exists() {
node, _ := sjson.SetRaw(`{}`, geminiName, tool.Raw)
extraToolNodes = append(extraToolNodes, node)
isPassthrough = true
break
}
}
if isPassthrough {
continue
}

Comment on lines +361 to +370
if toolDeclCount > 0 || len(extraToolNodes) > 0 {
toolsNode := `[]`
if toolDeclCount > 0 {
toolsNode, _ = sjson.SetRaw(toolsNode, "-1", functionToolNode)
}
for _, node := range extraToolNodes {
toolsNode, _ = sjson.SetRaw(toolsNode, "-1", node)
}
toolsJSON = toolsNode
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic for combining standard function tools with passthrough 'extra' tools is duplicated across multiple request translators (e.g., gemini-cli_claude_request.go, gemini_claude_request.go). To improve maintainability and reduce code duplication, this could be extracted into a shared helper function. Such a function could take the functionToolNode and extraToolNodes and return the final toolsJSON string, which can then be set on the output request.


// Cache groundingMetadata for inclusion in the message_delta event.
if gm := gjson.GetBytes(rawJSON, "response.candidates.0.groundingMetadata"); gm.Exists() {
params.GroundingMetadataRaw = strings.ReplaceAll(strings.ReplaceAll(gm.Raw, "\n", ""), "\r", "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This JSON compacting logic using chained strings.ReplaceAll is repeated in at least 7 different files for streaming responses. To improve maintainability and reduce code duplication, consider extracting this into a shared utility function, for example in the internal/util package.

A new function like util.CompactJSON(string) string could encapsulate this logic, making the translators cleaner and ensuring consistency across the codebase.

cjangrist and others added 3 commits February 11, 2026 06:43
…formats

Preserve web_search_20250305 built-in tools in request translation and
surface web_search_tool_result/citations_delta in Chat Completions and
Responses API streaming + non-streaming output.

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

Preserve built-in tools in Gemini request translation and convert
web_search_tool_result/citations_delta to groundingMetadata in streaming
and non-streaming Gemini output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11 tests covering request tool preservation, streaming/non-streaming
response translation for OpenAI, Responses, and Gemini formats,
plus accumulator reset verification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cjangrist cjangrist changed the title feat(translator): pass through Google Search grounding metadata feat(translator): grounding metadata + Claude web_search citation passthrough Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant