diff --git a/pyproject.toml b/pyproject.toml index 1925fc46..080a4a4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "celeste-ai" -version = "0.2.4" +version = "0.2.5" 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" diff --git a/src/celeste/__init__.py b/src/celeste/__init__.py index e80e8e31..281c4a1b 100644 --- a/src/celeste/__init__.py +++ b/src/celeste/__init__.py @@ -16,6 +16,7 @@ StreamNotExhaustedError, UnsupportedCapabilityError, UnsupportedParameterError, + UnsupportedProviderError, ValidationError, ) from celeste.http import HTTPClient, close_all_http_clients @@ -120,6 +121,7 @@ def create_client( "StreamingNotSupportedError", "UnsupportedCapabilityError", "UnsupportedParameterError", + "UnsupportedProviderError", "Usage", "ValidationError", "close_all_http_clients", diff --git a/src/celeste/core.py b/src/celeste/core.py index 91e155cc..11194ce7 100644 --- a/src/celeste/core.py +++ b/src/celeste/core.py @@ -19,6 +19,7 @@ class Provider(StrEnum): TOPAZLABS = "topazlabs" PERPLEXITY = "perplexity" BYTEDANCE = "bytedance" + ELEVENLABS = "elevenlabs" class Capability(StrEnum): @@ -39,6 +40,9 @@ class Capability(StrEnum): # Audio AUDIO_INTELLIGENCE = "audio-intelligence" + # Speech + SPEECH_GENERATION = "speech-generation" + # Search SEARCH = "search" diff --git a/src/celeste/credentials.py b/src/celeste/credentials.py index 124a0011..f61ede4d 100644 --- a/src/celeste/credentials.py +++ b/src/celeste/credentials.py @@ -5,7 +5,7 @@ from pydantic_settings import BaseSettings from celeste.core import Provider -from celeste.exceptions import MissingCredentialsError +from celeste.exceptions import MissingCredentialsError, UnsupportedProviderError # Provider to credential field mapping PROVIDER_CREDENTIAL_MAP = { @@ -22,6 +22,7 @@ Provider.TOPAZLABS: "topazlabs_api_key", Provider.PERPLEXITY: "perplexity_api_key", Provider.BYTEDANCE: "bytedance_api_key", + Provider.ELEVENLABS: "elevenlabs_api_key", } @@ -41,6 +42,7 @@ class Credentials(BaseSettings): topazlabs_api_key: SecretStr | None = Field(None, alias="TOPAZLABS_API_KEY") perplexity_api_key: SecretStr | None = Field(None, alias="PERPLEXITY_API_KEY") bytedance_api_key: SecretStr | None = Field(None, alias="BYTEDANCE_API_KEY") + elevenlabs_api_key: SecretStr | None = Field(None, alias="ELEVENLABS_API_KEY") model_config = { "env_file": find_dotenv(), @@ -95,12 +97,11 @@ def has_credential(self, provider: Provider) -> bool: True if provider has credentials configured, False if credentials not set. Raises: - ValueError: If provider has no credential mapping. + UnsupportedProviderError: If provider has no credential mapping. """ credential_field = PROVIDER_CREDENTIAL_MAP.get(provider) if not credential_field: - msg = f"Provider {provider} has no credential mapping" - raise ValueError(msg) + raise UnsupportedProviderError(provider=provider) return getattr(self, credential_field, None) is not None diff --git a/src/celeste/exceptions.py b/src/celeste/exceptions.py index cff116e6..c4768dae 100644 --- a/src/celeste/exceptions.py +++ b/src/celeste/exceptions.py @@ -147,6 +147,18 @@ def __init__(self, provider: str) -> None: ) +class UnsupportedProviderError(CredentialsError): + """Raised when a provider is not configured in the credential system.""" + + def __init__(self, provider: str) -> None: + """Initialize with provider details.""" + self.provider = provider + super().__init__( + f"Provider {provider} has no credential mapping. " + f"This provider is not configured in the credential system." + ) + + class UnsupportedParameterError(ValidationError): """Raised when a parameter is not supported by a model.""" @@ -170,4 +182,5 @@ def __init__(self, parameter: str, model_id: str) -> None: "StreamingNotSupportedError", "UnsupportedCapabilityError", "UnsupportedParameterError", + "UnsupportedProviderError", ]