diffprism 0.31.1 → 0.33.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-ZLIUNVTW.js +6498 -0
- package/dist/mcp-server.js +184 -6
- package/package.json +1 -1
- package/ui-dist/assets/{index-Cwwzm9DK.js → index-D_thqcUo.js} +78 -73
- package/ui-dist/assets/index-w55XbIEb.css +1 -0
- package/ui-dist/index.html +2 -2
- package/dist/chunk-OJ723D6Z.js +0 -2589
- package/ui-dist/assets/index-r-H-ptFw.css +0 -1
package/dist/bin.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
createGitHubClient,
|
|
4
|
+
fetchPullRequest,
|
|
5
|
+
fetchPullRequestDiff,
|
|
3
6
|
isServerAlive,
|
|
7
|
+
normalizePr,
|
|
8
|
+
parsePrRef,
|
|
4
9
|
readServerFile,
|
|
5
10
|
readWatchFile,
|
|
11
|
+
resolveGitHubToken,
|
|
6
12
|
startGlobalServer,
|
|
7
13
|
startReview,
|
|
8
|
-
startWatch
|
|
9
|
-
|
|
14
|
+
startWatch,
|
|
15
|
+
submitGitHubReview
|
|
16
|
+
} from "./chunk-ZLIUNVTW.js";
|
|
10
17
|
|
|
11
18
|
// cli/src/index.ts
|
|
12
19
|
import { Command } from "commander";
|
|
@@ -39,6 +46,111 @@ async function review(ref, flags) {
|
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
// cli/src/commands/review-pr.ts
|
|
50
|
+
import readline from "readline";
|
|
51
|
+
async function reviewPr(pr, flags) {
|
|
52
|
+
try {
|
|
53
|
+
const token = resolveGitHubToken();
|
|
54
|
+
const { owner, repo, number } = parsePrRef(pr);
|
|
55
|
+
console.log(`Fetching PR #${number} from ${owner}/${repo}...`);
|
|
56
|
+
const client = createGitHubClient(token);
|
|
57
|
+
const [prMetadata, rawDiff] = await Promise.all([
|
|
58
|
+
fetchPullRequest(client, owner, repo, number),
|
|
59
|
+
fetchPullRequestDiff(client, owner, repo, number)
|
|
60
|
+
]);
|
|
61
|
+
if (!rawDiff.trim()) {
|
|
62
|
+
console.log("PR has no changes to review.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const { payload, diffSet, briefing, metadata } = normalizePr(rawDiff, prMetadata, {
|
|
66
|
+
title: flags.title,
|
|
67
|
+
reasoning: flags.reasoning
|
|
68
|
+
});
|
|
69
|
+
console.log(
|
|
70
|
+
`${diffSet.files.length} files, +${diffSet.files.reduce((s, f) => s + f.additions, 0)} -${diffSet.files.reduce((s, f) => s + f.deletions, 0)}`
|
|
71
|
+
);
|
|
72
|
+
let result;
|
|
73
|
+
const serverInfo = await isServerAlive();
|
|
74
|
+
if (serverInfo) {
|
|
75
|
+
const createResponse = await fetch(
|
|
76
|
+
`http://localhost:${serverInfo.httpPort}/api/reviews`,
|
|
77
|
+
{
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: { "Content-Type": "application/json" },
|
|
80
|
+
body: JSON.stringify({
|
|
81
|
+
payload,
|
|
82
|
+
projectPath: `github:${owner}/${repo}`,
|
|
83
|
+
diffRef: `PR #${number}`
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
if (!createResponse.ok) {
|
|
88
|
+
throw new Error(`Global server returned ${createResponse.status}`);
|
|
89
|
+
}
|
|
90
|
+
const { sessionId } = await createResponse.json();
|
|
91
|
+
console.log(`Review session created: ${sessionId}`);
|
|
92
|
+
console.log("Waiting for review submission...");
|
|
93
|
+
result = await pollForResult(serverInfo.httpPort, sessionId);
|
|
94
|
+
} else {
|
|
95
|
+
result = await startReview({
|
|
96
|
+
diffRef: `PR #${number}`,
|
|
97
|
+
title: metadata.title,
|
|
98
|
+
description: metadata.description,
|
|
99
|
+
reasoning: metadata.reasoning,
|
|
100
|
+
cwd: process.cwd(),
|
|
101
|
+
dev: flags.dev,
|
|
102
|
+
injectedPayload: payload
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
console.log(JSON.stringify(result, null, 2));
|
|
106
|
+
if (flags.postToGithub || result.decision !== "dismissed" && await promptPostToGithub()) {
|
|
107
|
+
console.log("Posting review to GitHub...");
|
|
108
|
+
const posted = await submitGitHubReview(client, owner, repo, number, result);
|
|
109
|
+
if (posted) {
|
|
110
|
+
console.log(`Review posted: ${prMetadata.url}#pullrequestreview-${posted.reviewId}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
process.exit(0);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
116
|
+
console.error(`Error: ${message}`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function pollForResult(httpPort, sessionId) {
|
|
121
|
+
const pollIntervalMs = 2e3;
|
|
122
|
+
const maxWaitMs = 600 * 1e3;
|
|
123
|
+
const start2 = Date.now();
|
|
124
|
+
while (Date.now() - start2 < maxWaitMs) {
|
|
125
|
+
const response = await fetch(
|
|
126
|
+
`http://localhost:${httpPort}/api/reviews/${sessionId}/result`
|
|
127
|
+
);
|
|
128
|
+
if (response.ok) {
|
|
129
|
+
const data = await response.json();
|
|
130
|
+
if (data.result) {
|
|
131
|
+
return data.result;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
135
|
+
}
|
|
136
|
+
throw new Error("Review timed out waiting for submission.");
|
|
137
|
+
}
|
|
138
|
+
async function promptPostToGithub() {
|
|
139
|
+
if (!process.stdin.isTTY) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const rl = readline.createInterface({
|
|
143
|
+
input: process.stdin,
|
|
144
|
+
output: process.stdout
|
|
145
|
+
});
|
|
146
|
+
return new Promise((resolve) => {
|
|
147
|
+
rl.question("Post this review to GitHub? (y/N) ", (answer) => {
|
|
148
|
+
rl.close();
|
|
149
|
+
resolve(answer.toLowerCase() === "y");
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
42
154
|
// cli/src/commands/serve.ts
|
|
43
155
|
async function serve() {
|
|
44
156
|
const { startMcpServer } = await import("./mcp-server.js");
|
|
@@ -49,7 +161,7 @@ async function serve() {
|
|
|
49
161
|
import fs from "fs";
|
|
50
162
|
import path from "path";
|
|
51
163
|
import os from "os";
|
|
52
|
-
import
|
|
164
|
+
import readline2 from "readline";
|
|
53
165
|
|
|
54
166
|
// cli/src/templates/skill.ts
|
|
55
167
|
var skillContent = `---
|
|
@@ -244,7 +356,8 @@ function setupClaudeSettings(baseDir, force) {
|
|
|
244
356
|
"mcp__diffprism__analyze_diff",
|
|
245
357
|
"mcp__diffprism__add_annotation",
|
|
246
358
|
"mcp__diffprism__get_review_state",
|
|
247
|
-
"mcp__diffprism__flag_for_attention"
|
|
359
|
+
"mcp__diffprism__flag_for_attention",
|
|
360
|
+
"mcp__diffprism__review_pr"
|
|
248
361
|
];
|
|
249
362
|
const allPresent = toolNames.every((t) => allow.includes(t));
|
|
250
363
|
if (allPresent && !force) {
|
|
@@ -344,7 +457,7 @@ function setupStopHook(gitRoot, force) {
|
|
|
344
457
|
return { action, filePath: filePath + " (Stop hook)" };
|
|
345
458
|
}
|
|
346
459
|
async function promptUser(question) {
|
|
347
|
-
const rl =
|
|
460
|
+
const rl = readline2.createInterface({
|
|
348
461
|
input: process.stdin,
|
|
349
462
|
output: process.stdout
|
|
350
463
|
});
|
|
@@ -479,7 +592,8 @@ function isGlobalSetupDone() {
|
|
|
479
592
|
"mcp__diffprism__analyze_diff",
|
|
480
593
|
"mcp__diffprism__add_annotation",
|
|
481
594
|
"mcp__diffprism__get_review_state",
|
|
482
|
-
"mcp__diffprism__flag_for_attention"
|
|
595
|
+
"mcp__diffprism__flag_for_attention",
|
|
596
|
+
"mcp__diffprism__review_pr"
|
|
483
597
|
];
|
|
484
598
|
return toolNames.every((t) => allow.includes(t));
|
|
485
599
|
}
|
|
@@ -887,8 +1001,9 @@ async function serverStop() {
|
|
|
887
1001
|
|
|
888
1002
|
// cli/src/index.ts
|
|
889
1003
|
var program = new Command();
|
|
890
|
-
program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.
|
|
1004
|
+
program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.33.0" : "0.0.0-dev");
|
|
891
1005
|
program.command("review [ref]").description("Open a browser-based diff review").option("--staged", "Review staged changes").option("--unstaged", "Review unstaged changes").option("-t, --title <title>", "Review title").option("--dev", "Use Vite dev server with HMR instead of static files").action(review);
|
|
1006
|
+
program.command("review-pr <pr>").description("Review a GitHub pull request in DiffPrism").option("-t, --title <title>", "Override review title").option("--reasoning <text>", "Agent reasoning about the PR").option("--dev", "Use Vite dev server with HMR instead of static files").option("--post-to-github", "Automatically post review back to GitHub without prompting").action(reviewPr);
|
|
892
1007
|
program.command("start [ref]").description("Set up DiffPrism and start watching for changes").option("--staged", "Watch staged changes").option("--unstaged", "Watch unstaged changes").option("-t, --title <title>", "Review title").option("--interval <ms>", "Poll interval in milliseconds (default: 1000)").option("--dev", "Use Vite dev server with HMR instead of static files").option("--global", "Install skill globally (~/.claude/skills/)").option("--force", "Overwrite existing configuration files").action(start);
|
|
893
1008
|
program.command("watch [ref]").description("Start a persistent diff watcher with live-updating browser UI").option("--staged", "Watch staged changes").option("--unstaged", "Watch unstaged changes").option("-t, --title <title>", "Review title").option("--interval <ms>", "Poll interval in milliseconds (default: 1000)").option("--dev", "Use Vite dev server with HMR instead of static files").action(watch);
|
|
894
1009
|
program.command("notify-stop").description("Signal the watch server to refresh (used by Claude Code hooks)").action(notifyStop);
|