From 38e4d9ad5d2498e228bd1d6215576763b21cc719 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Wed, 15 Jul 2026 11:24:05 +0200 Subject: [PATCH] feat(app): polish sidebar and tool call summaries --- packages/app/src/agent-stream/view.tsx | 2 - packages/app/src/components/left-sidebar.tsx | 2 +- .../tool-calls/detail-level/overview/model.ts | 15 ----- .../tool-calls/detail-level/overview/view.tsx | 25 ++------ .../detail-level/projection.test.ts | 59 ++++--------------- 5 files changed, 17 insertions(+), 86 deletions(-) diff --git a/packages/app/src/agent-stream/view.tsx b/packages/app/src/agent-stream/view.tsx index 4736bd5c0..3da69787d 100644 --- a/packages/app/src/agent-stream/view.tsx +++ b/packages/app/src/agent-stream/view.tsx @@ -779,7 +779,6 @@ const AgentStreamViewComponent = forwardRef {expanded ? group.run.calls.map((call, index) => ( @@ -799,7 +798,6 @@ const AgentStreamViewComponent = forwardRef + - ); diff --git a/packages/app/src/tool-calls/detail-level/overview/model.ts b/packages/app/src/tool-calls/detail-level/overview/model.ts index 31faa23f2..c0901ea63 100644 --- a/packages/app/src/tool-calls/detail-level/overview/model.ts +++ b/packages/app/src/tool-calls/detail-level/overview/model.ts @@ -21,21 +21,6 @@ export interface OverviewToolCallGroup { isLoading: boolean; } -export type OverviewHeader = { kind: "latest"; call: ToolCallRun["latest"] } | { kind: "summary" }; - -export function resolveOverviewHeader( - group: OverviewToolCallGroup, - expanded: boolean, -): OverviewHeader { - if (group.run.calls.length === 1) { - return { kind: "latest", call: group.run.latest }; - } - if (expanded || group.run.isSealed) { - return { kind: "summary" }; - } - return { kind: "latest", call: group.run.latest }; -} - function isPaseoCall(name: string, normalizedName: string): boolean { return isPaseoToolName(name) || normalizedName.startsWith(DIRECT_PASEO_TOOL_PREFIX); } diff --git a/packages/app/src/tool-calls/detail-level/overview/view.tsx b/packages/app/src/tool-calls/detail-level/overview/view.tsx index c2cc68fc7..75f4cf48f 100644 --- a/packages/app/src/tool-calls/detail-level/overview/view.tsx +++ b/packages/app/src/tool-calls/detail-level/overview/view.tsx @@ -9,7 +9,7 @@ import { useToolCallSheet } from "@/components/tool-call-sheet"; import { buildToolCallPresentation } from "@/tool-calls/presentation"; import { resolveToolCallIcon } from "@/utils/tool-call-icon"; import { describeToolCall } from "../grouping"; -import { resolveOverviewHeader, type OverviewSummary, type OverviewToolCallGroup } from "./model"; +import { type OverviewSummary, type OverviewToolCallGroup } from "./model"; interface OverviewGroupProps { group: OverviewToolCallGroup; @@ -18,7 +18,6 @@ interface OverviewGroupProps { isLastInSequence: boolean; onExpandedChange: (groupId: string, expanded: boolean) => void; cwd?: string; - onOpenFilePath?: (filePath: string) => void; children: ReactNode; } @@ -66,17 +65,14 @@ export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView isLastInSequence, onExpandedChange, cwd, - onOpenFilePath, children, }: OverviewGroupProps) { const { t } = useTranslation(); const { openToolCall } = useToolCallSheet(); const scrollRef = useRef(null); const aggregateSummary = useOverviewSummary(group.summary); - const header = resolveOverviewHeader(group, expanded); - const latestCall = header.kind === "latest" ? header.call : group.run.latest; const latest = useMemo(() => { - const descriptor = describeToolCall(latestCall); + const descriptor = describeToolCall(group.run.latest); return { detail: descriptor.detail, presentation: buildToolCallPresentation({ @@ -89,16 +85,8 @@ export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView resolveIcon: resolveToolCallIcon, }), }; - }, [cwd, latestCall]); - const showsLatest = header.kind === "latest"; + }, [cwd, group.run.latest]); const opensSingleCallSheet = isCompact && group.run.calls.length === 1; - const openLatestFile = useMemo(() => { - const path = latest.presentation.openFilePath; - if (!showsLatest || !path || !onOpenFilePath) { - return undefined; - } - return () => onOpenFilePath(path); - }, [showsLatest, latest.presentation.openFilePath, onOpenFilePath]); const failedSummary = group.failedCount > 0 ? t("toolCallGroup.failed", { count: group.failedCount }) : undefined; const scrollToLatest = useCallback(() => { @@ -147,15 +135,14 @@ export const OverviewToolCallGroupView = memo(function OverviewToolCallGroupView return ( 0} isExpanded={opensSingleCallSheet ? false : expanded} isLastInSequence={isLastInSequence} onToggle={canExpand ? toggle : undefined} - onOpenFile={openLatestFile} renderDetails={canExpand && !opensSingleCallSheet ? renderDetails : undefined} borderlessWhenExpanded /> diff --git a/packages/app/src/tool-calls/detail-level/projection.test.ts b/packages/app/src/tool-calls/detail-level/projection.test.ts index d8b56d46b..de5a8b150 100644 --- a/packages/app/src/tool-calls/detail-level/projection.test.ts +++ b/packages/app/src/tool-calls/detail-level/projection.test.ts @@ -7,7 +7,6 @@ import { type PreparedToolCallHistory, type ToolCallDetailLevel, } from "./projection"; -import { resolveOverviewHeader } from "./overview/model"; type AssistantMessageItem = Extract; @@ -111,25 +110,6 @@ describe("tool call detail-level projection", () => { }); }); - it("shows the latest call while collapsed and the summary while expanded", () => { - const calls = [ - toolCall("1", { type: "shell", command: "one" }), - toolCall("2", { type: "read", filePath: "/repo/a.ts" }, { status: "running" }), - ]; - const result = project({ - level: "overview", - head: calls, - isTurnActive: true, - }); - const group = result.groupsByHostId.get("1"); - if (!group) { - throw new Error("Expected an overview group"); - } - - expect(resolveOverviewHeader(group, false)).toEqual({ kind: "latest", call: calls[1] }); - expect(resolveOverviewHeader(group, true)).toEqual({ kind: "summary" }); - }); - it("keeps a parallel group loading while any call is still running", () => { const calls = [ toolCall("1", { type: "shell", command: "slow" }, { status: "running" }), @@ -140,16 +120,18 @@ describe("tool call detail-level projection", () => { expect(result.groupsByHostId.get("1")?.isLoading).toBe(true); }); - it("keeps a one-call run presented as its tool call", () => { - const call = toolCall("1", { type: "shell", command: "one" }); - const result = project({ level: "overview", head: [call] }); + it("builds a loading aggregate for a one-call run", () => { + const call = toolCall("1", { type: "shell", command: "one" }, { status: "running" }); + const result = project({ level: "overview", head: [call], isTurnActive: true }); const group = result.groupsByHostId.get(call.id); if (!group) { throw new Error("Expected an overview group"); } - expect(resolveOverviewHeader(group, false)).toEqual({ kind: "latest", call }); - expect(resolveOverviewHeader(group, true)).toEqual({ kind: "latest", call }); + expect(group).toMatchObject({ + isLoading: true, + summary: { commandCount: 1 }, + }); }); it("keeps an active overview group on its latest call until a visible boundary arrives", () => { @@ -172,11 +154,6 @@ describe("tool call detail-level projection", () => { mode: "overview", run: { id: "1", latest: calls[3], isSealed: false }, }); - expect(resolveOverviewHeader(activeGroup!, false)).toEqual({ - kind: "latest", - call: calls[3], - }); - const boundary = assistant("answer"); const sealed = project({ level: "overview", @@ -189,12 +166,9 @@ describe("tool call detail-level projection", () => { run: { latest: calls[3], isSealed: true }, summary: { editedFileCount: 1, readFileCount: 2, commandCount: 1 }, }); - expect(resolveOverviewHeader(sealed.groupsByHostId.get("1")!, false)).toEqual({ - kind: "summary", - }); }); - it("keeps a running overview header live before the agent lifecycle catches up", () => { + it("keeps a running overview group live before the agent lifecycle catches up", () => { const calls = ["1", "2", "3", "4"].map((id) => toolCall(id, { type: "shell", command: id }, { status: "running" }), ); @@ -207,10 +181,8 @@ describe("tool call detail-level projection", () => { expect(result.groupsByHostId.get("1")).toMatchObject({ run: { latest: calls[3], isSealed: false }, - }); - expect(resolveOverviewHeader(result.groupsByHostId.get("1")!, false)).toEqual({ - kind: "latest", - call: calls[3], + isLoading: true, + summary: { commandCount: 4 }, }); }); @@ -239,22 +211,11 @@ describe("tool call detail-level projection", () => { }); expect(betweenCalls.groupsByHostId.get("1")?.run.isSealed).toBe(false); - expect(resolveOverviewHeader(betweenCalls.groupsByHostId.get("1")!, false)).toEqual({ - kind: "latest", - call: calls[3], - }); expect(continued.groupsByHostId.get("1")?.run).toMatchObject({ latest: nextCall, isSealed: false, }); - expect(resolveOverviewHeader(continued.groupsByHostId.get("1")!, false)).toEqual({ - kind: "latest", - call: nextCall, - }); expect(ended.groupsByHostId.get("1")?.run.isSealed).toBe(true); - expect(resolveOverviewHeader(ended.groupsByHostId.get("1")!, false)).toEqual({ - kind: "summary", - }); }); it("builds overview summaries without category-specific presentation data", () => {