mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-06-15 15:24:06 +00:00
fix: reject custom provider alias conflicts
maintainer edit: reject arbitrary custom provider keys that normalize to built-in provider names so runtime and WebUI settings cannot disagree about whether a provider is dynamic or built in.
This commit is contained in:
parent
b2d00a4ce0
commit
af9f9ebfd7
@ -234,7 +234,7 @@ If you have more than one custom OpenAI-compatible endpoint, give each endpoint
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Custom provider keys are treated as direct OpenAI-compatible providers. `apiBase` is required because nanobot cannot know the endpoint URL. `apiKey` is optional for local servers or private proxies that do not require one. Do not set `apiType` on custom provider keys; `apiType` is only for `providers.openai`.
|
Custom provider keys are treated as direct OpenAI-compatible providers. `apiBase` is required because nanobot cannot know the endpoint URL. `apiKey` is optional for local servers or private proxies that do not require one. Choose a name that does not conflict with a built-in provider name or alias, such as `openai`, `openai-codex`, `github-copilot`, or `lm-studio`. Do not set `apiType` on custom provider keys; `apiType` is only for `providers.openai`.
|
||||||
|
|
||||||
This named custom provider path is not for Anthropic-compatible endpoints. For Anthropic-compatible proxies, use `providers.anthropic.apiBase` and set the preset provider to `anthropic`.
|
This named custom provider path is not for Anthropic-compatible endpoints. For Anthropic-compatible proxies, use `providers.anthropic.apiBase` and set the preset provider to `anthropic`.
|
||||||
|
|
||||||
|
|||||||
@ -245,7 +245,14 @@ class ProvidersConfig(Base):
|
|||||||
def convert_extra_providers(self):
|
def convert_extra_providers(self):
|
||||||
"""Convert extra fields (custom providers) to ProviderConfig objects."""
|
"""Convert extra fields (custom providers) to ProviderConfig objects."""
|
||||||
if self.model_extra:
|
if self.model_extra:
|
||||||
|
from nanobot.providers.registry import find_by_name
|
||||||
|
|
||||||
for key, value in self.model_extra.items():
|
for key, value in self.model_extra.items():
|
||||||
|
if spec := find_by_name(key):
|
||||||
|
raise ValueError(
|
||||||
|
f"providers.{key} conflicts with built-in provider {spec.name!r}; "
|
||||||
|
"use the built-in provider key or choose a different custom provider name"
|
||||||
|
)
|
||||||
if isinstance(value, dict):
|
if isinstance(value, dict):
|
||||||
self.model_extra[key] = ProviderConfig.model_validate(value)
|
self.model_extra[key] = ProviderConfig.model_validate(value)
|
||||||
return self
|
return self
|
||||||
|
|||||||
@ -60,6 +60,18 @@ def test_provider_api_type_is_openai_only() -> None:
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("provider_name", ["openai-codex", "github-copilot", "lm-studio"])
|
||||||
|
def test_dynamic_custom_provider_rejects_builtin_provider_aliases(provider_name: str) -> None:
|
||||||
|
with pytest.raises(ValueError, match="conflicts with built-in provider"):
|
||||||
|
Config.model_validate({
|
||||||
|
"providers": {
|
||||||
|
provider_name: {
|
||||||
|
"apiBase": "https://example.test/v1",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def test_custom_provider_fallback_uses_model_extra_without_pydantic_warnings() -> None:
|
def test_custom_provider_fallback_uses_model_extra_without_pydantic_warnings() -> None:
|
||||||
config = Config.model_validate({
|
config = Config.model_validate({
|
||||||
"agents": {
|
"agents": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user