diff --git a/packages/session-ui/src/components/apply-patch-file.test.ts b/packages/session-ui/src/components/apply-patch-file.test.ts index c3853c43252..ba2bef6c57d 100644 --- a/packages/session-ui/src/components/apply-patch-file.test.ts +++ b/packages/session-ui/src/components/apply-patch-file.test.ts @@ -30,6 +30,15 @@ describe("apply patch files", () => { ]) }) + test("removes files without diff changes", () => { + expect( + patchFiles([ + { file: "src/changed.ts", patch: "@@ -1 +1 @@\n-old\n+new", additions: 1, deletions: 1, status: "modified" }, + { file: "src/unchanged.ts", patch: "", additions: 0, deletions: 0, status: "modified" }, + ]).map((file) => file.path), + ).toEqual(["src/changed.ts"]) + }) + test("composes sequential complete patches for the same file", () => { const before = "const a = 1\nconst b = 2\n" const middle = "const a = 2\nconst b = 2\n" diff --git a/packages/session-ui/src/components/apply-patch-file.ts b/packages/session-ui/src/components/apply-patch-file.ts index 2dd94e50f8f..ffe12999fa3 100644 --- a/packages/session-ui/src/components/apply-patch-file.ts +++ b/packages/session-ui/src/components/apply-patch-file.ts @@ -15,18 +15,19 @@ export type ApplyPatchFile = { export type ApplyPatchFileGroup = Omit & { views: ViewDiff[] } -function fileDiff(value: unknown): value is FileDiffInfo { +export function changedFileDiff(value: unknown): value is FileDiffInfo { if (!value || typeof value !== "object") return false if (!("file" in value) || typeof value.file !== "string") return false if (!("patch" in value) || typeof value.patch !== "string") return false if (!("additions" in value) || typeof value.additions !== "number") return false if (!("deletions" in value) || typeof value.deletions !== "number") return false if (!("status" in value)) return false - return value.status === "added" || value.status === "deleted" || value.status === "modified" + if (value.status !== "added" && value.status !== "deleted" && value.status !== "modified") return false + return value.additions > 0 || value.deletions > 0 } export function patchFile(value: unknown): ApplyPatchFile | undefined { - if (!fileDiff(value)) return + if (!changedFileDiff(value)) return return { path: value.file, type: value.status === "added" ? "add" : value.status === "deleted" ? "delete" : "update", diff --git a/packages/session-ui/src/tools/tool-renderer.tsx b/packages/session-ui/src/tools/tool-renderer.tsx index 802b1a7e400..fac419e20e5 100644 --- a/packages/session-ui/src/tools/tool-renderer.tsx +++ b/packages/session-ui/src/tools/tool-renderer.tsx @@ -33,7 +33,7 @@ import { IconButton } from "@opencode-ai/ui/icon-button" import { TextShimmer } from "@opencode-ai/ui/text-shimmer" import { AnimatedCountList } from "../components/tool-count-summary" import { ToolStatusTitle } from "../components/tool-status-title" -import { patchFileGroups } from "../components/apply-patch-file" +import { changedFileDiff, patchFileGroups } from "../components/apply-patch-file" import { animate } from "motion" import { SessionProgressIndicatorV2 } from "../v2/components/session-progress-indicator-v2" import type { SessionMessageAssistantTool, SessionMessageShell } from "@opencode-ai/client/promise" @@ -1349,11 +1349,7 @@ ToolRegistry.register({ const diff = createMemo(() => { const files = props.metadata.files if (!Array.isArray(files)) return undefined - const value = files.find( - (file) => !!file && typeof file === "object" && "file" in file && typeof file.file === "string", - ) - if (!value || typeof value !== "object") return undefined - return value + return files.find(changedFileDiff) }) const diagnostics = createMemo(() => getDiagnostics(props.metadata.diagnostics, inputPath())) const path = createMemo(() => {