Skip to content

Commit 4e46151

Browse files
committed
fix: preserve legacy thinking blocks when encrypted_content is absent
Address review feedback: the previous change replaced with as the reconstruction guard, which silently dropped thinking blocks for older persisted turns where signatures were absent and only content text was stored. Fix by using so both paths are covered: - encrypted_content present: try JSON first, fall back to legacy '\n'-joined signatures format - encrypted_content absent but content_items present: reconstruct signature-less thinking blocks from content text only, preserving the prior behaviour for those older sessions
1 parent a9dbad8 commit 4e46151

1 file changed

Lines changed: 35 additions & 25 deletions

File tree

src/agents/models/chatcmpl_converter.py

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -775,35 +775,45 @@ def ensure_assistant_message() -> ChatCompletionAssistantMessageParam:
775775
model
776776
and ("claude" in model.lower() or "anthropic" in model.lower())
777777
and preserve_thinking_blocks
778-
and encrypted_content
778+
and (content_items or encrypted_content)
779779
# Items may not all originate from Claude, so we need to check for model match.
780780
# For backward compatibility, if provider_data is missing, we ignore the check.
781781
and (model == item_model or item_provider_data == {})
782782
):
783-
# Try the JSON format first (current serialisation, preserves
784-
# redacted_thinking verbatim). Fall back to the legacy
785-
# "\n"-joined signatures format so existing in-flight sessions
786-
# with the old encoding are not broken.
787-
try:
788-
pending_thinking_blocks = json.loads(encrypted_content)
789-
except (json.JSONDecodeError, TypeError):
790-
signatures = encrypted_content.split("\n") if encrypted_content else []
791-
792-
reconstructed_thinking_blocks = []
793-
for content_item in content_items:
794-
if (
795-
isinstance(content_item, dict)
796-
and content_item.get("type") == "reasoning_text"
797-
):
798-
thinking_block: dict[str, str] = {
799-
"type": "thinking",
800-
"thinking": content_item.get("text", ""),
801-
}
802-
if signatures:
803-
thinking_block["signature"] = signatures.pop(0)
804-
reconstructed_thinking_blocks.append(thinking_block)
805-
806-
pending_thinking_blocks = reconstructed_thinking_blocks
783+
if encrypted_content:
784+
# Try the JSON format first (current serialisation, preserves
785+
# redacted_thinking verbatim). Fall back to the legacy
786+
# "\n"-joined signatures format so existing in-flight sessions
787+
# with the old encoding are not broken.
788+
try:
789+
pending_thinking_blocks = json.loads(encrypted_content)
790+
except (json.JSONDecodeError, TypeError):
791+
signatures = encrypted_content.split("\n")
792+
793+
reconstructed_thinking_blocks = []
794+
for content_item in content_items:
795+
if (
796+
isinstance(content_item, dict)
797+
and content_item.get("type") == "reasoning_text"
798+
):
799+
thinking_block: dict[str, str] = {
800+
"type": "thinking",
801+
"thinking": content_item.get("text", ""),
802+
}
803+
if signatures:
804+
thinking_block["signature"] = signatures.pop(0)
805+
reconstructed_thinking_blocks.append(thinking_block)
806+
807+
pending_thinking_blocks = reconstructed_thinking_blocks
808+
else:
809+
# No encrypted_content: older persisted turns where signatures
810+
# were absent. Reconstruct thinking blocks from content text
811+
# only so multi-turn history is not silently dropped.
812+
pending_thinking_blocks = [
813+
{"type": "thinking", "thinking": item.get("text", "")}
814+
for item in content_items
815+
if isinstance(item, dict) and item.get("type") == "reasoning_text"
816+
]
807817

808818
if model is not None:
809819
replay_context = ReasoningContentReplayContext(

0 commit comments

Comments
 (0)