fix: add clear error message for invalid thinking_style values
Widen thinking_style from Literal to str | None and add a @field_validator that produces a helpful error message listing valid options when an invalid value is provided. Addresses the review feedback on #4482.
This commit is contained in:
@@ -2,9 +2,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Any, Literal
|
from typing import TYPE_CHECKING, Any, ClassVar, Literal
|
||||||
|
|
||||||
from pydantic import AliasChoices, ConfigDict, Field, model_validator
|
from pydantic import AliasChoices, ConfigDict, Field, field_validator, model_validator
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
from nanobot.config_base import Base
|
from nanobot.config_base import Base
|
||||||
@@ -182,7 +182,29 @@ class ProviderConfig(Base):
|
|||||||
extra_headers: dict[str, str] | None = None # Custom headers (e.g. APP-Code for AiHubMix)
|
extra_headers: dict[str, str] | None = None # Custom headers (e.g. APP-Code for AiHubMix)
|
||||||
extra_body: dict[str, Any] | None = None # Extra provider request fields; shape depends on provider/API surface
|
extra_body: dict[str, Any] | None = None # Extra provider request fields; shape depends on provider/API surface
|
||||||
extra_query: dict[str, str] | None = None # Extra query params (e.g. api-version for Azure-style gateways)
|
extra_query: dict[str, str] | None = None # Extra query params (e.g. api-version for Azure-style gateways)
|
||||||
thinking_style: Literal["thinking_type", "enable_thinking", "reasoning_split"] | None = None # Thinking/reasoning style for custom providers
|
thinking_style: str | None = None # Thinking/reasoning style for custom providers
|
||||||
|
|
||||||
|
# Valid values mirror the keys of _THINKING_STYLE_MAP in
|
||||||
|
# nanobot/providers/openai_compat_provider.py. Kept duplicated here to
|
||||||
|
# avoid an import cycle (schema.py must not import from providers/).
|
||||||
|
_VALID_THINKING_STYLES: ClassVar[tuple[str, ...]] = (
|
||||||
|
"thinking_type",
|
||||||
|
"enable_thinking",
|
||||||
|
"reasoning_split",
|
||||||
|
)
|
||||||
|
|
||||||
|
@field_validator("thinking_style")
|
||||||
|
@classmethod
|
||||||
|
def _validate_thinking_style(cls, v: str | None) -> str | None:
|
||||||
|
if not v: # None or "" -> no injection, valid (backwards compatible)
|
||||||
|
return v
|
||||||
|
if v not in cls._VALID_THINKING_STYLES:
|
||||||
|
raise ValueError(
|
||||||
|
f"Invalid thinking_style {v!r}. "
|
||||||
|
f"Must be one of: {', '.join(repr(s) for s in cls._VALID_THINKING_STYLES)} "
|
||||||
|
f"(or empty/omitted)."
|
||||||
|
)
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
class BedrockProviderConfig(ProviderConfig):
|
class BedrockProviderConfig(ProviderConfig):
|
||||||
|
|||||||
@@ -45,3 +45,18 @@ class TestCustomProviderThinkingStyle:
|
|||||||
}
|
}
|
||||||
pc = ProvidersConfig.model_validate(data)
|
pc = ProvidersConfig.model_validate(data)
|
||||||
assert pc.custom.thinking_style == "enable_thinking"
|
assert pc.custom.thinking_style == "enable_thinking"
|
||||||
|
|
||||||
|
def test_invalid_thinking_style_raises_with_clear_message(self) -> None:
|
||||||
|
"""An invalid thinking_style must raise a ValidationError whose message
|
||||||
|
lists the valid options (not just Pydantic's generic Literal error)."""
|
||||||
|
import pytest
|
||||||
|
from pydantic import ValidationError
|
||||||
|
|
||||||
|
with pytest.raises(ValidationError) as exc_info:
|
||||||
|
ProviderConfig.model_validate({"thinkingStyle": "thinking_typ"})
|
||||||
|
|
||||||
|
message = str(exc_info.value)
|
||||||
|
assert "Invalid thinking_style" in message
|
||||||
|
assert "thinking_type" in message
|
||||||
|
assert "enable_thinking" in message
|
||||||
|
assert "reasoning_split" in message
|
||||||
|
|||||||
Reference in New Issue
Block a user