Skip to content

fix(dashboard): recover mobile chat reconnect - #61314

Closed
shannonsands wants to merge 2 commits into
NousResearch:mainfrom
shannonsands:shannonsands/ns-591-mobile-chat-reconnect
Closed

fix(dashboard): recover mobile chat reconnect#61314
shannonsands wants to merge 2 commits into
NousResearch:mainfrom
shannonsands:shannonsands/ns-591-mobile-chat-reconnect

Conversation

@shannonsands

Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes Android/mobile dashboard Chat failures tracked in NS-591.

Root cause: the embedded dashboard chat relies on an xterm.js PTY WebSocket and browser timers. On Android, tab/background resume can leave the page showing a stale code 1006 reconnect state while the retry timer is throttled or the socket is gone. The terminal also stayed focusable, so users could type into what looked like a live chat even though input was being dropped. A follow-up report showed Google Keyboard suggestions could emit replacement-like IME input that xterm forwarded as normal append text, duplicating the current prompt line.

This PR adds explicit PTY connection state, active page-resume recovery, a main-chat reconnect affordance, and mobile input normalization for replacement/suggestion events. It keeps the existing /api/pty protocol and server-side attach/resume behavior intact.

Related Issue

Fixes https://linear.app/nousresearch/issue/NS-591/mobile-chat-can-get-stuck-reconnecting-after-android-tab-switch

Related PR checked for overlap: #60829.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • web/src/pages/ChatPage.tsx: track PTY state explicitly, recover on visibilitychange / pageshow / focus / online, and show a main terminal Reconnect now action for stuck reconnects.
  • web/src/pages/ChatPage.tsx: block disconnected terminal input with a one-time hint instead of silently dropping typed text.
  • web/src/pages/ChatPage.tsx: add mobile IME/replacement handling for xterm input so Gboard suggestions replace the current prompt line instead of appending the full line again.
  • web/src/components/ChatSidebar.tsx: relabel the sidebar reconnect button as reconnect tools feed to make clear it only reconnects the sidecar/events feed, not the main PTY.
  • web/src/lib/pty-reconnect.ts and web/src/lib/pty-mobile-input.ts: add tested pure helpers for reconnect decisions and mobile input normalization.

How to Test

  1. Run focused web unit tests:
    npm --workspace web test -- src/lib/pty-mobile-input.test.ts src/lib/pty-reconnect.test.ts src/lib/api.test.ts
  2. Build the dashboard bundle:
    npm --workspace web run build
  3. Run the focused backend PTY reconnect tests:
    .venv/bin/python -m pytest tests/hermes_cli/test_web_server_pty_reconnect.py -q
  4. Optional manual smoke: serve the dashboard on LAN, open it on Android Chrome, background/foreground the tab, verify chat recovers or shows Reconnect now, and verify Gboard suggestions do not duplicate the prompt line.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS local dashboard, Android Chrome LAN smoke by reporter/user

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

Validation run locally:

npm --workspace web test -- src/lib/pty-mobile-input.test.ts src/lib/pty-reconnect.test.ts src/lib/api.test.ts
Test Files  3 passed (3)
Tests       16 passed (16)

npm --workspace web run build
✓ built

.venv/bin/python -m pytest tests/hermes_cli/test_web_server_pty_reconnect.py -q
4 passed

git diff --check
clean

@shannonsands
shannonsands marked this pull request as ready for review July 9, 2026 05:59
Two review fixes on the mobile input normalization path:

- updatePtyInputLine appended the printable payload of escape sequences
  (the '[D' of a left-arrow) to the tracked line, and after any cursor
  movement the flat tracker no longer matched the visual line — the
  DELETE-repeat replacement could then be computed against a stale
  snapshot. Any chunk containing ESC now resets the tracker, disarming
  replacement normalization until a cleanly-tracked line starts.
- Move the SGR mouse-report filter ahead of the blocked-input check so
  scrolling a disconnected terminal doesn't print the reconnect notice.
@alt-glitch alt-glitch added type/bug Something isn't working comp/dashboard Web dashboard / control panel UI (dashboard/, landing) P3 Low — cosmetic, nice to have labels Jul 9, 2026
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Merged via #61374 — your two commits were cherry-picked with authorship preserved (rebase merge on 6f42bf344... history), plus a follow-up commit from us folding in review findings: an async-open reconnect-race guard (no double socket if a resume event fires before the socket is assigned), a wedged-WS_CONNECTING force-close so a half-open mobile socket after a radio handoff recovers via onclose→reconnect (the NS-591 case), a >=2-char guard so the duplicate-final-word heuristic doesn't eat legitimate single-letter reduplication, and the 350ms/1000ms magic numbers extracted to named consts. Verified: web tests 24/24, typecheck clean, backend PTY reconnect 4/4, /api/pty protocol untouched. Thanks for the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/dashboard Web dashboard / control panel UI (dashboard/, landing) P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants