Repository navigation
fix: report truncation between Claude max_tokens and OpenAI length - #147
Merged
lich0821 merged 2 commits intoOct 24, 2026
Merged
Conversation
…sh_reason stop OpenAI-compatible providers such as Gemini finish tool calls with finish_reason "stop". OpenAIStreamToClaude mapped that to end_turn even though a tool_use block had been sent, so Claude clients stopped instead of running the tool. It now reports tool_use when a tool block was started, also when the stream ends with [DONE] without a finish_reason. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Claude <-> OpenAI Chat converters never mapped a truncated reply. Claude stop_reason max_tokens always became finish_reason stop, and OpenAI finish_reason length always became end_turn, so clients treated a cut-off reply as complete. Map them in the non-stream and stream converters, both directions. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The Claude <-> OpenAI Chat converters in
internal/transformer/convert/claude_openai.gonever mapped a reply that was cut off by the token limit:stop_reason: "max_tokens"always became OpenAIfinish_reason: "stop"(ClaudeRespToOpenAIand themessage_deltabranch ofClaudeStreamToOpenAI).finish_reason: "length"always became Claudestop_reason: "end_turn"(OpenAIRespToClaudeand the finish branch ofOpenAIStreamToClaude).A client behind ccNexus therefore saw a truncated reply as a complete one. Claude Code, for one, only continues or reports a cut-off answer when it sees
max_tokens.Both directions now map
max_tokens<->length, in the non-stream and stream converters, through one small helper (claudeStopReasonToOpenAI) for the Claude side. Tool-call mapping is unchanged. InOpenAIRespToClaudeandOpenAIStreamToClaude,lengthwins overtool_use, since a tool call cut off mid-arguments is a truncated reply. The Gemini converters are left for a separate change.Tests
In
internal/transformer/convert/claude_openai_test.go:TestClaudeRespToOpenAIMaxTokensReportsLengthandTestClaudeStreamToOpenAIMaxTokensReportsLength: a Claudemax_tokensstop givesfinish_reason: "length".TestOpenAIRespToClaudeLengthReportsMaxTokensandTestOpenAIStreamToClaudeLengthReportsMaxTokens: an OpenAIlengthfinish givesstop_reason: "max_tokens"and neverend_turn.All four fail on the base commit and pass now.
go test ./internal/transformer/...andgo vet ./internal/transformer/...pass.Stacked on #145 (the first commit,
tool_usewhen an OpenAI stream ends a tool call withstop), which the stream branch here extends; only the second commit belongs to this PR.This change was made with Claude Code; the tests above were run on the branch to check it.