google-adk 0.5.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/adk/agents/base_agent.py +76 -30
- google/adk/agents/callback_context.py +2 -6
- google/adk/agents/llm_agent.py +122 -30
- google/adk/agents/loop_agent.py +1 -1
- google/adk/agents/parallel_agent.py +7 -0
- google/adk/agents/readonly_context.py +8 -0
- google/adk/agents/run_config.py +1 -1
- google/adk/agents/sequential_agent.py +31 -0
- google/adk/agents/transcription_entry.py +4 -2
- google/adk/artifacts/gcs_artifact_service.py +1 -1
- google/adk/artifacts/in_memory_artifact_service.py +1 -1
- google/adk/auth/auth_credential.py +10 -2
- google/adk/auth/auth_preprocessor.py +7 -1
- google/adk/auth/auth_tool.py +3 -4
- google/adk/cli/agent_graph.py +5 -5
- google/adk/cli/browser/index.html +4 -4
- google/adk/cli/browser/{main-ULN5R5I5.js → main-PKDNKWJE.js} +59 -60
- google/adk/cli/browser/polyfills-B6TNHZQ6.js +17 -0
- google/adk/cli/cli.py +10 -9
- google/adk/cli/cli_deploy.py +7 -2
- google/adk/cli/cli_eval.py +109 -115
- google/adk/cli/cli_tools_click.py +179 -67
- google/adk/cli/fast_api.py +248 -197
- google/adk/cli/utils/agent_loader.py +137 -0
- google/adk/cli/utils/cleanup.py +40 -0
- google/adk/cli/utils/common.py +23 -0
- google/adk/cli/utils/evals.py +83 -0
- google/adk/cli/utils/logs.py +8 -5
- google/adk/code_executors/__init__.py +3 -1
- google/adk/code_executors/built_in_code_executor.py +52 -0
- google/adk/code_executors/code_execution_utils.py +2 -1
- google/adk/code_executors/container_code_executor.py +0 -1
- google/adk/code_executors/vertex_ai_code_executor.py +6 -8
- google/adk/evaluation/__init__.py +1 -1
- google/adk/evaluation/agent_evaluator.py +168 -128
- google/adk/evaluation/eval_case.py +104 -0
- google/adk/evaluation/eval_metrics.py +74 -0
- google/adk/evaluation/eval_result.py +86 -0
- google/adk/evaluation/eval_set.py +39 -0
- google/adk/evaluation/eval_set_results_manager.py +47 -0
- google/adk/evaluation/eval_sets_manager.py +43 -0
- google/adk/evaluation/evaluation_generator.py +88 -113
- google/adk/evaluation/evaluator.py +58 -0
- google/adk/evaluation/local_eval_set_results_manager.py +113 -0
- google/adk/evaluation/local_eval_sets_manager.py +264 -0
- google/adk/evaluation/response_evaluator.py +106 -1
- google/adk/evaluation/trajectory_evaluator.py +84 -2
- google/adk/events/event.py +6 -1
- google/adk/events/event_actions.py +6 -1
- google/adk/examples/base_example_provider.py +1 -0
- google/adk/examples/example_util.py +3 -2
- google/adk/flows/llm_flows/_code_execution.py +9 -1
- google/adk/flows/llm_flows/audio_transcriber.py +4 -3
- google/adk/flows/llm_flows/base_llm_flow.py +58 -21
- google/adk/flows/llm_flows/contents.py +3 -1
- google/adk/flows/llm_flows/functions.py +9 -8
- google/adk/flows/llm_flows/instructions.py +18 -80
- google/adk/flows/llm_flows/single_flow.py +2 -2
- google/adk/memory/__init__.py +1 -1
- google/adk/memory/_utils.py +23 -0
- google/adk/memory/base_memory_service.py +23 -21
- google/adk/memory/in_memory_memory_service.py +57 -25
- google/adk/memory/memory_entry.py +37 -0
- google/adk/memory/vertex_ai_rag_memory_service.py +38 -15
- google/adk/models/anthropic_llm.py +16 -9
- google/adk/models/base_llm.py +2 -1
- google/adk/models/base_llm_connection.py +2 -0
- google/adk/models/gemini_llm_connection.py +11 -11
- google/adk/models/google_llm.py +12 -2
- google/adk/models/lite_llm.py +80 -23
- google/adk/models/llm_response.py +16 -3
- google/adk/models/registry.py +1 -1
- google/adk/runners.py +98 -42
- google/adk/sessions/__init__.py +1 -1
- google/adk/sessions/_session_util.py +2 -1
- google/adk/sessions/base_session_service.py +6 -33
- google/adk/sessions/database_session_service.py +57 -67
- google/adk/sessions/in_memory_session_service.py +106 -24
- google/adk/sessions/session.py +3 -0
- google/adk/sessions/vertex_ai_session_service.py +44 -51
- google/adk/telemetry.py +7 -2
- google/adk/tools/__init__.py +4 -7
- google/adk/tools/_memory_entry_utils.py +30 -0
- google/adk/tools/agent_tool.py +10 -10
- google/adk/tools/apihub_tool/apihub_toolset.py +55 -74
- google/adk/tools/apihub_tool/clients/apihub_client.py +10 -3
- google/adk/tools/apihub_tool/clients/secret_client.py +1 -0
- google/adk/tools/application_integration_tool/application_integration_toolset.py +111 -85
- google/adk/tools/application_integration_tool/clients/connections_client.py +28 -1
- google/adk/tools/application_integration_tool/clients/integration_client.py +7 -5
- google/adk/tools/application_integration_tool/integration_connector_tool.py +69 -26
- google/adk/tools/base_toolset.py +96 -0
- google/adk/tools/bigquery/__init__.py +28 -0
- google/adk/tools/bigquery/bigquery_credentials.py +216 -0
- google/adk/tools/bigquery/bigquery_tool.py +116 -0
- google/adk/tools/{built_in_code_execution_tool.py → enterprise_search_tool.py} +17 -11
- google/adk/tools/function_parameter_parse_util.py +9 -2
- google/adk/tools/function_tool.py +33 -3
- google/adk/tools/get_user_choice_tool.py +1 -0
- google/adk/tools/google_api_tool/__init__.py +24 -70
- google/adk/tools/google_api_tool/google_api_tool.py +12 -6
- google/adk/tools/google_api_tool/{google_api_tool_set.py → google_api_toolset.py} +57 -55
- google/adk/tools/google_api_tool/google_api_toolsets.py +108 -0
- google/adk/tools/google_api_tool/googleapi_to_openapi_converter.py +40 -42
- google/adk/tools/google_search_tool.py +2 -2
- google/adk/tools/langchain_tool.py +96 -49
- google/adk/tools/load_memory_tool.py +14 -5
- google/adk/tools/mcp_tool/__init__.py +3 -2
- google/adk/tools/mcp_tool/conversion_utils.py +6 -2
- google/adk/tools/mcp_tool/mcp_session_manager.py +80 -69
- google/adk/tools/mcp_tool/mcp_tool.py +35 -32
- google/adk/tools/mcp_tool/mcp_toolset.py +99 -194
- google/adk/tools/openapi_tool/auth/credential_exchangers/base_credential_exchanger.py +1 -3
- google/adk/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.py +6 -7
- google/adk/tools/openapi_tool/common/common.py +5 -1
- google/adk/tools/openapi_tool/openapi_spec_parser/__init__.py +7 -2
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +27 -7
- google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +36 -32
- google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +11 -1
- google/adk/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.py +1 -1
- google/adk/tools/preload_memory_tool.py +27 -18
- google/adk/tools/retrieval/__init__.py +1 -1
- google/adk/tools/retrieval/vertex_ai_rag_retrieval.py +1 -1
- google/adk/tools/toolbox_toolset.py +107 -0
- google/adk/tools/transfer_to_agent_tool.py +0 -1
- google/adk/utils/__init__.py +13 -0
- google/adk/utils/instructions_utils.py +131 -0
- google/adk/version.py +1 -1
- {google_adk-0.5.0.dist-info → google_adk-1.1.0.dist-info}/METADATA +18 -19
- google_adk-1.1.0.dist-info/RECORD +200 -0
- google/adk/agents/remote_agent.py +0 -50
- google/adk/cli/browser/polyfills-FFHMD2TL.js +0 -18
- google/adk/cli/fast_api.py.orig +0 -728
- google/adk/tools/google_api_tool/google_api_tool_sets.py +0 -112
- google/adk/tools/toolbox_tool.py +0 -46
- google_adk-0.5.0.dist-info/RECORD +0 -180
- {google_adk-0.5.0.dist-info → google_adk-1.1.0.dist-info}/WHEEL +0 -0
- {google_adk-0.5.0.dist-info → google_adk-1.1.0.dist-info}/entry_points.txt +0 -0
- {google_adk-0.5.0.dist-info → google_adk-1.1.0.dist-info}/licenses/LICENSE +0 -0
@@ -12,255 +12,160 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
|
15
|
+
import logging
|
16
16
|
import sys
|
17
|
-
from
|
18
|
-
from typing import
|
19
|
-
|
20
|
-
from
|
17
|
+
from typing import List
|
18
|
+
from typing import Optional
|
19
|
+
from typing import TextIO
|
20
|
+
from typing import Union
|
21
|
+
|
22
|
+
from ...agents.readonly_context import ReadonlyContext
|
23
|
+
from ..base_tool import BaseTool
|
24
|
+
from ..base_toolset import BaseToolset
|
25
|
+
from ..base_toolset import ToolPredicate
|
26
|
+
from .mcp_session_manager import MCPSessionManager
|
27
|
+
from .mcp_session_manager import retry_on_closed_resource
|
28
|
+
from .mcp_session_manager import SseServerParams
|
21
29
|
|
22
30
|
# Attempt to import MCP Tool from the MCP library, and hints user to upgrade
|
23
31
|
# their Python version to 3.10 if it fails.
|
24
32
|
try:
|
25
|
-
from mcp import
|
33
|
+
from mcp import StdioServerParameters
|
26
34
|
from mcp.types import ListToolsResult
|
27
35
|
except ImportError as e:
|
28
36
|
import sys
|
29
37
|
|
30
38
|
if sys.version_info < (3, 10):
|
31
39
|
raise ImportError(
|
32
|
-
|
33
|
-
|
40
|
+
"MCP Tool requires Python 3.10 or above. Please upgrade your Python"
|
41
|
+
" version."
|
34
42
|
) from e
|
35
43
|
else:
|
36
44
|
raise e
|
37
45
|
|
38
46
|
from .mcp_tool import MCPTool
|
39
47
|
|
48
|
+
logger = logging.getLogger("google_adk." + __name__)
|
49
|
+
|
40
50
|
|
41
|
-
class MCPToolset:
|
51
|
+
class MCPToolset(BaseToolset):
|
42
52
|
"""Connects to a MCP Server, and retrieves MCP Tools into ADK Tools.
|
43
53
|
|
54
|
+
This toolset manages the connection to an MCP server and provides tools
|
55
|
+
that can be used by an agent. It properly implements the BaseToolset
|
56
|
+
interface for easy integration with the agent framework.
|
57
|
+
|
44
58
|
Usage:
|
45
|
-
|
46
|
-
|
47
|
-
async def load_tools():
|
48
|
-
return await MCPToolset.from_server(
|
59
|
+
```python
|
60
|
+
toolset = MCPToolset(
|
49
61
|
connection_params=StdioServerParameters(
|
50
62
|
command='npx',
|
51
63
|
args=["-y", "@modelcontextprotocol/server-filesystem"],
|
52
|
-
|
53
|
-
|
64
|
+
),
|
65
|
+
tool_filter=['read_file', 'list_directory'] # Optional: filter specific tools
|
66
|
+
)
|
54
67
|
|
55
|
-
# Use
|
56
|
-
tools, exit_stack = await load_tools()
|
68
|
+
# Use in an agent
|
57
69
|
agent = LlmAgent(
|
58
|
-
|
70
|
+
model='gemini-2.0-flash',
|
71
|
+
name='enterprise_assistant',
|
72
|
+
instruction='Help user accessing their file systems',
|
73
|
+
tools=[toolset],
|
59
74
|
)
|
60
|
-
...
|
61
|
-
await exit_stack.aclose()
|
62
|
-
```
|
63
|
-
|
64
|
-
Example 2: (using `async with`):
|
65
|
-
|
66
|
-
```
|
67
|
-
async def load_tools():
|
68
|
-
async with MCPToolset(
|
69
|
-
connection_params=SseServerParams(url="http://0.0.0.0:8090/sse")
|
70
|
-
) as toolset:
|
71
|
-
tools = await toolset.load_tools()
|
72
|
-
|
73
|
-
agent = LlmAgent(
|
74
|
-
...
|
75
|
-
tools=tools
|
76
|
-
)
|
77
|
-
```
|
78
|
-
|
79
|
-
Example 3: (provide AsyncExitStack):
|
80
|
-
```
|
81
|
-
async def load_tools():
|
82
|
-
async_exit_stack = AsyncExitStack()
|
83
|
-
toolset = MCPToolset(
|
84
|
-
connection_params=StdioServerParameters(...),
|
85
|
-
)
|
86
|
-
async_exit_stack.enter_async_context(toolset)
|
87
|
-
tools = await toolset.load_tools()
|
88
|
-
agent = LlmAgent(
|
89
|
-
...
|
90
|
-
tools=tools
|
91
|
-
)
|
92
|
-
...
|
93
|
-
await async_exit_stack.aclose()
|
94
75
|
|
76
|
+
# Cleanup is handled automatically by the agent framework
|
77
|
+
# But you can also manually close if needed:
|
78
|
+
# await toolset.close()
|
95
79
|
```
|
96
|
-
|
97
|
-
Attributes:
|
98
|
-
connection_params: The connection parameters to the MCP server. Can be
|
99
|
-
either `StdioServerParameters` or `SseServerParams`.
|
100
|
-
exit_stack: The async exit stack to manage the connection to the MCP server.
|
101
|
-
session: The MCP session being initialized with the connection.
|
102
80
|
"""
|
103
81
|
|
104
82
|
def __init__(
|
105
83
|
self,
|
106
84
|
*,
|
107
85
|
connection_params: StdioServerParameters | SseServerParams,
|
86
|
+
tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
|
108
87
|
errlog: TextIO = sys.stderr,
|
109
|
-
exit_stack=AsyncExitStack(),
|
110
88
|
):
|
111
89
|
"""Initializes the MCPToolset.
|
112
90
|
|
113
|
-
Usage:
|
114
|
-
Example 1: (using from_server helper):
|
115
|
-
```
|
116
|
-
async def load_tools():
|
117
|
-
return await MCPToolset.from_server(
|
118
|
-
connection_params=StdioServerParameters(
|
119
|
-
command='npx',
|
120
|
-
args=["-y", "@modelcontextprotocol/server-filesystem"],
|
121
|
-
)
|
122
|
-
)
|
123
|
-
|
124
|
-
# Use the tools in an LLM agent
|
125
|
-
tools, exit_stack = await load_tools()
|
126
|
-
agent = LlmAgent(
|
127
|
-
tools=tools
|
128
|
-
)
|
129
|
-
...
|
130
|
-
await exit_stack.aclose()
|
131
|
-
```
|
132
|
-
|
133
|
-
Example 2: (using `async with`):
|
134
|
-
|
135
|
-
```
|
136
|
-
async def load_tools():
|
137
|
-
async with MCPToolset(
|
138
|
-
connection_params=SseServerParams(url="http://0.0.0.0:8090/sse")
|
139
|
-
) as toolset:
|
140
|
-
tools = await toolset.load_tools()
|
141
|
-
|
142
|
-
agent = LlmAgent(
|
143
|
-
...
|
144
|
-
tools=tools
|
145
|
-
)
|
146
|
-
```
|
147
|
-
|
148
|
-
Example 3: (provide AsyncExitStack):
|
149
|
-
```
|
150
|
-
async def load_tools():
|
151
|
-
async_exit_stack = AsyncExitStack()
|
152
|
-
toolset = MCPToolset(
|
153
|
-
connection_params=StdioServerParameters(...),
|
154
|
-
)
|
155
|
-
async_exit_stack.enter_async_context(toolset)
|
156
|
-
tools = await toolset.load_tools()
|
157
|
-
agent = LlmAgent(
|
158
|
-
...
|
159
|
-
tools=tools
|
160
|
-
)
|
161
|
-
...
|
162
|
-
await async_exit_stack.aclose()
|
163
|
-
|
164
|
-
```
|
165
|
-
|
166
91
|
Args:
|
167
|
-
|
168
|
-
|
169
|
-
|
92
|
+
connection_params: The connection parameters to the MCP server. Can be:
|
93
|
+
`StdioServerParameters` for using local mcp server (e.g. using `npx` or
|
94
|
+
`python3`); or `SseServerParams` for a local/remote SSE server.
|
95
|
+
tool_filter: Optional filter to select specific tools. Can be either:
|
96
|
+
- A list of tool names to include
|
97
|
+
- A ToolPredicate function for custom filtering logic
|
98
|
+
errlog: TextIO stream for error logging.
|
170
99
|
"""
|
100
|
+
super().__init__(tool_filter=tool_filter)
|
101
|
+
|
171
102
|
if not connection_params:
|
172
|
-
raise ValueError(
|
173
|
-
self.connection_params = connection_params
|
174
|
-
self.errlog = errlog
|
175
|
-
self.exit_stack = exit_stack
|
103
|
+
raise ValueError("Missing connection params in MCPToolset.")
|
176
104
|
|
177
|
-
self.
|
178
|
-
|
179
|
-
exit_stack=self.exit_stack,
|
180
|
-
errlog=self.errlog,
|
181
|
-
)
|
105
|
+
self._connection_params = connection_params
|
106
|
+
self._errlog = errlog
|
182
107
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
errlog: TextIO = sys.stderr,
|
190
|
-
) -> Tuple[List[MCPTool], AsyncExitStack]:
|
191
|
-
"""Retrieve all tools from the MCP connection.
|
108
|
+
# Create the session manager that will handle the MCP connection
|
109
|
+
self._mcp_session_manager = MCPSessionManager(
|
110
|
+
connection_params=self._connection_params,
|
111
|
+
errlog=self._errlog,
|
112
|
+
)
|
113
|
+
self._session = None
|
192
114
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
args=["-y", "@modelcontextprotocol/server-filesystem"],
|
200
|
-
)
|
201
|
-
)
|
202
|
-
```
|
115
|
+
@retry_on_closed_resource("_reinitialize_session")
|
116
|
+
async def get_tools(
|
117
|
+
self,
|
118
|
+
readonly_context: Optional[ReadonlyContext] = None,
|
119
|
+
) -> List[BaseTool]:
|
120
|
+
"""Return all tools in the toolset based on the provided context.
|
203
121
|
|
204
122
|
Args:
|
205
|
-
|
206
|
-
|
207
|
-
AsyncExitStack will be created.
|
123
|
+
readonly_context: Context used to filter tools available to the agent.
|
124
|
+
If None, all tools in the toolset are returned.
|
208
125
|
|
209
126
|
Returns:
|
210
|
-
|
211
|
-
- tools: The list of MCPTools.
|
212
|
-
- async_exit_stack: The AsyncExitStack used to manage the connection to
|
213
|
-
the MCP server. Use `await async_exit_stack.aclose()` to close the
|
214
|
-
connection when server shuts down.
|
127
|
+
List[BaseTool]: A list of tools available under the specified context.
|
215
128
|
"""
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
)
|
129
|
+
# Get session from session manager
|
130
|
+
if not self._session:
|
131
|
+
self._session = await self._mcp_session_manager.create_session()
|
132
|
+
|
133
|
+
# Fetch available tools from the MCP server
|
134
|
+
tools_response: ListToolsResult = await self._session.list_tools()
|
135
|
+
|
136
|
+
# Apply filtering based on context and tool_filter
|
137
|
+
tools = []
|
138
|
+
for tool in tools_response.tools:
|
139
|
+
mcp_tool = MCPTool(
|
140
|
+
mcp_tool=tool,
|
141
|
+
mcp_session_manager=self._mcp_session_manager,
|
142
|
+
)
|
222
143
|
|
223
|
-
|
224
|
-
|
225
|
-
return
|
144
|
+
if self._is_tool_selected(mcp_tool, readonly_context):
|
145
|
+
tools.append(mcp_tool)
|
146
|
+
return tools
|
226
147
|
|
227
|
-
async def
|
228
|
-
"""
|
229
|
-
|
230
|
-
|
148
|
+
async def _reinitialize_session(self):
|
149
|
+
"""Reinitializes the session when connection is lost."""
|
150
|
+
# Close the old session and clear cache
|
151
|
+
await self._mcp_session_manager.close()
|
152
|
+
self._session = await self._mcp_session_manager.create_session()
|
231
153
|
|
232
|
-
|
233
|
-
"""Closes the connection to MCP Server."""
|
234
|
-
await self.exit_stack.aclose()
|
154
|
+
# Tools will be reloaded on next get_tools call
|
235
155
|
|
236
|
-
|
237
|
-
|
238
|
-
"""Loads all tools from the MCP Server.
|
156
|
+
async def close(self) -> None:
|
157
|
+
"""Performs cleanup and releases resources held by the toolset.
|
239
158
|
|
240
|
-
|
241
|
-
|
159
|
+
This method closes the MCP session and cleans up all associated resources.
|
160
|
+
It's designed to be safe to call multiple times and handles cleanup errors
|
161
|
+
gracefully to avoid blocking application shutdown.
|
242
162
|
"""
|
243
|
-
tools_response: ListToolsResult = await self.session.list_tools()
|
244
|
-
return [
|
245
|
-
MCPTool(
|
246
|
-
mcp_tool=tool,
|
247
|
-
mcp_session=self.session,
|
248
|
-
mcp_session_manager=self.session_manager,
|
249
|
-
)
|
250
|
-
for tool in tools_response.tools
|
251
|
-
]
|
252
|
-
|
253
|
-
async def __aenter__(self):
|
254
163
|
try:
|
255
|
-
await self.
|
256
|
-
return self
|
164
|
+
await self._mcp_session_manager.close()
|
257
165
|
except Exception as e:
|
258
|
-
raise
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
tb: Optional[TracebackType],
|
265
|
-
) -> None:
|
266
|
-
await self._exit()
|
166
|
+
# Log the error but don't re-raise to avoid blocking shutdown
|
167
|
+
print(f"Warning: Error during MCPToolset cleanup: {e}", file=self._errlog)
|
168
|
+
finally:
|
169
|
+
# Clear cached tools
|
170
|
+
self._tools_cache = None
|
171
|
+
self._tools_loaded = False
|
@@ -21,14 +21,13 @@ from google.auth.transport.requests import Request
|
|
21
21
|
from google.oauth2 import service_account
|
22
22
|
import google.oauth2.credentials
|
23
23
|
|
24
|
-
from .....auth.auth_credential import
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
HttpCredentials,
|
29
|
-
)
|
24
|
+
from .....auth.auth_credential import AuthCredential
|
25
|
+
from .....auth.auth_credential import AuthCredentialTypes
|
26
|
+
from .....auth.auth_credential import HttpAuth
|
27
|
+
from .....auth.auth_credential import HttpCredentials
|
30
28
|
from .....auth.auth_schemes import AuthScheme
|
31
|
-
from .base_credential_exchanger import AuthCredentialMissingError
|
29
|
+
from .base_credential_exchanger import AuthCredentialMissingError
|
30
|
+
from .base_credential_exchanger import BaseAuthCredentialExchanger
|
32
31
|
|
33
32
|
|
34
33
|
class ServiceAccountCredentialExchanger(BaseAuthCredentialExchanger):
|
@@ -14,7 +14,11 @@
|
|
14
14
|
|
15
15
|
import keyword
|
16
16
|
import re
|
17
|
-
from typing import Any
|
17
|
+
from typing import Any
|
18
|
+
from typing import Dict
|
19
|
+
from typing import List
|
20
|
+
from typing import Optional
|
21
|
+
from typing import Union
|
18
22
|
|
19
23
|
from fastapi.openapi.models import Response
|
20
24
|
from fastapi.openapi.models import Schema
|
@@ -12,10 +12,15 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
from .openapi_spec_parser import OpenApiSpecParser
|
15
|
+
from .openapi_spec_parser import OpenApiSpecParser
|
16
|
+
from .openapi_spec_parser import OperationEndpoint
|
17
|
+
from .openapi_spec_parser import ParsedOperation
|
16
18
|
from .openapi_toolset import OpenAPIToolset
|
17
19
|
from .operation_parser import OperationParser
|
18
|
-
from .rest_api_tool import AuthPreparationState
|
20
|
+
from .rest_api_tool import AuthPreparationState
|
21
|
+
from .rest_api_tool import RestApiTool
|
22
|
+
from .rest_api_tool import snake_to_lower_camel
|
23
|
+
from .rest_api_tool import to_gemini_schema
|
19
24
|
from .tool_auth_handler import ToolAuthHandler
|
20
25
|
|
21
26
|
__all__ = [
|
@@ -20,18 +20,23 @@ from typing import Final
|
|
20
20
|
from typing import List
|
21
21
|
from typing import Literal
|
22
22
|
from typing import Optional
|
23
|
+
from typing import Union
|
23
24
|
|
25
|
+
from typing_extensions import override
|
24
26
|
import yaml
|
25
27
|
|
28
|
+
from ....agents.readonly_context import ReadonlyContext
|
26
29
|
from ....auth.auth_credential import AuthCredential
|
27
30
|
from ....auth.auth_schemes import AuthScheme
|
31
|
+
from ...base_toolset import BaseToolset
|
32
|
+
from ...base_toolset import ToolPredicate
|
28
33
|
from .openapi_spec_parser import OpenApiSpecParser
|
29
34
|
from .rest_api_tool import RestApiTool
|
30
35
|
|
31
|
-
logger = logging.getLogger(__name__)
|
36
|
+
logger = logging.getLogger("google_adk." + __name__)
|
32
37
|
|
33
38
|
|
34
|
-
class OpenAPIToolset:
|
39
|
+
class OpenAPIToolset(BaseToolset):
|
35
40
|
"""Class for parsing OpenAPI spec into a list of RestApiTool.
|
36
41
|
|
37
42
|
Usage:
|
@@ -61,6 +66,7 @@ class OpenAPIToolset:
|
|
61
66
|
spec_str_type: Literal["json", "yaml"] = "json",
|
62
67
|
auth_scheme: Optional[AuthScheme] = None,
|
63
68
|
auth_credential: Optional[AuthCredential] = None,
|
69
|
+
tool_filter: Optional[Union[ToolPredicate, List[str]]] = None,
|
64
70
|
):
|
65
71
|
"""Initializes the OpenAPIToolset.
|
66
72
|
|
@@ -94,10 +100,13 @@ class OpenAPIToolset:
|
|
94
100
|
auth_credential: The auth credential to use for all tools. Use
|
95
101
|
AuthCredential or use helpers in
|
96
102
|
`google.adk.tools.openapi_tool.auth.auth_helpers`
|
103
|
+
tool_filter: The filter used to filter the tools in the toolset. It can be
|
104
|
+
either a tool predicate or a list of tool names of the tools to expose.
|
97
105
|
"""
|
106
|
+
super().__init__(tool_filter=tool_filter)
|
98
107
|
if not spec_dict:
|
99
108
|
spec_dict = self._load_spec(spec_str, spec_str_type)
|
100
|
-
self.
|
109
|
+
self._tools: Final[List[RestApiTool]] = list(self._parse(spec_dict))
|
101
110
|
if auth_scheme or auth_credential:
|
102
111
|
self._configure_auth_all(auth_scheme, auth_credential)
|
103
112
|
|
@@ -106,19 +115,26 @@ class OpenAPIToolset:
|
|
106
115
|
):
|
107
116
|
"""Configure auth scheme and credential for all tools."""
|
108
117
|
|
109
|
-
for tool in self.
|
118
|
+
for tool in self._tools:
|
110
119
|
if auth_scheme:
|
111
120
|
tool.configure_auth_scheme(auth_scheme)
|
112
121
|
if auth_credential:
|
113
122
|
tool.configure_auth_credential(auth_credential)
|
114
123
|
|
115
|
-
|
124
|
+
@override
|
125
|
+
async def get_tools(
|
126
|
+
self, readonly_context: Optional[ReadonlyContext] = None
|
127
|
+
) -> List[RestApiTool]:
|
116
128
|
"""Get all tools in the toolset."""
|
117
|
-
return
|
129
|
+
return [
|
130
|
+
tool
|
131
|
+
for tool in self._tools
|
132
|
+
if self._is_tool_selected(tool, readonly_context)
|
133
|
+
]
|
118
134
|
|
119
135
|
def get_tool(self, tool_name: str) -> Optional[RestApiTool]:
|
120
136
|
"""Get a tool by name."""
|
121
|
-
matching_tool = filter(lambda t: t.name == tool_name, self.
|
137
|
+
matching_tool = filter(lambda t: t.name == tool_name, self._tools)
|
122
138
|
return next(matching_tool, None)
|
123
139
|
|
124
140
|
def _load_spec(
|
@@ -142,3 +158,7 @@ class OpenAPIToolset:
|
|
142
158
|
logger.info("Parsed tool: %s", tool.name)
|
143
159
|
tools.append(tool)
|
144
160
|
return tools
|
161
|
+
|
162
|
+
@override
|
163
|
+
async def close(self):
|
164
|
+
pass
|