Skip to content

Commit 8969a3d

Browse files
xr843claude
andcommitted
Fixed thinking blocks dropped when thinking field is null (#24026)
The check `content.get("thinking", None) is not None` incorrectly drops thinking blocks when the `thinking` key is explicitly null or absent. Changed to `content.get("type") == "thinking"` to match the fix already applied in the experimental pass-through path (PR #15501). Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 488b93c commit 8969a3d

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

litellm/llms/anthropic/chat/transformation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1522,7 +1522,7 @@ def extract_response_content(
15221522
tool_results = []
15231523
tool_results.append(content)
15241524

1525-
elif content.get("thinking", None) is not None:
1525+
elif content.get("type") == "thinking":
15261526
if thinking_blocks is None:
15271527
thinking_blocks = []
15281528
thinking_blocks.append(cast(ChatCompletionThinkingBlock, content))

tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,3 +3321,54 @@ def test_map_tool_helper_empty_parameters_get_default():
33213321
assert result is not None
33223322
assert result["input_schema"]["type"] == "object"
33233323
assert result["input_schema"].get("properties") == {}
3324+
3325+
3326+
def test_extract_response_content_thinking_block_null_thinking():
3327+
"""
3328+
Test that thinking blocks are not dropped when the 'thinking' field is null
3329+
or missing. Regression test for https://github.com/BerriAI/litellm/issues/24026
3330+
"""
3331+
config = AnthropicConfig()
3332+
3333+
# Case 1: thinking key is explicitly null
3334+
completion_response_null = {
3335+
"content": [
3336+
{"type": "thinking", "thinking": None, "signature": "sig123"},
3337+
{"type": "text", "text": "Hello"},
3338+
]
3339+
}
3340+
text, _, thinking_blocks, _, _, _, _, _ = config.extract_response_content(
3341+
completion_response_null
3342+
)
3343+
assert thinking_blocks is not None, "thinking blocks should not be None when thinking=null"
3344+
assert len(thinking_blocks) == 1
3345+
assert "Hello" in text
3346+
3347+
# Case 2: thinking key is absent entirely
3348+
completion_response_missing = {
3349+
"content": [
3350+
{"type": "thinking", "signature": "sig456"},
3351+
{"type": "text", "text": "World"},
3352+
]
3353+
}
3354+
text, _, thinking_blocks, _, _, _, _, _ = config.extract_response_content(
3355+
completion_response_missing
3356+
)
3357+
assert thinking_blocks is not None, "thinking blocks should not be None when thinking key is absent"
3358+
assert len(thinking_blocks) == 1
3359+
assert "World" in text
3360+
3361+
# Case 3: thinking key has actual content (should still work)
3362+
completion_response_text = {
3363+
"content": [
3364+
{"type": "thinking", "thinking": "Let me think...", "signature": "sig789"},
3365+
{"type": "text", "text": "Done"},
3366+
]
3367+
}
3368+
text, _, thinking_blocks, _, _, _, _, _ = config.extract_response_content(
3369+
completion_response_text
3370+
)
3371+
assert thinking_blocks is not None
3372+
assert len(thinking_blocks) == 1
3373+
assert thinking_blocks[0]["thinking"] == "Let me think..."
3374+
assert "Done" in text

0 commit comments

Comments
 (0)