@@ -340,6 +340,7 @@ def items_to_messages(
340340 cls ,
341341 items : str | Iterable [TResponseInputItem ],
342342 preserve_thinking_blocks : bool = False ,
343+ include_reasoning_content : bool = False ,
343344 ) -> list [ChatCompletionMessageParam ]:
344345 """
345346 Convert a sequence of 'Item' objects into a list of ChatCompletionMessageParam.
@@ -372,6 +373,21 @@ def items_to_messages(
372373 result : list [ChatCompletionMessageParam ] = []
373374 current_assistant_msg : ChatCompletionAssistantMessageParam | None = None
374375 pending_thinking_blocks : list [dict [str , str ]] | None = None
376+ pending_reasoning_content : str | None = None
377+
378+ def apply_pending_reasoning_content (
379+ message : ChatCompletionAssistantMessageParam ,
380+ ) -> None :
381+ nonlocal pending_reasoning_content
382+ if (
383+ not include_reasoning_content
384+ or pending_reasoning_content is None
385+ or "reasoning_content" in message
386+ ):
387+ return
388+
389+ cast (dict [str , Any ], message )["reasoning_content" ] = pending_reasoning_content
390+ pending_reasoning_content = None
375391
376392 def flush_assistant_message () -> None :
377393 nonlocal current_assistant_msg
@@ -387,6 +403,9 @@ def ensure_assistant_message() -> ChatCompletionAssistantMessageParam:
387403 if current_assistant_msg is None :
388404 current_assistant_msg = ChatCompletionAssistantMessageParam (role = "assistant" )
389405 current_assistant_msg ["tool_calls" ] = []
406+ apply_pending_reasoning_content (current_assistant_msg )
407+ else :
408+ apply_pending_reasoning_content (current_assistant_msg )
390409
391410 return current_assistant_msg
392411
@@ -479,6 +498,7 @@ def ensure_assistant_message() -> ChatCompletionAssistantMessageParam:
479498 new_asst ["content" ] = combined
480499
481500 new_asst ["tool_calls" ] = []
501+ apply_pending_reasoning_content (new_asst )
482502 current_assistant_msg = new_asst
483503
484504 # 4) function/file-search calls => attach to assistant
@@ -556,6 +576,32 @@ def ensure_assistant_message() -> ChatCompletionAssistantMessageParam:
556576
557577 # 7) reasoning message => extract thinking blocks if present
558578 elif reasoning_item := cls .maybe_reasoning_message (item ):
579+ # Capture reasoning content if present so we can attach it to the next assistant
580+ # message (required by some providers for tool calls).
581+ summary_items = reasoning_item .get ("summary" )
582+ if (
583+ include_reasoning_content
584+ and isinstance (summary_items , list )
585+ and len (summary_items ) > 0
586+ ):
587+ reasoning_text = summary_items [0 ].get ("text" )
588+ if reasoning_text is not None :
589+ pending_reasoning_content = reasoning_text
590+ if (
591+ include_reasoning_content
592+ and pending_reasoning_content is None
593+ and isinstance (reasoning_item .get ("content" ), list )
594+ ):
595+ reasoning_texts = [
596+ content_item .get ("text" )
597+ for content_item in cast (list [dict [str , Any ]], reasoning_item ["content" ])
598+ if isinstance (content_item , dict )
599+ and content_item .get ("type" ) == "reasoning_text"
600+ and content_item .get ("text" ) is not None
601+ ]
602+ if reasoning_texts :
603+ pending_reasoning_content = "" .join (cast (list [str ], reasoning_texts ))
604+
559605 # Reconstruct thinking blocks from content (text) and encrypted_content (signature)
560606 content_items = reasoning_item .get ("content" , [])
561607 encrypted_content = reasoning_item .get ("encrypted_content" )
0 commit comments