Skip to content

Commit 62266f8

Browse files
mattdhollowaySamMorrowDrumsCopilot
authored
OSS granular PRs and issues toolsets (#2306)
* initial OSS granular PRs and issues toolsets * update docs * refactor: reuse existing helpers in granular toolsets Refactor granular issue and PR tools to delegate to existing tested helper functions instead of reimplementing logic from scratch: - Sub-issue tools (add/remove/reprioritize) now delegate to existing REST-based AddSubIssue, RemoveSubIssue, ReprioritizeSubIssue helpers - PR review tools (create/submit/delete) now delegate to existing CreatePullRequestReview, SubmitPendingPullRequestReview, DeletePendingPullRequestReview helpers (fixes viewer filtering bug) - Review comment tool now uses viewer-safe pattern from AddCommentToPendingReview (query viewer, filter by author, validate PENDING state, pass PullRequestReviewID) - Fix milestone param to use RequiredInt instead of float64 cast - Fix line/startLine params to use OptionalIntParam - Draft state tool uses typed GraphQL inputs matching existing patterns - Remove duplicate GraphQL types and helper functions - Add toolsnap tests for all 20 granular tools - Update generated docs Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: use feature flags instead of separate granular toolsets Place granular tools in existing issues/pull_requests toolsets with FeatureFlagEnable, instead of creating separate issues_granular and pull_requests_granular toolsets. This is simpler and uses the existing feature flag infrastructure to switch between consolidated and granular tool variants at runtime. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address review feedback on granular toolsets - Fix REST response handling: capture resp, close body, use ghErrors helpers in issueUpdateTool, prUpdateTool, GranularCreateIssue, and GranularRequestPullRequestReviewers - Add FeatureFlagDisable on consolidated tools (IssueWrite, SubIssueWrite, UpdatePullRequest, PullRequestReviewWrite, AddCommentToPendingReview) so they are hidden when granular variants are active - Use OptionalStringArrayParam for assignees, labels, reviewers instead of manual loop that silently dropped non-string elements - Fix side/startSide empty string leak: pass nil pointer when absent instead of pointer to empty string in GraphQL mutations - Fix milestone minimum from 0 to 1 to match RequiredInt rejection of 0 - Return MinimalResponse {id, url} instead of full JSON objects - Fix RequiredParam[bool] rejecting draft=false by using presence check - Add handler tests for update_pull_request_draft_state (draft + ready) and add_pull_request_review_comment with full GraphQL mocking Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address review feedback on granular toolsets - Fix translation keys to use ALL_CAPS convention (strings.ToUpper) - Fix assignees/labels clearing: check key presence instead of len==0 - Extract AddCommentToPendingReviewCall helper to deduplicate GraphQL logic between consolidated and granular tools - Add missing granular tools: resolve_review_thread, unresolve_review_thread (were in pull_request_review_write but had no granular replacements) - Add handler tests for new resolve/unresolve tools Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Sam Morrow <info@sam-morrow.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 372c874 commit 62266f8

28 files changed

+3120
-124
lines changed
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Add Pull Request Review Comment"
6+
},
7+
"description": "Add a review comment to the current user's pending pull request review.",
8+
"inputSchema": {
9+
"properties": {
10+
"body": {
11+
"description": "The comment body",
12+
"type": "string"
13+
},
14+
"line": {
15+
"description": "The line number in the diff to comment on (optional)",
16+
"type": "number"
17+
},
18+
"owner": {
19+
"description": "Repository owner (username or organization)",
20+
"type": "string"
21+
},
22+
"path": {
23+
"description": "The relative path of the file to comment on",
24+
"type": "string"
25+
},
26+
"pullNumber": {
27+
"description": "The pull request number",
28+
"minimum": 1,
29+
"type": "number"
30+
},
31+
"repo": {
32+
"description": "Repository name",
33+
"type": "string"
34+
},
35+
"side": {
36+
"description": "The side of the diff to comment on (optional)",
37+
"enum": [
38+
"LEFT",
39+
"RIGHT"
40+
],
41+
"type": "string"
42+
},
43+
"startLine": {
44+
"description": "The start line of a multi-line comment (optional)",
45+
"type": "number"
46+
},
47+
"startSide": {
48+
"description": "The start side of a multi-line comment (optional)",
49+
"enum": [
50+
"LEFT",
51+
"RIGHT"
52+
],
53+
"type": "string"
54+
},
55+
"subjectType": {
56+
"description": "The subject type of the comment",
57+
"enum": [
58+
"FILE",
59+
"LINE"
60+
],
61+
"type": "string"
62+
}
63+
},
64+
"required": [
65+
"owner",
66+
"repo",
67+
"pullNumber",
68+
"path",
69+
"body",
70+
"subjectType"
71+
],
72+
"type": "object"
73+
},
74+
"name": "add_pull_request_review_comment"
75+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Add Sub-Issue"
6+
},
7+
"description": "Add a sub-issue to a parent issue.",
8+
"inputSchema": {
9+
"properties": {
10+
"issue_number": {
11+
"description": "The parent issue number",
12+
"minimum": 1,
13+
"type": "number"
14+
},
15+
"owner": {
16+
"description": "Repository owner (username or organization)",
17+
"type": "string"
18+
},
19+
"replace_parent": {
20+
"description": "If true, reparent the sub-issue if it already has a parent",
21+
"type": "boolean"
22+
},
23+
"repo": {
24+
"description": "Repository name",
25+
"type": "string"
26+
},
27+
"sub_issue_id": {
28+
"description": "The ID of the sub-issue to add. ID is not the same as issue number",
29+
"type": "number"
30+
}
31+
},
32+
"required": [
33+
"owner",
34+
"repo",
35+
"issue_number",
36+
"sub_issue_id"
37+
],
38+
"type": "object"
39+
},
40+
"name": "add_sub_issue"
41+
}

