Skip to content

fix(cli): throttle UI invalidate to prevent terminal blinking on SSH#284

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
ygd58:fix-terminal-blinking
Mar 3, 2026
Merged

fix(cli): throttle UI invalidate to prevent terminal blinking on SSH#284
teknium1 merged 1 commit into
NousResearch:mainfrom
ygd58:fix-terminal-blinking

Conversation

@ygd58

@ygd58 ygd58 commented Mar 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #282

Problem

When Hermes Agent runs on a remote server over SSH, the terminal input area blinks rapidly due to self._app.invalidate() being called every second in multiple polling loops (clarify, sudo, approval callbacks).

Fix

  • Added _invalidate(min_interval=0.25) method to HermesCLI that throttles UI repaints
  • Added _last_invalidate timestamp to track last repaint
  • Replaced all direct self._app.invalidate() calls with self._invalidate()
  • Result: UI repaints at most 4 times per second instead of continuously

Root Cause

Each polling loop used queue.get(timeout=1) + invalidate() on every tick. Over SSH with higher latency, this caused visible flickering/blinking of the input area.

@teknium1 teknium1 merged commit b0cce17 into NousResearch:main Mar 3, 2026
@teknium1

teknium1 commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Merged in b0cce17. Correct fix — targets the actual callback methods in cli.py. All 1106 tests pass. Thanks for the contribution!

angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…t terminal blinking on SSH

Authored by ygd58. Fixes NousResearch#282.
olympus-terminal pushed a commit to olympus-terminal/hermes-agent that referenced this pull request May 16, 2026
…t terminal blinking on SSH

Authored by ygd58. Fixes NousResearch#282.
kshitijk4poor added a commit to kshitijk4poor/hermes-agent that referenced this pull request Jun 7, 2026
…ery (NousResearch#41098)

The salvaged approval fix (sanidhyasin) makes the dangerous-command
approval panel paint past the _invalidate() throttle. But the two sibling
user-blocking modals regressed identically and from the same root cause:

- _clarify_callback (clarify tool prompt, 120s timeout)
- _sudo_password_callback (sudo password prompt, 45s timeout)

Both set their modal state on the agent/background thread and then relied
on a single throttled self._invalidate() to paint. The approval, clarify,
and sudo prompts all originally used direct self._app.invalidate() and
worked. PR NousResearch#284 (b603b6e) blanket-replaced those with the throttled
_invalidate(), making the modal paints droppable — but the bug stayed
masked because the spinner loop's idle branch called _invalidate(
min_interval=1.0) every second, repainting a dropped modal within ~1s.
Commit 5e92b67 ('stop idle CLI redraws') removed that idle repaint to
fix tmux/Ghostty viewport-restore flicker, which unmasked the bug: a
dropped modal paint now never recovers and the prompt times out unseen.

Re-adding the idle repaint would reintroduce the flicker 5e92b67 fixed,
so the correct fix is to make the modal-entry paints unconditional via the
established min_interval=0.0 bypass idiom. Applied to clarify + sudo to
match the approval fix: initial paint, response-received, in-wait
countdown (cadence 5s->1s for clarify), and timeout teardown.

Resize-recovery edge case: even min_interval=0.0 did not bypass the
_resize_recovery_pending early-return added by 76074d9 — so during a
(possibly held) drag-resize the modal could stay invisible until it timed
out. Add a keyword-only force=True to _invalidate that bypasses BOTH the
throttle AND the resize guard, and use it for the three modal *entry*
paints only. This is safe: a modal overlay is live prompt_toolkit chrome
(not scrollback output), so painting it slightly early during a resize is
harmless, and _recover_after_resize issues its own unconditional
app.invalidate() when the debounce settles. The resize guard still
suppresses ordinary repaints (status bar / footer chrome) as before.

Also removes a copy-paste-duplicated countdown-refresh block in
_clarify_callback (the same 5s gate appeared twice).

Adds regression tests: mirror dropped-paint tests for clarify and sudo;
an approval-during-resize test; and a direct _invalidate force-vs-gates
test. Each fails if its corresponding bypass is reverted. 16 tests pass;
full tests/cli suite green (899).
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…t terminal blinking on SSH

Authored by ygd58. Fixes NousResearch#282.
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.

Unintended terminal blinking in Hermes Agent CLI

2 participants