11import asyncio
22import json
3+ import os
34from typing import Any
45
56from arcadepy import AsyncArcade
67
78
8- def convert_output_to_json (output : Any ) -> str :
9- if isinstance (output , dict ) or isinstance (output , list ):
10- return json .dumps (output )
11- else :
12- return str (output )
9+ def get_arcade_client (
10+ base_url : str = "https://api.arcade.dev" ,
11+ api_key : str = os .getenv ("ARCADE_API_KEY" , None ),
12+ ** kwargs : dict [str , Any ],
13+ ) -> AsyncArcade :
14+ """
15+ Returns an AsyncArcade client.
16+ """
17+ if api_key is None :
18+ raise ValueError ("ARCADE_API_KEY is not set" )
19+ return AsyncArcade (base_url = base_url , api_key = api_key , ** kwargs )
20+
21+
22+ async def _get_arcade_tool_formats (
23+ client : AsyncArcade ,
24+ tools : list [str ] | None = None ,
25+ toolkits : list [str ] | None = None ,
26+ raise_on_empty : bool = True ,
27+ ) -> list :
28+ """
29+ Asynchronously fetches tool definitions for each toolkit using client.tools.list,
30+ and returns a list of formatted tools respecting OpenAI's formatting.
31+
32+ Args:
33+ client: AsyncArcade client
34+ tools: Optional list of specific tool names to include.
35+ toolkits: Optional list of toolkit names to include all tools from.
36+ raise_on_empty: Whether to raise an error if no tools or toolkits are provided.
1337
38+ Returns:
39+ A list of formatted tools respecting OpenAI's formatting.
40+ """
41+ if not tools and not toolkits :
42+ if raise_on_empty :
43+ raise ValueError (
44+ "No tools or toolkits provided to retrieve tool definitions" )
45+ return {}
46+
47+ all_tool_formats = []
48+ # Retrieve individual tools if specified
49+ if tools :
50+ tasks = [client .tools .formatted .get (name = tool_id , format = "openai" )
51+ for tool_id in tools ]
52+ responses = await asyncio .gather (* tasks )
53+ for response in responses :
54+ all_tool_formats .append (response )
55+
56+ # Retrieve tools from specified toolkits
57+ if toolkits :
58+ # Create a task for each toolkit to fetch its tool definitions concurrently.
59+ tasks = [client .tools .formatted .list (toolkit = tk , format = "openai" )
60+ for tk in toolkits ]
61+ responses = await asyncio .gather (* tasks )
62+
63+ # Combine the tool definitions from each response.
64+ for response in responses :
65+ # Here we assume the returned response has an "items" attribute
66+ # containing a list of ToolDefinition objects.
67+ all_tool_formats .extend (response .items )
1468
15- async def get_arcade_client () -> AsyncArcade :
16- return AsyncArcade ()
69+ return all_tool_formats
1770
1871
1972async def _get_arcade_tool_definitions (
20- client : AsyncArcade , toolkits : list [str ], tools : list [str ] | None = None
73+ client : AsyncArcade ,
74+ tools : list [str ] | None = None ,
75+ toolkits : list [str ] | None = None ,
76+ raise_on_empty : bool = True ,
2177) -> dict [str , bool ]:
2278 """
2379 Asynchronously fetches tool definitions for each toolkit using client.tools.list,
@@ -26,30 +82,55 @@ async def _get_arcade_tool_definitions(
2682
2783 Args:
2884 client: AsyncArcade client
29- toolkits: List of toolkit names to get tools from
30- tools: Optional list of specific tool names to include. If None, all tools are included.
85+ tools: Optional list of specific tool names to include.
86+ toolkits: Optional list of toolkit names to include all tools from.
87+ raise_on_empty: Whether to raise an error if no tools or toolkits are provided.
88+
89+ Returns:
90+ A dictionary mapping each tool's name to a boolean indicating whether the
91+ tool requires authorization.
3192 """
32- # Create a task for each toolkit to fetch its tool definitions concurrently.
33- tasks = [client .tools .list (toolkit = toolkit ) for toolkit in toolkits ]
34- responses = await asyncio .gather (* tasks )
93+ if not tools and not toolkits :
94+ if raise_on_empty :
95+ raise ValueError (
96+ "No tools or toolkits provided to retrieve tool definitions" )
97+ return {}
3598
36- # Combine the tool definitions from each response.
3799 all_tool_definitions = []
38- for response in responses :
39- # Here we assume the returned response has an "items" attribute
40- # containing a list of ToolDefinition objects.
41- all_tool_definitions .extend (response .items )
100+ # Retrieve individual tools if specified
101+ if tools :
102+ tasks = [client .tools .get (name = tool_id ) for tool_id in tools ]
103+ responses = await asyncio .gather (* tasks )
104+ for response in responses :
105+ all_tool_definitions .append (response )
106+
107+ # Retrieve tools from specified toolkits
108+ if toolkits :
109+ # Create a task for each toolkit to fetch its tool definitions concurrently.
110+ tasks = [client .tools .list (toolkit = toolkit ) for toolkit in toolkits ]
111+ responses = await asyncio .gather (* tasks )
112+
113+ # Combine the tool definitions from each response.
114+ for response in responses :
115+ # Here we assume the returned response has an "items" attribute
116+ # containing a list of ToolDefinition objects.
117+ all_tool_definitions .extend (response .items )
42118
43119 # Create dictionary mapping tool name to a boolean for whether authorization is required.
44120 tool_auth_requirements = {}
45121 for tool_def in all_tool_definitions :
46- # If tools is None, include all tools
47- # If tools is not None, only include tools in the list
48- if tools is None or tool_def .name in tools :
49- # A tool requires authorization if its requirements exist and its
50- # authorization is not None.
51- requires_auth = bool (tool_def .requirements and tool_def .requirements .authorization )
52- tool_name = "_" .join ((tool_def .toolkit .name , tool_def .name ))
53- tool_auth_requirements [tool_name ] = requires_auth
122+ # A tool requires authorization if its requirements exist and its
123+ # authorization is not None.
124+ requires_auth = bool (
125+ tool_def .requirements and tool_def .requirements .authorization )
126+ tool_name = "_" .join ((tool_def .toolkit .name , tool_def .name ))
127+ tool_auth_requirements [tool_name ] = requires_auth
54128
55129 return tool_auth_requirements
130+
131+
132+ def convert_output_to_json (output : Any ) -> str :
133+ if isinstance (output , dict ) or isinstance (output , list ):
134+ return json .dumps (output )
135+ else :
136+ return str (output )
0 commit comments