@@ -219,6 +219,23 @@ def split_json_objects(raw: str) -> list[str]:
219219 return expanded
220220
221221
222+ def _merge_reasoning_detail (details : list , new : dict ) -> None :
223+ """Merge a reasoning_details delta chunk into the accumulated list by (type, index)."""
224+ dtype = new .get ('type' , '' )
225+ idx = new .get ('index' )
226+ if idx is not None :
227+ for entry in details :
228+ if entry .get ('type' ) == dtype and entry .get ('index' ) == idx :
229+ if dtype == 'reasoning.text' :
230+ entry ['text' ] = (entry .get ('text' ) or '' ) + (new .get ('text' ) or '' )
231+ elif dtype == 'reasoning.summary' :
232+ entry ['summary' ] = (entry .get ('summary' ) or '' ) + (new .get ('summary' ) or '' )
233+ elif dtype == 'reasoning.encrypted' :
234+ entry ['data' ] = new .get ('data' , entry .get ('data' , '' ))
235+ return
236+ details .append (dict (new ))
237+
238+
222239def get_citation_source_from_tool_result (
223240 tool_name : str , tool_params : dict , tool_result : str , tool_id : str = ''
224241) -> list [dict ]:
@@ -3125,8 +3142,14 @@ async def non_streaming_chat_response_handler(response, ctx):
31253142 )
31263143
31273144 choices = response_data .get ('choices' , [])
3128- if choices and choices [0 ].get ('message' , {}).get ('content' ):
3129- content = response_data ['choices' ][0 ]['message' ]['content' ]
3145+ if choices :
3146+ message_obj = choices [0 ].get ('message' , {})
3147+ content = (
3148+ message_obj .get ('content' )
3149+ or message_obj .get ('reasoning' )
3150+ or message_obj .get ('reasoning_content' )
3151+ or ''
3152+ )
31303153
31313154 if content :
31323155 await event_emitter (
@@ -3809,7 +3832,18 @@ async def flush_pending_delta_data(threshold: int = 0):
38093832 or delta .get ('reasoning' )
38103833 or delta .get ('thinking' )
38113834 )
3812- if reasoning_content :
3835+ reasoning_details = delta .get ('reasoning_details' ) or []
3836+
3837+ # Extract display text from reasoning_details if no plain text arrived
3838+ if not reasoning_content and reasoning_details :
3839+ for detail in reasoning_details :
3840+ if detail .get ('type' ) == 'reasoning.text' and detail .get ('text' ):
3841+ reasoning_content = (reasoning_content or '' ) + detail ['text' ]
3842+ elif detail .get ('type' ) == 'reasoning.summary' and detail .get ('summary' ):
3843+ reasoning_content = (reasoning_content or '' ) + detail ['summary' ]
3844+ # reasoning.encrypted has no displayable text
3845+
3846+ if reasoning_content or reasoning_details :
38133847 if not output or output [- 1 ].get ('type' ) != 'reasoning' :
38143848 reasoning_item = {
38153849 'type' : 'reasoning' ,
@@ -3820,23 +3854,31 @@ async def flush_pending_delta_data(threshold: int = 0):
38203854 'attributes' : {'type' : 'reasoning_content' },
38213855 'content' : [],
38223856 'summary' : None ,
3857+ 'reasoning_details' : [],
38233858 'started_at' : time .time (),
38243859 }
38253860 output .append (reasoning_item )
38263861 else :
38273862 reasoning_item = output [- 1 ]
38283863
3829- # Append to reasoning content
3830- parts = reasoning_item .get ('content' , [])
3831- if parts and parts [- 1 ].get ('type' ) == 'output_text' :
3832- parts [- 1 ]['text' ] += reasoning_content
3833- else :
3834- reasoning_item ['content' ] = [
3835- {
3836- 'type' : 'output_text' ,
3837- 'text' : reasoning_content ,
3838- }
3839- ]
3864+ # Merge reasoning_details chunks into the item for pass-through
3865+ if reasoning_details :
3866+ existing = reasoning_item .setdefault ('reasoning_details' , [])
3867+ for detail in reasoning_details :
3868+ _merge_reasoning_detail (existing , detail )
3869+
3870+ # Append display text for UI rendering
3871+ if reasoning_content :
3872+ parts = reasoning_item .get ('content' , [])
3873+ if parts and parts [- 1 ].get ('type' ) == 'output_text' :
3874+ parts [- 1 ]['text' ] += reasoning_content
3875+ else :
3876+ reasoning_item ['content' ] = [
3877+ {
3878+ 'type' : 'output_text' ,
3879+ 'text' : reasoning_content ,
3880+ }
3881+ ]
38403882
38413883 data = {'content' : serialize_output (full_output ())}
38423884
0 commit comments