88 lines
3.6 KiB
Go
88 lines
3.6 KiB
Go
package protocol
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
func TestManifestAgentMapsRequestAndResponse(t *testing.T) {
|
|
manifest := []byte(`{
|
|
"apiVersion":"v1",
|
|
"metadata":{"id":"agent-test","version":"1.0.0","name":"Agent Test","vendor":"Test","categories":["text"],"scopes":["agent"],"documentation":"# Agent Test"},
|
|
"create":{"method":"POST","path":"/create"},
|
|
"agent":{"method":"POST","path":"/messages","fields":{"model":"request.model","messages":"request.extra.agent.chatCompletion.messages","tools":"request.extra.agent.chatCompletion.tools","tool_choice":"request.extra.agent.chatCompletion.tool_choice"}},
|
|
"agentResponse":{"textPaths":["choices.0.message.content"],"toolCallsPath":"choices.0.message.tool_calls","toolCallIdPaths":["id"],"toolCallNamePaths":["function.name"],"toolCallArgumentsPaths":["function.arguments"]},
|
|
"response":{}
|
|
}`)
|
|
adapter, err := LoadManifest(manifest)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
agent, ok := adapter.(AgentAdapter)
|
|
if !ok {
|
|
t.Fatal("manifest adapter does not expose AgentAdapter")
|
|
}
|
|
request := map[string]any{
|
|
"chatCompletion": map[string]any{
|
|
"messages": []any{map[string]any{"role": "user", "content": "hello"}},
|
|
"tools": []any{map[string]any{"type": "function"}},
|
|
"tool_choice": "required",
|
|
},
|
|
"responses": map[string]any{},
|
|
}
|
|
spec, err := agent.BuildAgent(context.Background(), AgentRequestContext{Model: "model-a", Request: request})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
body, ok := spec.Body.(map[string]any)
|
|
if !ok || body["model"] != "model-a" {
|
|
t.Fatalf("request body = %#v", spec.Body)
|
|
}
|
|
if _, ok := body["messages"].([]any); !ok {
|
|
t.Fatalf("messages were not mapped: %#v", body)
|
|
}
|
|
result, err := agent.ParseAgent(context.Background(), []byte(`{"choices":[{"message":{"content":"answer","tool_calls":[{"id":"call-1","function":{"name":"search","arguments":"{\"q\":\"x\"}"}}]}}]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.Text != "answer" || len(result.ToolCalls) != 1 || result.ToolCalls[0].Name != "search" {
|
|
t.Fatalf("agent result = %#v", result)
|
|
}
|
|
if !json.Valid([]byte(result.ToolCalls[0].Arguments)) {
|
|
t.Fatalf("tool arguments are not JSON: %q", result.ToolCalls[0].Arguments)
|
|
}
|
|
|
|
result, err = agent.ParseAgent(context.Background(), []byte(`{"choices":[{"message":{"tool_calls":[{"id":"call-2","function":{"name":"search","arguments":{"q":"object"}}}]}}]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := result.ToolCalls[0].Arguments; got != `{"q":"object"}` {
|
|
t.Fatalf("object tool arguments = %q", got)
|
|
}
|
|
}
|
|
|
|
func TestManifestMapsSynchronousTextResponse(t *testing.T) {
|
|
manifest := []byte(`{
|
|
"apiVersion":"v1",
|
|
"metadata":{"id":"text-test","version":"1.0.0","name":"Text Test","vendor":"Test","categories":["text"],"scopes":["canvas"],"documentation":"# Text Test"},
|
|
"create":{"method":"POST","path":"/chat","fields":{"prompt":"request.prompt"}},
|
|
"response":{"textPaths":["choices.0.message.content"],"reasoningPaths":["choices.0.message.reasoning_content"]}
|
|
}`)
|
|
adapter, err := LoadManifest(manifest)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
spec, err := adapter.BuildCreate(context.Background(), RequestContext{Request: GenerationRequest{Prompt: "hello"}})
|
|
if err != nil || spec.Body == nil {
|
|
t.Fatalf("build create = %#v, %v", spec, err)
|
|
}
|
|
result, err := adapter.ParseCreate(context.Background(), []byte(`{"choices":[{"message":{"content":"answer","reasoning_content":"thinking"}}]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.Status != StatusSucceeded || result.Result == nil || result.Result.Text != "answer" || result.Result.Reasoning != "thinking" {
|
|
t.Fatalf("text result = %#v", result)
|
|
}
|
|
}
|