fix: surface Claude thinking blocks as reasoning_content and fix Gemini reasoning param#145
Conversation
…e Gemini reasoning param Claude's extended thinking content was silently dropped during Anthropic→OpenAI normalization. Thinking blocks now flow through as `reasoning_content` in both non-streaming and streaming responses, matching the format OpenAI SDKs expect. Gemini's OpenAI-compatible endpoint requires `reasoning_effort` as a top-level string rather than the nested `reasoning.effort` object — requests now translate the parameter automatically, fixing 400 errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAnthropic provider: added Thinking and Signature fields, tracks thinking blocks in stream converters, extracts and surfaces reasoning_content separately from text in both streaming and batch flows. Gemini provider: adapts chat requests by promoting nested reasoning.Effort to a top-level reasoning_effort field before sending to /chat/completions. Changes
Sequence DiagramsequenceDiagram
participant Client
participant StreamConverter as StreamConverter (Anthropic)
participant ContentService as Content Provider
participant Extractor as Content Extractor
participant ExtraFields as ExtraFields (Reasoning)
Client->>StreamConverter: Receive streaming events
StreamConverter->>ContentService: content_block_start
ContentService-->>StreamConverter: block metadata (type: thinking/text)
StreamConverter->>StreamConverter: mark thinkingBlocks[index] = true
StreamConverter->>ContentService: content_block_delta
ContentService-->>StreamConverter: thinking_delta / text_delta / signature_delta
alt thinking_delta
StreamConverter->>Extractor: append to thinking buffer
Extractor-->>ExtraFields: populate reasoning_content
else signature_delta
StreamConverter->>StreamConverter: suppress for OpenAI-compatible output
else text_delta
StreamConverter->>Extractor: append to text buffer (skip pre-thinking when applicable)
end
ExtraFields-->>Client: emit message with `content` and `reasoning_content`
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The contract replay test golden file was stale — now includes the reasoning_content field that the gateway correctly surfaces from Anthropic thinking blocks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
Summary
reasoning_contentin both non-streaming and streaming responses (OpenAI SDK compatible)reasoningparam caused 400 errors — now translated from nestedreasoning.effortto Gemini's expected top-levelreasoning_effortstringWhat changed
Anthropic provider (
internal/providers/anthropic/anthropic.go)anthropicContentandanthropicDeltastructs now capturethinkingandsignaturefieldsconvertFromAnthropicResponseextracts thinking content and setsreasoning_contentviaExtraFieldsthinking_delta→ emitsreasoning_contentchunks; handlessignature_delta→ skips silentlyextractTextContentrefined to skip preamble text blocks before thinking blocksGemini provider (
internal/providers/gemini/gemini.go)adaptChatRequest()translates{"reasoning": {"effort": "low"}}→{"reasoning_effort": "low"}ChatCompletionandStreamChatCompletionTest plan
make test)make test-e2e)make lint)reasoning_contentpresent in responsereasoning_contentchunks emitted beforecontentmessage.reasoning_contentaccessiblemessage.reasoning_contentaccessiblereasoning.effort— no longer returns 400, response is correct🤖 Generated with Claude Code
Summary by CodeRabbit
New Features