Skip to content

fix(web): take the coordinator's working state from the hub alone - #222

Merged
TheGreatAxios merged 5 commits into
mainfrom
fix/thinking-stuck-after-tab-hidden
Nov 8, 2026
Merged

TheGreatAxios merged 5 commits into
mainfrom
fix/thinking-stuck-after-tab-hidden

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

What

"Thinking…" no longer sticks under a reply that arrived while the tab was hidden.

Why

The transcript took the coordinator to be working if the run stream's own flag was set or the hub's activity read said so. The stream pauses while the tab is hidden, so a run that ended meanwhile never cleared the flag, and the mark stayed until a reload. The hub's read already answers the question and is refreshed on every stream event and poll, so the flag is no longer consulted.

Changes

  • apps/web/src/pages/workspace/index.tsx: working comes from the hub's activity read alone, and the coordinator's activity is looked up once for it and for the hand-off calls.

The transcript's stream flag stayed set when the run ended while the tab was hidden, so "Thinking…" stuck under the reply until a reload. The hub's activity read already answers the same question and is re-read every poll; the flag is no longer consulted.
@corbits-triage

corbits-triage Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Triage: Pass

No changes needed from you. A maintainer will review this pull request.

Changed since the last verdict (Fail at af6fdb6): 4 new commits.

The invented zero stood in for a stream that had seen no end yet.
coordinatorWorking in live-run.ts beside the other run helpers; the room finds the coordinator's activity once.
Comment on lines 749 to +752
const working =
liveRun.running ||
(coordinatorTurnSince !== undefined &&
Date.parse(coordinatorTurnSince) > (liveRun.endedAt ?? 0));
coordinator !== undefined &&
(liveRun.endedAt === null ||
Date.parse(coordinator.since) > liveRun.endedAt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Thinking… now shows up late when a turn starts

message.run.started is not in reloadAfter, so it does not refresh the room or re-read the hub's activity. With liveRun.running dropped, working waits for the next activity poll (POLL_MS, 10s when idle) or a later reload frame such as inference.done or tool.done.

The tab is idle and the coordinator starts a turn, for example on a message from elsewhere. The stream gets message.run.started, but nothing shows the coordinator working for up to 10s.

Resolve this comment. Triage will not finish while it is open.

Comment on lines +751 to +752
(liveRun.endedAt === null ||
Date.parse(coordinator.since) > liveRun.endedAt);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 · Clock skew can hide an entire turn now that the stream flag is gone

liveRun.endedAt is the browser's Date.now(), but coordinator.since is the hub's clock. If the browser clock runs ahead of the hub by more than the gap between turns, since > endedAt stays false for the whole next turn. Before this change, liveRun.running covered that case; now nothing does.

The browser clock is a few seconds ahead of the server and the person sends a follow-up soon after a reply. working stays false for that whole turn.

Resolve this comment. Triage will not finish while it is open.

@TheGreatAxios
TheGreatAxios added this pull request to the merge queue Nov 8, 2026
Merged via the queue into main with commit a48e2d9 Nov 8, 2026
9 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