Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/celeste/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Provider(StrEnum):
GROQ = "groq"
GRADIUM = "gradium"
OLLAMA = "ollama"
OPENROUTER = "openrouter"


class Protocol(StrEnum):
Expand Down
1 change: 1 addition & 0 deletions src/celeste/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Credentials(BaseSettings):
bfl_api_key: SecretStr | None = Field(None, alias="BFL_API_KEY")
groq_api_key: SecretStr | None = Field(None, alias="GROQ_API_KEY")
gradium_api_key: SecretStr | None = Field(None, alias="GRADIUM_API_KEY")
openrouter_api_key: SecretStr | None = Field(None, alias="OPENROUTER_API_KEY")

model_config = {
"env_file": find_dotenv(),
Expand Down
2 changes: 2 additions & 0 deletions src/celeste/modalities/text/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .providers.moonshot.models import MODELS as MOONSHOT_MODELS
from .providers.ollama.models import MODELS as OLLAMA_MODELS
from .providers.openai.models import MODELS as OPENAI_MODELS
from .providers.openrouter.models import MODELS as OPENROUTER_MODELS
from .providers.xai.models import MODELS as XAI_MODELS

MODELS: list[Model] = [
Expand All @@ -25,5 +26,6 @@
*MISTRAL_MODELS,
*MOONSHOT_MODELS,
*OPENAI_MODELS,
*OPENROUTER_MODELS,
*XAI_MODELS,
]
2 changes: 2 additions & 0 deletions src/celeste/modalities/text/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .moonshot import MoonshotTextClient
from .ollama import OllamaTextClient
from .openai import OpenAITextClient
from .openrouter import OpenRouterTextClient
from .xai import XAITextClient

PROVIDERS: dict[Provider, type[TextClient]] = {
Expand All @@ -26,5 +27,6 @@
Provider.MISTRAL: MistralTextClient,
Provider.MOONSHOT: MoonshotTextClient,
Provider.OPENAI: OpenAITextClient,
Provider.OPENROUTER: OpenRouterTextClient,
Provider.XAI: XAITextClient,
}
6 changes: 6 additions & 0 deletions src/celeste/modalities/text/providers/openrouter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""OpenRouter provider for text modality."""

from .client import OpenRouterTextClient
from .models import MODELS

__all__ = ["MODELS", "OpenRouterTextClient"]
20 changes: 20 additions & 0 deletions src/celeste/modalities/text/providers/openrouter/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""OpenRouter text client (OpenResponses protocol)."""

from typing import ClassVar

from celeste.modalities.text.protocols.openresponses.client import (
OpenResponsesTextClient,
OpenResponsesTextStream,
)
from celeste.providers.openrouter.config import DEFAULT_BASE_URL


class OpenRouterTextClient(OpenResponsesTextClient):
"""OpenRouter — OpenResponses with default https://openrouter.ai/api."""

_default_base_url: ClassVar[str] = DEFAULT_BASE_URL


OpenRouterTextStream = OpenResponsesTextStream

__all__ = ["OpenRouterTextClient", "OpenRouterTextStream"]
5 changes: 5 additions & 0 deletions src/celeste/modalities/text/providers/openrouter/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""OpenRouter models for text modality."""

from celeste.models import Model

MODELS: list[Model] = []
2 changes: 2 additions & 0 deletions src/celeste/providers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
moonshot,
ollama,
openai,
openrouter,
xai,
)

Expand All @@ -33,5 +34,6 @@
"moonshot",
"ollama",
"openai",
"openrouter",
"xai",
]
11 changes: 11 additions & 0 deletions src/celeste/providers/openrouter/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""OpenRouter provider package for Celeste AI."""

from celeste.core import Provider
from celeste.credentials import register_auth

register_auth( # nosec B106 - env var name, not hardcoded password
provider=Provider.OPENROUTER,
secret_name="OPENROUTER_API_KEY",
header="Authorization",
prefix="Bearer ",
)
3 changes: 3 additions & 0 deletions src/celeste/providers/openrouter/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""OpenRouter configuration."""

DEFAULT_BASE_URL = "https://openrouter.ai/api"
1 change: 1 addition & 0 deletions src/celeste/telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
Provider.XAI: "x_ai",
Provider.GROQ: "groq",
Provider.DEEPSEEK: "deepseek",
Provider.OPENROUTER: "openrouter",
Provider.PERPLEXITY: "perplexity",
Provider.COHERE: "cohere",
}
Expand Down
2 changes: 1 addition & 1 deletion tests/unit_tests/test_provider_api_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def _provider_api_client_files() -> list[Path]:

# Wrapper providers that just re-export another provider's client
# These don't need to match the template contract
wrapper_providers = {"ollama"}
wrapper_providers = {"ollama", "openrouter"}

out: list[Path] = []
for provider_dir in sorted([p for p in providers_dir.iterdir() if p.is_dir()]):
Expand Down
Loading