Skip to content

fix(tui): defer buffered gateway events to stop dashboard chat #301 (#36658) - #54116

Merged
kshitijk4poor merged 1 commit into
NousResearch:mainfrom
kshitijk4poor:fix/36658-gateway-drain-microtask
Jun 28, 2026
Merged

fix(tui): defer buffered gateway events to stop dashboard chat #301 (#36658)#54116
kshitijk4poor merged 1 commit into
NousResearch:mainfrom
kshitijk4poor:fix/36658-gateway-drain-microtask

Conversation

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Summary

Dashboard /chat works again after hermes update — it was throwing Minified React error #301 ("Too many re-renders") and rendering nothing.

Root cause: Dashboard /chat spawns the TUI attached to the dashboard's in-memory gateway (HERMES_TUI_GATEWAY_URL). In attach mode the gateway is already running, so it replays gateway.ready / session.info the instant the socket connects — those land in GatewayClient.bufferedEvents before the consumer's mount-time subscribe effect (useMainApp.ts) calls drain(). drain() emitted the buffered events synchronously, so the gateway.ready handler's patchUiState / setHistoryItems cascade ran while React was still inside its first commit → #301. Spawn / inline / sidecar modes never hit it: their gateway.ready arrives only after the Python child boots, on a later async tick.

Changes

  • ui-tui/src/gatewayClient.tsdrain() defers the buffered-event replay to the next microtask and keeps subscribed false until that microtask runs, so a LIVE event arriving in the gap keeps buffering (publish() pushes when !subscribed) instead of jumping ahead of the chronologically-earlier replayed events; the flush re-drains right after flipping subscribed, preserving FIFO. A drainGeneration token (bumped in resetStartupState) makes a queued flush a no-op if the transport was reset/killed meanwhile.
  • ui-tui/src/__tests__/gatewayClient.test.ts — 2 regression tests: (1) drain() does not dispatch buffered events synchronously; (2) a live event arriving in the post-drain / pre-microtask window still delivers BEHIND the earlier-buffered event (FIFO).

Same class of fix as #44528 (deferred a config RPC for an embedded-dashboard #301) — the defect is event-delivery timing at the transport seam, not hook-dep identity in the component.

Validation

Synchronous drain() (before) Deferred drain() (after)
attach-mode gateway.ready replay fires inside first commit → #301 fires on microtask, after commit ✓
live event in post-drain gap could reorder ahead of buffered stays FIFO behind buffered ✓
  • npx vitest run src/__tests__/gatewayClient.test.ts → 13 passed. Proven RED→GREEN: reverting drain() to the synchronous loop fails the 2 new tests, restoring passes.
  • npx tsc --noEmit -p tsconfig.json → clean. npx eslint on changed files → clean.

Closes #36658

…search#301 (NousResearch#36658)

Dashboard /chat spawns the TUI attached to the dashboard's in-memory
gateway via HERMES_TUI_GATEWAY_URL. In that attach mode the already-running
gateway replays `gateway.ready` (and `session.info`) the instant the socket
connects, so those events land in GatewayClient.bufferedEvents *before* the
consumer's mount-time subscribe effect (useMainApp.ts) calls drain().

drain() then emitted the buffered events synchronously, so the
`gateway.ready` handler's patchUiState / setHistoryItems cascade ran while
React was still inside the first commit — tripping "Too many re-renders"
(Minified React error NousResearch#301) and breaking Dashboard chat after `hermes update`.
Spawn / inline / sidecar modes never hit this: their `gateway.ready` only
arrives after the Python child boots, on a later async tick.

Fix: drain() defers the replay to the next microtask AND keeps `subscribed`
false until that microtask runs. Keeping `subscribed` false in the gap means
any live event arriving before the flush keeps buffering (publish() pushes
when !subscribed) instead of emitting synchronously and jumping ahead of the
chronologically-earlier replayed events — the flush re-drains the buffer
right after flipping `subscribed`, preserving FIFO order. A drainGeneration
token (bumped in resetStartupState) makes a queued flush a no-op if the
transport was reset/killed in the meantime, avoiding use-after-teardown and
duplicate/reordered exits.

Regression tests: (1) drain() does not dispatch buffered events synchronously;
(2) a live event arriving in the post-drain / pre-microtask window still
delivers BEHIND the earlier-buffered event (FIFO). Both are red against the
old synchronous behavior, green with this fix. Same class of fix as NousResearch#44528.

Closes NousResearch#36658
@kshitijk4poor
kshitijk4poor enabled auto-merge June 28, 2026 09:16
@kshitijk4poor
kshitijk4poor merged commit f3d8f20 into NousResearch:main Jun 28, 2026
19 of 20 checks passed
@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists labels Jun 28, 2026
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…teway-drain-microtask

fix(tui): defer buffered gateway events to stop dashboard chat NousResearch#301 (NousResearch#36658)
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…teway-drain-microtask

fix(tui): defer buffered gateway events to stop dashboard chat NousResearch#301 (NousResearch#36658)
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…teway-drain-microtask

fix(tui): defer buffered gateway events to stop dashboard chat NousResearch#301 (NousResearch#36658)
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…teway-drain-microtask

fix(tui): defer buffered gateway events to stop dashboard chat NousResearch#301 (NousResearch#36658)
@kshitijk4poor
kshitijk4poor deleted the fix/36658-gateway-drain-microtask branch August 5, 2026 07:09
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…teway-drain-microtask

fix(tui): defer buffered gateway events to stop dashboard chat NousResearch#301 (NousResearch#36658)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Dashboard chat feature is broken after hermes update

2 participants