on main help sign in
fix: openai provider tool calls
commit0c8e111af5d8bccf77d544da967c28f7df56d36f authorKujtim Hoxha <kujtimii.h@gmail.com> dateWed 27 Aug 2025, 14:30 (1 year ago) parentd69dcc1
1 file changed+15−15
internal/llm/provider/openai.go+15−15
internal/llm/provider/openai.go+15−15
@@ -7,7 +7,6 @@ import (
77 "fmt"
88 "io"
99 "log/slog"
10− "slices"
1110 "strings"
1211 "time"
1312
@@ -342,18 +341,15 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
342341 acc := openai.ChatCompletionAccumulator{}
343342 currentContent := ""
344343 toolCalls := make([]message.ToolCall, 0)
345− var msgToolCalls []openai.ChatCompletionMessageToolCall
344+ msgToolCalls := make(map[int64]openai.ChatCompletionMessageToolCall)
346345 for openaiStream.Next() {
347346 chunk := openaiStream.Current()
348− if len(chunk.Choices) == 0 {
349− continue
350− }
351347 // Kujtim: this is an issue with openrouter qwen, its sending -1 for the tool index
352− if len(chunk.Choices[0].Delta.ToolCalls) > 0 && chunk.Choices[0].Delta.ToolCalls[0].Index == -1 {
348+ if len(chunk.Choices) != 0 && len(chunk.Choices[0].Delta.ToolCalls) > 0 && chunk.Choices[0].Delta.ToolCalls[0].Index == -1 {
353349 chunk.Choices[0].Delta.ToolCalls[0].Index = 0
354350 }
355351 acc.AddChunk(chunk)
356− for i, choice := range chunk.Choices {
352+ for _, choice := range chunk.Choices {
357353 reasoning, ok := choice.Delta.JSON.ExtraFields["reasoning"]
358354 if ok && reasoning.Raw() != "" {
359355 reasoningStr := ""
@@ -374,14 +370,14 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
374370 } else if len(choice.Delta.ToolCalls) > 0 {
375371 toolCall := choice.Delta.ToolCalls[0]
376372 newToolCall := false
377− if len(msgToolCalls)-1 >= int(toolCall.Index) { // tool call exists
378− existingToolCall := msgToolCalls[toolCall.Index]
373+ if existingToolCall, ok := msgToolCalls[toolCall.Index]; ok { // tool call exists
379374 if toolCall.ID != "" && toolCall.ID != existingToolCall.ID {
380375 found := false
381376 // try to find the tool based on the ID
382− for i, tool := range msgToolCalls {
377+ for _, tool := range msgToolCalls {
383378 if tool.ID == toolCall.ID {
384− msgToolCalls[i].Function.Arguments += toolCall.Function.Arguments
379+ existingToolCall.Function.Arguments += toolCall.Function.Arguments
380+ msgToolCalls[toolCall.Index] = existingToolCall
385381 found = true
386382 }
387383 }
@@ -389,7 +385,8 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
389385 newToolCall = true
390386 }
391387 } else {
392− msgToolCalls[toolCall.Index].Function.Arguments += toolCall.Function.Arguments
388+ existingToolCall.Function.Arguments += toolCall.Function.Arguments
389+ msgToolCalls[toolCall.Index] = existingToolCall
393390 }
394391 } else {
395392 newToolCall = true
@@ -406,17 +403,16 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
406403 Finished: false,
407404 },
408405 }
409− msgToolCalls = append(msgToolCalls, openai.ChatCompletionMessageToolCall{
406+ msgToolCalls[toolCall.Index] = openai.ChatCompletionMessageToolCall{
410407 ID: toolCall.ID,
411408 Type: "function",
412409 Function: openai.ChatCompletionMessageToolCallFunction{
413410 Name: toolCall.Function.Name,
414411 Arguments: toolCall.Function.Arguments,
415412 },
416− })
413+ }
417414 }
418415 }
419− acc.Choices[i].Message.ToolCalls = slices.Clone(msgToolCalls)
420416 }
421417 }
422418
@@ -541,6 +537,10 @@ func (o *openaiClient) toolCalls(completion openai.ChatCompletion) []message.Too
541537
542538 if len(completion.Choices) > 0 && len(completion.Choices[0].Message.ToolCalls) > 0 {
543539 for _, call := range completion.Choices[0].Message.ToolCalls {
540+ // accumulator for some reason does this.
541+ if call.Function.Name == "" {
542+ continue
543+ }
544544 toolCall := message.ToolCall{
545545 ID: call.ID,
546546 Name: call.Function.Name,