Skip to content

fix(tui): patch StdinParser to prevent garbled text from fragmented mouse sequences#19468

Closed
agutmanstein-scale wants to merge 1 commit intoanomalyco:devfrom
agutmanstein-scale:fix/sgr-mouse-esc-recovery
Closed

fix(tui): patch StdinParser to prevent garbled text from fragmented mouse sequences#19468
agutmanstein-scale wants to merge 1 commit intoanomalyco:devfrom
agutmanstein-scale:fix/sgr-mouse-esc-recovery

Conversation

@agutmanstein-scale
Copy link
Copy Markdown

@agutmanstein-scale agutmanstein-scale commented Mar 27, 2026

Issue for this PR

Closes #3199

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

When the event loop is busy (LLM streaming + 60fps rendering), the StdinParser's 25ms timeout can fire mid-mouse-sequence, causing individual bytes to leak as KEY events and appear as garbled text in the input box.

The parser has three timeout paths that could trigger this. This PR patches all three via patchedDependencies for @opentui/core@0.1.90:

  • esc_recovery timeout: was emitting [ as a KEY event. Changed to emitOpaqueResponse (dropped) + set justFlushedEscBracket flag so < still routes to mouse handling.
  • csi timeout: was dropping \x1b[ but losing context. Now also sets the recovery flag.
  • esc_less_mouse timeout: had no deferred mechanism — flushed mid-sequence and leaked remaining bytes. Now waits for more bytes instead of flushing, matching the existing csi_sgr_mouse_deferred pattern.

Also bumps DEFAULT_TIMEOUT_MS from 10 to 25ms (matches kitty/alacritty defaults).

How did you verify your code works?

  • packages/opencode/test/cli/tui/test-stdin-parser.mjs — unit test confirming the 3-chunk fragmentation case is fixed
  • packages/opencode/test/cli/tui/frag-pty.py — PTY wrapper that fragments every mouse event byte-by-byte with 12ms delays. Ran in a VS Code web terminal (code-server), scrolled and clicked — zero garbled text with the fix, consistent garbling without it
  • bun typecheck passes (13/13 packages)

Screenshots / recordings

Not a UI change — this is a stdin parser fix. Verified via the included test files.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Mar 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

…ouse sequences

When SGR mouse escape sequences arrive fragmented across multiple stdin
chunks (due to event loop pressure from LLM streaming + TUI rendering),
opentui's StdinParser timeout fires mid-sequence and leaks individual
bytes as KEY events, inserting garbled characters into the input box.

Three timeout paths in the parser could trigger this:

1. esc_recovery timeout: emitted '[' as a KEY event via emitKeyOrResponse.
   Fixed to use emitOpaqueResponse (dropped) and set justFlushedEscBracket
   flag so subsequent '<' routes to mouse handling.

2. CSI timeout: dropped '\x1b[' correctly but lost recovery context.
   Fixed to set justFlushedEscBracket so '<' arriving in ground state
   routes to esc_less_mouse.

3. esc_less_mouse timeout: had no deferred mechanism — flushed accumulated
   bytes and returned to ground, causing remaining bytes to leak as KEY
   events. Fixed to clear forceFlush and wait for more bytes, matching
   the csi_sgr_mouse_deferred pattern.

Also increases DEFAULT_TIMEOUT_MS from 10 to 25ms (matches kitty/alacritty
defaults) for defense-in-depth.

Includes test-stdin-parser.mjs (parser unit test) and frag-pty.py (PTY
reproducer with 12ms byte-by-byte delay). Verified end-to-end: frag-pty.py
no longer produces garbled text.

Fixes anomalyco#3199

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Mar 28, 2026
@github-actions github-actions Bot closed this Mar 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mouse Generates Garbled Text Input & Blocks User Input

1 participant