Skip to content

feat(translator): align OpenAI/Gemini/Claude protocol conversion and streaming behavior#1835

Open
Hsiangpo wants to merge 1 commit intorouter-for-me:mainfrom
Hsiangpo:feat/protocol-align-20260305
Open

feat(translator): align OpenAI/Gemini/Claude protocol conversion and streaming behavior#1835
Hsiangpo wants to merge 1 commit intorouter-for-me:mainfrom
Hsiangpo:feat/protocol-align-20260305

Conversation

@Hsiangpo
Copy link

@Hsiangpo Hsiangpo commented Mar 4, 2026

Summary

  • align protocol conversion details across OpenAI/Gemini/Claude/Gemini-CLI translators
  • fix object/string preservation, stop/stop_sequences mapping, tool_choice compatibility, and finish_reason mapping
  • add multi-candidate support for both stream and non-stream conversion paths
  • add regression tests for all repaired conversion paths
  • add protocol alignment documentation under docs/protocol/2026-03-05-openai-compat-alignment.md

Verification

  • go test ./internal/translator/...
  • go test ./sdk/api/handlers/openai/...
  • go test ./internal/runtime/executor/... -run "OpenAI|compat|Translator"

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, 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 compatibility layer for various large language model providers, specifically OpenAI, Gemini, and Claude. The core objective is to ensure that requests and responses are translated with high fidelity, preserving data types, structures, and semantic meaning across different API protocols. This includes robust handling of complex fields like tool calls, image data, and multi-candidate outputs, leading to a more reliable and consistent experience when interacting with diverse LLM services through the proxy.

Highlights

  • Protocol Alignment: Aligned protocol conversion details across OpenAI, Gemini, Claude, and Gemini-CLI translators to ensure consistent behavior and data fidelity.
  • Data Preservation: Fixed issues with object/string preservation for fields like tool_choice and function_call_output.output, ensuring their original JSON structures are maintained.
  • Parameter Mapping: Improved mapping for various parameters including stop/stop_sequences, max_tokens/max_completion_tokens, and tool_choice compatibility across different API specifications.
  • Multi-Candidate Support: Added comprehensive support for multi-candidate responses in both streaming and non-streaming conversion paths for Gemini and Gemini-CLI, preventing data loss in scenarios with multiple generated outputs.
  • Image and File Handling: Enhanced conversion logic for image URLs (including remote URLs and data URIs) and file data, ensuring correct MIME type detection and data embedding/referencing.
  • Finish Reason Mapping: Refined the mapping of finish_reason values from Gemini and Gemini-CLI to OpenAI's semantic equivalents, such as MAX_TOKENS to length.
  • Built-in Tool Preservation: Ensured that built-in tools like web_search and file_search are no longer silently ignored during OpenAI Responses to Chat Completions conversion.
  • Enhanced Transformer Registry: Improved the HasResponseTransformer function to correctly identify bidirectional transformation capabilities, preventing false negatives.
  • Regression Tests: Added extensive regression tests for all repaired conversion paths to prevent future regressions and validate the fixes.

