@arii/boomtick-mcp 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mcp/schemas/agent.search_ddgs.json +28 -24
- package/.mcp/schemas/agent_search_ddgs.json +31 -0
- package/.mcp/schemas/boomtick.health.json +14 -10
- package/.mcp/schemas/boomtick_health.json +16 -0
- package/.mcp/schemas/github.checkout_branch.json +28 -24
- package/.mcp/schemas/github.comment_triage_summary.json +21 -17
- package/.mcp/schemas/github.create_issue.json +55 -50
- package/.mcp/schemas/github.create_pull_request.json +53 -48
- package/.mcp/schemas/github.get_merge_conflict_files.json +21 -17
- package/.mcp/schemas/github.get_pr.json +30 -12
- package/.mcp/schemas/github.get_pr_diff.json +30 -12
- package/.mcp/schemas/github.issue_comment.json +35 -17
- package/.mcp/schemas/github.issue_update.json +114 -96
- package/.mcp/schemas/github.issue_view.json +30 -12
- package/.mcp/schemas/github.open_replacement_pr.json +64 -60
- package/.mcp/schemas/github.search_open_prs.json +61 -43
- package/.mcp/schemas/github_checkout_branch.json +31 -0
- package/.mcp/schemas/github_comment_triage_summary.json +24 -0
- package/.mcp/schemas/github_create_issue.json +58 -0
- package/.mcp/schemas/github_create_pull_request.json +56 -0
- package/.mcp/schemas/github_get_merge_conflict_files.json +24 -0
- package/.mcp/schemas/github_get_pr.json +32 -0
- package/.mcp/schemas/github_get_pr_diff.json +32 -0
- package/.mcp/schemas/github_issue_comment.json +38 -0
- package/.mcp/schemas/github_issue_update.json +123 -0
- package/.mcp/schemas/github_issue_view.json +32 -0
- package/.mcp/schemas/github_open_replacement_pr.json +67 -0
- package/.mcp/schemas/github_search_open_prs.json +65 -0
- package/.mcp/schemas/jules.cancel_session.json +16 -12
- package/.mcp/schemas/jules.create_session.json +41 -37
- package/.mcp/schemas/jules.get_messages.json +16 -12
- package/.mcp/schemas/jules.get_pr.json +16 -12
- package/.mcp/schemas/jules.get_session.json +16 -12
- package/.mcp/schemas/jules.list_sessions.json +33 -29
- package/.mcp/schemas/jules.send_message.json +30 -26
- package/.mcp/schemas/jules.trigger_feedback.json +16 -12
- package/.mcp/schemas/jules_cancel_session.json +18 -0
- package/.mcp/schemas/jules_create_session.json +44 -0
- package/.mcp/schemas/jules_get_messages.json +18 -0
- package/.mcp/schemas/jules_get_pr.json +18 -0
- package/.mcp/schemas/jules_get_session.json +18 -0
- package/.mcp/schemas/jules_list_sessions.json +36 -0
- package/.mcp/schemas/jules_send_message.json +35 -0
- package/.mcp/schemas/jules_trigger_feedback.json +18 -0
- package/.mcp/schemas/repo.commit_patch.json +34 -30
- package/.mcp/schemas/repo.create_branch.json +21 -17
- package/.mcp/schemas/repo.create_repair_branch.json +34 -30
- package/.mcp/schemas/repo.get_changed_files.json +19 -15
- package/.mcp/schemas/repo.get_command_schema.json +16 -12
- package/.mcp/schemas/repo.get_package_scripts.json +21 -17
- package/.mcp/schemas/repo.get_route_map.json +21 -17
- package/.mcp/schemas/repo.logs.json +28 -24
- package/.mcp/schemas/repo.read_agent_context.json +7 -3
- package/.mcp/schemas/repo.read_ci_logs.json +21 -17
- package/.mcp/schemas/repo.run_lighthouse.json +26 -22
- package/.mcp/schemas/repo.run_playwright.json +33 -29
- package/.mcp/schemas/repo.run_tests.json +40 -36
- package/.mcp/schemas/repo_commit_patch.json +39 -0
- package/.mcp/schemas/repo_create_branch.json +24 -0
- package/.mcp/schemas/repo_create_repair_branch.json +37 -0
- package/.mcp/schemas/repo_get_changed_files.json +22 -0
- package/.mcp/schemas/repo_get_command_schema.json +18 -0
- package/.mcp/schemas/repo_get_package_scripts.json +23 -0
- package/.mcp/schemas/repo_get_route_map.json +23 -0
- package/.mcp/schemas/repo_logs.json +31 -0
- package/.mcp/schemas/repo_read_agent_context.json +9 -0
- package/.mcp/schemas/repo_read_ci_logs.json +24 -0
- package/.mcp/schemas/repo_run_lighthouse.json +29 -0
- package/.mcp/schemas/repo_run_playwright.json +36 -0
- package/.mcp/schemas/repo_run_tests.json +45 -0
- package/CHANGELOG.md +16 -0
- package/dist/config.js +43 -17
- package/dist/config.test.js +18 -3
- package/dist/lib/git.js +30 -0
- package/dist/lib/param_utils.js +35 -0
- package/dist/lib/param_utils.test.js +44 -0
- package/dist/mcp/definitions.js +11 -1
- package/dist/mcp/schemas.test.js +28 -0
- package/dist/mcp/server.js +72 -36
- package/dist/tools/contract.js +94 -8
- package/dist/tools/github.create_issue.js +3 -2
- package/dist/tools/github.create_issue.test.js +10 -0
- package/dist/tools/github.create_pull_request.js +4 -4
- package/dist/tools/github.get_pr.js +4 -1
- package/dist/tools/github.get_pr_diff.js +6 -2
- package/dist/tools/github.issue_comment.js +8 -1
- package/dist/tools/github.issue_update.js +3 -0
- package/dist/tools/github.issue_view.js +4 -1
- package/dist/tools/github.search_open_prs.js +4 -0
- package/dist/tools/repo.commit_patch.js +30 -10
- package/dist/tools/repo.run_playwright.js +10 -5
- package/dist/tools/repo.run_tests.js +26 -4
- package/package.json +2 -2
- package/scripts/sync-mcp-schemas.ts +6 -1
- package/src/config.test.ts +22 -3
- package/src/config.ts +47 -17
- package/src/lib/git.ts +34 -0
- package/src/lib/param_utils.test.ts +49 -0
- package/src/lib/param_utils.ts +42 -0
- package/src/mcp/definitions.ts +12 -1
- package/src/mcp/schemas.test.ts +34 -0
- package/src/mcp/server.ts +73 -38
- package/src/tools/contract.ts +94 -8
- package/src/tools/github.create_issue.test.ts +10 -0
- package/src/tools/github.create_issue.ts +3 -1
- package/src/tools/github.create_pull_request.ts +4 -5
- package/src/tools/github.get_pr.ts +4 -1
- package/src/tools/github.get_pr_diff.ts +7 -2
- package/src/tools/github.issue_comment.ts +8 -1
- package/src/tools/github.issue_update.ts +4 -1
- package/src/tools/github.issue_view.ts +4 -1
- package/src/tools/github.search_open_prs.ts +4 -0
- package/src/tools/repo.commit_patch.ts +35 -11
- package/src/tools/repo.run_playwright.ts +13 -6
- package/src/tools/repo.run_tests.ts +28 -5
package/src/tools/contract.ts
CHANGED
|
@@ -1228,7 +1228,7 @@ export const CreateBranchInputJsonSchema = {
|
|
|
1228
1228
|
"type": "object"
|
|
1229
1229
|
} as const;
|
|
1230
1230
|
|
|
1231
|
-
export const CreateIssueInputSchema = z.object({ "title": z.string().min(1), "body": z.union([z.string().min(1), z.null()]).default(null), "file": z.union([z.string().min(1), z.null()]).default(null), "repo": z.union([z.string(), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1231
|
+
export const CreateIssueInputSchema = z.object({ "title": z.string().min(1), "body": z.union([z.string().min(1), z.null()]).default(null), "file": z.union([z.string().min(1), z.null()]).default(null), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1232
1232
|
|
|
1233
1233
|
export type CreateIssueInput = z.infer<typeof CreateIssueInputSchema>;
|
|
1234
1234
|
|
|
@@ -1268,6 +1268,7 @@ export const CreateIssueInputJsonSchema = {
|
|
|
1268
1268
|
"repo": {
|
|
1269
1269
|
"anyOf": [
|
|
1270
1270
|
{
|
|
1271
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1271
1272
|
"type": "string"
|
|
1272
1273
|
},
|
|
1273
1274
|
{
|
|
@@ -1410,7 +1411,7 @@ export const CreateJulesSessionInputJsonSchema = {
|
|
|
1410
1411
|
"type": "object"
|
|
1411
1412
|
} as const;
|
|
1412
1413
|
|
|
1413
|
-
export const CreatePullRequestInputSchema = z.object({ "title": z.string().describe("PR Title."), "body": z.string().describe("Description of changes."), "head": z.string().describe("The branch containing changes to merge."), "base": z.string().describe("The target branch to merge into.").default("main"), "draft": z.boolean().describe("Whether to create the PR as a draft.").default(false), "repo": z.union([z.string(), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1414
|
+
export const CreatePullRequestInputSchema = z.object({ "title": z.string().describe("PR Title."), "body": z.string().describe("Description of changes."), "head": z.string().describe("The branch containing changes to merge."), "base": z.string().describe("The target branch to merge into.").default("main"), "draft": z.boolean().describe("Whether to create the PR as a draft.").default(false), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1414
1415
|
|
|
1415
1416
|
export type CreatePullRequestInput = z.infer<typeof CreatePullRequestInputSchema>;
|
|
1416
1417
|
|
|
@@ -1446,6 +1447,7 @@ export const CreatePullRequestInputJsonSchema = {
|
|
|
1446
1447
|
"repo": {
|
|
1447
1448
|
"anyOf": [
|
|
1448
1449
|
{
|
|
1450
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1449
1451
|
"type": "string"
|
|
1450
1452
|
},
|
|
1451
1453
|
{
|
|
@@ -1595,7 +1597,7 @@ export const GetPackageScriptsInputJsonSchema = {
|
|
|
1595
1597
|
"type": "object"
|
|
1596
1598
|
} as const;
|
|
1597
1599
|
|
|
1598
|
-
export const GetPrDiffInputSchema = z.object({ "prNumber": z.number().int().describe("The number of the pull request to get the diff for.") });
|
|
1600
|
+
export const GetPrDiffInputSchema = z.object({ "prNumber": z.number().int().describe("The number of the pull request to get the diff for."), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1599
1601
|
|
|
1600
1602
|
export type GetPrDiffInput = z.infer<typeof GetPrDiffInputSchema>;
|
|
1601
1603
|
|
|
@@ -1605,6 +1607,20 @@ export const GetPrDiffInputJsonSchema = {
|
|
|
1605
1607
|
"description": "The number of the pull request to get the diff for.",
|
|
1606
1608
|
"title": "Prnumber",
|
|
1607
1609
|
"type": "integer"
|
|
1610
|
+
},
|
|
1611
|
+
"repo": {
|
|
1612
|
+
"anyOf": [
|
|
1613
|
+
{
|
|
1614
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1615
|
+
"type": "string"
|
|
1616
|
+
},
|
|
1617
|
+
{
|
|
1618
|
+
"type": "null"
|
|
1619
|
+
}
|
|
1620
|
+
],
|
|
1621
|
+
"default": null,
|
|
1622
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
1623
|
+
"title": "Repo"
|
|
1608
1624
|
}
|
|
1609
1625
|
},
|
|
1610
1626
|
"required": [
|
|
@@ -1614,7 +1630,7 @@ export const GetPrDiffInputJsonSchema = {
|
|
|
1614
1630
|
"type": "object"
|
|
1615
1631
|
} as const;
|
|
1616
1632
|
|
|
1617
|
-
export const GetPrInputSchema = z.object({ "prNumber": z.number().int().describe("The number of the PR to view.") });
|
|
1633
|
+
export const GetPrInputSchema = z.object({ "prNumber": z.number().int().describe("The number of the PR to view."), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1618
1634
|
|
|
1619
1635
|
export type GetPrInput = z.infer<typeof GetPrInputSchema>;
|
|
1620
1636
|
|
|
@@ -1624,6 +1640,20 @@ export const GetPrInputJsonSchema = {
|
|
|
1624
1640
|
"description": "The number of the PR to view.",
|
|
1625
1641
|
"title": "Prnumber",
|
|
1626
1642
|
"type": "integer"
|
|
1643
|
+
},
|
|
1644
|
+
"repo": {
|
|
1645
|
+
"anyOf": [
|
|
1646
|
+
{
|
|
1647
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1648
|
+
"type": "string"
|
|
1649
|
+
},
|
|
1650
|
+
{
|
|
1651
|
+
"type": "null"
|
|
1652
|
+
}
|
|
1653
|
+
],
|
|
1654
|
+
"default": null,
|
|
1655
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
1656
|
+
"title": "Repo"
|
|
1627
1657
|
}
|
|
1628
1658
|
},
|
|
1629
1659
|
"required": [
|
|
@@ -1674,7 +1704,7 @@ export const HealthCheckInputJsonSchema = {
|
|
|
1674
1704
|
"type": "object"
|
|
1675
1705
|
} as const;
|
|
1676
1706
|
|
|
1677
|
-
export const IssueCommentInputSchema = z.object({ "issueNumber": z.number().int().describe("The number of the issue to comment on."), "body": z.string().describe("The content of the comment.") });
|
|
1707
|
+
export const IssueCommentInputSchema = z.object({ "issueNumber": z.number().int().describe("The number of the issue to comment on."), "body": z.string().describe("The content of the comment."), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1678
1708
|
|
|
1679
1709
|
export type IssueCommentInput = z.infer<typeof IssueCommentInputSchema>;
|
|
1680
1710
|
|
|
@@ -1689,6 +1719,20 @@ export const IssueCommentInputJsonSchema = {
|
|
|
1689
1719
|
"description": "The content of the comment.",
|
|
1690
1720
|
"title": "Body",
|
|
1691
1721
|
"type": "string"
|
|
1722
|
+
},
|
|
1723
|
+
"repo": {
|
|
1724
|
+
"anyOf": [
|
|
1725
|
+
{
|
|
1726
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1727
|
+
"type": "string"
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
"type": "null"
|
|
1731
|
+
}
|
|
1732
|
+
],
|
|
1733
|
+
"default": null,
|
|
1734
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
1735
|
+
"title": "Repo"
|
|
1692
1736
|
}
|
|
1693
1737
|
},
|
|
1694
1738
|
"required": [
|
|
@@ -1732,7 +1776,7 @@ export const IssueSummaryJsonSchema = {
|
|
|
1732
1776
|
"type": "object"
|
|
1733
1777
|
} as const;
|
|
1734
1778
|
|
|
1735
|
-
export const IssueUpdateInputSchema = z.object({ "issueNumber": z.number().int().describe("The number of the issue to update."), "body": z.union([z.string(), z.null()]).describe("The new body content for the issue.").default(null), "file": z.union([z.string(), z.null()]).describe("Path to file containing new issue body.").default(null), "labels": z.union([z.array(z.string()), z.null()]).describe("Comma-separated list of labels to set.").default(null), "addLabels": z.union([z.array(z.string()), z.null()]).describe("Comma-separated list of labels to add.").default(null), "removeLabels": z.union([z.array(z.string()), z.null()]).describe("Comma-separated list of labels to remove.").default(null), "state": z.union([z.enum(["open","closed"]), z.null()]).describe("The state to set the issue to.").default(null) });
|
|
1779
|
+
export const IssueUpdateInputSchema = z.object({ "issueNumber": z.number().int().describe("The number of the issue to update."), "body": z.union([z.string(), z.null()]).describe("The new body content for the issue.").default(null), "file": z.union([z.string(), z.null()]).describe("Path to file containing new issue body.").default(null), "labels": z.union([z.array(z.string()), z.null()]).describe("Comma-separated list of labels to set.").default(null), "addLabels": z.union([z.array(z.string()), z.null()]).describe("Comma-separated list of labels to add.").default(null), "removeLabels": z.union([z.array(z.string()), z.null()]).describe("Comma-separated list of labels to remove.").default(null), "state": z.union([z.enum(["open","closed"]), z.null()]).describe("The state to set the issue to.").default(null), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1736
1780
|
|
|
1737
1781
|
export type IssueUpdateInput = z.infer<typeof IssueUpdateInputSchema>;
|
|
1738
1782
|
|
|
@@ -1833,6 +1877,20 @@ export const IssueUpdateInputJsonSchema = {
|
|
|
1833
1877
|
"default": null,
|
|
1834
1878
|
"description": "The state to set the issue to.",
|
|
1835
1879
|
"title": "State"
|
|
1880
|
+
},
|
|
1881
|
+
"repo": {
|
|
1882
|
+
"anyOf": [
|
|
1883
|
+
{
|
|
1884
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1885
|
+
"type": "string"
|
|
1886
|
+
},
|
|
1887
|
+
{
|
|
1888
|
+
"type": "null"
|
|
1889
|
+
}
|
|
1890
|
+
],
|
|
1891
|
+
"default": null,
|
|
1892
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
1893
|
+
"title": "Repo"
|
|
1836
1894
|
}
|
|
1837
1895
|
},
|
|
1838
1896
|
"required": [
|
|
@@ -1921,7 +1979,7 @@ export const IssueUpdateResponseJsonSchema = {
|
|
|
1921
1979
|
"type": "object"
|
|
1922
1980
|
} as const;
|
|
1923
1981
|
|
|
1924
|
-
export const IssueViewInputSchema = z.object({ "issueNumber": z.number().int().describe("The number of the issue to view.") });
|
|
1982
|
+
export const IssueViewInputSchema = z.object({ "issueNumber": z.number().int().describe("The number of the issue to view."), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
1925
1983
|
|
|
1926
1984
|
export type IssueViewInput = z.infer<typeof IssueViewInputSchema>;
|
|
1927
1985
|
|
|
@@ -1931,6 +1989,20 @@ export const IssueViewInputJsonSchema = {
|
|
|
1931
1989
|
"description": "The number of the issue to view.",
|
|
1932
1990
|
"title": "Issuenumber",
|
|
1933
1991
|
"type": "integer"
|
|
1992
|
+
},
|
|
1993
|
+
"repo": {
|
|
1994
|
+
"anyOf": [
|
|
1995
|
+
{
|
|
1996
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
1997
|
+
"type": "string"
|
|
1998
|
+
},
|
|
1999
|
+
{
|
|
2000
|
+
"type": "null"
|
|
2001
|
+
}
|
|
2002
|
+
],
|
|
2003
|
+
"default": null,
|
|
2004
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
2005
|
+
"title": "Repo"
|
|
1934
2006
|
}
|
|
1935
2007
|
},
|
|
1936
2008
|
"required": [
|
|
@@ -2998,7 +3070,7 @@ export const SearchDdgsInputJsonSchema = {
|
|
|
2998
3070
|
"type": "object"
|
|
2999
3071
|
} as const;
|
|
3000
3072
|
|
|
3001
|
-
export const SearchPRsInputSchema = z.object({ "state": z.enum(["open","closed","all"]).describe("The state of the PRs to search for.").default("open"), "limit": z.number().int().gte(1).lte(100).describe("The maximum number of PRs to return (default: 100, range: 1-100).").default(100), "includeDrafts": z.boolean().describe("Whether to include draft PRs in the results.").default(true), "labels": z.union([z.array(z.string()), z.null()]).describe("Filter PRs by labels.").default(null) });
|
|
3073
|
+
export const SearchPRsInputSchema = z.object({ "state": z.enum(["open","closed","all"]).describe("The state of the PRs to search for.").default("open"), "limit": z.number().int().gte(1).lte(100).describe("The maximum number of PRs to return (default: 100, range: 1-100).").default(100), "includeDrafts": z.boolean().describe("Whether to include draft PRs in the results.").default(true), "labels": z.union([z.array(z.string()), z.null()]).describe("Filter PRs by labels.").default(null), "repo": z.union([z.string().regex(new RegExp("^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$")), z.null()]).describe("The target repository override (e.g. org/repo).").default(null) });
|
|
3002
3074
|
|
|
3003
3075
|
export type SearchPRsInput = z.infer<typeof SearchPRsInputSchema>;
|
|
3004
3076
|
|
|
@@ -3044,6 +3116,20 @@ export const SearchPRsInputJsonSchema = {
|
|
|
3044
3116
|
"default": null,
|
|
3045
3117
|
"description": "Filter PRs by labels.",
|
|
3046
3118
|
"title": "Labels"
|
|
3119
|
+
},
|
|
3120
|
+
"repo": {
|
|
3121
|
+
"anyOf": [
|
|
3122
|
+
{
|
|
3123
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
3124
|
+
"type": "string"
|
|
3125
|
+
},
|
|
3126
|
+
{
|
|
3127
|
+
"type": "null"
|
|
3128
|
+
}
|
|
3129
|
+
],
|
|
3130
|
+
"default": null,
|
|
3131
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
3132
|
+
"title": "Repo"
|
|
3047
3133
|
}
|
|
3048
3134
|
},
|
|
3049
3135
|
"title": "SearchPRsInput",
|
|
@@ -27,6 +27,16 @@ describe("github.create_issue", () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
const result = await createIssueHandler({ title: "Test Issue", body: "Test Body", file: null, repo: null });
|
|
30
|
+
expect(shell.runCommand).toHaveBeenCalledWith("td-cli", [
|
|
31
|
+
"gh",
|
|
32
|
+
"create-issue",
|
|
33
|
+
"--title",
|
|
34
|
+
"Test Issue",
|
|
35
|
+
"--body",
|
|
36
|
+
"Test Body",
|
|
37
|
+
"--repo",
|
|
38
|
+
expect.any(String)
|
|
39
|
+
]);
|
|
30
40
|
expect(result.status).toBe("success");
|
|
31
41
|
expect(result.issue?.number).toBe(123);
|
|
32
42
|
expect(result.issue?.title).toBe("Test Issue");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
import { sanitizeError } from "../lib/error_utils.js";
|
|
4
5
|
import { CreateIssueInputSchema, CreateIssueResponseSchema } from "./contract.js";
|
|
5
6
|
|
|
@@ -7,11 +8,12 @@ export { CreateIssueInputSchema };
|
|
|
7
8
|
|
|
8
9
|
export async function createIssueHandler(args: z.input<typeof CreateIssueInputSchema>) {
|
|
9
10
|
const params = CreateIssueInputSchema.parse(args);
|
|
11
|
+
const targetRepo = resolveRepo(params.repo);
|
|
10
12
|
|
|
11
13
|
const cmdArgs = ["gh", "create-issue", "--title", params.title];
|
|
12
14
|
if (params.body) cmdArgs.push("--body", params.body);
|
|
13
15
|
if (params.file) cmdArgs.push("--file", params.file);
|
|
14
|
-
|
|
16
|
+
cmdArgs.push("--repo", targetRepo);
|
|
15
17
|
|
|
16
18
|
const result = await runCommand("td-cli", cmdArgs);
|
|
17
19
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
import { CreatePullRequestInputSchema } from "./contract.js";
|
|
4
5
|
|
|
5
6
|
export { CreatePullRequestInputSchema };
|
|
6
7
|
|
|
7
8
|
export async function createPullRequestHandler(args: z.input<typeof CreatePullRequestInputSchema>) {
|
|
8
9
|
const params = CreatePullRequestInputSchema.parse(args);
|
|
10
|
+
const targetRepo = resolveRepo(params.repo);
|
|
9
11
|
|
|
10
12
|
const tdArgs = [
|
|
11
13
|
"gh",
|
|
@@ -13,17 +15,14 @@ export async function createPullRequestHandler(args: z.input<typeof CreatePullRe
|
|
|
13
15
|
"--title", params.title,
|
|
14
16
|
"--body", params.body,
|
|
15
17
|
"--head", params.head,
|
|
16
|
-
"--base", params.base
|
|
18
|
+
"--base", params.base,
|
|
19
|
+
"--repo", targetRepo
|
|
17
20
|
];
|
|
18
21
|
|
|
19
22
|
if (params.draft) {
|
|
20
23
|
tdArgs.push("--draft");
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
if (params.repo) {
|
|
24
|
-
tdArgs.push("--repo", params.repo);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
26
|
const result = await runCommand("td-cli", tdArgs);
|
|
28
27
|
|
|
29
28
|
if (result.exitCode !== 0) {
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
import { sanitizeError } from "../lib/error_utils.js";
|
|
4
5
|
|
|
5
6
|
export const GetPrInputSchema = z.object({
|
|
6
7
|
prNumber: z.number().describe("The number of the PR to view."),
|
|
8
|
+
repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
|
|
7
9
|
});
|
|
8
10
|
|
|
9
11
|
export async function getPrHandler(args: z.infer<typeof GetPrInputSchema>) {
|
|
10
12
|
const params = GetPrInputSchema.parse(args);
|
|
13
|
+
const targetRepo = resolveRepo(params.repo);
|
|
11
14
|
|
|
12
|
-
const result = await runCommand("td-cli", ["gh", "view", params.prNumber.toString()]);
|
|
15
|
+
const result = await runCommand("td-cli", ["gh", "view", params.prNumber.toString(), "--repo", targetRepo]);
|
|
13
16
|
|
|
14
17
|
if (result.exitCode !== 0) {
|
|
15
18
|
throw new Error(`Failed to get PR details: ${sanitizeError(result.stderr)}`);
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
|
|
4
5
|
export const GetPrDiffInputSchema = z.object({
|
|
5
|
-
prNumber: z.number(),
|
|
6
|
+
prNumber: z.number().describe("The number of the pull request to get the diff for."),
|
|
7
|
+
repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
|
|
6
8
|
});
|
|
7
9
|
|
|
8
10
|
export async function getPrDiffHandler(args: z.infer<typeof GetPrDiffInputSchema>) {
|
|
11
|
+
const params = GetPrDiffInputSchema.parse(args);
|
|
12
|
+
const targetRepo = resolveRepo(params.repo);
|
|
13
|
+
|
|
9
14
|
const result = await runCommand("td-cli", [
|
|
10
|
-
"gh", "pr-diff",
|
|
15
|
+
"gh", "pr-diff", params.prNumber.toString(), "--repo", targetRepo
|
|
11
16
|
]);
|
|
12
17
|
|
|
13
18
|
if (result.exitCode !== 0) {
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
import { sanitizeError } from "../lib/error_utils.js";
|
|
4
5
|
|
|
5
6
|
export const IssueCommentInputSchema = z.object({
|
|
6
7
|
issueNumber: z.number().describe("The number of the issue to comment on."),
|
|
7
8
|
body: z.string().min(1, "Comment body cannot be empty").describe("The content of the comment."),
|
|
9
|
+
repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
|
|
8
10
|
});
|
|
9
11
|
|
|
10
12
|
const IssueCommentOutputSchema = z.object({
|
|
@@ -15,8 +17,13 @@ const IssueCommentOutputSchema = z.object({
|
|
|
15
17
|
|
|
16
18
|
export async function issueCommentHandler(args: z.infer<typeof IssueCommentInputSchema>) {
|
|
17
19
|
const params = IssueCommentInputSchema.parse(args);
|
|
20
|
+
const targetRepo = resolveRepo(params.repo);
|
|
18
21
|
|
|
19
|
-
const result = await runCommand("td-cli", [
|
|
22
|
+
const result = await runCommand("td-cli", [
|
|
23
|
+
"gh", "issue-comment", params.issueNumber.toString(),
|
|
24
|
+
"--body", params.body,
|
|
25
|
+
"--repo", targetRepo
|
|
26
|
+
]);
|
|
20
27
|
|
|
21
28
|
if (result.exitCode !== 0) {
|
|
22
29
|
throw new Error(`Failed to post comment: ${sanitizeError(result.stderr)}`);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
import { sanitizeError } from "../lib/error_utils.js";
|
|
4
5
|
import { IssueUpdateInputSchema, IssueUpdateResponseSchema } from "./contract.js";
|
|
5
6
|
|
|
6
7
|
export { IssueUpdateInputSchema };
|
|
7
8
|
|
|
8
|
-
export async function issueUpdateHandler(args:
|
|
9
|
+
export async function issueUpdateHandler(args: z.infer<typeof IssueUpdateInputSchema>) {
|
|
9
10
|
const params = IssueUpdateInputSchema.parse(args);
|
|
11
|
+
const targetRepo = resolveRepo(params.repo);
|
|
10
12
|
|
|
11
13
|
const cmdArgs = ["gh", "issue-update", params.issueNumber.toString()];
|
|
12
14
|
if (params.body) cmdArgs.push("--body", params.body);
|
|
@@ -15,6 +17,7 @@ export async function issueUpdateHandler(args: any) {
|
|
|
15
17
|
if (params.addLabels && params.addLabels.length > 0) cmdArgs.push("--add-labels", params.addLabels.join(","));
|
|
16
18
|
if (params.removeLabels && params.removeLabels.length > 0) cmdArgs.push("--remove-labels", params.removeLabels.join(","));
|
|
17
19
|
if (params.state) cmdArgs.push("--state", params.state);
|
|
20
|
+
cmdArgs.push("--repo", targetRepo);
|
|
18
21
|
|
|
19
22
|
const result = await runCommand("td-cli", cmdArgs);
|
|
20
23
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
import { sanitizeError } from "../lib/error_utils.js";
|
|
4
5
|
|
|
5
6
|
export const IssueViewInputSchema = z.object({
|
|
6
7
|
issueNumber: z.number().describe("The number of the issue to view."),
|
|
8
|
+
repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
|
|
7
9
|
});
|
|
8
10
|
|
|
9
11
|
const IssueViewOutputSchema = z.object({
|
|
@@ -19,8 +21,9 @@ const IssueViewOutputSchema = z.object({
|
|
|
19
21
|
|
|
20
22
|
export async function issueViewHandler(args: z.infer<typeof IssueViewInputSchema>) {
|
|
21
23
|
const params = IssueViewInputSchema.parse(args);
|
|
24
|
+
const targetRepo = resolveRepo(params.repo);
|
|
22
25
|
|
|
23
|
-
const result = await runCommand("td-cli", ["gh", "issue-view", params.issueNumber.toString()]);
|
|
26
|
+
const result = await runCommand("td-cli", ["gh", "issue-view", params.issueNumber.toString(), "--repo", targetRepo]);
|
|
24
27
|
|
|
25
28
|
if (result.exitCode !== 0) {
|
|
26
29
|
throw new Error(`Failed to view issue: ${sanitizeError(result.stderr)}`);
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { resolveRepo } from "../lib/git.js";
|
|
3
4
|
|
|
4
5
|
export const SearchOpenPrsInputSchema = z.object({
|
|
5
6
|
state: z.enum(["open", "closed", "all"]).optional().default("open"),
|
|
6
7
|
includeDrafts: z.boolean().optional().default(true),
|
|
7
8
|
limit: z.number().min(1).max(100).optional().default(100),
|
|
8
9
|
labels: z.array(z.string()).optional(),
|
|
10
|
+
repo: z.string().optional().describe("The target repository override (e.g. org/repo)."),
|
|
9
11
|
});
|
|
10
12
|
|
|
11
13
|
export async function searchOpenPrsHandler(args: z.infer<typeof SearchOpenPrsInputSchema>) {
|
|
12
14
|
const params = SearchOpenPrsInputSchema.parse(args);
|
|
15
|
+
const targetRepo = resolveRepo(params.repo);
|
|
13
16
|
|
|
14
17
|
const tdArgs = [
|
|
15
18
|
"gh", "search-prs",
|
|
16
19
|
"--state", params.state,
|
|
17
20
|
"--limit", params.limit.toString(),
|
|
21
|
+
"--repo", targetRepo,
|
|
18
22
|
];
|
|
19
23
|
|
|
20
24
|
if (!params.includeDrafts) {
|
|
@@ -1,21 +1,45 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { runCommand } from "../lib/shell.js";
|
|
3
|
+
import { config } from "../config.js";
|
|
3
4
|
|
|
4
5
|
export const CommitPatchInputSchema = z.object({
|
|
5
|
-
worktreePath: z.string(),
|
|
6
|
+
worktreePath: z.string().optional(),
|
|
6
7
|
message: z.string(),
|
|
7
8
|
allowedFiles: z.array(z.string()),
|
|
8
|
-
writeMode: z.boolean().optional().default(
|
|
9
|
+
writeMode: z.boolean().optional().default(true),
|
|
9
10
|
});
|
|
10
11
|
|
|
11
|
-
export
|
|
12
|
-
|
|
12
|
+
export type CommitPatchInput = z.input<typeof CommitPatchInputSchema>;
|
|
13
|
+
|
|
14
|
+
export async function commitPatchHandler(args: CommitPatchInput) {
|
|
15
|
+
const parsed = CommitPatchInputSchema.parse(args || {});
|
|
16
|
+
const worktreePath = parsed.worktreePath || config.repoPath;
|
|
17
|
+
|
|
18
|
+
if (parsed.writeMode === false) {
|
|
13
19
|
throw new Error("writeMode must be true to commit changes.");
|
|
14
20
|
}
|
|
15
|
-
const statusResult = await runCommand("git", ["status", "--porcelain"], { cwd: args.worktreePath });
|
|
16
|
-
const changedFiles = statusResult.stdout.trim().split("\n").filter(l => l.length > 0).map(l => l.substring(3));
|
|
17
21
|
|
|
18
|
-
const
|
|
22
|
+
const statusResult = await runCommand("git", ["status", "--porcelain"], { cwd: worktreePath });
|
|
23
|
+
|
|
24
|
+
const changedFiles = statusResult.stdout
|
|
25
|
+
.split("\n")
|
|
26
|
+
.map((l) => (l.endsWith("\r") ? l.slice(0, -1) : l))
|
|
27
|
+
.filter((l) => l.trim().length > 0)
|
|
28
|
+
.map((l) => {
|
|
29
|
+
const match = l.match(/^..\s+(.*)$/);
|
|
30
|
+
if (!match) return l.slice(3).trim();
|
|
31
|
+
let file = match[1].trim();
|
|
32
|
+
if (file.includes(" -> ")) {
|
|
33
|
+
file = file.split(" -> ").pop()!.trim();
|
|
34
|
+
}
|
|
35
|
+
if (file.startsWith('"') && file.endsWith('"')) {
|
|
36
|
+
file = file.slice(1, -1);
|
|
37
|
+
}
|
|
38
|
+
return file;
|
|
39
|
+
})
|
|
40
|
+
.filter(Boolean);
|
|
41
|
+
|
|
42
|
+
const forbiddenFiles = changedFiles.filter((f) => !parsed.allowedFiles.includes(f));
|
|
19
43
|
if (forbiddenFiles.length > 0) {
|
|
20
44
|
throw new Error(`The following files are not in the allowed list: ${forbiddenFiles.join(", ")}`);
|
|
21
45
|
}
|
|
@@ -24,18 +48,18 @@ export async function commitPatchHandler(args: z.infer<typeof CommitPatchInputSc
|
|
|
24
48
|
throw new Error("No changes to commit.");
|
|
25
49
|
}
|
|
26
50
|
|
|
27
|
-
await runCommand("git", ["add", "
|
|
28
|
-
const commitResult = await runCommand("git", ["commit", "-m",
|
|
51
|
+
await runCommand("git", ["add", "--", ...changedFiles], { cwd: worktreePath });
|
|
52
|
+
const commitResult = await runCommand("git", ["commit", "-m", parsed.message], { cwd: worktreePath });
|
|
29
53
|
|
|
30
54
|
if (commitResult.exitCode !== 0) {
|
|
31
55
|
throw new Error(`Failed to commit: ${commitResult.stderr}`);
|
|
32
56
|
}
|
|
33
57
|
|
|
34
|
-
const shaResult = await runCommand("git", ["rev-parse", "HEAD"], { cwd:
|
|
58
|
+
const shaResult = await runCommand("git", ["rev-parse", "HEAD"], { cwd: worktreePath });
|
|
35
59
|
|
|
36
60
|
return {
|
|
37
61
|
success: true,
|
|
38
62
|
commitSha: shaResult.stdout.trim(),
|
|
39
|
-
changedFiles
|
|
63
|
+
changedFiles,
|
|
40
64
|
};
|
|
41
65
|
}
|
|
@@ -4,18 +4,25 @@ import { runCommand } from "../lib/shell.js";
|
|
|
4
4
|
export const RunPlaywrightInputSchema = z.object({
|
|
5
5
|
grep: z.string().optional(),
|
|
6
6
|
worktreePath: z.string().optional(),
|
|
7
|
+
timeoutSeconds: z.number().optional().default(180),
|
|
7
8
|
});
|
|
8
9
|
|
|
9
|
-
export
|
|
10
|
+
export type RunPlaywrightInput = z.input<typeof RunPlaywrightInputSchema>;
|
|
11
|
+
|
|
12
|
+
export async function runPlaywrightHandler(args: RunPlaywrightInput) {
|
|
13
|
+
const parsed = RunPlaywrightInputSchema.parse(args || {});
|
|
10
14
|
const tdArgs = ["repo", "run-playwright"];
|
|
11
|
-
if (
|
|
12
|
-
tdArgs.push("--grep",
|
|
15
|
+
if (parsed.grep) {
|
|
16
|
+
tdArgs.push("--grep", parsed.grep);
|
|
13
17
|
}
|
|
14
|
-
if (
|
|
15
|
-
tdArgs.push("--worktree",
|
|
18
|
+
if (parsed.worktreePath) {
|
|
19
|
+
tdArgs.push("--worktree", parsed.worktreePath);
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
const result = await runCommand("td-cli", tdArgs
|
|
22
|
+
const result = await runCommand("td-cli", tdArgs, {
|
|
23
|
+
cwd: parsed.worktreePath,
|
|
24
|
+
timeout: parsed.timeoutSeconds * 1000,
|
|
25
|
+
});
|
|
19
26
|
|
|
20
27
|
if (result.exitCode !== 0) {
|
|
21
28
|
// Playwright might exit with non-zero if tests fail, but our td-cli should ideally handle it
|
|
@@ -7,8 +7,31 @@ export const RunTestsInputSchema = z.object({
|
|
|
7
7
|
worktreePath: z.string().optional(),
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
export
|
|
11
|
-
|
|
10
|
+
export type RunTestsInput = z.input<typeof RunTestsInputSchema>;
|
|
11
|
+
|
|
12
|
+
export function parseCommandArguments(fullCmd: string): [string, string[]] {
|
|
13
|
+
const tokens: string[] = [];
|
|
14
|
+
const regex = /"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|(\S+)/g;
|
|
15
|
+
let match: RegExpExecArray | null;
|
|
16
|
+
while ((match = regex.exec(fullCmd)) !== null) {
|
|
17
|
+
if (match[1] !== undefined) {
|
|
18
|
+
tokens.push(match[1].replace(/\\"/g, '"'));
|
|
19
|
+
} else if (match[2] !== undefined) {
|
|
20
|
+
tokens.push(match[2].replace(/\\'/g, "'"));
|
|
21
|
+
} else {
|
|
22
|
+
tokens.push(match[3]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (tokens.length === 0) {
|
|
26
|
+
return ["", []];
|
|
27
|
+
}
|
|
28
|
+
const [cmd, ...args] = tokens;
|
|
29
|
+
return [cmd, args];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function runTestsHandler(args: RunTestsInput) {
|
|
33
|
+
const parsed = RunTestsInputSchema.parse(args || {});
|
|
34
|
+
const commands = parsed.commands || [
|
|
12
35
|
"pnpm install --frozen-lockfile",
|
|
13
36
|
"pnpm lint",
|
|
14
37
|
"pnpm test",
|
|
@@ -19,11 +42,11 @@ export async function runTestsHandler(args: z.infer<typeof RunTestsInputSchema>)
|
|
|
19
42
|
let success = true;
|
|
20
43
|
|
|
21
44
|
for (const fullCmd of commands) {
|
|
22
|
-
const [cmd,
|
|
45
|
+
const [cmd, cmdArgs] = parseCommandArguments(fullCmd);
|
|
23
46
|
try {
|
|
24
47
|
const res = await runCommand(cmd, cmdArgs, {
|
|
25
|
-
cwd:
|
|
26
|
-
timeout:
|
|
48
|
+
cwd: parsed.worktreePath,
|
|
49
|
+
timeout: parsed.timeoutSeconds * 1000
|
|
27
50
|
});
|
|
28
51
|
results.push(res);
|
|
29
52
|
if (res.exitCode !== 0) {
|