2024-06-11 11:39:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  inspect  
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  re  
						 
					
						
							
								
									
										
										
										
											2025-03-26 15:40:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  inspect  
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  aiohttp  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  asyncio  
						 
					
						
							
								
									
										
										
										
											2025-04-08 21:11:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  yaml  
						 
					
						
							
								
									
										
										
										
											2025-03-26 15:40:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  pydantic  import  BaseModel  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  pydantic . fields  import  FieldInfo  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  typing  import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Any , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Awaitable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Callable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get_type_hints , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get_args , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get_origin , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Dict , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    List , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Tuple , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Union , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Optional , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Type , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  functools  import  update_wrapper ,  partial  
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-13 12:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  fastapi  import  Request  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  pydantic  import  BaseModel ,  Field ,  create_model  
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:43:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  langchain_core . utils . function_calling  import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    convert_to_openai_function  as  convert_pydantic_model_to_openai_function_spec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
									
										
										
										
											2024-12-13 12:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-10 16:54:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  open_webui . models . tools  import  Tools  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  open_webui . models . users  import  UserModel  
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:41:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  open_webui . utils . plugin  import  load_tool_module_by_id  
						 
					
						
							
								
									
										
										
										
											2025-04-18 13:02:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  open_webui . env  import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
									
										
										
										
											2024-08-19 23:27:38 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  copy  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								log  =  logging . getLogger ( __name__ )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  get_async_tool_function_and_apply_extra_params (  
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    function :  Callable ,  extra_params :  dict 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  - >  Callable [ . . . ,  Awaitable ] :  
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:41:35 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    sig  =  inspect . signature ( function ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    extra_params  =  { k :  v  for  k ,  v  in  extra_params . items ( )  if  k  in  sig . parameters } 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    partial_func  =  partial ( function ,  * * extra_params ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  inspect . iscoroutinefunction ( function ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        update_wrapper ( partial_func ,  function ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  partial_func 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Make it a coroutine function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        async  def  new_function ( * args ,  * * kwargs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  partial_func ( * args ,  * * kwargs ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        update_wrapper ( new_function ,  function ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  new_function 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_tools (  
						 
					
						
							
								
									
										
										
										
											2024-12-13 12:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    request :  Request ,  tool_ids :  list [ str ] ,  user :  UserModel ,  extra_params :  dict 
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  - >  dict [ str ,  dict ] :  
						 
					
						
							
								
									
										
										
										
											2024-11-17 10:31:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    tools_dict  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-08-19 17:53:12 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    for  tool_id  in  tool_ids : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:03:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        tool  =  Tools . get_tool_by_id ( tool_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  tool  is  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  tool_id . startswith ( " server: " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                server_idx  =  int ( tool_id . split ( " : " ) [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                tool_server_connection  =  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    request . app . state . config . TOOL_SERVER_CONNECTIONS [ server_idx ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-08 18:35:04 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                tool_server_data  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  server  in  request . app . state . TOOL_SERVERS : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  server [ " idx " ]  ==  server_idx : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        tool_server_data  =  server 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                assert  tool_server_data  is  not  None 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                specs  =  tool_server_data . get ( " specs " ,  [ ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  spec  in  specs : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    function_name  =  spec [ " name " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    auth_type  =  tool_server_connection . get ( " auth_type " ,  " bearer " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    token  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  auth_type  ==  " bearer " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        token  =  tool_server_connection . get ( " key " ,  " " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    elif  auth_type  ==  " session " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        token  =  request . state . token . credentials 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:45:32 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    def  make_tool_function ( function_name ,  token ,  tool_server_data ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        async  def  tool_function ( * * kwargs ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            print ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                f " Executing tool function  { function_name }  with params:  { kwargs } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            return  await  execute_tool_server ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                token = token , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                url = tool_server_data [ " url " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                name = function_name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                params = kwargs , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                server_data = tool_server_data , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        return  tool_function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    tool_function  =  make_tool_function ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        function_name ,  token ,  tool_server_data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:38:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    callable  =  get_async_tool_function_and_apply_extra_params ( 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:38:46 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        tool_function , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        { } , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    tool_dict  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " tool_id " :  tool_id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " callable " :  callable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " spec " :  spec , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # TODO: if collision, prepend toolkit name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  function_name  in  tools_dict : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        log . warning ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            f " Tool  { function_name }  already exists in another tools! " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        log . warning ( f " Discarding  { tool_id } . { function_name } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        tools_dict [ function_name ]  =  tool_dict 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:03:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            module  =  request . app . state . TOOLS . get ( tool_id ,  None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  module  is  None : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:41:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                module ,  _  =  load_tool_module_by_id ( tool_id ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                request . app . state . TOOLS [ tool_id ]  =  module 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            extra_params [ " __id__ " ]  =  tool_id 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # Set valves for the tool 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  hasattr ( module ,  " valves " )  and  hasattr ( module ,  " Valves " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                valves  =  Tools . get_tool_valves_by_id ( tool_id )  or  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                module . valves  =  module . Valves ( * * valves ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  hasattr ( module ,  " UserValves " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                extra_params [ " __user__ " ] [ " valves " ]  =  module . UserValves (   # type: ignore 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    * * Tools . get_user_valves_by_id_and_user_id ( tool_id ,  user . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:03:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  spec  in  tool . specs : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # TODO: Fix hack for OpenAI API 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Some times breaks OpenAI but others don't. Leaving the comment 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  val  in  spec . get ( " parameters " ,  { } ) . get ( " properties " ,  { } ) . values ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  val [ " type " ]  ==  " str " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        val [ " type " ]  =  " string " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # Remove internal reserved parameters (e.g. __id__, __user__) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                spec [ " parameters " ] [ " properties " ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    key :  val 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    for  key ,  val  in  spec [ " parameters " ] [ " properties " ] . items ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  not  key . startswith ( " __ " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # convert to function that takes only model params and inserts custom params 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                function_name  =  spec [ " name " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                tool_function  =  getattr ( module ,  function_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                callable  =  get_async_tool_function_and_apply_extra_params ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    tool_function ,  extra_params 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # TODO: Support Pydantic models as parameters 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  callable . __doc__  and  callable . __doc__ . strip ( )  !=  " " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    s  =  re . split ( " :(param|return) " ,  callable . __doc__ ,  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    spec [ " description " ]  =  s [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    spec [ " description " ]  =  function_name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                tool_dict  =  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:03:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    " tool_id " :  tool_id , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    " callable " :  callable , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " spec " :  spec , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # Misc info 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " metadata " :  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " file_handler " :  hasattr ( module ,  " file_handler " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        and  module . file_handler , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " citation " :  hasattr ( module ,  " citation " )  and  module . citation , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # TODO: if collision, prepend toolkit name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  function_name  in  tools_dict : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    log . warning ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        f " Tool  { function_name }  already exists in another tools! " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:31:22 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    log . warning ( f " Discarding  { tool_id } . { function_name } " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    tools_dict [ function_name ]  =  tool_dict 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-17 10:31:13 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  tools_dict 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-11 11:39:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-23 00:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  parse_description ( docstring :  str  |  None )  - >  str :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Parse  a  function ' s docstring to extract the description. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Args : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        docstring  ( str ) :  The  docstring  to  parse . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Returns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        str :  The  description . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  docstring : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  " " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lines  =  [ line . strip ( )  for  line  in  docstring . strip ( ) . split ( " \n " ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    description_lines :  list [ str ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  line  in  lines : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  re . match ( r " :param " ,  line )  or  re . match ( r " :return " ,  line ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        description_lines . append ( line ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  " \n " . join ( description_lines ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  parse_docstring ( docstring ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Parse  a  function ' s docstring to extract parameter descriptions in reST format. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Args : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        docstring  ( str ) :  The  docstring  to  parse . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Returns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        dict :  A  dictionary  where  keys  are  parameter  names  and  values  are  descriptions . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  docstring : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Regex to match `:param name: description` format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    param_pattern  =  re . compile ( r " :param ( \ w+): \ s*(.+) " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    param_descriptions  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  line  in  docstring . splitlines ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        match  =  param_pattern . match ( line . strip ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-23 04:51:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  match : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        param_name ,  param_description  =  match . groups ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  param_name . startswith ( " __ " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        param_descriptions [ param_name ]  =  param_description 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  param_descriptions 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-11 11:39:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:43:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  convert_function_to_pydantic_model ( func :  Callable )  - >  type [ BaseModel ] :  
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Converts  a  Python  function ' s type hints and docstring to a Pydantic model, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    including  support  for  nested  types ,  default  values ,  and  descriptions . 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-11 11:39:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    Args : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        func :  The  function  whose  type  hints  and  docstring  should  be  converted . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        model_name :  The  name  of  the  generated  Pydantic  model . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Returns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        A  Pydantic  model  class . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    type_hints  =  get_type_hints ( func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    signature  =  inspect . signature ( func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parameters  =  signature . parameters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    docstring  =  func . __doc__ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-01 02:22:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    function_description  =  parse_description ( docstring ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    function_param_descriptions  =  parse_docstring ( docstring ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-23 00:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    field_defs  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  name ,  param  in  parameters . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        type_hint  =  type_hints . get ( name ,  Any ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        default_value  =  param . default  if  param . default  is  not  param . empty  else  . . . 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-01 02:22:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        param_description  =  function_param_descriptions . get ( name ,  None ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-01 02:22:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  param_description : 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 03:48:24 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            field_defs [ name ]  =  type_hint ,  Field ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                default_value ,  description = param_description 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            field_defs [ name ]  =  type_hint ,  default_value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-11-23 00:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    model  =  create_model ( func . __name__ ,  * * field_defs ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-01 02:22:38 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    model . __doc__  =  function_description 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-23 00:25:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  model 
							 
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:41:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  get_functions_from_tool ( tool :  object )  - >  list [ Callable ] :  
						 
					
						
							
								
									
										
										
										
											2024-11-22 01:19:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        getattr ( tool ,  func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  func  in  dir ( tool ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:41:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  callable ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            getattr ( tool ,  func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        )   # checks if the attribute is callable (a method or function). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        and  not  func . startswith ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " __ " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        )   # filters out special (dunder) methods like init, str, etc. — these are usually built-in functions of an object that you might not need to use directly. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        and  not  inspect . isclass ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            getattr ( tool ,  func ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        )   # ensures that the callable is not a class itself, just a method or function. 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-11 11:39:55 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:41:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  get_tool_specs ( tool_module :  object )  - >  list [ dict ] :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    function_models  =  map ( 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:43:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        convert_function_to_pydantic_model ,  get_functions_from_tool ( tool_module ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 19:03:15 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:41:17 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    specs  =  [ 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 10:43:26 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        convert_pydantic_model_to_openai_function_spec ( function_model ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  function_model  in  function_models 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:59:11 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    ] 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 12:22:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    return  specs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  resolve_schema ( schema ,  components ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Recursively  resolves  a  JSON  schema  using  OpenAPI  components . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  schema : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  " $ref "  in  schema : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ref_path  =  schema [ " $ref " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ref_parts  =  ref_path . strip ( " #/ " ) . split ( " / " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        resolved  =  components 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  part  in  ref_parts [ 1 : ] :   # Skip the initial 'components' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            resolved  =  resolved . get ( part ,  { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  resolve_schema ( resolved ,  components ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    resolved_schema  =  copy . deepcopy ( schema ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Recursively resolve inner schemas 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  " properties "  in  resolved_schema : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  prop ,  prop_schema  in  resolved_schema [ " properties " ] . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            resolved_schema [ " properties " ] [ prop ]  =  resolve_schema ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                prop_schema ,  components 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  " items "  in  resolved_schema : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        resolved_schema [ " items " ]  =  resolve_schema ( resolved_schema [ " items " ] ,  components ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  resolved_schema 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  convert_openapi_to_tool_payload ( openapi_spec ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Converts  an  OpenAPI  specification  into  a  custom  tool  payload  structure . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Args : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        openapi_spec  ( dict ) :  The  OpenAPI  specification  as  a  Python  dict . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Returns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        list :  A  list  of  tool  payloads . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    tool_payload  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  path ,  methods  in  openapi_spec . get ( " paths " ,  { } ) . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  method ,  operation  in  methods . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:46:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  operation . get ( " operationId " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                tool  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " type " :  " function " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " name " :  operation . get ( " operationId " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " description " :  operation . get ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " description " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        operation . get ( " summary " ,  " No description available. " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " parameters " :  { " type " :  " object " ,  " properties " :  { } ,  " required " :  [ ] } , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:46:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # Extract path and query parameters 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  param  in  operation . get ( " parameters " ,  [ ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    param_name  =  param [ " name " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    param_schema  =  param . get ( " schema " ,  { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    description  =  param_schema . get ( " description " ,  " " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  not  description : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        description  =  param . get ( " description " )  or  " " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  param_schema . get ( " enum " )  and  isinstance ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        param_schema . get ( " enum " ) ,  list 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        description  + =  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            f " . Possible values:  { ' ,  ' . join ( param_schema . get ( ' enum ' ) ) } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    tool [ " parameters " ] [ " properties " ] [ param_name ]  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " type " :  param_schema . get ( " type " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " description " :  description , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  param . get ( " required " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        tool [ " parameters " ] [ " required " ] . append ( param_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Extract and resolve requestBody if available 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                request_body  =  operation . get ( " requestBody " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  request_body : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    content  =  request_body . get ( " content " ,  { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    json_schema  =  content . get ( " application/json " ,  { } ) . get ( " schema " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  json_schema : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        resolved_schema  =  resolve_schema ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            json_schema ,  openapi_spec . get ( " components " ,  { } ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:46:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  resolved_schema . get ( " properties " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            tool [ " parameters " ] [ " properties " ] . update ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                resolved_schema [ " properties " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            if  " required "  in  resolved_schema : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                tool [ " parameters " ] [ " required " ]  =  list ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    set ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        tool [ " parameters " ] [ " required " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        +  resolved_schema [ " required " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:46:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        elif  resolved_schema . get ( " type " )  ==  " array " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            tool [ " parameters " ]  =  ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                resolved_schema   # special case for array 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-19 18:46:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                tool_payload . append ( tool ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  tool_payload 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  get_tool_server_data ( token :  str ,  url :  str )  - >  Dict [ str ,  Any ] :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    headers  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " Accept " :  " application/json " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " Content-Type " :  " application/json " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  token : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        headers [ " Authorization " ]  =  f " Bearer  { token } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-11 01:23:14 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        timeout  =  aiohttp . ClientTimeout ( total = AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-18 13:02:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        async  with  aiohttp . ClientSession ( timeout = timeout ,  trust_env = True )  as  session : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            async  with  session . get ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                url ,  headers = headers ,  ssl = AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            )  as  response : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  response . status  !=  200 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    error_body  =  await  response . json ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    raise  Exception ( error_body ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-08 21:11:37 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Check if URL ends with .yaml or .yml to determine format 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  url . lower ( ) . endswith ( ( " .yaml " ,  " .yml " ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    text_content  =  await  response . text ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    res  =  yaml . safe_load ( text_content ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    res  =  await  response . json ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    except  Exception  as  err : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-08 21:13:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        log . exception ( f " Could not fetch tool server spec from  { url } " ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  isinstance ( err ,  dict )  and  " detail "  in  err : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            error  =  err [ " detail " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            error  =  str ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  Exception ( error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    data  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " openapi " :  res , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " info " :  res . get ( " info " ,  { } ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " specs " :  convert_openapi_to_tool_payload ( res ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    print ( " Fetched data: " ,  data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								async  def  get_tool_servers_data (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    servers :  List [ Dict [ str ,  Any ] ] ,  session_token :  Optional [ str ]  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  - >  List [ Dict [ str ,  Any ] ] :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Prepare list of enabled servers along with their original index 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    server_entries  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  idx ,  server  in  enumerate ( servers ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  server . get ( " config " ,  { } ) . get ( " enable " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            url_path  =  server . get ( " path " ,  " openapi.json " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            full_url  =  f " { server . get ( ' url ' ) } / { url_path } " 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            auth_type  =  server . get ( " auth_type " ,  " bearer " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            token  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  auth_type  ==  " bearer " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                token  =  server . get ( " key " ,  " " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  auth_type  ==  " session " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                token  =  session_token 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            server_entries . append ( ( idx ,  server ,  full_url ,  token ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Create async tasks to fetch data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    tasks  =  [ get_tool_server_data ( token ,  url )  for  ( _ ,  _ ,  url ,  token )  in  server_entries ] 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Execute tasks concurrently 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    responses  =  await  asyncio . gather ( * tasks ,  return_exceptions = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # Build final results with index and server metadata 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    results  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  ( idx ,  server ,  url ,  _ ) ,  response  in  zip ( server_entries ,  responses ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  isinstance ( response ,  Exception ) : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:40:01 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            print ( f " Failed to connect to  { url }  OpenAPI tool server " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        results . append ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                " idx " :  idx , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                " url " :  server . get ( " url " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                " openapi " :  response . get ( " openapi " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                " info " :  response . get ( " info " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                " specs " :  response . get ( " specs " ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ) 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  results 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								async  def  execute_tool_server (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    token :  str ,  url :  str ,  name :  str ,  params :  Dict [ str ,  Any ] ,  server_data :  Dict [ str ,  Any ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  - >  Any :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    error  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        openapi  =  server_data . get ( " openapi " ,  { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        paths  =  openapi . get ( " paths " ,  { } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        matching_route  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  route_path ,  methods  in  paths . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  http_method ,  operation  in  methods . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  isinstance ( operation ,  dict )  and  operation . get ( " operationId " )  ==  name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    matching_route  =  ( route_path ,  methods ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  matching_route : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  matching_route : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  Exception ( f " No matching route found for operationId:  { name } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        route_path ,  methods  =  matching_route 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        method_entry  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  http_method ,  operation  in  methods . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  operation . get ( " operationId " )  ==  name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                method_entry  =  ( http_method . lower ( ) ,  operation ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  method_entry : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  Exception ( f " No matching method found for operationId:  { name } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        http_method ,  operation  =  method_entry 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        path_params  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        query_params  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        body_params  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  param  in  operation . get ( " parameters " ,  [ ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            param_name  =  param [ " name " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            param_in  =  param [ " in " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  param_name  in  params : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  param_in  ==  " path " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    path_params [ param_name ]  =  params [ param_name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                elif  param_in  ==  " query " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    query_params [ param_name ]  =  params [ param_name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        final_url  =  f " { url } { route_path } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  key ,  value  in  path_params . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            final_url  =  final_url . replace ( f " {{ { key } }} " ,  str ( value ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  query_params : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            query_string  =  " & " . join ( f " { k } = { v } "  for  k ,  v  in  query_params . items ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            final_url  =  f " { final_url } ? { query_string } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  operation . get ( " requestBody " ,  { } ) . get ( " content " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  params : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                body_params  =  params 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                raise  Exception ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    f " Request body expected for operation  ' { name } '  but none found. " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        headers  =  { " Content-Type " :  " application/json " } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  token : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            headers [ " Authorization " ]  =  f " Bearer  { token } " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-04-18 13:02:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        async  with  aiohttp . ClientSession ( trust_env = True )  as  session : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            request_method  =  getattr ( session ,  http_method . lower ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  http_method  in  [ " post " ,  " put " ,  " patch " ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                async  with  request_method ( 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-18 13:02:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    final_url , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    json = body_params , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    headers = headers , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ssl = AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL , 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                )  as  response : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  response . status  > =  400 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        text  =  await  response . text ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        raise  Exception ( f " HTTP error  { response . status } :  { text } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return  await  response . json ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-18 13:02:16 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                async  with  request_method ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    final_url , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    headers = headers , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ssl = AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                )  as  response : 
							 
						 
					
						
							
								
									
										
										
										
											2025-04-05 18:05:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  response . status  > =  400 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        text  =  await  response . text ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        raise  Exception ( f " HTTP error  { response . status } :  { text } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    return  await  response . json ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    except  Exception  as  err : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        error  =  str ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print ( " API Request Error: " ,  error ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  { " error " :  error }