fix(websearch): route a hook's model on a JSON-configured provider and keep the request provider on an echoed model

This commit is contained in:
mateo-berri 2026-10-20 19:40:05 -07:00
parent f07723fe83
commit 6234434de6
4 changed files with 27 additions and 5 deletions

View file

@ -42,14 +42,19 @@ def names_a_provider(candidate: str) -> bool:
"""Whether a model name's leading segment is a provider rather than part of the model."""
import litellm
from litellm.litellm_core_utils.get_llm_provider_logic import is_registered_custom_provider
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
provider_names: Final = {getattr(provider, "value", provider) for provider in litellm.provider_list}
return candidate in provider_names or is_registered_custom_provider(candidate)
return (
candidate in provider_names
or JSONProviderRegistry.exists(candidate)
or is_registered_custom_provider(candidate)
)
def qualify_agentic_followup_model(patch_model: str | None, model: str, custom_llm_provider: str) -> str:
"""Resolve the model an agentic follow-up re-dispatches, keeping a hook's own provider."""
if not patch_model:
if not patch_model or patch_model == model:
return qualify_provider_stripped_model(model, custom_llm_provider)
leading_segment: Final = patch_model.split("/", 1)[0]
if leading_segment != patch_model and names_a_provider(leading_segment):

View file

@ -48,7 +48,10 @@ from litellm.litellm_core_utils.audio_utils.subtitle_utils import (
SUBTITLE_RESPONSE_FORMATS,
synthesize_subtitle_document,
)
from litellm.litellm_core_utils.core_helpers import set_provider_response_headers_in_hidden_params
from litellm.litellm_core_utils.core_helpers import (
qualify_agentic_followup_model,
set_provider_response_headers_in_hidden_params,
)
from litellm.litellm_core_utils.get_litellm_params import AWS_CREDENTIAL_KWARGS_KEYS
from litellm.litellm_core_utils.llm_request_utils import serialize_multipart_form_fields
from litellm.litellm_core_utils.realtime_errors import (
@ -5847,8 +5850,6 @@ class BaseLLMHTTPHandler:
if patch.messages is None:
raise ValueError("Agentic loop plan missing patched messages")
from litellm.litellm_core_utils.core_helpers import qualify_agentic_followup_model
full_model_name: Final = qualify_agentic_followup_model(patch.model, model, custom_llm_provider)
optional_params_for_followup: Final = dict(optional_params)

View file

@ -662,6 +662,16 @@ def test_a_patched_sub_path_model_still_takes_the_request_provider():
)
def test_a_patched_model_on_a_json_configured_provider_reaches_that_provider():
assert qualify_agentic_followup_model("aihubmix/gpt-4o", "gpt-4o", "openai") == "aihubmix/gpt-4o"
def test_a_patch_echoing_the_request_model_keeps_the_request_provider():
assert qualify_agentic_followup_model("openai/gpt-4o", "openai/gpt-4o", "openrouter") == (
"openrouter/openai/gpt-4o"
)
def test_spend_metadata_merge_survives_the_logging_thread_inserting_into_the_request_metadata() -> None:
metadata: Final[dict[str, object]] = {}

View file

@ -5368,3 +5368,9 @@ class TestAgenticFollowUpKeepsTheProviderPrefix:
assert response.model == "claude-sonnet-4-5"
assert response._hidden_params["custom_llm_provider"] == "anthropic"
@pytest.mark.asyncio
async def test_a_hook_echoing_an_org_style_model_stays_on_the_request_provider(self):
response = await self._run_followup("openai/gpt-4o", "openrouter", patched_model="openai/gpt-4o")
assert response._hidden_params["custom_llm_provider"] == "openrouter"