fix(runtime): release 2.7.1 with consistent ADB and failure diagnostics

This commit is contained in:
chenmingxuan committed 2026-11-05 11:40:49 +08:00
1 parent b2316ca249
commit 8bf59897bb
24 files changed
+792 -45

No files matched your search

+50
View File
@@ -1,6 +1,7 @@
"""Tests for the LLM gateway: complete(), classified recovery, and fallback."""
from types import SimpleNamespace
from unittest.mock import AsyncMock
from langchain_core.messages import AIMessage, AIMessageChunk, HumanMessage, SystemMessage
import pytest
@@ -16,6 +17,55 @@ from artemis.services.llm import (
)
@pytest.mark.asyncio
@pytest.mark.parametrize(
"invalid",
[
None,
{"raw": AIMessage(content=""), "parsed": None, "parsing_error": None},
{
"raw": AIMessage(content=""),
"parsed": None,
"parsing_error": ValueError("Invalid schema"),
},
],
)
async def test_missing_structured_output_retries_inside_existing_budget(invalid):
expected = {"found": True, "output": "com.example.app", "reason": "Matched"}
base = SimpleNamespace(
ainvoke=AsyncMock(
side_effect=[
invalid,
{"raw": AIMessage(content=""), "parsed": expected, "parsing_error": None},
]
)
)
model = RobustChatModelWrapper(base, structured_mode="parsed")
assert await model.ainvoke([]) == expected
assert base.ainvoke.await_count == 2
@pytest.mark.asyncio
async def test_empty_structured_output_exhausts_then_uses_fallback():
primary = SimpleNamespace(
ainvoke=AsyncMock(return_value={"raw": AIMessage(content=""), "parsed": None})
)
expected = {"found": False, "output": None, "reason": "No match"}
secondary = SimpleNamespace(
ainvoke=AsyncMock(return_value={"raw": AIMessage(content=""), "parsed": expected})
)
main = RobustChatModelWrapper(
primary, endpoint=ModelEndpoint(model_name="primary"), structured_mode="parsed"
)
fallback = RobustChatModelWrapper(
secondary, endpoint=ModelEndpoint(model_name="fallback"), structured_mode="parsed"
)
result = await with_fallback(lambda: main.ainvoke([]), lambda: fallback.ainvoke([]))
assert result == expected
assert primary.ainvoke.await_count == 2
assert secondary.ainvoke.await_count == 1
@pytest.fixture(autouse=True)
def _isolate_gateway_state(monkeypatch, tmp_path):
llm_service._ENDPOINT_BREAKER._states.clear()