From ec0883a627b06b6ba2a393d5cf66ddf6ebc4cd0d Mon Sep 17 00:00:00 2001 From: Guilhem Date: Mon, 5 Oct 2026 16:21:59 +0200 Subject: [PATCH] feat(ai-chat): show per-file diffs for raw app edits (#11521) * feat(ai-chat): show per-file diffs for raw app edits Co-Authored-By: Claude Opus 5.5 (1M context) * fix: keep reference runnable writes on the generic tool card Co-Authored-By: Claude Opus 5.5 (1M context) * fix: extend diff row highlights across horizontal overflow Co-Authored-By: Claude Opus 5.5 (1M context) --------- Co-authored-by: Claude Opus 5.5 (1M context) --- .../copilot/chat/ToolCodeDiffView.svelte | 97 ++++++++------- .../copilot/chat/ToolDiffCard.svelte | 15 ++- .../copilot/chat/ToolExecutionDisplay.svelte | 2 +- .../copilot/chat/global/core.test.ts | 80 +++++++++++++ .../components/copilot/chat/global/core.ts | 113 +++++++++++++----- .../src/lib/components/copilot/chat/shared.ts | 3 + .../copilot/chat/toolCodeDiff.test.ts | 59 +++++++-- .../components/copilot/chat/toolCodeDiff.ts | 92 ++++++++++++-- .../copilot/chat/toolCodeDiffLanguage.ts | 13 +- 9 files changed, 371 insertions(+), 103 deletions(-) diff --git a/frontend/src/lib/components/copilot/chat/ToolCodeDiffView.svelte b/frontend/src/lib/components/copilot/chat/ToolCodeDiffView.svelte index 6f74ff7a80..2a63c58308 100644 --- a/frontend/src/lib/components/copilot/chat/ToolCodeDiffView.svelte +++ b/frontend/src/lib/components/copilot/chat/ToolCodeDiffView.svelte @@ -24,6 +24,7 @@ const diffRows = $derived(diffLines ?? toolDiffLines(diff, streaming)) const visibleRows = $derived(visibleToolDiffRows(diffRows, expansions)) const language = $derived(toolCodeDiffLanguage(diff.lang)) + const beforeLanguage = $derived(toolCodeDiffLanguage(diff.beforeLang ?? diff.lang)) const lastLines = $derived.by(() => { let old = 0 let current = 0 @@ -38,10 +39,12 @@ `max(0.875rem, ${String(Math.max(lastLines.old, lastLines.current)).length}ch)` ) const highlighted = $derived.by(() => { - if (!hljs.getLanguage(language.name)) hljs.registerLanguage(language.name, language.register) + for (const { name, register } of [language, beforeLanguage]) { + if (!hljs.getLanguage(name)) hljs.registerLanguage(name, register) + } return { - original: highlightedSourceLines(diff.before, language.name, lastLines.old), + original: highlightedSourceLines(diff.before, beforeLanguage.name, lastLines.old), modified: highlightedSourceLines(diff.after, language.name, lastLines.current) } }) @@ -82,50 +85,54 @@ class="tool-code-diff max-h-[400px] overflow-auto bg-surface-tertiary text-xs leading-[18px] text-primary" style="--line-number: {lineNumberWidth}" > - {#each visibleRows as row, index ('key' in row ? `${row.kind}:${row.key}` : `line:${row.oldLine}:${row.newLine}:${index}`)} - {#if row.kind === 'collapsed' || row.kind === 'omitted'} - - {:else} -
- {row.oldLine ?? ''} - - {row.newLine ?? ''}{row.kind === 'added' ? '+' : row.kind === 'removed' ? '-' : ''} - - +
+ {#each visibleRows as row, index ('key' in row ? `${row.kind}:${row.key}` : `line:${row.oldLine}:${row.newLine}:${index}`)} + {#if row.kind === 'collapsed' || row.kind === 'omitted'} +
- {/if} - {/each} + ... + + ...... + + {row.count} {row.kind === 'collapsed' ? 'unchanged lines' : 'more lines'} + + {:else} +
+ {row.oldLine ?? ''} + + {row.newLine ?? ''}{row.kind === 'added' ? '+' : row.kind === 'removed' ? '-' : ''} + + + {#each row.changedRanges ?? [] as range} + + {/each} + {@html highlightedLine(row) || ' '} + +
+ {/if} + {/each} +