Skip to content

fix: route /bg spinner through TUI widget to prevent status bar collision - #3643

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-ea354159
Mar 29, 2026
Merged

fix: route /bg spinner through TUI widget to prevent status bar collision#3643
teknium1 merged 1 commit into
mainfrom
hermes/hermes-ea354159

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Salvage of #3493 by @kshitijk4poor. Cherry-picked cleanly onto current main.

Problem

When running /bg <prompt>, the background agent's KawaiiSpinner writes \r-based animation and stop() final messages directly through prompt_toolkit's StdoutProxy. StdoutProxy injects newlines around each flush, so spinner frames land on the status bar row — garbling both the spinner and the prompt.

Fix (2 files, +19/-5)

agent/display.py — Improved _is_patch_stdout_proxy() detection:

  • Old: hasattr(out, 'raw') and type(out).__name__ == 'StdoutProxy' — fragile heuristic that can break across prompt_toolkit versions
  • New: isinstance(self._out, StdoutProxy) with try/except ImportError guard

cli.py — Background agent spinner routing:

  • bg_agent._print_fn = lambda *_a, **_kw: None — silences all raw spinner output (both _animate() and stop() paths)
  • bg_agent.thinking_callback = _bg_thinking — routes thinking updates through TUI widget (_spinner_text) only when no foreground agent is active
  • finally block clears spinner text with same foreground guard

Tests

  • 146 spinner/background/display tests pass (2 skipped)

Closes #2718

…sion

Background agent's KawaiiSpinner wrote \r-based animation and stop()
messages through StdoutProxy, colliding with prompt_toolkit's status bar.

Two fixes:
- display.py: use isinstance(out, StdoutProxy) instead of fragile
  hasattr+name check for detecting prompt_toolkit's stdout wrapper
- cli.py: silence bg agent's raw spinner (_print_fn=no-op) and route
  thinking updates through the TUI widget only when no foreground
  agent is active; clear spinner text in finally block with same guard

Closes #2718

Co-authored-by: kshitijk4poor <kshitijk4poor@users.noreply.github.com>
@teknium1
teknium1 merged commit bea49e0 into main Mar 29, 2026
2 checks passed
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…sion (NousResearch#3643)

Background agent's KawaiiSpinner wrote \r-based animation and stop()
messages through StdoutProxy, colliding with prompt_toolkit's status bar.

Two fixes:
- display.py: use isinstance(out, StdoutProxy) instead of fragile
  hasattr+name check for detecting prompt_toolkit's stdout wrapper
- cli.py: silence bg agent's raw spinner (_print_fn=no-op) and route
  thinking updates through the TUI widget only when no foreground
  agent is active; clear spinner text in finally block with same guard

Closes NousResearch#2718

Co-authored-by: kshitijk4poor <kshitijk4poor@users.noreply.github.com>
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…sion (NousResearch#3643)

Background agent's KawaiiSpinner wrote \r-based animation and stop()
messages through StdoutProxy, colliding with prompt_toolkit's status bar.

Two fixes:
- display.py: use isinstance(out, StdoutProxy) instead of fragile
  hasattr+name check for detecting prompt_toolkit's stdout wrapper
- cli.py: silence bg agent's raw spinner (_print_fn=no-op) and route
  thinking updates through the TUI widget only when no foreground
  agent is active; clear spinner text in finally block with same guard

Closes NousResearch#2718

Co-authored-by: kshitijk4poor <kshitijk4poor@users.noreply.github.com>
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…sion (NousResearch#3643)

Background agent's KawaiiSpinner wrote \r-based animation and stop()
messages through StdoutProxy, colliding with prompt_toolkit's status bar.

Two fixes:
- display.py: use isinstance(out, StdoutProxy) instead of fragile
  hasattr+name check for detecting prompt_toolkit's stdout wrapper
- cli.py: silence bg agent's raw spinner (_print_fn=no-op) and route
  thinking updates through the TUI widget only when no foreground
  agent is active; clear spinner text in finally block with same guard

Closes NousResearch#2718

Co-authored-by: kshitijk4poor <kshitijk4poor@users.noreply.github.com>
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…sion (NousResearch#3643)

Background agent's KawaiiSpinner wrote \r-based animation and stop()
messages through StdoutProxy, colliding with prompt_toolkit's status bar.

Two fixes:
- display.py: use isinstance(out, StdoutProxy) instead of fragile
  hasattr+name check for detecting prompt_toolkit's stdout wrapper
- cli.py: silence bg agent's raw spinner (_print_fn=no-op) and route
  thinking updates through the TUI widget only when no foreground
  agent is active; clear spinner text in finally block with same guard

Closes NousResearch#2718

Co-authored-by: kshitijk4poor <kshitijk4poor@users.noreply.github.com>
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.

UI Bug: /bg command causes status bar to render on same row as thinking spinner

2 participants