🧠 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
  • docs/protocol/2026-03-05-openai-compat-alignment.md
    • Added a new documentation file detailing the OpenAI compatibility layer protocol alignment fixes.
  • internal/translator/claude/openai/chat-completions/claude_openai_request.go
    • Added logic to map remote image URLs to Claude's source.type=url format.
  • internal/translator/claude/openai/chat-completions/claude_openai_request_test.go
    • Added a test case to verify the preservation of remote image URLs during Claude request conversion.
  • internal/translator/claude/openai/responses/claude_openai-responses_request.go
    • Added mapping for input string to user messages and for temperature, top_p, and stop parameters.
  • internal/translator/claude/openai/responses/claude_openai-responses_request_test.go
    • Added a test case to verify the mapping of input strings and various parameters to Claude responses.
  • internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_request.go
    • Implemented mapping for max_tokens and stop sequences to Gemini-CLI's generationConfig.
    • Enhanced image URL handling to support both data URIs and remote URLs, mapping remote URLs to fileData.fileUri.
    • Improved tool_choice mapping to Gemini-CLI's functionCallingConfig.
    • Ensured tool result objects are preserved by attempting to deserialize JSON strings into objects.
  • internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_request_test.go
    • Added test cases for preserving tool result objects.
    • Added test cases for mapping max_tokens, stop sequences, and tool_choice.
    • Verified max_completion_tokens precedence over max_tokens.
    • Added a test for tool_choice function allowed name mapping.
    • Verified remote image URL mapping to fileData.fileUri.
    • Added a test for parsing JSON string tool results into objects.
  • internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_response.go
    • Refactored response conversion to support multiple candidates in streaming responses.
    • Improved finish_reason mapping from Gemini-CLI to OpenAI semantics, including MAX_TOKENS to length.
  • internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_response_test.go
    • Added a test case for mapping finish_reason to length.
    • Added a test case to verify multi-candidate support in streaming responses.
  • internal/translator/gemini/openai/chat-completions/gemini_openai_request.go
    • Implemented mapping for max_tokens and stop sequences to Gemini's generationConfig.
    • Enhanced image URL handling to support both data URIs and remote URLs, mapping remote URLs to fileData.fileUri.
    • Improved file data URI parsing to strip prefixes.
    • Improved tool_choice mapping to Gemini's functionCallingConfig.
    • Ensured tool result objects are preserved.
  • internal/translator/gemini/openai/chat-completions/gemini_openai_request_test.go
    • Added test cases for mapping max_tokens and stop sequences.
    • Verified image URL preservation.
    • Verified file data URI prefix stripping.
    • Added a test for tool_choice required mapping.
    • Added a test for preserving tool result objects.
  • internal/translator/gemini/openai/chat-completions/gemini_openai_response.go
    • Introduced mapGeminiFinishReason to standardize finish reason mapping.
    • Updated streaming response logic to use candidate-specific finishReason instead of a fixed candidate index.
  • internal/translator/gemini/openai/chat-completions/gemini_openai_response_test.go
    • Added a test case to verify streaming responses use candidate-specific finishReason.
    • Added a test case for non-streaming MAX_TOKENS mapping to length.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_request.go
    • Fixed function_call_output.output object preservation by using SetRaw for JSON objects.
    • Added mapping for stop sequences (supporting both string and array formats) and tool_choice.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_request_test.go
    • Added a test case for mapping stop from OpenAI's stop field.
    • Verified preservation of function call output objects.
    • Added a test case for tool_choice required mapping.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_response.go
    • Refactored streaming response handling to manage per-candidate state for messages and reasoning.
    • Ensured correct aggregation of outputs from multiple candidates in response.completed events.
    • Updated finalizeReasoning and finalizeMessage to operate on per-candidate states.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_response_test.go
    • Added test cases for multi-candidate messages in non-streaming responses.
    • Added test cases for multi-candidate messages in streaming responses.
  • internal/translator/openai/claude/openai_claude_request.go
    • Added support for the stop field as an alias for stop_sequences in Claude requests.
  • internal/translator/openai/claude/openai_claude_request_test.go
    • Added a test case to verify the mapping of the stop alias.
  • internal/translator/openai/gemini/openai_gemini_request.go
    • Added support for generationConfig.stop (string and array inputs) in Gemini requests.
    • Improved tool_choice mapping to convert ANY mode with allowedFunctionNames to OpenAI's specific function tool_choice object.
    • Refined tool_call_id matching for functionResponse to prioritize exact name matches.
  • internal/translator/openai/gemini/openai_gemini_request_test.go
    • Added a test case for mapping stop string from generationConfig.stop.
    • Added a test case for tool_choice mapping with allowedFunctionNames.
  • internal/translator/openai/gemini/openai_gemini_response.go
    • Modified streaming and non-streaming response conversion to correctly handle multiple candidates by using choiceIndex for candidate paths, preventing overwrites.
  • internal/translator/openai/gemini/openai_gemini_response_test.go
    • Added test cases for multi-candidate streaming responses.
    • Added test cases for multi-candidate non-streaming responses.
  • internal/translator/openai/openai/responses/openai_openai-responses_request.go
    • Ensured built-in tools (web_search, file_search) are preserved during conversion from OpenAI Responses to Chat Completions.
    • Updated tool_choice conversion to correctly handle object and array types, not just strings.
  • internal/translator/openai/openai/responses/openai_openai-responses_request_test.go
    • Added a test case for preserving the tool_choice object.
    • Added a test case for keeping built-in tools during conversion.
  • sdk/translator/registry.go
    • Enhanced HasResponseTransformer to check for transformations in both from->to and to->from directions.
