83 lines
2.5 KiB
Python
83 lines
2.5 KiB
Python
|
|
import importlib
|
||
|
|
import json
|
||
|
|
from types import SimpleNamespace
|
||
|
|
from unittest.mock import AsyncMock, MagicMock
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
|
||
|
|
moa = importlib.import_module("tools.mixture_of_agents_tool")
|
||
|
|
|
||
|
|
|
||
|
|
def test_moa_defaults_track_current_openrouter_frontier_models():
|
||
|
|
assert moa.REFERENCE_MODELS == [
|
||
|
|
"anthropic/claude-opus-4.6",
|
||
|
|
"google/gemini-3-pro-preview",
|
||
|
|
"openai/gpt-5.4-pro",
|
||
|
|
"deepseek/deepseek-v3.2",
|
||
|
|
]
|
||
|
|
assert moa.AGGREGATOR_MODEL == "anthropic/claude-opus-4.6"
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_reference_model_retry_warnings_avoid_exc_info_until_terminal_failure(monkeypatch):
|
||
|
|
fake_client = SimpleNamespace(
|
||
|
|
chat=SimpleNamespace(
|
||
|
|
completions=SimpleNamespace(
|
||
|
|
create=AsyncMock(side_effect=RuntimeError("rate limited"))
|
||
|
|
)
|
||
|
|
)
|
||
|
|
)
|
||
|
|
warn = MagicMock()
|
||
|
|
err = MagicMock()
|
||
|
|
|
||
|
|
monkeypatch.setattr(moa, "_get_openrouter_client", lambda: fake_client)
|
||
|
|
monkeypatch.setattr(moa.logger, "warning", warn)
|
||
|
|
monkeypatch.setattr(moa.logger, "error", err)
|
||
|
|
|
||
|
|
model, message, success = await moa._run_reference_model_safe(
|
||
|
|
"openai/gpt-5.4-pro", "hello", max_retries=2
|
||
|
|
)
|
||
|
|
|
||
|
|
assert model == "openai/gpt-5.4-pro"
|
||
|
|
assert success is False
|
||
|
|
assert "failed after 2 attempts" in message
|
||
|
|
assert warn.call_count == 2
|
||
|
|
assert all(call.kwargs.get("exc_info") is None for call in warn.call_args_list)
|
||
|
|
err.assert_called_once()
|
||
|
|
assert err.call_args.kwargs.get("exc_info") is True
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.asyncio
|
||
|
|
async def test_moa_top_level_error_logs_single_traceback_on_aggregator_failure(monkeypatch):
|
||
|
|
monkeypatch.setenv("OPENROUTER_API_KEY", "test-key")
|
||
|
|
monkeypatch.setattr(
|
||
|
|
moa,
|
||
|
|
"_run_reference_model_safe",
|
||
|
|
AsyncMock(return_value=("anthropic/claude-opus-4.6", "ok", True)),
|
||
|
|
)
|
||
|
|
monkeypatch.setattr(
|
||
|
|
moa,
|
||
|
|
"_run_aggregator_model",
|
||
|
|
AsyncMock(side_effect=RuntimeError("aggregator boom")),
|
||
|
|
)
|
||
|
|
monkeypatch.setattr(
|
||
|
|
moa,
|
||
|
|
"_debug",
|
||
|
|
SimpleNamespace(log_call=MagicMock(), save=MagicMock(), active=False),
|
||
|
|
)
|
||
|
|
|
||
|
|
err = MagicMock()
|
||
|
|
monkeypatch.setattr(moa.logger, "error", err)
|
||
|
|
|
||
|
|
result = json.loads(
|
||
|
|
await moa.mixture_of_agents_tool(
|
||
|
|
"solve this",
|
||
|
|
reference_models=["anthropic/claude-opus-4.6"],
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
assert result["success"] is False
|
||
|
|
assert "Error in MoA processing" in result["error"]
|
||
|
|
err.assert_called_once()
|
||
|
|
assert err.call_args.kwargs.get("exc_info") is True
|