chore: auto-commit from dashboard
This commit is contained in:
@@ -217,6 +217,48 @@ class TestRegularMessage:
|
||||
assert "Error: API timeout" in response
|
||||
assert is_cmd is False
|
||||
|
||||
@patch("src.router._local_fallback_reply")
|
||||
@patch("src.router._get_channel_config")
|
||||
@patch("src.router._get_config")
|
||||
@patch("src.router.send_message")
|
||||
def test_rate_limit_falls_back_to_local_llm(
|
||||
self, mock_send, mock_get_config, mock_chan_cfg, mock_fallback,
|
||||
):
|
||||
mock_send.side_effect = RuntimeError(
|
||||
"Claude CLI error (exit 1): You've hit your session limit · resets 10:50am (UTC)"
|
||||
)
|
||||
mock_chan_cfg.return_value = None
|
||||
mock_cfg = MagicMock()
|
||||
mock_cfg.get.return_value = "sonnet"
|
||||
mock_get_config.return_value = mock_cfg
|
||||
mock_fallback.return_value = "⚠️ fallback reply"
|
||||
|
||||
response, is_cmd = route_message("ch-1", "user-1", "hello")
|
||||
assert response == "⚠️ fallback reply"
|
||||
assert is_cmd is False
|
||||
mock_fallback.assert_called_once_with("hello")
|
||||
|
||||
@patch("src.router._local_fallback_reply")
|
||||
@patch("src.router._get_channel_config")
|
||||
@patch("src.router._get_config")
|
||||
@patch("src.router.send_message")
|
||||
def test_rate_limit_fallback_unavailable_surfaces_original_error(
|
||||
self, mock_send, mock_get_config, mock_chan_cfg, mock_fallback,
|
||||
):
|
||||
mock_send.side_effect = RuntimeError(
|
||||
"Claude CLI error (exit 1): You've hit your session limit · resets 10:50am (UTC)"
|
||||
)
|
||||
mock_chan_cfg.return_value = None
|
||||
mock_cfg = MagicMock()
|
||||
mock_cfg.get.return_value = "sonnet"
|
||||
mock_get_config.return_value = mock_cfg
|
||||
mock_fallback.return_value = None # local fallback itself unreachable
|
||||
|
||||
response, is_cmd = route_message("ch-1", "user-1", "hello")
|
||||
assert "Error:" in response
|
||||
assert "hit your session limit" in response
|
||||
assert is_cmd is False
|
||||
|
||||
@patch("src.router._get_channel_config")
|
||||
@patch("src.router._get_config")
|
||||
@patch("src.router.send_message")
|
||||
@@ -488,3 +530,65 @@ class TestVoiceLangMarker:
|
||||
mock_clear.assert_called_once_with("ch-1")
|
||||
for call in mock_clear.call_args_list:
|
||||
assert not call.args[0].startswith("voice:")
|
||||
|
||||
|
||||
# --- Rate-limit detection + local fallback ---
|
||||
|
||||
class TestRateLimitFallback:
|
||||
def test_is_rate_limit_error_session_limit(self):
|
||||
from src.router import _is_rate_limit_error
|
||||
|
||||
err = RuntimeError(
|
||||
"Claude CLI error (exit 1): You've hit your session limit · resets 10:50am (UTC)"
|
||||
)
|
||||
assert _is_rate_limit_error(err) is True
|
||||
|
||||
def test_is_rate_limit_error_usage_limit_variant(self):
|
||||
from src.router import _is_rate_limit_error
|
||||
|
||||
assert _is_rate_limit_error(RuntimeError("You've hit your usage limit for today")) is True
|
||||
|
||||
def test_is_rate_limit_error_false_for_other_errors(self):
|
||||
from src.router import _is_rate_limit_error
|
||||
|
||||
assert _is_rate_limit_error(RuntimeError("Claude CLI error (exit 1): network timeout")) is False
|
||||
|
||||
@patch("src.router._get_config")
|
||||
def test_local_fallback_disabled_returns_none(self, mock_get_config):
|
||||
from src.router import _local_fallback_reply
|
||||
|
||||
mock_cfg = MagicMock()
|
||||
mock_cfg.get.return_value = {"enabled": False, "url": "http://x"}
|
||||
mock_get_config.return_value = mock_cfg
|
||||
|
||||
assert _local_fallback_reply("hello") is None
|
||||
|
||||
@patch("src.router.requests.post")
|
||||
@patch("src.router._get_config")
|
||||
def test_local_fallback_success(self, mock_get_config, mock_post):
|
||||
from src.router import _local_fallback_reply
|
||||
|
||||
mock_cfg = MagicMock()
|
||||
mock_cfg.get.return_value = {"enabled": True, "url": "http://10.0.20.161:8091/v1/chat/completions"}
|
||||
mock_get_config.return_value = mock_cfg
|
||||
|
||||
mock_resp = MagicMock()
|
||||
mock_resp.json.return_value = {"choices": [{"message": {"content": "Capitala Franței este Paris."}}]}
|
||||
mock_post.return_value = mock_resp
|
||||
|
||||
reply = _local_fallback_reply("Care este capitala Franței?")
|
||||
assert reply is not None
|
||||
assert "Capitala Franței este Paris." in reply
|
||||
assert "Claude e la limită" in reply
|
||||
|
||||
@patch("src.router.requests.post")
|
||||
@patch("src.router._get_config")
|
||||
def test_local_fallback_network_failure_returns_none(self, mock_get_config, mock_post):
|
||||
from src.router import _local_fallback_reply
|
||||
|
||||
mock_cfg = MagicMock()
|
||||
mock_cfg.get.return_value = {"enabled": True, "url": "http://10.0.20.161:8091/v1/chat/completions"}
|
||||
mock_get_config.return_value = mock_cfg
|
||||
mock_post.side_effect = ConnectionError("unreachable")
|
||||
|
||||
assert _local_fallback_reply("hello") is None
|
||||
|
||||
Reference in New Issue
Block a user