refactor(text-generation): migrate Anthropic to mixin pattern#75
Conversation
Migrate text-generation Anthropic provider to use celeste-anthropic Messages API mixin pattern, reducing code duplication and improving maintainability. **Client (client.py):** - Inherit from AnthropicMessagesClient mixin - Delegate HTTP requests to mixin via super() - Remove _make_request() and _make_stream_request() implementations (104 lines → mixin) - Simplify to only wrap responses in TextGenerationUsage/FinishReason **Streaming (streaming.py):** - Inherit from AnthropicMessagesStream mixin - Remove manual SSE event parsing (content_block_delta, message_delta, message_stop) - Remove _parse_usage_from_event() duplication (reuse mixin's usage mapping) - Reduce from 145 lines to 96 lines (34% reduction) **Parameters (parameters.py):** - Import base mappers from celeste-anthropic (TemperatureMapper, MaxTokensMapper, ThinkingMapper, OutputSchemaMapper) - Wrap with TextGenerationParameter names - ThinkingBudgetMapper translates unified values (-1 → "auto") to provider-native format - Remove 248 lines of duplicated mapper implementations **Core Types:** - TextGenerationFinishReason.reason: str → str | None (align with base FinishReason) - AnthropicMessagesClient._parse_finish_reason: Always return FinishReason (not None) - Remove redundant None checks in capability code **Models:** - Add Claude Opus 4.5 model - Remove config.py (moved to provider package) **Dependencies:** - Add celeste-anthropic workspace dependency to text-generation pyproject.toml **Net change:** -319 lines across 8 files Stats: - Client: 104 lines removed (HTTP/request logic → mixin) - Streaming: 49 lines removed (SSE parsing → mixin) - Parameters: 166 lines removed (mapper implementations → provider)
All Anthropic models now include Parameter.MAX_TOKENS in parameter_constraints: - Claude 4.5 models (Sonnet, Haiku, Opus): max 64,000 tokens - Claude Sonnet 4 (20250514): max 64,000 tokens - Claude Opus 4.1 & Opus 4 (20250514): max 32,000 tokens This fixes UnsupportedParameterError when using max_tokens parameter with Anthropic models.
Pull Request Review: Migrate Anthropic to Mixin PatternSummaryThis PR successfully refactors the Anthropic text-generation provider to use a shared mixin pattern, achieving significant code reduction (-319 lines, 58%) while maintaining functionality. The architectural improvements enable horizontal reuse across future capabilities. ✅ StrengthsArchitecture & Design
Code Quality
🔍 Issues & Concerns1. Missing Validation: Thinking Budget Minimum (Severity: Medium)Location: packages/capabilities/text-generation/src/celeste_text_generation/providers/anthropic/parameters.py:32-54 The old implementation validated that thinking budget must be >= 1024 when not using auto. This validation is now missing. The new code translates -1 to auto but does not validate the minimum of 1024 for fixed budgets. Recommendation: Add validation to ThinkingBudgetMapper.map() or document why it's no longer needed. 2. Type Safety in _parse_finish_reason (Severity: High - Documentation)Location: packages/providers/anthropic/src/celeste_anthropic/messages/client.py:136-142 The method always returns a FinishReason object, but stop_reason can be None. While FinishReason.reason is typed as str | None, the behavior should be clearly documented. 3. Content Parsing Behavior (Severity: Low)Location: packages/capabilities/text-generation/src/celeste_text_generation/providers/anthropic/client.py:37-51 The logic finds the first text block and breaks. If there are no text blocks, it returns empty string. Consider documenting this behavior or adding error handling. 4. Beta Header Validation (Severity: Low)Location: packages/providers/anthropic/src/celeste_anthropic/messages/client.py:51-68 The _build_headers method will raise AttributeError if an invalid beta feature name is provided. Consider adding validation or try/except with helpful error message. 🧪 Testing ConcernsThe PR description notes integration tests and manual API testing are not yet complete. Before merging:
🔒 Security Review✅ No security issues found
📊 Performance✅ Performance improvements expected
🎯 Recommendations Before MergeMust Fix
Should Fix
📈 Overall AssessmentRating: 8.5/10 Well-architected refactor with excellent code reduction and maintainability improvements. Main concerns are missing validation and need for integration testing confirmation. Recommendation: Approve with minor changes requested Great work on this refactor! 🚀 |
Summary
Migrates text-generation Anthropic provider to use the
celeste-anthropicMessages API mixin pattern, achieving 319 lines reduction while improving code maintainability and enabling horizontal reuse across future capabilities.Changes
Client Refactoring (-104 lines)
AnthropicMessagesClientmixinsuper()calls_make_request()and_make_stream_request()implementationsTextGenerationUsage/TextGenerationFinishReasonBefore:
After:
Streaming Refactoring (-49 lines, 34% reduction)
AnthropicMessagesStreammixincontent_block_delta,message_delta,message_stop)_parse_usage_from_event()duplication (reuse mixin's usage mapping)Mixin benefit: When Anthropic adds image/video generation, they get SSE parsing for free.
Parameters Refactoring (-166 lines)
celeste-anthropicprovider packageTextGenerationParameternames for capability-specific APIThinkingBudgetMappertranslates unified values (-1→"auto") to provider-native formatBefore: 248 lines of duplicated mapper implementations
After: 68 lines wrapping provider mappers
Core Type Improvements
FinishReason standardization:
TextGenerationFinishReason.reason:str→str | None(align with base)AnthropicMessagesClient._parse_finish_reason: Always returnFinishReason(notNone)Nonechecks in capability codeModel constraints:
Parameter.MAX_TOKENSto all Anthropic models (was missing, causingUnsupportedParameterError)max=64,000tokensmax=32,000tokensDependencies
celeste-anthropicworkspace dependency totext-generation/pyproject.tomlArchitecture Benefits
1. Horizontal Reuse
The mixin enables zero-cost addition of Anthropic support to other capabilities:
2. Single Source of Truth
AnthropicMessagesClient.map_usage_fields()used by both client and streamingAnthropicMessagesStreamfor all capabilities3. Maintainability
_build_headers)Metrics
Test Plan
max_tokens)Migration Validation
Verified the mixin pattern maintains identical behavior:
UsageFieldenum)extended-thinking,structured-outputs)