From bdd9a109716584c67d9fd4eb538513a6f1b17d84 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Fri, 7 Nov 2025 14:58:46 +0100 Subject: [PATCH 1/2] chore: bump version to 0.1.1 - Update version in root pyproject.toml - Update version in text-generation package - This version includes optional dependencies configuration --- packages/text-generation/pyproject.toml | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/text-generation/pyproject.toml b/packages/text-generation/pyproject.toml index 61f4b557..64ad2925 100644 --- a/packages/text-generation/pyproject.toml +++ b/packages/text-generation/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "celeste-text-generation" -version = "0.1.0" +version = "0.1.1" description = "Type-safe text generation for Celeste AI. Unified interface for OpenAI, Anthropic, Google, Mistral, Cohere, and more" authors = [{name = "Kamilbenkirane", email = "kamil@withceleste.ai"}] readme = "README.md" diff --git a/pyproject.toml b/pyproject.toml index 46bfa706..5e27d21b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "celeste-ai" -version = "0.1.0" +version = "0.1.1" description = "Open source, type-safe primitives for multi-modal AI. All capabilities, all providers, one interface" authors = [{name = "Kamilbenkirane", email = "kamil@withceleste.ai"}] readme = "README.md" From d69bcf69d64ee9b21bb2c434486962e162c6c594 Mon Sep 17 00:00:00 2001 From: kamilbenkirane Date: Sun, 9 Nov 2025 21:21:46 +0100 Subject: [PATCH 2/2] refactor: standardize capability naming to kebab-case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change capability enum values from snake_case to kebab-case (e.g., text_generation → text-generation) - Update entry point name to match kebab-case convention - Move integration tests to package-specific directories - Update Makefile to reflect new test paths - Remove deprecated claude-sonnet-3-7 model - Update error messages to use capability enums directly --- Makefile | 2 +- packages/text-generation/pyproject.toml | 2 +- .../providers/anthropic/models.py | 9 --------- .../test_text_generation/__init__.py | 0 .../test_text_generation/test_generate.py | 0 src/celeste/client.py | 4 ++-- src/celeste/core.py | 12 ++++++------ tests/integration_tests/__init__.py | 1 - tests/unit_tests/test_client.py | 11 ++++++----- tests/unit_tests/test_core.py | 12 ++++++------ tests/unit_tests/test_init.py | 2 +- 11 files changed, 23 insertions(+), 32 deletions(-) rename {tests => packages/text-generation/tests}/integration_tests/test_text_generation/__init__.py (100%) rename {tests => packages/text-generation/tests}/integration_tests/test_text_generation/test_generate.py (100%) delete mode 100644 tests/integration_tests/__init__.py diff --git a/Makefile b/Makefile index b4e30dfd..19a5e34f 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ test: # Integration testing (requires API keys) integration-test: - uv run pytest tests/integration_tests/ -m integration -v --dist=worksteal -n auto + uv run pytest packages/*/tests/integration_tests/ -m integration -v --dist=worksteal -n auto # Security scanning (config reads from pyproject.toml) security: diff --git a/packages/text-generation/pyproject.toml b/packages/text-generation/pyproject.toml index 64ad2925..5ab20929 100644 --- a/packages/text-generation/pyproject.toml +++ b/packages/text-generation/pyproject.toml @@ -29,7 +29,7 @@ Issues = "https://github.com/withceleste/celeste-python/issues" celeste-ai = { workspace = true } [project.entry-points."celeste.packages"] -text_generation = "celeste_text_generation:register_package" +text-generation = "celeste_text_generation:register_package" [build-system] requires = ["hatchling"] diff --git a/packages/text-generation/src/celeste_text_generation/providers/anthropic/models.py b/packages/text-generation/src/celeste_text_generation/providers/anthropic/models.py index d87b6e1a..14b085c3 100644 --- a/packages/text-generation/src/celeste_text_generation/providers/anthropic/models.py +++ b/packages/text-generation/src/celeste_text_generation/providers/anthropic/models.py @@ -45,15 +45,6 @@ TextGenerationParameter.OUTPUT_SCHEMA: Schema(), }, ), - Model( - id="claude-sonnet-3-7", - provider=Provider.ANTHROPIC, - display_name="Claude Sonnet 3.7", - streaming=True, - parameter_constraints={ - TextGenerationParameter.OUTPUT_SCHEMA: Schema(), - }, - ), Model( id="claude-opus-4-20250514", provider=Provider.ANTHROPIC, diff --git a/tests/integration_tests/test_text_generation/__init__.py b/packages/text-generation/tests/integration_tests/test_text_generation/__init__.py similarity index 100% rename from tests/integration_tests/test_text_generation/__init__.py rename to packages/text-generation/tests/integration_tests/test_text_generation/__init__.py diff --git a/tests/integration_tests/test_text_generation/test_generate.py b/packages/text-generation/tests/integration_tests/test_text_generation/test_generate.py similarity index 100% rename from tests/integration_tests/test_text_generation/test_generate.py rename to packages/text-generation/tests/integration_tests/test_text_generation/test_generate.py diff --git a/src/celeste/client.py b/src/celeste/client.py index 00e5cb6e..d35cd23b 100644 --- a/src/celeste/client.py +++ b/src/celeste/client.py @@ -30,7 +30,7 @@ def model_post_init(self, __context: object) -> None: """Validate capability compatibility.""" if self.capability not in self.model.capabilities: raise ValueError( - f"Model '{self.model.id}' does not support capability {self.capability.value}" + f"Model '{self.model.id}' does not support capability {self.capability}" ) @property @@ -240,7 +240,7 @@ def get_client_class( """ if (capability, provider) not in _clients: raise NotImplementedError( - f"No client registered for {capability.value} with provider {provider.value}" + f"No client registered for {capability} with provider {provider}" ) return _clients[(capability, provider)] diff --git a/src/celeste/core.py b/src/celeste/core.py index ccbd4a24..91e155cc 100644 --- a/src/celeste/core.py +++ b/src/celeste/core.py @@ -25,19 +25,19 @@ class Capability(StrEnum): """Supported AI capabilities.""" # Text - TEXT_GENERATION = "text_generation" + TEXT_GENERATION = "text-generation" EMBEDDINGS = "embeddings" # Image - IMAGE_GENERATION = "image_generation" - IMAGE_INTELLIGENCE = "image_intelligence" + IMAGE_GENERATION = "image-generation" + IMAGE_INTELLIGENCE = "image-intelligence" # Video - VIDEO_INTELLIGENCE = "video_intelligence" - VIDEO_GENERATION = "video_generation" + VIDEO_INTELLIGENCE = "video-intelligence" + VIDEO_GENERATION = "video-generation" # Audio - AUDIO_INTELLIGENCE = "audio_intelligence" + AUDIO_INTELLIGENCE = "audio-intelligence" # Search SEARCH = "search" diff --git a/tests/integration_tests/__init__.py b/tests/integration_tests/__init__.py deleted file mode 100644 index 3bcf811d..00000000 --- a/tests/integration_tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Integration tests for Celeste AI.""" diff --git a/tests/unit_tests/test_client.py b/tests/unit_tests/test_client.py index 58dbe952..7f8317ad 100644 --- a/tests/unit_tests/test_client.py +++ b/tests/unit_tests/test_client.py @@ -235,7 +235,7 @@ def test_validation_failure_with_incompatible_capability( # Arrange & Act & Assert with pytest.raises( ValidationError, - match=r"Model 'gpt-4' does not support capability image_generation", + match=rf"Model 'gpt-4' does not support capability {Capability.IMAGE_GENERATION}", ): ConcreteClient( model=text_model, @@ -287,7 +287,7 @@ def test_validation_fails_with_model_lacking_any_capabilities( # Act & Assert with pytest.raises( ValidationError, - match=r"Model 'broken-model' does not support capability text_generation", + match=rf"Model 'broken-model' does not support capability {Capability.TEXT_GENERATION}", ): ConcreteClient( model=empty_model, @@ -335,7 +335,8 @@ def test_get_client_class_raises_for_unregistered_capability(self) -> None: # Act & Assert with pytest.raises( - NotImplementedError, match=r"No client registered for image_generation" + NotImplementedError, + match=rf"No client registered for {Capability.IMAGE_GENERATION}", ): get_client_class(unregistered_capability, provider) @@ -380,13 +381,13 @@ def test_registry_isolation_between_different_capabilities(self) -> None: ( Capability.IMAGE_GENERATION, Provider.ANTHROPIC, - "image_generation", + "image-generation", "anthropic", ), ( Capability.VIDEO_GENERATION, Provider.OPENAI, - "video_generation", + "video-generation", "openai", ), ], diff --git a/tests/unit_tests/test_core.py b/tests/unit_tests/test_core.py index f69132c6..863ca202 100644 --- a/tests/unit_tests/test_core.py +++ b/tests/unit_tests/test_core.py @@ -80,7 +80,7 @@ def test_capability_is_str_enum(self) -> None: assert issubclass(Capability, Enum) assert issubclass(Capability, str) # Can create capability from string - cap = Capability("text_generation") + cap = Capability("text-generation") assert cap == Capability.TEXT_GENERATION def test_capability_set_operations(self) -> None: @@ -103,19 +103,19 @@ def test_capability_values_are_unique(self) -> None: # Act & Assert assert text.value != image.value - assert text.value == "text_generation" - assert image.value == "image_generation" + assert text.value == "text-generation" + assert image.value == "image-generation" def test_capability_string_conversion(self) -> None: """Capability converts from and to strings correctly.""" # Arrange & Act - from_string = Capability("text_generation") + from_string = Capability("text-generation") from_enum = Capability.TEXT_GENERATION # Assert assert from_string == from_enum - assert from_enum.value == "text_generation" - assert from_enum == "text_generation" + assert from_enum.value == "text-generation" + assert from_enum == "text-generation" class TestEnumImmutability: diff --git a/tests/unit_tests/test_init.py b/tests/unit_tests/test_init.py index 586480f2..4cd4e818 100644 --- a/tests/unit_tests/test_init.py +++ b/tests/unit_tests/test_init.py @@ -44,7 +44,7 @@ def test_create_client_no_models_available_raises_error(self) -> None: # Act & Assert with pytest.raises( - ValueError, match=r"No model found for.*text_generation" + ValueError, match=rf"No model found for.*{Capability.TEXT_GENERATION}" ): create_client(capability=Capability.TEXT_GENERATION)