Skip to content

fix(webui): clear stale 'Reasoning...' indicator before large-chat re-render - #1803

Open
Zenetusken wants to merge 1 commit into
agent0ai:mainfrom
Zenetusken:fix/webui-stale-progress-reconnect
Open

fix(webui): clear stale 'Reasoning...' indicator before large-chat re-render#1803
Zenetusken wants to merge 1 commit into
agent0ai:mainfrom
Zenetusken:fix/webui-stale-progress-reconnect

Conversation

@Zenetusken

Copy link
Copy Markdown

Problem

After a WebSocket reconnect mid-turn (e.g. container restart while a chat is open), applySnapshot applied the cheap agent-state fields after await setMessages(...):

if (lastLogVersion != snapshot.log_version) {
  await setMessages(...);              // can take minutes on large chats
}
updateProgress(...);                   // stale 'A0: Reasoning...' until render drains
notificationStore.updateFromPoll(...);
inputStore.paused = ...;

While disconnected the log version advances, so the reconnect snapshot always takes the heavy render path. On large chats (observed: 543 entries / 7.5 MB log) the re-render takes so long that the frontend shows a stale "A0: Reasoning..." progress indicator long after the agent has actually finished — the Web UI appears to still be working while other clients (CLI, fresh tabs) correctly report completion.

Root cause evidence

  • Backend verified idle and correct: all run_ui threads parked (py-spy dump), persisted log frozen with a final response entry, message queue empty; log.progress_active is false in every post-completion snapshot.
  • The temporary "Reasoning..." item exists only in-memory during streaming (extensions/python/reasoning_stream/_10_log_from_stream.py) and is never persisted; the stale display was purely frontend sequencing.

Fix

Apply updateProgress, notificationStore.updateFromPoll and inputStore.paused before the render await in applySnapshot. Log-version cursors intentionally remain behind the render: if setMessages throws, the next poll retries the same log version instead of skipping it.

Validation

  • New tests/test_webui_snapshot_ordering.py (4 tests) pins the ordering — discriminating: 3 fail on pre-fix v2.8 code, all 4 pass with the fix; the cursor-ordering guard passes on both.
  • Full suite: 1328 passed, 0 failed, 1 skipped on the v2.8 runtime.
  • node --check webui/index.js clean.

After a WebSocket reconnect mid-turn, applySnapshot sequenced the cheap
agent-state updates (progress indicator, paused flag, notifications) behind
'await setMessages(...)'. On large chats the re-render can take a very long
time, so a stale 'A0: Reasoning...' indicator persisted after the agent had
actually finished — the Web UI appeared to still be working while the CLI
(cheap render, fresh connection) correctly reported completion.

Apply updateProgress, notificationStore.updateFromPoll and inputStore.paused
before the render await. Log-version cursors intentionally stay behind the
render so a failed render retries the same version on the next poll.

Regression coverage pins the ordering in webui/index.js (discriminating:
fails on pre-fix v2.8, passes with the fix).
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