Add task sidebar workflow
This commit is contained in:
@@ -119,6 +119,32 @@ func TestToolsListReturnsConcreteSchemas(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestToolsListTaskRegisterWorktreeIsTaskBound(t *testing.T) {
|
||||
unbound := toolsListNames(t, &Server{})
|
||||
if containsString(unbound, "task_register_worktree") {
|
||||
t.Fatalf("unbound tools leaked task_register_worktree: %v", unbound)
|
||||
}
|
||||
s := &Server{}
|
||||
s.SetHost(&blockingToolHost{task: TaskInfo{ID: "task_1", Title: "Fix sidebar"}})
|
||||
bound := toolsListNames(t, s)
|
||||
if !containsString(bound, "task_register_worktree") {
|
||||
t.Fatalf("task-bound tools missing task_register_worktree: %v", bound)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitializeTaskInstructionsAreTaskBound(t *testing.T) {
|
||||
unbound := initializeInstructions(t, &Server{})
|
||||
if strings.Contains(unbound, "task_register_worktree") {
|
||||
t.Fatalf("unbound initialize leaked task instruction: %q", unbound)
|
||||
}
|
||||
s := &Server{}
|
||||
s.SetHost(&blockingToolHost{task: TaskInfo{ID: "task_1", Title: "Fix sidebar"}})
|
||||
bound := initializeInstructions(t, s)
|
||||
if !strings.Contains(bound, "task_register_worktree") {
|
||||
t.Fatalf("task-bound initialize missing worktree instruction: %q", bound)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapToolResultDoesNotDuplicateStructuredJSON(t *testing.T) {
|
||||
result := ProcessOutput{
|
||||
Content: strings.Repeat("x", 1024),
|
||||
@@ -162,6 +188,69 @@ func TestPingReturnsEmptyObject(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func toolsListNames(t *testing.T, s *Server) []string {
|
||||
t.Helper()
|
||||
req := []byte(`{"jsonrpc":"2.0","id":2,"method":"tools/list"}`)
|
||||
resp := s.dispatch("caller", req)
|
||||
if resp == nil {
|
||||
t.Fatal("expected response for tools/list")
|
||||
}
|
||||
var parsed struct {
|
||||
Result struct {
|
||||
Tools []struct {
|
||||
Name string `json:"name"`
|
||||
} `json:"tools"`
|
||||
} `json:"result"`
|
||||
Error *struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(resp, &parsed); err != nil {
|
||||
t.Fatalf("parse tools/list: %v\n%s", err, resp)
|
||||
}
|
||||
if parsed.Error != nil {
|
||||
t.Fatalf("tools/list error: %+v", parsed.Error)
|
||||
}
|
||||
out := make([]string, 0, len(parsed.Result.Tools))
|
||||
for _, tool := range parsed.Result.Tools {
|
||||
out = append(out, tool.Name)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func initializeInstructions(t *testing.T, s *Server) string {
|
||||
t.Helper()
|
||||
req := []byte(`{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}`)
|
||||
resp := s.dispatch("caller", req)
|
||||
if resp == nil {
|
||||
t.Fatal("expected response for initialize")
|
||||
}
|
||||
var parsed struct {
|
||||
Result struct {
|
||||
Instructions string `json:"instructions"`
|
||||
} `json:"result"`
|
||||
Error *struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"error"`
|
||||
}
|
||||
if err := json.Unmarshal(resp, &parsed); err != nil {
|
||||
t.Fatalf("parse initialize: %v\n%s", err, resp)
|
||||
}
|
||||
if parsed.Error != nil {
|
||||
t.Fatalf("initialize error: %+v", parsed.Error)
|
||||
}
|
||||
return parsed.Result.Instructions
|
||||
}
|
||||
|
||||
func containsString(haystack []string, needle string) bool {
|
||||
for _, s := range haystack {
|
||||
if s == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestTypedInvalidArgsMapToInvalidParams(t *testing.T) {
|
||||
for _, errKind := range []string{ErrorKindInvalidArgs, ErrorKindInvalidKind} {
|
||||
_, code, msg, data := mapToolError(Errorf(errKind, "bad args"))
|
||||
|
||||
Reference in New Issue
Block a user