| 1 | """Utilities for Anthropic API compatibility."""
|
| 2 |
|
| 3 |
|
| 4 | def _is_anthropic_thinking_block(block) -> bool:
|
| 5 | """Check if a content block is a thinking-type block."""
|
| 6 | if not isinstance(block, dict):
|
| 7 | return False
|
| 8 | return block.get("type") in ("thinking", "redacted_thinking")
|
| 9 |
|
| 10 |
|
| 11 | def _reorder_anthropic_thinking_blocks(messages: list[dict]) -> list[dict]:
|
| 12 | """Reorder thinking blocks so they are not the final block in assistant messages.
|
| 13 |
|
| 14 | This is an Anthropic API requirement: thinking blocks must come before other blocks.
|
| 15 | """
|
| 16 | result = []
|
| 17 | for msg in messages:
|
| 18 | if msg.get("role") == "assistant" and isinstance(msg.get("content"), list):
|
| 19 | content = msg["content"]
|
| 20 | thinking_blocks = [b for b in content if _is_anthropic_thinking_block(b)]
|
| 21 | if thinking_blocks:
|
| 22 | other_blocks = [b for b in content if not _is_anthropic_thinking_block(b)]
|
| 23 | if other_blocks:
|
| 24 | msg = {**msg, "content": thinking_blocks + other_blocks}
|
| 25 | else:
|
| 26 | msg = {**msg, "content": thinking_blocks + [{"type": "text", "text": ""}]}
|
| 27 | result.append(msg)
|
| 28 | return result
|
| 29 |
|