pkg/github/__toolsnaps__/create_issue.snap

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,18 @@
11
{
22
"annotations": {
3-
"title": "Open new issue",
4-
"readOnlyHint": false
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Create Issue"
56
},
6-
"description": "Create a new issue in a GitHub repository.",
7+
"description": "Create a new issue in a GitHub repository with a title and optional body.",
78
"inputSchema": {
89
"properties": {
9-
"assignees": {
10-
"description": "Usernames to assign to this issue",
11-
"items": {
12-
"type": "string"
13-
},
14-
"type": "array"
15-
},
1610
"body": {
17-
"description": "Issue body content",
11+
"description": "Issue body content (optional)",
1812
"type": "string"
1913
},
20-
"labels": {
21-
"description": "Labels to apply to this issue",
22-
"items": {
23-
"type": "string"
24-
},
25-
"type": "array"
26-
},
27-
"milestone": {
28-
"description": "Milestone number",
29-
"type": "number"
30-
},
3114
"owner": {
32-
"description": "Repository owner",
15+
"description": "Repository owner (username or organization)",
3316
"type": "string"
3417
},
3518
"repo": {
@@ -39,10 +22,6 @@
3922
"title": {
4023
"description": "Issue title",
4124
"type": "string"
42-
},
43-
"type": {
44-
"description": "Type of this issue",
45-
"type": "string"
4625
}
4726
},
4827
"required": [
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Create Pull Request Review"
6+
},
7+
"description": "Create a review on a pull request. If event is provided, the review is submitted immediately; otherwise a pending review is created.",
8+
"inputSchema": {
9+
"properties": {
10+
"body": {
11+
"description": "The review body text (optional)",
12+
"type": "string"
13+
},
14+
"commitID": {
15+
"description": "The SHA of the commit to review (optional, defaults to latest)",
16+
"type": "string"
17+
},
18+
"event": {
19+
"description": "The review action to perform. If omitted, creates a pending review.",
20+
"enum": [
21+
"APPROVE",
22+
"REQUEST_CHANGES",
23+
"COMMENT"
24+
],
25+
"type": "string"
26+
},
27+
"owner": {
28+
"description": "Repository owner (username or organization)",
29+
"type": "string"
30+
},
31+
"pullNumber": {
32+
"description": "The pull request number",
33+
"minimum": 1,
34+
"type": "number"
35+
},
36+
"repo": {
37+
"description": "Repository name",
38+
"type": "string"
39+
}
40+
},
41+
"required": [
42+
"owner",
43+
"repo",
44+
"pullNumber"
45+
],
46+
"type": "object"
47+
},
48+
"name": "create_pull_request_review"
49+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": true,
4+
"openWorldHint": true,
5+
"title": "Delete Pending Pull Request Review"
6+
},
7+
"description": "Delete a pending pull request review.",
8+
"inputSchema": {
9+
"properties": {
10+
"owner": {
11+
"description": "Repository owner (username or organization)",
12+
"type": "string"
13+
},
14+
"pullNumber": {
15+
"description": "The pull request number",
16+
"minimum": 1,
17+
"type": "number"
18+
},
19+
"repo": {
20+
"description": "Repository name",
21+
"type": "string"
22+
}
23+
},
24+
"required": [
25+
"owner",
26+
"repo",
27+
"pullNumber"
28+
],
29+
"type": "object"
30+
},
31+
"name": "delete_pending_pull_request_review"
32+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": true,
4+
"openWorldHint": true,
5+
"title": "Remove Sub-Issue"
6+
},
7+
"description": "Remove a sub-issue from a parent issue.",
8+
"inputSchema": {
9+
"properties": {
10+
"issue_number": {
11+
"description": "The parent issue number",
12+
"minimum": 1,
13+
"type": "number"
14+
},
15+
"owner": {
16+
"description": "Repository owner (username or organization)",
17+
"type": "string"
18+
},
19+
"repo": {
20+
"description": "Repository name",
21+
"type": "string"
22+
},
23+
"sub_issue_id": {
24+
"description": "The ID of the sub-issue to remove. ID is not the same as issue number",
25+
"type": "number"
26+
}
27+
},
28+
"required": [
29+
"owner",
30+
"repo",
31+
"issue_number",
32+
"sub_issue_id"
33+
],
34+
"type": "object"
35+
},
36+
"name": "remove_sub_issue"
37+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Reprioritize Sub-Issue"
6+
},
7+
"description": "Reprioritize (reorder) a sub-issue relative to other sub-issues.",
8+
"inputSchema": {
9+
"properties": {
10+
"after_id": {
11+
"description": "The ID of the sub-issue to place this after (either after_id OR before_id should be specified)",
12+
"type": "number"
13+
},
14+
"before_id": {
15+
"description": "The ID of the sub-issue to place this before (either after_id OR before_id should be specified)",
16+
"type": "number"
17+
},
18+
"issue_number": {
19+
"description": "The parent issue number",
20+
"minimum": 1,
21+
"type": "number"
22+
},
23+
"owner": {
24+
"description": "Repository owner (username or organization)",
25+
"type": "string"
26+
},
27+
"repo": {
28+
"description": "Repository name",
29+
"type": "string"
30+
},
31+
"sub_issue_id": {
32+
"description": "The ID of the sub-issue to reorder. ID is not the same as issue number",
33+
"type": "number"
34+
}
35+
},
36+
"required": [
37+
"owner",
38+
"repo",
39+
"issue_number",
40+
"sub_issue_id"
41+
],
42+
"type": "object"
43+
},
44+
"name": "reprioritize_sub_issue"
45+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Request Pull Request Reviewers"
6+
},
7+
"description": "Request reviewers for a pull request.",
8+
"inputSchema": {
9+
"properties": {
10+
"owner": {
11+
"description": "Repository owner (username or organization)",
12+
"type": "string"
13+
},
14+
"pullNumber": {
15+
"description": "The pull request number",
16+
"minimum": 1,
17+
"type": "number"
18+
},
19+
"repo": {
20+
"description": "Repository name",
21+
"type": "string"
22+
},
23+
"reviewers": {
24+
"description": "GitHub usernames to request reviews from",
25+
"items": {
26+
"type": "string"
27+
},
28+
"type": "array"
29+
}
30+
},
31+
"required": [
32+
"owner",
33+
"repo",
34+
"pullNumber",
35+
"reviewers"
36+
],
37+
"type": "object"
38+
},
39+
"name": "request_pull_request_reviewers"
40+
}

0 commit comments

Comments
 (0)