feat(desktop): show per-turn wall-clock duration in the transcript - #84430
feat(desktop): show per-turn wall-clock duration in the transcript#84430Tommy00748 wants to merge 1 commit into
Conversation
Each assistant reply now carries a small time badge below the message text showing how long its turn took (message.start -> message.complete), so users can gauge task latency at a glance without hovering. The duration is computed renderer-side from the per-session turnStartedAt timestamp the app already tracks and stamped onto the ChatMessage at completion (successful and failed turns alike). It is not persisted backend-side, so messages hydrated from history have no badge — matching how reasoning-block durations already behave. Also adds the assistant.thread.turnDuration i18n key across all five locale files.
Related: #81949 is an earlier open implementation of Desktop turn-duration display that persists end-to-end metadata. This PR instead keeps renderer-only wall-clock duration for live turns. The user-facing scope overlaps, but the persistence/design choices differ; maintainer selection is needed. |
|
Salvaged and merged in #87245 — your commit landed on main with authorship preserved (a6f7a5b → rebase-merged). Two small adjustments during the salvage: kept main's newer timeline fields ( |
Summary
Each assistant reply in the desktop app now carries a small time badge (⏱ 38s) below the message text, showing how long its turn took (message.start → message.complete). Users get a glanceable sense of task latency per turn — useful when a turn spins through many tools or a long reasoning block.
Design notes
turnStartedAtper session (set onmessage.start, cleared on completion). The badge duration is computed from that at settle time — no backend change, no new events, works for adopted and local turns alike.ChatMessage.durationSat completion incompleteAssistantMessage(all settle paths viacompleteMessage/newAssistantFromCompletion) and onfailAssistantMessage(failed turns get a badge too).useMeasuredDurationis renderer-memory only). The badge is a "you were here" signal, not archival data.useAuiStateselector for the badge reads a value set once at completion — referentially stable across the 30 Hz delta stream, so no per-token re-renders (the component has strict perf rules; the footer/action bar must not subscribe to streaming text).assistant.thread.turnDurationkey added to all five locale files.Verification
npm run typecheck(renderer + electron + e2e tsconfigs) ✅eslintclean on all changed files ✅npm run test:ui— 413 files / 3680 tests ✅vitest run --project electron— 86 files / 1023 tests ✅npm run test:desktop:all(packaging + bundle validation) ✅