Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e4317f6a73 |
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "ratatoskr"
|
name = "ratatoskr"
|
||||||
version = "0.18.3"
|
version = "0.18.4"
|
||||||
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
|
description = "Worldtree Conversation API debug TUI — multi-pane observability dashboard"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
@@ -241,7 +241,11 @@ class TurnLaunchUnavailable(SseConnectFailed):
|
|||||||
self.message = message
|
self.message = message
|
||||||
|
|
||||||
|
|
||||||
_EAGER_TURN_FAILURE_CODE = {409: "agent_not_available", 503: "turn_launch_unavailable"}
|
# Canonical error_codes (Worldtree #331 / v1.0.0b2): 409 -> agent_not_available,
|
||||||
|
# 503 -> not_ready (retryable; re-pinned from internal_error). Used only as a
|
||||||
|
# fallback default when the body omits error_code — the real code is surfaced
|
||||||
|
# verbatim from the {detail:{error_code,message}} envelope.
|
||||||
|
_EAGER_TURN_FAILURE_CODE = {409: "agent_not_available", 503: "not_ready"}
|
||||||
|
|
||||||
|
|
||||||
def _eager_failure_fields(body: bytes, status: int) -> tuple[str, str]:
|
def _eager_failure_fields(body: bytes, status: int) -> tuple[str, str]:
|
||||||
|
|||||||
@@ -479,6 +479,19 @@ class TestStreamTurn:
|
|||||||
_ = [e async for e in stream_turn(client, "s1", "hi")]
|
_ = [e async for e in stream_turn(client, "s1", "hi")]
|
||||||
assert exc.value.error_code == "agent_not_available"
|
assert exc.value.error_code == "agent_not_available"
|
||||||
|
|
||||||
|
@respx.mock
|
||||||
|
async def test_eager_503_non_json_body_defaults_not_ready(self) -> None:
|
||||||
|
"""b2: eager 503 with a non-JSON body -> TurnLaunchUnavailable with the
|
||||||
|
canonical default error_code `not_ready`."""
|
||||||
|
respx.post("https://w.example/sessions/s1/messages").mock(
|
||||||
|
return_value=httpx.Response(503, content=b"<html>nope</html>")
|
||||||
|
)
|
||||||
|
async with httpx.AsyncClient(base_url="https://w.example") as client:
|
||||||
|
with pytest.raises(TurnLaunchUnavailable) as exc:
|
||||||
|
_ = [e async for e in stream_turn(client, "s1", "hi")]
|
||||||
|
assert exc.value.error_code == "not_ready"
|
||||||
|
assert exc.value.retryable is True
|
||||||
|
|
||||||
@respx.mock
|
@respx.mock
|
||||||
async def test_no_text_aggregation(self) -> None:
|
async def test_no_text_aggregation(self) -> None:
|
||||||
"""no_text_aggregation: consumer yields each text event separately; no concat."""
|
"""no_text_aggregation: consumer yields each text event separately; no concat."""
|
||||||
|
|||||||
Reference in New Issue
Block a user