From cbd14f867cf6d81c030402ec750e30699ae9be91 Mon Sep 17 00:00:00 2001 From: Waishnav Date: Mon, 10 Aug 2026 00:44:29 +0530 Subject: [PATCH 1/5] fix(ui): degrade change review rendering instead of crashing The review card parsed the git diff patch without guards. An unexpected patch shape or a broken diff driver crashed card rendering and blanked the whole review widget. - parseReviewPatchFiles returns an ok flag instead of throwing - multiline-diff parse failures degrade to a fallback file list using the card's per-file summary, with an explanatory note - binary files render a file summary row with a hidden-diff note - ToolResultCard gains an optional error field the card can render --- src/ui/card-types.ts | 5 +- src/ui/patch-display.test.ts | 26 ++++ src/ui/patch-display.ts | 26 ++++ src/ui/review-payload.tsx | 252 +++++++++++++++++++++++++++-------- src/ui/workspace-app.css | 25 ++++ 5 files changed, 276 insertions(+), 58 deletions(-) diff --git a/src/ui/card-types.ts b/src/ui/card-types.ts index 3d2380830..a0383922e 100644 --- a/src/ui/card-types.ts +++ b/src/ui/card-types.ts @@ -42,6 +42,7 @@ export interface ToolResultCard { managed?: boolean; }; status?: string; + error?: string; summary?: Record; files?: Array<{ path?: string; @@ -180,7 +181,9 @@ export function isExpandableCard(card: ToolResultCard): boolean { ); } - if (isReviewTool(card.tool)) return Boolean(card.files?.length || card.payload?.patch); + if (isReviewTool(card.tool)) { + return Boolean(card.files?.length || card.payload?.patch || card.error); + } if (isPatchTool(card.tool)) return Boolean(card.payload?.patch); return Boolean(card.payload); diff --git a/src/ui/patch-display.test.ts b/src/ui/patch-display.test.ts index 612809ff6..ca4273cdf 100644 --- a/src/ui/patch-display.test.ts +++ b/src/ui/patch-display.test.ts @@ -4,6 +4,7 @@ import { getPatchDisplayParts, getRenderedFileChangeKind, getRenderedFileChangePathDisplay, + parseReviewPatchFiles, } from "./patch-display.js"; assert.deepEqual(getPatchDisplayParts({}), { @@ -203,3 +204,28 @@ assert.deepEqual( tone: "edit", }, ); + +const reviewPatch = `diff --git a/src/a.ts b/src/a.ts +index 1111111..2222222 100644 +--- a/src/a.ts ++++ b/src/a.ts +@@ -1,3 +1,3 @@ +-const x = 1; ++const x = 2; +`; + +const parsedReview = parseReviewPatchFiles(reviewPatch); +assert.equal(parsedReview.ok, true); +assert.equal(parsedReview.files.length, 1); +assert.equal(parsedReview.files[0]?.name, "src/a.ts"); +assert.equal(parsedReview.files[0]?.hunks.length, 1); +assert.equal(parsedReview.files[0]?.hunks[0]?.additionLines, 1); +assert.equal(parsedReview.files[0]?.hunks[0]?.deletionLines, 1); + +assert.deepEqual(parseReviewPatchFiles(undefined), { files: [], ok: true }); +assert.deepEqual(parseReviewPatchFiles(" \n "), { files: [], ok: true }); +assert.deepEqual(parseReviewPatchFiles("garbage that is not a patch"), { files: [], ok: true }); + +const crlfReviewPatch = reviewPatch.replace(/\n/g, "\r\n"); +assert.equal(parseReviewPatchFiles(crlfReviewPatch).ok, true); +assert.equal(parseReviewPatchFiles(crlfReviewPatch).files.length, 1); diff --git a/src/ui/patch-display.ts b/src/ui/patch-display.ts index ec1f7ad29..4ae476a12 100644 --- a/src/ui/patch-display.ts +++ b/src/ui/patch-display.ts @@ -1,5 +1,11 @@ +import { parsePatchFiles, type FileDiffMetadata } from "@pierre/diffs"; import type { ToolResultCard } from "./card-types.js"; +export interface ReviewPatchParse { + files: FileDiffMetadata[]; + ok: boolean; +} + export type FileChangeKind = | "added" | "edited" @@ -160,6 +166,26 @@ export function fileChangeKindLabel(kind: FileChangeKind): string { return kind === "unknown" ? "Changed" : fileChangeLabels[kind]; } +/** + * Parse a review patch without ever throwing, so a malformed or unexpected + * patch cannot take down the whole card render. A parse failure surfaces as + * `ok: false` so the caller can fall back to a file-summary-only card. + */ +export function parseReviewPatchFiles(patch: string | undefined): ReviewPatchParse { + if (!patch) return { files: [], ok: true }; + const normalized = patch.replace(/\r\n/g, "\n").trim(); + if (normalized.length === 0) return { files: [], ok: true }; + + try { + const files = parsePatchFiles(normalized, "review", true).flatMap( + (parsedPatch) => parsedPatch.files, + ); + return { files, ok: true }; + } catch { + return { files: [], ok: false }; + } +} + function countChangedFiles(files: NonNullable): number { const paths = new Set(); let unnamedFiles = 0; diff --git a/src/ui/review-payload.tsx b/src/ui/review-payload.tsx index 455e54726..3893707c5 100644 --- a/src/ui/review-payload.tsx +++ b/src/ui/review-payload.tsx @@ -1,12 +1,15 @@ import { useMemo, useState } from "react"; import { createRoot } from "react-dom/client"; -import { parsePatchFiles, type FileDiffMetadata, type FileDiffOptions } from "@pierre/diffs"; +import { type FileDiffMetadata, type FileDiffOptions } from "@pierre/diffs"; import { FileDiff } from "@pierre/diffs/react"; import type { HostContext, ToolResultCard } from "./card-types.js"; import { fileChangeKindLabel, - getRenderedFileChangePathDisplay, + getFileChangeKind, + getFileChangePathDisplay, getRenderedFileChangeKind, + getRenderedFileChangePathDisplay, + parseReviewPatchFiles, type FileChangeKind, } from "./patch-display.js"; import { pierrePrettyScrollbarCss } from "./scrollbar.js"; @@ -50,23 +53,30 @@ function ReviewPayload({ }: PayloadRendererOptions) { const patch = card.payload?.patch; const themeType: ThemeType = hostContext?.theme === "light" ? "light" : "dark"; - const files = useMemo(() => parseFiles(patch), [patch]); + const reviewParse = useMemo(() => parseReviewPatchFiles(patch), [patch]); + const files = reviewParse.files; const visibleFiles = typeof visibleFileCount === "number" ? files.slice(0, visibleFileCount) : files; const [openFiles, setOpenFiles] = useState(() => new Set()); if (errorMessage) return ; + if (card.error) return ; if (!patch) return ; + if (!reviewParse.ok) return ; if (files.length === 0) return ; const options = diffOptions(themeType); if (files.length === 1) { + const fileDiff = files[0]; + if (fileDiff.hunks.length === 0) { + return ; + } return (
@@ -101,58 +111,121 @@ function ReviewPayload({ return (
- + {isOpen ? ( + + ) : null} + + )} +
+ ); + })} +
+ + ); +} + +function FallbackReviewList({ card }: { card: ToolResultCard }) { + const files = card.files ?? []; + if (files.length === 0) { + return ; + } + + return ( +
+
+ Diff preview is unavailable — showing the changed files instead. +
+
+ {files.map((file, index) => { + const kind = getFileChangeKind(file); + const pathDisplay = getFileChangePathDisplay(file); + return ( +
+
+ - +{stats.additions} - -{stats.removals} + +{file.additions ?? 0} + -{file.removals ?? 0} - - {isOpen ? ( - - ) : null} +
+
+ ); + })} +
+
+ ); +} + +function BinaryFileList({ + files, + card, +}: { + files: FileDiffMetadata[]; + card: ToolResultCard; +}) { + return ( +
+
+ {files.map((fileDiff, index) => { + const changeKind = getRenderedFileChangeKind( + card.files ?? [], + { path: fileDiff.name, previousPath: fileDiff.prevName, type: fileDiff.type }, + index, + ); + const pathDisplay = getRenderedFileChangePathDisplay( + card.files ?? [], + { path: fileDiff.name, previousPath: fileDiff.prevName }, + index, + ); + return ( +
+
); })} @@ -161,6 +234,76 @@ function ReviewPayload({ ); } +function FileSummaryRow({ + kind, + pathDisplay, + name, + additions, + removals, + note, +}: { + kind: FileChangeKind; + pathDisplay: ReturnType; + name: string; + additions: number; + removals: number; + note: string; +}) { + return ( +
+
+ + + +{additions} + -{removals} + +
+
{note}
+
+ ); +} + +function FileSummaryLabel({ + kind, + pathDisplay, + name, +}: { + kind: FileChangeKind; + pathDisplay: ReturnType; + name: string; +}) { + return ( + <> + + {fileChangeSymbol(kind)} + + {pathDisplay?.previous ? ( + + + {pathDisplay.previous} + + + + {pathDisplay.current} + + + ) : ( + + {pathDisplay?.current ?? name} + + )} + + ); +} + function fileChangeSymbol(kind: FileChangeKind): string { switch (kind) { case "added": @@ -177,11 +320,6 @@ function fileChangeSymbol(kind: FileChangeKind): string { } } -function parseFiles(patch: string | undefined): FileDiffMetadata[] { - if (!patch) return []; - return parsePatchFiles(patch, "review", true).flatMap((parsedPatch) => parsedPatch.files); -} - function diffStats(fileDiff: FileDiffMetadata): { additions: number; removals: number } { return fileDiff.hunks.reduce( (stats, hunk) => ({ diff --git a/src/ui/workspace-app.css b/src/ui/workspace-app.css index bee72228f..4f9d24ec9 100644 --- a/src/ui/workspace-app.css +++ b/src/ui/workspace-app.css @@ -772,6 +772,31 @@ body { background: var(--tool-card-hover-bg); } +.review-diff-file-header.static, +.review-diff-file-header.static:hover { + cursor: default; + background: transparent; +} + +.review-diff-file-group { + overflow: hidden; + border: 0; + border-radius: 0; +} + +.review-summary-note { + padding: 8px 12px; + border-bottom: 1px solid var(--tool-card-divider); + color: var(--color-text-secondary, #b7b7bf); + font-size: var(--font-text-sm-size, 12px); +} + +.review-binary-note { + padding: 4px 12px 10px 44px; + color: var(--color-text-tertiary, #a3a3aa); + font-size: var(--font-text-sm-size, 12px); +} + .review-diff-file-name, .review-diff-file-stats { overflow: hidden; From 417c680f7d03bb26b7c4815834858927a24e01a0 Mon Sep 17 00:00:00 2001 From: Waishnav Date: Mon, 10 Aug 2026 00:44:32 +0530 Subject: [PATCH 2/5] fix: return an error card when change review fails show_changes threw, failing the whole tool call, when the git-backed review could not produce a patch. The widget stayed blank at best. Catch review failures, log them as failed tool calls, and return an error card the widget expands to show the failure message. --- src/server.ts | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/server.ts b/src/server.ts index 840594ab7..10527b1f2 100644 --- a/src/server.ts +++ b/src/server.ts @@ -49,7 +49,10 @@ import { type McpSessionCloseResult, } from "./mcp-sessions.js"; import { ProcessSessionManager, type ProcessSnapshot } from "./process-sessions.js"; -import { createReviewCheckpointManager } from "./review-checkpoints.js"; +import { + createReviewCheckpointManager, + type ReviewChangesResult, +} from "./review-checkpoints.js"; import { openAiConversationScopeId } from "./request-meta.js"; import { shutdownHttpServer } from "./server-shutdown.js"; import { formatPathForPrompt } from "./skills.js"; @@ -1308,11 +1311,39 @@ export function createMcpServer( async ({ workspaceId }) => { const startedAt = performance.now(); const workspace = workspaces.getWorkspace(workspaceId); - const review = await reviewCheckpoints.reviewChanges({ - workspaceId, - root: workspace.root, - markReviewed: true, - }); + + let review: ReviewChangesResult; + try { + review = await reviewCheckpoints.reviewChanges({ + workspaceId, + root: workspace.root, + markReviewed: true, + }); + } catch (error) { + const message = error instanceof Error ? error.message : String(error); + const content = [textBlock(`show_changes failed: ${message}`)]; + logFailedToolResponse(config, { + tool: "show_changes", + workspaceId, + }, content, startedAt); + return { + isError: true, + content, + _meta: { + tool: "show_changes", + card: { + workspaceId, + summary: { files: 0, additions: 0, removals: 0 }, + files: [], + payload: {}, + error: message, + }, + }, + structuredContent: { + result: contentText(content), + }, + }; + } const content = [textBlock(review.result)]; logToolCall(config, { From c7a59c6eb6eeba323513c1a677f8a809cd731ec0 Mon Sep 17 00:00:00 2001 From: Waishnav Date: Mon, 10 Aug 2026 00:44:32 +0530 Subject: [PATCH 3/5] fix: disable external diff drivers in review patches git diff honors user-configured external diff drivers and textconv filters from ~/.gitconfig, which can produce unparseable output or launch interactive processes. Add --no-ext-diff and --no-textconv so review patches always come back as plain unified diffs. --- src/review-checkpoints.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/review-checkpoints.ts b/src/review-checkpoints.ts index 0fd8bf361..467b80f4f 100644 --- a/src/review-checkpoints.ts +++ b/src/review-checkpoints.ts @@ -108,7 +108,14 @@ export function createReviewCheckpointManager(): ReviewCheckpointManager { const baselineRef = effectiveSince === "workspace_open" ? state.openRef : state.baselineRef; const baseline = (await git(state.gitRoot, ["rev-parse", "--verify", `${baselineRef}^{commit}`])).stdout.trim(); const current = await createWorkingTreeSnapshot(state.gitRoot); - const patch = (await git(state.gitRoot, ["diff", "--binary", "--no-color", baseline, current], { + const patch = (await git(state.gitRoot, [ + "diff", + "--no-color", + "--no-ext-diff", + "--no-textconv", + baseline, + current, + ], { maxBuffer: 50 * 1024 * 1024, })).stdout; const numstat = (await git(state.gitRoot, ["diff", "--numstat", "-z", baseline, current], { From 1b4cd3fe5e252868852d19c5b373f6577fa7aa21 Mon Sep 17 00:00:00 2001 From: Waishnav Date: Mon, 10 Aug 2026 01:19:29 +0530 Subject: [PATCH 4/5] fix(ui): distinguish hunkless binary files from metadata-only changes Hunkless diffs are normal for renames, mode changes, and binary files, but the review card treated every hunkless file as binary. Detect binary files from their explicit git markers instead, render hunkless renames and mode changes as ordinary static summaries, and stop blanking the card when a journal-only file (e.g. an oversized diff) has no parseable hunks. Also stop trimming patch whitespace: stripping leading and trailing whitespace from a patch could silently drop a trailing-space change on the final line. Only blank line runs at the patch edges are removed. --- src/ui/patch-display.test.ts | 61 ++++++++++++++++++++++++++++++-- src/ui/patch-display.ts | 24 ++++++++++--- src/ui/review-payload.tsx | 68 ++++++++++++++++++++++++++++-------- 3 files changed, 131 insertions(+), 22 deletions(-) diff --git a/src/ui/patch-display.test.ts b/src/ui/patch-display.test.ts index ca4273cdf..9ac722447 100644 --- a/src/ui/patch-display.test.ts +++ b/src/ui/patch-display.test.ts @@ -222,10 +222,65 @@ assert.equal(parsedReview.files[0]?.hunks.length, 1); assert.equal(parsedReview.files[0]?.hunks[0]?.additionLines, 1); assert.equal(parsedReview.files[0]?.hunks[0]?.deletionLines, 1); -assert.deepEqual(parseReviewPatchFiles(undefined), { files: [], ok: true }); -assert.deepEqual(parseReviewPatchFiles(" \n "), { files: [], ok: true }); -assert.deepEqual(parseReviewPatchFiles("garbage that is not a patch"), { files: [], ok: true }); +assert.deepEqual(parseReviewPatchFiles(undefined), { files: [], binaryFiles: new Set(), ok: true }); +{ + const whitespaceOnly = parseReviewPatchFiles(" \n "); + assert.deepEqual(whitespaceOnly.files, []); + assert.equal(whitespaceOnly.ok, true); +} +assert.equal(parseReviewPatchFiles("garbage that is not a patch").ok, true); const crlfReviewPatch = reviewPatch.replace(/\n/g, "\r\n"); assert.equal(parseReviewPatchFiles(crlfReviewPatch).ok, true); assert.equal(parseReviewPatchFiles(crlfReviewPatch).files.length, 1); + +const binaryPatch = `diff --git a/logo.png b/logo.png +index 1111111..2222222 100644 +Binary files a/logo.png and b/logo.png differ +`; +{ + const parsed = parseReviewPatchFiles(binaryPatch); + assert.equal(parsed.ok, true); + assert.equal(parsed.files.length, 1); + assert.equal(parsed.files[0]?.hunks.length, 0); + assert.deepEqual([...parsed.binaryFiles], ["logo.png"]); +} + +const renamePatch = `diff --git a/old.txt b/new.txt +similarity index 100% +rename from old.txt +rename to new.txt +`; +{ + const parsed = parseReviewPatchFiles(renamePatch); + assert.equal(parsed.ok, true); + assert.equal(parsed.files[0]?.type, "rename-pure"); + assert.deepEqual([...parsed.binaryFiles], []); +} + +const modePatch = `diff --git a/run.sh b/run.sh +old mode 100644 +new mode 100755 +`; +{ + const parsed = parseReviewPatchFiles(modePatch); + assert.equal(parsed.ok, true); + assert.equal(parsed.files[0]?.hunks.length, 0); + assert.equal(parsed.files[0]?.prevMode, "100644"); + assert.equal(parsed.files[0]?.mode, "100755"); + assert.deepEqual([...parsed.binaryFiles], []); +} + +const trailingSpacePatch = `diff --git a/f.txt b/f.txt +index 1111111..2222222 100644 +--- a/f.txt ++++ b/f.txt +@@ -1 +1 @@ +-old ++new +`; +{ + const parsed = parseReviewPatchFiles(trailingSpacePatch); + assert.equal(parsed.ok, true); + assert.equal(parsed.files[0]?.additionLines[0], "new "); +} diff --git a/src/ui/patch-display.ts b/src/ui/patch-display.ts index 4ae476a12..fce0a6f8e 100644 --- a/src/ui/patch-display.ts +++ b/src/ui/patch-display.ts @@ -3,6 +3,7 @@ import type { ToolResultCard } from "./card-types.js"; export interface ReviewPatchParse { files: FileDiffMetadata[]; + binaryFiles: Set; ok: boolean; } @@ -170,19 +171,32 @@ export function fileChangeKindLabel(kind: FileChangeKind): string { * Parse a review patch without ever throwing, so a malformed or unexpected * patch cannot take down the whole card render. A parse failure surfaces as * `ok: false` so the caller can fall back to a file-summary-only card. + * + * Diffs without hunks are normal for renames, mode changes, and binary + * files. Binary files are detected from their explicit git markers + * ("Binary files ... differ" or "GIT binary patch") so hunkless renames and + * mode changes are not mistaken for binary content. */ export function parseReviewPatchFiles(patch: string | undefined): ReviewPatchParse { - if (!patch) return { files: [], ok: true }; - const normalized = patch.replace(/\r\n/g, "\n").trim(); - if (normalized.length === 0) return { files: [], ok: true }; + if (!patch) return { files: [], binaryFiles: new Set(), ok: true }; + const normalized = patch.replace(/\r\n/g, "\n").replace(/^\n+|\n+$/g, ""); + if (/^\s*$/.test(normalized)) return { files: [], binaryFiles: new Set(), ok: true }; try { const files = parsePatchFiles(normalized, "review", true).flatMap( (parsedPatch) => parsedPatch.files, ); - return { files, ok: true }; + const binaryFiles = new Set(); + for (const section of patch.split(/^diff --git /m)) { + if (!section || !/Binary files|GIT binary patch/.test(section)) continue; + const firstLine = section.split("\n")[0] ?? ""; + const binaryPath = firstLine.match(/ b\/(.+?)\s*$/)?.[1]?.replace(/^"|"$/g, "") + ?? firstLine.split(" ")[1]?.slice(2); + if (binaryPath) binaryFiles.add(binaryPath); + } + return { files, binaryFiles, ok: true }; } catch { - return { files: [], ok: false }; + return { files: [], binaryFiles: new Set(), ok: false }; } } diff --git a/src/ui/review-payload.tsx b/src/ui/review-payload.tsx index 3893707c5..120c2a779 100644 --- a/src/ui/review-payload.tsx +++ b/src/ui/review-payload.tsx @@ -62,16 +62,30 @@ function ReviewPayload({ if (errorMessage) return ; if (card.error) return ; - if (!patch) return ; + const cardFiles = card.files ?? []; + if (!patch) { + if (cardFiles.length === 0) return ; + return ; + } if (!reviewParse.ok) return ; - if (files.length === 0) return ; + if (files.length === 0) { + if (cardFiles.length === 0) return ; + return ; + } const options = diffOptions(themeType); + const binaryFiles = reviewParse.binaryFiles; if (files.length === 1) { const fileDiff = files[0]; if (fileDiff.hunks.length === 0) { - return ; + return ( + + ); } return (
@@ -118,7 +132,9 @@ function ReviewPayload({ name={fileDiff.name} additions={stats.additions} removals={stats.removals} - note="Binary file — diff preview hidden" + note={binaryFiles.has(fileDiff.name) + ? "Binary file — diff preview hidden" + : undefined} /> ) : ( <> @@ -154,6 +170,25 @@ function ReviewPayload({
); })} + {cardFiles + .filter((cardFile) => ( + !files.some((fileDiff) => ( + fileDiff.name === cardFile.path || + fileDiff.name === cardFile.previousPath + )) + )) + .map((cardFile, index) => ( +
+ +
+ ))}
); @@ -198,9 +233,11 @@ function FallbackReviewList({ card }: { card: ToolResultCard }) { function BinaryFileList({ files, card, + note, }: { files: FileDiffMetadata[]; card: ToolResultCard; + note?: string; }) { return (
@@ -224,7 +261,7 @@ function BinaryFileList({ name={fileDiff.name} additions={0} removals={0} - note="Binary file — diff preview hidden" + note={note} />
); @@ -247,18 +284,21 @@ function FileSummaryRow({ name: string; additions: number; removals: number; - note: string; + note?: string; }) { + const row = ( +
+ + + +{additions} + -{removals} + +
+ ); return (
-
- - - +{additions} - -{removals} - -
-
{note}
+ {row} + {note ?
{note}
: null}
); } From 8a56b41f73cf83b0cdff671064becc62a1d5dcea Mon Sep 17 00:00:00 2001 From: Waishnav Date: Mon, 10 Aug 2026 11:17:11 +0530 Subject: [PATCH 5/5] fix(ui): derive binary paths from diff headers only The space-split fallback for binary path extraction could record a fragment of a quoted header as the file name. Git diff headers already carry the new path after the 'b/' prefix, quoted when the path contains special characters, so the header match alone is sufficient and test coverage now locks in paths containing spaces, both plain and quoted. --- src/ui/patch-display.test.ts | 20 ++++++++++++++++++++ src/ui/patch-display.ts | 3 +-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/ui/patch-display.test.ts b/src/ui/patch-display.test.ts index 9ac722447..b39c3b175 100644 --- a/src/ui/patch-display.test.ts +++ b/src/ui/patch-display.test.ts @@ -284,3 +284,23 @@ index 1111111..2222222 100644 assert.equal(parsed.ok, true); assert.equal(parsed.files[0]?.additionLines[0], "new "); } + +const binarySpacePathPatch = `diff --git a/logo mark.png b/logo mark.png +index 1111111..2222222 100644 +Binary files a/logo mark.png and b/logo mark.png differ +`; +{ + const parsed = parseReviewPatchFiles(binarySpacePathPatch); + assert.equal(parsed.ok, true); + assert.deepEqual([...parsed.binaryFiles], ["logo mark.png"]); +} + +const quotedBinaryPatch = `diff --git a/"logo mark.png" b/"logo mark.png" +index 1111111..2222222 100644 +Binary files a/"logo mark.png" and b/"logo mark.png" differ +`; +{ + const parsed = parseReviewPatchFiles(quotedBinaryPatch); + assert.equal(parsed.ok, true); + assert.deepEqual([...parsed.binaryFiles], ["logo mark.png"]); +} diff --git a/src/ui/patch-display.ts b/src/ui/patch-display.ts index fce0a6f8e..490a722b0 100644 --- a/src/ui/patch-display.ts +++ b/src/ui/patch-display.ts @@ -190,8 +190,7 @@ export function parseReviewPatchFiles(patch: string | undefined): ReviewPatchPar for (const section of patch.split(/^diff --git /m)) { if (!section || !/Binary files|GIT binary patch/.test(section)) continue; const firstLine = section.split("\n")[0] ?? ""; - const binaryPath = firstLine.match(/ b\/(.+?)\s*$/)?.[1]?.replace(/^"|"$/g, "") - ?? firstLine.split(" ")[1]?.slice(2); + const binaryPath = firstLine.match(/ b\/(.+?)\s*$/)?.[1]?.replace(/^"|"$/g, ""); if (binaryPath) binaryFiles.add(binaryPath); } return { files, binaryFiles, ok: true };