162 lines
4.8 KiB
Go
162 lines
4.8 KiB
Go
package a2a
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/nomadcode/nomadcode-core/internal/agent"
|
|
)
|
|
|
|
func TestSendMessagePostsJSONRPCMessageSend(t *testing.T) {
|
|
var gotAuth string
|
|
var gotReq jsonRPCRequest
|
|
var gotParams map[string]any
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotAuth = r.Header.Get("Authorization")
|
|
if err := json.NewDecoder(r.Body).Decode(&gotReq); err != nil {
|
|
t.Fatalf("decode request: %v", err)
|
|
}
|
|
paramsBytes, _ := json.Marshal(gotReq.Params)
|
|
if err := json.Unmarshal(paramsBytes, &gotParams); err != nil {
|
|
t.Fatalf("decode params: %v", err)
|
|
}
|
|
_, _ = w.Write([]byte(`{
|
|
"jsonrpc": "2.0",
|
|
"id": "nomadcode-1",
|
|
"result": {
|
|
"kind": "task",
|
|
"id": "task-1",
|
|
"contextId": "ctx-1",
|
|
"status": {"state": "working"}
|
|
}
|
|
}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(Config{URL: server.URL, Token: "secret"}, nil)
|
|
result, err := client.SendMessage(context.Background(), agent.SendMessageInput{
|
|
Text: "fix issue",
|
|
ContextID: "ctx-1",
|
|
AcceptedOutputModes: []string{"text/plain"},
|
|
Blocking: true,
|
|
Metadata: map[string]any{
|
|
"nomad_task_id": "task-local",
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("SendMessage returned error: %v", err)
|
|
}
|
|
|
|
if gotAuth != "Bearer secret" {
|
|
t.Fatalf("unexpected auth header: %q", gotAuth)
|
|
}
|
|
if gotReq.JSONRPC != "2.0" || gotReq.Method != "message/send" || gotReq.ID != "nomadcode-1" {
|
|
t.Fatalf("unexpected json-rpc request: %#v", gotReq)
|
|
}
|
|
message := gotParams["message"].(map[string]any)
|
|
if message["role"] != "user" || message["kind"] != "message" || message["contextId"] != "ctx-1" {
|
|
t.Fatalf("unexpected message: %#v", message)
|
|
}
|
|
parts := message["parts"].([]any)
|
|
part := parts[0].(map[string]any)
|
|
if part["kind"] != "text" || part["text"] != "fix issue" {
|
|
t.Fatalf("unexpected part: %#v", part)
|
|
}
|
|
config := gotParams["configuration"].(map[string]any)
|
|
if config["blocking"] != true {
|
|
t.Fatalf("expected blocking=true, got %#v", config["blocking"])
|
|
}
|
|
metadata := gotParams["metadata"].(map[string]any)
|
|
if metadata["nomad_task_id"] != "task-local" {
|
|
t.Fatalf("unexpected metadata: %#v", metadata)
|
|
}
|
|
if result.Task == nil || result.Task.ID != "task-1" || result.Task.Status.State != agent.TaskStateWorking {
|
|
t.Fatalf("unexpected result: %#v", result)
|
|
}
|
|
}
|
|
|
|
func TestSendMessageReturnsDirectMessage(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
_, _ = w.Write([]byte(`{
|
|
"jsonrpc": "2.0",
|
|
"id": "nomadcode-1",
|
|
"result": {
|
|
"kind": "message",
|
|
"role": "agent",
|
|
"messageId": "msg-2",
|
|
"parts": [{"kind": "text", "text": "done"}]
|
|
}
|
|
}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(Config{URL: server.URL}, nil)
|
|
result, err := client.SendMessage(context.Background(), agent.SendMessageInput{Text: "status"})
|
|
if err != nil {
|
|
t.Fatalf("SendMessage returned error: %v", err)
|
|
}
|
|
if result.Message == nil || result.Message.Role != "agent" || result.Message.Parts[0].Text != "done" {
|
|
t.Fatalf("unexpected result: %#v", result)
|
|
}
|
|
}
|
|
|
|
func TestGetAndCancelTask(t *testing.T) {
|
|
var methods []string
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var req jsonRPCRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
t.Fatalf("decode request: %v", err)
|
|
}
|
|
methods = append(methods, req.Method)
|
|
_, _ = w.Write([]byte(`{
|
|
"jsonrpc": "2.0",
|
|
"id": "` + req.ID + `",
|
|
"result": {
|
|
"kind": "task",
|
|
"id": "task-1",
|
|
"status": {"state": "completed"}
|
|
}
|
|
}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(Config{URL: server.URL}, nil)
|
|
task, err := client.GetTask(context.Background(), agent.GetTaskInput{TaskID: "task-1"})
|
|
if err != nil {
|
|
t.Fatalf("GetTask returned error: %v", err)
|
|
}
|
|
if task.Status.State != agent.TaskStateCompleted {
|
|
t.Fatalf("unexpected get task: %#v", task)
|
|
}
|
|
|
|
task, err = client.CancelTask(context.Background(), agent.CancelTaskInput{TaskID: "task-1"})
|
|
if err != nil {
|
|
t.Fatalf("CancelTask returned error: %v", err)
|
|
}
|
|
if task.ID != "task-1" {
|
|
t.Fatalf("unexpected cancel task: %#v", task)
|
|
}
|
|
if len(methods) != 2 || methods[0] != "tasks/get" || methods[1] != "tasks/cancel" {
|
|
t.Fatalf("unexpected methods: %#v", methods)
|
|
}
|
|
}
|
|
|
|
func TestJSONRPCError(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
_, _ = w.Write([]byte(`{
|
|
"jsonrpc": "2.0",
|
|
"id": "nomadcode-1",
|
|
"error": {"code": -32602, "message": "invalid params"}
|
|
}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewClient(Config{URL: server.URL}, nil)
|
|
if _, err := client.SendMessage(context.Background(), agent.SendMessageInput{Text: "hello"}); err == nil {
|
|
t.Fatal("expected JSON-RPC error")
|
|
}
|
|
}
|