2424    MessageRole ,
2525    TextBlock ,
2626    ThinkingBlock ,
27+     ToolCallBlock ,
2728)
2829from  llama_index .core .bridge .pydantic  import  Field , PrivateAttr 
2930from  llama_index .core .callbacks  import  CallbackManager 
@@ -365,18 +366,17 @@ def _get_all_kwargs(self, **kwargs: Any) -> Dict[str, Any]:
365366    def  _get_content_and_tool_calls (
366367        self , response : Optional [Dict [str , Any ]] =  None , content : Dict [str , Any ] =  None 
367368    ) ->  Tuple [
368-         List [Union [TextBlock , ThinkingBlock ]],  Dict [ str ,  Any ], List [str ], List [str ]
369+         List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ] ], List [str ], List [str ]
369370    ]:
370371        assert  response  is  not   None  or  content  is  not   None , (
371372            f"Either response or content must be provided. Got response: { response }  , content: { content }  " 
372373        )
373374        assert  response  is  None  or  content  is  None , (
374375            f"Only one of response or content should be provided. Got response: { response }  , content: { content }  " 
375376        )
376-         tool_calls  =  []
377377        tool_call_ids  =  []
378378        status  =  []
379-         blocks  =  []
379+         blocks :  List [ TextBlock   |   ThinkingBlock   |   ToolCallBlock ]  =  []
380380        if  content  is  not   None :
381381            content_list  =  [content ]
382382        else :
@@ -401,15 +401,21 @@ def _get_content_and_tool_calls(
401401                    tool_usage ["toolUseId" ] =  content_block ["toolUseId" ]
402402                if  "name"  not  in   tool_usage :
403403                    tool_usage ["name" ] =  content_block ["name" ]
404-                 tool_calls .append (tool_usage )
404+                 blocks .append (
405+                     ToolCallBlock (
406+                         tool_name = tool_usage .get ("name" , "" ),
407+                         tool_call_id = tool_usage .get ("toolUseId" ),
408+                         tool_kwargs = tool_usage .get ("input" , {}),
409+                     )
410+                 )
405411            if  tool_result  :=  content_block .get ("toolResult" , None ):
406412                for  tool_result_content  in  tool_result ["content" ]:
407413                    if  text  :=  tool_result_content .get ("text" , None ):
408414                        text_content  +=  text 
409415                tool_call_ids .append (tool_result_content .get ("toolUseId" , "" ))
410416                status .append (tool_result .get ("status" , "" ))
411417
412-         return  blocks , tool_calls ,  tool_call_ids , status 
418+         return  blocks , tool_call_ids , status 
413419
414420    @llm_chat_callback () 
415421    def  chat (self , messages : Sequence [ChatMessage ], ** kwargs : Any ) ->  ChatResponse :
@@ -436,16 +442,13 @@ def chat(self, messages: Sequence[ChatMessage], **kwargs: Any) -> ChatResponse:
436442            ** all_kwargs ,
437443        )
438444
439-         blocks , tool_calls , tool_call_ids , status  =  self ._get_content_and_tool_calls (
440-             response 
441-         )
445+         blocks , tool_call_ids , status  =  self ._get_content_and_tool_calls (response )
442446
443447        return  ChatResponse (
444448            message = ChatMessage (
445449                role = MessageRole .ASSISTANT ,
446450                blocks = blocks ,
447451                additional_kwargs = {
448-                     "tool_calls" : tool_calls ,
449452                    "tool_call_id" : tool_call_ids ,
450453                    "status" : status ,
451454                },
@@ -540,7 +543,7 @@ def gen() -> ChatResponseGen:
540543                                    current_tool_call , tool_use_delta 
541544                                )
542545
543-                     blocks : List [Union [TextBlock , ThinkingBlock ]] =  [
546+                     blocks : List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ]] =  [
544547                        TextBlock (text = content .get ("text" , "" ))
545548                    ]
546549                    if  thinking  !=  "" :
@@ -553,13 +556,21 @@ def gen() -> ChatResponseGen:
553556                                },
554557                            ),
555558                        )
559+                     if  tool_calls :
560+                         for  tool_call  in  tool_calls :
561+                             blocks .append (
562+                                 ToolCallBlock (
563+                                     tool_kwargs = tool_call .get ("input" , {}),
564+                                     tool_name = tool_call .get ("name" , "" ),
565+                                     tool_call_id = tool_call .get ("toolUseId" ),
566+                                 )
567+                             )
556568
557569                    yield  ChatResponse (
558570                        message = ChatMessage (
559571                            role = role ,
560572                            blocks = blocks ,
561573                            additional_kwargs = {
562-                                 "tool_calls" : tool_calls ,
563574                                "tool_call_id" : [
564575                                    tc .get ("toolUseId" , "" ) for  tc  in  tool_calls 
565576                                ],
@@ -579,7 +590,7 @@ def gen() -> ChatResponseGen:
579590                        # Add to our list of tool calls 
580591                        tool_calls .append (current_tool_call )
581592
582-                     blocks : List [Union [TextBlock , ThinkingBlock ]] =  [
593+                     blocks : List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ]] =  [
583594                        TextBlock (text = content .get ("text" , "" ))
584595                    ]
585596                    if  thinking  !=  "" :
@@ -593,12 +604,21 @@ def gen() -> ChatResponseGen:
593604                            ),
594605                        )
595606
607+                     if  tool_calls :
608+                         for  tool_call  in  tool_calls :
609+                             blocks .append (
610+                                 ToolCallBlock (
611+                                     tool_kwargs = tool_call .get ("input" , {}),
612+                                     tool_name = tool_call .get ("name" , "" ),
613+                                     tool_call_id = tool_call .get ("toolUseId" ),
614+                                 )
615+                             )
616+ 
596617                    yield  ChatResponse (
597618                        message = ChatMessage (
598619                            role = role ,
599620                            blocks = blocks ,
600621                            additional_kwargs = {
601-                                 "tool_calls" : tool_calls ,
602622                                "tool_call_id" : [
603623                                    tc .get ("toolUseId" , "" ) for  tc  in  tool_calls 
604624                                ],
@@ -615,7 +635,7 @@ def gen() -> ChatResponseGen:
615635                    # Handle metadata event - this contains the final token usage 
616636                    if  usage  :=  metadata .get ("usage" ):
617637                        # Yield a final response with correct token usage 
618-                         blocks : List [Union [TextBlock , ThinkingBlock ]] =  [
638+                         blocks : List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ]] =  [
619639                            TextBlock (text = content .get ("text" , "" ))
620640                        ]
621641                        if  thinking  !=  "" :
@@ -628,13 +648,21 @@ def gen() -> ChatResponseGen:
628648                                    },
629649                                ),
630650                            )
651+                         if  tool_calls :
652+                             for  tool_call  in  tool_calls :
653+                                 blocks .append (
654+                                     ToolCallBlock (
655+                                         tool_kwargs = tool_call .get ("input" , {}),
656+                                         tool_name = tool_call .get ("name" , "" ),
657+                                         tool_call_id = tool_call .get ("toolUseId" ),
658+                                     )
659+                                 )
631660
632661                        yield  ChatResponse (
633662                            message = ChatMessage (
634663                                role = role ,
635664                                blocks = blocks ,
636665                                additional_kwargs = {
637-                                     "tool_calls" : tool_calls ,
638666                                    "tool_call_id" : [
639667                                        tc .get ("toolUseId" , "" ) for  tc  in  tool_calls 
640668                                    ],
@@ -685,16 +713,13 @@ async def achat(
685713            ** all_kwargs ,
686714        )
687715
688-         blocks , tool_calls , tool_call_ids , status  =  self ._get_content_and_tool_calls (
689-             response 
690-         )
716+         blocks , tool_call_ids , status  =  self ._get_content_and_tool_calls (response )
691717
692718        return  ChatResponse (
693719            message = ChatMessage (
694720                role = MessageRole .ASSISTANT ,
695721                blocks = blocks ,
696722                additional_kwargs = {
697-                     "tool_calls" : tool_calls ,
698723                    "tool_call_id" : tool_call_ids ,
699724                    "status" : status ,
700725                },
@@ -789,7 +814,7 @@ async def gen() -> ChatResponseAsyncGen:
789814                                current_tool_call  =  join_two_dicts (
790815                                    current_tool_call , tool_use_delta 
791816                                )
792-                     blocks : List [Union [TextBlock , ThinkingBlock ]] =  [
817+                     blocks : List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ]] =  [
793818                        TextBlock (text = content .get ("text" , "" ))
794819                    ]
795820                    if  thinking  !=  "" :
@@ -803,12 +828,21 @@ async def gen() -> ChatResponseAsyncGen:
803828                            ),
804829                        )
805830
831+                     if  tool_calls :
832+                         for  tool_call  in  tool_calls :
833+                             blocks .append (
834+                                 ToolCallBlock (
835+                                     tool_kwargs = tool_call .get ("input" , {}),
836+                                     tool_name = tool_call .get ("name" , "" ),
837+                                     tool_call_id = tool_call .get ("toolUseId" ),
838+                                 )
839+                             )
840+ 
806841                    yield  ChatResponse (
807842                        message = ChatMessage (
808843                            role = role ,
809844                            blocks = blocks ,
810845                            additional_kwargs = {
811-                                 "tool_calls" : tool_calls ,
812846                                "tool_call_id" : [
813847                                    tc .get ("toolUseId" , "" ) for  tc  in  tool_calls 
814848                                ],
@@ -828,7 +862,7 @@ async def gen() -> ChatResponseAsyncGen:
828862                        # Add to our list of tool calls 
829863                        tool_calls .append (current_tool_call )
830864
831-                     blocks : List [Union [TextBlock , ThinkingBlock ]] =  [
865+                     blocks : List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ]] =  [
832866                        TextBlock (text = content .get ("text" , "" ))
833867                    ]
834868                    if  thinking  !=  "" :
@@ -842,12 +876,21 @@ async def gen() -> ChatResponseAsyncGen:
842876                            ),
843877                        )
844878
879+                     if  tool_calls :
880+                         for  tool_call  in  tool_calls :
881+                             blocks .append (
882+                                 ToolCallBlock (
883+                                     tool_kwargs = tool_call .get ("input" , {}),
884+                                     tool_name = tool_call .get ("name" , "" ),
885+                                     tool_call_id = tool_call .get ("toolUseId" ),
886+                                 )
887+                             )
888+ 
845889                    yield  ChatResponse (
846890                        message = ChatMessage (
847891                            role = role ,
848892                            blocks = blocks ,
849893                            additional_kwargs = {
850-                                 "tool_calls" : tool_calls ,
851894                                "tool_call_id" : [
852895                                    tc .get ("toolUseId" , "" ) for  tc  in  tool_calls 
853896                                ],
@@ -864,7 +907,7 @@ async def gen() -> ChatResponseAsyncGen:
864907                    # Handle metadata event - this contains the final token usage 
865908                    if  usage  :=  metadata .get ("usage" ):
866909                        # Yield a final response with correct token usage 
867-                         blocks : List [Union [TextBlock , ThinkingBlock ]] =  [
910+                         blocks : List [Union [TextBlock , ThinkingBlock ,  ToolCallBlock ]] =  [
868911                            TextBlock (text = content .get ("text" , "" ))
869912                        ]
870913                        if  thinking  !=  "" :
@@ -878,12 +921,21 @@ async def gen() -> ChatResponseAsyncGen:
878921                                ),
879922                            )
880923
924+                         if  tool_calls :
925+                             for  tool_call  in  tool_calls :
926+                                 blocks .append (
927+                                     ToolCallBlock (
928+                                         tool_kwargs = tool_call .get ("input" , {}),
929+                                         tool_name = tool_call .get ("name" , "" ),
930+                                         tool_call_id = tool_call .get ("toolUseId" ),
931+                                     )
932+                                 )
933+ 
881934                        yield  ChatResponse (
882935                            message = ChatMessage (
883936                                role = role ,
884937                                blocks = blocks ,
885938                                additional_kwargs = {
886-                                     "tool_calls" : tool_calls ,
887939                                    "tool_call_id" : [
888940                                        tc .get ("toolUseId" , "" ) for  tc  in  tool_calls 
889941                                    ],
@@ -960,7 +1012,11 @@ def get_tool_calls_from_response(
9601012        ** kwargs : Any ,
9611013    ) ->  List [ToolSelection ]:
9621014        """Predict and call the tool.""" 
963-         tool_calls  =  response .message .additional_kwargs .get ("tool_calls" , [])
1015+         tool_calls  =  [
1016+             block 
1017+             for  block  in  response .message .blocks 
1018+             if  isinstance (block , ToolCallBlock )
1019+         ]
9641020
9651021        if  len (tool_calls ) <  1 :
9661022            if  error_on_no_tool_call :
@@ -972,26 +1028,23 @@ def get_tool_calls_from_response(
9721028
9731029        tool_selections  =  []
9741030        for  tool_call  in  tool_calls :
975-             if  "toolUseId"  not  in   tool_call  or  "name"  not  in   tool_call :
976-                 raise  ValueError ("Invalid tool call." )
977- 
9781031            # handle empty inputs 
9791032            argument_dict  =  {}
980-             if  "input"   in   tool_call   and   isinstance (tool_call [ "input" ] , str ):
1033+             if  isinstance (tool_call . tool_kwargs , str ):
9811034                # TODO parse_partial_json is not perfect 
9821035                try :
983-                     argument_dict  =  parse_partial_json (tool_call [ "input" ] )
1036+                     argument_dict  =  parse_partial_json (tool_call . tool_kwargs )
9841037                except  ValueError :
9851038                    argument_dict  =  {}
986-             elif  "input"   in   tool_call   and   isinstance (tool_call [ "input" ] , dict ):
987-                 argument_dict  =  tool_call [ "input" ] 
1039+             elif  isinstance (tool_call . tool_kwargs , dict ):
1040+                 argument_dict  =  tool_call . tool_kwargs 
9881041            else :
9891042                continue 
9901043
9911044            tool_selections .append (
9921045                ToolSelection (
993-                     tool_id = tool_call [ "toolUseId" ] ,
994-                     tool_name = tool_call [ "name" ] ,
1046+                     tool_id = tool_call . tool_call_id   or   "" ,
1047+                     tool_name = tool_call . tool_name ,
9951048                    tool_kwargs = argument_dict ,
9961049                )
9971050            )
0 commit comments