google-adk 0.0.1__py3-none-any.whl → 0.0.2__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/__init__.py +20 -0
- google/adk/agents/__init__.py +32 -0
- google/adk/agents/active_streaming_tool.py +38 -0
- google/adk/agents/base_agent.py +345 -0
- google/adk/agents/callback_context.py +112 -0
- google/adk/agents/invocation_context.py +181 -0
- google/adk/agents/langgraph_agent.py +140 -0
- google/adk/agents/live_request_queue.py +64 -0
- google/adk/agents/llm_agent.py +376 -0
- google/adk/agents/loop_agent.py +62 -0
- google/adk/agents/parallel_agent.py +96 -0
- google/adk/agents/readonly_context.py +46 -0
- google/adk/agents/remote_agent.py +50 -0
- google/adk/agents/run_config.py +87 -0
- google/adk/agents/sequential_agent.py +45 -0
- google/adk/agents/transcription_entry.py +34 -0
- google/adk/artifacts/__init__.py +23 -0
- google/adk/artifacts/base_artifact_service.py +128 -0
- google/adk/artifacts/gcs_artifact_service.py +195 -0
- google/adk/artifacts/in_memory_artifact_service.py +133 -0
- google/adk/auth/__init__.py +22 -0
- google/adk/auth/auth_credential.py +220 -0
- google/adk/auth/auth_handler.py +268 -0
- google/adk/auth/auth_preprocessor.py +116 -0
- google/adk/auth/auth_schemes.py +67 -0
- google/adk/auth/auth_tool.py +55 -0
- google/adk/cli/__init__.py +15 -0
- google/adk/cli/__main__.py +18 -0
- google/adk/cli/agent_graph.py +122 -0
- google/adk/cli/browser/adk_favicon.svg +17 -0
- google/adk/cli/browser/assets/audio-processor.js +51 -0
- google/adk/cli/browser/assets/config/runtime-config.json +3 -0
- google/adk/cli/browser/index.html +33 -0
- google/adk/cli/browser/main-XUU6OGCC.js +75 -0
- google/adk/cli/browser/polyfills-FFHMD2TL.js +18 -0
- google/adk/cli/browser/styles-4VDSPQ37.css +17 -0
- google/adk/cli/cli.py +181 -0
- google/adk/cli/cli_deploy.py +181 -0
- google/adk/cli/cli_eval.py +282 -0
- google/adk/cli/cli_tools_click.py +479 -0
- google/adk/cli/fast_api.py +774 -0
- google/adk/cli/media_streamer/__init__.py +19 -0
- google/adk/cli/media_streamer/index.html +228 -0
- google/adk/cli/utils/__init__.py +49 -0
- google/adk/cli/utils/envs.py +57 -0
- google/adk/cli/utils/evals.py +93 -0
- google/adk/cli/utils/logs.py +72 -0
- google/adk/code_executors/__init__.py +49 -0
- google/adk/code_executors/base_code_executor.py +97 -0
- google/adk/code_executors/code_execution_utils.py +256 -0
- google/adk/code_executors/code_executor_context.py +202 -0
- google/adk/code_executors/container_code_executor.py +196 -0
- google/adk/code_executors/unsafe_local_code_executor.py +71 -0
- google/adk/code_executors/vertex_ai_code_executor.py +234 -0
- google/adk/evaluation/__init__.py +31 -0
- google/adk/evaluation/agent_evaluator.py +329 -0
- google/adk/evaluation/evaluation_constants.py +24 -0
- google/adk/evaluation/evaluation_generator.py +270 -0
- google/adk/evaluation/response_evaluator.py +135 -0
- google/adk/evaluation/trajectory_evaluator.py +184 -0
- google/adk/events/__init__.py +21 -0
- google/adk/events/event.py +130 -0
- google/adk/events/event_actions.py +55 -0
- google/adk/examples/__init__.py +28 -0
- google/adk/examples/base_example_provider.py +35 -0
- google/adk/examples/example.py +27 -0
- google/adk/examples/example_util.py +123 -0
- google/adk/examples/vertex_ai_example_store.py +104 -0
- google/adk/flows/__init__.py +14 -0
- google/adk/flows/llm_flows/__init__.py +20 -0
- google/adk/flows/llm_flows/_base_llm_processor.py +52 -0
- google/adk/flows/llm_flows/_code_execution.py +458 -0
- google/adk/flows/llm_flows/_nl_planning.py +129 -0
- google/adk/flows/llm_flows/agent_transfer.py +132 -0
- google/adk/flows/llm_flows/audio_transcriber.py +109 -0
- google/adk/flows/llm_flows/auto_flow.py +49 -0
- google/adk/flows/llm_flows/base_llm_flow.py +559 -0
- google/adk/flows/llm_flows/basic.py +72 -0
- google/adk/flows/llm_flows/contents.py +370 -0
- google/adk/flows/llm_flows/functions.py +486 -0
- google/adk/flows/llm_flows/identity.py +47 -0
- google/adk/flows/llm_flows/instructions.py +137 -0
- google/adk/flows/llm_flows/single_flow.py +57 -0
- google/adk/memory/__init__.py +35 -0
- google/adk/memory/base_memory_service.py +74 -0
- google/adk/memory/in_memory_memory_service.py +62 -0
- google/adk/memory/vertex_ai_rag_memory_service.py +177 -0
- google/adk/models/__init__.py +31 -0
- google/adk/models/anthropic_llm.py +243 -0
- google/adk/models/base_llm.py +87 -0
- google/adk/models/base_llm_connection.py +76 -0
- google/adk/models/gemini_llm_connection.py +200 -0
- google/adk/models/google_llm.py +331 -0
- google/adk/models/lite_llm.py +673 -0
- google/adk/models/llm_request.py +98 -0
- google/adk/models/llm_response.py +111 -0
- google/adk/models/registry.py +102 -0
- google/adk/planners/__init__.py +23 -0
- google/adk/planners/base_planner.py +66 -0
- google/adk/planners/built_in_planner.py +75 -0
- google/adk/planners/plan_re_act_planner.py +208 -0
- google/adk/runners.py +456 -0
- google/adk/sessions/__init__.py +41 -0
- google/adk/sessions/base_session_service.py +133 -0
- google/adk/sessions/database_session_service.py +522 -0
- google/adk/sessions/in_memory_session_service.py +206 -0
- google/adk/sessions/session.py +54 -0
- google/adk/sessions/state.py +71 -0
- google/adk/sessions/vertex_ai_session_service.py +356 -0
- google/adk/telemetry.py +189 -0
- google/adk/tests/__init__.py +14 -0
- google/adk/tests/integration/.env.example +10 -0
- google/adk/tests/integration/__init__.py +18 -0
- google/adk/tests/integration/conftest.py +119 -0
- google/adk/tests/integration/fixture/__init__.py +14 -0
- google/adk/tests/integration/fixture/agent_with_config/__init__.py +15 -0
- google/adk/tests/integration/fixture/agent_with_config/agent.py +88 -0
- google/adk/tests/integration/fixture/callback_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/callback_agent/agent.py +105 -0
- google/adk/tests/integration/fixture/context_update_test/OWNERS +1 -0
- google/adk/tests/integration/fixture/context_update_test/__init__.py +15 -0
- google/adk/tests/integration/fixture/context_update_test/agent.py +43 -0
- google/adk/tests/integration/fixture/context_update_test/successful_test.session.json +582 -0
- google/adk/tests/integration/fixture/context_variable_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/context_variable_agent/agent.py +115 -0
- google/adk/tests/integration/fixture/customer_support_ma/__init__.py +15 -0
- google/adk/tests/integration/fixture/customer_support_ma/agent.py +172 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/agent.py +338 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/order_query.test.json +69 -0
- google/adk/tests/integration/fixture/ecommerce_customer_service_agent/test_config.json +6 -0
- google/adk/tests/integration/fixture/flow_complex_spark/__init__.py +15 -0
- google/adk/tests/integration/fixture/flow_complex_spark/agent.py +182 -0
- google/adk/tests/integration/fixture/flow_complex_spark/sample.debug.log +243 -0
- google/adk/tests/integration/fixture/flow_complex_spark/sample.session.json +190 -0
- google/adk/tests/integration/fixture/hello_world_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/hello_world_agent/agent.py +95 -0
- google/adk/tests/integration/fixture/hello_world_agent/roll_die.test.json +24 -0
- google/adk/tests/integration/fixture/hello_world_agent/test_config.json +6 -0
- google/adk/tests/integration/fixture/home_automation_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/home_automation_agent/agent.py +304 -0
- google/adk/tests/integration/fixture/home_automation_agent/simple_test.test.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/simple_test2.test.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_config.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/dependent_tool_calls.test.json +18 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/eval_data.test.json +17 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/memorizing_past_events/test_config.json +6 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_multi_turn_conversation.test.json +18 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test.test.json +17 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/simple_test2.test.json +5 -0
- google/adk/tests/integration/fixture/home_automation_agent/test_files/test_config.json +5 -0
- google/adk/tests/integration/fixture/tool_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/tool_agent/agent.py +218 -0
- google/adk/tests/integration/fixture/tool_agent/files/Agent_test_plan.pdf +0 -0
- google/adk/tests/integration/fixture/trip_planner_agent/__init__.py +15 -0
- google/adk/tests/integration/fixture/trip_planner_agent/agent.py +110 -0
- google/adk/tests/integration/fixture/trip_planner_agent/initial.session.json +13 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_config.json +5 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/initial.session.json +13 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/test_config.json +5 -0
- google/adk/tests/integration/fixture/trip_planner_agent/test_files/trip_inquiry_sub_agent.test.json +7 -0
- google/adk/tests/integration/fixture/trip_planner_agent/trip_inquiry.test.json +19 -0
- google/adk/tests/integration/models/__init__.py +14 -0
- google/adk/tests/integration/models/test_google_llm.py +65 -0
- google/adk/tests/integration/test_callback.py +70 -0
- google/adk/tests/integration/test_context_variable.py +67 -0
- google/adk/tests/integration/test_evalute_agent_in_fixture.py +76 -0
- google/adk/tests/integration/test_multi_agent.py +28 -0
- google/adk/tests/integration/test_multi_turn.py +42 -0
- google/adk/tests/integration/test_single_agent.py +23 -0
- google/adk/tests/integration/test_sub_agent.py +26 -0
- google/adk/tests/integration/test_system_instruction.py +177 -0
- google/adk/tests/integration/test_tools.py +287 -0
- google/adk/tests/integration/test_with_test_file.py +34 -0
- google/adk/tests/integration/tools/__init__.py +14 -0
- google/adk/tests/integration/utils/__init__.py +16 -0
- google/adk/tests/integration/utils/asserts.py +75 -0
- google/adk/tests/integration/utils/test_runner.py +97 -0
- google/adk/tests/unittests/__init__.py +14 -0
- google/adk/tests/unittests/agents/__init__.py +14 -0
- google/adk/tests/unittests/agents/test_base_agent.py +407 -0
- google/adk/tests/unittests/agents/test_langgraph_agent.py +191 -0
- google/adk/tests/unittests/agents/test_llm_agent_callbacks.py +138 -0
- google/adk/tests/unittests/agents/test_llm_agent_fields.py +231 -0
- google/adk/tests/unittests/agents/test_loop_agent.py +136 -0
- google/adk/tests/unittests/agents/test_parallel_agent.py +92 -0
- google/adk/tests/unittests/agents/test_sequential_agent.py +114 -0
- google/adk/tests/unittests/artifacts/__init__.py +14 -0
- google/adk/tests/unittests/artifacts/test_artifact_service.py +276 -0
- google/adk/tests/unittests/auth/test_auth_handler.py +575 -0
- google/adk/tests/unittests/conftest.py +73 -0
- google/adk/tests/unittests/fast_api/__init__.py +14 -0
- google/adk/tests/unittests/fast_api/test_fast_api.py +269 -0
- google/adk/tests/unittests/flows/__init__.py +14 -0
- google/adk/tests/unittests/flows/llm_flows/__init__.py +14 -0
- google/adk/tests/unittests/flows/llm_flows/_test_examples.py +142 -0
- google/adk/tests/unittests/flows/llm_flows/test_agent_transfer.py +311 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_long_running.py +244 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_request_euc.py +346 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_sequential.py +93 -0
- google/adk/tests/unittests/flows/llm_flows/test_functions_simple.py +258 -0
- google/adk/tests/unittests/flows/llm_flows/test_identity.py +66 -0
- google/adk/tests/unittests/flows/llm_flows/test_instructions.py +164 -0
- google/adk/tests/unittests/flows/llm_flows/test_model_callbacks.py +142 -0
- google/adk/tests/unittests/flows/llm_flows/test_other_configs.py +46 -0
- google/adk/tests/unittests/flows/llm_flows/test_tool_callbacks.py +269 -0
- google/adk/tests/unittests/models/__init__.py +14 -0
- google/adk/tests/unittests/models/test_google_llm.py +224 -0
- google/adk/tests/unittests/models/test_litellm.py +804 -0
- google/adk/tests/unittests/models/test_models.py +60 -0
- google/adk/tests/unittests/sessions/__init__.py +14 -0
- google/adk/tests/unittests/sessions/test_session_service.py +227 -0
- google/adk/tests/unittests/sessions/test_vertex_ai_session_service.py +246 -0
- google/adk/tests/unittests/streaming/__init__.py +14 -0
- google/adk/tests/unittests/streaming/test_streaming.py +50 -0
- google/adk/tests/unittests/tools/__init__.py +14 -0
- google/adk/tests/unittests/tools/apihub_tool/clients/test_apihub_client.py +499 -0
- google/adk/tests/unittests/tools/apihub_tool/test_apihub_toolset.py +204 -0
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_connections_client.py +600 -0
- google/adk/tests/unittests/tools/application_integration_tool/clients/test_integration_client.py +630 -0
- google/adk/tests/unittests/tools/application_integration_tool/test_application_integration_toolset.py +345 -0
- google/adk/tests/unittests/tools/google_api_tool/__init__.py +13 -0
- google/adk/tests/unittests/tools/google_api_tool/test_googleapi_to_openapi_converter.py +657 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_auto_auth_credential_exchanger.py +145 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_base_auth_credential_exchanger.py +68 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_oauth2_exchanger.py +153 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/credential_exchangers/test_service_account_exchanger.py +196 -0
- google/adk/tests/unittests/tools/openapi_tool/auth/test_auth_helper.py +573 -0
- google/adk/tests/unittests/tools/openapi_tool/common/test_common.py +436 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test.yaml +1367 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_spec_parser.py +628 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_openapi_toolset.py +139 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_operation_parser.py +406 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_rest_api_tool.py +966 -0
- google/adk/tests/unittests/tools/openapi_tool/openapi_spec_parser/test_tool_auth_handler.py +201 -0
- google/adk/tests/unittests/tools/retrieval/__init__.py +14 -0
- google/adk/tests/unittests/tools/retrieval/test_vertex_ai_rag_retrieval.py +147 -0
- google/adk/tests/unittests/tools/test_agent_tool.py +167 -0
- google/adk/tests/unittests/tools/test_base_tool.py +141 -0
- google/adk/tests/unittests/tools/test_build_function_declaration.py +277 -0
- google/adk/tests/unittests/utils.py +304 -0
- google/adk/tools/__init__.py +51 -0
- google/adk/tools/_automatic_function_calling_util.py +346 -0
- google/adk/tools/agent_tool.py +176 -0
- google/adk/tools/apihub_tool/__init__.py +19 -0
- google/adk/tools/apihub_tool/apihub_toolset.py +209 -0
- google/adk/tools/apihub_tool/clients/__init__.py +13 -0
- google/adk/tools/apihub_tool/clients/apihub_client.py +332 -0
- google/adk/tools/apihub_tool/clients/secret_client.py +115 -0
- google/adk/tools/application_integration_tool/__init__.py +19 -0
- google/adk/tools/application_integration_tool/application_integration_toolset.py +230 -0
- google/adk/tools/application_integration_tool/clients/connections_client.py +903 -0
- google/adk/tools/application_integration_tool/clients/integration_client.py +253 -0
- google/adk/tools/base_tool.py +144 -0
- google/adk/tools/built_in_code_execution_tool.py +59 -0
- google/adk/tools/crewai_tool.py +72 -0
- google/adk/tools/example_tool.py +62 -0
- google/adk/tools/exit_loop_tool.py +23 -0
- google/adk/tools/function_parameter_parse_util.py +307 -0
- google/adk/tools/function_tool.py +87 -0
- google/adk/tools/get_user_choice_tool.py +28 -0
- google/adk/tools/google_api_tool/__init__.py +14 -0
- google/adk/tools/google_api_tool/google_api_tool.py +59 -0
- google/adk/tools/google_api_tool/google_api_tool_set.py +107 -0
- google/adk/tools/google_api_tool/google_api_tool_sets.py +55 -0
- google/adk/tools/google_api_tool/googleapi_to_openapi_converter.py +521 -0
- google/adk/tools/google_search_tool.py +68 -0
- google/adk/tools/langchain_tool.py +86 -0
- google/adk/tools/load_artifacts_tool.py +113 -0
- google/adk/tools/load_memory_tool.py +58 -0
- google/adk/tools/load_web_page.py +41 -0
- google/adk/tools/long_running_tool.py +39 -0
- google/adk/tools/mcp_tool/__init__.py +42 -0
- google/adk/tools/mcp_tool/conversion_utils.py +161 -0
- google/adk/tools/mcp_tool/mcp_tool.py +113 -0
- google/adk/tools/mcp_tool/mcp_toolset.py +272 -0
- google/adk/tools/openapi_tool/__init__.py +21 -0
- google/adk/tools/openapi_tool/auth/__init__.py +19 -0
- google/adk/tools/openapi_tool/auth/auth_helpers.py +498 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/__init__.py +25 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/auto_auth_credential_exchanger.py +105 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/base_credential_exchanger.py +55 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/oauth2_exchanger.py +117 -0
- google/adk/tools/openapi_tool/auth/credential_exchangers/service_account_exchanger.py +97 -0
- google/adk/tools/openapi_tool/common/__init__.py +19 -0
- google/adk/tools/openapi_tool/common/common.py +300 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/__init__.py +32 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py +231 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +144 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/operation_parser.py +260 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +496 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/tool_auth_handler.py +268 -0
- google/adk/tools/preload_memory_tool.py +72 -0
- google/adk/tools/retrieval/__init__.py +36 -0
- google/adk/tools/retrieval/base_retrieval_tool.py +37 -0
- google/adk/tools/retrieval/files_retrieval.py +33 -0
- google/adk/tools/retrieval/llama_index_retrieval.py +41 -0
- google/adk/tools/retrieval/vertex_ai_rag_retrieval.py +107 -0
- google/adk/tools/tool_context.py +90 -0
- google/adk/tools/toolbox_tool.py +46 -0
- google/adk/tools/transfer_to_agent_tool.py +21 -0
- google/adk/tools/vertex_ai_search_tool.py +96 -0
- google/adk/version.py +16 -0
- google_adk-0.0.1.dist-info/LICENSE.txt → google_adk-0.0.2.dist-info/LICENSE +32 -0
- google_adk-0.0.2.dist-info/METADATA +73 -0
- google_adk-0.0.2.dist-info/RECORD +308 -0
- {google_adk-0.0.1.dist-info → google_adk-0.0.2.dist-info}/WHEEL +1 -2
- google_adk-0.0.2.dist-info/entry_points.txt +3 -0
- agent_kit/__init__.py +0 -0
- google_adk-0.0.1.dist-info/METADATA +0 -15
- google_adk-0.0.1.dist-info/RECORD +0 -6
- google_adk-0.0.1.dist-info/top_level.txt +0 -1
@@ -0,0 +1,201 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from typing import Optional
|
16
|
+
from unittest.mock import MagicMock
|
17
|
+
|
18
|
+
from google.adk.agents.invocation_context import InvocationContext
|
19
|
+
from google.adk.agents.llm_agent import LlmAgent
|
20
|
+
from google.adk.auth.auth_credential import AuthCredential
|
21
|
+
from google.adk.auth.auth_credential import AuthCredentialTypes
|
22
|
+
from google.adk.auth.auth_credential import HttpAuth
|
23
|
+
from google.adk.auth.auth_credential import HttpCredentials
|
24
|
+
from google.adk.auth.auth_credential import OAuth2Auth
|
25
|
+
from google.adk.auth.auth_schemes import AuthScheme
|
26
|
+
from google.adk.sessions.in_memory_session_service import InMemorySessionService
|
27
|
+
from google.adk.sessions.session import Session
|
28
|
+
from google.adk.tools.openapi_tool.auth.auth_helpers import openid_dict_to_scheme_credential
|
29
|
+
from google.adk.tools.openapi_tool.auth.auth_helpers import token_to_scheme_credential
|
30
|
+
from google.adk.tools.openapi_tool.auth.credential_exchangers.auto_auth_credential_exchanger import OAuth2CredentialExchanger
|
31
|
+
from google.adk.tools.openapi_tool.openapi_spec_parser.tool_auth_handler import ToolAuthHandler
|
32
|
+
from google.adk.tools.openapi_tool.openapi_spec_parser.tool_auth_handler import ToolContextCredentialStore
|
33
|
+
from google.adk.tools.tool_context import ToolContext
|
34
|
+
import pytest
|
35
|
+
|
36
|
+
|
37
|
+
# Helper function to create a mock ToolContext
|
38
|
+
def create_mock_tool_context():
|
39
|
+
return ToolContext(
|
40
|
+
function_call_id='test-fc-id',
|
41
|
+
invocation_context=InvocationContext(
|
42
|
+
agent=LlmAgent(name='test'),
|
43
|
+
session=Session(app_name='test', user_id='123', id='123'),
|
44
|
+
invocation_id='123',
|
45
|
+
session_service=InMemorySessionService(),
|
46
|
+
),
|
47
|
+
)
|
48
|
+
|
49
|
+
|
50
|
+
# Test cases for OpenID Connect
|
51
|
+
class MockOpenIdConnectCredentialExchanger(OAuth2CredentialExchanger):
|
52
|
+
|
53
|
+
def __init__(
|
54
|
+
self, expected_scheme, expected_credential, expected_access_token
|
55
|
+
):
|
56
|
+
self.expected_scheme = expected_scheme
|
57
|
+
self.expected_credential = expected_credential
|
58
|
+
self.expected_access_token = expected_access_token
|
59
|
+
|
60
|
+
def exchange_credential(
|
61
|
+
self,
|
62
|
+
auth_scheme: AuthScheme,
|
63
|
+
auth_credential: Optional[AuthCredential] = None,
|
64
|
+
) -> AuthCredential:
|
65
|
+
if auth_credential.oauth2 and (
|
66
|
+
auth_credential.oauth2.auth_response_uri
|
67
|
+
or auth_credential.oauth2.auth_code
|
68
|
+
):
|
69
|
+
auth_code = (
|
70
|
+
auth_credential.oauth2.auth_response_uri
|
71
|
+
if auth_credential.oauth2.auth_response_uri
|
72
|
+
else auth_credential.oauth2.auth_code
|
73
|
+
)
|
74
|
+
# Simulate the token exchange
|
75
|
+
updated_credential = AuthCredential(
|
76
|
+
auth_type=AuthCredentialTypes.HTTP, # Store as a bearer token
|
77
|
+
http=HttpAuth(
|
78
|
+
scheme='bearer',
|
79
|
+
credentials=HttpCredentials(
|
80
|
+
token=auth_code + self.expected_access_token
|
81
|
+
),
|
82
|
+
),
|
83
|
+
)
|
84
|
+
return updated_credential
|
85
|
+
|
86
|
+
# simulate the case of getting auth_uri
|
87
|
+
return None
|
88
|
+
|
89
|
+
|
90
|
+
def get_mock_openid_scheme_credential():
|
91
|
+
config_dict = {
|
92
|
+
'authorization_endpoint': 'test.com',
|
93
|
+
'token_endpoint': 'test.com',
|
94
|
+
}
|
95
|
+
scopes = ['test_scope']
|
96
|
+
credential_dict = {
|
97
|
+
'client_id': '123',
|
98
|
+
'client_secret': '456',
|
99
|
+
'redirect_uri': 'test.com',
|
100
|
+
}
|
101
|
+
return openid_dict_to_scheme_credential(config_dict, scopes, credential_dict)
|
102
|
+
|
103
|
+
|
104
|
+
# Fixture for the OpenID Connect security scheme
|
105
|
+
@pytest.fixture
|
106
|
+
def openid_connect_scheme():
|
107
|
+
scheme, _ = get_mock_openid_scheme_credential()
|
108
|
+
return scheme
|
109
|
+
|
110
|
+
|
111
|
+
# Fixture for a base OpenID Connect credential
|
112
|
+
@pytest.fixture
|
113
|
+
def openid_connect_credential():
|
114
|
+
_, credential = get_mock_openid_scheme_credential()
|
115
|
+
return credential
|
116
|
+
|
117
|
+
|
118
|
+
def test_openid_connect_no_auth_response(
|
119
|
+
openid_connect_scheme, openid_connect_credential
|
120
|
+
):
|
121
|
+
# Setup Mock exchanger
|
122
|
+
mock_exchanger = MockOpenIdConnectCredentialExchanger(
|
123
|
+
openid_connect_scheme, openid_connect_credential, None
|
124
|
+
)
|
125
|
+
tool_context = create_mock_tool_context()
|
126
|
+
credential_store = ToolContextCredentialStore(tool_context=tool_context)
|
127
|
+
handler = ToolAuthHandler(
|
128
|
+
tool_context,
|
129
|
+
openid_connect_scheme,
|
130
|
+
openid_connect_credential,
|
131
|
+
credential_exchanger=mock_exchanger,
|
132
|
+
credential_store=credential_store,
|
133
|
+
)
|
134
|
+
result = handler.prepare_auth_credentials()
|
135
|
+
assert result.state == 'pending'
|
136
|
+
assert result.auth_credential == openid_connect_credential
|
137
|
+
|
138
|
+
|
139
|
+
def test_openid_connect_with_auth_response(
|
140
|
+
openid_connect_scheme, openid_connect_credential, monkeypatch
|
141
|
+
):
|
142
|
+
mock_exchanger = MockOpenIdConnectCredentialExchanger(
|
143
|
+
openid_connect_scheme,
|
144
|
+
openid_connect_credential,
|
145
|
+
'test_access_token',
|
146
|
+
)
|
147
|
+
tool_context = create_mock_tool_context()
|
148
|
+
|
149
|
+
mock_auth_handler = MagicMock()
|
150
|
+
mock_auth_handler.get_auth_response.return_value = AuthCredential(
|
151
|
+
auth_type=AuthCredentialTypes.OPEN_ID_CONNECT,
|
152
|
+
oauth2=OAuth2Auth(auth_response_uri='test_auth_response_uri'),
|
153
|
+
)
|
154
|
+
mock_auth_handler_path = 'google.adk.tools.tool_context.AuthHandler'
|
155
|
+
monkeypatch.setattr(
|
156
|
+
mock_auth_handler_path, lambda *args, **kwargs: mock_auth_handler
|
157
|
+
)
|
158
|
+
|
159
|
+
credential_store = ToolContextCredentialStore(tool_context=tool_context)
|
160
|
+
handler = ToolAuthHandler(
|
161
|
+
tool_context,
|
162
|
+
openid_connect_scheme,
|
163
|
+
openid_connect_credential,
|
164
|
+
credential_exchanger=mock_exchanger,
|
165
|
+
credential_store=credential_store,
|
166
|
+
)
|
167
|
+
result = handler.prepare_auth_credentials()
|
168
|
+
assert result.state == 'done'
|
169
|
+
assert result.auth_credential.auth_type == AuthCredentialTypes.HTTP
|
170
|
+
assert 'test_access_token' in result.auth_credential.http.credentials.token
|
171
|
+
# Verify that the credential was stored:
|
172
|
+
stored_credential = credential_store.get_credential(
|
173
|
+
openid_connect_scheme, openid_connect_credential
|
174
|
+
)
|
175
|
+
assert stored_credential == result.auth_credential
|
176
|
+
mock_auth_handler.get_auth_response.assert_called_once()
|
177
|
+
|
178
|
+
|
179
|
+
def test_openid_connect_existing_token(
|
180
|
+
openid_connect_scheme, openid_connect_credential
|
181
|
+
):
|
182
|
+
_, existing_credential = token_to_scheme_credential(
|
183
|
+
'oauth2Token', 'header', 'bearer', '123123123'
|
184
|
+
)
|
185
|
+
tool_context = create_mock_tool_context()
|
186
|
+
# Store the credential to simulate existing credential
|
187
|
+
credential_store = ToolContextCredentialStore(tool_context=tool_context)
|
188
|
+
key = credential_store.get_credential_key(
|
189
|
+
openid_connect_scheme, openid_connect_credential
|
190
|
+
)
|
191
|
+
credential_store.store_credential(key, existing_credential)
|
192
|
+
|
193
|
+
handler = ToolAuthHandler(
|
194
|
+
tool_context,
|
195
|
+
openid_connect_scheme,
|
196
|
+
openid_connect_credential,
|
197
|
+
credential_store=credential_store,
|
198
|
+
)
|
199
|
+
result = handler.prepare_auth_credentials()
|
200
|
+
assert result.state == 'done'
|
201
|
+
assert result.auth_credential == existing_credential
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from google.adk.agents import Agent
|
16
|
+
from google.adk.tools.function_tool import FunctionTool
|
17
|
+
from google.adk.tools.retrieval.vertex_ai_rag_retrieval import VertexAiRagRetrieval
|
18
|
+
from google.genai import types
|
19
|
+
|
20
|
+
from ... import utils
|
21
|
+
|
22
|
+
|
23
|
+
def noop_tool(x: str) -> str:
|
24
|
+
return x
|
25
|
+
|
26
|
+
|
27
|
+
def test_vertex_rag_retrieval_for_gemini_1_x():
|
28
|
+
responses = [
|
29
|
+
'response1',
|
30
|
+
]
|
31
|
+
mockModel = utils.MockModel.create(responses=responses)
|
32
|
+
mockModel.model = 'gemini-1.5-pro'
|
33
|
+
|
34
|
+
# Calls the first time.
|
35
|
+
agent = Agent(
|
36
|
+
name='root_agent',
|
37
|
+
model=mockModel,
|
38
|
+
tools=[
|
39
|
+
VertexAiRagRetrieval(
|
40
|
+
name='rag_retrieval',
|
41
|
+
description='rag_retrieval',
|
42
|
+
rag_corpora=[
|
43
|
+
'projects/123456789/locations/us-central1/ragCorpora/1234567890'
|
44
|
+
],
|
45
|
+
)
|
46
|
+
],
|
47
|
+
)
|
48
|
+
runner = utils.InMemoryRunner(agent)
|
49
|
+
events = runner.run('test1')
|
50
|
+
|
51
|
+
# Asserts the requests.
|
52
|
+
assert len(mockModel.requests) == 1
|
53
|
+
assert utils.simplify_contents(mockModel.requests[0].contents) == [
|
54
|
+
('user', 'test1'),
|
55
|
+
]
|
56
|
+
assert len(mockModel.requests[0].config.tools) == 1
|
57
|
+
assert (
|
58
|
+
mockModel.requests[0].config.tools[0].function_declarations[0].name
|
59
|
+
== 'rag_retrieval'
|
60
|
+
)
|
61
|
+
assert mockModel.requests[0].tools_dict['rag_retrieval'] is not None
|
62
|
+
|
63
|
+
|
64
|
+
def test_vertex_rag_retrieval_for_gemini_1_x_with_another_function_tool():
|
65
|
+
responses = [
|
66
|
+
'response1',
|
67
|
+
]
|
68
|
+
mockModel = utils.MockModel.create(responses=responses)
|
69
|
+
mockModel.model = 'gemini-1.5-pro'
|
70
|
+
|
71
|
+
# Calls the first time.
|
72
|
+
agent = Agent(
|
73
|
+
name='root_agent',
|
74
|
+
model=mockModel,
|
75
|
+
tools=[
|
76
|
+
VertexAiRagRetrieval(
|
77
|
+
name='rag_retrieval',
|
78
|
+
description='rag_retrieval',
|
79
|
+
rag_corpora=[
|
80
|
+
'projects/123456789/locations/us-central1/ragCorpora/1234567890'
|
81
|
+
],
|
82
|
+
),
|
83
|
+
FunctionTool(func=noop_tool),
|
84
|
+
],
|
85
|
+
)
|
86
|
+
runner = utils.InMemoryRunner(agent)
|
87
|
+
events = runner.run('test1')
|
88
|
+
|
89
|
+
# Asserts the requests.
|
90
|
+
assert len(mockModel.requests) == 1
|
91
|
+
assert utils.simplify_contents(mockModel.requests[0].contents) == [
|
92
|
+
('user', 'test1'),
|
93
|
+
]
|
94
|
+
assert len(mockModel.requests[0].config.tools[0].function_declarations) == 2
|
95
|
+
assert (
|
96
|
+
mockModel.requests[0].config.tools[0].function_declarations[0].name
|
97
|
+
== 'rag_retrieval'
|
98
|
+
)
|
99
|
+
assert (
|
100
|
+
mockModel.requests[0].config.tools[0].function_declarations[1].name
|
101
|
+
== 'noop_tool'
|
102
|
+
)
|
103
|
+
assert mockModel.requests[0].tools_dict['rag_retrieval'] is not None
|
104
|
+
|
105
|
+
|
106
|
+
def test_vertex_rag_retrieval_for_gemini_2_x():
|
107
|
+
responses = [
|
108
|
+
'response1',
|
109
|
+
]
|
110
|
+
mockModel = utils.MockModel.create(responses=responses)
|
111
|
+
mockModel.model = 'gemini-2.0-flash'
|
112
|
+
|
113
|
+
# Calls the first time.
|
114
|
+
agent = Agent(
|
115
|
+
name='root_agent',
|
116
|
+
model=mockModel,
|
117
|
+
tools=[
|
118
|
+
VertexAiRagRetrieval(
|
119
|
+
name='rag_retrieval',
|
120
|
+
description='rag_retrieval',
|
121
|
+
rag_corpora=[
|
122
|
+
'projects/123456789/locations/us-central1/ragCorpora/1234567890'
|
123
|
+
],
|
124
|
+
)
|
125
|
+
],
|
126
|
+
)
|
127
|
+
runner = utils.InMemoryRunner(agent)
|
128
|
+
events = runner.run('test1')
|
129
|
+
|
130
|
+
# Asserts the requests.
|
131
|
+
assert len(mockModel.requests) == 1
|
132
|
+
assert utils.simplify_contents(mockModel.requests[0].contents) == [
|
133
|
+
('user', 'test1'),
|
134
|
+
]
|
135
|
+
assert len(mockModel.requests[0].config.tools) == 1
|
136
|
+
assert mockModel.requests[0].config.tools == [
|
137
|
+
types.Tool(
|
138
|
+
retrieval=types.Retrieval(
|
139
|
+
vertex_rag_store=types.VertexRagStore(
|
140
|
+
rag_corpora=[
|
141
|
+
'projects/123456789/locations/us-central1/ragCorpora/1234567890'
|
142
|
+
]
|
143
|
+
)
|
144
|
+
)
|
145
|
+
)
|
146
|
+
]
|
147
|
+
assert 'rag_retrieval' not in mockModel.requests[0].tools_dict
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from google.adk.agents import Agent
|
16
|
+
from google.adk.agents.callback_context import CallbackContext
|
17
|
+
from google.adk.tools.agent_tool import AgentTool
|
18
|
+
from google.genai.types import Part
|
19
|
+
from pydantic import BaseModel
|
20
|
+
import pytest
|
21
|
+
from pytest import mark
|
22
|
+
|
23
|
+
from .. import utils
|
24
|
+
|
25
|
+
pytestmark = pytest.mark.skip(
|
26
|
+
reason='Skipping until tool.func evaluations are fixed (async)'
|
27
|
+
)
|
28
|
+
|
29
|
+
|
30
|
+
function_call_custom = Part.from_function_call(
|
31
|
+
name='tool_agent', args={'custom_input': 'test1'}
|
32
|
+
)
|
33
|
+
|
34
|
+
function_call_no_schema = Part.from_function_call(
|
35
|
+
name='tool_agent', args={'request': 'test1'}
|
36
|
+
)
|
37
|
+
|
38
|
+
function_response_custom = Part.from_function_response(
|
39
|
+
name='tool_agent', response={'custom_output': 'response1'}
|
40
|
+
)
|
41
|
+
|
42
|
+
function_response_no_schema = Part.from_function_response(
|
43
|
+
name='tool_agent', response={'result': 'response1'}
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
def change_state_callback(callback_context: CallbackContext):
|
48
|
+
callback_context.state['state_1'] = 'changed_value'
|
49
|
+
print('change_state_callback: ', callback_context.state)
|
50
|
+
|
51
|
+
|
52
|
+
def test_no_schema():
|
53
|
+
mock_model = utils.MockModel.create(
|
54
|
+
responses=[
|
55
|
+
function_call_no_schema,
|
56
|
+
'response1',
|
57
|
+
'response2',
|
58
|
+
]
|
59
|
+
)
|
60
|
+
|
61
|
+
tool_agent = Agent(
|
62
|
+
name='tool_agent',
|
63
|
+
model=mock_model,
|
64
|
+
)
|
65
|
+
|
66
|
+
root_agent = Agent(
|
67
|
+
name='root_agent',
|
68
|
+
model=mock_model,
|
69
|
+
tools=[AgentTool(agent=tool_agent)],
|
70
|
+
)
|
71
|
+
|
72
|
+
runner = utils.InMemoryRunner(root_agent)
|
73
|
+
|
74
|
+
assert utils.simplify_events(runner.run('test1')) == [
|
75
|
+
('root_agent', function_call_no_schema),
|
76
|
+
('root_agent', function_response_no_schema),
|
77
|
+
('root_agent', 'response2'),
|
78
|
+
]
|
79
|
+
|
80
|
+
|
81
|
+
def test_update_state():
|
82
|
+
"""The agent tool can read and change parent state."""
|
83
|
+
|
84
|
+
mock_model = utils.MockModel.create(
|
85
|
+
responses=[
|
86
|
+
function_call_no_schema,
|
87
|
+
'{"custom_output": "response1"}',
|
88
|
+
'response2',
|
89
|
+
]
|
90
|
+
)
|
91
|
+
|
92
|
+
tool_agent = Agent(
|
93
|
+
name='tool_agent',
|
94
|
+
model=mock_model,
|
95
|
+
instruction='input: {state_1}',
|
96
|
+
before_agent_callback=change_state_callback,
|
97
|
+
)
|
98
|
+
|
99
|
+
root_agent = Agent(
|
100
|
+
name='root_agent',
|
101
|
+
model=mock_model,
|
102
|
+
tools=[AgentTool(agent=tool_agent)],
|
103
|
+
)
|
104
|
+
|
105
|
+
runner = utils.InMemoryRunner(root_agent)
|
106
|
+
runner.session.state['state_1'] = 'state1_value'
|
107
|
+
|
108
|
+
runner.run('test1')
|
109
|
+
assert (
|
110
|
+
'input: changed_value' in mock_model.requests[1].config.system_instruction
|
111
|
+
)
|
112
|
+
assert runner.session.state['state_1'] == 'changed_value'
|
113
|
+
|
114
|
+
|
115
|
+
@mark.parametrize(
|
116
|
+
'env_variables',
|
117
|
+
[
|
118
|
+
'GOOGLE_AI',
|
119
|
+
# TODO(wanyif): re-enable after fix.
|
120
|
+
# 'VERTEX',
|
121
|
+
],
|
122
|
+
indirect=True,
|
123
|
+
)
|
124
|
+
def test_custom_schema():
|
125
|
+
class CustomInput(BaseModel):
|
126
|
+
custom_input: str
|
127
|
+
|
128
|
+
class CustomOutput(BaseModel):
|
129
|
+
custom_output: str
|
130
|
+
|
131
|
+
mock_model = utils.MockModel.create(
|
132
|
+
responses=[
|
133
|
+
function_call_custom,
|
134
|
+
'{"custom_output": "response1"}',
|
135
|
+
'response2',
|
136
|
+
]
|
137
|
+
)
|
138
|
+
|
139
|
+
tool_agent = Agent(
|
140
|
+
name='tool_agent',
|
141
|
+
model=mock_model,
|
142
|
+
input_schema=CustomInput,
|
143
|
+
output_schema=CustomOutput,
|
144
|
+
output_key='tool_output',
|
145
|
+
)
|
146
|
+
|
147
|
+
root_agent = Agent(
|
148
|
+
name='root_agent',
|
149
|
+
model=mock_model,
|
150
|
+
tools=[AgentTool(agent=tool_agent)],
|
151
|
+
)
|
152
|
+
|
153
|
+
runner = utils.InMemoryRunner(root_agent)
|
154
|
+
runner.session.state['state_1'] = 'state1_value'
|
155
|
+
|
156
|
+
assert utils.simplify_events(runner.run('test1')) == [
|
157
|
+
('root_agent', function_call_custom),
|
158
|
+
('root_agent', function_response_custom),
|
159
|
+
('root_agent', 'response2'),
|
160
|
+
]
|
161
|
+
|
162
|
+
assert runner.session.state['tool_output'] == {'custom_output': 'response1'}
|
163
|
+
|
164
|
+
assert len(mock_model.requests) == 3
|
165
|
+
# The second request is the tool agent request.
|
166
|
+
assert mock_model.requests[1].config.response_schema == CustomOutput
|
167
|
+
assert mock_model.requests[1].config.response_mime_type == 'application/json'
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from typing import Optional
|
16
|
+
|
17
|
+
from google.adk.agents.invocation_context import InvocationContext
|
18
|
+
from google.adk.agents.sequential_agent import SequentialAgent
|
19
|
+
from google.adk.models.llm_request import LlmRequest
|
20
|
+
from google.adk.sessions.in_memory_session_service import InMemorySessionService
|
21
|
+
from google.adk.tools.base_tool import BaseTool
|
22
|
+
from google.adk.tools.tool_context import ToolContext
|
23
|
+
from google.genai import types
|
24
|
+
import pytest
|
25
|
+
|
26
|
+
|
27
|
+
class _TestingTool(BaseTool):
|
28
|
+
|
29
|
+
def __init__(
|
30
|
+
self,
|
31
|
+
declaration: Optional[types.FunctionDeclaration] = None,
|
32
|
+
):
|
33
|
+
super().__init__(name='test_tool', description='test_description')
|
34
|
+
self.declaration = declaration
|
35
|
+
|
36
|
+
def _get_declaration(self) -> Optional[types.FunctionDeclaration]:
|
37
|
+
return self.declaration
|
38
|
+
|
39
|
+
|
40
|
+
def _create_tool_context() -> ToolContext:
|
41
|
+
session_service = InMemorySessionService()
|
42
|
+
session = session_service.create_session(
|
43
|
+
app_name='test_app', user_id='test_user'
|
44
|
+
)
|
45
|
+
agent = SequentialAgent(name='test_agent')
|
46
|
+
invocation_context = InvocationContext(
|
47
|
+
invocation_id='invocation_id',
|
48
|
+
agent=agent,
|
49
|
+
session=session,
|
50
|
+
session_service=session_service,
|
51
|
+
)
|
52
|
+
return ToolContext(invocation_context)
|
53
|
+
|
54
|
+
|
55
|
+
@pytest.mark.asyncio
|
56
|
+
async def test_process_llm_request_no_declaration():
|
57
|
+
tool = _TestingTool()
|
58
|
+
tool_context = _create_tool_context()
|
59
|
+
llm_request = LlmRequest()
|
60
|
+
|
61
|
+
await tool.process_llm_request(
|
62
|
+
tool_context=tool_context, llm_request=llm_request
|
63
|
+
)
|
64
|
+
|
65
|
+
assert llm_request.config is None
|
66
|
+
|
67
|
+
|
68
|
+
@pytest.mark.asyncio
|
69
|
+
async def test_process_llm_request_with_declaration():
|
70
|
+
declaration = types.FunctionDeclaration(
|
71
|
+
name='test_tool',
|
72
|
+
description='test_description',
|
73
|
+
parameters=types.Schema(
|
74
|
+
type=types.Type.STRING,
|
75
|
+
title='param_1',
|
76
|
+
),
|
77
|
+
)
|
78
|
+
tool = _TestingTool(declaration)
|
79
|
+
llm_request = LlmRequest()
|
80
|
+
tool_context = _create_tool_context()
|
81
|
+
|
82
|
+
await tool.process_llm_request(
|
83
|
+
tool_context=tool_context, llm_request=llm_request
|
84
|
+
)
|
85
|
+
|
86
|
+
assert llm_request.config.tools[0].function_declarations == [declaration]
|
87
|
+
|
88
|
+
|
89
|
+
@pytest.mark.asyncio
|
90
|
+
async def test_process_llm_request_with_builtin_tool():
|
91
|
+
declaration = types.FunctionDeclaration(
|
92
|
+
name='test_tool',
|
93
|
+
description='test_description',
|
94
|
+
parameters=types.Schema(
|
95
|
+
type=types.Type.STRING,
|
96
|
+
title='param_1',
|
97
|
+
),
|
98
|
+
)
|
99
|
+
tool = _TestingTool(declaration)
|
100
|
+
llm_request = LlmRequest(
|
101
|
+
config=types.GenerateContentConfig(
|
102
|
+
tools=[types.Tool(google_search=types.GoogleSearch())]
|
103
|
+
)
|
104
|
+
)
|
105
|
+
tool_context = _create_tool_context()
|
106
|
+
|
107
|
+
await tool.process_llm_request(
|
108
|
+
tool_context=tool_context, llm_request=llm_request
|
109
|
+
)
|
110
|
+
|
111
|
+
# function_declaration is added to another types.Tool without builtin tool.
|
112
|
+
assert llm_request.config.tools[1].function_declarations == [declaration]
|
113
|
+
|
114
|
+
|
115
|
+
@pytest.mark.asyncio
|
116
|
+
async def test_process_llm_request_with_builtin_tool_and_another_declaration():
|
117
|
+
declaration = types.FunctionDeclaration(
|
118
|
+
name='test_tool',
|
119
|
+
description='test_description',
|
120
|
+
parameters=types.Schema(
|
121
|
+
type=types.Type.STRING,
|
122
|
+
title='param_1',
|
123
|
+
),
|
124
|
+
)
|
125
|
+
tool = _TestingTool(declaration)
|
126
|
+
llm_request = LlmRequest(
|
127
|
+
config=types.GenerateContentConfig(
|
128
|
+
tools=[
|
129
|
+
types.Tool(google_search=types.GoogleSearch()),
|
130
|
+
types.Tool(function_declarations=[types.FunctionDeclaration()]),
|
131
|
+
]
|
132
|
+
)
|
133
|
+
)
|
134
|
+
tool_context = _create_tool_context()
|
135
|
+
|
136
|
+
await tool.process_llm_request(
|
137
|
+
tool_context=tool_context, llm_request=llm_request
|
138
|
+
)
|
139
|
+
|
140
|
+
# function_declaration is added to existing types.Tool with function_declaration.
|
141
|
+
assert llm_request.config.tools[1].function_declarations[1] == declaration
|