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:
committed by
Xubin Ren
co-authored by
Cursor
parent
c15d816d9c
commit
66682eb46f
+28
-13
@@ -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():
|
||||||
|
|||||||
@@ -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)]
|
||||||
Reference in New Issue
Block a user