From 67e2913f3dbcea4f1b7f114eebb84f2f7ef69416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BE=84=E6=BD=AD?= Date: Sat, 14 Feb 2026 12:12:07 +0800 Subject: [PATCH] fix(ai-proxy): preserve text content alongside tool_result in Claude to OpenAI conversion (#3503) --- .../ai-proxy/provider/claude_to_openai.go | 9 +++++++++ .../ai-proxy/provider/claude_to_openai_test.go | 13 ++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai.go b/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai.go index 4a61f59a8..1df7821ba 100644 --- a/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai.go +++ b/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai.go @@ -119,6 +119,15 @@ func (c *ClaudeToOpenAIConverter) ConvertClaudeRequestToOpenAI(body []byte) ([]b } openaiRequest.Messages = append(openaiRequest.Messages, toolMsg) } + // Also add text content if present alongside tool results + // This handles cases like: [tool_result, tool_result, text] + if len(conversionResult.textParts) > 0 { + textMsg := chatMessage{ + Role: claudeMsg.Role, + Content: strings.Join(conversionResult.textParts, "\n\n"), + } + openaiRequest.Messages = append(openaiRequest.Messages, textMsg) + } } // Handle regular content if no tool calls or tool results diff --git a/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai_test.go b/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai_test.go index 10b9a1ac0..bf294b8a4 100644 --- a/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai_test.go +++ b/plugins/wasm-go/extensions/ai-proxy/provider/claude_to_openai_test.go @@ -388,6 +388,7 @@ func TestClaudeToOpenAIConverter_ConvertClaudeRequestToOpenAI(t *testing.T) { t.Run("convert_tool_result_with_actual_error_data", func(t *testing.T) { // Test using the actual JSON data from the error log to ensure our fix works + // This tests the fix for issue #3344 - text content alongside tool_result should be preserved claudeRequest := `{ "model": "anthropic/claude-sonnet-4", "messages": [{ @@ -415,14 +416,20 @@ func TestClaudeToOpenAIConverter_ConvertClaudeRequestToOpenAI(t *testing.T) { err = json.Unmarshal(result, &openaiRequest) require.NoError(t, err) - // Should have one tool message (the text content is included in the same message array) - require.Len(t, openaiRequest.Messages, 1) + // Should have two messages: tool message + user message with text content + // This is the fix for issue #3344 - text content alongside tool_result is preserved + require.Len(t, openaiRequest.Messages, 2) - // Should be tool message + // First should be tool message toolMsg := openaiRequest.Messages[0] assert.Equal(t, "tool", toolMsg.Role) assert.Contains(t, toolMsg.Content, "three.js") assert.Equal(t, "toolu_vrtx_01UbCfwoTgoDBqbYEwkVaxd5", toolMsg.ToolCallId) + + // Second should be user message with text content + userMsg := openaiRequest.Messages[1] + assert.Equal(t, "user", userMsg.Role) + assert.Equal(t, "继续", userMsg.Content) }) t.Run("convert_multiple_tool_calls", func(t *testing.T) {