|
15 | 15 | import logging |
16 | 16 | from unittest import mock |
17 | 17 |
|
| 18 | +from google.adk.agents.readonly_context import ReadonlyContext |
18 | 19 | from google.adk.code_executors.base_code_executor import BaseCodeExecutor |
19 | 20 | from google.adk.code_executors.code_execution_utils import CodeExecutionResult |
20 | 21 | from google.adk.models import llm_request as llm_request_model |
@@ -1290,41 +1291,87 @@ async def test_execute_script_binary_content_packaged(): |
1290 | 1291 |
|
1291 | 1292 |
|
1292 | 1293 | @pytest.mark.asyncio |
1293 | | -async def test_skill_toolset_dynamic_tool_resolution(mock_skill1): |
1294 | | - # Set up a skill with additional_tools in metadata |
| 1294 | +async def test_skill_toolset_dynamic_tool_resolution(mock_skill1, mock_skill2): |
| 1295 | + # Set up skills with additional_tools in metadata |
1295 | 1296 | mock_skill1.frontmatter.metadata = { |
1296 | | - "adk_additional_tools": ["my_custom_tool", "my_func"] |
| 1297 | + "adk_additional_tools": ["my_custom_tool", "my_func", "shared_tool"] |
1297 | 1298 | } |
1298 | 1299 | mock_skill1.name = "skill1" |
1299 | 1300 |
|
| 1301 | + mock_skill2.frontmatter.metadata = { |
| 1302 | + "adk_additional_tools": [ |
| 1303 | + "skill2_tool", |
| 1304 | + "shared_tool", |
| 1305 | + "prefixed_mock_tool", |
| 1306 | + ] |
| 1307 | + } |
| 1308 | + mock_skill2.name = "skill2" |
| 1309 | + |
1300 | 1310 | # Prepare additional tools |
1301 | 1311 | custom_tool = mock.create_autospec(skill_toolset.BaseTool, instance=True) |
1302 | 1312 | custom_tool.name = "my_custom_tool" |
1303 | 1313 |
|
| 1314 | + skill2_tool = mock.create_autospec(skill_toolset.BaseTool, instance=True) |
| 1315 | + skill2_tool.name = "skill2_tool" |
| 1316 | + |
| 1317 | + shared_tool = mock.create_autospec(skill_toolset.BaseTool, instance=True) |
| 1318 | + shared_tool.name = "shared_tool" |
| 1319 | + |
1304 | 1320 | def my_func(): |
1305 | 1321 | """My function description.""" |
1306 | 1322 | pass |
1307 | 1323 |
|
| 1324 | + # Setup prefixed toolset |
| 1325 | + mock_tool = mock.create_autospec(skill_toolset.BaseTool, instance=True) |
| 1326 | + mock_tool.name = "prefixed_mock_tool" |
| 1327 | + prefixed_set = mock.create_autospec(skill_toolset.BaseToolset, instance=True) |
| 1328 | + prefixed_set.get_tools_with_prefix.return_value = [mock_tool] |
| 1329 | + |
1308 | 1330 | toolset = skill_toolset.SkillToolset( |
1309 | | - [mock_skill1], |
1310 | | - additional_tools=[custom_tool, my_func], |
| 1331 | + [mock_skill1, mock_skill2], |
| 1332 | + additional_tools=[ |
| 1333 | + custom_tool, |
| 1334 | + skill2_tool, |
| 1335 | + shared_tool, |
| 1336 | + my_func, |
| 1337 | + prefixed_set, |
| 1338 | + ], |
1311 | 1339 | ) |
1312 | 1340 |
|
1313 | 1341 | ctx = _make_tool_context_with_agent() |
1314 | 1342 | # Initial tools (only core) |
1315 | 1343 | tools = await toolset.get_tools(readonly_context=ctx) |
1316 | 1344 | assert len(tools) == 4 |
1317 | 1345 |
|
1318 | | - # Activate skill |
| 1346 | + # Activate skills |
1319 | 1347 | load_tool = skill_toolset.LoadSkillTool(toolset) |
1320 | 1348 | await load_tool.run_async(args={"name": "skill1"}, tool_context=ctx) |
| 1349 | + await load_tool.run_async(args={"name": "skill2"}, tool_context=ctx) |
1321 | 1350 |
|
1322 | 1351 | # Dynamic tools should now be resolved |
1323 | 1352 | tools = await toolset.get_tools(readonly_context=ctx) |
1324 | 1353 | tool_names = {t.name for t in tools} |
| 1354 | + |
| 1355 | + # Core tools |
| 1356 | + assert "list_skills" in tool_names |
| 1357 | + assert "load_skill" in tool_names |
| 1358 | + assert "load_skill_resource" in tool_names |
| 1359 | + assert "run_skill_script" in tool_names |
| 1360 | + |
| 1361 | + # Skill 1 tools |
1325 | 1362 | assert "my_custom_tool" in tool_names |
1326 | 1363 | assert "my_func" in tool_names |
1327 | 1364 |
|
| 1365 | + # Skill 2 tools |
| 1366 | + assert "skill2_tool" in tool_names |
| 1367 | + |
| 1368 | + # Shared tool (should only appear once) |
| 1369 | + assert "shared_tool" in tool_names |
| 1370 | + assert len([t for t in tools if t.name == "shared_tool"]) == 1 |
| 1371 | + |
| 1372 | + # Prefixed toolset tool |
| 1373 | + assert "prefixed_mock_tool" in tool_names |
| 1374 | + |
1328 | 1375 | # Check specific tool resolution details |
1329 | 1376 | my_func_tool = next(t for t in tools if t.name == "my_func") |
1330 | 1377 | assert isinstance(my_func_tool, skill_toolset.FunctionTool) |
|
0 commit comments