diffprism 0.45.0 → 0.47.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
CHANGED
|
@@ -102,6 +102,41 @@ diffprism review main..feature # Branch diff
|
|
|
102
102
|
|
|
103
103
|
Running multiple Claude Code sessions? All reviews appear in one browser dashboard with status badges, branch info, and desktop notifications.
|
|
104
104
|
|
|
105
|
+
## Commit Gate
|
|
106
|
+
|
|
107
|
+
Review is only reliable if something other than memory triggers it. `diffprism hook`
|
|
108
|
+
wires the review into your pre-commit hook, so a substantial change opens a review
|
|
109
|
+
before it can land.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
diffprism hook install # Add the gate to this repo's pre-commit hook
|
|
113
|
+
diffprism hook uninstall # Remove it
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
By default a staged diff of **120+ changed lines** opens a review; anything smaller
|
|
117
|
+
commits untouched. A gate that stops every commit is one you learn to skip with
|
|
118
|
+
`--no-verify`, and a skipped gate is worse than none. Tune it per repo:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git config diffprism.gate-lines 200
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Approve and the commit proceeds. Request changes and the commit is blocked — with
|
|
125
|
+
your comments printed in the output, so the agent that ran `git commit` can read
|
|
126
|
+
what you asked for and fix it without another round trip:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
140 staged lines (gate at 120) — opening DiffPrism review...
|
|
130
|
+
|
|
131
|
+
feature.ts:12 [must_fix] these should be a single exported record
|
|
132
|
+
feature.ts:88 [question] is this range meant to be inclusive?
|
|
133
|
+
|
|
134
|
+
Commit blocked: the review requested changes.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Install adds one line between markers, so uninstall removes exactly that and leaves
|
|
138
|
+
the rest of your hook alone. Repos using `core.hooksPath` are handled.
|
|
139
|
+
|
|
105
140
|
## Features
|
|
106
141
|
|
|
107
142
|
- **AI-powered PR review** — Your AI gets full codebase context via 14 MCP tools
|
|
@@ -124,6 +159,8 @@ diffprism setup --global # Global setup (no git repo needed)
|
|
|
124
159
|
diffprism server # Start the background server
|
|
125
160
|
diffprism server status # Check server status
|
|
126
161
|
diffprism server stop # Stop the server
|
|
162
|
+
diffprism hook install # Gate commits on a review
|
|
163
|
+
diffprism hook uninstall # Remove the gate
|
|
127
164
|
diffprism teardown # Remove configuration
|
|
128
165
|
```
|
|
129
166
|
|
package/dist/bin.js
CHANGED
|
@@ -5,15 +5,17 @@ import {
|
|
|
5
5
|
} from "./chunk-24B33UN6.js";
|
|
6
6
|
import {
|
|
7
7
|
demo
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-TZ5SGWHP.js";
|
|
9
9
|
import {
|
|
10
10
|
ensureServer,
|
|
11
11
|
isServerAlive,
|
|
12
12
|
readServerFile,
|
|
13
13
|
startGlobalServer,
|
|
14
14
|
submitReviewToServer
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import
|
|
15
|
+
} from "./chunk-PQWU5NW4.js";
|
|
16
|
+
import {
|
|
17
|
+
getDiff
|
|
18
|
+
} from "./chunk-QGWYCEJN.js";
|
|
17
19
|
import "./chunk-DHCVZGHE.js";
|
|
18
20
|
import "./chunk-JSBRDJBE.js";
|
|
19
21
|
|
|
@@ -39,21 +41,26 @@ async function review(ref, flags) {
|
|
|
39
41
|
await reviewLocalFlow(diffRef, flags);
|
|
40
42
|
}
|
|
41
43
|
} catch (err) {
|
|
42
|
-
const
|
|
43
|
-
console.error(`Error: ${
|
|
44
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
45
|
+
console.error(`Error: ${message2}`);
|
|
44
46
|
process.exit(1);
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
async function reviewLocalFlow(diffRef, flags) {
|
|
48
50
|
const serverInfo = await ensureServer({ dev: flags.dev });
|
|
49
|
-
console.
|
|
51
|
+
console.error("Opening review in browser...");
|
|
50
52
|
const { result } = await submitReviewToServer(serverInfo, diffRef, {
|
|
51
53
|
title: flags.title,
|
|
52
54
|
cwd: process.cwd(),
|
|
53
55
|
diffRef
|
|
54
56
|
});
|
|
55
57
|
console.log(JSON.stringify(result, null, 2));
|
|
56
|
-
|
|
58
|
+
if (!result) {
|
|
59
|
+
console.error("No review result was returned.");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
const approved = result.decision === "approved" || result.decision === "approved_with_comments";
|
|
63
|
+
process.exit(approved ? 0 : 1);
|
|
57
64
|
}
|
|
58
65
|
async function reviewPrFlow(pr, flags) {
|
|
59
66
|
const { owner, repo, number } = parsePrRef(pr);
|
|
@@ -370,7 +377,7 @@ async function setupInteractive(flags) {
|
|
|
370
377
|
}
|
|
371
378
|
async function runDemo(dev) {
|
|
372
379
|
console.log("");
|
|
373
|
-
const { demo: demo2 } = await import("./demo-
|
|
380
|
+
const { demo: demo2 } = await import("./demo-H2NAMKCT.js");
|
|
374
381
|
await demo2({ dev });
|
|
375
382
|
}
|
|
376
383
|
async function setupBatch(flags) {
|
|
@@ -703,9 +710,9 @@ async function server(flags) {
|
|
|
703
710
|
await new Promise(() => {
|
|
704
711
|
});
|
|
705
712
|
} catch (err) {
|
|
706
|
-
const
|
|
713
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
707
714
|
if (!isDaemon) {
|
|
708
|
-
console.error(`Error starting server: ${
|
|
715
|
+
console.error(`Error starting server: ${message2}`);
|
|
709
716
|
}
|
|
710
717
|
process.exit(1);
|
|
711
718
|
}
|
|
@@ -778,8 +785,8 @@ async function serverStatus() {
|
|
|
778
785
|
}
|
|
779
786
|
}
|
|
780
787
|
} catch (err) {
|
|
781
|
-
const
|
|
782
|
-
console.error(`Error checking server status: ${
|
|
788
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
789
|
+
console.error(`Error checking server status: ${message2}`);
|
|
783
790
|
process.exit(1);
|
|
784
791
|
}
|
|
785
792
|
}
|
|
@@ -813,7 +820,7 @@ async function fetchStatus(httpPort) {
|
|
|
813
820
|
return await response.json();
|
|
814
821
|
}
|
|
815
822
|
function printStatus(status, httpPort) {
|
|
816
|
-
const version = true ? "0.
|
|
823
|
+
const version = true ? "0.47.0" : "0.0.0-dev";
|
|
817
824
|
console.log(`
|
|
818
825
|
DiffPrism v${version}
|
|
819
826
|
`);
|
|
@@ -845,19 +852,211 @@ async function defaultAction() {
|
|
|
845
852
|
await open(status.uiUrl);
|
|
846
853
|
}
|
|
847
854
|
} catch (err) {
|
|
848
|
-
const
|
|
849
|
-
console.error(`Error fetching server status: ${
|
|
855
|
+
const message2 = err instanceof Error ? err.message : String(err);
|
|
856
|
+
console.error(`Error fetching server status: ${message2}`);
|
|
850
857
|
process.exit(1);
|
|
851
858
|
}
|
|
852
859
|
}
|
|
853
860
|
|
|
861
|
+
// cli/src/commands/hook.ts
|
|
862
|
+
import { execFileSync } from "child_process";
|
|
863
|
+
import fs4 from "fs";
|
|
864
|
+
import path4 from "path";
|
|
865
|
+
var DEFAULT_MIN_LINES = 120;
|
|
866
|
+
var MARKER_START = "# >>> diffprism >>>";
|
|
867
|
+
var MARKER_END = "# <<< diffprism <<<";
|
|
868
|
+
var HOOK_LINE = "diffprism hook pre-commit || exit 1";
|
|
869
|
+
async function preCommitHook(flags = {}) {
|
|
870
|
+
const cwd = process.cwd();
|
|
871
|
+
const minLines = resolveMinLines(flags, cwd);
|
|
872
|
+
let changedLines;
|
|
873
|
+
try {
|
|
874
|
+
const { diffSet } = getDiff("staged", { cwd });
|
|
875
|
+
changedLines = diffSet.files.reduce(
|
|
876
|
+
(total, file) => total + file.additions + file.deletions,
|
|
877
|
+
0
|
|
878
|
+
);
|
|
879
|
+
} catch (err) {
|
|
880
|
+
fail(`Could not read the staged diff: ${message(err)}`);
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
if (changedLines === 0) {
|
|
884
|
+
process.exit(0);
|
|
885
|
+
}
|
|
886
|
+
if (changedLines < minLines) {
|
|
887
|
+
process.exit(0);
|
|
888
|
+
}
|
|
889
|
+
console.error(
|
|
890
|
+
`${changedLines} staged lines (gate at ${minLines}) \u2014 opening DiffPrism review...`
|
|
891
|
+
);
|
|
892
|
+
let review2 = null;
|
|
893
|
+
try {
|
|
894
|
+
const serverInfo = await ensureServer({ dev: flags.dev });
|
|
895
|
+
const { result } = await submitReviewToServer(serverInfo, "staged", {
|
|
896
|
+
cwd,
|
|
897
|
+
diffRef: "staged",
|
|
898
|
+
title: "Pre-commit review"
|
|
899
|
+
});
|
|
900
|
+
review2 = result;
|
|
901
|
+
} catch (err) {
|
|
902
|
+
fail(`DiffPrism could not run the review: ${message(err)}`);
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
const decision = review2?.decision;
|
|
906
|
+
if (decision === "approved" || decision === "approved_with_comments") {
|
|
907
|
+
console.error(`Review: ${decision} \u2014 proceeding.`);
|
|
908
|
+
process.exit(0);
|
|
909
|
+
}
|
|
910
|
+
if (decision === "changes_requested") {
|
|
911
|
+
printComments(review2?.comments ?? []);
|
|
912
|
+
fail("Commit blocked: the review requested changes.");
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
if (decision === "dismissed") {
|
|
916
|
+
fail("Commit blocked: the review was dismissed without a decision.");
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
fail(
|
|
920
|
+
`Commit blocked: no review decision was returned (got ${String(decision)}).`
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
function printComments(comments) {
|
|
924
|
+
if (comments.length === 0) {
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
console.error("");
|
|
928
|
+
for (const c of comments) {
|
|
929
|
+
console.error(` ${c.file}:${c.line} [${c.type}] ${c.body}`);
|
|
930
|
+
}
|
|
931
|
+
console.error("");
|
|
932
|
+
}
|
|
933
|
+
function installHook() {
|
|
934
|
+
const hookPath = resolveHookPath(process.cwd());
|
|
935
|
+
const existing = fs4.existsSync(hookPath) ? fs4.readFileSync(hookPath, "utf8") : "";
|
|
936
|
+
if (existing.includes(MARKER_START)) {
|
|
937
|
+
console.log(`Already installed in ${hookPath}`);
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const block = `${MARKER_START}
|
|
941
|
+
${HOOK_LINE}
|
|
942
|
+
${MARKER_END}
|
|
943
|
+
`;
|
|
944
|
+
const base = existing === "" ? "#!/bin/sh\n" : ensureTrailingNewline(existing);
|
|
945
|
+
const created = existing === "";
|
|
946
|
+
fs4.mkdirSync(path4.dirname(hookPath), { recursive: true });
|
|
947
|
+
fs4.writeFileSync(hookPath, `${base}
|
|
948
|
+
${block}`);
|
|
949
|
+
fs4.chmodSync(hookPath, 493);
|
|
950
|
+
console.log(`${created ? "Created" : "Updated"} ${hookPath}`);
|
|
951
|
+
console.log(
|
|
952
|
+
`Staged changes of ${DEFAULT_MIN_LINES}+ lines now open a review before the commit lands.`
|
|
953
|
+
);
|
|
954
|
+
console.log("Tune with: git config diffprism.gate-lines <n>");
|
|
955
|
+
console.log("Remove with: diffprism hook uninstall");
|
|
956
|
+
}
|
|
957
|
+
function uninstallHook() {
|
|
958
|
+
const hookPath = resolveHookPath(process.cwd());
|
|
959
|
+
if (!fs4.existsSync(hookPath)) {
|
|
960
|
+
console.log("Nothing to remove \u2014 no hook file.");
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
const existing = fs4.readFileSync(hookPath, "utf8");
|
|
964
|
+
if (!existing.includes(MARKER_START)) {
|
|
965
|
+
console.log(`Nothing to remove \u2014 no diffprism block in ${hookPath}`);
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
const cleaned = removeMarkedBlock(existing);
|
|
969
|
+
if (/^\s*(#![^\n]*)?\s*$/.test(cleaned)) {
|
|
970
|
+
fs4.rmSync(hookPath);
|
|
971
|
+
console.log(`Removed ${hookPath} (it contained nothing else).`);
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
fs4.writeFileSync(hookPath, cleaned);
|
|
975
|
+
console.log(`Removed the diffprism block from ${hookPath}`);
|
|
976
|
+
}
|
|
977
|
+
function removeMarkedBlock(contents) {
|
|
978
|
+
const lines = contents.split("\n");
|
|
979
|
+
const out = [];
|
|
980
|
+
let inside = false;
|
|
981
|
+
for (const line of lines) {
|
|
982
|
+
if (line.trim() === MARKER_START) {
|
|
983
|
+
inside = true;
|
|
984
|
+
continue;
|
|
985
|
+
}
|
|
986
|
+
if (line.trim() === MARKER_END) {
|
|
987
|
+
inside = false;
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
if (!inside) {
|
|
991
|
+
out.push(line);
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
return ensureTrailingNewline(out.join("\n").replace(/\n{3,}/g, "\n\n"));
|
|
995
|
+
}
|
|
996
|
+
function resolveMinLines(flags, cwd) {
|
|
997
|
+
const fromFlag = flags.minLines ? Number.parseInt(flags.minLines, 10) : NaN;
|
|
998
|
+
if (Number.isFinite(fromFlag) && fromFlag > 0) {
|
|
999
|
+
return fromFlag;
|
|
1000
|
+
}
|
|
1001
|
+
const configured = Number.parseInt(
|
|
1002
|
+
git(["config", "--get", "diffprism.gate-lines"], cwd) ?? "",
|
|
1003
|
+
10
|
|
1004
|
+
);
|
|
1005
|
+
if (Number.isFinite(configured) && configured > 0) {
|
|
1006
|
+
return configured;
|
|
1007
|
+
}
|
|
1008
|
+
return DEFAULT_MIN_LINES;
|
|
1009
|
+
}
|
|
1010
|
+
function resolveHookPath(cwd) {
|
|
1011
|
+
const configured = git(["config", "--get", "core.hooksPath"], cwd);
|
|
1012
|
+
if (configured) {
|
|
1013
|
+
return path4.resolve(cwd, configured, "pre-commit");
|
|
1014
|
+
}
|
|
1015
|
+
const hooksDir = git(["rev-parse", "--git-path", "hooks"], cwd) ?? ".git/hooks";
|
|
1016
|
+
return path4.resolve(cwd, hooksDir, "pre-commit");
|
|
1017
|
+
}
|
|
1018
|
+
function git(args, cwd) {
|
|
1019
|
+
try {
|
|
1020
|
+
const out = execFileSync("git", args, {
|
|
1021
|
+
cwd,
|
|
1022
|
+
encoding: "utf8",
|
|
1023
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
1024
|
+
});
|
|
1025
|
+
const trimmed = out.trim();
|
|
1026
|
+
return trimmed === "" ? null : trimmed;
|
|
1027
|
+
} catch {
|
|
1028
|
+
return null;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function ensureTrailingNewline(text) {
|
|
1032
|
+
return text.endsWith("\n") ? text : `${text}
|
|
1033
|
+
`;
|
|
1034
|
+
}
|
|
1035
|
+
function message(err) {
|
|
1036
|
+
return err instanceof Error ? err.message : String(err);
|
|
1037
|
+
}
|
|
1038
|
+
function fail(text) {
|
|
1039
|
+
console.error(text);
|
|
1040
|
+
process.exit(1);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
854
1043
|
// cli/src/index.ts
|
|
855
1044
|
var program = new Command();
|
|
856
|
-
program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.
|
|
1045
|
+
program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.47.0" : "0.0.0-dev");
|
|
857
1046
|
program.action(defaultAction);
|
|
858
1047
|
program.command("demo").description("Open a sample review to see DiffPrism in action").option("--dev", "Use Vite dev server").action(demo);
|
|
859
1048
|
program.command("review [ref]").description("Open a browser-based diff review (local git ref or GitHub PR ref like owner/repo#123)").option("--staged", "Review staged changes").option("--unstaged", "Review unstaged changes").option("-t, --title <title>", "Review title").option("--reasoning <text>", "Agent reasoning about the changes").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(review);
|
|
860
1049
|
program.command("review-pr <pr>", { hidden: true }).action((pr, flags) => review(pr, flags));
|
|
1050
|
+
var hookCmd = program.command("hook").description("Git hook integration \u2014 gate commits on a human review");
|
|
1051
|
+
hookCmd.command("pre-commit").description("Run the review gate for the staged changes (called from a git hook)").option("--min-lines <n>", "Staged lines required to trigger a review (default: 120)").option("--dev", "Use Vite dev server").action((flags) => {
|
|
1052
|
+
void preCommitHook(flags);
|
|
1053
|
+
});
|
|
1054
|
+
hookCmd.command("install").description("Add the diffprism gate to this repo's pre-commit hook").action(() => {
|
|
1055
|
+
installHook();
|
|
1056
|
+
});
|
|
1057
|
+
hookCmd.command("uninstall").description("Remove the diffprism gate from this repo's pre-commit hook").action(() => {
|
|
1058
|
+
uninstallHook();
|
|
1059
|
+
});
|
|
861
1060
|
program.command("serve").description("Start the MCP server for Claude Code integration").action(serve);
|
|
862
1061
|
program.command("setup").description("Configure DiffPrism for Claude Code integration").option("--global", "Configure globally (skill + permissions, no git repo required)").option("--force", "Overwrite existing configuration files").option("--dev", "Use Vite dev server").option("--no-demo", "Skip the demo review after setup").action((flags) => {
|
|
863
1062
|
setup(flags);
|
|
@@ -122,30 +122,45 @@ function buildDefaultSpawnCommand(options) {
|
|
|
122
122
|
const thisDir = path2.dirname(thisFile);
|
|
123
123
|
const workspaceRoot = path2.resolve(thisDir, "..", "..", "..");
|
|
124
124
|
const devBin = path2.join(workspaceRoot, "cli", "bin", "diffprism.mjs");
|
|
125
|
-
let binPath = "diffprism";
|
|
126
125
|
if (fs2.existsSync(devBin)) {
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
126
|
+
return withDevFlag([process.execPath, devBin, "server", "--_daemon"], options);
|
|
127
|
+
}
|
|
128
|
+
let searchDir = thisDir;
|
|
129
|
+
while (searchDir !== path2.dirname(searchDir)) {
|
|
130
|
+
const ownBin = readOwnBinPath(searchDir);
|
|
131
|
+
if (ownBin) {
|
|
132
|
+
return withDevFlag(
|
|
133
|
+
[process.execPath, ownBin, "server", "--_daemon"],
|
|
134
|
+
options
|
|
136
135
|
);
|
|
137
|
-
if (fs2.existsSync(candidate)) {
|
|
138
|
-
binPath = candidate;
|
|
139
|
-
break;
|
|
140
|
-
}
|
|
141
|
-
searchDir = path2.dirname(searchDir);
|
|
142
136
|
}
|
|
137
|
+
const shim = path2.join(searchDir, "node_modules", ".bin", "diffprism");
|
|
138
|
+
if (fs2.existsSync(shim)) {
|
|
139
|
+
return withDevFlag([shim, "server", "--_daemon"], options);
|
|
140
|
+
}
|
|
141
|
+
searchDir = path2.dirname(searchDir);
|
|
142
|
+
}
|
|
143
|
+
return withDevFlag(["diffprism", "server", "--_daemon"], options);
|
|
144
|
+
}
|
|
145
|
+
function withDevFlag(args, options) {
|
|
146
|
+
return options.dev ? [...args, "--dev"] : args;
|
|
147
|
+
}
|
|
148
|
+
function readOwnBinPath(dir) {
|
|
149
|
+
const manifestPath = path2.join(dir, "package.json");
|
|
150
|
+
if (!fs2.existsSync(manifestPath)) {
|
|
151
|
+
return null;
|
|
143
152
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
153
|
+
try {
|
|
154
|
+
const manifest = JSON.parse(fs2.readFileSync(manifestPath, "utf8"));
|
|
155
|
+
const entry = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.diffprism;
|
|
156
|
+
if (!entry) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const resolved = path2.resolve(dir, entry);
|
|
160
|
+
return fs2.existsSync(resolved) ? resolved : null;
|
|
161
|
+
} catch {
|
|
162
|
+
return null;
|
|
147
163
|
}
|
|
148
|
-
return args;
|
|
149
164
|
}
|
|
150
165
|
async function submitReviewToServer(serverInfo, diffRef, options = {}) {
|
|
151
166
|
const cwd = options.cwd ?? process.cwd();
|
package/dist/mcp-server.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
ensureServer,
|
|
7
7
|
isServerAlive,
|
|
8
8
|
submitReviewToServer
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PQWU5NW4.js";
|
|
10
10
|
import {
|
|
11
11
|
getDiff
|
|
12
12
|
} from "./chunk-QGWYCEJN.js";
|
|
@@ -144,7 +144,7 @@ async function handlePrReview(pr, options) {
|
|
|
144
144
|
async function startMcpServer() {
|
|
145
145
|
const server = new McpServer({
|
|
146
146
|
name: "diffprism",
|
|
147
|
-
version: true ? "0.
|
|
147
|
+
version: true ? "0.47.0" : "0.0.0-dev"
|
|
148
148
|
});
|
|
149
149
|
server.tool(
|
|
150
150
|
"open_review",
|