diffprism 1.3.3 → 1.4.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/README.md +1 -1
- package/dist/bin.js +7 -5
- package/dist/{chunk-4PXCENR6.js → chunk-6P6QJPWT.js} +2 -2
- package/dist/{chunk-3GMPE2ZR.js → chunk-GGK6TIQZ.js} +22 -0
- package/dist/{chunk-EPU4F7WT.js → chunk-RFDSC6MC.js} +1 -1
- package/dist/{chunk-UWIDAULW.js → chunk-SCQFIDIK.js} +46 -33
- package/dist/{demo-WOT5AZBP.js → demo-GHOE7YNU.js} +3 -3
- package/dist/mcp-server.js +5 -5
- package/dist/{src-DNNNQ2RD.js → src-LLACFIIT.js} +2 -2
- package/dist/{src-OZQ32NDN.js → src-XT4XP6TC.js} +3 -1
- package/package.json +1 -1
- package/ui-dist/assets/index-C_mA2r7X.js +350 -0
- package/ui-dist/assets/index-DrWM7I5e.css +1 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/index-BulxhOr3.css +0 -1
- package/ui-dist/assets/index-DPjdYQ0h.js +0 -345
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ Reviews are **one per repo**: opening a review for a repo that already has one u
|
|
|
89
89
|
|
|
90
90
|
In a local review, **Ask agent now** in a line's comment form asks the agent while you're still reviewing: the agent's wait for your decision ends with your question, it answers in the thread, and goes back to waiting.
|
|
91
91
|
|
|
92
|
-
PR reviews are opened with `diffprism review <PR URL>` or the dashboard — not by `open_review` — and your AI then works inside them with the tools above. Click a line to ask the agent about it; an agent listening with `wait_for_comments` answers in the thread.
|
|
92
|
+
PR reviews are opened with `diffprism review <PR URL>` or the dashboard — not by `open_review` — and your AI then works inside them with the tools above. Click a line to ask the agent about it; an agent listening with `wait_for_comments` answers in the thread. Nothing starts an agent for you: if none has picked a question up, the thread says so and names the session to ask Claude Code about.
|
|
93
93
|
|
|
94
94
|
When you're done, **Approve**, **Request changes** or **Comment** from the bar at the bottom: DiffPrism posts it to GitHub as a pull request review. Your threads are a conversation with the agent, so none of them goes to GitHub unless you tick it; a ticked thread posts your opening message as an inline review comment. The token comes from `GITHUB_TOKEN`, `gh auth token`, or `~/.diffprism/config.json`.
|
|
95
95
|
|
package/dist/bin.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
isPrRef,
|
|
4
4
|
parsePrRef
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RFDSC6MC.js";
|
|
6
6
|
import {
|
|
7
7
|
demo
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-6P6QJPWT.js";
|
|
9
9
|
import {
|
|
10
10
|
COMMIT_GATE_DIFF_REF,
|
|
11
11
|
DEFAULT_DIFF_REF,
|
|
@@ -26,10 +26,10 @@ import {
|
|
|
26
26
|
recordError,
|
|
27
27
|
startGlobalServer,
|
|
28
28
|
submitReviewToServer
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-SCQFIDIK.js";
|
|
30
30
|
import {
|
|
31
31
|
getDiff
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-GGK6TIQZ.js";
|
|
33
33
|
import "./chunk-DHCVZGHE.js";
|
|
34
34
|
import "./chunk-JSBRDJBE.js";
|
|
35
35
|
|
|
@@ -518,6 +518,8 @@ The reviewer can also ask you questions on lines of the PR. Hold that conversati
|
|
|
518
518
|
2. \`mcp__diffprism__reply\` \u2014 answer each thread, passing its \`annotation_id\`.
|
|
519
519
|
3. Wait again. On \`timed_out\`, nothing new was said \u2014 keep waiting until the user tells you to stop.
|
|
520
520
|
|
|
521
|
+
When no agent has read a question, the dashboard tells the reviewer so, and to ask you to answer their DiffPrism comments on a session id. When they do, run this loop with that \`session_id\`.
|
|
522
|
+
|
|
521
523
|
A PR review and a working-copy review can be open for the same clone at once. If a tool reports more than one session, pass the \`session_id\` of the one you mean.
|
|
522
524
|
|
|
523
525
|
## Tool Reference
|
|
@@ -719,7 +721,7 @@ async function setupInteractive(flags) {
|
|
|
719
721
|
}
|
|
720
722
|
async function runDemo(dev) {
|
|
721
723
|
console.log("");
|
|
722
|
-
const { demo: demo2 } = await import("./demo-
|
|
724
|
+
const { demo: demo2 } = await import("./demo-GHOE7YNU.js");
|
|
723
725
|
await demo2({ dev });
|
|
724
726
|
}
|
|
725
727
|
async function setupBatch(flags) {
|
|
@@ -210,6 +210,27 @@ function getRepoRoot(options) {
|
|
|
210
210
|
return null;
|
|
211
211
|
}
|
|
212
212
|
}
|
|
213
|
+
function getGitHubRemotes(options) {
|
|
214
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
215
|
+
let output;
|
|
216
|
+
try {
|
|
217
|
+
output = execSync("git remote -v", {
|
|
218
|
+
cwd,
|
|
219
|
+
encoding: "utf-8",
|
|
220
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
221
|
+
});
|
|
222
|
+
} catch {
|
|
223
|
+
return [];
|
|
224
|
+
}
|
|
225
|
+
const repos = /* @__PURE__ */ new Set();
|
|
226
|
+
for (const line of output.split("\n")) {
|
|
227
|
+
const match = /github\.com[:/]([^/\s]+)\/([^/\s]+?)(?:\.git)?\s/i.exec(line);
|
|
228
|
+
if (match) {
|
|
229
|
+
repos.add(`${match[1]}/${match[2]}`.toLowerCase());
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return Array.from(repos);
|
|
233
|
+
}
|
|
213
234
|
|
|
214
235
|
// packages/git/src/parser.ts
|
|
215
236
|
import path2 from "path";
|
|
@@ -456,6 +477,7 @@ export {
|
|
|
456
477
|
listCommits,
|
|
457
478
|
detectWorktree,
|
|
458
479
|
getRepoRoot,
|
|
480
|
+
getGitHubRemotes,
|
|
459
481
|
parseDiff,
|
|
460
482
|
getDiff
|
|
461
483
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getCurrentBranch,
|
|
3
3
|
getDiff,
|
|
4
|
+
getGitHubRemotes,
|
|
4
5
|
getRepoRoot,
|
|
5
6
|
listBranches,
|
|
6
7
|
listCommits
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GGK6TIQZ.js";
|
|
8
9
|
import {
|
|
9
10
|
analyze
|
|
10
11
|
} from "./chunk-DHCVZGHE.js";
|
|
@@ -79,12 +80,28 @@ async function isServerAlive() {
|
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
// packages/core/src/threads.ts
|
|
84
|
+
function lastAuthor(annotation) {
|
|
85
|
+
const replies = annotation.replies ?? [];
|
|
86
|
+
return replies.length > 0 ? replies[replies.length - 1].author : annotation.author ?? "agent";
|
|
87
|
+
}
|
|
88
|
+
function awaitingAgent(annotation) {
|
|
89
|
+
return !annotation.dismissed && lastAuthor(annotation) === "reviewer";
|
|
90
|
+
}
|
|
91
|
+
function lastMessageAt(annotation) {
|
|
92
|
+
const replies = annotation.replies ?? [];
|
|
93
|
+
return replies.length > 0 ? replies[replies.length - 1].createdAt : annotation.createdAt;
|
|
94
|
+
}
|
|
95
|
+
function pickedUpByAgent(annotation, agentReadAt) {
|
|
96
|
+
return agentReadAt !== void 0 && agentReadAt > lastMessageAt(annotation);
|
|
97
|
+
}
|
|
98
|
+
|
|
82
99
|
// packages/core/src/build-info.ts
|
|
83
100
|
import fs2 from "fs";
|
|
84
101
|
import path2 from "path";
|
|
85
102
|
import { fileURLToPath } from "url";
|
|
86
103
|
function builtAt() {
|
|
87
|
-
return true ?
|
|
104
|
+
return true ? 1789619773143 : null;
|
|
88
105
|
}
|
|
89
106
|
function getBuildInfo() {
|
|
90
107
|
let dir = path2.dirname(fileURLToPath(import.meta.url));
|
|
@@ -122,7 +139,7 @@ import path3 from "path";
|
|
|
122
139
|
var ISSUES_NEW_URL = "https://github.com/CodeJonesW/diffprism/issues/new";
|
|
123
140
|
var MAX_ERROR_CHARS = 1500;
|
|
124
141
|
function currentVersion() {
|
|
125
|
-
return true ? "1.
|
|
142
|
+
return true ? "1.4.0" : "0.0.0-dev";
|
|
126
143
|
}
|
|
127
144
|
function describeEnvironment() {
|
|
128
145
|
return {
|
|
@@ -211,15 +228,6 @@ ${errorText}
|
|
|
211
228
|
return `${ISSUES_NEW_URL}?${params.toString()}`;
|
|
212
229
|
}
|
|
213
230
|
|
|
214
|
-
// packages/core/src/threads.ts
|
|
215
|
-
function lastAuthor(annotation) {
|
|
216
|
-
const replies = annotation.replies ?? [];
|
|
217
|
-
return replies.length > 0 ? replies[replies.length - 1].author : annotation.author ?? "agent";
|
|
218
|
-
}
|
|
219
|
-
function awaitingAgent(annotation) {
|
|
220
|
-
return !annotation.dismissed && lastAuthor(annotation) === "reviewer";
|
|
221
|
-
}
|
|
222
|
-
|
|
223
231
|
// packages/core/src/server-client.ts
|
|
224
232
|
import { spawn } from "child_process";
|
|
225
233
|
import fs4 from "fs";
|
|
@@ -393,7 +401,7 @@ async function waitForDecision(serverInfo, sessionId, maxWaitMs, pollIntervalMs
|
|
|
393
401
|
if (result) {
|
|
394
402
|
return result;
|
|
395
403
|
}
|
|
396
|
-
const annotationsResponse = await fetch(`${base}/annotations`);
|
|
404
|
+
const annotationsResponse = await fetch(`${base}/annotations?reader=agent`);
|
|
397
405
|
if (!annotationsResponse.ok) {
|
|
398
406
|
throw new Error(`Could not read threads for ${sessionId}: server returned ${annotationsResponse.status}`);
|
|
399
407
|
}
|
|
@@ -413,7 +421,7 @@ async function submitReviewToServer(serverInfo, diffRef, options = {}) {
|
|
|
413
421
|
if (options.injectedPayload) {
|
|
414
422
|
payload = options.injectedPayload;
|
|
415
423
|
} else {
|
|
416
|
-
const { getDiff: getDiff2, getCurrentBranch: getCurrentBranch2, detectWorktree } = await import("./src-
|
|
424
|
+
const { getDiff: getDiff2, getCurrentBranch: getCurrentBranch2, detectWorktree } = await import("./src-XT4XP6TC.js");
|
|
417
425
|
const { analyze: analyze2 } = await import("./src-JMPTSU3P.js");
|
|
418
426
|
const { diffSet, rawDiff } = getDiff2(diffRef, { cwd });
|
|
419
427
|
if (diffSet.files.length === 0) {
|
|
@@ -800,6 +808,14 @@ var IDLE_SESSION_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
|
800
808
|
function touch(session) {
|
|
801
809
|
session.lastActivityAt = Date.now();
|
|
802
810
|
}
|
|
811
|
+
function recordAgentRead(session) {
|
|
812
|
+
const previous = session.agentReadAt;
|
|
813
|
+
session.agentReadAt = Date.now();
|
|
814
|
+
touch(session);
|
|
815
|
+
if (session.annotations.some((a) => awaitingAgent(a) && !pickedUpByAgent(a, previous))) {
|
|
816
|
+
broadcastSessionUpdate(session);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
803
819
|
var sessions = /* @__PURE__ */ new Map();
|
|
804
820
|
function listedSummaries() {
|
|
805
821
|
return Array.from(sessions.values()).filter((session) => session.closedAt === void 0).map(toSummary);
|
|
@@ -943,7 +959,8 @@ function toSummary(session) {
|
|
|
943
959
|
hasNewChanges: session.hasNewChanges,
|
|
944
960
|
needsAttention: needsAttention(session),
|
|
945
961
|
diffRef: session.diffRef,
|
|
946
|
-
source: session.source
|
|
962
|
+
source: session.source,
|
|
963
|
+
agentReadAt: session.agentReadAt
|
|
947
964
|
};
|
|
948
965
|
}
|
|
949
966
|
function readBody(req) {
|
|
@@ -1260,7 +1277,7 @@ async function handleApiRequest(req, res) {
|
|
|
1260
1277
|
fetchPullRequest,
|
|
1261
1278
|
fetchPullRequestDiff,
|
|
1262
1279
|
normalizePr
|
|
1263
|
-
} = await import("./src-
|
|
1280
|
+
} = await import("./src-LLACFIIT.js");
|
|
1264
1281
|
if (!isPrRef(prUrl)) {
|
|
1265
1282
|
jsonResponse(res, 400, {
|
|
1266
1283
|
error: "Invalid PR URL. Expected https://github.com/owner/repo/pull/123 or owner/repo#123"
|
|
@@ -1283,20 +1300,7 @@ async function handleApiRequest(req, res) {
|
|
|
1283
1300
|
fetchPullRequestDiff(client, owner, repo, prNumber)
|
|
1284
1301
|
]);
|
|
1285
1302
|
const normalized = normalizePr(rawDiff, prMetadata);
|
|
1286
|
-
|
|
1287
|
-
try {
|
|
1288
|
-
const { execSync } = await import("child_process");
|
|
1289
|
-
const remoteOutput = execSync("git remote -v", {
|
|
1290
|
-
cwd: process.cwd(),
|
|
1291
|
-
encoding: "utf-8",
|
|
1292
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
1293
|
-
});
|
|
1294
|
-
const repoPattern = new RegExp(`github\\.com[:/]${owner}/${repo}(\\.git)?\\s`, "i");
|
|
1295
|
-
if (repoPattern.test(remoteOutput)) {
|
|
1296
|
-
localRepoPath = process.cwd();
|
|
1297
|
-
}
|
|
1298
|
-
} catch {
|
|
1299
|
-
}
|
|
1303
|
+
const localRepoPath = getGitHubRemotes({ cwd: process.cwd() }).includes(`${owner}/${repo}`.toLowerCase()) ? process.cwd() : null;
|
|
1300
1304
|
const { session, reused } = openSession({
|
|
1301
1305
|
key: `pr:${owner}/${repo}#${prNumber}`.toLowerCase(),
|
|
1302
1306
|
repoRoot: localRepoPath ? getRepoRoot({ cwd: localRepoPath }) ?? localRepoPath : null,
|
|
@@ -1373,7 +1377,13 @@ async function handleApiRequest(req, res) {
|
|
|
1373
1377
|
return true;
|
|
1374
1378
|
}
|
|
1375
1379
|
const repoRoot = getRepoRoot({ cwd: rawPath }) ?? path7.resolve(rawPath);
|
|
1376
|
-
const
|
|
1380
|
+
const remotes = getGitHubRemotes({ cwd: repoRoot });
|
|
1381
|
+
const matches = Array.from(sessions.values()).filter((session) => {
|
|
1382
|
+
if (session.closedAt !== void 0) return false;
|
|
1383
|
+
if (session.repoRoot === repoRoot) return true;
|
|
1384
|
+
const pr = session.payload.metadata.githubPr;
|
|
1385
|
+
return pr !== void 0 && remotes.includes(`${pr.owner}/${pr.repo}`.toLowerCase());
|
|
1386
|
+
}).map(toSummary);
|
|
1377
1387
|
jsonResponse(res, 200, { repoRoot, sessions: matches });
|
|
1378
1388
|
return true;
|
|
1379
1389
|
}
|
|
@@ -1527,6 +1537,9 @@ async function handleApiRequest(req, res) {
|
|
|
1527
1537
|
jsonResponse(res, 404, { error: "Session not found" });
|
|
1528
1538
|
return true;
|
|
1529
1539
|
}
|
|
1540
|
+
if (new URL(req.url ?? "/", "http://localhost").searchParams.get("reader") === "agent") {
|
|
1541
|
+
recordAgentRead(session);
|
|
1542
|
+
}
|
|
1530
1543
|
jsonResponse(res, 200, { annotations: session.annotations });
|
|
1531
1544
|
return true;
|
|
1532
1545
|
}
|
|
@@ -1592,7 +1605,7 @@ async function handleApiRequest(req, res) {
|
|
|
1592
1605
|
jsonResponse(res, 400, { error: built.error });
|
|
1593
1606
|
return true;
|
|
1594
1607
|
}
|
|
1595
|
-
const { resolveGitHubToken, createGitHubClient, submitGitHubReview } = await import("./src-
|
|
1608
|
+
const { resolveGitHubToken, createGitHubClient, submitGitHubReview } = await import("./src-LLACFIIT.js");
|
|
1596
1609
|
let token;
|
|
1597
1610
|
try {
|
|
1598
1611
|
token = resolveGitHubToken();
|
|
@@ -2072,6 +2085,7 @@ function mcpToolPermission(name) {
|
|
|
2072
2085
|
export {
|
|
2073
2086
|
readServerFile,
|
|
2074
2087
|
isServerAlive,
|
|
2088
|
+
awaitingAgent,
|
|
2075
2089
|
getBuildInfo,
|
|
2076
2090
|
describeVersion,
|
|
2077
2091
|
DEFAULT_DIFF_REF,
|
|
@@ -2083,7 +2097,6 @@ export {
|
|
|
2083
2097
|
REPORT_HINT,
|
|
2084
2098
|
buildFeedbackUrl,
|
|
2085
2099
|
startGlobalServer,
|
|
2086
|
-
awaitingAgent,
|
|
2087
2100
|
ensureServer,
|
|
2088
2101
|
ReviewTimeoutError,
|
|
2089
2102
|
ReviewerAskedError,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
demo
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-6P6QJPWT.js";
|
|
4
|
+
import "./chunk-SCQFIDIK.js";
|
|
5
|
+
import "./chunk-GGK6TIQZ.js";
|
|
6
6
|
import "./chunk-DHCVZGHE.js";
|
|
7
7
|
import "./chunk-JSBRDJBE.js";
|
|
8
8
|
export {
|
package/dist/mcp-server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isPrRef
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RFDSC6MC.js";
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_DIFF_REF,
|
|
6
6
|
DIFF_REF_DESCRIPTION,
|
|
@@ -14,10 +14,10 @@ import {
|
|
|
14
14
|
recordError,
|
|
15
15
|
submitReviewToServer,
|
|
16
16
|
waitForDecision
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-SCQFIDIK.js";
|
|
18
18
|
import {
|
|
19
19
|
getDiff
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-GGK6TIQZ.js";
|
|
21
21
|
import {
|
|
22
22
|
analyze
|
|
23
23
|
} from "./chunk-DHCVZGHE.js";
|
|
@@ -73,7 +73,7 @@ ${candidates}`
|
|
|
73
73
|
}
|
|
74
74
|
async function readThreads(serverInfo, sessionId) {
|
|
75
75
|
const response = await fetch(
|
|
76
|
-
`http://localhost:${serverInfo.httpPort}/api/reviews/${sessionId}/annotations`
|
|
76
|
+
`http://localhost:${serverInfo.httpPort}/api/reviews/${sessionId}/annotations?reader=agent`
|
|
77
77
|
);
|
|
78
78
|
if (!response.ok) {
|
|
79
79
|
return null;
|
|
@@ -354,7 +354,7 @@ ${REPORT_HINT}`);
|
|
|
354
354
|
async ({ session_id, repo_path }) => withSession({ session_id, repo_path }, async ({ serverInfo, sessionId }) => {
|
|
355
355
|
const [sessionResponse, annotationsResponse] = await Promise.all([
|
|
356
356
|
fetch(`http://localhost:${serverInfo.httpPort}/api/reviews/${sessionId}`),
|
|
357
|
-
fetch(`http://localhost:${serverInfo.httpPort}/api/reviews/${sessionId}/annotations`)
|
|
357
|
+
fetch(`http://localhost:${serverInfo.httpPort}/api/reviews/${sessionId}/annotations?reader=agent`)
|
|
358
358
|
]);
|
|
359
359
|
if (!sessionResponse.ok) {
|
|
360
360
|
return toolError(`Session not found: ${sessionId}`);
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
parsePrRef,
|
|
8
8
|
resolveGitHubToken,
|
|
9
9
|
submitGitHubReview
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-RFDSC6MC.js";
|
|
11
|
+
import "./chunk-GGK6TIQZ.js";
|
|
12
12
|
import "./chunk-DHCVZGHE.js";
|
|
13
13
|
import "./chunk-JSBRDJBE.js";
|
|
14
14
|
export {
|
|
@@ -3,17 +3,19 @@ import {
|
|
|
3
3
|
getCurrentBranch,
|
|
4
4
|
getDiff,
|
|
5
5
|
getGitDiff,
|
|
6
|
+
getGitHubRemotes,
|
|
6
7
|
getRepoRoot,
|
|
7
8
|
listBranches,
|
|
8
9
|
listCommits,
|
|
9
10
|
parseDiff
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GGK6TIQZ.js";
|
|
11
12
|
import "./chunk-JSBRDJBE.js";
|
|
12
13
|
export {
|
|
13
14
|
detectWorktree,
|
|
14
15
|
getCurrentBranch,
|
|
15
16
|
getDiff,
|
|
16
17
|
getGitDiff,
|
|
18
|
+
getGitHubRemotes,
|
|
17
19
|
getRepoRoot,
|
|
18
20
|
listBranches,
|
|
19
21
|
listCommits,
|