diff --git a/pkg/agentic/issue.go b/pkg/agentic/issue.go index 4a88dd5..329fe59 100644 --- a/pkg/agentic/issue.go +++ b/pkg/agentic/issue.go @@ -56,13 +56,16 @@ type IssueGetInput struct { Slug string `json:"slug,omitempty"` } -// input := agentic.IssueListInput{Status: "open", Type: "bug"} +// input := agentic.IssueListInput{Status: "open", Type: "bug", Priority: "high", Labels: []string{"auth"}} type IssueListInput struct { - Status string `json:"status,omitempty"` - Type string `json:"type,omitempty"` - SprintID int `json:"sprint_id,omitempty"` - SprintSlug string `json:"sprint_slug,omitempty"` - Limit int `json:"limit,omitempty"` + Status string `json:"status,omitempty"` + Type string `json:"type,omitempty"` + Priority string `json:"priority,omitempty"` + Assignee string `json:"assignee,omitempty"` + Labels []string `json:"labels,omitempty"` + SprintID int `json:"sprint_id,omitempty"` + SprintSlug string `json:"sprint_slug,omitempty"` + Limit int `json:"limit,omitempty"` } // input := agentic.IssueUpdateInput{Slug: "fix-auth", Status: "in_progress"} @@ -180,6 +183,9 @@ func (s *PrepSubsystem) handleIssueRecordList(ctx context.Context, options core. _, output, err := s.issueList(ctx, nil, IssueListInput{ Status: optionStringValue(options, "status"), Type: optionStringValue(options, "type"), + Priority: optionStringValue(options, "priority"), + Assignee: optionStringValue(options, "assignee", "agent", "agent_type"), + Labels: optionStringSliceValue(options, "labels"), SprintID: optionIntValue(options, "sprint_id", "sprint-id"), SprintSlug: optionStringValue(options, "sprint_slug", "sprint-slug"), Limit: optionIntValue(options, "limit"), @@ -385,6 +391,9 @@ func (s *PrepSubsystem) issueList(ctx context.Context, _ *mcp.CallToolRequest, i path := "/v1/issues" path = appendQueryParam(path, "status", input.Status) path = appendQueryParam(path, "type", input.Type) + path = appendQueryParam(path, "priority", input.Priority) + path = appendQueryParam(path, "assignee", input.Assignee) + path = appendQuerySlice(path, "labels", input.Labels) if input.SprintID > 0 { path = appendQueryParam(path, "sprint_id", core.Sprint(input.SprintID)) } diff --git a/pkg/agentic/issue_test.go b/pkg/agentic/issue_test.go index e7762e5..2e15334 100644 --- a/pkg/agentic/issue_test.go +++ b/pkg/agentic/issue_test.go @@ -78,6 +78,52 @@ func TestIssue_HandleIssueRecordGet_Good_IDAlias(t *testing.T) { assert.Equal(t, "fix-auth", output.Issue.Slug) } +func TestIssue_HandleIssueRecordList_Good_Filters(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, "/v1/issues", r.URL.Path) + require.Equal(t, "open", r.URL.Query().Get("status")) + require.Equal(t, "bug", r.URL.Query().Get("type")) + require.Equal(t, "high", r.URL.Query().Get("priority")) + require.Equal(t, "codex", r.URL.Query().Get("assignee")) + require.Equal(t, []string{"auth", "backend"}, r.URL.Query()["labels"]) + _, _ = w.Write([]byte(`{"data":{"issues":[{"id":7,"workspace_id":3,"sprint_id":5,"slug":"fix-auth","title":"Fix auth","labels":["auth","backend"]}],"total":1}}`)) + })) + defer server.Close() + + subsystem := testPrepWithPlatformServer(t, server, "secret-token") + result := subsystem.handleIssueRecordList(context.Background(), core.NewOptions( + core.Option{Key: "status", Value: "open"}, + core.Option{Key: "type", Value: "bug"}, + core.Option{Key: "priority", Value: "high"}, + core.Option{Key: "assignee", Value: "codex"}, + core.Option{Key: "labels", Value: []string{"auth", "backend"}}, + )) + require.True(t, result.OK) + + output, ok := result.Value.(IssueListOutput) + require.True(t, ok) + assert.Len(t, output.Issues, 1) + assert.Equal(t, 1, output.Count) + assert.Equal(t, []string{"auth", "backend"}, output.Issues[0].Labels) +} + +func TestIssue_HandleIssueRecordList_Bad_ServerError(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, "/v1/issues", r.URL.Path) + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(`{"error":"backend offline"}`)) + })) + defer server.Close() + + subsystem := testPrepWithPlatformServer(t, server, "secret-token") + result := subsystem.handleIssueRecordList(context.Background(), core.NewOptions( + core.Option{Key: "status", Value: "open"}, + )) + assert.False(t, result.OK) + require.Error(t, result.Value.(error)) + assert.Contains(t, result.Value.(error).Error(), "issue.list") +} + func TestIssue_HandleIssueRecordAssign_Good(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { require.Equal(t, "/v1/issues/fix-auth", r.URL.Path)