fix: group raw app edits that carry a file diff in the ai chat (#11558)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem
2026-10-06 14:35:26 +02:00
committed by GitHub
co-authored by Claude Opus 5.5
parent b371af31c9
commit 5912d300a5
4 changed files with 20 additions and 4 deletions
@@ -13,9 +13,10 @@
interface Props {
message: ToolDisplayMessage
hidePreviewChip?: boolean
}
let { message }: Props = $props()
let { message, hidePreviewChip = false }: Props = $props()
const diff = $derived(toolCodeDiff(message))
const isStreaming = $derived(Boolean(message.isStreamingArguments))
@@ -56,7 +57,7 @@
const isRunning = $derived(Boolean(message.isLoading && !message.needsConfirmation))
const showPreviewChip = $derived(
Boolean(message.previewCard && !message.isLoading && !message.error)
Boolean(!hidePreviewChip && message.previewCard && !message.isLoading && !message.error)
)
</script>
@@ -197,7 +197,7 @@
{:else if isRunCard}
<RunScriptCard {message} />
{:else if isDiffCard}
<ToolDiffCard {message} />
<ToolDiffCard {message} {hidePreviewChip} />
{:else if planState}
<!-- Same lean shape as a tool call below: a header row that collapses into the
transcript, with everything else in one box under it. -->
@@ -187,6 +187,19 @@ describe('groupToolRuns', () => {
).toEqual([{ edit: [0, 1, 2] }, { edit: [3, 4] }])
})
it('folds app edits that carry a file diff, but not a script edit with one', () => {
const app = { path: 'f/a/x' }
const diff = { codeDiff: { before: 'a', after: 'b' } }
expect(
shape([
tool('init_app', app),
tool('write_app_file', { ...app, file_path: '/App.tsx' }, diff),
tool('delete_app_runnable', { ...app, key: 'greet' }, diff),
tool('write_script', { path: 'f/a/s' }, diff)
])
).toEqual([{ edit: [0, 1, 2] }, 3])
})
it('leaves a flow read that prepares an edit to the edit group, not the lookups before it', () => {
const flow = { type: 'flow', path: 'f/a/flow' }
expect(
@@ -116,7 +116,9 @@ function groupableCall(message: DisplayMessage): ToolDisplayMessage | undefined
if (message.needsConfirmation || message.blockedByPlanMode) return undefined
if (message.heldForFolderInstructions) return undefined
if (message.runForm || message.inspectedRun || message.userQuestion) return undefined
if (message.codeDiff || message.imageUrl || message.webSearchSources) return undefined
// An app edit's diff covers one file of many, so it stays a row inside the app's group.
if (message.codeDiff && EDIT_TOOLS[message.toolName] !== 'app') return undefined
if (message.imageUrl || message.webSearchSources) return undefined
if (!message.error && webSearchResultOf(message.result)) return undefined
// The user's own refusal is a decision, not a failure to fold away.
if (message.declinedByUser) return undefined