Activity
  • Hsiangpo created the pull request to align protocol conversion and streaming behavior across OpenAI, Gemini, and Claude translators.
  • The pull request includes a new documentation file detailing 19 specific fixes and improvements.
  • Verification steps include running go test for internal/translator/..., sdk/api/handlers/openai/..., and internal/runtime/executor/... -run "OpenAI|compat|Translator", all of which passed.
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

此 PR 引入了广泛的修复和增强功能,以对齐 OpenAI、Gemini 和 Claude 之间的协议转换。这些更改是广泛的,涵盖了参数映射、多候选者支持以及工具调用和图像 URL 的数据保真度。为所有修复的路径添加全面的回归测试是一个很好的实践,显著提高了翻译器的鲁棒性。新的文档文件也是一个有价值的补充。

我发现了一些问题。一个是在文档文件名和标题中可能存在一个拼写错误。另一个是 sdk/translator/registry.go 文件中一个更关键的问题,其中检查响应转换器是否存在的逻辑似乎不正确,并可能导致错误。

@@ -0,0 +1,146 @@
# 2026-03-05 OpenAI 兼容层协议对齐修复记录
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

文件名和此文档标题中的日期 2026-03-05 似乎是一个拼写错误,很可能意在表示过去的日期(例如 2024-03-05)。使用未来日期可能会引起混淆。最好将其更正以反映更改的实际日期。

Suggested change
# 2026-03-05 OpenAI 兼容层协议对齐修复记录
# 2024-03-05 OpenAI 兼容层协议对齐修复记录

Copy link
Collaborator

@luispater luispater left a comment

Choose a reason for hiding this comment

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

Thanks for the protocol-alignment work — the overall direction looks good, and the added regression coverage improves confidence in the request/response mapping changes.

That said, I found three blocking issues before this can be merged. Aside from these blocking items, the rest of the changes look reasonable to me.

Blocking findings:

  • Blocking: Gemini CLI -> OpenAI streaming tracks tool-call indices globally instead of per choice. In internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_response.go, FunctionIndex is shared across the whole stream, so if two candidates each emit their first function call, the second candidate gets tool_calls[0].index = 1 instead of 0. OpenAI-compatible clients treat tool-call indices as scoped to a single choice, so this breaks reconstruction of multi-choice tool-call streams.
  • Blocking: OpenAI -> Gemini streaming also shares tool-call accumulation across choices. In internal/translator/openai/gemini/openai_gemini_response.go, ToolCallsAccumulator is keyed only by toolIndex, not by (choiceIndex, toolIndex). If two choices both emit tool_calls[0], the later choice overwrites the earlier one. When a finish chunk arrives, the accumulated tool call is flushed into the wrong candidate and the shared accumulator is cleared, so the other candidate loses its tool call entirely.
  • Blocking: the PR introduces new Chinese comments, which violates the repository convention that code comments must be in English only. I noticed this in internal/translator/openai/gemini/openai_gemini_request.go:67 and internal/translator/openai/claude/openai_claude_request.go:41. Please convert all newly added comments to English for consistency with the rest of the codebase.

Test plan:

  • go test ./internal/translator/...
  • go test ./sdk/api/handlers/openai/...
  • go test ./internal/runtime/executor/... -run "OpenAI|compat|Translator"
  • plus local repros for both multi-candidate streaming tool-call cases described above

Suggested follow-up:

  • Please make the streaming tool-call state choice-aware in both directions.
  • Please add regression tests for multi-candidate + tool-call streaming, not just multi-candidate text output.
  • Please convert all newly added non-English comments to English.

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.

3 participants