fix(translator): use string content for assistant messages in OpenAI format#2859
fix(translator): use string content for assistant messages in OpenAI format#2859ArcaneOrion wants to merge 1 commit into
Conversation
…format OpenAI spec requires assistant message content to be a string, not an array. The Claude-to-OpenAI translator was incorrectly preserving Claude's array format which caused some upstream providers to reject requests mid-stream.
|
This pull request targeted The base branch has been automatically changed to |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 373c8de4cb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| item := gjson.ParseBytes(contentItem) | ||
| if item.Get("type").String() == "text" { | ||
| textParts = append(textParts, item.Get("text").String()) | ||
| } |
There was a problem hiding this comment.
Preserve assistant image blocks when flattening content
The new assistant-content conversion now keeps only type == "text" blocks and drops every other content block before building the OpenAI message string. For Claude histories that include assistant image blocks (or mixed text+image assistant content), this silently removes previously preserved context and sends an incomplete prompt upstream. This regression was introduced in ConvertClaudeRequestToOpenAI by filtering content items to text-only instead of preserving non-text blocks or handling them explicitly.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Code Review
This pull request updates the translation logic from Claude to OpenAI to ensure that assistant message content is formatted as a single string instead of an array, aligning with the OpenAI specification. Multiple text parts are now concatenated with newlines, and non-text items are excluded. The associated tests have been updated to reflect these changes. I have no feedback to provide.
luispater
left a comment
There was a problem hiding this comment.
Summary
This PR updates the Claude→OpenAI translator to emit assistant content as a string (by concatenating text blocks) instead of an array, which should improve compatibility with OpenAI Chat Completions–style upstream relays that reject assistant content arrays.
Findings
- No blocking issues found in the patch itself.
- Non-blocking: please double-check the choice of
"\n"as the join separator for multiple text blocks; it may introduce new newlines compared to the original Claude block boundaries. A small unit test for multiple adjacent text blocks (no tools) would lock in the expected behavior.
CI / Checks
pr-test-buildpassed.translator-path-guardis failing (expected for translator-only changes, but may still be merge-gating depending on repo policy).
Test plan
- Not run locally (reviewed via
ghdiff/checks only; no PR checkout). - Suggested:
go test ./...(or at least the translator package tests) before merge.
This is an automated Codex review result and still requires manual verification by a human reviewer.
Problem
The Claude→OpenAI translator was outputting assistant message
contentas an array ([{"type":"text","text":"..."}]), but the OpenAI Chat Completions API spec requires assistant contentto be a string.
This caused some upstream providers (notably New API / One API based relay stations) to reject requests mid-stream with
HTTP/2 INTERNAL_ERROR, resulting inunexpected EOForstream errordisconnections visible as500errors with "Headers were already written" warnings in the proxy log.Fix
For assistant messages, extract text from content items and concatenate into a single string. Non-assistant roles (user, etc.) keep the array format since OpenAI allows array content for
user messages.
Testing
internal/translator/openai/claude/pass