Skip to content

fix(web/dashboard): skip xterm.js WebGL renderer on Safari to fix Unicode box-drawing glyphs#18788

Open
Sanjays2402 wants to merge 1 commit into
NousResearch:mainfrom
Sanjays2402:fix/issue-18773-safari-webgl-box-drawing
Open

fix(web/dashboard): skip xterm.js WebGL renderer on Safari to fix Unicode box-drawing glyphs#18788
Sanjays2402 wants to merge 1 commit into
NousResearch:mainfrom
Sanjays2402:fix/issue-18773-safari-webgl-box-drawing

Conversation

@Sanjays2402

Copy link
Copy Markdown
Contributor

Summary

Fixes #18773. In the dashboard Chat tab, Safari's WebGL renderer mangles Unicode box-drawing characters (╔╗║╚╝, ██╗, etc.) used by the HERMES AGENT banner and TUI borders — they fragment into blocks instead of forming proper shapes. Chrome and Firefox WebGL render the same glyphs correctly.

This is a known xterm.js + Safari WebKit interaction (also affects VS Code Server, JupyterLab, etc.).

Fix

web/src/pages/ChatPage.tsx: skip the WebglAddon on Safari and let xterm.js fall back to the default DOM renderer, which renders the box-drawing glyphs faithfully on Safari.

A short isSafariBrowser() helper detects macOS/iOS Safari without false positives on Chromium derivatives:

  • Requires the Safari/ UA token.
  • Excludes Chromium fingerprints (Chrome/, Chromium/, CriOS/) — Chromium-based browsers all advertise Safari/ in their UA for legacy compat.
  • Excludes other WebKit-wrapping shells we know don't hit the bug (FxiOS/, EdgiOS/, Android UAs).

Existing WebGL gate (terminalTierWidthPx(host) >= 768) is preserved, so wide layouts on Chrome/Firefox/Edge still get the crisp WebGL rendering. Only Safari at any width goes to the DOM renderer.

Why not the issue's proposed rendererType: 'dom'?

The proposed new Terminal({ rendererType: 'dom' }) option is from xterm.js v4 and was removed in v5+. The repo is on @xterm/xterm@^6.0.0, where renderer choice is controlled via addons (WebglAddon, CanvasAddon). Skipping the WebglAddon is the modern equivalent.

Verification

  • tsc -b: clean.
  • vite build: clean (1.65s).
  • Diff scope: web/src/pages/ChatPage.tsx only, +38/-1.

What I did NOT change

  • Chrome/Firefox/Edge WebGL path (still active for wide layouts).
  • Mobile/narrow layout fallback (< 768px → DOM renderer; unchanged).
  • The Safari path uses the default DOM renderer, not the canvas addon — adding @xterm/addon-canvas would be a bigger dependency change and the DOM renderer already renders box-drawing correctly on Safari per the issue and xterm.js docs.

cc @bb @W0921

Closes #18773

…-drawing glyphs

Safari's WebGL implementation mangles Unicode box-drawing characters
(╔╗║╚╝, ██╗ etc.) used by the HERMES AGENT banner and TUI borders in
the dashboard Chat tab — the texture-atlas path renders fragmented
blocks instead of forming proper shapes, while Chrome and Firefox WebGL
render the same glyphs correctly. This is a known xterm.js + Safari
WebKit interaction.

Add isSafariBrowser() that matches macOS/iOS Safari without false
positives on Chromium derivatives (which all advertise 'Safari/' in
their UA for legacy compat) by:
- Requiring the 'Safari/' token.
- Excluding Chromium fingerprints (Chrome/, Chromium/, CriOS/).
- Excluding other WebKit-wrapping shells we know don't hit the bug
  (FxiOS/, EdgiOS/, Android UAs).

Wire it into the WebGL gate so the chat tab falls back to the default
DOM renderer on Safari, which renders the box-drawing glyphs faithfully.
Chrome/Firefox/Edge on wide layouts still get the WebGL renderer.

Verified locally:
- tsc -b: clean.
- vite build: clean (1.65s).
- ChatPage.tsx diff: +38/-1, single file.

Fixes NousResearch#18773.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels May 2, 2026
@Sanjays2402

Copy link
Copy Markdown
Contributor Author

CI status note for maintainers — the failing test check on this PR is from a set of 15 pre-existing test failures on main, not regressions introduced here.

Verified by diffing the failing-test sets:

  • Latest main push run (25250051126): 16 failed
  • This PR's run: same 15 (subset)
  • Net new failures introduced by this PR: 0

The clusters on main:

Cluster Tests Likely cause
Systemd TimeoutStopSec test_*_unit_avoids_recursive_execstop_and_uses_extended_stop_timeout Code emits 210, test asserts 90 — drift
Gateway restart kill semantics test_update_* Recent change in expected .kill() call counts
update --yes flag test_update_yes_flag TTY prompt / stash restore behavior changed
Dockerfile pid1 test_dockerfile_* Dockerfile regenerated, dropped TUI ink references
Concurrent interrupt _Stub test fixture missing _tool_guardrails attr
dotenv vs os.environ test_os_environ_still_wins_over_dotenv Same class as #18757; happy to add to my fix PR if useful
ACP commands test_send_available_commands_update Command list ordering
Teams typing test_send_typing Mock not awaited
TUI pending_title test_session_create_drops_pending_title_on_valueerror ValueError no longer drops title

Happy to open targeted fix PRs for any of these clusters if it helps unblock the queue. Otherwise this PR is ready whenever main is green.

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/) 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.

[Bug] Dashboard --tui: xterm.js WebGL renderer garbles Unicode box-drawing characters in Safari

2 participants