@arii/boomtick-mcp 0.4.2 → 0.5.0
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/github.get_pr_commits.json +32 -0
- package/.mcp/schemas/github.get_pr_reviews.json +32 -0
- package/.mcp/schemas/github_get_pr_commits.json +32 -0
- package/.mcp/schemas/github_get_pr_reviews.json +32 -0
- package/.mcp/schemas/repo.get_workflow_runs.json +50 -0
- package/.mcp/schemas/repo.logs.json +14 -0
- package/.mcp/schemas/repo.read_ci_logs.json +14 -0
- package/.mcp/schemas/repo_get_workflow_runs.json +50 -0
- package/.mcp/schemas/repo_logs.json +14 -0
- package/.mcp/schemas/repo_read_ci_logs.json +14 -0
- package/CHANGELOG.md +7 -0
- package/README.md +0 -1
- package/actions/impact-analysis/action.yml +4 -16
- package/actions/run-project-gate/action.yml +2 -9
- package/actions/test-build/action.yml +1 -19
- package/dist/lib/git.js +44 -0
- package/dist/lib/git.test.js +82 -0
- package/dist/mcp/definitions.js +16 -39
- package/dist/mcp/server.js +0 -46
- package/dist/mcp/server.test.js +0 -33
- package/dist/tools/contract.js +135 -2
- package/dist/tools/github.get_merge_conflict_files.js +10 -18
- package/dist/tools/github.get_pr_commits.js +21 -0
- package/dist/tools/github.get_pr_reviews.js +21 -0
- package/dist/tools/github.get_pr_reviews.test.js +99 -0
- package/dist/tools/jules/create-session.js +1 -2
- package/dist/tools/jules/get-pr.js +1 -2
- package/dist/tools/jules/get-session.js +1 -2
- package/dist/tools/jules/shared.js +24 -0
- package/dist/tools/repo.get_changed_files.js +2 -13
- package/dist/tools/repo.get_workflow_runs.js +29 -0
- package/dist/tools/repo.logs.js +5 -1
- package/dist/tools/repo.read_agent_context.js +27 -1
- package/dist/tools/repo.read_agent_context.test.js +1 -1
- package/dist/tools/repo.read_ci_logs.js +5 -1
- package/dist/tools/repo.run_tests.js +1 -1
- package/package.json +3 -6
- package/src/agents/verifier-agent.prompt.md +0 -4
- package/src/lib/git.test.ts +110 -0
- package/src/lib/git.ts +75 -0
- package/src/mcp/definitions.ts +18 -42
- package/src/mcp/server.test.ts +0 -42
- package/src/mcp/server.ts +0 -45
- package/src/tools/contract.ts +147 -2
- package/src/tools/github.get_merge_conflict_files.ts +10 -20
- package/src/tools/github.get_pr_commits.ts +27 -0
- package/src/tools/github.get_pr_reviews.test.ts +110 -0
- package/src/tools/github.get_pr_reviews.ts +27 -0
- package/src/tools/jules/create-session.ts +1 -2
- package/src/tools/jules/get-pr.ts +1 -2
- package/src/tools/jules/get-session.ts +1 -2
- package/src/tools/jules/shared.ts +35 -0
- package/src/tools/repo.get_changed_files.ts +2 -16
- package/src/tools/repo.get_workflow_runs.ts +36 -0
- package/src/tools/repo.logs.ts +5 -1
- package/src/tools/repo.read_agent_context.test.ts +1 -1
- package/src/tools/repo.read_agent_context.ts +35 -1
- package/src/tools/repo.read_ci_logs.ts +5 -1
- package/src/tools/repo.run_tests.ts +1 -1
- package/.mcp/schemas/agent.search_ddgs.json +0 -31
- package/.mcp/schemas/agent_search_ddgs.json +0 -31
- package/.mcp/schemas/repo.get_route_map.json +0 -23
- package/.mcp/schemas/repo.run_lighthouse.json +0 -29
- package/.mcp/schemas/repo.run_playwright.json +0 -36
- package/.mcp/schemas/repo_get_route_map.json +0 -23
- package/.mcp/schemas/repo_run_lighthouse.json +0 -29
- package/.mcp/schemas/repo_run_playwright.json +0 -36
- package/dist/lib/td-cli.js +0 -54
- package/dist/tools/ddgs.search.js +0 -50
- package/dist/tools/ddgs.search.test.js +0 -67
- package/dist/tools/ddgs_search.py +0 -23
- package/dist/tools/repo.get_route_map.js +0 -37
- package/dist/tools/repo.run_lighthouse.js +0 -37
- package/dist/tools/repo.run_playwright.js +0 -34
- package/scripts/export-mcp-schema.ts +0 -7
- package/src/lib/td-cli.ts +0 -73
- package/src/tools/ddgs.search.test.ts +0 -92
- package/src/tools/ddgs.search.ts +0 -58
- package/src/tools/ddgs_search.py +0 -23
- package/src/tools/repo.get_route_map.ts +0 -41
- package/src/tools/repo.run_lighthouse.ts +0 -40
- package/src/tools/repo.run_playwright.ts +0 -42
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "github.get_pr_commits",
|
|
3
|
+
"description": "List commits and commit metadata (SHAs, authors, messages) for a GitHub PR.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"properties": {
|
|
6
|
+
"prNumber": {
|
|
7
|
+
"description": "The number of the PR to list commits for.",
|
|
8
|
+
"title": "Prnumber",
|
|
9
|
+
"type": "integer"
|
|
10
|
+
},
|
|
11
|
+
"repo": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"type": "null"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"default": null,
|
|
22
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
23
|
+
"title": "Repo"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": [
|
|
27
|
+
"prNumber"
|
|
28
|
+
],
|
|
29
|
+
"title": "GetPrCommitsInput",
|
|
30
|
+
"type": "object"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "github.get_pr_reviews",
|
|
3
|
+
"description": "Get top-level reviews, verdicts, states, and bodies for a GitHub PR.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"properties": {
|
|
6
|
+
"prNumber": {
|
|
7
|
+
"description": "The number of the PR to view reviews for.",
|
|
8
|
+
"title": "Prnumber",
|
|
9
|
+
"type": "integer"
|
|
10
|
+
},
|
|
11
|
+
"repo": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"type": "null"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"default": null,
|
|
22
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
23
|
+
"title": "Repo"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": [
|
|
27
|
+
"prNumber"
|
|
28
|
+
],
|
|
29
|
+
"title": "GetPrReviewsInput",
|
|
30
|
+
"type": "object"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "github_get_pr_commits",
|
|
3
|
+
"description": "List commits and commit metadata (SHAs, authors, messages) for a GitHub PR.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"properties": {
|
|
6
|
+
"prNumber": {
|
|
7
|
+
"description": "The number of the PR to list commits for.",
|
|
8
|
+
"title": "Prnumber",
|
|
9
|
+
"type": "integer"
|
|
10
|
+
},
|
|
11
|
+
"repo": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"type": "null"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"default": null,
|
|
22
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
23
|
+
"title": "Repo"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": [
|
|
27
|
+
"prNumber"
|
|
28
|
+
],
|
|
29
|
+
"title": "GetPrCommitsInput",
|
|
30
|
+
"type": "object"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "github_get_pr_reviews",
|
|
3
|
+
"description": "Get top-level reviews, verdicts, states, and bodies for a GitHub PR.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"properties": {
|
|
6
|
+
"prNumber": {
|
|
7
|
+
"description": "The number of the PR to view reviews for.",
|
|
8
|
+
"title": "Prnumber",
|
|
9
|
+
"type": "integer"
|
|
10
|
+
},
|
|
11
|
+
"repo": {
|
|
12
|
+
"anyOf": [
|
|
13
|
+
{
|
|
14
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"type": "null"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"default": null,
|
|
22
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
23
|
+
"title": "Repo"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"required": [
|
|
27
|
+
"prNumber"
|
|
28
|
+
],
|
|
29
|
+
"title": "GetPrReviewsInput",
|
|
30
|
+
"type": "object"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "repo.get_workflow_runs",
|
|
3
|
+
"description": "List recent GitHub Actions workflow runs for the repository.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"properties": {
|
|
6
|
+
"branch": {
|
|
7
|
+
"anyOf": [
|
|
8
|
+
{
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "null"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"default": null,
|
|
16
|
+
"description": "Filter workflow runs by branch name.",
|
|
17
|
+
"title": "Branch"
|
|
18
|
+
},
|
|
19
|
+
"event": {
|
|
20
|
+
"anyOf": [
|
|
21
|
+
{
|
|
22
|
+
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "null"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"default": null,
|
|
29
|
+
"description": "Filter workflow runs by event (e.g. push, pull_request).",
|
|
30
|
+
"title": "Event"
|
|
31
|
+
},
|
|
32
|
+
"repo": {
|
|
33
|
+
"anyOf": [
|
|
34
|
+
{
|
|
35
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"type": "null"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"default": null,
|
|
43
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
44
|
+
"title": "Repo"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"title": "GetWorkflowRunsInput",
|
|
48
|
+
"type": "object"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -20,6 +20,20 @@
|
|
|
20
20
|
"default": null,
|
|
21
21
|
"description": "Optional pattern to filter log lines.",
|
|
22
22
|
"title": "Grep"
|
|
23
|
+
},
|
|
24
|
+
"repo": {
|
|
25
|
+
"anyOf": [
|
|
26
|
+
{
|
|
27
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
28
|
+
"type": "string"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "null"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"default": null,
|
|
35
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
36
|
+
"title": "Repo"
|
|
23
37
|
}
|
|
24
38
|
},
|
|
25
39
|
"required": [
|
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
"description": "Include logs for successful runs (default: false).",
|
|
14
14
|
"title": "All",
|
|
15
15
|
"type": "boolean"
|
|
16
|
+
},
|
|
17
|
+
"repo": {
|
|
18
|
+
"anyOf": [
|
|
19
|
+
{
|
|
20
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "null"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"default": null,
|
|
28
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
29
|
+
"title": "Repo"
|
|
16
30
|
}
|
|
17
31
|
},
|
|
18
32
|
"required": [
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "repo_get_workflow_runs",
|
|
3
|
+
"description": "List recent GitHub Actions workflow runs for the repository.",
|
|
4
|
+
"parameters": {
|
|
5
|
+
"properties": {
|
|
6
|
+
"branch": {
|
|
7
|
+
"anyOf": [
|
|
8
|
+
{
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"type": "null"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"default": null,
|
|
16
|
+
"description": "Filter workflow runs by branch name.",
|
|
17
|
+
"title": "Branch"
|
|
18
|
+
},
|
|
19
|
+
"event": {
|
|
20
|
+
"anyOf": [
|
|
21
|
+
{
|
|
22
|
+
"type": "string"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "null"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"default": null,
|
|
29
|
+
"description": "Filter workflow runs by event (e.g. push, pull_request).",
|
|
30
|
+
"title": "Event"
|
|
31
|
+
},
|
|
32
|
+
"repo": {
|
|
33
|
+
"anyOf": [
|
|
34
|
+
{
|
|
35
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"type": "null"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"default": null,
|
|
43
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
44
|
+
"title": "Repo"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"title": "GetWorkflowRunsInput",
|
|
48
|
+
"type": "object"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -20,6 +20,20 @@
|
|
|
20
20
|
"default": null,
|
|
21
21
|
"description": "Optional pattern to filter log lines.",
|
|
22
22
|
"title": "Grep"
|
|
23
|
+
},
|
|
24
|
+
"repo": {
|
|
25
|
+
"anyOf": [
|
|
26
|
+
{
|
|
27
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
28
|
+
"type": "string"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "null"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"default": null,
|
|
35
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
36
|
+
"title": "Repo"
|
|
23
37
|
}
|
|
24
38
|
},
|
|
25
39
|
"required": [
|
|
@@ -13,6 +13,20 @@
|
|
|
13
13
|
"description": "Include logs for successful runs (default: false).",
|
|
14
14
|
"title": "All",
|
|
15
15
|
"type": "boolean"
|
|
16
|
+
},
|
|
17
|
+
"repo": {
|
|
18
|
+
"anyOf": [
|
|
19
|
+
{
|
|
20
|
+
"pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
|
|
21
|
+
"type": "string"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "null"
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"default": null,
|
|
28
|
+
"description": "The target repository override (e.g. org/repo).",
|
|
29
|
+
"title": "Repo"
|
|
16
30
|
}
|
|
17
31
|
},
|
|
18
32
|
"required": [
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.5.0](https://github.com/arii/boomtick/compare/mcp-v0.4.2...mcp-v0.5.0) (2026-10-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **tooling:** add PR reviews, PR commits, workflow runs inspection, and repo overrides ([#834](https://github.com/arii/boomtick/issues/834)) ([42a8638](https://github.com/arii/boomtick/commit/42a8638add4ce8278dedacd6d8d14acc9e0a3bb9))
|
|
9
|
+
|
|
3
10
|
## [0.4.2](https://github.com/arii/boomtick/compare/mcp-v0.4.1...mcp-v0.4.2) (2026-10-12)
|
|
4
11
|
|
|
5
12
|
|
package/README.md
CHANGED
|
@@ -12,7 +12,6 @@ A Model Context Protocol (MCP) server designed to empower AI agents with structu
|
|
|
12
12
|
|
|
13
13
|
### 📄 Resources
|
|
14
14
|
- `repo://package-json`: Access root package manifest.
|
|
15
|
-
- `repo://routes`: Access application route-to-content mapping.
|
|
16
15
|
- `repo://design-tokens`: Access UI design tokens.
|
|
17
16
|
- `repo://diff/{prNumber}`: Access full PR diff text.
|
|
18
17
|
- `repo://ci/{prNumber}`: Access detailed CI check results and logs.
|
|
@@ -306,22 +306,10 @@ runs:
|
|
|
306
306
|
PR_NUMBER: ${{ inputs.pr_number }}
|
|
307
307
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
308
308
|
run: |
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
export PYTHONPATH="$(realpath "${{ github.action_path }}/../../../cli"):$PYTHONPATH"
|
|
314
|
-
python3 "$RESOLVED_PATH"
|
|
315
|
-
else
|
|
316
|
-
# Fallback check for docker run execution or direct python script in checkout workspace
|
|
317
|
-
# Inside container execution, scripts/send-jules-impact.py should exist in workspace
|
|
318
|
-
if [ -f "scripts/send-jules-impact.py" ]; then
|
|
319
|
-
echo "Executing send-jules-impact.py from current workspace."
|
|
320
|
-
export PYTHONPATH="cli:$PYTHONPATH"
|
|
321
|
-
python3 scripts/send-jules-impact.py
|
|
322
|
-
else
|
|
323
|
-
echo "⚠️ Skipping: send-jules-impact.py script not found."
|
|
324
|
-
fi
|
|
309
|
+
if command -v pnpm &> /dev/null; then
|
|
310
|
+
pnpm exec tsx -e "import { sendJulesImpactReport } from './lib/julesReviewClient'; (async () => { await sendJulesImpactReport(process.env.TASK_ID); })();"
|
|
311
|
+
elif command -v npx &> /dev/null; then
|
|
312
|
+
npx tsx -e "import { sendJulesImpactReport } from './lib/julesReviewClient'; (async () => { await sendJulesImpactReport(process.env.TASK_ID); })();"
|
|
325
313
|
fi
|
|
326
314
|
shell: bash
|
|
327
315
|
|
|
@@ -17,19 +17,12 @@ runs:
|
|
|
17
17
|
env:
|
|
18
18
|
TARGET: ${{ inputs.target }}
|
|
19
19
|
run: |
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
CLI_PATH=$(bash scripts/resolve-cli.sh | sed "s|$(pwd)/||")
|
|
23
|
-
elif [ -f "boomtick-pkg/scripts/resolve-cli.sh" ]; then
|
|
24
|
-
CLI_PATH=$(bash boomtick-pkg/scripts/resolve-cli.sh | sed "s|$(pwd)/||")
|
|
25
|
-
elif [ -f "boomtick/scripts/resolve-cli.sh" ]; then
|
|
26
|
-
CLI_PATH=$(bash boomtick/scripts/resolve-cli.sh | sed "s|$(pwd)/||")
|
|
20
|
+
if [ -d "cli" ]; then
|
|
21
|
+
CLI_PATH="cli"
|
|
27
22
|
elif [ -d "boomtick-pkg/cli" ]; then
|
|
28
23
|
CLI_PATH="boomtick-pkg/cli"
|
|
29
24
|
elif [ -d "boomtick/cli" ]; then
|
|
30
25
|
CLI_PATH="boomtick/cli"
|
|
31
|
-
elif [ -d "cli" ]; then
|
|
32
|
-
CLI_PATH="cli"
|
|
33
26
|
else
|
|
34
27
|
CLI_PATH="cli"
|
|
35
28
|
fi
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
name: BoomTick Build & Test
|
|
2
|
-
description: Encapsulates build, bundle size check, Playwright E2E
|
|
2
|
+
description: Encapsulates build, bundle size check, and Playwright E2E
|
|
3
3
|
inputs:
|
|
4
4
|
github_token:
|
|
5
5
|
description: 'GitHub token'
|
|
6
6
|
required: true
|
|
7
|
-
run_lighthouse:
|
|
8
|
-
description: 'Whether to run Lighthouse CI'
|
|
9
|
-
required: false
|
|
10
|
-
default: 'true'
|
|
11
7
|
runs:
|
|
12
8
|
using: composite
|
|
13
9
|
steps:
|
|
@@ -36,20 +32,6 @@ runs:
|
|
|
36
32
|
VITE_BASE_PATH=/ pnpm run test:e2e
|
|
37
33
|
shell: bash
|
|
38
34
|
|
|
39
|
-
- name: Run Lighthouse CI
|
|
40
|
-
if: inputs.run_lighthouse == 'true'
|
|
41
|
-
run: |
|
|
42
|
-
set -eu
|
|
43
|
-
VITE_BASE_PATH="/"
|
|
44
|
-
CHROME_PATH="$(node -e "console.log(require('playwright').chromium.executablePath())")"
|
|
45
|
-
export VITE_BASE_PATH
|
|
46
|
-
export CHROME_PATH
|
|
47
|
-
echo "CHROME_PATH=$CHROME_PATH"
|
|
48
|
-
pnpm run lighthouse --collect.url="http://localhost:4173${VITE_BASE_PATH}"
|
|
49
|
-
env:
|
|
50
|
-
LHCI_GITHUB_TOKEN: ${{ inputs.github_token }}
|
|
51
|
-
shell: bash
|
|
52
|
-
|
|
53
35
|
- name: Check Playwright Report Exists
|
|
54
36
|
id: check_report
|
|
55
37
|
if: always()
|
package/dist/lib/git.js
CHANGED
|
@@ -59,3 +59,47 @@ export async function removeWorktree(worktreePath) {
|
|
|
59
59
|
await runCommand("git", ["worktree", "remove", "--force", worktreePath]);
|
|
60
60
|
await runCommand("git", ["worktree", "prune"]);
|
|
61
61
|
}
|
|
62
|
+
export async function getChangedFiles(base = "main", head = "HEAD", cwd) {
|
|
63
|
+
const result = await runCommand("git", ["diff", "--name-status", "-z", `${base}...${head}`], { cwd });
|
|
64
|
+
if (result.exitCode !== 0) {
|
|
65
|
+
throw new Error(`Failed to get changed files: ${result.stderr}`);
|
|
66
|
+
}
|
|
67
|
+
const tokens = result.stdout.split("\0").filter((t) => t.length > 0);
|
|
68
|
+
const files = [];
|
|
69
|
+
let i = 0;
|
|
70
|
+
while (i < tokens.length) {
|
|
71
|
+
const status = tokens[i];
|
|
72
|
+
if (status.startsWith("R") || status.startsWith("C")) {
|
|
73
|
+
const oldPath = tokens[i + 1];
|
|
74
|
+
const newPath = tokens[i + 2];
|
|
75
|
+
if (oldPath && newPath) {
|
|
76
|
+
files.push({ status, path: newPath, oldPath });
|
|
77
|
+
}
|
|
78
|
+
i += 3;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
const filePath = tokens[i + 1];
|
|
82
|
+
if (filePath) {
|
|
83
|
+
files.push({ status, path: filePath });
|
|
84
|
+
}
|
|
85
|
+
i += 2;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return files;
|
|
89
|
+
}
|
|
90
|
+
export async function getMergeConflictFiles(baseBranch = "main", headRef = "HEAD", cwd) {
|
|
91
|
+
const result = await runCommand("git", ["merge-tree", "--write-tree", "--name-only", baseBranch, headRef], { cwd });
|
|
92
|
+
// git merge-tree returns exit code 1 if conflicts are present, 0 if clean merge
|
|
93
|
+
if (result.exitCode !== 0 && result.exitCode !== 1) {
|
|
94
|
+
throw new Error(`Git merge-tree failed: ${result.stderr}`);
|
|
95
|
+
}
|
|
96
|
+
const lines = result.stdout
|
|
97
|
+
.split("\n")
|
|
98
|
+
.map((l) => l.trim())
|
|
99
|
+
.filter((l) => l.length > 0);
|
|
100
|
+
// First line is tree hash if successful or conflict output
|
|
101
|
+
// When conflicts exist, git merge-tree --write-tree --name-only outputs conflicted filenames
|
|
102
|
+
// Skip tree hash line if present (40 hex chars)
|
|
103
|
+
const files = lines.filter((line) => !/^[0-9a-f]{40}$/i.test(line));
|
|
104
|
+
return files;
|
|
105
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
2
|
+
import { getChangedFiles, getMergeConflictFiles } from "./git.js";
|
|
3
|
+
import * as shell from "./shell.js";
|
|
4
|
+
vi.mock("./shell.js", () => ({
|
|
5
|
+
runCommand: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
describe("Git Helpers", () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
vi.resetAllMocks();
|
|
10
|
+
});
|
|
11
|
+
describe("getChangedFiles", () => {
|
|
12
|
+
it("should parse null-delimited git diff output correctly", async () => {
|
|
13
|
+
// Mock git diff output with null character delimiters:
|
|
14
|
+
// Status M -> file1.txt
|
|
15
|
+
// Status A -> file2.txt
|
|
16
|
+
// Status R100 -> old.txt -> new.txt
|
|
17
|
+
const mockStdout = "M\0file1.txt\0A\0file2.txt\0R100\0old.txt\0new.txt\0";
|
|
18
|
+
vi.mocked(shell.runCommand).mockResolvedValueOnce({
|
|
19
|
+
exitCode: 0,
|
|
20
|
+
stdout: mockStdout,
|
|
21
|
+
stderr: "",
|
|
22
|
+
durationMs: 10,
|
|
23
|
+
command: "git diff --name-status -z main...HEAD",
|
|
24
|
+
});
|
|
25
|
+
const result = await getChangedFiles("main", "HEAD");
|
|
26
|
+
expect(shell.runCommand).toHaveBeenCalledWith("git", ["diff", "--name-status", "-z", "main...HEAD"], { cwd: undefined });
|
|
27
|
+
expect(result).toEqual([
|
|
28
|
+
{ status: "M", path: "file1.txt" },
|
|
29
|
+
{ status: "A", path: "file2.txt" },
|
|
30
|
+
{ status: "R100", path: "new.txt", oldPath: "old.txt" },
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
it("should throw error if git diff fails", async () => {
|
|
34
|
+
vi.mocked(shell.runCommand).mockResolvedValueOnce({
|
|
35
|
+
exitCode: 1,
|
|
36
|
+
stdout: "",
|
|
37
|
+
stderr: "fatal: bad revision",
|
|
38
|
+
durationMs: 10,
|
|
39
|
+
command: "git diff --name-status -z invalid...HEAD",
|
|
40
|
+
});
|
|
41
|
+
await expect(getChangedFiles("invalid", "HEAD")).rejects.toThrow("Failed to get changed files: fatal: bad revision");
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe("getMergeConflictFiles", () => {
|
|
45
|
+
it("should parse git merge-tree output when conflicts exist", async () => {
|
|
46
|
+
// Output with 40-char tree hash followed by conflicting filenames
|
|
47
|
+
const mockStdout = "5d71843ed2e051b2be91361db7bea0fc4ee1e5a0\nfile1.txt\nsrc/file2.ts\n";
|
|
48
|
+
vi.mocked(shell.runCommand).mockResolvedValueOnce({
|
|
49
|
+
exitCode: 1, // merge-tree exits 1 on conflicts
|
|
50
|
+
stdout: mockStdout,
|
|
51
|
+
stderr: "",
|
|
52
|
+
durationMs: 10,
|
|
53
|
+
command: "git merge-tree --write-tree --name-only main feature",
|
|
54
|
+
});
|
|
55
|
+
const conflicts = await getMergeConflictFiles("main", "feature");
|
|
56
|
+
expect(shell.runCommand).toHaveBeenCalledWith("git", ["merge-tree", "--write-tree", "--name-only", "main", "feature"], { cwd: undefined });
|
|
57
|
+
expect(conflicts).toEqual(["file1.txt", "src/file2.ts"]);
|
|
58
|
+
});
|
|
59
|
+
it("should return empty array when no conflicts exist", async () => {
|
|
60
|
+
const mockStdout = "5d71843ed2e051b2be91361db7bea0fc4ee1e5a0\n";
|
|
61
|
+
vi.mocked(shell.runCommand).mockResolvedValueOnce({
|
|
62
|
+
exitCode: 0,
|
|
63
|
+
stdout: mockStdout,
|
|
64
|
+
stderr: "",
|
|
65
|
+
durationMs: 10,
|
|
66
|
+
command: "git merge-tree --write-tree --name-only main feature",
|
|
67
|
+
});
|
|
68
|
+
const conflicts = await getMergeConflictFiles("main", "feature");
|
|
69
|
+
expect(conflicts).toEqual([]);
|
|
70
|
+
});
|
|
71
|
+
it("should throw error if git merge-tree exits with unexpected exit code", async () => {
|
|
72
|
+
vi.mocked(shell.runCommand).mockResolvedValueOnce({
|
|
73
|
+
exitCode: 128,
|
|
74
|
+
stdout: "",
|
|
75
|
+
stderr: "fatal: not a valid object name",
|
|
76
|
+
durationMs: 10,
|
|
77
|
+
command: "git merge-tree --write-tree --name-only invalid feature",
|
|
78
|
+
});
|
|
79
|
+
await expect(getMergeConflictFiles("invalid", "feature")).rejects.toThrow("Git merge-tree failed: fatal: not a valid object name");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
package/dist/mcp/definitions.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HealthCheckInputJsonSchema, SearchPRsInputJsonSchema, GetPrDiffInputJsonSchema, CheckoutBranchInputJsonSchema, GetMergeConflictFilesInputJsonSchema, GetChangedFilesInputJsonSchema, GetPackageScriptsInputJsonSchema,
|
|
1
|
+
import { HealthCheckInputJsonSchema, SearchPRsInputJsonSchema, GetPrDiffInputJsonSchema, CheckoutBranchInputJsonSchema, GetMergeConflictFilesInputJsonSchema, GetChangedFilesInputJsonSchema, GetPackageScriptsInputJsonSchema, ReadCiLogsInputJsonSchema, RepoLogsInputJsonSchema, CreateBranchInputJsonSchema, CreateRepairBranchInputJsonSchema, RunTestsInputJsonSchema, CommitPatchInputJsonSchema, OpenReplacementPrInputJsonSchema, CreatePullRequestInputJsonSchema, CommentTriageSummaryInputJsonSchema, GetPrInputJsonSchema, IssueViewInputJsonSchema, IssueUpdateInputJsonSchema, IssueCommentInputJsonSchema, CreateIssueInputJsonSchema, GetCommandSchemaInputJsonSchema, ReadAgentContextInputJsonSchema as ReadAgentContextSchema, CreateJulesSessionInputJsonSchema, JulesSessionIdInputJsonSchema, JulesSendMessageInputJsonSchema, JulesListSessionsInputJsonSchema, GetPrReviewsInputJsonSchema, GetPrCommitsInputJsonSchema, GetWorkflowRunsInputJsonSchema, } from "../tools/contract.js";
|
|
2
2
|
export const MCP_PROMPTS = [
|
|
3
3
|
{
|
|
4
4
|
name: "conflict-scout",
|
|
@@ -32,12 +32,6 @@ export const MCP_RESOURCES = [
|
|
|
32
32
|
mimeType: "application/json",
|
|
33
33
|
description: "The root package.json file of the repository.",
|
|
34
34
|
},
|
|
35
|
-
{
|
|
36
|
-
uri: "repo://routes",
|
|
37
|
-
name: "Route Map",
|
|
38
|
-
mimeType: "application/json",
|
|
39
|
-
description: "The mapping of application routes to content files.",
|
|
40
|
-
},
|
|
41
35
|
{
|
|
42
36
|
uri: "repo://design-tokens",
|
|
43
37
|
name: "Design Tokens",
|
|
@@ -50,18 +44,6 @@ export const MCP_RESOURCES = [
|
|
|
50
44
|
mimeType: "application/json",
|
|
51
45
|
description: "The validation report for a specific repair branch.",
|
|
52
46
|
},
|
|
53
|
-
{
|
|
54
|
-
uri: "repo://lighthouse/{branch}",
|
|
55
|
-
name: "Lighthouse Report",
|
|
56
|
-
mimeType: "application/json",
|
|
57
|
-
description: "Lighthouse CI report for a specific branch.",
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
uri: "repo://playwright/{branch}",
|
|
61
|
-
name: "Playwright Report",
|
|
62
|
-
mimeType: "application/json",
|
|
63
|
-
description: "Playwright test report for a specific branch.",
|
|
64
|
-
},
|
|
65
47
|
];
|
|
66
48
|
const BASE_MCP_TOOLS = [
|
|
67
49
|
{
|
|
@@ -109,11 +91,6 @@ const BASE_MCP_TOOLS = [
|
|
|
109
91
|
description: "Get the scripts defined in package.json.",
|
|
110
92
|
inputSchema: GetPackageScriptsInputJsonSchema,
|
|
111
93
|
},
|
|
112
|
-
{
|
|
113
|
-
name: "repo.get_route_map",
|
|
114
|
-
description: "Get the mapping of routes to content files.",
|
|
115
|
-
inputSchema: GetRouteMapInputJsonSchema,
|
|
116
|
-
},
|
|
117
94
|
{
|
|
118
95
|
name: "repo.read_ci_logs",
|
|
119
96
|
description: "Read CI logs for a given pull request.",
|
|
@@ -139,16 +116,6 @@ const BASE_MCP_TOOLS = [
|
|
|
139
116
|
description: "Run repository tests and checks.",
|
|
140
117
|
inputSchema: RunTestsInputJsonSchema,
|
|
141
118
|
},
|
|
142
|
-
{
|
|
143
|
-
name: "repo.run_lighthouse",
|
|
144
|
-
description: "Run Lighthouse CI audits.",
|
|
145
|
-
inputSchema: RunLighthouseInputJsonSchema,
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
name: "repo.run_playwright",
|
|
149
|
-
description: "Run Playwright E2E tests.",
|
|
150
|
-
inputSchema: RunPlaywrightInputJsonSchema,
|
|
151
|
-
},
|
|
152
119
|
{
|
|
153
120
|
name: "repo.commit_patch",
|
|
154
121
|
description: "Commit verified repair changes in a worktree.",
|
|
@@ -174,6 +141,21 @@ const BASE_MCP_TOOLS = [
|
|
|
174
141
|
description: "Get details of a GitHub PR including title, state, and URLs.",
|
|
175
142
|
inputSchema: GetPrInputJsonSchema,
|
|
176
143
|
},
|
|
144
|
+
{
|
|
145
|
+
name: "github.get_pr_reviews",
|
|
146
|
+
description: "Get top-level reviews, verdicts, states, and bodies for a GitHub PR.",
|
|
147
|
+
inputSchema: GetPrReviewsInputJsonSchema,
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "github.get_pr_commits",
|
|
151
|
+
description: "List commits and commit metadata (SHAs, authors, messages) for a GitHub PR.",
|
|
152
|
+
inputSchema: GetPrCommitsInputJsonSchema,
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
name: "repo.get_workflow_runs",
|
|
156
|
+
description: "List recent GitHub Actions workflow runs for the repository.",
|
|
157
|
+
inputSchema: GetWorkflowRunsInputJsonSchema,
|
|
158
|
+
},
|
|
177
159
|
{
|
|
178
160
|
name: "github.issue_view",
|
|
179
161
|
description: "View details of a GitHub issue including title, body, and state.",
|
|
@@ -234,11 +216,6 @@ const BASE_MCP_TOOLS = [
|
|
|
234
216
|
description: "Automatically collect CI status/logs for the PR associated with a Jules session and send them back as feedback.",
|
|
235
217
|
inputSchema: JulesSessionIdInputJsonSchema,
|
|
236
218
|
},
|
|
237
|
-
{
|
|
238
|
-
name: "agent.search_ddgs",
|
|
239
|
-
description: "Search the web using DuckDuckGo (via ddgs python library).",
|
|
240
|
-
inputSchema: SearchDdgsInputJsonSchema,
|
|
241
|
-
},
|
|
242
219
|
];
|
|
243
220
|
export const MCP_TOOLS = BASE_MCP_TOOLS.flatMap((tool) => {
|
|
244
221
|
const underscoreName = tool.name.replace(/\./g, "_");
|