feat(agentic): add issue list filters

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 21:42:09 +00:00
parent b390491b0f
commit 1832728b05
2 changed files with 61 additions and 6 deletions

View file

@ -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))
}

View file

@ -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)