From 5ad5e2981625c6f86c55c12ae5aa2e3d3b13610d Mon Sep 17 00:00:00 2001 From: vitalii-dynamiq Date: Wed, 6 May 2026 20:52:02 +0400 Subject: [PATCH] fix(types): make EmbeddingResponse fields all-defaulted (litellm-compat) End-to-end validation of arcllm-sdk in dynamiq's unit-test suite surfaced 10 failures from test fixtures constructing ``EmbeddingResponse()`` with no positional args. Litellm's EmbeddingResponse is a Pydantic model where every field is optional; arcllm 0.4.1's ``msgspec.Struct`` had three required fields (model, data, usage), so every fixture-style construction blew up with ``TypeError: Missing required argument 'model'``. Aligned with the same pattern arcllm already uses for ``ModelResponse``: - ``model: str = ""`` - ``data: list[EmbeddingData] = []`` - ``usage: EmbeddingUsage | None = None`` ``model_dump`` now emits ``"usage": None`` when the field is unset, matching litellm's serialised shape. Real provider responses always populate every field, so this is purely caller ergonomics. Bumps to 0.4.2. --- arcllm/__init__.py | 2 +- arcllm/types.py | 16 +++++++++++----- pyproject.toml | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/arcllm/__init__.py b/arcllm/__init__.py index 4647f80..debf79c 100644 --- a/arcllm/__init__.py +++ b/arcllm/__init__.py @@ -69,7 +69,7 @@ from __future__ import annotations -__version__ = "0.4.1" +__version__ = "0.4.2" __all__ = [ "APIConnectionError", "APIError", diff --git a/arcllm/types.py b/arcllm/types.py index fbb4412..8091392 100644 --- a/arcllm/types.py +++ b/arcllm/types.py @@ -427,11 +427,17 @@ def model_dump(self) -> dict[str, Any]: class EmbeddingResponse(msgspec.Struct): - """Response from an embedding request.""" + """Response from an embedding request. - model: str - data: list[EmbeddingData] - usage: EmbeddingUsage + All fields default — matches the litellm-compat contract where test + fixtures construct ``EmbeddingResponse()`` with no args and populate + fields after the fact. Adapters always set every field on real + responses, so this is purely for caller ergonomics. + """ + + model: str = "" + data: list[EmbeddingData] = [] + usage: EmbeddingUsage | None = None object: str = "list" def model_dump(self) -> dict[str, Any]: @@ -439,7 +445,7 @@ def model_dump(self) -> dict[str, Any]: return { "model": self.model, "data": [d.model_dump() for d in self.data], - "usage": self.usage.model_dump(), + "usage": self.usage.model_dump() if self.usage is not None else None, "object": self.object, } diff --git a/pyproject.toml b/pyproject.toml index 0b7db88..d46cbc8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "arcllm-sdk" -version = "0.4.1" +version = "0.4.2" description = "The arc connecting you to every LLM. Minimal dependencies, maximum performance." readme = "README.md" license = "Apache-2.0"