Skip to content

chat-ui: reply-timeout backstop gets ref + Retry (CL-6677) - #330

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-6677-timeout-ref-retry
Aug 22, 2026
Merged

chat-ui: reply-timeout backstop gets ref + Retry (CL-6677)#330
TheGreatAxios merged 2 commits into
mainfrom
cl-6677-timeout-ref-retry

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Two independent 120s no-reply backstops existed; only the server-side postUndeliveredNotice had the ref+Retry treatment (CL-6308). A cold-wake failure never throws inside dispatchTurn — mail sends fine, the agent just never streams — so it was caught only by an older client-side timer that rendered a bare, ref-less notice.

The client timer now reports through reportError (real refId) and renders via the same FailedTurnStrip as every other failed turn.

Known follow-up (documented at the call site, not fixed here): there is no wake-in-progress signal anywhere in the stack, so a ~105s cold wake is indistinguishable from thinking time.

  • Tests first: 0cfb2cea
  • Implementation: 1a3ce433

bun run check green in the worktree.

A turn that fails on the cold-wake path (a parked room re-deploying
and re-deriving its inference source, PR #327) never emits a single
chat.agent event, so the client's own reply-timeout backstop fires
instead of the server-side undelivered-turn notice. These tests pin
the fix: that backstop must mint a reportError refId and render
through the same FailedTurnStrip (ref id quotable, Retry wired) as
any other turn that ends with no reply, rather than a bare event line
with no ref and no action.
useStreamingReply's PENDING_REPLY_CLEAR_MS backstop (a turn that opens
but never gets a token or a terminal event) rendered as a bare quiet
event line with no ref id and no Retry -- a weaker, separate backstop
sitting beside postUndeliveredNotice's honest one for the exact same
failure class. This surfaced starkly on the cold-wake path (PR #327's
defer-to-wake single-step restore): a room can wake, redeploy, and
re-derive its inference source without ever throwing an error the
server side can catch, so every such failure fell through to this
weaker client-side notice.

useStreamingReply now mints a reportError refId the moment its timer
fires (replyTimedOutRefId replaces the bare boolean), and
appendReplyTimedOutNotice builds a turnFailed text part carrying it,
attributed to the workbench's agent participant the same way
mergeStreamingReply already does. That routes it through the same
FailedTurnStrip every other undelivered-turn notice uses, so the
person gets a quotable ref and a working Retry regardless of which
backstop caught the failure. The now-dead chat.reply-timed-out event
branch is removed rather than left beside the new path.

Also notes, at the sendMail wake call site, that no wake-in-progress
signal exists yet to shorten the ~105s of silent typing pulse a real
cold wake can take before either backstop fires -- surfacing a
"waking up" state needs a signal threaded through sendMail's wake,
subscribeToWorkbench's stream, and useStreamingReply, which is
follow-up work rather than a client-side fix.
@TheGreatAxios
TheGreatAxios merged commit 29b0b47 into main Aug 22, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant