todo: refresh mid-turn folds the still-running tool call
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
---
|
||||
id: known-bugs/refresh-mid-tool-call-renders-the-turn-folded
|
||||
title: 'Refresh mid-turn folds the live tool call — it reads as finished while still running'
|
||||
theme: known-bugs
|
||||
status: open
|
||||
created: 2026-08-25
|
||||
date_source: stated
|
||||
order: 5
|
||||
---
|
||||
|
||||
**Refresh mid-turn folds the live tool call.** Reported 2026-08-25: refreshing while an agent is mid
|
||||
tool-run collapses that turn's tool calls instead of leaving them expanded, so the chat reads as
|
||||
finished when the agent is still working. Requested fix: the last, still-running turn must always
|
||||
render EXPANDED across a refresh or a back-navigation, never folded.
|
||||
|
||||
**This is not unbuilt — there is already code for exactly this case, and it is being defeated
|
||||
somewhere between the transcript load and the live-state confirmation.** `turn-rows.ts`'s `buildRows`
|
||||
computes `generatingNow = isLast && isGenerating` and refuses to fold the last turn when it is true — a
|
||||
comment there names this precise failure mode: _"for those few frames every unfinished turn looks
|
||||
finished."_ So the intended behaviour is real; the bug is that the frames it warns about are not always
|
||||
brief.
|
||||
|
||||
Where the race most likely lives, traced but not proven — `hooks/useChat.ts`:
|
||||
|
||||
- **`historicalCount` starts at `preloadedMessages?.length ?? 0`** (line ~110) — the whole HTTP-loaded
|
||||
transcript, tool call included, counted as history from the first render.
|
||||
- **`isGenerating` starts `false`** and is only set true when the socket confirms it — via
|
||||
`sync:live` (rebinding to a turn that kept running) or `sync:messages` (a full resume).
|
||||
- **`sync:live`'s own comment says messages are "deliberately absent — the transcript already loaded
|
||||
over HTTP"** — it sets `isGenerating` but does not touch `historicalCount`. `sync:messages`, by
|
||||
contrast, sets both together in one call (`setHistoricalCount(transcript.length)` immediately before
|
||||
`setIsGenerating(msg.isGenerating)`), which is the version that should self-correct.
|
||||
|
||||
So the two socket messages that confirm "still generating" do not treat `historicalCount` the same way,
|
||||
and a refresh's actual sequence — HTTP transcript first, socket confirmation after — is exactly the
|
||||
gap the `generatingNow` guard was written to close but may not fully reach depending on which message
|
||||
arrives. Worth checking first: whether `sync:live` reliably fires before the user notices, and whether
|
||||
server-side `session.isGenerating` (true from turn-start to turn-end in `claude-manager.ts`, tool calls
|
||||
included) is actually what reaches the client in that message — or whether it's a timing gap rather
|
||||
than a wrong value.
|
||||
|
||||
Possibly related, same neighbourhood (refresh + a live turn + folding), not confirmed as the same
|
||||
cause: `known-bugs/refreshing-a-finished-chat-turn-loses-output` — a different symptom (a turn that DID
|
||||
finish loses its output entirely and misreports `0 turns · 0 tok`) but the same refresh-time seam
|
||||
between what the transcript says and what the live socket confirms.
|
||||
Reference in New Issue
Block a user