From 565b802a6b7f4a5dee8c1fa88407f98d04f2afe3 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Thu, 6 Nov 2025 15:26:25 -0800 Subject: [PATCH] openai: fix tool call ID mapping (#12988) --- middleware/openai_test.go | 13 ++++++++++--- openai/openai.go | 20 ++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/middleware/openai_test.go b/middleware/openai_test.go index e5cb245b0e..fc71b57d2d 100644 --- a/middleware/openai_test.go +++ b/middleware/openai_test.go @@ -218,6 +218,7 @@ func TestChatMiddleware(t *testing.T) { Role: "assistant", ToolCalls: []api.ToolCall{ { + ID: "id", Function: api.ToolCallFunction{ Name: "get_current_weather", Arguments: map[string]any{ @@ -257,6 +258,7 @@ func TestChatMiddleware(t *testing.T) { Content: "Let's see what the weather is like in Paris", ToolCalls: []api.ToolCall{ { + ID: "id", Function: api.ToolCallFunction{ Name: "get_current_weather", Arguments: map[string]any{ @@ -295,6 +297,7 @@ func TestChatMiddleware(t *testing.T) { Role: "assistant", ToolCalls: []api.ToolCall{ { + ID: "id", Function: api.ToolCallFunction{ Name: "get_current_weather", Arguments: map[string]any{ @@ -334,6 +337,7 @@ func TestChatMiddleware(t *testing.T) { Thinking: "Let's see what the weather is like in Paris", ToolCalls: []api.ToolCall{ { + ID: "id", Function: api.ToolCallFunction{ Name: "get_current_weather", Arguments: map[string]any{ @@ -373,6 +377,7 @@ func TestChatMiddleware(t *testing.T) { Role: "assistant", ToolCalls: []api.ToolCall{ { + ID: "id_abc", Function: api.ToolCallFunction{ Name: "get_current_weather", Arguments: map[string]any{ @@ -384,9 +389,10 @@ func TestChatMiddleware(t *testing.T) { }, }, { - Role: "tool", - Content: "The weather in Paris is 20 degrees Celsius", - ToolName: "get_current_weather", + Role: "tool", + Content: "The weather in Paris is 20 degrees Celsius", + ToolName: "get_current_weather", + ToolCallID: "id_abc", }, }, Options: map[string]any{ @@ -417,6 +423,7 @@ func TestChatMiddleware(t *testing.T) { Role: "assistant", ToolCalls: []api.ToolCall{ { + ID: "id", Function: api.ToolCallFunction{ Name: "get_current_weather", Arguments: map[string]any{ diff --git a/openai/openai.go b/openai/openai.go index caabbfaadf..d4fd26c251 100644 --- a/openai/openai.go +++ b/openai/openai.go @@ -437,7 +437,7 @@ func FromChatRequest(r ChatCompletionRequest) (*api.ChatRequest, error) { if err != nil { return nil, err } - messages = append(messages, api.Message{Role: msg.Role, Content: content, Thinking: msg.Reasoning, ToolCalls: toolCalls, ToolName: toolName}) + messages = append(messages, api.Message{Role: msg.Role, Content: content, Thinking: msg.Reasoning, ToolCalls: toolCalls, ToolName: toolName, ToolCallID: msg.ToolCallID}) case []any: for _, c := range content { data, ok := c.(map[string]any) @@ -501,9 +501,8 @@ func FromChatRequest(r ChatCompletionRequest) (*api.ChatRequest, error) { return nil, err } messages[len(messages)-1].ToolCalls = toolCalls - if toolName != "" { - messages[len(messages)-1].ToolName = toolName - } + messages[len(messages)-1].ToolName = toolName + messages[len(messages)-1].ToolCallID = msg.ToolCallID messages[len(messages)-1].Thinking = msg.Reasoning } default: @@ -512,15 +511,11 @@ func FromChatRequest(r ChatCompletionRequest) (*api.ChatRequest, error) { return nil, fmt.Errorf("invalid message content type: %T", content) } - toolCalls := make([]api.ToolCall, len(msg.ToolCalls)) - for i, tc := range msg.ToolCalls { - toolCalls[i].Function.Name = tc.Function.Name - err := json.Unmarshal([]byte(tc.Function.Arguments), &toolCalls[i].Function.Arguments) - if err != nil { - return nil, errors.New("invalid tool call arguments") - } + toolCalls, err := FromCompletionToolCall(msg.ToolCalls) + if err != nil { + return nil, err } - messages = append(messages, api.Message{Role: msg.Role, Thinking: msg.Reasoning, ToolCalls: toolCalls}) + messages = append(messages, api.Message{Role: msg.Role, Thinking: msg.Reasoning, ToolCalls: toolCalls, ToolCallID: msg.ToolCallID}) } } @@ -631,6 +626,7 @@ func nameFromToolCallID(messages []Message, toolCallID string) string { func FromCompletionToolCall(toolCalls []ToolCall) ([]api.ToolCall, error) { apiToolCalls := make([]api.ToolCall, len(toolCalls)) for i, tc := range toolCalls { + apiToolCalls[i].ID = tc.ID apiToolCalls[i].Function.Name = tc.Function.Name err := json.Unmarshal([]byte(tc.Function.Arguments), &apiToolCalls[i].Function.Arguments) if err != nil {