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,268 @@
|
|
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
|
+
|
16
|
+
import logging
|
17
|
+
from typing import Literal
|
18
|
+
from typing import Optional
|
19
|
+
|
20
|
+
from fastapi.encoders import jsonable_encoder
|
21
|
+
from pydantic import BaseModel
|
22
|
+
|
23
|
+
from ....auth.auth_credential import AuthCredential
|
24
|
+
from ....auth.auth_credential import AuthCredentialTypes
|
25
|
+
from ....auth.auth_schemes import AuthScheme
|
26
|
+
from ....auth.auth_schemes import AuthSchemeType
|
27
|
+
from ....auth.auth_tool import AuthConfig
|
28
|
+
from ...tool_context import ToolContext
|
29
|
+
from ..auth.credential_exchangers.auto_auth_credential_exchanger import AutoAuthCredentialExchanger
|
30
|
+
from ..auth.credential_exchangers.base_credential_exchanger import AuthCredentialMissingError
|
31
|
+
from ..auth.credential_exchangers.base_credential_exchanger import BaseAuthCredentialExchanger
|
32
|
+
|
33
|
+
logger = logging.getLogger(__name__)
|
34
|
+
|
35
|
+
AuthPreparationState = Literal["pending", "done"]
|
36
|
+
|
37
|
+
|
38
|
+
class AuthPreparationResult(BaseModel):
|
39
|
+
"""Result of the credential preparation process."""
|
40
|
+
|
41
|
+
state: AuthPreparationState
|
42
|
+
auth_scheme: Optional[AuthScheme] = None
|
43
|
+
auth_credential: Optional[AuthCredential] = None
|
44
|
+
|
45
|
+
|
46
|
+
class ToolContextCredentialStore:
|
47
|
+
"""Handles storage and retrieval of credentials within a ToolContext."""
|
48
|
+
|
49
|
+
def __init__(self, tool_context: ToolContext):
|
50
|
+
self.tool_context = tool_context
|
51
|
+
|
52
|
+
def get_credential_key(
|
53
|
+
self,
|
54
|
+
auth_scheme: Optional[AuthScheme],
|
55
|
+
auth_credential: Optional[AuthCredential],
|
56
|
+
) -> str:
|
57
|
+
"""Generates a unique key for the given auth scheme and credential."""
|
58
|
+
scheme_name = (
|
59
|
+
f"{auth_scheme.type_.name}_{hash(auth_scheme.model_dump_json())}"
|
60
|
+
if auth_scheme
|
61
|
+
else ""
|
62
|
+
)
|
63
|
+
credential_name = (
|
64
|
+
f"{auth_credential.auth_type.value}_{hash(auth_credential.model_dump_json())}"
|
65
|
+
if auth_credential
|
66
|
+
else ""
|
67
|
+
)
|
68
|
+
# no need to prepend temp: namespace, session state is a copy, changes to
|
69
|
+
# it won't be persisted , only changes in event_action.state_delta will be
|
70
|
+
# persisted. temp: namespace will be cleared after current run. but tool
|
71
|
+
# want access token to be there stored across runs
|
72
|
+
|
73
|
+
return f"{scheme_name}_{credential_name}_existing_exchanged_credential"
|
74
|
+
|
75
|
+
def get_credential(
|
76
|
+
self,
|
77
|
+
auth_scheme: Optional[AuthScheme],
|
78
|
+
auth_credential: Optional[AuthCredential],
|
79
|
+
) -> Optional[AuthCredential]:
|
80
|
+
if not self.tool_context:
|
81
|
+
return None
|
82
|
+
|
83
|
+
token_key = self.get_credential_key(auth_scheme, auth_credential)
|
84
|
+
# TODO try not to use session state, this looks a hacky way, depend on
|
85
|
+
# session implementation, we don't want session to persist the token,
|
86
|
+
# meanwhile we want the token shared across runs.
|
87
|
+
serialized_credential = self.tool_context.state.get(token_key)
|
88
|
+
if not serialized_credential:
|
89
|
+
return None
|
90
|
+
return AuthCredential.model_validate(serialized_credential)
|
91
|
+
|
92
|
+
def store_credential(
|
93
|
+
self,
|
94
|
+
key: str,
|
95
|
+
auth_credential: Optional[AuthCredential],
|
96
|
+
):
|
97
|
+
if self.tool_context:
|
98
|
+
serializable_credential = jsonable_encoder(
|
99
|
+
auth_credential, exclude_none=True
|
100
|
+
)
|
101
|
+
self.tool_context.state[key] = serializable_credential
|
102
|
+
|
103
|
+
def remove_credential(self, key: str):
|
104
|
+
del self.tool_context.state[key]
|
105
|
+
|
106
|
+
|
107
|
+
class ToolAuthHandler:
|
108
|
+
"""Handles the preparation and exchange of authentication credentials for tools."""
|
109
|
+
|
110
|
+
def __init__(
|
111
|
+
self,
|
112
|
+
tool_context: ToolContext,
|
113
|
+
auth_scheme: Optional[AuthScheme],
|
114
|
+
auth_credential: Optional[AuthCredential],
|
115
|
+
credential_exchanger: Optional[BaseAuthCredentialExchanger] = None,
|
116
|
+
credential_store: Optional["ToolContextCredentialStore"] = None,
|
117
|
+
):
|
118
|
+
self.tool_context = tool_context
|
119
|
+
self.auth_scheme = (
|
120
|
+
auth_scheme.model_copy(deep=True) if auth_scheme else None
|
121
|
+
)
|
122
|
+
self.auth_credential = (
|
123
|
+
auth_credential.model_copy(deep=True) if auth_credential else None
|
124
|
+
)
|
125
|
+
self.credential_exchanger = (
|
126
|
+
credential_exchanger or AutoAuthCredentialExchanger()
|
127
|
+
)
|
128
|
+
self.credential_store = credential_store
|
129
|
+
self.should_store_credential = True
|
130
|
+
|
131
|
+
@classmethod
|
132
|
+
def from_tool_context(
|
133
|
+
cls,
|
134
|
+
tool_context: ToolContext,
|
135
|
+
auth_scheme: Optional[AuthScheme],
|
136
|
+
auth_credential: Optional[AuthCredential],
|
137
|
+
credential_exchanger: Optional[BaseAuthCredentialExchanger] = None,
|
138
|
+
) -> "ToolAuthHandler":
|
139
|
+
"""Creates a ToolAuthHandler instance from a ToolContext."""
|
140
|
+
credential_store = ToolContextCredentialStore(tool_context)
|
141
|
+
return cls(
|
142
|
+
tool_context,
|
143
|
+
auth_scheme,
|
144
|
+
auth_credential,
|
145
|
+
credential_exchanger,
|
146
|
+
credential_store,
|
147
|
+
)
|
148
|
+
|
149
|
+
def _handle_existing_credential(
|
150
|
+
self,
|
151
|
+
) -> Optional[AuthPreparationResult]:
|
152
|
+
"""Checks for and returns an existing, exchanged credential."""
|
153
|
+
if self.credential_store:
|
154
|
+
existing_credential = self.credential_store.get_credential(
|
155
|
+
self.auth_scheme, self.auth_credential
|
156
|
+
)
|
157
|
+
if existing_credential:
|
158
|
+
return AuthPreparationResult(
|
159
|
+
state="done",
|
160
|
+
auth_scheme=self.auth_scheme,
|
161
|
+
auth_credential=existing_credential,
|
162
|
+
)
|
163
|
+
return None
|
164
|
+
|
165
|
+
def _exchange_credential(
|
166
|
+
self, auth_credential: AuthCredential
|
167
|
+
) -> Optional[AuthPreparationResult]:
|
168
|
+
"""Handles an OpenID Connect authorization response."""
|
169
|
+
|
170
|
+
exchanged_credential = None
|
171
|
+
try:
|
172
|
+
exchanged_credential = self.credential_exchanger.exchange_credential(
|
173
|
+
self.auth_scheme, auth_credential
|
174
|
+
)
|
175
|
+
except Exception as e:
|
176
|
+
logger.error("Failed to exchange credential: %s", e)
|
177
|
+
return exchanged_credential
|
178
|
+
|
179
|
+
def _store_credential(self, auth_credential: AuthCredential) -> None:
|
180
|
+
"""stores the auth_credential."""
|
181
|
+
|
182
|
+
if self.credential_store:
|
183
|
+
key = self.credential_store.get_credential_key(
|
184
|
+
self.auth_scheme, self.auth_credential
|
185
|
+
)
|
186
|
+
self.credential_store.store_credential(key, auth_credential)
|
187
|
+
|
188
|
+
def _reqeust_credential(self) -> None:
|
189
|
+
"""Handles the case where an OpenID Connect or OAuth2 authentication request is needed."""
|
190
|
+
if self.auth_scheme.type_ in (
|
191
|
+
AuthSchemeType.openIdConnect,
|
192
|
+
AuthSchemeType.oauth2,
|
193
|
+
):
|
194
|
+
if not self.auth_credential or not self.auth_credential.oauth2:
|
195
|
+
raise ValueError(
|
196
|
+
f"auth_credential is empty for scheme {self.auth_scheme.type_}."
|
197
|
+
"Please create AuthCredential using OAuth2Auth."
|
198
|
+
)
|
199
|
+
|
200
|
+
if not self.auth_credential.oauth2.client_id:
|
201
|
+
raise AuthCredentialMissingError(
|
202
|
+
"OAuth2 credentials client_id is missing."
|
203
|
+
)
|
204
|
+
|
205
|
+
if not self.auth_credential.oauth2.client_secret:
|
206
|
+
raise AuthCredentialMissingError(
|
207
|
+
"OAuth2 credentials client_secret is missing."
|
208
|
+
)
|
209
|
+
|
210
|
+
self.tool_context.request_credential(
|
211
|
+
AuthConfig(
|
212
|
+
auth_scheme=self.auth_scheme,
|
213
|
+
raw_auth_credential=self.auth_credential,
|
214
|
+
)
|
215
|
+
)
|
216
|
+
return None
|
217
|
+
|
218
|
+
def _get_auth_response(self) -> AuthCredential:
|
219
|
+
return self.tool_context.get_auth_response(
|
220
|
+
AuthConfig(
|
221
|
+
auth_scheme=self.auth_scheme,
|
222
|
+
raw_auth_credential=self.auth_credential,
|
223
|
+
)
|
224
|
+
)
|
225
|
+
|
226
|
+
def _request_credential(self, auth_config: AuthConfig):
|
227
|
+
if not self.tool_context:
|
228
|
+
return
|
229
|
+
self.tool_context.request_credential(auth_config)
|
230
|
+
|
231
|
+
def prepare_auth_credentials(
|
232
|
+
self,
|
233
|
+
) -> AuthPreparationResult:
|
234
|
+
"""Prepares authentication credentials, handling exchange and user interaction."""
|
235
|
+
|
236
|
+
# no auth is needed
|
237
|
+
if not self.auth_scheme:
|
238
|
+
return AuthPreparationResult(state="done")
|
239
|
+
|
240
|
+
# Check for existing credential.
|
241
|
+
existing_result = self._handle_existing_credential()
|
242
|
+
if existing_result:
|
243
|
+
return existing_result
|
244
|
+
|
245
|
+
# fetch credential from adk framework
|
246
|
+
# Some auth scheme like OAuth2 AuthCode & OpenIDConnect may require
|
247
|
+
# multi-step exchange:
|
248
|
+
# client_id , client_secret -> auth_uri -> auth_code -> access_token
|
249
|
+
# -> bearer token
|
250
|
+
# adk framework supports exchange access_token already
|
251
|
+
fetched_credential = self._get_auth_response() or self.auth_credential
|
252
|
+
|
253
|
+
exchanged_credential = self._exchange_credential(fetched_credential)
|
254
|
+
|
255
|
+
if exchanged_credential:
|
256
|
+
self._store_credential(exchanged_credential)
|
257
|
+
return AuthPreparationResult(
|
258
|
+
state="done",
|
259
|
+
auth_scheme=self.auth_scheme,
|
260
|
+
auth_credential=exchanged_credential,
|
261
|
+
)
|
262
|
+
else:
|
263
|
+
self._reqeust_credential()
|
264
|
+
return AuthPreparationResult(
|
265
|
+
state="pending",
|
266
|
+
auth_scheme=self.auth_scheme,
|
267
|
+
auth_credential=self.auth_credential,
|
268
|
+
)
|
@@ -0,0 +1,72 @@
|
|
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 __future__ import annotations
|
16
|
+
|
17
|
+
from datetime import datetime
|
18
|
+
from typing import TYPE_CHECKING
|
19
|
+
|
20
|
+
from typing_extensions import override
|
21
|
+
|
22
|
+
from .base_tool import BaseTool
|
23
|
+
from .tool_context import ToolContext
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from ..models import LlmRequest
|
27
|
+
|
28
|
+
|
29
|
+
class PreloadMemoryTool(BaseTool):
|
30
|
+
"""A tool that preloads the memory for the current user."""
|
31
|
+
|
32
|
+
def __init__(self):
|
33
|
+
# Name and description are not used because this tool only
|
34
|
+
# changes llm_request.
|
35
|
+
super().__init__(name='preload_memory', description='preload_memory')
|
36
|
+
|
37
|
+
@override
|
38
|
+
async def process_llm_request(
|
39
|
+
self,
|
40
|
+
*,
|
41
|
+
tool_context: ToolContext,
|
42
|
+
llm_request: LlmRequest,
|
43
|
+
) -> None:
|
44
|
+
parts = tool_context.user_content.parts
|
45
|
+
if not parts or not parts[0].text:
|
46
|
+
return
|
47
|
+
query = parts[0].text
|
48
|
+
response = tool_context.search_memory(query)
|
49
|
+
if not response.memories:
|
50
|
+
return
|
51
|
+
memory_text = ''
|
52
|
+
for memory in response.memories:
|
53
|
+
time_str = datetime.fromtimestamp(memory.events[0].timestamp).isoformat()
|
54
|
+
memory_text += f'Time: {time_str}\n'
|
55
|
+
for event in memory.events:
|
56
|
+
# TODO: support multi-part content.
|
57
|
+
if (
|
58
|
+
event.content
|
59
|
+
and event.content.parts
|
60
|
+
and event.content.parts[0].text
|
61
|
+
):
|
62
|
+
memory_text += f'{event.author}: {event.content.parts[0].text}\n'
|
63
|
+
si = f"""The following content is from your previous conversations with the user.
|
64
|
+
They may be useful for answering the user's current query.
|
65
|
+
<PAST_CONVERSATIONS>
|
66
|
+
{memory_text}
|
67
|
+
</PAST_CONVERSATIONS>
|
68
|
+
"""
|
69
|
+
llm_request.append_instructions([si])
|
70
|
+
|
71
|
+
|
72
|
+
preload_memory_tool = PreloadMemoryTool()
|
@@ -0,0 +1,36 @@
|
|
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 .base_retrieval_tool import BaseRetrievalTool
|
16
|
+
from .files_retrieval import FilesRetrieval
|
17
|
+
from .llama_index_retrieval import LlamaIndexRetrieval
|
18
|
+
|
19
|
+
__all__ = [
|
20
|
+
'BaseRetrievalTool',
|
21
|
+
'FilesRetrieval',
|
22
|
+
'LlamaIndexRetrieval',
|
23
|
+
]
|
24
|
+
|
25
|
+
try:
|
26
|
+
from .vertex_ai_rag_retrieval import VertexAiRagRetrieval
|
27
|
+
|
28
|
+
__all__.append('VertexAiRagRetrieval')
|
29
|
+
except ImportError:
|
30
|
+
import logging
|
31
|
+
|
32
|
+
logger = logging.getLogger(__name__)
|
33
|
+
logger.debug(
|
34
|
+
'The Vertex sdk is not installed. If you want to use the Vertex RAG with'
|
35
|
+
' agents, please install it. If not, you can ignore this warning.'
|
36
|
+
)
|
@@ -0,0 +1,37 @@
|
|
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.genai import types
|
16
|
+
from typing_extensions import override
|
17
|
+
|
18
|
+
from ..base_tool import BaseTool
|
19
|
+
|
20
|
+
|
21
|
+
class BaseRetrievalTool(BaseTool):
|
22
|
+
|
23
|
+
@override
|
24
|
+
def _get_declaration(self) -> types.FunctionDeclaration:
|
25
|
+
return types.FunctionDeclaration(
|
26
|
+
name=self.name,
|
27
|
+
description=self.description,
|
28
|
+
parameters=types.Schema(
|
29
|
+
type=types.Type.OBJECT,
|
30
|
+
properties={
|
31
|
+
'query': types.Schema(
|
32
|
+
type=types.Type.STRING,
|
33
|
+
description='The query to retrieve.',
|
34
|
+
),
|
35
|
+
},
|
36
|
+
),
|
37
|
+
)
|
@@ -0,0 +1,33 @@
|
|
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
|
+
"""Provides data for the agent."""
|
16
|
+
|
17
|
+
from llama_index.core import SimpleDirectoryReader
|
18
|
+
from llama_index.core import VectorStoreIndex
|
19
|
+
|
20
|
+
from .llama_index_retrieval import LlamaIndexRetrieval
|
21
|
+
|
22
|
+
|
23
|
+
class FilesRetrieval(LlamaIndexRetrieval):
|
24
|
+
|
25
|
+
def __init__(self, *, name: str, description: str, input_dir: str):
|
26
|
+
|
27
|
+
self.input_dir = input_dir
|
28
|
+
|
29
|
+
print(f'Loading data from {input_dir}')
|
30
|
+
retriever = VectorStoreIndex.from_documents(
|
31
|
+
SimpleDirectoryReader(input_dir).load_data()
|
32
|
+
).as_retriever()
|
33
|
+
super().__init__(name=name, description=description, retriever=retriever)
|
@@ -0,0 +1,41 @@
|
|
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
|
+
"""Provides data for the agent."""
|
16
|
+
|
17
|
+
from __future__ import annotations
|
18
|
+
|
19
|
+
from typing import Any
|
20
|
+
from typing import TYPE_CHECKING
|
21
|
+
|
22
|
+
from typing_extensions import override
|
23
|
+
|
24
|
+
from ..tool_context import ToolContext
|
25
|
+
from .base_retrieval_tool import BaseRetrievalTool
|
26
|
+
|
27
|
+
if TYPE_CHECKING:
|
28
|
+
from llama_index.core.base.base_retriever import BaseRetriever
|
29
|
+
|
30
|
+
|
31
|
+
class LlamaIndexRetrieval(BaseRetrievalTool):
|
32
|
+
|
33
|
+
def __init__(self, *, name: str, description: str, retriever: BaseRetriever):
|
34
|
+
super().__init__(name=name, description=description)
|
35
|
+
self.retriever = retriever
|
36
|
+
|
37
|
+
@override
|
38
|
+
async def run_async(
|
39
|
+
self, *, args: dict[str, Any], tool_context: ToolContext
|
40
|
+
) -> Any:
|
41
|
+
return self.retriever.retrieve(args['query'])[0].text
|
@@ -0,0 +1,107 @@
|
|
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
|
+
"""A retrieval tool that uses Vertex AI RAG to retrieve data."""
|
16
|
+
|
17
|
+
from __future__ import annotations
|
18
|
+
|
19
|
+
import logging
|
20
|
+
from typing import Any
|
21
|
+
from typing import TYPE_CHECKING
|
22
|
+
|
23
|
+
from google.genai import types
|
24
|
+
from typing_extensions import override
|
25
|
+
from vertexai.preview import rag
|
26
|
+
|
27
|
+
from ..tool_context import ToolContext
|
28
|
+
from .base_retrieval_tool import BaseRetrievalTool
|
29
|
+
|
30
|
+
if TYPE_CHECKING:
|
31
|
+
from ...models.llm_request import LlmRequest
|
32
|
+
|
33
|
+
logger = logging.getLogger(__name__)
|
34
|
+
|
35
|
+
|
36
|
+
class VertexAiRagRetrieval(BaseRetrievalTool):
|
37
|
+
"""A retrieval tool that uses Vertex AI RAG (Retrieval-Augmented Generation) to retrieve data."""
|
38
|
+
|
39
|
+
def __init__(
|
40
|
+
self,
|
41
|
+
*,
|
42
|
+
name: str,
|
43
|
+
description: str,
|
44
|
+
rag_corpora: list[str] = None,
|
45
|
+
rag_resources: list[rag.RagResource] = None,
|
46
|
+
similarity_top_k: int = None,
|
47
|
+
vector_distance_threshold: float = None,
|
48
|
+
):
|
49
|
+
super().__init__(name=name, description=description)
|
50
|
+
self.vertex_rag_store = types.VertexRagStore(
|
51
|
+
rag_corpora=rag_corpora,
|
52
|
+
rag_resources=rag_resources,
|
53
|
+
similarity_top_k=similarity_top_k,
|
54
|
+
vector_distance_threshold=vector_distance_threshold,
|
55
|
+
)
|
56
|
+
|
57
|
+
@override
|
58
|
+
async def process_llm_request(
|
59
|
+
self,
|
60
|
+
*,
|
61
|
+
tool_context: ToolContext,
|
62
|
+
llm_request: LlmRequest,
|
63
|
+
) -> None:
|
64
|
+
# Use Gemini built-in Vertex AI RAG tool for Gemini 2 models.
|
65
|
+
if llm_request.model and llm_request.model.startswith('gemini-2'):
|
66
|
+
llm_request.config = (
|
67
|
+
types.GenerateContentConfig()
|
68
|
+
if not llm_request.config
|
69
|
+
else llm_request.config
|
70
|
+
)
|
71
|
+
llm_request.config.tools = (
|
72
|
+
[] if not llm_request.config.tools else llm_request.config.tools
|
73
|
+
)
|
74
|
+
llm_request.config.tools.append(
|
75
|
+
types.Tool(
|
76
|
+
retrieval=types.Retrieval(vertex_rag_store=self.vertex_rag_store)
|
77
|
+
)
|
78
|
+
)
|
79
|
+
else:
|
80
|
+
# Add the function declaration to the tools
|
81
|
+
await super().process_llm_request(
|
82
|
+
tool_context=tool_context, llm_request=llm_request
|
83
|
+
)
|
84
|
+
|
85
|
+
@override
|
86
|
+
async def run_async(
|
87
|
+
self,
|
88
|
+
*,
|
89
|
+
args: dict[str, Any],
|
90
|
+
tool_context: ToolContext,
|
91
|
+
) -> Any:
|
92
|
+
|
93
|
+
response = rag.retrieval_query(
|
94
|
+
text=args['query'],
|
95
|
+
rag_resources=self.vertex_rag_store.rag_resources,
|
96
|
+
rag_corpora=self.vertex_rag_store.rag_corpora,
|
97
|
+
similarity_top_k=self.vertex_rag_store.similarity_top_k,
|
98
|
+
vector_distance_threshold=self.vertex_rag_store.vector_distance_threshold,
|
99
|
+
)
|
100
|
+
|
101
|
+
logging.debug('RAG raw response: %s', response)
|
102
|
+
|
103
|
+
return (
|
104
|
+
f'No matching result found with the config: {self.vertex_rag_store}'
|
105
|
+
if not response.contexts.contexts
|
106
|
+
else [context.text for context in response.contexts.contexts]
|
107
|
+
)
|
@@ -0,0 +1,90 @@
|
|
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 __future__ import annotations
|
16
|
+
|
17
|
+
from typing import Optional
|
18
|
+
from typing import TYPE_CHECKING
|
19
|
+
|
20
|
+
from ..agents.callback_context import CallbackContext
|
21
|
+
from ..auth.auth_credential import AuthCredential
|
22
|
+
from ..auth.auth_handler import AuthHandler
|
23
|
+
from ..auth.auth_tool import AuthConfig
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from ..agents.invocation_context import InvocationContext
|
27
|
+
from ..events.event_actions import EventActions
|
28
|
+
from ..memory.base_memory_service import SearchMemoryResponse
|
29
|
+
|
30
|
+
|
31
|
+
class ToolContext(CallbackContext):
|
32
|
+
"""The context of the tool.
|
33
|
+
|
34
|
+
This class provides the context for a tool invocation, including access to
|
35
|
+
the invocation context, function call ID, event actions, and authentication
|
36
|
+
response. It also provides methods for requesting credentials, retrieving
|
37
|
+
authentication responses, listing artifacts, and searching memory.
|
38
|
+
|
39
|
+
Attributes:
|
40
|
+
invocation_context: The invocation context of the tool.
|
41
|
+
function_call_id: The function call id of the current tool call. This id was
|
42
|
+
returned in the function call event from LLM to identify a function call.
|
43
|
+
If LLM didn't return this id, ADK will assign one to it. This id is used
|
44
|
+
to map function call response to the original function call.
|
45
|
+
event_actions: The event actions of the current tool call.
|
46
|
+
"""
|
47
|
+
|
48
|
+
def __init__(
|
49
|
+
self,
|
50
|
+
invocation_context: InvocationContext,
|
51
|
+
*,
|
52
|
+
function_call_id: Optional[str] = None,
|
53
|
+
event_actions: Optional[EventActions] = None,
|
54
|
+
):
|
55
|
+
super().__init__(invocation_context, event_actions=event_actions)
|
56
|
+
self.function_call_id = function_call_id
|
57
|
+
|
58
|
+
@property
|
59
|
+
def actions(self) -> EventActions:
|
60
|
+
return self._event_actions
|
61
|
+
|
62
|
+
def request_credential(self, auth_config: AuthConfig) -> None:
|
63
|
+
if not self.function_call_id:
|
64
|
+
raise ValueError('function_call_id is not set.')
|
65
|
+
self._event_actions.requested_auth_configs[self.function_call_id] = (
|
66
|
+
AuthHandler(auth_config).generate_auth_request()
|
67
|
+
)
|
68
|
+
|
69
|
+
def get_auth_response(self, auth_config: AuthConfig) -> AuthCredential:
|
70
|
+
return AuthHandler(auth_config).get_auth_response(self.state)
|
71
|
+
|
72
|
+
def list_artifacts(self) -> list[str]:
|
73
|
+
"""Lists the filenames of the artifacts attached to the current session."""
|
74
|
+
if self._invocation_context.artifact_service is None:
|
75
|
+
raise ValueError('Artifact service is not initialized.')
|
76
|
+
return self._invocation_context.artifact_service.list_artifact_keys(
|
77
|
+
app_name=self._invocation_context.app_name,
|
78
|
+
user_id=self._invocation_context.user_id,
|
79
|
+
session_id=self._invocation_context.session.id,
|
80
|
+
)
|
81
|
+
|
82
|
+
def search_memory(self, query: str) -> 'SearchMemoryResponse':
|
83
|
+
"""Searches the memory of the current user."""
|
84
|
+
if self._invocation_context.memory_service is None:
|
85
|
+
raise ValueError('Memory service is not available.')
|
86
|
+
return self._invocation_context.memory_service.search_memory(
|
87
|
+
app_name=self._invocation_context.app_name,
|
88
|
+
user_id=self._invocation_context.user_id,
|
89
|
+
query=query,
|
90
|
+
)
|