feat(webui): show the actual fallback model (#5017)
This commit is contained in:
@@ -285,6 +285,30 @@ class TestFallbackOnPrimaryError:
|
||||
assert primary.chat_calls[0]["model"] == "primary-model"
|
||||
assert fallback.chat_calls[0]["model"] == "fallback-a"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_reports_the_fallback_model_before_its_request(self) -> None:
|
||||
primary = _FakeProvider("primary", _error_response())
|
||||
fallback = _FakeProvider("fallback", _make_response("fallback ok"))
|
||||
fallback_models: list[str] = []
|
||||
|
||||
async def _observe(model: str) -> None:
|
||||
fallback_models.append(model)
|
||||
|
||||
fb = FallbackProvider(
|
||||
primary=primary,
|
||||
fallback_presets=[_fallback("fallback-a", provider="backup")],
|
||||
provider_factory=MagicMock(return_value=fallback),
|
||||
fallback_model_observer=_observe,
|
||||
)
|
||||
|
||||
result = await fb.chat_with_retry(
|
||||
messages=[{"role": "user", "content": "hi"}],
|
||||
model="primary-model",
|
||||
)
|
||||
|
||||
assert result.content == "fallback ok"
|
||||
assert fallback_models == ["fallback-a"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_logs_primary_error_before_fallback(self) -> None:
|
||||
primary = _FakeProvider("primary", _error_response("primary overloaded"))
|
||||
|
||||
@@ -4,8 +4,9 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from nanobot.agent.tools.context import RequestContext, request_context
|
||||
from nanobot.bus.events import InboundMessage
|
||||
from nanobot.bus.outbound_events import GoalStatusEvent
|
||||
from nanobot.bus.outbound_events import GoalStatusEvent, TurnModelUpdatedEvent
|
||||
from nanobot.session import webui_turns as wth
|
||||
|
||||
|
||||
@@ -69,3 +70,38 @@ async def test_publish_turn_run_status_non_websocket_noop_registry() -> None:
|
||||
await wth.publish_turn_run_status(bus, msg, "running")
|
||||
|
||||
assert wth._WEBSOCKET_TURN_WALL_STARTED_AT == {}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fallback_model_is_scoped_to_its_websocket_chat() -> None:
|
||||
bus = MagicMock()
|
||||
bus.publish_outbound = AsyncMock()
|
||||
observer = wth.build_webui_fallback_model_observer(bus)
|
||||
|
||||
with request_context(
|
||||
RequestContext(
|
||||
channel="websocket",
|
||||
chat_id="chat-model",
|
||||
metadata={"webui": True},
|
||||
)
|
||||
):
|
||||
await observer("deepseek/deepseek-chat")
|
||||
|
||||
outbound = bus.publish_outbound.await_args.args[0]
|
||||
assert outbound.channel == "websocket"
|
||||
assert outbound.chat_id == "chat-model"
|
||||
assert outbound.metadata == {"webui": True}
|
||||
assert isinstance(outbound.event, TurnModelUpdatedEvent)
|
||||
assert outbound.event.model == "deepseek/deepseek-chat"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fallback_model_ignores_non_websocket_requests() -> None:
|
||||
bus = MagicMock()
|
||||
bus.publish_outbound = AsyncMock()
|
||||
observer = wth.build_webui_fallback_model_observer(bus)
|
||||
|
||||
with request_context(RequestContext(channel="telegram", chat_id="chat-model")):
|
||||
await observer("fallback")
|
||||
|
||||
bus.publish_outbound.assert_not_awaited()
|
||||
|
||||
Reference in New Issue
Block a user