Skip to content

fix(cli): recover classic CLI output after resize#20444

Merged
teknium1 merged 1 commit into
NousResearch:mainfrom
helix4u:fix-classic-cli-resize-replay
May 6, 2026
Merged

fix(cli): recover classic CLI output after resize#20444
teknium1 merged 1 commit into
NousResearch:mainfrom
helix4u:fix-classic-cli-resize-replay

Conversation

@helix4u
Copy link
Copy Markdown
Contributor

@helix4u helix4u commented May 5, 2026

What does this PR do?

Fixes classic CLI redraw behavior after terminal resize. The prompt_toolkit footer/status chrome was being stamped into normal terminal scrollback during resize storms, and Ctrl+L or /redraw could leave the screen blank because previous output was not rebuildable.

This change keeps a bounded Hermes-owned output history for the classic CLI, debounces resize recovery, suppresses status/footer invalidates while resize recovery is pending, and rebuilds scrollback from that history after the terminal size settles. The resumed-history panel is stored as a structured renderable history entry so it is re-rendered at the current terminal width instead of replayed as stale terminal bytes.

Related Issue

Related to #19280.

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

  • cli.py: add bounded replay history for classic CLI output, including structured renderable entries for resize-aware resume panels.
  • cli.py: debounce resize recovery and suppress footer/status invalidates while resize recovery is pending.
  • cli.py: rebuild terminal scrollback from Hermes-owned history after resize, then repaint the live prompt/footer once at the settled size.
  • hermes_cli/config.py: add display.persistent_output and display.persistent_output_max_lines defaults for the replay buffer.
  • tests/cli/test_cli_force_redraw.py: cover redraw ordering, resize debounce behavior, and invalidate suppression during resize recovery.
  • tests/cli/test_cprint_bg_thread.py: cover output-history recording, replay, suppression, and structured render entries.
  • tests/cli/test_resume_display.py: cover storing the resumed-history panel as a resize-aware replay entry.

How to Test

  1. Start the classic CLI with a resumed session that displays previous conversation history.
  2. Resize the terminal narrower and wider, including while the status timer is updating.
  3. Confirm the footer/status area is replaced rather than duplicated, and the resumed-history panel is rebuilt at the current width instead of wrapping stale borders.
  4. Run the targeted tests listed below.

Targeted tests run locally:

  • HERMES_TEST_WORKERS=1 scripts/run_tests.sh tests/cli/test_resume_display.py tests/cli/test_cli_force_redraw.py tests/cli/test_cprint_bg_thread.py tests/cli/test_cli_init.py tests/cli/test_cli_status_bar.py -q → 115 passed
  • HERMES_TEST_WORKERS=1 scripts/run_tests.sh tests/hermes_cli/test_config_drift.py -q → 1 passed

Full suite run after opening draft PR:

  • scripts/run_tests.sh → failed: 49 failed, 19874 passed, 51 skipped, 230 warnings in 614.31s
  • Failures were outside the modified CLI resize/resume tests and covered existing gateway/provider/browser/delegation/update/TUI areas, including tests/gateway/test_approve_deny_commands.py, tests/cron/test_cron_script.py, tests/agent/test_auxiliary_client.py, tests/agent/test_bedrock_1m_context.py, tests/gateway/test_dingtalk.py, tests/hermes_cli/test_update_gateway_restart.py, tests/tools/test_browser_chromium_check.py, tests/tools/test_delegate.py, and tests/tui_gateway/test_goal_command.py.

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: Windows Terminal / Ubuntu under WSL

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

Manual reproduction involved Windows Terminal resizing of the classic CLI with a resumed session and live status/footer updates. Targeted and full-suite test output is summarized above.

@helix4u helix4u marked this pull request as ready for review May 5, 2026 22:25
@alt-glitch alt-glitch added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have labels May 5, 2026
@teknium1 teknium1 merged commit 76074d9 into NousResearch:main May 6, 2026
5 of 6 checks passed
29206394 pushed a commit to 29206394/hermes-agent that referenced this pull request May 8, 2026
_resize_clear_ghosts (introduced in NousResearch#20444) replays _OUTPUT_HISTORY after
every SIGWINCH to recover conversation content lost by the screen clear.
This causes a jarring "re-streaming" effect — all recent output lines,
including streaming tokens and spinner frames, are reprinted in rapid
succession whenever the user maximizes/restores the terminal window
(Command+Enter on macOS).

Change _recover_after_resize to only clear the screen + reset the
renderer, without replaying output history.  prompt_toolkit's native
_on_resize handler redraws the input area and status bar cleanly.

Users who want to see conversation history restored after resize can
still press Ctrl+L (/redraw), which calls _force_full_redraw (that path
still includes _replay_output_history).

Fixes the symptom reported in NousResearch#19280 where resize recovery replays
entire conversation as if it were streaming from the beginning.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard 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