test(cli): cover retry-wait interactive routing

Keep provider retry wait messages on the interactive progress path so they do not fall through as assistant responses.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Xubin Ren
2026-05-03 22:59:08 +08:00
committed by Xubin Ren
co-authored by Cursor
parent c15d816d9c
commit 66682eb46f
2 changed files with 59 additions and 13 deletions
+28 -13
View File
@@ -216,6 +216,29 @@ async def _print_interactive_progress_line(text: str, thinking: ThinkingSpinner
await _print_interactive_line(text) await _print_interactive_line(text)
async def _maybe_print_interactive_progress(
msg: Any,
thinking: ThinkingSpinner | None,
channels_config: Any,
) -> bool:
metadata = msg.metadata or {}
if metadata.get("_retry_wait"):
await _print_interactive_progress_line(msg.content, thinking)
return True
if not metadata.get("_progress"):
return False
is_tool_hint = metadata.get("_tool_hint", False)
if channels_config and is_tool_hint and not channels_config.send_tool_hints:
return True
if channels_config and not is_tool_hint and not channels_config.send_progress:
return True
await _print_interactive_progress_line(msg.content, thinking)
return True
def _is_exit_command(command: str) -> bool: def _is_exit_command(command: str) -> bool:
"""Return True when input should end interactive chat.""" """Return True when input should end interactive chat."""
return command.lower() in EXIT_COMMANDS return command.lower() in EXIT_COMMANDS
@@ -1127,19 +1150,11 @@ def agent(
turn_done.set() turn_done.set()
continue continue
if msg.metadata.get("_retry_wait"): if await _maybe_print_interactive_progress(
await _print_interactive_progress_line(msg.content, _thinking) msg,
continue _thinking,
agent_loop.channels_config,
if msg.metadata.get("_progress"): ):
is_tool_hint = msg.metadata.get("_tool_hint", False)
ch = agent_loop.channels_config
if ch and is_tool_hint and not ch.send_tool_hints:
pass
elif ch and not is_tool_hint and not ch.send_progress:
pass
else:
await _print_interactive_progress_line(msg.content, _thinking)
continue continue
if not turn_done.is_set(): if not turn_done.is_set():
+31
View File
@@ -0,0 +1,31 @@
from types import SimpleNamespace
from unittest.mock import patch
import pytest
from nanobot.cli import commands
@pytest.mark.asyncio
async def test_interactive_retry_wait_is_rendered_as_progress_even_when_progress_disabled():
"""Provider retry waits should not fall through as assistant responses."""
calls: list[tuple[str, object | None]] = []
thinking = None
channels_config = SimpleNamespace(send_progress=False, send_tool_hints=False)
msg = SimpleNamespace(
content="Model request failed, retry in 2s (attempt 1).",
metadata={"_retry_wait": True},
)
async def fake_print(text: str, active_thinking: object | None) -> None:
calls.append((text, active_thinking))
with patch("nanobot.cli.commands._print_interactive_progress_line", side_effect=fake_print):
handled = await commands._maybe_print_interactive_progress(
msg,
thinking,
channels_config,
)
assert handled is True
assert calls == [("Model request failed, retry in 2s (attempt 1).", thinking)]