fix(providers): surface clear arrearage warning on quota/billing errors (#3006)
This commit is contained in:
@@ -78,6 +78,31 @@ async def test_llm_error_not_appended_to_session_messages():
|
||||
assert assistant_msgs[-1]["content"] == _PERSISTED_MODEL_ERROR_PLACEHOLDER
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_llm_arrearage_error_surfaces_clear_message():
|
||||
"""Arrearage errors yield a clear user-facing message, not a raw dump (#3006)."""
|
||||
from nanobot.agent.runner import AgentRunSpec, AgentRunner, _ARREARAGE_ERROR_MESSAGE
|
||||
|
||||
provider = MagicMock(spec=LLMProvider)
|
||||
provider.chat_with_retry = AsyncMock(return_value=LLMResponse(
|
||||
content="HTTP 402 insufficient_quota", finish_reason="error", error_status_code=402,
|
||||
))
|
||||
tools = MagicMock()
|
||||
tools.get_definitions.return_value = []
|
||||
|
||||
runner = AgentRunner(provider)
|
||||
result = await runner.run(AgentRunSpec(
|
||||
initial_messages=[{"role": "user", "content": "hello"}],
|
||||
tools=tools,
|
||||
model="test-model",
|
||||
max_iterations=5,
|
||||
max_tool_result_chars=_MAX_TOOL_RESULT_CHARS,
|
||||
))
|
||||
|
||||
assert result.stop_reason == "error"
|
||||
assert result.final_content == _ARREARAGE_ERROR_MESSAGE
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_runner_tool_error_sets_final_content():
|
||||
from nanobot.agent.runner import AgentRunSpec, AgentRunner
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
from nanobot.providers.anthropic_provider import AnthropicProvider
|
||||
from nanobot.providers.base import LLMProvider, LLMResponse
|
||||
from nanobot.providers.openai_compat_provider import OpenAICompatProvider
|
||||
|
||||
|
||||
@@ -79,3 +82,14 @@ def test_anthropic_handle_error_marks_connection_kind() -> None:
|
||||
|
||||
assert response.finish_reason == "error"
|
||||
assert response.error_kind == "connection"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected, kwargs", [
|
||||
(True, {"error_status_code": 402}), # HTTP 402
|
||||
(True, {"error_type": "insufficient_quota"}), # billing token
|
||||
(True, {"content": "429 You exceeded your current quota"}), # text marker
|
||||
(False, {"error_status_code": 429, "error_type": "rate_limit_exceeded"}), # plain rate limit
|
||||
])
|
||||
def test_is_arrearage_response(expected: bool, kwargs: dict) -> None:
|
||||
response = LLMResponse(finish_reason="error", **{"content": "boom", **kwargs})
|
||||
assert LLMProvider.is_arrearage_response(response) is expected
|
||||
|
||||
Reference in New Issue
Block a user