chore: auto-commit from dashboard

This commit is contained in:
2026-08-22 08:40:56 +00:00
parent 4d2dbfb8a7
commit fe500a7227
35 changed files with 1372 additions and 144 deletions

View File

@@ -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