fix(clients): preserve gemini tool call responses

This commit is contained in:
2026-05-19 21:32:50 +08:00
parent baffccf8f8
commit 69d23efb57
2 changed files with 102 additions and 5 deletions
+45 -5
View File
@@ -265,7 +265,7 @@ func geminiResult(request Request, raw map[string]any) map[string]any {
"raw": raw,
}
}
content := geminiText(raw)
message, finishReason := geminiChatMessage(raw)
return map[string]any{
"id": "gemini-chat",
"object": "chat.completion",
@@ -273,8 +273,8 @@ func geminiResult(request Request, raw map[string]any) map[string]any {
"model": request.Model,
"choices": []any{map[string]any{
"index": 0,
"finish_reason": "stop",
"message": map[string]any{"role": "assistant", "content": content},
"finish_reason": finishReason,
"message": message,
}},
"usage": geminiUsageMap(raw),
"raw": raw,
@@ -303,19 +303,59 @@ func textFromMessages(body map[string]any) string {
}
func geminiText(raw map[string]any) string {
message, _ := geminiChatMessage(raw)
content, _ := message["content"].(string)
return content
}
func geminiChatMessage(raw map[string]any) (map[string]any, string) {
candidates, _ := raw["candidates"].([]any)
for _, candidate := range candidates {
candidateMap, _ := candidate.(map[string]any)
content, _ := candidateMap["content"].(map[string]any)
parts, _ := content["parts"].([]any)
textParts := make([]string, 0, len(parts))
toolCalls := make([]any, 0)
for _, part := range parts {
partMap, _ := part.(map[string]any)
if text, ok := partMap["text"].(string); ok && text != "" {
return text
textParts = append(textParts, text)
}
functionCall := mapFromAny(firstPresent(partMap["functionCall"], partMap["function_call"]))
if len(functionCall) == 0 {
continue
}
if toolCall := normalizeGeminiFunctionCall(functionCall, len(toolCalls), false); toolCall != nil {
toolCalls = append(toolCalls, toolCall)
}
}
message := map[string]any{
"role": "assistant",
"content": strings.Join(textParts, ""),
}
if len(toolCalls) > 0 {
message["tool_calls"] = toolCalls
if len(textParts) == 0 {
message["content"] = nil
}
}
return message, geminiFinishReason(candidateMap, len(toolCalls) > 0)
}
return map[string]any{"role": "assistant", "content": ""}, "stop"
}
func geminiFinishReason(candidate map[string]any, hasToolCalls bool) string {
if hasToolCalls {
return "tool_calls"
}
switch strings.ToUpper(stringFromAny(candidate["finishReason"])) {
case "MAX_TOKENS":
return "length"
case "SAFETY", "RECITATION", "BLOCKLIST", "PROHIBITED_CONTENT", "SPII":
return "content_filter"
default:
return "stop"
}
return ""
}
func geminiImageData(raw map[string]any) []any {