diff --git a/src/celeste/client.py b/src/celeste/client.py index 095e4123..d9f9ab10 100644 --- a/src/celeste/client.py +++ b/src/celeste/client.py @@ -13,6 +13,7 @@ from celeste.exceptions import StreamingNotSupportedError from celeste.http import HTTPClient, get_http_client from celeste.io import Chunk, FinishReason, Input, Output, Usage +from celeste.mime_types import ApplicationMimeType from celeste.models import Model from celeste.parameters import ParameterMapper, Parameters from celeste.streaming import Stream @@ -52,6 +53,10 @@ def http_client(self) -> HTTPClient: """HTTP client with connection pooling for this provider.""" ... + def _json_headers(self) -> dict[str, str]: + """Build standard JSON request headers with auth.""" + return {**self.auth.get_headers(), "Content-Type": ApplicationMimeType.JSON} + @staticmethod def _deep_merge( target: dict[str, Any], diff --git a/src/celeste/protocols/chatcompletions/client.py b/src/celeste/protocols/chatcompletions/client.py index 71871155..bd2171f8 100644 --- a/src/celeste/protocols/chatcompletions/client.py +++ b/src/celeste/protocols/chatcompletions/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -79,10 +78,7 @@ async def _make_request( if endpoint is None: endpoint = self._default_endpoint - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( self._build_url(endpoint), @@ -104,10 +100,7 @@ def _make_stream_request( if endpoint is None: endpoint = self._default_endpoint - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( self._build_url(endpoint, streaming=True), diff --git a/src/celeste/protocols/openresponses/client.py b/src/celeste/protocols/openresponses/client.py index a0e29dd2..fbc153b3 100644 --- a/src/celeste/protocols/openresponses/client.py +++ b/src/celeste/protocols/openresponses/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -79,10 +78,7 @@ async def _make_request( if endpoint is None: endpoint = self._default_endpoint - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( self._build_url(endpoint), @@ -104,10 +100,7 @@ def _make_stream_request( if endpoint is None: endpoint = self._default_endpoint - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( self._build_url(endpoint, streaming=True), diff --git a/src/celeste/providers/bfl/images/client.py b/src/celeste/providers/bfl/images/client.py index 3ee66c30..d1c36355 100644 --- a/src/celeste/providers/bfl/images/client.py +++ b/src/celeste/providers/bfl/images/client.py @@ -49,12 +49,7 @@ async def _make_request( 2. Poll polling_url until Ready/Failed 3. Return response with _submit_metadata for usage parsing """ - auth_headers = self.auth.get_headers() - headers = { - **auth_headers, - "Content-Type": ApplicationMimeType.JSON, - "Accept": ApplicationMimeType.JSON, - } + headers = {**self._json_headers(), "Accept": ApplicationMimeType.JSON} if endpoint is None: endpoint = config.BFLImagesEndpoint.CREATE_IMAGE @@ -77,10 +72,7 @@ async def _make_request( # Phase 2: Poll for completion start_time = time.monotonic() - poll_headers = { - **auth_headers, - "Accept": ApplicationMimeType.JSON, - } + poll_headers = {**self.auth.get_headers(), "Accept": ApplicationMimeType.JSON} while True: elapsed = time.monotonic() - start_time diff --git a/src/celeste/providers/byteplus/images/client.py b/src/celeste/providers/byteplus/images/client.py index 06223a4a..81cbf0ff 100644 --- a/src/celeste/providers/byteplus/images/client.py +++ b/src/celeste/providers/byteplus/images/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -57,10 +56,7 @@ async def _make_request( if endpoint is None: endpoint = config.BytePlusImagesEndpoint.CREATE_IMAGE - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", @@ -82,10 +78,7 @@ def _make_stream_request( if endpoint is None: endpoint = config.BytePlusImagesEndpoint.CREATE_IMAGE - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/byteplus/videos/client.py b/src/celeste/providers/byteplus/videos/client.py index fe305e8c..cc3493cd 100644 --- a/src/celeste/providers/byteplus/videos/client.py +++ b/src/celeste/providers/byteplus/videos/client.py @@ -10,7 +10,6 @@ from celeste.core import UsageField from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -67,11 +66,7 @@ async def _make_request( 2. Poll CONTENT_STATUS endpoint until succeeded/failed/canceled 3. Return response with final status data """ - auth_headers = self.auth.get_headers() - headers = { - **auth_headers, - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() if endpoint is None: endpoint = config.BytePlusVideosEndpoint.CREATE_VIDEO diff --git a/src/celeste/providers/cohere/chat/client.py b/src/celeste/providers/cohere/chat/client.py index 34780e43..9f3576b5 100644 --- a/src/celeste/providers/cohere/chat/client.py +++ b/src/celeste/providers/cohere/chat/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -59,10 +58,7 @@ async def _make_request( if endpoint is None: endpoint = config.CohereChatEndpoint.CREATE_CHAT - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", @@ -84,10 +80,7 @@ def _make_stream_request( if endpoint is None: endpoint = config.CohereChatEndpoint.CREATE_CHAT - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/elevenlabs/text_to_speech/client.py b/src/celeste/providers/elevenlabs/text_to_speech/client.py index fa8aa8c8..0322e329 100644 --- a/src/celeste/providers/elevenlabs/text_to_speech/client.py +++ b/src/celeste/providers/elevenlabs/text_to_speech/client.py @@ -7,7 +7,7 @@ from celeste.client import APIMixin from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType, AudioMimeType +from celeste.mime_types import AudioMimeType from . import config @@ -55,10 +55,7 @@ async def _make_request( endpoint = config.ElevenLabsTextToSpeechEndpoint.CREATE_SPEECH endpoint = endpoint.format(voice_id=voice_id) - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", @@ -96,10 +93,7 @@ def _make_stream_request( endpoint = config.ElevenLabsTextToSpeechEndpoint.STREAM_SPEECH endpoint = endpoint.format(voice_id=voice_id) - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self._stream_binary_audio( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/google/cloud_tts/client.py b/src/celeste/providers/google/cloud_tts/client.py index b1d3d8e0..8fad1a41 100644 --- a/src/celeste/providers/google/cloud_tts/client.py +++ b/src/celeste/providers/google/cloud_tts/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from ..auth import GoogleADC from . import config @@ -67,10 +66,7 @@ async def _make_request( if endpoint is None: endpoint = config.GoogleCloudTTSEndpoint.CREATE_SPEECH - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/google/embeddings/client.py b/src/celeste/providers/google/embeddings/client.py index 0181f0dd..482f8fa4 100644 --- a/src/celeste/providers/google/embeddings/client.py +++ b/src/celeste/providers/google/embeddings/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from ..auth import GoogleADC from . import config @@ -96,10 +95,7 @@ async def _make_request( if endpoint is None: endpoint = endpoint_template - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( self._build_url(endpoint), diff --git a/src/celeste/providers/google/generate_content/client.py b/src/celeste/providers/google/generate_content/client.py index 5f7badda..d537763d 100644 --- a/src/celeste/providers/google/generate_content/client.py +++ b/src/celeste/providers/google/generate_content/client.py @@ -6,7 +6,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from ..auth import GoogleADC from . import config @@ -70,10 +69,7 @@ async def _make_request( if endpoint is None: endpoint = config.GoogleGenerateContentEndpoint.GENERATE_CONTENT - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( url=self._build_url(endpoint), headers=headers, @@ -94,10 +90,7 @@ def _make_stream_request( if endpoint is None: endpoint = config.GoogleGenerateContentEndpoint.STREAM_GENERATE_CONTENT - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( url=self._build_url(endpoint), headers=headers, diff --git a/src/celeste/providers/google/imagen/client.py b/src/celeste/providers/google/imagen/client.py index a6f443d9..cff92175 100644 --- a/src/celeste/providers/google/imagen/client.py +++ b/src/celeste/providers/google/imagen/client.py @@ -7,7 +7,6 @@ from celeste.core import UsageField from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from ..auth import GoogleADC from . import config @@ -67,10 +66,7 @@ async def _make_request( if endpoint is None: endpoint = config.GoogleImagenEndpoint.CREATE_IMAGE - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( self._build_url(endpoint), headers=headers, diff --git a/src/celeste/providers/google/interactions/client.py b/src/celeste/providers/google/interactions/client.py index e0aa1ab8..9b095e90 100644 --- a/src/celeste/providers/google/interactions/client.py +++ b/src/celeste/providers/google/interactions/client.py @@ -8,7 +8,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -66,10 +65,7 @@ async def _make_request( if endpoint is None: endpoint = config.GoogleInteractionsEndpoint.CREATE_INTERACTION - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", headers=headers, @@ -90,10 +86,7 @@ def _make_stream_request( if endpoint is None: endpoint = config.GoogleInteractionsEndpoint.STREAM_INTERACTION - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( f"{config.BASE_URL}{endpoint}", headers=headers, diff --git a/src/celeste/providers/google/veo/client.py b/src/celeste/providers/google/veo/client.py index 5de40eb1..7817c968 100644 --- a/src/celeste/providers/google/veo/client.py +++ b/src/celeste/providers/google/veo/client.py @@ -8,7 +8,6 @@ from celeste.client import APIMixin from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from ..auth import GoogleADC from . import config @@ -72,10 +71,7 @@ async def _make_poll_request(self, operation_name: str) -> dict[str, Any]: Vertex AI uses POST to fetchPredictOperation with operationName in body. AI Studio uses GET to /v1beta/{operation_name}. """ - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() poll_url = self._build_poll_url(operation_name) if isinstance(self.auth, GoogleADC): @@ -117,11 +113,7 @@ async def _make_request( if endpoint is None: endpoint = config.GoogleVeoEndpoint.CREATE_VIDEO - auth_headers = self.auth.get_headers() - headers = { - **auth_headers, - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() logger.info(f"Initiating video generation with model {self.model.id}") response = await self.http_client.post( diff --git a/src/celeste/providers/ollama/generate/client.py b/src/celeste/providers/ollama/generate/client.py index f41becab..b07c370e 100644 --- a/src/celeste/providers/ollama/generate/client.py +++ b/src/celeste/providers/ollama/generate/client.py @@ -7,7 +7,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -56,10 +55,7 @@ async def _make_request( if base_url is None: base_url = config.DEFAULT_BASE_URL - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{base_url}{endpoint}", @@ -84,10 +80,7 @@ def _make_stream_request( if base_url is None: base_url = config.DEFAULT_BASE_URL - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post_ndjson( f"{base_url}{endpoint}", diff --git a/src/celeste/providers/openai/audio/client.py b/src/celeste/providers/openai/audio/client.py index 13b199d8..28d77392 100644 --- a/src/celeste/providers/openai/audio/client.py +++ b/src/celeste/providers/openai/audio/client.py @@ -6,7 +6,7 @@ from celeste.client import APIMixin from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType, AudioMimeType +from celeste.mime_types import AudioMimeType from . import config @@ -68,10 +68,7 @@ async def _make_request( if endpoint is None: endpoint = config.OpenAIAudioEndpoint.CREATE_SPEECH - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/openai/images/client.py b/src/celeste/providers/openai/images/client.py index 2cac5492..367cbf0d 100644 --- a/src/celeste/providers/openai/images/client.py +++ b/src/celeste/providers/openai/images/client.py @@ -11,7 +11,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from celeste.utils import detect_mime_type from . import config @@ -75,10 +74,7 @@ async def _make_json_request( if self.model.id in ("dall-e-2", "dall-e-3"): request_body.setdefault("response_format", "b64_json") - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", @@ -141,10 +137,7 @@ def _make_stream_request( if "partial_images" not in request_body: request_body["partial_images"] = 1 - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/openai/videos/client.py b/src/celeste/providers/openai/videos/client.py index db7d8380..f4f08415 100644 --- a/src/celeste/providers/openai/videos/client.py +++ b/src/celeste/providers/openai/videos/client.py @@ -14,7 +14,6 @@ from celeste.core import UsageField from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -86,10 +85,7 @@ async def _make_request( if endpoint is None: endpoint = config.OpenAIVideosEndpoint.CREATE_VIDEO - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() files, data = await self._prepare_multipart_request(request_body.copy()) diff --git a/src/celeste/providers/xai/images/client.py b/src/celeste/providers/xai/images/client.py index e95ae829..9d5a398a 100644 --- a/src/celeste/providers/xai/images/client.py +++ b/src/celeste/providers/xai/images/client.py @@ -7,7 +7,6 @@ from celeste.core import UsageField from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -54,10 +53,7 @@ async def _make_request( if endpoint is None: endpoint = config.XAIImagesEndpoint.CREATE_IMAGE - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", diff --git a/src/celeste/providers/xai/videos/client.py b/src/celeste/providers/xai/videos/client.py index d76cc821..42429a1c 100644 --- a/src/celeste/providers/xai/videos/client.py +++ b/src/celeste/providers/xai/videos/client.py @@ -8,7 +8,6 @@ from celeste.core import UsageField from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -66,10 +65,7 @@ async def _make_request( if endpoint is None: endpoint = config.XAIVideosEndpoint.CREATE_VIDEO - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() # Submit video generation request response = await self.http_client.post( diff --git a/templates/providers/{provider_slug}/{api_slug}/client.py.template b/templates/providers/{provider_slug}/{api_slug}/client.py.template index 093695dd..9047f599 100644 --- a/templates/providers/{provider_slug}/{api_slug}/client.py.template +++ b/templates/providers/{provider_slug}/{api_slug}/client.py.template @@ -9,7 +9,6 @@ from celeste.client import APIMixin from celeste.core import UsageField from celeste.exceptions import StreamingNotSupportedError from celeste.io import FinishReason -from celeste.mime_types import ApplicationMimeType from . import config @@ -85,10 +84,7 @@ class {Provider}{Api}Client(APIMixin): if endpoint is None: endpoint = config.{Provider}{Api}Endpoint.CREATE_... - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() response = await self.http_client.post( f"{config.BASE_URL}{endpoint}", @@ -122,10 +118,7 @@ class {Provider}{Api}Client(APIMixin): if endpoint is None: endpoint = config.{Provider}{Api}Endpoint.CREATE_... - headers = { - **self.auth.get_headers(), - "Content-Type": ApplicationMimeType.JSON, - } + headers = self._json_headers() return self.http_client.stream_post( f"{config.BASE_URL}{endpoint}",