Skip to content

Conversation

@luispater
Copy link

No description provided.

luispater and others added 6 commits December 17, 2025 14:53
@gemini-code-assist
Copy link

Summary of Changes

Hello @luispater, 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 focuses on a significant refactoring of the authentication synthesis mechanism, centralizing the creation of authentication entries from various sources into a new synthesizer package. This change enhances the system's architecture by separating concerns and making the authentication process more robust and easier to manage. Additionally, it includes specific improvements to how Claude API requests and responses are translated, particularly in handling complex content types like 'thinking' blocks and tool calls, and addresses a minor issue in configuration change reporting.

Highlights

  • Auth Synthesis Refactoring: The core logic for synthesizing authentication entries from both configuration API keys and file-based OAuth credentials has been refactored into a new, dedicated synthesizer package, improving modularity and maintainability.
  • Claude Translation Updates: The Claude request and response translation logic has been updated to use direct JSON manipulation (sjson) instead of intermediate Go structs, simplifying the handling of 'thinking' blocks, tool use, and image data.
  • Config Diff Reporting Fix: A minor correction was applied to the configuration difference reporting for provider prefixes, ensuring that whitespace is properly trimmed before comparison.
  • New synthesizer Package: A new synthesizer package has been introduced, containing ConfigSynthesizer for API key-based auth, FileSynthesizer for OAuth file-based auth, and helper utilities like StableIDGenerator and functions for applying excluded models metadata and headers.
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.

@luispater luispater merged commit 462a705 into router-for-me:main Dec 17, 2025
1 check failed
@luispater luispater deleted the plus branch December 17, 2025 08:43
Copy link

@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 a significant and well-executed refactoring of the watcher package by abstracting auth entry creation into a new synthesizer package. This greatly improves the separation of concerns and maintainability. The PR also includes a bug fix for how configuration prefixes are logged. However, I've identified a few potential regressions in the antigravity/claude translator related to the handling of "thinking" block signatures, which I've detailed in the comments. Specifically, the logic for handling unsigned thinking blocks in requests has changed, and signature handling appears to have been completely removed from the non-streaming response conversion, which could be critical.

Comment on lines 88 to +103
if contentTypeResult.Type == gjson.String && contentTypeResult.String() == "thinking" {
// Claude "thinking" blocks are internal-only. They also require a valid provider signature
// when replayed as conversation history. Since we cannot mint signatures, only forward
// thinking blocks when the client provides a non-empty signature; otherwise, drop them.
prompt := contentResult.Get("thinking").String()
signatureResult := contentResult.Get("signature")
if signatureResult.Type == gjson.String && signatureResult.String() != "" {
prompt := contentResult.Get("thinking").String()
clientContent.Parts = append(clientContent.Parts, client.Part{
Text: prompt,
Thought: true,
ThoughtSignature: signatureResult.String(),
})
signature := geminiCLIClaudeThoughtSignature
if signatureResult.Exists() {
signature = signatureResult.String()
}
partJSON := `{}`
partJSON, _ = sjson.Set(partJSON, "thought", true)
if prompt != "" {
partJSON, _ = sjson.Set(partJSON, "text", prompt)
}
if signature != "" {
partJSON, _ = sjson.Set(partJSON, "thoughtSignature", signature)
}
clientContentJSON, _ = sjson.SetRaw(clientContentJSON, "parts.-1", partJSON)

Choose a reason for hiding this comment

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

high

The logic for handling thinking blocks has been changed. Previously, thinking blocks without a client-provided signature were dropped, as noted by a comment in the original code. The new implementation adds a default signature (skip_thought_signature_validator) to all thinking blocks, regardless of whether a signature was provided. This is a significant change in behavior that may have unintended consequences, as the original implementation was more defensive about replaying thinking blocks. Was this change intentional? The removal of test/antigravity_claude_signature_test.go::TestAntigravityClaudeRequest_DropsUnsignedThinkingBlocks suggests it might be, but it's a critical change to make without clarification.

Comment on lines +389 to +392
contentBlocks = append(contentBlocks, map[string]interface{}{
"type": "thinking",
"thinking": thinkingBuilder.String(),
}
if thinkingSignature != "" {
block["signature"] = thinkingSignature
}
contentBlocks = append(contentBlocks, block)
})

Choose a reason for hiding this comment

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

high

In the non-streaming response converter (ConvertAntigravityResponseToClaudeNonStream), it appears that all handling for thinkingSignature has been removed. This seems to be a regression, as the signature might be required by the Claude API for maintaining conversation history. The streaming response converter still handles signatures, so this creates an inconsistency. Please restore the logic to handle thinkingSignature, which includes re-introducing the thinkingSignature variable, populating it from the response parts, and adding it to the thinking block here.

Suggested change
contentBlocks = append(contentBlocks, map[string]interface{}{
"type": "thinking",
"thinking": thinkingBuilder.String(),
}
if thinkingSignature != "" {
block["signature"] = thinkingSignature
}
contentBlocks = append(contentBlocks, block)
})
block := map[string]interface{}{
"type": "thinking",
"thinking": thinkingBuilder.String(),
}
if thinkingSignature != "" {
block["signature"] = thinkingSignature
}
contentBlocks = append(contentBlocks, block)

// Ensure we have an open thinking block to attach thinking/signature deltas to.
if params.ResponseType != 2 {
if partResult.Get("thought").Bool() {
if thoughtSignature := partResult.Get("thoughtSignature"); thoughtSignature.Exists() && thoughtSignature.String() != "" {

Choose a reason for hiding this comment

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

medium

The fallback from thoughtSignature to thought_signature has been removed. If some backend responses still use the snake_case thought_signature key, this change could cause signatures to be missed. It would be safer to retain this fallback to ensure compatibility. For example:

thoughtSignature := partResult.Get("thoughtSignature")
if !thoughtSignature.Exists() {
    thoughtSignature = partResult.Get("thought_signature")
}
if thoughtSignature.Exists() && thoughtSignature.String() != "" {
    // ... existing signature handling logic
}

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.

2 participants