feat: add Gemini API compatibility, refactor stream rendering, and enhance tool call handling and configuration options

This commit is contained in:
CJACK
2026-02-22 20:53:42 +08:00
parent ae7dce0b32
commit a9403c5392
21 changed files with 581 additions and 297 deletions

View File

@@ -21,12 +21,6 @@ func BuildResponseObject(responseID, model, finalPrompt, finalThinking, finalTex
output := make([]any, 0, 2)
if len(detected) > 0 {
exposedOutputText = ""
if strings.TrimSpace(finalThinking) != "" {
output = append(output, map[string]any{
"type": "reasoning",
"text": finalThinking,
})
}
output = append(output, toResponsesFunctionCallItems(detected)...)
} else {
content := make([]any, 0, 2)
@@ -52,6 +46,21 @@ func BuildResponseObject(responseID, model, finalPrompt, finalThinking, finalTex
"content": content,
})
}
return BuildResponseObjectFromItems(
responseID,
model,
finalPrompt,
finalThinking,
finalText,
output,
exposedOutputText,
)
}
func BuildResponseObjectFromItems(responseID, model, finalPrompt, finalThinking, finalText string, output []any, outputText string) map[string]any {
if output == nil {
output = []any{}
}
return map[string]any{
"id": responseID,
"type": "response",
@@ -60,7 +69,7 @@ func BuildResponseObject(responseID, model, finalPrompt, finalThinking, finalTex
"status": "completed",
"model": model,
"output": output,
"output_text": exposedOutputText,
"output_text": outputText,
"usage": BuildResponsesUsage(finalPrompt, finalThinking, finalText),
}
}

View File

@@ -59,12 +59,15 @@ func BuildResponsesContentPartDonePayload(responseID, itemID string, outputIndex
}
}
func BuildResponsesTextDeltaPayload(responseID, delta string) map[string]any {
func BuildResponsesTextDeltaPayload(responseID, itemID string, outputIndex, contentIndex int, delta string) map[string]any {
return map[string]any{
"type": "response.output_text.delta",
"id": responseID,
"response_id": responseID,
"delta": delta,
"type": "response.output_text.delta",
"id": responseID,
"response_id": responseID,
"item_id": itemID,
"output_index": outputIndex,
"content_index": contentIndex,
"delta": delta,
}
}

View File

@@ -138,15 +138,11 @@ func TestBuildResponseObjectDetectsToolCallFromThinkingChannel(t *testing.T) {
)
output, _ := obj["output"].([]any)
if len(output) != 2 {
t.Fatalf("expected reasoning + function_call outputs, got %#v", obj["output"])
if len(output) != 1 {
t.Fatalf("expected function_call output only, got %#v", obj["output"])
}
first, _ := output[0].(map[string]any)
if first["type"] != "reasoning" {
t.Fatalf("expected first output reasoning, got %#v", first["type"])
}
second, _ := output[1].(map[string]any)
if second["type"] != "function_call" {
t.Fatalf("expected second output function_call, got %#v", second["type"])
if first["type"] != "function_call" {
t.Fatalf("expected output function_call, got %#v", first["type"])
}
}