diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index 1468d775d..243280ed1 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -235,22 +235,22 @@ def _print_cli_progress_line(text: str, thinking: ThinkingSpinner | None) -> Non console.print(f" [dim]↳ {text}[/dim]") -async def _print_interactive_progress_line(text: str, thinking: ThinkingSpinner | None) -> None: - """Print an interactive progress line, pausing the spinner if needed.""" +async def _print_interactive_progress_line(text: str, renderer: StreamRenderer | None) -> None: + """Print an interactive progress line, pausing the renderer's spinner if needed.""" if not text.strip(): return - with thinking.pause() if thinking else nullcontext(): + with renderer.pause() if renderer else nullcontext(): await _print_interactive_line(text) async def _maybe_print_interactive_progress( msg: Any, - thinking: ThinkingSpinner | None, + renderer: StreamRenderer | None, channels_config: Any, ) -> bool: metadata = msg.metadata or {} if metadata.get("_retry_wait"): - await _print_interactive_progress_line(msg.content, thinking) + await _print_interactive_progress_line(msg.content, renderer) return True if not metadata.get("_progress"): @@ -262,7 +262,7 @@ async def _maybe_print_interactive_progress( if channels_config and not is_tool_hint and not channels_config.send_progress: return True - await _print_interactive_progress_line(msg.content, thinking) + await _print_interactive_progress_line(msg.content, renderer) return True @@ -1204,7 +1204,7 @@ def agent( if await _maybe_print_interactive_progress( msg, - _thinking, + renderer, agent_loop.channels_config, ): continue diff --git a/nanobot/cli/stream.py b/nanobot/cli/stream.py index addf4fe7c..b0095f153 100644 --- a/nanobot/cli/stream.py +++ b/nanobot/cli/stream.py @@ -134,6 +134,13 @@ class StreamRenderer: """Stop spinner before user input to avoid prompt_toolkit conflicts.""" self._stop_spinner() + def pause(self): + """Context manager: pause spinner for external output. No-op once streaming has started.""" + from contextlib import nullcontext + if self._spinner: + return self._spinner.pause() + return nullcontext() + async def close(self) -> None: """Stop spinner/live without rendering a final streamed round.""" if self._live: