Files
nanobot/tests/test_long_context_recovery.py
nanobot 59b4abaa14
Build Nanobot OAuth / build (pull_request) Successful in 7m4s
Build Nanobot OAuth / cleanup (pull_request) Has been skipped
Build Nanobot OAuth / build (push) Successful in 2m48s
Build Nanobot OAuth / cleanup (push) Successful in 1s
chore: bump model defaults to Opus 4.7, Sonnet 4.6
- Default model: anthropic/claude-opus-4-5 → anthropic/claude-opus-4-7
- Quota switcher: claude-opus-4-6 → claude-opus-4-7
- Update all provider defaults and test fixtures
- Update comments/docstrings referencing old model names
- Claude Opus 4.7 released 2026-04-16, same pricing as 4.6
2026-04-17 02:53:08 +02:00

79 lines
2.6 KiB
Python

"""Test auto-consolidation on long context 429 errors."""
import pytest
from unittest.mock import AsyncMock, MagicMock
from nanobot.providers.base import LongContextError, LLMResponse
def test_long_context_error_is_exception():
"""LongContextError should be a distinct exception class."""
err = LongContextError("too long")
assert isinstance(err, Exception)
assert str(err) == "too long"
@pytest.mark.asyncio
async def test_provider_raises_long_context_error_on_long_context_429():
"""Provider should raise LongContextError immediately for long-context 429s."""
from nanobot.providers.anthropic_oauth import AnthropicOAuthProvider
provider = AnthropicOAuthProvider(
oauth_token="sk-ant-oat01-test-token",
default_model="claude-sonnet-4-6",
)
mock_response = MagicMock()
mock_response.status_code = 429
mock_response.text = '{"type":"error","error":{"type":"rate_limit_error","message":"Extra usage is required for long context requests."}}'
mock_response.headers = {}
mock_client = AsyncMock()
mock_client.post.return_value = mock_response
provider._client = mock_client
with pytest.raises(LongContextError, match="Context too long"):
await provider._make_request(
messages=[{"role": "user", "content": "hello"}],
)
# Should NOT retry — only one call
assert mock_client.post.call_count == 1
@pytest.mark.asyncio
async def test_provider_retries_normal_429():
"""Provider should still retry normal 429s (not long-context)."""
from nanobot.providers.anthropic_oauth import AnthropicOAuthProvider
provider = AnthropicOAuthProvider(
oauth_token="sk-ant-oat01-test-token",
default_model="claude-sonnet-4-6",
)
rate_limit_response = MagicMock()
rate_limit_response.status_code = 429
rate_limit_response.text = '{"type":"error","error":{"type":"rate_limit_error","message":"Rate limit exceeded"}}'
rate_limit_response.headers = {}
success_response = MagicMock()
success_response.status_code = 200
success_response.headers = {}
success_response.json.return_value = {
"content": [{"type": "text", "text": "ok"}],
"stop_reason": "end_turn",
"usage": {"input_tokens": 1, "output_tokens": 1},
}
mock_client = AsyncMock()
mock_client.post.side_effect = [rate_limit_response, success_response]
provider._client = mock_client
result = await provider._make_request(
messages=[{"role": "user", "content": "hello"}],
)
# Should have retried and succeeded
assert mock_client.post.call_count == 2
assert result["stop_reason"] == "end_turn"