From 11447c9d406ab9e7dbecc94eab198f8fc4e5abc1 Mon Sep 17 00:00:00 2001 From: Oleksandr Gubarets Date: Fri, 14 Aug 2026 11:15:18 +0300 Subject: [PATCH 1/2] Allow localized display_name/description in ToolsetInfo (str | dict[str, str] | None) --- aidial_client/types/toolset.py | 4 +- scripts/check_toolset_localized.py | 66 ++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 scripts/check_toolset_localized.py diff --git a/aidial_client/types/toolset.py b/aidial_client/types/toolset.py index 077fb78..69aa177 100644 --- a/aidial_client/types/toolset.py +++ b/aidial_client/types/toolset.py @@ -5,9 +5,9 @@ class ToolsetInfo(ExtraAllowModel): id: str toolset: str - display_name: str | None = None + display_name: str | dict[str, str] | None = None display_version: str | None = None - description: str | None = None + description: str | dict[str, str] | None = None icon_url: str | None = None owner: str | None = None object: str | None = None diff --git a/scripts/check_toolset_localized.py b/scripts/check_toolset_localized.py new file mode 100644 index 0000000..27de854 --- /dev/null +++ b/scripts/check_toolset_localized.py @@ -0,0 +1,66 @@ +"""Small script to validate ToolsetInfo accepts string and dict for display_name/description. + +This script avoids importing the package-level `aidial_client` package (which pulls +in other third-party deps) by reading the `types/toolset.py` source, replacing the +top-level package imports with local stubs that provide `ExtraAllowModel` and +`Features` backed by pydantic BaseModel, and executing the modified source in an +isolated namespace. +""" +import sys +import pathlib + +import pydantic + + +def _load_toolset_info_class(): + project_root = pathlib.Path(__file__).resolve().parents[1] + toolset_path = project_root / "aidial_client" / "types" / "toolset.py" + src = toolset_path.read_text(encoding="utf-8") + + # Replace package-level imports with local stubs that rely on pydantic.BaseModel + src = src.replace( + "from aidial_client._internal_types._model import ExtraAllowModel", + "ExtraAllowModel = pydantic.BaseModel", + ) + src = src.replace( + "from aidial_client.types.deployment import Features", + "class Features(pydantic.BaseModel):\n pass", + ) + + ns: dict = {"pydantic": pydantic} + exec(compile(src, str(toolset_path), "exec"), ns) + return ns["ToolsetInfo"] + + +def check(): + ToolsetInfo = _load_toolset_info_class() + try: + obj1 = ToolsetInfo.model_validate({ + "id": "x", + "toolset": "y", + "display_name": {"en": "Foo", "fr": "Foo FR"}, + }) + except Exception as e: + print("FAIL: display_name dict validation failed:", e) + return 1 + + try: + obj2 = ToolsetInfo.model_validate({ + "id": "x", + "toolset": "y", + "display_name": "Foo", + "description": "A description", + }) + except Exception as e: + print("FAIL: display_name string validation failed:", e) + return 1 + + print("PASS: Both validations succeeded") + print("obj1.display_name:", obj1.display_name) + print("obj2.display_name:", obj2.display_name) + return 0 + + +if __name__ == "__main__": + sys.exit(check()) + From 2c8cb47c822ca87c0a32403bff3da1acbd0db6e5 Mon Sep 17 00:00:00 2001 From: Oleksandr Gubarets Date: Fri, 14 Aug 2026 11:55:53 +0300 Subject: [PATCH 2/2] remove test script --- scripts/check_toolset_localized.py | 66 ------------------------------ 1 file changed, 66 deletions(-) delete mode 100644 scripts/check_toolset_localized.py diff --git a/scripts/check_toolset_localized.py b/scripts/check_toolset_localized.py deleted file mode 100644 index 27de854..0000000 --- a/scripts/check_toolset_localized.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Small script to validate ToolsetInfo accepts string and dict for display_name/description. - -This script avoids importing the package-level `aidial_client` package (which pulls -in other third-party deps) by reading the `types/toolset.py` source, replacing the -top-level package imports with local stubs that provide `ExtraAllowModel` and -`Features` backed by pydantic BaseModel, and executing the modified source in an -isolated namespace. -""" -import sys -import pathlib - -import pydantic - - -def _load_toolset_info_class(): - project_root = pathlib.Path(__file__).resolve().parents[1] - toolset_path = project_root / "aidial_client" / "types" / "toolset.py" - src = toolset_path.read_text(encoding="utf-8") - - # Replace package-level imports with local stubs that rely on pydantic.BaseModel - src = src.replace( - "from aidial_client._internal_types._model import ExtraAllowModel", - "ExtraAllowModel = pydantic.BaseModel", - ) - src = src.replace( - "from aidial_client.types.deployment import Features", - "class Features(pydantic.BaseModel):\n pass", - ) - - ns: dict = {"pydantic": pydantic} - exec(compile(src, str(toolset_path), "exec"), ns) - return ns["ToolsetInfo"] - - -def check(): - ToolsetInfo = _load_toolset_info_class() - try: - obj1 = ToolsetInfo.model_validate({ - "id": "x", - "toolset": "y", - "display_name": {"en": "Foo", "fr": "Foo FR"}, - }) - except Exception as e: - print("FAIL: display_name dict validation failed:", e) - return 1 - - try: - obj2 = ToolsetInfo.model_validate({ - "id": "x", - "toolset": "y", - "display_name": "Foo", - "description": "A description", - }) - except Exception as e: - print("FAIL: display_name string validation failed:", e) - return 1 - - print("PASS: Both validations succeeded") - print("obj1.display_name:", obj1.display_name) - print("obj2.display_name:", obj2.display_name) - return 0 - - -if __name__ == "__main__": - sys.exit(check()) -