Bladeren bron

fix: preserve tool_use on malformed tool arguments to keep tool_result pairing valid

Seefs 5 dagen geleden
bovenliggende
commit
d826dd2c16
2 gewijzigde bestanden met toevoegingen van 46 en 2 verwijderingen
  1. 2 2
      relay/channel/claude/relay-claude.go
  2. 44 0
      relay/channel/claude/relay_claude_test.go

+ 2 - 2
relay/channel/claude/relay-claude.go

@@ -376,9 +376,9 @@ func RequestOpenAI2ClaudeMessage(c *gin.Context, textRequest dto.GeneralOpenAIRe
 				if message.ToolCalls != nil {
 					for _, toolCall := range message.ParseToolCalls() {
 						inputObj := make(map[string]any)
-						if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &inputObj); err != nil {
+						if err := common.UnmarshalJsonStr(toolCall.Function.Arguments, &inputObj); err != nil {
 							common.SysLog("tool call function arguments is not a map[string]any: " + fmt.Sprintf("%v", toolCall.Function.Arguments))
-							continue
+							inputObj = map[string]any{}
 						}
 						claudeMediaMessages = append(claudeMediaMessages, dto.ClaudeMediaMessage{
 							Type:  "tool_use",

+ 44 - 0
relay/channel/claude/relay_claude_test.go

@@ -171,3 +171,47 @@ func TestRequestOpenAI2ClaudeMessage_AssistantToolCallWithEmptyContent(t *testin
 		assert.NotEqual(t, "", *contentBlocks[0].Text)
 	}
 }
+
+func TestRequestOpenAI2ClaudeMessage_AssistantToolCallWithMalformedArguments(t *testing.T) {
+	request := dto.GeneralOpenAIRequest{
+		Model: "claude-opus-4-6",
+		Messages: []dto.Message{
+			{
+				Role:    "user",
+				Content: "what time is it",
+			},
+		},
+	}
+	assistantMessage := dto.Message{
+		Role:    "assistant",
+		Content: "",
+	}
+	assistantMessage.SetToolCalls([]dto.ToolCallRequest{
+		{
+			ID:   "call_bad_args",
+			Type: "function",
+			Function: dto.FunctionRequest{
+				Name:      "get_current_timestamp",
+				Arguments: "{",
+			},
+		},
+	})
+	request.Messages = append(request.Messages, assistantMessage)
+
+	claudeRequest, err := RequestOpenAI2ClaudeMessage(nil, request)
+	require.NoError(t, err)
+	require.Len(t, claudeRequest.Messages, 2)
+
+	assistantClaudeMessage := claudeRequest.Messages[1]
+	contentBlocks, ok := assistantClaudeMessage.Content.([]dto.ClaudeMediaMessage)
+	require.True(t, ok)
+	require.Len(t, contentBlocks, 1)
+
+	assert.Equal(t, "tool_use", contentBlocks[0].Type)
+	assert.Equal(t, "call_bad_args", contentBlocks[0].Id)
+	assert.Equal(t, "get_current_timestamp", contentBlocks[0].Name)
+
+	inputObj, ok := contentBlocks[0].Input.(map[string]any)
+	require.True(t, ok)
+	assert.Empty(t, inputObj)
+}