feat: enable full AI automation and safe startup updates

This commit is contained in:
chenmingxuan committed 2026-09-22 23:50:03 +08:00
1 parent 2ddec53954
commit 7b1a0755e2
62 files changed
+3123 -240

No files matched your search

+54
View File
@@ -239,3 +239,57 @@ async def test_mid_stream_failure_records_stream_reset_payload(monkeypatch):
assert payload["reason"] == "mid_stream_failure"
assert "stream_exec_id" in payload
assert "lower API priority" in payload["message"]
@pytest.mark.asyncio
async def test_configured_retry_budget_is_shared_by_identical_fallback(monkeypatch):
from unittest.mock import AsyncMock
from artemis.llm.reliability import retry_policy_for
from artemis.llm.router import ModelEndpoint
monkeypatch.setattr(llm_service, "retry_policy_for", retry_policy_for)
monkeypatch.setattr(llm_service.settings, "OPENAI_MAX_RETRIES", 5)
monkeypatch.setattr(llm_service.settings, "OPENAI_RETRY_INTERVAL_SECONDS", 10)
monkeypatch.setattr(llm_service, "_wait_for_resume", AsyncMock(return_value=False))
sleep = AsyncMock()
monkeypatch.setattr(llm_service.asyncio, "sleep", sleep)
class Fails:
def __init__(self):
self.calls = 0
async def ainvoke(self, *args, **kwargs):
self.calls += 1
if self.calls % 2:
raise ConnectionError("connection reset")
raise TimeoutError("timeout")
main, fallback = Fails(), Fails()
endpoint = ModelEndpoint(model_name="test", api_base="https://example.test/v1", max_retries=5)
primary = RobustChatModelWrapper(main, endpoint=endpoint)
secondary = RobustChatModelWrapper(fallback, endpoint=endpoint.model_copy())
with pytest.raises(LLMExhaustedError):
await with_fallback(lambda: primary.ainvoke([]), lambda: secondary.ainvoke([]))
assert main.calls == 6
assert fallback.calls == 0
assert [call.args[0] for call in sleep.call_args_list] == [10] * 5
assert llm_service._FAILED_ENDPOINTS.get() is None
@pytest.mark.asyncio
async def test_request_deadline_cancels_attempt_and_respects_zero_retries(monkeypatch):
import asyncio
from unittest.mock import AsyncMock
monkeypatch.setattr(llm_service, "_wait_for_resume", AsyncMock(return_value=False))
cancelled = asyncio.Event()
async def pending():
try:
await asyncio.Event().wait()
finally:
cancelled.set()
with pytest.raises(LLMExhaustedError):
await llm_service._run_with_recovery(pending, request_timeout=0.005, max_retries=0)
assert cancelled.is_set()