fix(edge): 분리된 Gemini 도구 호출을 보존한다

This commit is contained in:
toki 2026-08-15 10:29:48 +09:00
parent 03aff0b8f8
commit 81439001f9
2 changed files with 33 additions and 2 deletions

View file

@ -695,10 +695,27 @@ func decodeOpenAIPresetSSE(body []byte) (normalizedStageOutput, error) {
stage.Deltas = append(stage.Deltas, normalizedStageDelta{Kind: normalizedStageDeltaReasoning, Text: reasoning})
}
for _, delta := range choice.Delta.ToolCalls {
state := tools[delta.Index]
toolIndex := delta.Index
if toolIndex == 0 && delta.ID != "" {
if first := tools[0]; first != nil && first.id != "" && first.id != delta.ID {
matched := false
for existingIndex, existing := range tools {
if existing.id == delta.ID {
toolIndex = existingIndex
matched = true
break
}
}
if !matched {
for toolIndex = 1; tools[toolIndex] != nil; toolIndex++ {
}
}
}
}
state := tools[toolIndex]
if state == nil {
state = &toolState{}
tools[delta.Index] = state
tools[toolIndex] = state
}
if delta.ID != "" {
state.id = delta.ID

View file

@ -102,6 +102,20 @@ func TestGeminiChatProviderResponseAddsMissingParallelToolIndices(t *testing.T)
}
}
func TestOpenAIPresetSSESeparatesNewToolIDsWithoutIndices(t *testing.T) {
body := []byte("data: {\"id\":\"chat-1\",\"choices\":[{\"delta\":{\"tool_calls\":[{\"id\":\"call-1\",\"function\":{\"name\":\"read_file\",\"arguments\":\"{\\\"path\\\":\\\"plan.md\\\"}\"}}]}}]}\n\n" +
"data: {\"id\":\"chat-1\",\"choices\":[{\"delta\":{\"tool_calls\":[{\"id\":\"call-2\",\"function\":{\"name\":\"read_file\",\"arguments\":\"{\\\"path\\\":\\\"review.md\\\"}\"}}]}}]}\n\n" +
"data: {\"id\":\"chat-1\",\"choices\":[{\"delta\":{\"tool_calls\":[{\"id\":\"call-3\",\"function\":{\"name\":\"bash\",\"arguments\":\"{\\\"command\\\":\\\"test -f index.html\\\"}\"}}]}}]}\n\n" +
"data: {\"id\":\"chat-1\",\"choices\":[{\"delta\":{},\"finish_reason\":\"tool_calls\"}],\"usage\":{\"prompt_tokens\":1,\"completion_tokens\":1,\"total_tokens\":2}}\n\ndata: [DONE]\n\n")
stage, err := decodeOpenAIPresetSSE(body)
if err != nil {
t.Fatal(err)
}
if len(stage.ToolCalls) != 3 {
t.Fatalf("decoded tool calls = %+v", stage.ToolCalls)
}
}
func TestProviderChatTokenLimitNormalizationUsesSelectedProfile(t *testing.T) {
tests := []struct {
name string