mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
The cold resume path in resumeSession() painted the transcript twice: once from the REST prefetch (eager setMessages), then again when the session.resume RPC landed (reconcileAuthoritativeMessages + setMessages). A third re-render came from setBusy(true) during the load followed by setBusy(false) in the finally — the busy→idle transition re-rendered the thread viewport. Three changes fix this: 1. Defer the prefetch paint until BOTH the prefetch and the resume RPC have landed, then paint once. Wall time stays max(prefetch, resume) but the DOM only updates a single time. The prefetch result is awaited concurrently but not applied until after the RPC resolves. 2. Remove setBusy(true) from the cold-path entry. This is a history load, not a live turn — the busy flag is for active LLM turns only. The loading spinner is unaffected: it's driven by messagesEmpty && !activeSessionId, not by $busy. The busy→idle transition was causing a second thread viewport re-render. 3. Drop the resumed.messages.length <= prefetchedMessageCount guard on the prefetch-hit fast path. When the prefetch already painted (now deferred) and the RPC returns no live projection, the REST endpoint is the display authority — the RPC's compressed-context projection can differ in count/content, so re-painting from it causes a teardown + rebuild. Now the prefetch result is always preferred when idle. Also adds a direct setMessages call after updateSessionState so the final paint happens synchronously (updateSessionState's RAF flush via syncSessionStateToView is deferred and mocked in tests). The e2e test (large-session-reload.spec.ts) now fails with 1 mutation burst instead of 2, proving the fix eliminates the duplicate re-render. The test's MutationObserver was also refined to only count additive bursts (node additions), ignoring the expected setMessages([]) clear. |
||
|---|---|---|
| .. | ||
| bootstrap-installer | ||
| desktop | ||
| shared | ||