diffprism 0.33.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.
- package/dist/bin.js +2 -2
- package/dist/{chunk-ZLIUNVTW.js → chunk-NJKYNMAQ.js} +147 -37
- package/dist/mcp-server.js +5 -5
- package/package.json +1 -1
- package/ui-dist/assets/index-1PUjTjRT.js +324 -0
- package/ui-dist/assets/index-RCLz30rX.css +1 -0
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/index-D_thqcUo.js +0 -324
- package/ui-dist/assets/index-w55XbIEb.css +0 -1
package/dist/bin.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
startReview,
|
|
14
14
|
startWatch,
|
|
15
15
|
submitGitHubReview
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NJKYNMAQ.js";
|
|
17
17
|
|
|
18
18
|
// cli/src/index.ts
|
|
19
19
|
import { Command } from "commander";
|
|
@@ -1001,7 +1001,7 @@ async function serverStop() {
|
|
|
1001
1001
|
|
|
1002
1002
|
// cli/src/index.ts
|
|
1003
1003
|
var program = new Command();
|
|
1004
|
-
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.34.0" : "0.0.0-dev");
|
|
1005
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
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);
|
|
1007
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);
|
|
@@ -1155,6 +1155,45 @@ function consumeReviewResult(cwd) {
|
|
|
1155
1155
|
import getPort from "get-port";
|
|
1156
1156
|
import open from "open";
|
|
1157
1157
|
|
|
1158
|
+
// packages/core/src/review-history.ts
|
|
1159
|
+
import fs2 from "fs";
|
|
1160
|
+
import path4 from "path";
|
|
1161
|
+
import { randomUUID } from "crypto";
|
|
1162
|
+
function generateEntryId() {
|
|
1163
|
+
return randomUUID();
|
|
1164
|
+
}
|
|
1165
|
+
function getHistoryPath(projectDir) {
|
|
1166
|
+
return path4.join(projectDir, ".diffprism", "history", "reviews.json");
|
|
1167
|
+
}
|
|
1168
|
+
function readHistory(projectDir) {
|
|
1169
|
+
const filePath = getHistoryPath(projectDir);
|
|
1170
|
+
if (!fs2.existsSync(filePath)) {
|
|
1171
|
+
return { version: 1, entries: [] };
|
|
1172
|
+
}
|
|
1173
|
+
try {
|
|
1174
|
+
const raw = fs2.readFileSync(filePath, "utf-8");
|
|
1175
|
+
const parsed = JSON.parse(raw);
|
|
1176
|
+
return parsed;
|
|
1177
|
+
} catch {
|
|
1178
|
+
return { version: 1, entries: [] };
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
function appendHistory(projectDir, entry) {
|
|
1182
|
+
const filePath = getHistoryPath(projectDir);
|
|
1183
|
+
const dir = path4.dirname(filePath);
|
|
1184
|
+
if (!fs2.existsSync(dir)) {
|
|
1185
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
1186
|
+
}
|
|
1187
|
+
const history = readHistory(projectDir);
|
|
1188
|
+
history.entries.push(entry);
|
|
1189
|
+
history.entries.sort((a, b) => a.timestamp - b.timestamp);
|
|
1190
|
+
fs2.writeFileSync(filePath, JSON.stringify(history, null, 2) + "\n");
|
|
1191
|
+
}
|
|
1192
|
+
function getRecentHistory(projectDir, limit = 50) {
|
|
1193
|
+
const history = readHistory(projectDir);
|
|
1194
|
+
return history.entries.slice(-limit);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1158
1197
|
// packages/core/src/watch-bridge.ts
|
|
1159
1198
|
import http from "http";
|
|
1160
1199
|
import { WebSocketServer, WebSocket } from "ws";
|
|
@@ -1478,8 +1517,8 @@ function updateSession(id, update) {
|
|
|
1478
1517
|
|
|
1479
1518
|
// packages/core/src/ui-server.ts
|
|
1480
1519
|
import http2 from "http";
|
|
1481
|
-
import
|
|
1482
|
-
import
|
|
1520
|
+
import fs3 from "fs";
|
|
1521
|
+
import path5 from "path";
|
|
1483
1522
|
import { fileURLToPath } from "url";
|
|
1484
1523
|
var MIME_TYPES = {
|
|
1485
1524
|
".html": "text/html",
|
|
@@ -1494,14 +1533,14 @@ var MIME_TYPES = {
|
|
|
1494
1533
|
};
|
|
1495
1534
|
function resolveUiDist() {
|
|
1496
1535
|
const thisFile = fileURLToPath(import.meta.url);
|
|
1497
|
-
const thisDir =
|
|
1498
|
-
const publishedUiDist =
|
|
1499
|
-
if (
|
|
1536
|
+
const thisDir = path5.dirname(thisFile);
|
|
1537
|
+
const publishedUiDist = path5.resolve(thisDir, "..", "ui-dist");
|
|
1538
|
+
if (fs3.existsSync(path5.join(publishedUiDist, "index.html"))) {
|
|
1500
1539
|
return publishedUiDist;
|
|
1501
1540
|
}
|
|
1502
|
-
const workspaceRoot =
|
|
1503
|
-
const devUiDist =
|
|
1504
|
-
if (
|
|
1541
|
+
const workspaceRoot = path5.resolve(thisDir, "..", "..", "..");
|
|
1542
|
+
const devUiDist = path5.join(workspaceRoot, "packages", "ui", "dist");
|
|
1543
|
+
if (fs3.existsSync(path5.join(devUiDist, "index.html"))) {
|
|
1505
1544
|
return devUiDist;
|
|
1506
1545
|
}
|
|
1507
1546
|
throw new Error(
|
|
@@ -1510,10 +1549,10 @@ function resolveUiDist() {
|
|
|
1510
1549
|
}
|
|
1511
1550
|
function resolveUiRoot() {
|
|
1512
1551
|
const thisFile = fileURLToPath(import.meta.url);
|
|
1513
|
-
const thisDir =
|
|
1514
|
-
const workspaceRoot =
|
|
1515
|
-
const uiRoot =
|
|
1516
|
-
if (
|
|
1552
|
+
const thisDir = path5.dirname(thisFile);
|
|
1553
|
+
const workspaceRoot = path5.resolve(thisDir, "..", "..", "..");
|
|
1554
|
+
const uiRoot = path5.join(workspaceRoot, "packages", "ui");
|
|
1555
|
+
if (fs3.existsSync(path5.join(uiRoot, "index.html"))) {
|
|
1517
1556
|
return uiRoot;
|
|
1518
1557
|
}
|
|
1519
1558
|
throw new Error(
|
|
@@ -1533,14 +1572,14 @@ async function startViteDevServer(uiRoot, port, silent) {
|
|
|
1533
1572
|
function createStaticServer(distPath, port) {
|
|
1534
1573
|
const server = http2.createServer((req, res) => {
|
|
1535
1574
|
const urlPath = req.url?.split("?")[0] ?? "/";
|
|
1536
|
-
let filePath =
|
|
1537
|
-
if (!
|
|
1538
|
-
filePath =
|
|
1575
|
+
let filePath = path5.join(distPath, urlPath === "/" ? "index.html" : urlPath);
|
|
1576
|
+
if (!fs3.existsSync(filePath)) {
|
|
1577
|
+
filePath = path5.join(distPath, "index.html");
|
|
1539
1578
|
}
|
|
1540
|
-
const ext =
|
|
1579
|
+
const ext = path5.extname(filePath);
|
|
1541
1580
|
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
1542
1581
|
try {
|
|
1543
|
-
const content =
|
|
1582
|
+
const content = fs3.readFileSync(filePath);
|
|
1544
1583
|
res.writeHead(200, { "Content-Type": contentType });
|
|
1545
1584
|
res.end(content);
|
|
1546
1585
|
} catch {
|
|
@@ -1737,6 +1776,24 @@ DiffPrism Review: ${title ?? briefing.summary}`);
|
|
|
1737
1776
|
const result = await bridge.waitForResult();
|
|
1738
1777
|
poller?.stop();
|
|
1739
1778
|
updateSession(session.id, { status: "completed", result });
|
|
1779
|
+
try {
|
|
1780
|
+
const projectDir = cwd ?? process.cwd();
|
|
1781
|
+
const entry = {
|
|
1782
|
+
id: generateEntryId(),
|
|
1783
|
+
timestamp: Date.now(),
|
|
1784
|
+
diffRef,
|
|
1785
|
+
decision: result.decision,
|
|
1786
|
+
filesReviewed: diffSet.files.length,
|
|
1787
|
+
additions: diffSet.files.reduce((sum, f) => sum + f.additions, 0),
|
|
1788
|
+
deletions: diffSet.files.reduce((sum, f) => sum + f.deletions, 0),
|
|
1789
|
+
commentCount: result.comments.length,
|
|
1790
|
+
branch: metadata.currentBranch,
|
|
1791
|
+
title: metadata.title,
|
|
1792
|
+
summary: result.summary ?? briefing.summary
|
|
1793
|
+
};
|
|
1794
|
+
appendHistory(projectDir, entry);
|
|
1795
|
+
} catch {
|
|
1796
|
+
}
|
|
1740
1797
|
return result;
|
|
1741
1798
|
} finally {
|
|
1742
1799
|
poller?.stop();
|
|
@@ -1752,14 +1809,14 @@ DiffPrism Review: ${title ?? briefing.summary}`);
|
|
|
1752
1809
|
}
|
|
1753
1810
|
|
|
1754
1811
|
// packages/core/src/server-file.ts
|
|
1755
|
-
import
|
|
1756
|
-
import
|
|
1812
|
+
import fs4 from "fs";
|
|
1813
|
+
import path6 from "path";
|
|
1757
1814
|
import os from "os";
|
|
1758
1815
|
function serverDir() {
|
|
1759
|
-
return
|
|
1816
|
+
return path6.join(os.homedir(), ".diffprism");
|
|
1760
1817
|
}
|
|
1761
1818
|
function serverFilePath() {
|
|
1762
|
-
return
|
|
1819
|
+
return path6.join(serverDir(), "server.json");
|
|
1763
1820
|
}
|
|
1764
1821
|
function isPidAlive2(pid) {
|
|
1765
1822
|
try {
|
|
@@ -1771,21 +1828,21 @@ function isPidAlive2(pid) {
|
|
|
1771
1828
|
}
|
|
1772
1829
|
function writeServerFile(info) {
|
|
1773
1830
|
const dir = serverDir();
|
|
1774
|
-
if (!
|
|
1775
|
-
|
|
1831
|
+
if (!fs4.existsSync(dir)) {
|
|
1832
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
1776
1833
|
}
|
|
1777
|
-
|
|
1834
|
+
fs4.writeFileSync(serverFilePath(), JSON.stringify(info, null, 2) + "\n");
|
|
1778
1835
|
}
|
|
1779
1836
|
function readServerFile() {
|
|
1780
1837
|
const filePath = serverFilePath();
|
|
1781
|
-
if (!
|
|
1838
|
+
if (!fs4.existsSync(filePath)) {
|
|
1782
1839
|
return null;
|
|
1783
1840
|
}
|
|
1784
1841
|
try {
|
|
1785
|
-
const raw =
|
|
1842
|
+
const raw = fs4.readFileSync(filePath, "utf-8");
|
|
1786
1843
|
const info = JSON.parse(raw);
|
|
1787
1844
|
if (!isPidAlive2(info.pid)) {
|
|
1788
|
-
|
|
1845
|
+
fs4.unlinkSync(filePath);
|
|
1789
1846
|
return null;
|
|
1790
1847
|
}
|
|
1791
1848
|
return info;
|
|
@@ -1796,8 +1853,8 @@ function readServerFile() {
|
|
|
1796
1853
|
function removeServerFile() {
|
|
1797
1854
|
try {
|
|
1798
1855
|
const filePath = serverFilePath();
|
|
1799
|
-
if (
|
|
1800
|
-
|
|
1856
|
+
if (fs4.existsSync(filePath)) {
|
|
1857
|
+
fs4.unlinkSync(filePath);
|
|
1801
1858
|
}
|
|
1802
1859
|
} catch {
|
|
1803
1860
|
}
|
|
@@ -1998,7 +2055,7 @@ Review submitted: ${result.decision}`);
|
|
|
1998
2055
|
|
|
1999
2056
|
// packages/core/src/global-server.ts
|
|
2000
2057
|
import http3 from "http";
|
|
2001
|
-
import { randomUUID } from "crypto";
|
|
2058
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
2002
2059
|
import getPort3 from "get-port";
|
|
2003
2060
|
import open3 from "open";
|
|
2004
2061
|
import { WebSocketServer as WebSocketServer2, WebSocket as WebSocket2 } from "ws";
|
|
@@ -2171,6 +2228,26 @@ function broadcastSessionList() {
|
|
|
2171
2228
|
const summaries = Array.from(sessions2.values()).map(toSummary);
|
|
2172
2229
|
broadcastToAll({ type: "session:list", payload: summaries });
|
|
2173
2230
|
}
|
|
2231
|
+
function recordReviewHistory(session, result) {
|
|
2232
|
+
try {
|
|
2233
|
+
const { payload } = session;
|
|
2234
|
+
const entry = {
|
|
2235
|
+
id: generateEntryId(),
|
|
2236
|
+
timestamp: Date.now(),
|
|
2237
|
+
diffRef: session.diffRef ?? "unknown",
|
|
2238
|
+
decision: result.decision,
|
|
2239
|
+
filesReviewed: payload.diffSet.files.length,
|
|
2240
|
+
additions: payload.diffSet.files.reduce((sum, f) => sum + f.additions, 0),
|
|
2241
|
+
deletions: payload.diffSet.files.reduce((sum, f) => sum + f.deletions, 0),
|
|
2242
|
+
commentCount: result.comments.length,
|
|
2243
|
+
branch: payload.metadata.currentBranch,
|
|
2244
|
+
title: payload.metadata.title,
|
|
2245
|
+
summary: result.summary ?? payload.briefing.summary
|
|
2246
|
+
};
|
|
2247
|
+
appendHistory(session.projectPath, entry);
|
|
2248
|
+
} catch {
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2174
2251
|
async function handleApiRequest(req, res) {
|
|
2175
2252
|
const method = req.method ?? "GET";
|
|
2176
2253
|
const url = (req.url ?? "/").split("?")[0];
|
|
@@ -2234,7 +2311,7 @@ async function handleApiRequest(req, res) {
|
|
|
2234
2311
|
reopenBrowserIfNeeded?.();
|
|
2235
2312
|
jsonResponse(res, 200, { sessionId });
|
|
2236
2313
|
} else {
|
|
2237
|
-
const sessionId = `session-${
|
|
2314
|
+
const sessionId = `session-${randomUUID2().slice(0, 8)}`;
|
|
2238
2315
|
payload.reviewId = sessionId;
|
|
2239
2316
|
if (diffRef) {
|
|
2240
2317
|
payload.watchMode = true;
|
|
@@ -2295,6 +2372,7 @@ async function handleApiRequest(req, res) {
|
|
|
2295
2372
|
const result = JSON.parse(body);
|
|
2296
2373
|
session.result = result;
|
|
2297
2374
|
session.status = "submitted";
|
|
2375
|
+
recordReviewHistory(session, result);
|
|
2298
2376
|
if (result.decision === "dismissed") {
|
|
2299
2377
|
broadcastSessionRemoved(postResultParams.id);
|
|
2300
2378
|
} else {
|
|
@@ -2360,7 +2438,7 @@ async function handleApiRequest(req, res) {
|
|
|
2360
2438
|
const body = await readBody(req);
|
|
2361
2439
|
const { file, line, body: annotationBody, type, confidence, category, source } = JSON.parse(body);
|
|
2362
2440
|
const annotation = {
|
|
2363
|
-
id:
|
|
2441
|
+
id: randomUUID2(),
|
|
2364
2442
|
sessionId: session.id,
|
|
2365
2443
|
file,
|
|
2366
2444
|
line,
|
|
@@ -2405,6 +2483,10 @@ async function handleApiRequest(req, res) {
|
|
|
2405
2483
|
return true;
|
|
2406
2484
|
}
|
|
2407
2485
|
annotation.dismissed = true;
|
|
2486
|
+
sendToSessionClients(dismissAnnotationParams.id, {
|
|
2487
|
+
type: "annotation:dismissed",
|
|
2488
|
+
payload: { annotationId: dismissAnnotationParams.annotationId }
|
|
2489
|
+
});
|
|
2408
2490
|
jsonResponse(res, 200, { ok: true });
|
|
2409
2491
|
return true;
|
|
2410
2492
|
}
|
|
@@ -2484,6 +2566,38 @@ async function handleApiRequest(req, res) {
|
|
|
2484
2566
|
}
|
|
2485
2567
|
return true;
|
|
2486
2568
|
}
|
|
2569
|
+
const getSessionHistoryParams = matchRoute(method, url, "GET", "/api/reviews/:id/history");
|
|
2570
|
+
if (getSessionHistoryParams) {
|
|
2571
|
+
const session = sessions2.get(getSessionHistoryParams.id);
|
|
2572
|
+
if (!session) {
|
|
2573
|
+
jsonResponse(res, 404, { error: "Session not found" });
|
|
2574
|
+
return true;
|
|
2575
|
+
}
|
|
2576
|
+
if (session.projectPath.startsWith("github:")) {
|
|
2577
|
+
jsonResponse(res, 200, { history: [] });
|
|
2578
|
+
return true;
|
|
2579
|
+
}
|
|
2580
|
+
const history = getRecentHistory(session.projectPath);
|
|
2581
|
+
jsonResponse(res, 200, { history });
|
|
2582
|
+
return true;
|
|
2583
|
+
}
|
|
2584
|
+
if (method === "GET" && req.url) {
|
|
2585
|
+
const parsedUrl = new URL(req.url, "http://localhost");
|
|
2586
|
+
if (parsedUrl.pathname === "/api/history") {
|
|
2587
|
+
const projectPath = parsedUrl.searchParams.get("project");
|
|
2588
|
+
if (!projectPath) {
|
|
2589
|
+
jsonResponse(res, 400, { error: "Missing required query parameter: project" });
|
|
2590
|
+
return true;
|
|
2591
|
+
}
|
|
2592
|
+
if (projectPath.startsWith("github:")) {
|
|
2593
|
+
jsonResponse(res, 200, { history: [] });
|
|
2594
|
+
return true;
|
|
2595
|
+
}
|
|
2596
|
+
const history = getRecentHistory(projectPath);
|
|
2597
|
+
jsonResponse(res, 200, { history });
|
|
2598
|
+
return true;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2487
2601
|
jsonResponse(res, 404, { error: "Not found" });
|
|
2488
2602
|
return true;
|
|
2489
2603
|
}
|
|
@@ -2580,6 +2694,7 @@ async function startGlobalServer(options = {}) {
|
|
|
2580
2694
|
if (session) {
|
|
2581
2695
|
session.result = msg.payload;
|
|
2582
2696
|
session.status = "submitted";
|
|
2697
|
+
recordReviewHistory(session, msg.payload);
|
|
2583
2698
|
if (msg.payload.decision === "dismissed") {
|
|
2584
2699
|
broadcastSessionRemoved(sid);
|
|
2585
2700
|
} else {
|
|
@@ -2738,11 +2853,6 @@ Waiting for reviews...
|
|
|
2738
2853
|
return { httpPort, wsPort, stop };
|
|
2739
2854
|
}
|
|
2740
2855
|
|
|
2741
|
-
// packages/core/src/review-history.ts
|
|
2742
|
-
import fs4 from "fs";
|
|
2743
|
-
import path6 from "path";
|
|
2744
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
2745
|
-
|
|
2746
2856
|
// packages/github/src/auth.ts
|
|
2747
2857
|
import { execSync as execSync3 } from "child_process";
|
|
2748
2858
|
import fs5 from "fs";
|
package/dist/mcp-server.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveGitHubToken,
|
|
16
16
|
startReview,
|
|
17
17
|
submitGitHubReview
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-NJKYNMAQ.js";
|
|
19
19
|
|
|
20
20
|
// packages/mcp-server/src/index.ts
|
|
21
21
|
import fs from "fs";
|
|
@@ -113,11 +113,11 @@ async function reviewViaGlobalServer(serverInfo, diffRef, options) {
|
|
|
113
113
|
async function startMcpServer() {
|
|
114
114
|
const server = new McpServer({
|
|
115
115
|
name: "diffprism",
|
|
116
|
-
version: true ? "0.
|
|
116
|
+
version: true ? "0.34.0" : "0.0.0-dev"
|
|
117
117
|
});
|
|
118
118
|
server.tool(
|
|
119
119
|
"open_review",
|
|
120
|
-
"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.",
|
|
121
121
|
{
|
|
122
122
|
diff_ref: z.string().describe(
|
|
123
123
|
'Git diff reference: "staged", "unstaged", "working-copy" (staged+unstaged grouped), or a ref range like "HEAD~3..HEAD"'
|
|
@@ -781,7 +781,7 @@ async function startMcpServer() {
|
|
|
781
781
|
);
|
|
782
782
|
server.tool(
|
|
783
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.",
|
|
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
785
|
{
|
|
786
786
|
pr: z.string().describe(
|
|
787
787
|
'GitHub PR reference: "owner/repo#123" or "https://github.com/owner/repo/pull/123"'
|
|
@@ -867,7 +867,7 @@ async function startMcpServer() {
|
|
|
867
867
|
injectedPayload: payload
|
|
868
868
|
});
|
|
869
869
|
}
|
|
870
|
-
if (post_to_github && result.decision !== "dismissed") {
|
|
870
|
+
if ((post_to_github || result.postToGithub) && result.decision !== "dismissed") {
|
|
871
871
|
const posted = await submitGitHubReview(client, owner, repo, number, result);
|
|
872
872
|
if (posted) {
|
|
873
873
|
return {
|