Skip to content

Commit 545d0d5

Browse files
committed
fix(anthropic): force Claude thinking budget and interleaved hint
- Force default Claude thinking budget to 31999 when thinking is enabled - Inject interleaved thinking hint for Claude tool calls - Log request headers and raw/unwrapped Claude responses for debugging - Preserve thinking signatures across Anthropic compat translation - Improve thinking signature validation/filtering in Antigravity provider Signed-off-by: Moeeze Hassan <fammas.maz@gmail.com>
1 parent 16c889f commit 545d0d5

File tree

2 files changed

+376
-45
lines changed

2 files changed

+376
-45
lines changed

src/rotator_library/anthropic_compat/translator.py

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
from .models import AnthropicMessagesRequest
1414

15+
MIN_THINKING_SIGNATURE_LENGTH = 100
16+
1517

1618
def anthropic_to_openai_messages(
1719
anthropic_messages: List[dict], system: Optional[Union[str, List[dict]]] = None
@@ -56,6 +58,8 @@ def anthropic_to_openai_messages(
5658
# Handle content blocks
5759
openai_content = []
5860
tool_calls = []
61+
reasoning_content = ""
62+
thinking_signature = ""
5963

6064
for block in content:
6165
if isinstance(block, dict):
@@ -84,6 +88,17 @@ def anthropic_to_openai_messages(
8488
"image_url": {"url": source.get("url", "")},
8589
}
8690
)
91+
elif block_type == "thinking":
92+
signature = block.get("signature", "")
93+
if signature and len(signature) >= MIN_THINKING_SIGNATURE_LENGTH:
94+
thinking_text = block.get("thinking", "")
95+
if thinking_text:
96+
reasoning_content += thinking_text
97+
thinking_signature = signature
98+
elif block_type == "redacted_thinking":
99+
signature = block.get("signature", "")
100+
if signature and len(signature) >= MIN_THINKING_SIGNATURE_LENGTH:
101+
thinking_signature = signature
87102
elif block_type == "tool_use":
88103
# Anthropic tool_use -> OpenAI tool_calls
89104
tool_calls.append(
@@ -196,16 +211,37 @@ def anthropic_to_openai_messages(
196211
msg_dict["content"] = " ".join(text_parts) if text_parts else None
197212
else:
198213
msg_dict["content"] = None
214+
if reasoning_content:
215+
msg_dict["reasoning_content"] = reasoning_content
216+
if thinking_signature:
217+
msg_dict["thinking_signature"] = thinking_signature
199218
msg_dict["tool_calls"] = tool_calls
200219
openai_messages.append(msg_dict)
201220
elif openai_content:
202221
# Check if it's just text or mixed content
203222
if len(openai_content) == 1 and openai_content[0].get("type") == "text":
204-
openai_messages.append(
205-
{"role": role, "content": openai_content[0].get("text", "")}
206-
)
223+
msg_dict = {
224+
"role": role,
225+
"content": openai_content[0].get("text", ""),
226+
}
227+
if reasoning_content:
228+
msg_dict["reasoning_content"] = reasoning_content
229+
if thinking_signature:
230+
msg_dict["thinking_signature"] = thinking_signature
231+
openai_messages.append(msg_dict)
207232
else:
208-
openai_messages.append({"role": role, "content": openai_content})
233+
msg_dict = {"role": role, "content": openai_content}
234+
if reasoning_content:
235+
msg_dict["reasoning_content"] = reasoning_content
236+
if thinking_signature:
237+
msg_dict["thinking_signature"] = thinking_signature
238+
openai_messages.append(msg_dict)
239+
elif reasoning_content:
240+
msg_dict = {"role": role, "content": ""}
241+
msg_dict["reasoning_content"] = reasoning_content
242+
if thinking_signature:
243+
msg_dict["thinking_signature"] = thinking_signature
244+
openai_messages.append(msg_dict)
209245

210246
return openai_messages
211247

@@ -293,11 +329,18 @@ def openai_to_anthropic_response(openai_response: dict, original_model: str) ->
293329
# Add thinking content block if reasoning_content is present
294330
reasoning_content = message.get("reasoning_content")
295331
if reasoning_content:
332+
thinking_signature = message.get("thinking_signature", "")
333+
signature = (
334+
thinking_signature
335+
if thinking_signature
336+
and len(thinking_signature) >= MIN_THINKING_SIGNATURE_LENGTH
337+
else ""
338+
)
296339
content_blocks.append(
297340
{
298341
"type": "thinking",
299342
"thinking": reasoning_content,
300-
"signature": "", # Signature is typically empty for proxied responses
343+
"signature": signature,
301344
}
302345
)
303346

0 commit comments

Comments
 (0)