From 454f7a8e96467eb169de562c1dc87b88c7fd215c Mon Sep 17 00:00:00 2001 From: Virgil Date: Tue, 31 Mar 2026 18:55:26 +0000 Subject: [PATCH] feat(agentic): add status filters Co-Authored-By: Virgil --- pkg/agentic/status.go | 46 +++++++++++++++++++++++++++-- pkg/agentic/status_extra_test.go | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/pkg/agentic/status.go b/pkg/agentic/status.go index 9ce11bb..c62e7dc 100644 --- a/pkg/agentic/status.go +++ b/pkg/agentic/status.go @@ -101,7 +101,7 @@ func workspaceStatusValue(result core.Result) (*WorkspaceStatus, bool) { return workspaceStatus, true } -// input := agentic.StatusInput{Workspace: "core/go-io/task-42", Limit: 50} +// input := agentic.StatusInput{Workspace: "core/go-io/task-42", Status: "blocked", Limit: 50} type StatusInput struct { Workspace string `json:"workspace,omitempty"` Limit int `json:"limit,omitempty"` @@ -129,7 +129,7 @@ type BlockedInfo struct { func (s *PrepSubsystem) registerStatusTool(server *mcp.Server) { mcp.AddTool(server, &mcp.Tool{ Name: "agentic_status", - Description: "List agent workspaces and their status (running, completed, blocked, failed). Shows blocked agents with their questions.", + Description: "List agent workspaces and their status (running, completed, blocked, failed). Supports workspace, status, and limit filters. Shows blocked agents with their questions.", }, s.status) } @@ -141,16 +141,30 @@ func (s *PrepSubsystem) status(ctx context.Context, _ *mcp.CallToolRequest, inpu } var statusSummary StatusOutput + matched := 0 for _, statusPath := range statusFiles { workspaceDir := core.PathDir(statusPath) name := WorkspaceName(workspaceDir) + if !statusInputMatchesWorkspace(input.Workspace, workspaceDir, name) { + continue + } result := ReadStatusResult(workspaceDir) workspaceStatus, ok := workspaceStatusValue(result) if !ok { + if input.Status != "" && input.Status != "failed" { + continue + } + if !statusInputMatchesStatus(input.Status, "failed") { + continue + } statusSummary.Total++ statusSummary.Failed++ + matched++ + if input.Limit > 0 && matched >= input.Limit { + break + } continue } @@ -172,6 +186,10 @@ func (s *PrepSubsystem) status(ctx context.Context, _ *mcp.CallToolRequest, inpu } } + if !statusInputMatchesStatus(input.Status, workspaceStatus.Status) { + continue + } + statusSummary.Total++ switch workspaceStatus.Status { case "running": @@ -190,7 +208,31 @@ func (s *PrepSubsystem) status(ctx context.Context, _ *mcp.CallToolRequest, inpu Question: workspaceStatus.Question, }) } + matched++ + if input.Limit > 0 && matched >= input.Limit { + break + } } return nil, statusSummary, nil } + +func statusInputMatchesWorkspace(requested, workspaceDir, workspaceName string) bool { + if requested == "" { + return true + } + if requested == workspaceName { + return true + } + if requested == workspaceDir { + return true + } + return false +} + +func statusInputMatchesStatus(requested, current string) bool { + if requested == "" { + return true + } + return requested == current +} diff --git a/pkg/agentic/status_extra_test.go b/pkg/agentic/status_extra_test.go index 9337570..ca18a53 100644 --- a/pkg/agentic/status_extra_test.go +++ b/pkg/agentic/status_extra_test.go @@ -104,6 +104,56 @@ func TestStatus_MixedWorkspaces_Good(t *testing.T) { assert.Equal(t, "agent", out.Blocked[0].Repo) } +func TestStatus_FilteredWorkspaces_Good(t *testing.T) { + root := t.TempDir() + t.Setenv("CORE_WORKSPACE", root) + wsRoot := core.JoinPath(root, "workspace") + + ws1 := core.JoinPath(wsRoot, "task-1") + require.True(t, fs.EnsureDir(ws1).OK) + require.NoError(t, writeStatus(ws1, &WorkspaceStatus{ + Status: "completed", + Repo: "go-io", + Agent: "codex", + })) + + ws2 := core.JoinPath(wsRoot, "task-2") + require.True(t, fs.EnsureDir(ws2).OK) + require.NoError(t, writeStatus(ws2, &WorkspaceStatus{ + Status: "blocked", + Repo: "go-log", + Agent: "claude", + Question: "Which log format?", + })) + + ws3 := core.JoinPath(wsRoot, "task-3") + require.True(t, fs.EnsureDir(ws3).OK) + require.NoError(t, writeStatus(ws3, &WorkspaceStatus{ + Status: "running", + Repo: "agent", + Agent: "gemini", + })) + + s := &PrepSubsystem{ + ServiceRuntime: core.NewServiceRuntime(testCore, AgentOptions{}), + backoff: make(map[string]time.Time), + failCount: make(map[string]int), + } + + _, out, err := s.status(context.Background(), nil, StatusInput{ + Workspace: "task-2", + Status: "blocked", + Limit: 1, + }) + require.NoError(t, err) + assert.Equal(t, 1, out.Total) + assert.Equal(t, 0, out.Failed) + assert.Equal(t, 0, out.Completed) + assert.Len(t, out.Blocked, 1) + assert.Equal(t, "go-log", out.Blocked[0].Repo) + assert.Equal(t, "Which log format?", out.Blocked[0].Question) +} + func TestStatus_DeepLayout_Good(t *testing.T) { root := t.TempDir() t.Setenv("CORE_WORKSPACE", root)