nanobot/tests/agent/test_self_model_preset.py
chengyongru 0bc42e2ab2 refactor: restrict fallback_models to preset-only and clean up provider factory
- Restrict fallback_models to only reference preset names in model_presets.
- Add schema validation to reject unknown preset names in fallback_models.
- Remove build_provider_for_model() since bare model fallback is no longer supported.
- Simplify make_provider_factory() to only look up presets by name.
- Update onboard UI to remove "Add custom model" option from fallback chain.
- Update tests to use preset names instead of bare model strings in fallback chains.
- Fix test imports referencing deleted _make_provider function.
2026-05-08 20:24:24 +08:00

90 lines
2.9 KiB
Python

# tests/agent/test_self_model_preset.py
from pathlib import Path
from typing import Any
from unittest.mock import MagicMock
from nanobot.agent.loop import AgentLoop
from nanobot.config.schema import ModelPresetConfig, MyToolConfig, ToolsConfig
from nanobot.providers.base import GenerationSettings
def _make_loop(presets: dict | None = None) -> tuple[AgentLoop, Any]:
provider = MagicMock()
provider.get_default_model.return_value = "test-model"
provider.generation = GenerationSettings(temperature=0.1, max_tokens=8192)
def _factory(name: str):
preset = (presets or {}).get(name)
if preset:
new_provider = MagicMock()
new_provider.generation = GenerationSettings(
temperature=preset.temperature,
max_tokens=preset.max_tokens,
reasoning_effort=preset.reasoning_effort,
)
return new_provider
return provider
loop = AgentLoop(
bus=MagicMock(),
provider=provider,
workspace=Path("/tmp/test"),
model="test-model",
context_window_tokens=65536,
model_presets=presets or {},
provider_factory=_factory,
tools_config=ToolsConfig(my=MyToolConfig(allow_set=True)),
)
tool = loop.tools.get("my")
return loop, tool
async def test_set_model_preset_updates_all_fields() -> None:
presets = {
"gpt5": ModelPresetConfig(
model="gpt-5",
provider="openai",
max_tokens=16384,
context_window_tokens=128000,
temperature=0.2,
),
}
loop, tool = _make_loop(presets)
await tool.execute(action="set", key="model_preset", value="gpt5")
assert loop.model == "gpt-5"
assert loop.context_window_tokens == 128000
assert loop.provider.generation.temperature == 0.2
assert loop.provider.generation.max_tokens == 16384
assert loop._active_preset == "gpt5"
async def test_set_model_preset_unknown_returns_error() -> None:
loop, tool = _make_loop({})
result = await tool.execute(action="set", key="model_preset", value="nope")
assert "Error" in result or "not found" in result
async def test_check_model_preset_shows_current() -> None:
presets = {"gpt5": ModelPresetConfig(model="gpt-5", provider="openai")}
loop, tool = _make_loop(presets)
await tool.execute(action="set", key="model_preset", value="gpt5")
result = await tool.execute(action="check", key="model_preset")
assert "gpt5" in result
async def test_check_model_presets_shows_available() -> None:
presets = {
"gpt5": ModelPresetConfig(model="gpt-5", provider="openai"),
"ds": ModelPresetConfig(model="deepseek-chat", provider="deepseek"),
}
loop, tool = _make_loop(presets)
result = await tool.execute(action="check", key="model_presets")
assert "gpt5" in result
assert "ds" in result