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.
@@ -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
- startReview
11
- } from "./chunk-G4W5QBT4.js";
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.32.0" : "0.0.0-dev"
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diffprism",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
4
4
  "type": "module",
5
5
  "description": "Local-first code review tool for agent-generated code changes",
6
6
  "bin": {