Merge pull request #337 from jlowin/coerce-numbers-to-str

Coerce numbers to str
This commit is contained in:
Jeremiah Lowin 2025-05-06 10:42:44 -04:00 committed by GitHub
commit 9931b4d2d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 10 additions and 5 deletions

View file

@ -127,7 +127,9 @@ class Tool(BaseModel):
except json.JSONDecodeError:
pass
type_adapter = get_cached_typeadapter(self.fn)
type_adapter = get_cached_typeadapter(
self.fn, config=frozenset([("coerce_numbers_to_str", True)])
)
result = type_adapter.validate_python(parsed_args | injected_args)
if inspect.isawaitable(result):
result = await result

View file

@ -6,23 +6,26 @@ from collections.abc import Callable
from functools import lru_cache
from pathlib import Path
from types import UnionType
from typing import Annotated, TypeVar, Union, get_args, get_origin
from typing import Annotated, Any, TypeVar, Union, get_args, get_origin
from mcp.types import ImageContent
from pydantic import TypeAdapter
from pydantic import ConfigDict, TypeAdapter
T = TypeVar("T")
@lru_cache(maxsize=5000)
def get_cached_typeadapter(cls: T) -> TypeAdapter[T]:
def get_cached_typeadapter(
cls: T, config: frozenset[tuple[str, Any]] | None = None
) -> TypeAdapter[T]:
"""
TypeAdapters are heavy objects, and in an application context we'd typically
create them once in a global scope and reuse them as often as possible.
However, this isn't feasible for user-generated functions. Instead, we use a
cache to minimize the cost of creating them as much as possible.
"""
return TypeAdapter(cls)
config_dict = dict(config or {})
return TypeAdapter(cls, config=ConfigDict(**config_dict))
def issubclass_safe(cls: type, base: type) -> bool: