diff --git a/tests/agent/test_mcp_transient_retry.py b/tests/agent/test_mcp_transient_retry.py index 8a0246ac..a76b1f1a 100644 --- a/tests/agent/test_mcp_transient_retry.py +++ b/tests/agent/test_mcp_transient_retry.py @@ -16,6 +16,7 @@ from nanobot.agent.tools.mcp import ( _is_session_terminated, _is_transient, ) +from nanobot.agent.tools.registry import is_tool_error_result # --------------------------------------------------------------------------- # _is_transient helper @@ -134,6 +135,7 @@ async def test_tool_fails_after_retry_exhausted(): assert "failed after retry" in output assert "ClosedResourceError" in output + assert is_tool_error_result(wrapper.name, output) assert session.call_tool.call_count == 2 @@ -237,12 +239,10 @@ async def test_tool_retry_on_end_of_stream(): @pytest.mark.asyncio -async def test_tool_reconnects_when_transient_retry_reveals_terminated_session(): - """Tool should reconnect if a stale session reports termination after transient retry.""" +async def test_tool_reconnects_on_transient_failure(): + """Tool should reconnect when a stale session reports a transient stream failure.""" old_session = AsyncMock() - old_session.call_tool = AsyncMock( - side_effect=[_FakeClosedResourceError("closed"), _session_terminated_error()] - ) + old_session.call_tool = AsyncMock(side_effect=_FakeClosedResourceError("closed")) new_session = AsyncMock() new_session.call_tool = AsyncMock(return_value=_make_tool_result("fresh")) @@ -257,12 +257,13 @@ async def test_tool_reconnects_when_transient_retry_reveals_terminated_session() wrapper.set_reconnect_handler(reconnect) - with patch("nanobot.agent.tools.mcp.asyncio.sleep", new_callable=AsyncMock): + with patch("nanobot.agent.tools.mcp.asyncio.sleep", new_callable=AsyncMock) as mock_sleep: output = await wrapper.execute(foo="bar") assert output == "fresh" - assert old_session.call_tool.call_count == 2 + assert old_session.call_tool.call_count == 1 assert new_session.call_tool.call_count == 1 + mock_sleep.assert_not_called() # --------------------------------------------------------------------------- diff --git a/tests/tools/test_mcp_tool.py b/tests/tools/test_mcp_tool.py index 5b61c384..1a915f90 100644 --- a/tests/tools/test_mcp_tool.py +++ b/tests/tools/test_mcp_tool.py @@ -478,61 +478,6 @@ async def test_execute_handles_generic_exception() -> None: assert is_tool_error_result(wrapper.name, result) -@pytest.mark.asyncio -async def test_execute_reconnects_on_transient_failure() -> None: - class ClosedResourceError(Exception): - pass - - reconnects = 0 - - async def stale_call_tool(_name: str, arguments: dict) -> object: - raise ClosedResourceError("stream closed") - - async def fresh_call_tool(_name: str, arguments: dict) -> object: - return SimpleNamespace(content=[_FakeTextContent("ok")]) - - wrapper = _make_wrapper(SimpleNamespace(call_tool=stale_call_tool)) - - async def reconnect(_server_name: str, _tool_name: str, _stale_tool: object) -> object: - nonlocal reconnects - reconnects += 1 - return SimpleNamespace(_session=SimpleNamespace(call_tool=fresh_call_tool)) - - wrapper.set_reconnect_handler(reconnect) - - result = await wrapper.execute() - - assert result == "ok" - assert reconnects == 1 - - -@pytest.mark.asyncio -async def test_execute_marks_transient_retry_failure_as_tool_error( - monkeypatch: pytest.MonkeyPatch, -) -> None: - class ClosedResourceError(Exception): - pass - - calls = 0 - - async def call_tool(_name: str, arguments: dict) -> object: - nonlocal calls - calls += 1 - raise ClosedResourceError("closed") - - async def fast_sleep(_delay: float) -> None: - return None - - monkeypatch.setattr(mcp_mod.asyncio, "sleep", fast_sleep) - wrapper = _make_wrapper(SimpleNamespace(call_tool=call_tool)) - - result = await wrapper.execute() - - assert calls == 2 - assert result == "(MCP tool call failed after retry: ClosedResourceError)" - assert is_tool_error_result(wrapper.name, result) - - def _make_tool_def(name: str) -> SimpleNamespace: return SimpleNamespace( name=name,