From ebda89b34ae8f46a99f5b492327bfc9e96dfb562 Mon Sep 17 00:00:00 2001 From: Marius Date: Fri, 8 May 2026 12:50:09 +0200 Subject: [PATCH] fix(agent-manager): stop repeated diff preview loads (#10064) --- .changeset/flickering-diffs-rest.md | 5 +++++ .../webview-ui/agent-manager/DiffPanel.tsx | 21 ++++++++++++++++++- .../agent-manager/FullScreenDiffView.tsx | 21 ++++++++++++++++++- .../webview-ui/agent-manager/diff-state.ts | 5 +++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 .changeset/flickering-diffs-rest.md diff --git a/.changeset/flickering-diffs-rest.md b/.changeset/flickering-diffs-rest.md new file mode 100644 index 0000000000..7a3fc58fcd --- /dev/null +++ b/.changeset/flickering-diffs-rest.md @@ -0,0 +1,5 @@ +--- +"kilo-code": patch +--- + +Stop repeatedly reloading non-renderable Agent Manager diff previews. diff --git a/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx b/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx index 08e408e41c..dc7b650f2e 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/DiffPanel.tsx @@ -25,6 +25,7 @@ import { LONG_DIFF_MARKER_FILE_COUNT, expandableOpenFiles, initialOpenFiles, isL import { DiffEndMarker } from "./DiffEndMarker" import { treeOrder } from "./file-tree-utils" import { isMarkdownFile, MarkdownDiffView } from "./MarkdownDiffView" +import { diffToken } from "./diff-state" // --- Data model --- @@ -75,6 +76,7 @@ export const DiffPanel: Component = (props) => { // key changes (different worktree) we expand reviewable files. Within the same key, // only pruning happens so the user's manual collapse state is preserved. let initializedKey: string | undefined + const requested = new Map() // Reorder diffs to match the file-tree's depth-first visual order so // scrolling through the accordion matches the tree grouping. @@ -166,16 +168,33 @@ export const DiffPanel: Component = (props) => { ), ) + createEffect( + on( + () => props.sessionKey, + () => { + requested.clear() + }, + ), + ) + createEffect( on( () => [open(), props.diffs] as const, ([next]) => { + const files = new Set(next) + for (const file of requested.keys()) { + if (!files.has(file)) requested.delete(file) + } + if (!props.onRequestDiff) return const loading = props.loadingFiles ?? new Set() for (const file of next) { if (loading.has(file)) continue const diff = props.diffs.find((item) => item.file === file) if (!diff || diff.summarized !== true) continue - props.onRequestDiff?.(file) + const value = diffToken(diff) + if (requested.get(file) === value) continue + requested.set(file, value) + props.onRequestDiff(file) } }, { defer: true }, diff --git a/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx b/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx index 06962fd739..1693c9b9b5 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx +++ b/packages/kilo-vscode/webview-ui/agent-manager/FullScreenDiffView.tsx @@ -32,6 +32,7 @@ import { import { LONG_DIFF_MARKER_FILE_COUNT, expandableOpenFiles, initialOpenFiles, isLargeDiffFile } from "./diff-open-policy" import { DiffEndMarker } from "./DiffEndMarker" import { isMarkdownFile, MarkdownDiffView } from "./MarkdownDiffView" +import { diffToken } from "./diff-state" type DiffStyle = "unified" | "split" @@ -88,6 +89,7 @@ export const FullScreenDiffView: Component = (props) => // key changes (different worktree) we expand reviewable files. Within the same key, // only pruning happens so the user's manual collapse state is preserved. let initializedKey: string | undefined + const requested = new Map() let rootRef: HTMLDivElement | undefined let scrollRef: HTMLDivElement | undefined let syncFrame: number | undefined @@ -176,16 +178,33 @@ export const FullScreenDiffView: Component = (props) => ), ) + createEffect( + on( + () => props.sessionKey, + () => { + requested.clear() + }, + ), + ) + createEffect( on( () => [open(), props.diffs] as const, ([next]) => { + const files = new Set(next) + for (const file of requested.keys()) { + if (!files.has(file)) requested.delete(file) + } + if (!props.onRequestDiff) return const loading = props.loadingFiles ?? new Set() for (const file of next) { if (loading.has(file)) continue const diff = props.diffs.find((item) => item.file === file) if (!diff || diff.summarized !== true) continue - props.onRequestDiff?.(file) + const value = diffToken(diff) + if (requested.get(file) === value) continue + requested.set(file, value) + props.onRequestDiff(file) } }, { defer: true }, diff --git a/packages/kilo-vscode/webview-ui/agent-manager/diff-state.ts b/packages/kilo-vscode/webview-ui/agent-manager/diff-state.ts index 1ffd6bd347..05a9657172 100644 --- a/packages/kilo-vscode/webview-ui/agent-manager/diff-state.ts +++ b/packages/kilo-vscode/webview-ui/agent-manager/diff-state.ts @@ -13,6 +13,11 @@ export function sameDiffMeta(left: WorktreeFileDiff, right: WorktreeFileDiff) { ) } +export function diffToken(diff: WorktreeFileDiff) { + const parts = [diff.status ?? "", diff.additions, diff.deletions, diff.tracked ?? "", diff.generatedLike ?? ""] + return diff.stamp ?? parts.join(":") +} + export interface MergeResult { diffs: WorktreeFileDiff[] /** Files whose metadata changed while we preserved cached content.