opensquilla--opensquilla
315 行
11 KiB
Python
315 行
11 KiB
Python
"""Router tier presets: config adapter parity, upgrade fixtures, downgrade guard.
|
|
|
|
The golden fixture (``tests/test_provider/golden/router_tier_profiles.json``)
|
|
was captured from
|
|
``git show staging/provider-overhaul:src/opensquilla/gateway/config.py``
|
|
(the ``_router_tier_profile_defaults`` dict literals at f884d4c9). Every test
|
|
here pins that moving the preset data into packaged TOML changed nothing about
|
|
how existing configs load: the fixture battery shapes come from the upgrade
|
|
audit and must keep loading byte-identically.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import tomllib
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import tomli_w
|
|
|
|
from opensquilla.gateway.config import (
|
|
ROUTER_TIER_PROFILE_IDS,
|
|
GatewayConfig,
|
|
_default_tiers,
|
|
_router_tier_profile_defaults,
|
|
)
|
|
|
|
GOLDEN_PATH = (
|
|
Path(__file__).resolve().parents[1]
|
|
/ "test_provider"
|
|
/ "golden"
|
|
/ "router_tier_profiles.json"
|
|
)
|
|
LEGACY_NINE = frozenset(
|
|
{
|
|
"openrouter",
|
|
"dashscope",
|
|
"deepseek",
|
|
"gemini",
|
|
"volcengine",
|
|
"byteplus",
|
|
"openai",
|
|
"zhipu",
|
|
"moonshot",
|
|
}
|
|
)
|
|
UNKNOWN_PROFILE_ERROR = (
|
|
"unknown squilla_router.tier_profile 'groq'; expected one of "
|
|
"byteplus, dashscope, deepseek, gemini, moonshot, openai, openrouter, "
|
|
"volcengine, zhipu"
|
|
)
|
|
|
|
|
|
def _golden() -> dict[str, dict]:
|
|
return json.loads(GOLDEN_PATH.read_text(encoding="utf-8"))
|
|
|
|
|
|
# --- adapter parity ---------------------------------------------------------
|
|
|
|
|
|
def test_router_tier_profile_ids_are_exactly_the_legacy_nine() -> None:
|
|
assert ROUTER_TIER_PROFILE_IDS == LEGACY_NINE
|
|
|
|
|
|
@pytest.mark.parametrize("profile_id", sorted(LEGACY_NINE))
|
|
def test_profile_defaults_match_pre_registry_dict_literals(profile_id: str) -> None:
|
|
assert _router_tier_profile_defaults(profile_id) == _golden()[profile_id]
|
|
|
|
|
|
def test_default_tiers_match_pre_registry_openrouter_literal() -> None:
|
|
assert _default_tiers() == _golden()["openrouter"]
|
|
|
|
|
|
def test_profile_defaults_returns_mutable_copies() -> None:
|
|
first = _router_tier_profile_defaults("openai")
|
|
first["c0"]["model"] = "mutated"
|
|
assert _router_tier_profile_defaults("openai")["c0"]["model"] != "mutated"
|
|
|
|
|
|
def test_synthesized_preset_id_is_rejected_as_tier_profile() -> None:
|
|
# groq has a synthesized preset in the registry, but tier_profile
|
|
# acceptance stays pinned to the legacy nine (rc1 bricks on unknown ids).
|
|
with pytest.raises(ValueError) as excinfo:
|
|
_router_tier_profile_defaults("groq")
|
|
assert str(excinfo.value) == UNKNOWN_PROFILE_ERROR
|
|
|
|
|
|
# --- fixture battery (upgrade audit) ----------------------------------------
|
|
|
|
|
|
@pytest.mark.parametrize("profile_id", sorted(LEGACY_NINE))
|
|
def test_minimal_toml_per_profile_loads_identical_tiers(
|
|
tmp_path: Path, profile_id: str
|
|
) -> None:
|
|
"""(a) each legacy tier_profile in a minimal TOML -> today's effective tiers."""
|
|
path = tmp_path / "config.toml"
|
|
path.write_text(
|
|
f'[llm]\nprovider = "{profile_id}"\n\n'
|
|
f'[squilla_router]\ntier_profile = "{profile_id}"\n',
|
|
encoding="utf-8",
|
|
)
|
|
cfg = GatewayConfig.load_from_toml(path)
|
|
assert cfg.squilla_router.tier_profile == profile_id
|
|
assert cfg.squilla_router.tiers == _golden()[profile_id]
|
|
|
|
|
|
def test_mixed_tiers_without_profile_round_trip_untouched(tmp_path: Path) -> None:
|
|
"""(b) openrouter-mix shape: no tier_profile, explicit tiers stay verbatim."""
|
|
tiers = {
|
|
"c0": {
|
|
"provider": "openrouter",
|
|
"model": "vendor-a/fast-model",
|
|
"description": "custom fast route",
|
|
"supports_image": False,
|
|
"thinking_level": "low",
|
|
},
|
|
"c1": {
|
|
"provider": "openrouter",
|
|
"model": "vendor-b/balanced-model",
|
|
"description": "custom balanced route",
|
|
"supports_image": False,
|
|
"thinking_level": "medium",
|
|
},
|
|
"c2": {
|
|
"provider": "openrouter",
|
|
"model": "vendor-c/strong-model",
|
|
"description": "custom strong route",
|
|
"supports_image": False,
|
|
"thinking_level": "high",
|
|
},
|
|
"c3": {
|
|
"provider": "openrouter",
|
|
"model": "vendor-c/strong-model",
|
|
"description": "custom highest route",
|
|
"supports_image": False,
|
|
"thinking_level": "high",
|
|
},
|
|
"image_model": {
|
|
"provider": "openrouter",
|
|
"model": "vendor-d/vision-model",
|
|
"description": "custom image route",
|
|
"supports_image": True,
|
|
"image_only": True,
|
|
"thinking_level": "medium",
|
|
},
|
|
}
|
|
path = tmp_path / "config.toml"
|
|
path.write_text(
|
|
tomli_w.dumps(
|
|
{
|
|
"llm": {"provider": "openrouter"},
|
|
"squilla_router": {"enabled": True, "tiers": tiers},
|
|
}
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
cfg = GatewayConfig.load_from_toml(path)
|
|
assert cfg.squilla_router.tier_profile is None
|
|
assert cfg.squilla_router.tiers == tiers
|
|
|
|
dump = cfg.to_toml_dict()
|
|
router = dump["squilla_router"]
|
|
assert "tier_profile" not in router
|
|
assert router["tiers"] == tiers
|
|
|
|
# full round-trip: dump -> TOML -> load -> identical tiers
|
|
path2 = tmp_path / "roundtrip.toml"
|
|
path2.write_text(tomli_w.dumps(dump), encoding="utf-8")
|
|
cfg2 = GatewayConfig.load_from_toml(path2)
|
|
assert cfg2.squilla_router.tier_profile is None
|
|
assert cfg2.squilla_router.tiers == tiers
|
|
|
|
|
|
def test_rc1_desktop_legacy_tier_keys_merge_to_single_canonical(tmp_path: Path) -> None:
|
|
"""(c) rc1-desktop shape: t0-t3 keys + default_tier="t1" + tier_profile.
|
|
|
|
Legacy keys must normalize BEFORE the profile merge, producing a single
|
|
canonical c0-c3 key set with the overrides applied inside the matching
|
|
canonical tier (normalize-before-merge invariant).
|
|
"""
|
|
path = tmp_path / "config.toml"
|
|
path.write_text(
|
|
"\n".join(
|
|
[
|
|
"[llm]",
|
|
'provider = "deepseek"',
|
|
"",
|
|
"[squilla_router]",
|
|
'tier_profile = "deepseek"',
|
|
'default_tier = "t1"',
|
|
"",
|
|
"[squilla_router.tiers.t0]",
|
|
'model = "custom-fast-model"',
|
|
"",
|
|
"[squilla_router.tiers.t1]",
|
|
'model = "custom-balanced-model"',
|
|
"",
|
|
"[squilla_router.tiers.t2]",
|
|
'model = "custom-strong-model"',
|
|
'thinking_level = "high"',
|
|
"",
|
|
"[squilla_router.tiers.t3]",
|
|
'model = "custom-highest-model"',
|
|
"",
|
|
]
|
|
),
|
|
encoding="utf-8",
|
|
)
|
|
cfg = GatewayConfig.load_from_toml(path)
|
|
router = cfg.squilla_router
|
|
golden = _golden()["deepseek"]
|
|
|
|
assert router.default_tier == "c1"
|
|
assert sorted(router.tiers) == ["c0", "c1", "c2", "c3"] # single-key merge
|
|
assert router.tiers["c0"] == {**golden["c0"], "model": "custom-fast-model"}
|
|
assert router.tiers["c1"] == {**golden["c1"], "model": "custom-balanced-model"}
|
|
assert router.tiers["c2"] == {
|
|
**golden["c2"],
|
|
"model": "custom-strong-model",
|
|
"thinking_level": "high",
|
|
}
|
|
assert router.tiers["c3"] == {**golden["c3"], "model": "custom-highest-model"}
|
|
|
|
|
|
def test_unknown_tier_profile_rejected_with_same_error_shape(tmp_path: Path) -> None:
|
|
"""(d) unknown tier_profile "groq" -> same rejection message as today."""
|
|
path = tmp_path / "config.toml"
|
|
path.write_text(
|
|
'[llm]\nprovider = "groq"\n\n[squilla_router]\ntier_profile = "groq"\n',
|
|
encoding="utf-8",
|
|
)
|
|
with pytest.raises(Exception) as excinfo:
|
|
GatewayConfig.load_from_toml(path)
|
|
assert UNKNOWN_PROFILE_ERROR in str(excinfo.value)
|
|
|
|
|
|
def test_full_default_tree_round_trips_via_to_toml_dict(tmp_path: Path) -> None:
|
|
"""(e) full-default-tree (rc1 RPC-persisted shape) loads and round-trips."""
|
|
dump1 = GatewayConfig().to_toml_dict()
|
|
path = tmp_path / "config.toml"
|
|
path.write_text(tomli_w.dumps(dump1), encoding="utf-8")
|
|
|
|
payload = tomllib.loads(path.read_text(encoding="utf-8"))
|
|
cfg = GatewayConfig(**payload)
|
|
dump2 = cfg.to_toml_dict()
|
|
|
|
assert dump2 == dump1
|
|
# The default tree carries the curated tokenrhythm ladder (the built-in
|
|
# default provider ships packaged tier data but no persistable
|
|
# tier_profile, so its ladder is applied inline).
|
|
tiers = cfg.squilla_router.tiers
|
|
assert set(tiers) == {"c0", "c1", "c2", "c3", "image_model"}
|
|
expected_models = {
|
|
"c0": "deepseek-v4-flash",
|
|
"c1": "deepseek-v4-pro",
|
|
"c2": "kimi-k2.7-code",
|
|
"c3": "glm-5.2",
|
|
"image_model": "kimi-k2.6",
|
|
}
|
|
for name, tier in tiers.items():
|
|
assert tier["provider"] == "tokenrhythm"
|
|
assert tier["model"] == expected_models[name]
|
|
|
|
|
|
# --- H4: downgrade chokepoint at to_toml_dict --------------------------------
|
|
|
|
|
|
def test_to_toml_dict_expands_tiers_and_omits_non_legacy_tier_profile() -> None:
|
|
"""Non-legacy tier_profile never reaches disk: tiers expand, id is dropped.
|
|
|
|
Unreachable through validation today (non-legacy ids are rejected), so the
|
|
guard is exercised by corrupting the profile post-validation — exactly the
|
|
shape a future registry-wide consumer bug would produce.
|
|
"""
|
|
cfg = GatewayConfig(
|
|
llm={"provider": "deepseek"},
|
|
squilla_router={"tier_profile": "deepseek"},
|
|
)
|
|
effective_tiers = {name: dict(t) for name, t in cfg.squilla_router.tiers.items()}
|
|
object.__setattr__(cfg.squilla_router, "tier_profile", "groq")
|
|
|
|
router = cfg.to_toml_dict()["squilla_router"]
|
|
assert "tier_profile" not in router
|
|
assert router["tiers"] == effective_tiers
|
|
|
|
# the guarded dump must load on a legacy-nine-only validator (rc1 shape)
|
|
reloaded = GatewayConfig(llm={"provider": "deepseek"}, squilla_router=router)
|
|
assert reloaded.squilla_router.tier_profile is None
|
|
assert reloaded.squilla_router.tiers == effective_tiers
|
|
|
|
|
|
def test_to_toml_dict_still_collapses_legacy_profile_default_tiers() -> None:
|
|
"""Control: a legacy profile with default tiers keeps today's compact dump."""
|
|
cfg = GatewayConfig(
|
|
llm={"provider": "deepseek"},
|
|
squilla_router={"tier_profile": "deepseek"},
|
|
)
|
|
router = cfg.to_toml_dict()["squilla_router"]
|
|
assert router["tier_profile"] == "deepseek"
|
|
assert "tiers" not in router
|
|
|
|
|
|
def test_to_toml_dict_keeps_overridden_tiers_for_legacy_profile() -> None:
|
|
"""Control: profile + non-default tier override keeps both keys in the dump."""
|
|
cfg = GatewayConfig(
|
|
llm={"provider": "deepseek"},
|
|
squilla_router={
|
|
"tier_profile": "deepseek",
|
|
"tiers": {"c2": {"model": "custom-strong-model"}},
|
|
},
|
|
)
|
|
router = cfg.to_toml_dict()["squilla_router"]
|
|
assert router["tier_profile"] == "deepseek"
|
|
assert router["tiers"]["c2"]["model"] == "custom-strong-model"
|