mirror of
https://github.com/usestrix/strix.git
synced 2026-08-16 01:16:40 +02:00
fix: also reject a fallback model from a different provider
This commit is contained in:
@@ -733,6 +733,25 @@ def _configure_litellm_default(name: str, value: str) -> None:
|
||||
setattr(litellm, name, value)
|
||||
|
||||
|
||||
def fallback_model_rejection(fallback: str, primary: str, settings: Settings) -> str | None:
|
||||
"""Why ``fallback`` cannot stand in for ``primary`` mid-run, or None if it can.
|
||||
|
||||
Provider credentials, SDK route, and each agent's tool wrappers are all set
|
||||
up once from the primary model, so a fallback that needs a different
|
||||
provider or tool schema would be rejected on every request it serves.
|
||||
"""
|
||||
if (
|
||||
_split_model_provider(_normalized_model_name(fallback))[0]
|
||||
!= (_split_model_provider(_normalized_model_name(primary))[0])
|
||||
):
|
||||
return "needs a different provider, whose credentials are not configured"
|
||||
if uses_chat_completions_tool_schema(fallback, settings) != uses_chat_completions_tool_schema(
|
||||
primary, settings
|
||||
):
|
||||
return "needs a different tool schema than the agents are built with"
|
||||
return None
|
||||
|
||||
|
||||
def uses_chat_completions_tool_schema(model_name: str, settings: Settings) -> bool:
|
||||
"""Return whether the resolved SDK route can only receive JSON function tools."""
|
||||
if codex.subscription_model(model_name):
|
||||
|
||||
@@ -22,6 +22,7 @@ from strix.config import load_settings
|
||||
from strix.config.models import (
|
||||
StrixProvider,
|
||||
configure_sdk_model_defaults,
|
||||
fallback_model_rejection,
|
||||
uses_chat_completions_tool_schema,
|
||||
)
|
||||
from strix.config.settings import DEFAULT_MAX_TURNS
|
||||
@@ -177,14 +178,11 @@ async def run_strix_scan(
|
||||
coordinator.set_snapshot_path(agents_path)
|
||||
fallback_model = settings.llm.fallback_model
|
||||
if fallback_model and (
|
||||
uses_chat_completions_tool_schema(fallback_model, settings) != chat_completions_tools
|
||||
rejection := fallback_model_rejection(fallback_model, resolved_model, settings)
|
||||
):
|
||||
# Agents build their tool set once, for the primary model's schema. A
|
||||
# fallback on the other SDK route would reject every replayed turn, so
|
||||
# it can never recover a denied agent — fail fast instead.
|
||||
raise RuntimeError(
|
||||
f"STRIX_LLM_FALLBACK '{fallback_model}' uses a different tool schema than "
|
||||
f"'{resolved_model}'. Pick a fallback from the same provider family."
|
||||
f"STRIX_LLM_FALLBACK '{fallback_model}' {rejection}; it could never serve a "
|
||||
f"turn for '{resolved_model}'. Pick a fallback from the same provider family."
|
||||
)
|
||||
coordinator.configure_denial_fallback(
|
||||
fallback_model,
|
||||
|
||||
Reference in New Issue
Block a user