fix: strip dynamic custom provider route prefixes

maintainer edit: preserve provider-prefix CLI routing for named custom providers by stripping only the matched dynamic route prefix before sending the model id to OpenAI-compatible endpoints. This keeps ordinary namespaced model ids intact when the provider is selected explicitly.
This commit is contained in:
chengyongru
2026-06-13 00:04:13 +08:00
committed by Xubin Ren
parent 09d24e6c25
commit b2d00a4ce0
3 changed files with 126 additions and 4 deletions
+23 -4
View File
@@ -18,6 +18,7 @@ from typing import TYPE_CHECKING, Any
from urllib.parse import urlparse
from loguru import logger
from pydantic.alias_generators import to_snake
from nanobot.providers.base import (
LLMProvider,
@@ -93,6 +94,10 @@ def _model_slug(model_name: str) -> str:
return model_name.lower().rsplit("/", 1)[-1]
def _provider_prefix_key(name: str) -> str:
return to_snake(name.replace("-", "_")).lower()
def _requires_max_completion_tokens(model_name: str) -> bool:
"""Return True for models that reject ``max_tokens`` (GPT-5 family, o-series)."""
slug = _model_slug(model_name)
@@ -592,6 +597,22 @@ class OpenAICompatProvider(LLMProvider):
# Build kwargs
# ------------------------------------------------------------------
def _request_model_name(self, model_name: str) -> str:
spec = self._spec
if not spec or "/" not in model_name:
return model_name
if spec.strip_model_prefix:
return model_name.split("/")[-1]
route_prefixes = getattr(spec, "strip_model_prefixes", ())
if not isinstance(route_prefixes, tuple) or not route_prefixes:
return model_name
model_prefix, routed_model = model_name.split("/", 1)
model_prefix_key = _provider_prefix_key(model_prefix)
if any(_provider_prefix_key(prefix) == model_prefix_key for prefix in route_prefixes):
return routed_model
return model_name
@staticmethod
def _supports_temperature(
model_name: str,
@@ -625,8 +646,7 @@ class OpenAICompatProvider(LLMProvider):
if any(model_name.lower().startswith(k) for k in ("anthropic/", "claude")):
messages, tools = self._apply_cache_control(messages, tools)
if spec and spec.strip_model_prefix:
model_name = model_name.split("/")[-1]
model_name = self._request_model_name(model_name)
kwargs: dict[str, Any] = {
"model": model_name,
@@ -830,8 +850,7 @@ class OpenAICompatProvider(LLMProvider):
) -> dict[str, Any]:
"""Build a Responses API body for direct OpenAI requests."""
model_name = model or self.default_model
if self._spec and self._spec.strip_model_prefix:
model_name = model_name.split("/")[-1]
model_name = self._request_model_name(model_name)
sanitized_messages = self._sanitize_messages(self._sanitize_empty_content(messages))
instructions, input_items = convert_messages(sanitized_messages)