fix: normalize input_text content blocks in Claude-to-OpenAI conversion#2968
fix: normalize input_text content blocks in Claude-to-OpenAI conversion#29680-don wants to merge 1 commit intoQuantumNous:mainfrom
Conversation
WalkthroughClaude-to-OpenAI conversion now treats "input_text" the same as "text" for media content, and response conversion emits "output_text" for assistant messages while non-assistant messages use "input_text". Changes
Sequence Diagram(s)(Skipped — changes are localized conversions without multi-component sequential flow requiring visualization.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
应该是搞错地方了,claude文档上没有这一个类型,这个报错可能是别的地方的转换错误 |
|
input_text is not in the Anthropic spec, it's from the Responses API. OpenClaw sends it through /v1/messages when using codex models — known bugs on their side (openclaw/openclaw#13189, openclaw/openclaw#18787). Same structure as text, just a different type string. Without this, the content gets silently dropped and upstream returns errors. |
Clients like OpenClaw send input_text content blocks (a Responses API type) through /v1/messages. The Claude-to-OpenAI converter silently drops unknown types, so the message arrives empty at the upstream, causing "Invalid value: 'input_text'" errors. Map input_text to text since they share the same structure.
20f3962 to
e8e94e9
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
service/convert.go (1)
129-136:⚠️ Potential issue | 🟡 Minor
output_textnot handled — symmetric silent-drop for assistant messagesThe companion change in
chat_to_responses.gonow emits"output_text"for assistant-role text content when converting Chat → Responses API. The OpenAI Responses API spec documentsoutput_textas the type always used for model-generated text. A community report confirms that usinginput_textfor the assistant role returns an API error, makingoutput_textthe required type for assistant turns.If a client that sends
output_textblocks (e.g., when forwarding a previous Responses API assistant turn verbatim) calls/v1/messages, those blocks fall through the switch without a matching case and are silently dropped — the exact same class of bug this PR fixes forinput_text.🐛 Proposed fix — add
output_textto the case- case "text", "input_text": + case "text", "input_text", "output_text":🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@service/convert.go` around lines 129 - 136, The switch in service/convert.go that handles mediaMsg.Type currently matches "text" and "input_text" but omits "output_text", causing assistant-originated Response API blocks to be dropped; update the switch in the conversion function that builds dto.MediaContent (the block that creates message := dto.MediaContent{ Type: "text", Text: mediaMsg.GetText(), CacheControl: mediaMsg.CacheControl } and appends to mediaMessages) to also match "output_text" (either by adding "output_text" to the same case list or by adding a case that maps "output_text" to the same dto.MediaContent shape) so assistant output_text blocks are preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@service/convert.go`:
- Around line 129-136: The switch in service/convert.go that handles
mediaMsg.Type currently matches "text" and "input_text" but omits "output_text",
causing assistant-originated Response API blocks to be dropped; update the
switch in the conversion function that builds dto.MediaContent (the block that
creates message := dto.MediaContent{ Type: "text", Text: mediaMsg.GetText(),
CacheControl: mediaMsg.CacheControl } and appends to mediaMessages) to also
match "output_text" (either by adding "output_text" to the same case list or by
adding a case that maps "output_text" to the same dto.MediaContent shape) so
assistant output_text blocks are preserved.
input_text→textinClaudeToOpenAIRequestso clients sending Responses API content types via/v1/messagesdon't get silently droppedInvalid value: 'input_text'errors from upstream providersSummary by CodeRabbit