feat(web): collapse chat tool calls into one agent trace, reverse the activity rail
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

The chat rendered one card per tool call, so a 20-call turn buried the
answer under 20 stacked cards. Merge them with the "thinking" indicator
into a single collapsible strip above the answer:

- collapsed: the live activity while running, a count once finished
- expanded: the turn's work in humanized language (reuses the activity
  log's toolActivityLabel, so ten identical "run · target: host:strong"
  rows now read as what they actually did)
- per row: the raw args/result, one more click in

Also flip the Activity rail to newest-first with the current step on top:

- follow-mode/auto-scroll re-anchored to the top to match, or it would
  jump to the oldest entry on every new event
- pending plan steps park at the tail rather than sorting above the
  running step and pushing it off the top; the goal anchors the bottom

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-26 13:06:01 +02:00
parent 4e4e2c169c
commit 8f440c5ad5
5 changed files with 203 additions and 67 deletions

View File

@@ -185,7 +185,10 @@ export function activityLogFor(sessionId: string): Readable<ActivityEntry[]> {
return derived([chat.messages, ws.planSteps, task], ([$msgs, $steps, $task]) => computeActivityLog($msgs, $steps, $task))
}
function toolActivityLabel(t: ToolCallResult): string {
// Humanized, past/present-tense description of what a tool call is doing
// ("Check execution", "Research: …") rather than its raw wire name. Exported
// so the chat's agent trace can read as a thinking log instead of an API log.
export function toolActivityLabel(t: ToolCallResult): string {
const args = t.args ?? {}
const str = (v: unknown): string => typeof v === 'string' ? v : ''
switch (t.name) {