diffprism 0.32.0 → 0.34.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/dist/bin.js +122 -7
- package/dist/chunk-NJKYNMAQ.js +6608 -0
- package/dist/mcp-server.js +138 -4
- package/package.json +1 -1
- package/ui-dist/assets/index-1PUjTjRT.js +324 -0
- package/ui-dist/assets/index-RCLz30rX.css +1 -0
- package/ui-dist/index.html +2 -2
- package/dist/chunk-G4W5QBT4.js +0 -2607
- package/ui-dist/assets/index-Cwwzm9DK.js +0 -319
- package/ui-dist/assets/index-r-H-ptFw.css +0 -1
package/dist/mcp-server.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
2
|
analyze,
|
|
3
3
|
consumeReviewResult,
|
|
4
|
+
createGitHubClient,
|
|
4
5
|
detectWorktree,
|
|
6
|
+
fetchPullRequest,
|
|
7
|
+
fetchPullRequestDiff,
|
|
5
8
|
getCurrentBranch,
|
|
6
9
|
getDiff,
|
|
7
10
|
isServerAlive,
|
|
11
|
+
normalizePr,
|
|
12
|
+
parsePrRef,
|
|
8
13
|
readReviewResult,
|
|
9
14
|
readWatchFile,
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
resolveGitHubToken,
|
|
16
|
+
startReview,
|
|
17
|
+
submitGitHubReview
|
|
18
|
+
} from "./chunk-NJKYNMAQ.js";
|
|
12
19
|
|
|
13
20
|
// packages/mcp-server/src/index.ts
|
|
14
21
|
import fs from "fs";
|
|
@@ -106,11 +113,11 @@ async function reviewViaGlobalServer(serverInfo, diffRef, options) {
|
|
|
106
113
|
async function startMcpServer() {
|
|
107
114
|
const server = new McpServer({
|
|
108
115
|
name: "diffprism",
|
|
109
|
-
version: true ? "0.
|
|
116
|
+
version: true ? "0.34.0" : "0.0.0-dev"
|
|
110
117
|
});
|
|
111
118
|
server.tool(
|
|
112
119
|
"open_review",
|
|
113
|
-
"Open a browser-based code review for local git changes. Blocks until the engineer submits their review decision.",
|
|
120
|
+
"Open a browser-based code review for local git changes. Blocks until the engineer submits their review decision. The result may include a `postReviewAction` field ('commit' or 'commit_and_pr') if the reviewer requested a post-review action.",
|
|
114
121
|
{
|
|
115
122
|
diff_ref: z.string().describe(
|
|
116
123
|
'Git diff reference: "staged", "unstaged", "working-copy" (staged+unstaged grouped), or a ref range like "HEAD~3..HEAD"'
|
|
@@ -772,6 +779,133 @@ async function startMcpServer() {
|
|
|
772
779
|
}
|
|
773
780
|
}
|
|
774
781
|
);
|
|
782
|
+
server.tool(
|
|
783
|
+
"review_pr",
|
|
784
|
+
"Open a browser-based code review for a GitHub pull request. Fetches the PR diff, runs DiffPrism analysis, and opens the review UI. Blocks until the engineer submits their review decision. Optionally posts the review back to GitHub. The result may include a `postReviewAction` field ('commit' or 'commit_and_pr') if the reviewer requested a post-review action.",
|
|
785
|
+
{
|
|
786
|
+
pr: z.string().describe(
|
|
787
|
+
'GitHub PR reference: "owner/repo#123" or "https://github.com/owner/repo/pull/123"'
|
|
788
|
+
),
|
|
789
|
+
title: z.string().optional().describe("Override review title"),
|
|
790
|
+
reasoning: z.string().optional().describe("Agent reasoning about the PR changes"),
|
|
791
|
+
post_to_github: z.boolean().optional().describe("Post the review back to GitHub after submission (default: false)")
|
|
792
|
+
},
|
|
793
|
+
async ({ pr, title, reasoning, post_to_github }) => {
|
|
794
|
+
try {
|
|
795
|
+
const token = resolveGitHubToken();
|
|
796
|
+
const { owner, repo, number } = parsePrRef(pr);
|
|
797
|
+
const client = createGitHubClient(token);
|
|
798
|
+
const [prMetadata, rawDiff] = await Promise.all([
|
|
799
|
+
fetchPullRequest(client, owner, repo, number),
|
|
800
|
+
fetchPullRequestDiff(client, owner, repo, number)
|
|
801
|
+
]);
|
|
802
|
+
if (!rawDiff.trim()) {
|
|
803
|
+
return {
|
|
804
|
+
content: [
|
|
805
|
+
{
|
|
806
|
+
type: "text",
|
|
807
|
+
text: JSON.stringify({
|
|
808
|
+
decision: "approved",
|
|
809
|
+
comments: [],
|
|
810
|
+
summary: "PR has no changes to review."
|
|
811
|
+
}, null, 2)
|
|
812
|
+
}
|
|
813
|
+
]
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
const { payload } = normalizePr(rawDiff, prMetadata, { title, reasoning });
|
|
817
|
+
const serverInfo = await isServerAlive();
|
|
818
|
+
let result;
|
|
819
|
+
if (serverInfo) {
|
|
820
|
+
const createResponse = await fetch(
|
|
821
|
+
`http://localhost:${serverInfo.httpPort}/api/reviews`,
|
|
822
|
+
{
|
|
823
|
+
method: "POST",
|
|
824
|
+
headers: { "Content-Type": "application/json" },
|
|
825
|
+
body: JSON.stringify({
|
|
826
|
+
payload,
|
|
827
|
+
projectPath: `github:${owner}/${repo}`,
|
|
828
|
+
diffRef: `PR #${number}`
|
|
829
|
+
})
|
|
830
|
+
}
|
|
831
|
+
);
|
|
832
|
+
if (!createResponse.ok) {
|
|
833
|
+
throw new Error(`Global server returned ${createResponse.status}`);
|
|
834
|
+
}
|
|
835
|
+
const { sessionId } = await createResponse.json();
|
|
836
|
+
lastGlobalSessionId = sessionId;
|
|
837
|
+
lastGlobalServerInfo = serverInfo;
|
|
838
|
+
const pollIntervalMs = 2e3;
|
|
839
|
+
const maxWaitMs = 600 * 1e3;
|
|
840
|
+
const start = Date.now();
|
|
841
|
+
while (Date.now() - start < maxWaitMs) {
|
|
842
|
+
const resultResponse = await fetch(
|
|
843
|
+
`http://localhost:${serverInfo.httpPort}/api/reviews/${sessionId}/result`
|
|
844
|
+
);
|
|
845
|
+
if (resultResponse.ok) {
|
|
846
|
+
const data = await resultResponse.json();
|
|
847
|
+
if (data.result) {
|
|
848
|
+
result = data.result;
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
853
|
+
}
|
|
854
|
+
result ??= { decision: "dismissed", comments: [], summary: "Review timed out." };
|
|
855
|
+
} else {
|
|
856
|
+
const isDev = fs.existsSync(
|
|
857
|
+
path.join(process.cwd(), "packages", "ui", "src", "App.tsx")
|
|
858
|
+
);
|
|
859
|
+
result = await startReview({
|
|
860
|
+
diffRef: `PR #${number}`,
|
|
861
|
+
title: payload.metadata.title,
|
|
862
|
+
description: payload.metadata.description,
|
|
863
|
+
reasoning: payload.metadata.reasoning,
|
|
864
|
+
cwd: process.cwd(),
|
|
865
|
+
silent: true,
|
|
866
|
+
dev: isDev,
|
|
867
|
+
injectedPayload: payload
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
if ((post_to_github || result.postToGithub) && result.decision !== "dismissed") {
|
|
871
|
+
const posted = await submitGitHubReview(client, owner, repo, number, result);
|
|
872
|
+
if (posted) {
|
|
873
|
+
return {
|
|
874
|
+
content: [
|
|
875
|
+
{
|
|
876
|
+
type: "text",
|
|
877
|
+
text: JSON.stringify({
|
|
878
|
+
...result,
|
|
879
|
+
githubReviewId: posted.reviewId,
|
|
880
|
+
githubReviewUrl: `${prMetadata.url}#pullrequestreview-${posted.reviewId}`
|
|
881
|
+
}, null, 2)
|
|
882
|
+
}
|
|
883
|
+
]
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return {
|
|
888
|
+
content: [
|
|
889
|
+
{
|
|
890
|
+
type: "text",
|
|
891
|
+
text: JSON.stringify(result, null, 2)
|
|
892
|
+
}
|
|
893
|
+
]
|
|
894
|
+
};
|
|
895
|
+
} catch (err) {
|
|
896
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
897
|
+
return {
|
|
898
|
+
content: [
|
|
899
|
+
{
|
|
900
|
+
type: "text",
|
|
901
|
+
text: `Error: ${message}`
|
|
902
|
+
}
|
|
903
|
+
],
|
|
904
|
+
isError: true
|
|
905
|
+
};
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
);
|
|
775
909
|
const transport = new StdioServerTransport();
|
|
776
910
|
await server.connect(transport);
|
|
777
911
|
}
|