diff --git a/strix/config/models.py b/strix/config/models.py index ea846f2a..31bef982 100644 --- a/strix/config/models.py +++ b/strix/config/models.py @@ -649,12 +649,17 @@ def configure_sdk_model_defaults(settings: Settings) -> None: if llm.api_base: os.environ["OPENAI_BASE_URL"] = llm.api_base _configure_litellm_default("api_base", llm.api_base) - api_type = resolve_api_type(llm.model or "", settings) - logger.info("OpenAI API route: %s", api_type) - set_default_openai_api(api_type) + configure_sdk_api_route(llm.model or "", settings) _configure_extra_headers(llm) +def configure_sdk_api_route(model_name: str, settings: Settings) -> None: + """Point SDK-native OpenAI requests for ``model_name`` at Responses or chat completions.""" + api_type = resolve_api_type(model_name, settings) + logger.info("OpenAI API route for %s: %s", model_name, api_type) + set_default_openai_api(api_type) + + _OPENAI_HOSTS = frozenset({"api.openai.com"}) _CHAT_COMPLETIONS_ENDPOINT = "/v1/chat/completions" diff --git a/strix/core/runner.py b/strix/core/runner.py index 6192063d..4e58faad 100644 --- a/strix/core/runner.py +++ b/strix/core/runner.py @@ -18,11 +18,11 @@ from openai import RateLimitError from strix.agents.factory import build_strix_agent, make_child_factory from strix.agents.prompt import render_scope_prompt, render_system_prompt -from strix.config import load_settings +from strix.config import codex, load_settings from strix.config.models import ( StrixProvider, + configure_sdk_api_route, configure_sdk_model_defaults, - resolve_api_type, supports_strict_tool_schemas, uses_chat_completions_tool_schema, ) @@ -258,6 +258,10 @@ async def run_strix_scan( raise RuntimeError( "No LLM model configured. Set STRIX_LLM env or pass model= to run_strix_scan().", ) + if resolved_model != (settings.llm.model or "").strip() and not codex.subscription_model( + resolved_model + ): + configure_sdk_api_route(resolved_model, settings) logger.info("LLM model resolved: %s", resolved_model) chat_completions_tools = uses_chat_completions_tool_schema(resolved_model, settings) strict_tool_schemas = supports_strict_tool_schemas(resolved_model) @@ -373,7 +377,7 @@ async def run_strix_scan( request_timeout=settings.llm.timeout, prompt_cache=settings.llm.prompt_cache, extra_headers=settings.llm.extra_headers, - api_type=resolve_api_type(resolved_model, settings), + api_type="chat_completions" if chat_completions_tools else "responses", ) run_config = RunConfig( model=resolved_model, diff --git a/tests/test_models.py b/tests/test_models.py index e025f4cb..64628a7c 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -10,6 +10,7 @@ from agents.models import _openai_shared from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel from agents.models.openai_responses import OpenAIResponsesModel +from strix.config import models from strix.config.models import ( StrixProvider, _NonStreamingModel, @@ -202,3 +203,17 @@ def test_reasoning_effort_is_case_insensitive( settings = Settings() assert settings.llm.reasoning_effort == expected assert settings.dedupe.reasoning_effort == expected + + +def test_configure_sdk_api_route_follows_the_given_model( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """A ``model=`` override picks its own route, not ``STRIX_LLM``'s.""" + routes: list[str] = [] + monkeypatch.setattr(models, "set_default_openai_api", routes.append) + settings = _settings(monkeypatch, "gpt-5", "https://gateway.example/v1") + + models.configure_sdk_api_route("gpt-5", settings) + models.configure_sdk_api_route("gpt-daybreak-blue-latest", settings) + + assert routes == ["chat_completions", "responses"]