on main help sign in
chore: fix openrouter issues
30b508fKujtim Hoxha
internal/llm/provider/openai.go+25−2
@@ -331,8 +331,14 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
331 var currentToolCallID string
331 var currentToolCallID string
332 var currentToolCall openai.ChatCompletionMessageToolCall
332 var currentToolCall openai.ChatCompletionMessageToolCall
333 var msgToolCalls []openai.ChatCompletionMessageToolCall
333 var msgToolCalls []openai.ChatCompletionMessageToolCall
334+ currentToolIndex := 0
334 for openaiStream.Next() {
335 for openaiStream.Next() {
335 chunk := openaiStream.Current()
336 chunk := openaiStream.Current()
337+ // Kujtim: this is an issue with openrouter qwen, its sending -1 for the tool index
338+ if len(chunk.Choices) > 0 && len(chunk.Choices[0].Delta.ToolCalls) > 0 && chunk.Choices[0].Delta.ToolCalls[0].Index == -1 {
339+ chunk.Choices[0].Delta.ToolCalls[0].Index = int64(currentToolIndex)
340+ currentToolIndex++
341+ }
336 acc.AddChunk(chunk)
342 acc.AddChunk(chunk)
337 // This fixes multiple tool calls for some providers
343 // This fixes multiple tool calls for some providers
338 for _, choice := range chunk.Choices {
344 for _, choice := range chunk.Choices {
@@ -348,6 +354,14 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
348 if currentToolCallID == "" {
354 if currentToolCallID == "" {
349 if toolCall.ID != "" {
355 if toolCall.ID != "" {
350 currentToolCallID = toolCall.ID
356 currentToolCallID = toolCall.ID
357+ eventChan <- ProviderEvent{
358+ Type: EventToolUseStart,
359+ ToolCall: &message.ToolCall{
360+ ID: toolCall.ID,
361+ Name: toolCall.Function.Name,
362+ Finished: false,
363+ },
364+ }
351 currentToolCall = openai.ChatCompletionMessageToolCall{
365 currentToolCall = openai.ChatCompletionMessageToolCall{
352 ID: toolCall.ID,
366 ID: toolCall.ID,
353 Type: "function",
367 Type: "function",
@@ -359,13 +373,21 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
359 }
373 }
360 } else {
374 } else {
361 // Delta tool use
375 // Delta tool use
362− if toolCall.ID == "" {
376+ if toolCall.ID == "" || toolCall.ID == currentToolCallID {
363 currentToolCall.Function.Arguments += toolCall.Function.Arguments
377 currentToolCall.Function.Arguments += toolCall.Function.Arguments
364 } else {
378 } else {
365 // Detect new tool use
379 // Detect new tool use
366 if toolCall.ID != currentToolCallID {
380 if toolCall.ID != currentToolCallID {
367 msgToolCalls = append(msgToolCalls, currentToolCall)
381 msgToolCalls = append(msgToolCalls, currentToolCall)
368 currentToolCallID = toolCall.ID
382 currentToolCallID = toolCall.ID
383+ eventChan <- ProviderEvent{
384+ Type: EventToolUseStart,
385+ ToolCall: &message.ToolCall{
386+ ID: toolCall.ID,
387+ Name: toolCall.Function.Name,
388+ Finished: false,
389+ },
390+ }
369 currentToolCall = openai.ChatCompletionMessageToolCall{
391 currentToolCall = openai.ChatCompletionMessageToolCall{
370 ID: toolCall.ID,
392 ID: toolCall.ID,
371 Type: "function",
393 Type: "function",
@@ -378,7 +400,8 @@ func (o *openaiClient) stream(ctx context.Context, messages []message.Message, t
378 }
400 }
379 }
401 }
380 }
402 }
403+ // Kujtim: some models send finish stop even for tool calls
381− if choice.FinishReason == "tool_calls" {
404+ if choice.FinishReason == "tool_calls" || (choice.FinishReason == "stop" && currentToolCallID != "") {
382 msgToolCalls = append(msgToolCalls, currentToolCall)
405 msgToolCalls = append(msgToolCalls, currentToolCall)
383 if len(acc.Choices) > 0 {
406 if len(acc.Choices) > 0 {
384 acc.Choices[0].Message.ToolCalls = msgToolCalls
407 acc.Choices[0].Message.ToolCalls = msgToolCalls