Files
coder/site/src/utils
Ethan 196c61051f feat(site): structured error/retry UX for agent chat (#23282)
> **PR Stack**
>
> 1. #23351 ← `#23282`
> 2. **#23282** ← `#23275` *(you are here)*
> 3. #23275 ← `#23349`
> 4. #23349 ← `main`

---

## Summary

Replaces raw error strings and infinite "Thinking..." spinners in the
agents chat UI with a structured live-status model that drives startup,
retry, and failure UI from one source of truth.

This branch also folds in the frontend follow-up fixes that fell out of
that refactor: malformed `retrying_at` timestamps no longer render
`Retrying in NaNs`, stale persisted generic errors no longer outlive a
recovered chat status, and partial streamed output stays visible when a
response fails after blocks have already rendered.

Consumes the structured error metadata added in #23275.
Retry-After header handling remains in #23351.

<img width="853" height="493" alt="image"
src="https://github.com/user-attachments/assets/5a4a1690-5e22-4ece-965c-a000fd669244"
/>

<img width="812" height="517" alt="image"
src="https://github.com/user-attachments/assets/e78d28ce-1566-48ca-a991-62c6e1838079"
/>

<img width="847" height="523" alt="image"
src="https://github.com/user-attachments/assets/e5fd7b60-4a3c-4573-ba4c-4e5f6dbfbdc3"
/>

## Problem

The previous AgentDetail chat UI derived startup, retry, and failure
behavior from several loosely connected bits of state spread across
`ChatContext`, `AgentDetailContent`, `ConversationTimeline`, and ad hoc
props. That made the UI inconsistent: some failures were just raw
strings, retry state could only partially describe what was happening,
startup could sit on an infinite spinner, and rendering decisions
depended on local booleans instead of one authoritative model.

Those splits also made edge cases brittle. Invalid retry timestamps
could produce broken countdown text, persisted generic errors could
linger after recovery, and streamed partial output could disappear if
the turn later failed.

## Fix

Introduce a structured live-status pipeline for AgentDetail.
`ChatContext` now normalizes stream errors and retry metadata into
richer state, `liveStatusModel` centralizes precedence and phase
derivation, and `ChatStatusCallout` renders startup, retry, and terminal
failure states with shared copy, provider attribution, status links,
attempt metadata, and guarded countdown handling.

`AgentDetailContent` and `ConversationTimeline` now consume that single
model instead of juggling separate error and stream booleans, while
usage-limit messaging stays on its explicit path. The result is a
timeline that shows consistent state transitions, preserves accumulated
assistant output across failures, suppresses stale generic errors once
live state recovers, and has focused model, store, and story coverage
around those behaviors.
2026-03-26 01:45:39 +11:00
..