mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
143 lines
4.0 KiB
Go
143 lines
4.0 KiB
Go
package oauthprovider
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestBuildRequestUsesFunctionFieldsWhenToolCallNameMissing(t *testing.T) {
|
|
p := &AntigravityProvider{}
|
|
|
|
messages := []Message{
|
|
{
|
|
Role: "assistant",
|
|
ToolCalls: []ToolCall{{
|
|
ID: "call_read_file_123",
|
|
Function: &FunctionCall{
|
|
Name: "read_file",
|
|
Arguments: `{"path":"README.md"}`,
|
|
},
|
|
}},
|
|
},
|
|
{
|
|
Role: "tool",
|
|
ToolCallID: "call_read_file_123",
|
|
Content: "ok",
|
|
},
|
|
}
|
|
|
|
req := p.buildRequest(messages, nil, "", nil)
|
|
if len(req.Contents) != 2 {
|
|
t.Fatalf("expected 2 contents, got %d", len(req.Contents))
|
|
}
|
|
|
|
modelPart := req.Contents[0].Parts[0]
|
|
if modelPart.FunctionCall == nil {
|
|
t.Fatal("expected functionCall in assistant message")
|
|
}
|
|
if modelPart.FunctionCall.Name != "read_file" {
|
|
t.Fatalf("expected functionCall name read_file, got %q", modelPart.FunctionCall.Name)
|
|
}
|
|
if got := modelPart.FunctionCall.Args["path"]; got != "README.md" {
|
|
t.Fatalf("expected functionCall args[path] to be README.md, got %v", got)
|
|
}
|
|
|
|
toolPart := req.Contents[1].Parts[0]
|
|
if toolPart.FunctionResponse == nil {
|
|
t.Fatal("expected functionResponse in tool message")
|
|
}
|
|
if toolPart.FunctionResponse.Name != "read_file" {
|
|
t.Fatalf("expected functionResponse name read_file, got %q", toolPart.FunctionResponse.Name)
|
|
}
|
|
}
|
|
|
|
func TestParseSSEResponse_SplitsThoughtAndVisibleContent(t *testing.T) {
|
|
p := &AntigravityProvider{}
|
|
body := "data: {\"response\":{\"candidates\":[{\"content\":{\"parts\":[{\"text\":\"hidden reasoning\",\"thought\":true},{\"text\":\"visible answer\"}],\"role\":\"model\"},\"finishReason\":\"STOP\"}],\"usageMetadata\":{\"promptTokenCount\":8,\"candidatesTokenCount\":17,\"totalTokenCount\":216}}}\n" +
|
|
"data: [DONE]\n"
|
|
|
|
resp, err := p.parseSSEResponse(body)
|
|
if err != nil {
|
|
t.Fatalf("parseSSEResponse() error = %v", err)
|
|
}
|
|
|
|
if resp.Content != "visible answer" {
|
|
t.Fatalf("Content = %q, want %q", resp.Content, "visible answer")
|
|
}
|
|
if resp.ReasoningContent != "hidden reasoning" {
|
|
t.Fatalf("ReasoningContent = %q, want %q", resp.ReasoningContent, "hidden reasoning")
|
|
}
|
|
if resp.FinishReason != "stop" {
|
|
t.Fatalf("FinishReason = %q, want %q", resp.FinishReason, "stop")
|
|
}
|
|
if resp.Usage == nil || resp.Usage.TotalTokens != 216 {
|
|
t.Fatalf("Usage.TotalTokens = %v, want %d", resp.Usage, 216)
|
|
}
|
|
}
|
|
|
|
func TestBuildRequest_PreservesComplexToolSchemasByDefault(t *testing.T) {
|
|
p := &AntigravityProvider{}
|
|
schema := map[string]any{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"parent": map[string]any{
|
|
"anyOf": []any{
|
|
map[string]any{"$ref": "#/$defs/pageParent"},
|
|
map[string]any{"$ref": "#/$defs/databaseParent"},
|
|
},
|
|
},
|
|
"icon": map[string]any{
|
|
"anyOf": []any{
|
|
map[string]any{"type": "null"},
|
|
map[string]any{"$ref": "#/$defs/emoji"},
|
|
},
|
|
},
|
|
},
|
|
"$defs": map[string]any{
|
|
"pageParent": map[string]any{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"page_id": map[string]any{"type": "string"},
|
|
},
|
|
"required": []any{"page_id"},
|
|
},
|
|
"databaseParent": map[string]any{
|
|
"type": "object",
|
|
"properties": map[string]any{
|
|
"database_id": map[string]any{"type": "string"},
|
|
},
|
|
"required": []any{"database_id"},
|
|
},
|
|
"emoji": map[string]any{
|
|
"type": "string",
|
|
"pattern": "^:[a-z_]+:$",
|
|
},
|
|
},
|
|
}
|
|
|
|
req := p.buildRequest(
|
|
[]Message{{Role: "user", Content: "hello"}},
|
|
[]ToolDefinition{{
|
|
Type: "function",
|
|
Function: ToolFunctionDefinition{
|
|
Name: "mcp_notion_create",
|
|
Description: "Create a Notion object",
|
|
Parameters: schema,
|
|
},
|
|
}},
|
|
"gemini-3-flash",
|
|
nil,
|
|
)
|
|
|
|
if len(req.Tools) != 1 || len(req.Tools[0].FunctionDeclarations) != 1 {
|
|
t.Fatalf("request tools = %#v, want one function declaration", req.Tools)
|
|
}
|
|
|
|
got, ok := req.Tools[0].FunctionDeclarations[0].Parameters.(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("parameters = %#v, want map", req.Tools[0].FunctionDeclarations[0].Parameters)
|
|
}
|
|
if got["$defs"] == nil {
|
|
t.Fatalf("parameters = %#v, want raw schema with $defs preserved by default", got)
|
|
}
|
|
}
|