Dashboard embedded chat wheel scrolling and scrollback handling
Cluster 19084 · dashboard. Data as of
1 open item. Fix merged in #28584 on 19 May 2026. Check it covers your case.
The short answer
- Known?
- Yes. 5 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #28584. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
resolved, deciding PR #28584. That is separate from the fix event. - Still open
- 0 issues and 1 PR.
Most members concern mouse wheel scrolling and transcript scrollback in the dashboard's embedded chat (/chat), including one issue report and several pull requests with similar titles. Some also mention related areas such as chat resume stability and terminal clipboard handling, but the shared theme is scroll behavior.
Open issues0
Open PRs1
- PR#29975fix: improve dashboard terminal clipboard and wheel handling
Fixes on record
-
#28584 fix(dashboard): use browser scrollback for chat wheel (#28029)
files:
hermes_cli/web_server.py,tests/hermes_cli/test_web_server.py,web/src/pages/ChatPage.tsxShow the diff
-
hermes_cli/web_server.py@@ -3350,6 +3350,7 @@ def _resolve_chat_argv( # build unchanged for native CLI usage; only disable mouse tracking for # the dashboard PTY path. env.setdefault("HERMES_TUI_DISABLE_MOUSE", "1") + env.setdefault("HERMES_TUI_INLINE", "1") if resume: latest_resume, _latest_path = _session_latest_descendant(resume) -
tests/hermes_cli/test_web_server.py@@ -2092,6 +2092,21 @@ def _url(self, token: str | None = None, **params: str) -> str: q = {"token": tok, **params} return f"/api/pty?{urlencode(q)}" + def test_resolve_chat_argv_uses_dashboard_scroll_env(self, monkeypatch): + """Dashboard chat runs the TUI in browser-scrollback mode.""" + import hermes_cli.main as main_mod + + monkeypatch.setattr( + main_mod, + "_make_tui_argv", + lambda project_root, tui_dev=False: (["node", "dist/entry.js"], "/tmp/ui-tui"), + ) + + _argv, _cwd, env = self.ws_module._resolve_chat_argv() + + assert env["HERMES_TUI_INLINE"] == "1" + assert env["HERMES_TUI_DISABLE_MOUSE"] == "1" + def test_rejects_when_embedded_chat_disabled(self, monkeypatch): monkeypatch.setattr(self.ws_module, "_DASHBOARD_EMBEDDED_CHAT_ENABLED", False) from starlette.websockets import WebSocketDisconnect -
web/src/pages/ChatPage.tsx@@ -298,10 +298,9 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) { // is false; enabling it gives users a single-action selection // path on top of the modifier-based bypass above. rightClickSelectsWord: true, - // Single-scroll-system experiment: - // let the inner Hermes TUI own transcript history/scroll behavior. - // The outer browser xterm should act as a display/input bridge only. - scrollback: 0, + // Browser-embedded chat runs the TUI in inline mode. Keep transcript + // history in xterm.js so the browser wheel can scroll it directly. + scrollback: 5000, theme: TERMINAL_THEME, }); termRef.current = term; @@ -345,7 +344,7 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) { // original keydown event's activation. Log to aid debugging. console.warn("[dashboard clipboard] OSC 52 write failed:", err.message); }); - } catch (e) { + } catch { console.warn("[dashboard clipboard] malformed OSC 52 payload"); } return true; @@ -404,34 +403,16 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) { fitRef.current = fit; term.loadAddon(fit); - // Single-scroll-system experiment: - // keep browser xterm as a display/input bridge only, and let the inner - // Hermes TUI own transcript scrolling. - // - // In practice, the most reliable path here is NOT terminal mouse-wheel - // protocol emulation — that can vary by terminal mode and parser path. - // The inner TUI already handles keyboard-driven transcript scrolling - // correctly (`Shift+Up` / `Shift+Down`, `PageUp` / `PageDown`), so we - // translate browser wheel gestures into those known-good key sequences. + // Dashboard chat should scroll the browser-side transcript, not send + // mouse-wheel protocol bytes through the PTY. term.attachCustomWheelEventHandler((ev) => { - if (wsRef.current?.readyState !== WebSocket.OPEN) { - return false; - } - const delta = ev.deltaY; if (!delta) { return false; } - // Shift+Up / Shift+Down: the TUI maps these to line-by-line - // transcript scrolling, which feels much closer to wheel behavior - // than PageUp/PageDown's half-page jumps. const step = Math.max(1, Math.round(Math.abs(delta) / 50)); - const seq = delta > 0 ? "\x1b[1;2B" : "\x1b[1;2A"; - - for (let i = 0; i < step; i++) { - wsRef.current.send(seq); - } + term.scrollLines(delta > 0 ? step : -step); ev.preventDefault(); ev.stopPropagation();
-
2 PRs closed without merging
From the close comments: merged via another change 1 · other 1
Closed issues · 1
- Closed#19084dashboard /chat: wheel scrolling does not reliably scroll transcript history in embedded chat
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.40: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- dashboard
- Merged PRs
- #28584
- Closed issues
- 1
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 19 May 2026