From 51bcb5635c701b51f82eb412fe7809f34bec6433 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Wed, 6 May 2026 15:03:33 -0700 Subject: [PATCH] feat(ui/agents): add FilesChangedAccordion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aggregates file_diff events into a 'N Files Changed' collapsible at the bottom of the conversation pane. Cumulative across the run per LIT-2881 spec — latest patch wins, additions/deletions sum per path. --- .../three-pane/files-changed-accordion.tsx | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/agents/components/three-pane/files-changed-accordion.tsx diff --git a/ui/litellm-dashboard/src/app/(dashboard)/agents/components/three-pane/files-changed-accordion.tsx b/ui/litellm-dashboard/src/app/(dashboard)/agents/components/three-pane/files-changed-accordion.tsx new file mode 100644 index 00000000000..2ce7bdff813 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/agents/components/three-pane/files-changed-accordion.tsx @@ -0,0 +1,85 @@ +"use client"; + +/** + * FilesChangedAccordion — collapsible "N Files Changed" block in the + * conversation pane. Aggregates file_diff events by path: the latest patch + * wins, additions/deletions are summed per file. + * + * Cumulative across the entire run (per spec). + */ +import { Collapse, Tag, Typography } from "antd"; +import type { FileDiffPayload } from "@/types/cloud-agents"; + +const { Paragraph, Text } = Typography; + +interface FilesChangedAccordionProps { + diffs: FileDiffPayload[]; +} + +interface AggregatedDiff { + path: string; + additions: number; + deletions: number; + patch: string; +} + +function aggregate(diffs: FileDiffPayload[]): AggregatedDiff[] { + const byPath = new Map(); + for (const d of diffs) { + const existing = byPath.get(d.path); + if (existing) { + existing.additions += d.additions; + existing.deletions += d.deletions; + existing.patch = d.patch; // latest wins + } else { + byPath.set(d.path, { path: d.path, additions: d.additions, deletions: d.deletions, patch: d.patch }); + } + } + return Array.from(byPath.values()); +} + +export default function FilesChangedAccordion({ diffs }: FilesChangedAccordionProps) { + const aggregated = aggregate(diffs); + if (aggregated.length === 0) return null; + + return ( + + {aggregated.length} {aggregated.length === 1 ? "File" : "Files"} Changed + + ), + children: ( +
+ {aggregated.map((d) => ( +
+ + +{d.additions} + + + -{d.deletions} + + {d.path} +
+ ))} + {aggregated.map((d) => ( + + {d.patch} + + ))} +
+ ), + }, + ]} + /> + ); +}