From e8e94e958f818c2f16a8c27a129e1716af490037 Mon Sep 17 00:00:00 2001 From: 0-don Date: Wed, 18 Feb 2026 18:24:59 +0100 Subject: [PATCH] fix: normalize input_text content blocks in Claude-to-OpenAI conversion 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. --- service/convert.go | 2 +- service/openaicompat/chat_to_responses.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/service/convert.go b/service/convert.go index 52824374e0..fad60e2297 100644 --- a/service/convert.go +++ b/service/convert.go @@ -127,7 +127,7 @@ func ClaudeToOpenAIRequest(claudeRequest dto.ClaudeRequest, info *relaycommon.Re for _, mediaMsg := range contents { switch mediaMsg.Type { - case "text": + case "text", "input_text": message := dto.MediaContent{ Type: "text", Text: mediaMsg.GetText(), diff --git a/service/openaicompat/chat_to_responses.go b/service/openaicompat/chat_to_responses.go index c2b44c9029..2904582fc1 100644 --- a/service/openaicompat/chat_to_responses.go +++ b/service/openaicompat/chat_to_responses.go @@ -214,8 +214,12 @@ func ChatCompletionsRequestToResponsesRequest(req *dto.GeneralOpenAIRequest) (*d for _, part := range parts { switch part.Type { case dto.ContentTypeText: + textType := "input_text" + if role == "assistant" { + textType = "output_text" + } contentParts = append(contentParts, map[string]any{ - "type": "input_text", + "type": textType, "text": part.Text, }) case dto.ContentTypeImageURL: