feat(providers): add OpenAI API package and migrate capabilities to mixins#82
feat(providers): add OpenAI API package and migrate capabilities to mixins#82Kamilbenkirane merged 8 commits intomainfrom
Conversation
Add standalone provider package for OpenAI APIs with mixin pattern
for capability-agnostic reuse across multiple endpoints.
## Images API (OpenAIImagesClient)
- HTTP POST/streaming to /v1/images/generations endpoint
- Supports DALL-E 2/3 (b64_json format) and gpt-image-1 (streaming)
- Usage parsing: input_tokens, output_tokens, total_tokens
- Content extraction from data array
- Revised prompt handling in metadata
## Responses API (OpenAIResponsesClient)
- HTTP POST/streaming to /v1/responses endpoint
- Unified API for text generation capabilities
- Usage parsing with cached and reasoning tokens support
- Content extraction from output array
- Finish reason mapping (completed status)
## Videos API (OpenAIVideosClient)
- Async polling workflow for video generation
- Phase 1: POST to /v1/videos to create job
- Phase 2: Poll GET /v1/videos/{id} until completed/failed
- Phase 3: GET /v1/videos/{id}/content to retrieve video
- Usage parsing: billing units (seconds)
- Multipart request support for input_reference images
## Audio API (OpenAIAudioClient)
- HTTP POST to /v1/audio/speech endpoint
- Binary audio response handling
- Response format mapping (mp3, opus, aac, flac, wav, pcm)
- MIME type conversion to AudioMimeType
All clients follow the mixin pattern for reuse across capabilities.
Add _parse_usage method to GoogleVeoClient to resolve mypy type checking error. GoogleVeoClient was missing this implementation, causing unsafe super() call in GoogleVideoGenerationClient. Google Veo API doesn't return usage data in the response, so this method returns an empty dict that capability clients can wrap in their Usage type.
Standardize parameter naming across speech generation capability. Changes unified parameter name from RESPONSE_FORMAT to OUTPUT_FORMAT to match enum definition and be more consistent with other capabilities. Breaking change: Updates parameter name in: - SpeechGenerationParameter enum - SpeechGenerationParameters class - All ElevenLabs models (9 occurrences) - All OpenAI models (3 occurrences) - Provider parameter mappers
Migrate image generation capability clients to use provider package mixins, eliminating code duplication and centralizing API-specific logic. ## Changes - OpenAI client now inherits from OpenAIImagesClient mixin - Parameter mappers inherit from provider package mappers - Google client uses super()._parse_usage() pattern - Remove unused config.py file (config now in provider package) - Remove revised_prompt handling from provider mixin (handled in capability) ## Code Reduction - ~188 lines removed across client and parameter files - Significant deduplication of HTTP request logic
…r mixins Migrate speech generation capability clients to use provider package mixins, eliminating code duplication and centralizing API-specific logic. ## Changes - OpenAI client now inherits from OpenAIAudioClient mixin - Parameter mappers inherit from provider package mappers - Add SpeechGenerationFinishReason type for consistency - Remove unused config.py file (config now in provider package) - Update _create_inputs to use parameters.get() pattern - Simplify VoiceConstraint docstring - Update tests to reflect new structure ## Code Reduction - ~187 lines removed across client and parameter files - Significant deduplication of HTTP request and parameter mapping logic
Migrate video generation capability clients to use provider package mixins, eliminating code duplication and centralizing API-specific logic. ## Changes - OpenAI client now inherits from OpenAIVideosClient mixin - Parameter mappers inherit from provider package mappers - Google client uses super()._parse_usage() pattern (after Commit 1 fix) - Remove unused config.py file (config now in provider package) - Remove async polling logic (now in provider mixin) - Simplify _parse_usage to use mixin's implementation ## Code Reduction - ~178 lines removed across client and parameter files - Significant deduplication of HTTP request and polling logic
…ve config files Migrate text generation capability client to use provider package mixins, eliminating code duplication and centralizing API-specific logic. ## Changes - OpenAI client now inherits from OpenAIResponsesClient mixin - Parameter mappers inherit from provider package mappers - Streaming class inherits from OpenAIResponsesStream mixin - Remove unused config.py file (config now in provider package) - Simplify _parse_content to use mixin's output array parsing - Simplify _parse_finish_reason to use mixin's implementation ## Code Reduction - ~429 lines removed across client, parameters, and streaming files - Significant deduplication of HTTP request, streaming, and schema logic
Add celeste-openai to [tool.uv.sources] in all capability packages that now import from the OpenAI provider package after the mixin migration. ## Changes - image-generation: Add celeste-openai (imports celeste_openai.images) - speech-generation: Add celeste-openai (imports celeste_openai.audio) - text-generation: Add celeste-openai (imports celeste_openai.responses) - video-generation: Add celeste-openai (imports celeste_openai.videos) This ensures workspace dependencies are properly declared for the refactored capability clients that use OpenAI provider mixins.
Pull Request Review: OpenAI Provider Package & Mixin MigrationThis is a well-architected refactoring that successfully eliminates code duplication through a mixin pattern. The PR achieves a net reduction of 459 lines while centralizing OpenAI API logic. ✅ StrengthsArchitecture & Design
Code Quality
Breaking Change Handling
🔍 Issues & Concerns1. Missing Test Coverage for New Provider Package The new celeste-openai provider package has zero tests. Core functionality like HTTP requests, usage parsing, SSE streaming, and async polling is untested at the provider level. Recommendation: Add unit tests covering:
Note: Integration tests exist at the capability level, but unit tests at the provider level are essential for faster feedback and easier debugging. 2. Potential Configuration Issue in Videos Client File: packages/providers/openai/src/celeste_openai/videos/client.py:90-115 The polling loop has hardcoded configuration:
Recommendation: Consider making polling configuration injectable or model-specific, and add exponential backoff. 3. Inconsistent Finish Reason Handling Mixins return FinishReason but capability clients override to return their specific types (ImageGenerationFinishReason, etc.). This creates type mismatches and redundant overrides. Recommendation: Have mixins return dict or None, matching the pattern used for _parse_usage(). 4. Parameter Name Inconsistency File: packages/capabilities/speech-generation/src/celeste_speech_generation/providers/openai/client.py:74-76 Using SpeechGenerationParameter.OUTPUT_FORMAT as dict key instead of string "output_format". 5. Empty py.typed File Consider adding a comment to clarify it's a PEP 561 marker file. 6. Hardcoded Model Logic in Mixin File: packages/providers/openai/src/celeste_openai/images/client.py:44-47 Model-specific DALL-E logic in mixin creates coupling. Consider moving to capability client. 🎯 Best Practices ValidationSecurity ✅
Performance ✅
Code Organization ✅
📋 Recommendations SummaryCritical: Add unit tests for celeste-openai provider package Should Address: Review polling configuration, refactor finish reason handling Nice to Have: Fix parameter access pattern, add py.typed comment, extract model logic 📊 Migration ImpactBreaking Changes: RESPONSE_FORMAT → OUTPUT_FORMAT is well-documented and consistently applied. Recommendation: Consider deprecation warnings before complete removal for external users. 🎓 ConclusionThis is a high-quality refactoring with excellent mixin pattern implementation. The main concern is lack of dedicated tests for the provider package. Recommendation: Approve after addressing test coverage (or create follow-up issue). Great work - the codebase is significantly cleaner and more maintainable! Reviewed with: Code analysis, architecture review, security scan, best practices validation |
Add standalone provider package for OpenAI APIs with mixin pattern for capability-agnostic reuse across multiple endpoints. Migrate all capability clients to use the new provider mixins, eliminating code duplication and centralizing API-specific logic.
Provider Package (celeste-openai)
Images API (OpenAIImagesClient)
/v1/images/generationsendpointinput_tokens,output_tokens,total_tokensdataarrayResponses API (OpenAIResponsesClient)
/v1/responsesendpointcached_tokensandreasoning_tokenssupportoutputarraycompletedstatus)response_formatVideos API (OpenAIVideosClient)
/v1/videosto create job/v1/videos/{id}untilcompleted/failed/v1/videos/{id}/contentto retrieve videobilling_units(seconds)input_referenceimagesAudio API (OpenAIAudioClient)
/v1/audio/speechendpointmp3,opus,aac,flac,wav,pcm)AudioMimeTypeAll clients follow the mixin pattern for reuse across capabilities.
Capability Migrations
Image Generation
OpenAIImagesClientmixinAspectRatioMapper,SizeMapper,QualityMapper,StyleMapper)config.pyfile (config now in provider package)Speech Generation
OpenAIAudioClientmixinVoiceMapper,SpeedMapper,OutputFormatMapper)SpeechGenerationFinishReasontype for consistencyconfig.pyfileRESPONSE_FORMAT→OUTPUT_FORMATin ElevenLabs modelsText Generation
OpenAIResponsesClientmixinTemperatureMapper,MaxTokensMapper,TopPMapper,FrequencyPenaltyMapper,PresencePenaltyMapper,StopSequencesMapper,ResponseFormatMapper)OpenAIResponsesStreammixinconfig.pyfileVideo Generation
OpenAIVideosClientmixinAspectRatioMapper,DurationMapper)config.pyfileOther Changes
Fixes
_parse_usage()toGoogleVeoClientmixin (returns empty dict, Veo API doesn't provide usage)celeste-openaiworkspace dependency to all capabilitypyproject.tomlfilesCode Statistics
Breaking Changes
Speech Generation Parameter Rename
SpeechGenerationParameter.RESPONSE_FORMAT→SpeechGenerationParameter.OUTPUT_FORMATSpeechGenerationParametersclass, all provider models (ElevenLabs, OpenAI), and parameter mappersRESPONSE_FORMATto useOUTPUT_FORMATinstead