fix(cli): recover terminal state after interrupt to prevent raw control sequence freeze

When the agent is interrupted during processing, prompt_toolkit's
renderer and VT100 input parser can be left in an inconsistent state.
CSI 6n cursor position report responses leak as literal text
(^[[19;1R) and the terminal stops accepting keyboard input.

Fix: in process_loop's finally block, after an interrupted turn:
- flush_stdin() to drain stray escape bytes from the OS input buffer
- _force_full_redraw() to reset prompt_toolkit's renderer cache

Closes #33271
This commit is contained in:
zccyman 2026-05-29 03:18:17 +08:00 committed by Teknium
parent 2e1b48ed31
commit f3aaba7f85
2 changed files with 143 additions and 0 deletions

16
cli.py
View file

@ -14702,6 +14702,22 @@ class HermesCLI(CLIAgentSetupMixin, CLICommandsMixin):
app.invalidate() # Refresh status line
# Post-turn terminal recovery (#33271): after an
# interrupt the prompt_toolkit renderer may have
# drifted from the physical terminal state — CSI 6n
# cursor position reports can leak as literal text
# (^[[19;1R), and the VT100 input parser can stall in
# a partial-escape state, accepting no further
# keystrokes. Drain stray escape bytes from the OS
# input buffer and force a clean renderer redraw.
if self._last_turn_interrupted:
try:
from hermes_cli.curses_ui import flush_stdin
flush_stdin()
except Exception:
pass
self._force_full_redraw()
# Goal continuation: if a standing goal is active, ask
# the judge whether the turn satisfied it. If not, and
# there's no real user message already queued, push the