Skip to content

Conversation

@happycastle114
Copy link

@happycastle114 happycastle114 commented Feb 10, 2026

Summary

Fix OpenAI Responses → Gemini request translation when message content is sent as a plain string (common in OpenAI SDKs, including Python), not just as an array.

Bug

ConvertOpenAIResponsesRequestToGemini only processed message content when content was an array.
For inputs like:

{"role":"system","content":"You are helpful"}
{"role":"user","content":"Hello"}

content was skipped, producing contents: [] in the Gemini payload and causing:

at least one contents field is required

Fix

1) System message handling

  • Added support for string content in system messages (in addition to array handling).
  • When content is a string, it now populates system_instruction.parts[0].text.

2) Regular message handling

  • Added non-array content handling before existing array logic.
  • When content is a string, it now creates a Gemini contents item directly with mapped role and a text part.

3) Tests

  • Added gemini_openai-responses_request_test.go with coverage for both formats:
    • string content (system + user)
    • array content (existing structured format)

Reproduction

  1. Send OpenAI Responses request with plain string message content:
    {
      "model": "gpt-5",
      "input": [
        {"role": "system", "content": "You are helpful"},
        {"role": "user", "content": "Hello"}
      ]
    }
  2. Before this fix: translated Gemini request has empty contents and request fails.
  3. After this fix: translated Gemini request includes system_instruction and contents with user text, and succeeds.

Notes

  • Followed existing style and preserved tab-indented Go formatting.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @happycastle114, 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 addresses a bug where the translation from OpenAI Responses to Gemini requests failed when message content was provided as a plain string rather than an array. The changes enhance the translator to correctly interpret and convert both string and array content formats for system and regular messages, ensuring successful request translation and preventing errors in the Gemini payload.

Highlights

  • System Message Handling: Implemented support for plain string content in OpenAI system messages, in addition to the existing array content handling, ensuring proper translation to Gemini's system_instruction.
  • Regular Message Handling: Added logic to correctly process plain string content within regular OpenAI messages, converting them into appropriate Gemini contents with a text part, before falling back to array content processing.
  • Comprehensive Testing: Introduced new test cases to validate the translation of both string and array formats for message content, covering system and user roles, to prevent regressions and ensure robustness.

🧠 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
  • internal/translator/gemini/openai/responses/gemini_openai-responses_request.go
    • Modified system message content parsing to support both array and plain string formats for the 'content' field.
    • Updated regular message content parsing to first handle plain string content, then delegate to the existing array content logic if the content is an array.
  • internal/translator/gemini/openai/responses/gemini_openai-responses_request_test.go
    • Added a new test file to cover various content formats.
    • Included test cases for system and user messages with plain string content.
    • Included test cases for system and user messages with array content to ensure existing functionality is maintained.
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 successfully addresses a bug by adding support for plain string content in OpenAI Responses to Gemini request translations, covering both system and regular messages. The inclusion of new tests to validate both string and array formats is a great addition. My review includes suggestions to refactor some duplicated code and remove redundant logic, which will improve the overall maintainability and clarity of the code.

Comment on lines +121 to 142
if content.IsArray() {
var builder strings.Builder
content.ForEach(func(_, contentItem gjson.Result) bool {
text := contentItem.Get("text").String()
if builder.Len() > 0 && text != "" {
builder.WriteByte('\n')
}
builder.WriteString(text)
return true
})
if !gjson.Get(out, "system_instruction").Exists() {
systemInstr := `{"parts":[{"text":""}]}`
systemInstr, _ = sjson.Set(systemInstr, "parts.0.text", builder.String())
out, _ = sjson.SetRaw(out, "system_instruction", systemInstr)
}
} else if content.Type == gjson.String {
if !gjson.Get(out, "system_instruction").Exists() {
systemInstr := `{"parts":[{"text":""}]}`
systemInstr, _ = sjson.Set(systemInstr, "parts.0.text", content.String())
out, _ = sjson.SetRaw(out, "system_instruction", systemInstr)
}
builder.WriteString(text)
return true
})
if !gjson.Get(out, "system_instruction").Exists() {
systemInstr := `{"parts":[{"text":""}]}`
systemInstr, _ = sjson.Set(systemInstr, "parts.0.text", builder.String())
out, _ = sjson.SetRaw(out, "system_instruction", systemInstr)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

There's some duplicated logic for setting the system_instruction. You can refactor this to be more DRY by extracting the text from either the string or array content first, and then using a single block to set the JSON value. This will make the code easier to read and maintain.

						var systemText string
						isSystemTextPresent := false

						if content.IsArray() {
							var builder strings.Builder
							content.ForEach(func(_, contentItem gjson.Result) bool {
								text := contentItem.Get("text").String()
								if builder.Len() > 0 && text != "" {
									builder.WriteByte('\n')
								}
								builder.WriteString(text)
								return true
							})
							systemText = builder.String()
							isSystemTextPresent = true
						} else if content.Type == gjson.String {
							systemText = content.String()
							isSystemTextPresent = true
						}

						if isSystemTextPresent && !gjson.Get(out, "system_instruction").Exists() {
							systemInstr := `{"parts":[{"text":""}]}`
							systemInstr, _ = sjson.Set(systemInstr, "parts.0.text", systemText)
							out, _ = sjson.SetRaw(out, "system_instruction", systemInstr)
						}

Comment on lines 162 to 164
if effRole == "assistant" {
effRole = "model"
}
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 if condition appears to be unreachable. The preceding switch statement on strings.ToLower(itemRole) already maps "assistant" to "model". Therefore, effRole cannot be "assistant" at this point, making this check redundant. You can safely remove this block.

Comment on lines +206 to 208
if effRole == "assistant" {
effRole = "model"
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the logic for string content, this if condition appears to be unreachable. The switch statement on itemRole already handles the "assistant" case by mapping it to "model". This block is redundant and can be removed to simplify the code.

@luispater luispater changed the base branch from main to dev February 11, 2026 06:17
@luispater
Copy link
Collaborator

I fixed the issue in v6.8.11.

Thank you for your contribution.

This PR has been closed.

@luispater luispater closed this 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.

2 participants