diffprism 0.24.3 → 0.26.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 CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  startGlobalServer,
7
7
  startReview,
8
8
  startWatch
9
- } from "./chunk-PG4ERDT3.js";
9
+ } from "./chunk-BNCXGE4V.js";
10
10
 
11
11
  // cli/src/index.ts
12
12
  import { Command } from "commander";
@@ -836,7 +836,7 @@ async function serverStop() {
836
836
 
837
837
  // cli/src/index.ts
838
838
  var program = new Command();
839
- program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.24.3" : "0.0.0-dev");
839
+ program.name("diffprism").description("Local-first code review tool for agent-generated changes").version(true ? "0.26.0" : "0.0.0-dev");
840
840
  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);
841
841
  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);
842
842
  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);
@@ -65,6 +65,57 @@ function getCurrentBranch(options) {
65
65
  return "unknown";
66
66
  }
67
67
  }
68
+ function listBranches(options) {
69
+ const cwd = options?.cwd ?? process.cwd();
70
+ try {
71
+ const output = execSync(
72
+ "git branch -a --format='%(refname:short)' --sort=-committerdate",
73
+ { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
74
+ ).trim();
75
+ if (!output) return { local: [], remote: [] };
76
+ const local = [];
77
+ const remote = [];
78
+ for (const line of output.split("\n")) {
79
+ const name = line.trim();
80
+ if (!name) continue;
81
+ if (name.endsWith("/HEAD")) continue;
82
+ if (name.includes("/")) {
83
+ remote.push(name);
84
+ } else {
85
+ local.push(name);
86
+ }
87
+ }
88
+ return { local, remote };
89
+ } catch {
90
+ return { local: [], remote: [] };
91
+ }
92
+ }
93
+ function listCommits(options) {
94
+ const cwd = options?.cwd ?? process.cwd();
95
+ const limit = options?.limit ?? 50;
96
+ try {
97
+ const output = execSync(
98
+ `git log --format='%H<<>>%h<<>>%s<<>>%an<<>>%aI' -n ${limit}`,
99
+ { cwd, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
100
+ ).trim();
101
+ if (!output) return [];
102
+ const commits = [];
103
+ for (const line of output.split("\n")) {
104
+ const parts = line.split("<<>>");
105
+ if (parts.length < 5) continue;
106
+ commits.push({
107
+ hash: parts[0],
108
+ shortHash: parts[1],
109
+ subject: parts[2],
110
+ author: parts[3],
111
+ date: parts[4]
112
+ });
113
+ }
114
+ return commits;
115
+ } catch {
116
+ return [];
117
+ }
118
+ }
68
119
  function getUntrackedDiffs(cwd) {
69
120
  let untrackedList;
70
121
  try {
@@ -1817,6 +1868,71 @@ async function handleApiRequest(req, res) {
1817
1868
  }
1818
1869
  return true;
1819
1870
  }
1871
+ const getRefsParams = matchRoute(method, url, "GET", "/api/reviews/:id/refs");
1872
+ if (getRefsParams) {
1873
+ const session = sessions2.get(getRefsParams.id);
1874
+ if (!session) {
1875
+ jsonResponse(res, 404, { error: "Session not found" });
1876
+ return true;
1877
+ }
1878
+ try {
1879
+ const branches = listBranches({ cwd: session.projectPath });
1880
+ const commits = listCommits({ cwd: session.projectPath });
1881
+ const currentBranch = getCurrentBranch({ cwd: session.projectPath });
1882
+ jsonResponse(res, 200, { branches, commits, currentBranch });
1883
+ } catch {
1884
+ jsonResponse(res, 500, { error: "Failed to list git refs" });
1885
+ }
1886
+ return true;
1887
+ }
1888
+ const postCompareParams = matchRoute(method, url, "POST", "/api/reviews/:id/compare");
1889
+ if (postCompareParams) {
1890
+ const session = sessions2.get(postCompareParams.id);
1891
+ if (!session) {
1892
+ jsonResponse(res, 404, { error: "Session not found" });
1893
+ return true;
1894
+ }
1895
+ try {
1896
+ const body = await readBody(req);
1897
+ const { ref } = JSON.parse(body);
1898
+ if (!ref) {
1899
+ jsonResponse(res, 400, { error: "Missing ref in request body" });
1900
+ return true;
1901
+ }
1902
+ const { diffSet: newDiffSet, rawDiff: newRawDiff } = getDiff(ref, {
1903
+ cwd: session.projectPath
1904
+ });
1905
+ const newBriefing = analyze(newDiffSet);
1906
+ const changedFiles = detectChangedFiles(session.lastDiffSet ?? null, newDiffSet);
1907
+ session.payload = {
1908
+ ...session.payload,
1909
+ diffSet: newDiffSet,
1910
+ rawDiff: newRawDiff,
1911
+ briefing: newBriefing
1912
+ };
1913
+ session.lastDiffHash = hashDiff(newRawDiff);
1914
+ session.lastDiffSet = newDiffSet;
1915
+ stopSessionWatcher(session.id);
1916
+ session.diffRef = ref;
1917
+ if (hasConnectedClients()) {
1918
+ startSessionWatcher(session.id);
1919
+ }
1920
+ sendToSessionClients(session.id, {
1921
+ type: "diff:update",
1922
+ payload: {
1923
+ diffSet: newDiffSet,
1924
+ rawDiff: newRawDiff,
1925
+ briefing: newBriefing,
1926
+ changedFiles,
1927
+ timestamp: Date.now()
1928
+ }
1929
+ });
1930
+ jsonResponse(res, 200, { ok: true, fileCount: newDiffSet.files.length });
1931
+ } catch {
1932
+ jsonResponse(res, 400, { error: "Failed to compute diff for the given ref" });
1933
+ }
1934
+ return true;
1935
+ }
1820
1936
  jsonResponse(res, 404, { error: "Not found" });
1821
1937
  return true;
1822
1938
  }
@@ -1976,7 +2092,7 @@ DiffPrism Global Server`);
1976
2092
  Waiting for reviews...
1977
2093
  `);
1978
2094
  }
1979
- const uiUrl = `http://localhost:${uiPort}?wsPort=${wsPort}&serverMode=true`;
2095
+ const uiUrl = `http://localhost:${uiPort}?wsPort=${wsPort}&httpPort=${httpPort}&serverMode=true`;
1980
2096
  await open3(uiUrl);
1981
2097
  reopenBrowserIfNeeded = () => {
1982
2098
  if (!hasConnectedClients()) {
@@ -7,7 +7,7 @@ import {
7
7
  readReviewResult,
8
8
  readWatchFile,
9
9
  startReview
10
- } from "./chunk-PG4ERDT3.js";
10
+ } from "./chunk-BNCXGE4V.js";
11
11
 
12
12
  // packages/mcp-server/src/index.ts
13
13
  import fs from "fs";
@@ -76,7 +76,7 @@ async function reviewViaGlobalServer(serverInfo, diffRef, options) {
76
76
  async function startMcpServer() {
77
77
  const server = new McpServer({
78
78
  name: "diffprism",
79
- version: true ? "0.24.3" : "0.0.0-dev"
79
+ version: true ? "0.26.0" : "0.0.0-dev"
80
80
  });
81
81
  server.tool(
82
82
  "open_review",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "diffprism",
3
- "version": "0.24.3",
3
+ "version": "0.26.0",
4
4
  "type": "module",
5
5
  "description": "Local-first code review tool for agent-generated code changes",
6
6
  "bin": {