Spaces:
Running
Running
| """tests/unit/test_loop_errors.py β loop error handling (SC-015). | |
| If the LLM client fails, the loop must yield an ``ErrorEvent`` and finish | |
| gracefully β never raise through the async generator (which in the UI would be a | |
| silent hang). No real network is used: the client is replaced with a fake. | |
| """ | |
| import pytest | |
| from agent.events import AgentStartEvent, ErrorEvent | |
| from agent.loop import AgentLoop | |
| class _RaisingClient: | |
| async def chat(self, *args, **kwargs): | |
| raise RuntimeError("connection refused") | |
| class _RaisingMidStreamClient: | |
| async def chat(self, *args, **kwargs): | |
| async def _gen(): | |
| raise RuntimeError("stream died") | |
| yield # pragma: no cover - makes this an async generator | |
| return _gen() | |
| async def test_error_before_stream_becomes_error_event(): | |
| loop = AgentLoop() | |
| loop._client = _RaisingClient() # bypass lazy real client | |
| events = [ev async for ev in loop.run("hi", session=None, system_prompt="x")] | |
| assert isinstance(events[0], AgentStartEvent) | |
| assert isinstance(events[-1], ErrorEvent) | |
| assert "connection refused" in events[-1].message | |
| async def test_error_mid_stream_becomes_error_event(): | |
| loop = AgentLoop() | |
| loop._client = _RaisingMidStreamClient() | |
| events = [ev async for ev in loop.run("hi", session=None, system_prompt="x")] | |
| types = [e.type for e in events] | |
| assert types[0] == "agent_start" | |
| assert types[-1] == "error" | |
| assert "stream died" in events[-1].message | |