Files
strix/tests/test_grok_routing.py
T

103 lines
4.0 KiB
Python

"""Grok subscription routing through StrixProvider.get_model."""
from __future__ import annotations
import argparse
from unittest import mock
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from strix.config import grok, subscription
from strix.config.models import StrixProvider, _TurnGuardModel
from strix.interface import scan_setup, utils
from strix.report import state as state_mod
def test_grok_prefix_routes_to_chat_completions(monkeypatch) -> None: # type: ignore[no-untyped-def]
client = mock.MagicMock()
monkeypatch.setattr(grok, "get_subscription_client", lambda: client)
model = StrixProvider().get_model("grok/grok-4")
assert isinstance(model, _TurnGuardModel)
assert isinstance(model._inner, OpenAIChatCompletionsModel)
# The provider strips the grok/ prefix and passes xAI's bare model slug.
assert model._inner.model == "grok-4"
def test_non_subscription_model_is_not_hijacked_by_grok(monkeypatch) -> None: # type: ignore[no-untyped-def]
def _boom() -> object:
msg = "grok client must not be built for a non-grok model"
raise AssertionError(msg)
monkeypatch.setattr(grok, "get_subscription_client", _boom)
# A metered xai/* key model must fall through to the normal provider path,
# not the subscription route.
model = StrixProvider().get_model("xai/grok-4")
assert isinstance(model, _TurnGuardModel)
assert not isinstance(model._inner, OpenAIChatCompletionsModel)
def test_provider_label_names_the_subscription() -> None:
assert subscription.provider_label("grok/grok-4") == "Grok"
assert subscription.provider_label("chatgpt/gpt-5.4") == "ChatGPT"
# Metered API-key models are not subscriptions.
assert subscription.provider_label("xai/grok-4") is None
assert subscription.provider_label("openai/gpt-5.4") is None
def test_run_record_reports_grok_provider(monkeypatch) -> None: # type: ignore[no-untyped-def]
settings = mock.MagicMock()
settings.llm.model = "grok/grok-4"
monkeypatch.setattr(state_mod, "load_settings", lambda: settings)
record = state_mod.ReportState(run_name="run-test").run_record
assert record["auth_mode"] == "subscription"
assert record["subscription_provider"] == "Grok"
def test_subscription_label_prefers_persisted_provider(monkeypatch) -> None: # type: ignore[no-untyped-def]
settings = mock.MagicMock()
settings.llm.model = "chatgpt/gpt-5.4" # current settings point at ChatGPT
monkeypatch.setattr(utils, "load_settings", lambda: settings)
# A resumed Grok run keeps its persisted provider even though settings changed.
resumed = mock.MagicMock(
run_record={"auth_mode": "subscription", "subscription_provider": "Grok"}
)
assert utils._subscription_label(resumed) == "Grok subscription"
# With no persisted provider, it derives the label from settings (not a
# hardcoded default).
fresh = mock.MagicMock(run_record={})
assert utils._subscription_label(fresh) == "ChatGPT subscription"
def test_persisted_run_record_carries_provider(tmp_path, monkeypatch) -> None: # type: ignore[no-untyped-def]
settings = mock.MagicMock()
settings.llm.model = "grok/grok-4"
monkeypatch.setattr(scan_setup, "load_settings", lambda: settings)
monkeypatch.setattr(scan_setup, "run_dir_for", lambda _name: tmp_path)
captured: dict[str, object] = {}
monkeypatch.setattr(
"strix.report.writer.write_run_record", lambda _dir, rec: captured.update(rec)
)
args = argparse.Namespace(
run_name="run-test",
targets_info=[],
scan_mode="scan",
instruction=None,
non_interactive=True,
local_sources=[],
diff_scope={"active": False},
scope_mode="mode",
diff_base=None,
)
scan_setup._persist_run_record(args)
# The resume/viewer record must carry the provider so resumed runs stay labeled.
assert captured["auth_mode"] == "subscription"
assert captured["subscription_provider"] == "Grok"