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,253 @@
|
|
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
|
+
import json
|
16
|
+
from typing import Optional
|
17
|
+
from google.adk.tools.application_integration_tool.clients.connections_client import ConnectionsClient
|
18
|
+
import google.auth
|
19
|
+
from google.auth import default as default_service_credential
|
20
|
+
import google.auth.transport.requests
|
21
|
+
from google.auth.transport.requests import Request
|
22
|
+
from google.oauth2 import service_account
|
23
|
+
import requests
|
24
|
+
|
25
|
+
|
26
|
+
class IntegrationClient:
|
27
|
+
"""A client for interacting with Google Cloud Application Integration.
|
28
|
+
|
29
|
+
This class provides methods for retrieving OpenAPI spec for an integration or
|
30
|
+
a connection.
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(
|
34
|
+
self,
|
35
|
+
project: str,
|
36
|
+
location: str,
|
37
|
+
integration: Optional[str] = None,
|
38
|
+
trigger: Optional[str] = None,
|
39
|
+
connection: Optional[str] = None,
|
40
|
+
entity_operations: Optional[dict[str, list[str]]] = None,
|
41
|
+
actions: Optional[list[str]] = None,
|
42
|
+
service_account_json: Optional[str] = None,
|
43
|
+
):
|
44
|
+
"""Initializes the ApplicationIntegrationClient.
|
45
|
+
|
46
|
+
Args:
|
47
|
+
project: The Google Cloud project ID.
|
48
|
+
location: The Google Cloud location (e.g., us-central1).
|
49
|
+
integration: The integration name.
|
50
|
+
trigger: The trigger ID for the integration.
|
51
|
+
connection: The connection name.
|
52
|
+
entity_operations: A dictionary mapping entity names to a list of
|
53
|
+
operations (e.g., LIST, CREATE, UPDATE, DELETE, GET).
|
54
|
+
actions: List of actions.
|
55
|
+
service_account_json: The service account configuration as a dictionary.
|
56
|
+
Required if not using default service credential. Used for fetching
|
57
|
+
connection details.
|
58
|
+
"""
|
59
|
+
self.project = project
|
60
|
+
self.location = location
|
61
|
+
self.integration = integration
|
62
|
+
self.trigger = trigger
|
63
|
+
self.connection = connection
|
64
|
+
self.entity_operations = (
|
65
|
+
entity_operations if entity_operations is not None else {}
|
66
|
+
)
|
67
|
+
self.actions = actions if actions is not None else []
|
68
|
+
self.service_account_json = service_account_json
|
69
|
+
self.credential_cache = None
|
70
|
+
|
71
|
+
def get_openapi_spec_for_integration(self):
|
72
|
+
"""Gets the OpenAPI spec for the integration.
|
73
|
+
|
74
|
+
Returns:
|
75
|
+
dict: The OpenAPI spec as a dictionary.
|
76
|
+
Raises:
|
77
|
+
PermissionError: If there are credential issues.
|
78
|
+
ValueError: If there's a request error or processing error.
|
79
|
+
Exception: For any other unexpected errors.
|
80
|
+
"""
|
81
|
+
try:
|
82
|
+
url = f"https://{self.location}-integrations.googleapis.com/v1/projects/{self.project}/locations/{self.location}:generateOpenApiSpec"
|
83
|
+
headers = {
|
84
|
+
"Content-Type": "application/json",
|
85
|
+
"Authorization": f"Bearer {self._get_access_token()}",
|
86
|
+
}
|
87
|
+
data = {
|
88
|
+
"apiTriggerResources": [
|
89
|
+
{
|
90
|
+
"integrationResource": self.integration,
|
91
|
+
"triggerId": [self.trigger],
|
92
|
+
},
|
93
|
+
],
|
94
|
+
"fileFormat": "JSON",
|
95
|
+
}
|
96
|
+
response = requests.post(url, headers=headers, json=data)
|
97
|
+
response.raise_for_status()
|
98
|
+
spec = response.json().get("openApiSpec", {})
|
99
|
+
return json.loads(spec)
|
100
|
+
except google.auth.exceptions.DefaultCredentialsError as e:
|
101
|
+
raise PermissionError(f"Credentials error: {e}") from e
|
102
|
+
except requests.exceptions.RequestException as e:
|
103
|
+
if (
|
104
|
+
"404" in str(e)
|
105
|
+
or "Not found" in str(e)
|
106
|
+
or "400" in str(e)
|
107
|
+
or "Bad request" in str(e)
|
108
|
+
):
|
109
|
+
raise ValueError(
|
110
|
+
"Invalid request. Please check the provided values of"
|
111
|
+
f" project({self.project}), location({self.location}),"
|
112
|
+
f" integration({self.integration}) and trigger({self.trigger})."
|
113
|
+
) from e
|
114
|
+
raise ValueError(f"Request error: {e}") from e
|
115
|
+
except Exception as e:
|
116
|
+
raise Exception(f"An unexpected error occurred: {e}") from e
|
117
|
+
|
118
|
+
def get_openapi_spec_for_connection(self, tool_name="", tool_instructions=""):
|
119
|
+
"""Gets the OpenAPI spec for the connection.
|
120
|
+
|
121
|
+
Returns:
|
122
|
+
dict: The OpenAPI spec as a dictionary.
|
123
|
+
Raises:
|
124
|
+
ValueError: If there's an error retrieving the OpenAPI spec.
|
125
|
+
PermissionError: If there are credential issues.
|
126
|
+
Exception: For any other unexpected errors.
|
127
|
+
"""
|
128
|
+
# Application Integration needs to be provisioned in the same region as connection and an integration with name "ExecuteConnection" and trigger "api_trigger/ExecuteConnection" should be created as per the documentation.
|
129
|
+
integration_name = "ExecuteConnection"
|
130
|
+
connections_client = ConnectionsClient(
|
131
|
+
self.project,
|
132
|
+
self.location,
|
133
|
+
self.connection,
|
134
|
+
self.service_account_json,
|
135
|
+
)
|
136
|
+
if not self.entity_operations and not self.actions:
|
137
|
+
raise ValueError(
|
138
|
+
"No entity operations or actions provided. Please provide at least"
|
139
|
+
" one of them."
|
140
|
+
)
|
141
|
+
connector_spec = connections_client.get_connector_base_spec()
|
142
|
+
for entity, operations in self.entity_operations.items():
|
143
|
+
schema, supported_operations = (
|
144
|
+
connections_client.get_entity_schema_and_operations(entity)
|
145
|
+
)
|
146
|
+
if not operations:
|
147
|
+
operations = supported_operations
|
148
|
+
json_schema_as_string = json.dumps(schema)
|
149
|
+
entity_lower = entity
|
150
|
+
connector_spec["components"]["schemas"][
|
151
|
+
f"connectorInputPayload_{entity_lower}"
|
152
|
+
] = connections_client.connector_payload(schema)
|
153
|
+
for operation in operations:
|
154
|
+
operation_lower = operation.lower()
|
155
|
+
path = f"/v2/projects/{self.project}/locations/{self.location}/integrations/{integration_name}:execute?triggerId=api_trigger/{integration_name}#{operation_lower}_{entity_lower}"
|
156
|
+
if operation_lower == "create":
|
157
|
+
connector_spec["paths"][path] = connections_client.create_operation(
|
158
|
+
entity_lower, tool_name, tool_instructions
|
159
|
+
)
|
160
|
+
connector_spec["components"]["schemas"][
|
161
|
+
f"create_{entity_lower}_Request"
|
162
|
+
] = connections_client.create_operation_request(entity_lower)
|
163
|
+
elif operation_lower == "update":
|
164
|
+
connector_spec["paths"][path] = connections_client.update_operation(
|
165
|
+
entity_lower, tool_name, tool_instructions
|
166
|
+
)
|
167
|
+
connector_spec["components"]["schemas"][
|
168
|
+
f"update_{entity_lower}_Request"
|
169
|
+
] = connections_client.update_operation_request(entity_lower)
|
170
|
+
elif operation_lower == "delete":
|
171
|
+
connector_spec["paths"][path] = connections_client.delete_operation(
|
172
|
+
entity_lower, tool_name, tool_instructions
|
173
|
+
)
|
174
|
+
connector_spec["components"]["schemas"][
|
175
|
+
f"delete_{entity_lower}_Request"
|
176
|
+
] = connections_client.delete_operation_request()
|
177
|
+
elif operation_lower == "list":
|
178
|
+
connector_spec["paths"][path] = connections_client.list_operation(
|
179
|
+
entity_lower, json_schema_as_string, tool_name, tool_instructions
|
180
|
+
)
|
181
|
+
connector_spec["components"]["schemas"][
|
182
|
+
f"list_{entity_lower}_Request"
|
183
|
+
] = connections_client.list_operation_request()
|
184
|
+
elif operation_lower == "get":
|
185
|
+
connector_spec["paths"][path] = connections_client.get_operation(
|
186
|
+
entity_lower, json_schema_as_string, tool_name, tool_instructions
|
187
|
+
)
|
188
|
+
connector_spec["components"]["schemas"][
|
189
|
+
f"get_{entity_lower}_Request"
|
190
|
+
] = connections_client.get_operation_request()
|
191
|
+
else:
|
192
|
+
raise ValueError(
|
193
|
+
f"Invalid operation: {operation} for entity: {entity}"
|
194
|
+
)
|
195
|
+
for action in self.actions:
|
196
|
+
action_details = connections_client.get_action_schema(action)
|
197
|
+
input_schema = action_details["inputSchema"]
|
198
|
+
output_schema = action_details["outputSchema"]
|
199
|
+
action_display_name = action_details["displayName"]
|
200
|
+
operation = "EXECUTE_ACTION"
|
201
|
+
if action == "ExecuteCustomQuery":
|
202
|
+
connector_spec["components"]["schemas"][
|
203
|
+
f"{action}_Request"
|
204
|
+
] = connections_client.execute_custom_query_request()
|
205
|
+
operation = "EXECUTE_QUERY"
|
206
|
+
else:
|
207
|
+
connector_spec["components"]["schemas"][
|
208
|
+
f"{action_display_name}_Request"
|
209
|
+
] = connections_client.action_request(action_display_name)
|
210
|
+
connector_spec["components"]["schemas"][
|
211
|
+
f"connectorInputPayload_{action_display_name}"
|
212
|
+
] = connections_client.connector_payload(input_schema)
|
213
|
+
connector_spec["components"]["schemas"][
|
214
|
+
f"connectorOutputPayload_{action_display_name}"
|
215
|
+
] = connections_client.connector_payload(output_schema)
|
216
|
+
connector_spec["components"]["schemas"][
|
217
|
+
f"{action_display_name}_Response"
|
218
|
+
] = connections_client.action_response(action_display_name)
|
219
|
+
path = f"/v2/projects/{self.project}/locations/{self.location}/integrations/{integration_name}:execute?triggerId=api_trigger/{integration_name}#{action}"
|
220
|
+
connector_spec["paths"][path] = connections_client.get_action_operation(
|
221
|
+
action, operation, action_display_name, tool_name, tool_instructions
|
222
|
+
)
|
223
|
+
return connector_spec
|
224
|
+
|
225
|
+
def _get_access_token(self) -> str:
|
226
|
+
"""Gets the access token for the service account or using default credentials.
|
227
|
+
|
228
|
+
Returns:
|
229
|
+
The access token.
|
230
|
+
"""
|
231
|
+
if self.credential_cache and not self.credential_cache.expired:
|
232
|
+
return self.credential_cache.token
|
233
|
+
|
234
|
+
if self.service_account_json:
|
235
|
+
credentials = service_account.Credentials.from_service_account_info(
|
236
|
+
json.loads(self.service_account_json),
|
237
|
+
scopes=["https://www.googleapis.com/auth/cloud-platform"],
|
238
|
+
)
|
239
|
+
else:
|
240
|
+
try:
|
241
|
+
credentials, _ = default_service_credential()
|
242
|
+
except:
|
243
|
+
credentials = None
|
244
|
+
|
245
|
+
if not credentials:
|
246
|
+
raise ValueError(
|
247
|
+
"Please provide a service account that has the required permissions"
|
248
|
+
" to access the connection."
|
249
|
+
)
|
250
|
+
|
251
|
+
credentials.refresh(Request())
|
252
|
+
self.credential_cache = credentials
|
253
|
+
return credentials.token
|
@@ -0,0 +1,144 @@
|
|
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 abc import ABC
|
18
|
+
import os
|
19
|
+
from typing import Any
|
20
|
+
from typing import Optional
|
21
|
+
from typing import TYPE_CHECKING
|
22
|
+
|
23
|
+
from deprecated import deprecated
|
24
|
+
from google.genai import types
|
25
|
+
|
26
|
+
from .tool_context import ToolContext
|
27
|
+
|
28
|
+
if TYPE_CHECKING:
|
29
|
+
from ..models.llm_request import LlmRequest
|
30
|
+
|
31
|
+
|
32
|
+
class BaseTool(ABC):
|
33
|
+
"""The base class for all tools."""
|
34
|
+
|
35
|
+
name: str
|
36
|
+
"""The name of the tool."""
|
37
|
+
description: str
|
38
|
+
"""The description of the tool."""
|
39
|
+
|
40
|
+
is_long_running: bool = False
|
41
|
+
"""Whether the tool is a long running operation, which typically returns a
|
42
|
+
resource id first and finishes the operation later."""
|
43
|
+
|
44
|
+
def __init__(self, *, name, description, is_long_running: bool = False):
|
45
|
+
self.name = name
|
46
|
+
self.description = description
|
47
|
+
self.is_long_running = is_long_running
|
48
|
+
|
49
|
+
def _get_declaration(self) -> Optional[types.FunctionDeclaration]:
|
50
|
+
"""Gets the OpenAPI specification of this tool in the form of a FunctionDeclaration.
|
51
|
+
|
52
|
+
NOTE
|
53
|
+
- Required if subclass uses the default implementation of
|
54
|
+
`process_llm_request` to add function declaration to LLM request.
|
55
|
+
- Otherwise, can be skipped, e.g. for a built-in GoogleSearch tool for
|
56
|
+
Gemini.
|
57
|
+
|
58
|
+
Returns:
|
59
|
+
The FunctionDeclaration of this tool, or None if it doesn't need to be
|
60
|
+
added to LlmRequest.config.
|
61
|
+
"""
|
62
|
+
return None
|
63
|
+
|
64
|
+
async def run_async(
|
65
|
+
self, *, args: dict[str, Any], tool_context: ToolContext
|
66
|
+
) -> Any:
|
67
|
+
"""Runs the tool with the given arguments and context.
|
68
|
+
|
69
|
+
NOTE
|
70
|
+
- Required if this tool needs to run at the client side.
|
71
|
+
- Otherwise, can be skipped, e.g. for a built-in GoogleSearch tool for
|
72
|
+
Gemini.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
args: The LLM-filled arguments.
|
76
|
+
ctx: The context of the tool.
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
The result of running the tool.
|
80
|
+
"""
|
81
|
+
raise NotImplementedError(f'{type(self)} is not implemented')
|
82
|
+
|
83
|
+
async def process_llm_request(
|
84
|
+
self, *, tool_context: ToolContext, llm_request: LlmRequest
|
85
|
+
) -> None:
|
86
|
+
"""Processes the outgoing LLM request for this tool.
|
87
|
+
|
88
|
+
Use cases:
|
89
|
+
- Most common use case is adding this tool to the LLM request.
|
90
|
+
- Some tools may just preprocess the LLM request before it's sent out.
|
91
|
+
|
92
|
+
Args:
|
93
|
+
tool_context: The context of the tool.
|
94
|
+
llm_request: The outgoing LLM request, mutable this method.
|
95
|
+
"""
|
96
|
+
if (function_declaration := self._get_declaration()) is None:
|
97
|
+
return
|
98
|
+
|
99
|
+
llm_request.tools_dict[self.name] = self
|
100
|
+
if tool_with_function_declarations := _find_tool_with_function_declarations(
|
101
|
+
llm_request
|
102
|
+
):
|
103
|
+
if tool_with_function_declarations.function_declarations is None:
|
104
|
+
tool_with_function_declarations.function_declarations = []
|
105
|
+
tool_with_function_declarations.function_declarations.append(
|
106
|
+
function_declaration
|
107
|
+
)
|
108
|
+
else:
|
109
|
+
llm_request.config = (
|
110
|
+
types.GenerateContentConfig()
|
111
|
+
if not llm_request.config
|
112
|
+
else llm_request.config
|
113
|
+
)
|
114
|
+
llm_request.config.tools = (
|
115
|
+
[] if not llm_request.config.tools else llm_request.config.tools
|
116
|
+
)
|
117
|
+
llm_request.config.tools.append(
|
118
|
+
types.Tool(function_declarations=[function_declaration])
|
119
|
+
)
|
120
|
+
|
121
|
+
@property
|
122
|
+
def _api_variant(self) -> str:
|
123
|
+
use_vertexai = os.environ.get('GOOGLE_GENAI_USE_VERTEXAI', '0').lower() in [
|
124
|
+
'true',
|
125
|
+
'1',
|
126
|
+
]
|
127
|
+
return 'VERTEX_AI' if use_vertexai else 'GOOGLE_AI'
|
128
|
+
|
129
|
+
|
130
|
+
def _find_tool_with_function_declarations(
|
131
|
+
llm_request: LlmRequest,
|
132
|
+
) -> Optional[types.Tool]:
|
133
|
+
# TODO: add individual tool with declaration and merge in google_llm.py
|
134
|
+
if not llm_request.config or not llm_request.config.tools:
|
135
|
+
return None
|
136
|
+
|
137
|
+
return next(
|
138
|
+
(
|
139
|
+
tool
|
140
|
+
for tool in llm_request.config.tools
|
141
|
+
if isinstance(tool, types.Tool) and tool.function_declarations
|
142
|
+
),
|
143
|
+
None,
|
144
|
+
)
|
@@ -0,0 +1,59 @@
|
|
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 TYPE_CHECKING
|
18
|
+
|
19
|
+
from google.genai import types
|
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 BuiltInCodeExecutionTool(BaseTool):
|
30
|
+
"""A built-in code execution tool that is automatically invoked by Gemini 2 models.
|
31
|
+
|
32
|
+
This tool operates internally within the model and does not require or perform
|
33
|
+
local code execution.
|
34
|
+
"""
|
35
|
+
|
36
|
+
def __init__(self):
|
37
|
+
# Name and description are not used because this is a model built-in tool.
|
38
|
+
super().__init__(name='code_execution', description='code_execution')
|
39
|
+
|
40
|
+
@override
|
41
|
+
async def process_llm_request(
|
42
|
+
self,
|
43
|
+
*,
|
44
|
+
tool_context: ToolContext,
|
45
|
+
llm_request: LlmRequest,
|
46
|
+
) -> None:
|
47
|
+
if llm_request.model and llm_request.model.startswith('gemini-2'):
|
48
|
+
llm_request.config = llm_request.config or types.GenerateContentConfig()
|
49
|
+
llm_request.config.tools = llm_request.config.tools or []
|
50
|
+
llm_request.config.tools.append(
|
51
|
+
types.Tool(code_execution=types.ToolCodeExecution())
|
52
|
+
)
|
53
|
+
else:
|
54
|
+
raise ValueError(
|
55
|
+
f'Code execution tool is not supported for model {llm_request.model}'
|
56
|
+
)
|
57
|
+
|
58
|
+
|
59
|
+
built_in_code_execution = BuiltInCodeExecutionTool()
|
@@ -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 google.genai import types
|
18
|
+
from typing_extensions import override
|
19
|
+
|
20
|
+
from . import _automatic_function_calling_util
|
21
|
+
from .function_tool import FunctionTool
|
22
|
+
|
23
|
+
try:
|
24
|
+
from crewai.tools import BaseTool as CrewaiBaseTool
|
25
|
+
except ImportError as e:
|
26
|
+
import sys
|
27
|
+
|
28
|
+
if sys.version_info < (3, 10):
|
29
|
+
raise ImportError(
|
30
|
+
"Crewai Tools require Python 3.10+. Please upgrade your Python version."
|
31
|
+
) from e
|
32
|
+
else:
|
33
|
+
raise ImportError(
|
34
|
+
"Crewai Tools require pip install 'google-adk[extensions]'."
|
35
|
+
) from e
|
36
|
+
|
37
|
+
|
38
|
+
class CrewaiTool(FunctionTool):
|
39
|
+
"""Use this class to wrap a CrewAI tool.
|
40
|
+
|
41
|
+
If the original tool name and description are not suitable, you can override
|
42
|
+
them in the constructor.
|
43
|
+
"""
|
44
|
+
|
45
|
+
tool: CrewaiBaseTool
|
46
|
+
"""The wrapped CrewAI tool."""
|
47
|
+
|
48
|
+
def __init__(self, tool: CrewaiBaseTool, *, name: str, description: str):
|
49
|
+
super().__init__(tool.run)
|
50
|
+
self.tool = tool
|
51
|
+
if name:
|
52
|
+
self.name = name
|
53
|
+
elif tool.name:
|
54
|
+
# Right now, CrewAI tool name contains white spaces. White spaces are
|
55
|
+
# not supported in our framework. So we replace them with "_".
|
56
|
+
self.name = tool.name.replace(" ", "_").lower()
|
57
|
+
if description:
|
58
|
+
self.description = description
|
59
|
+
elif tool.description:
|
60
|
+
self.description = tool.description
|
61
|
+
|
62
|
+
@override
|
63
|
+
def _get_declaration(self) -> types.FunctionDeclaration:
|
64
|
+
"""Build the function declaration for the tool."""
|
65
|
+
function_declaration = _automatic_function_calling_util.build_function_declaration_for_params_for_crewai(
|
66
|
+
False,
|
67
|
+
self.name,
|
68
|
+
self.description,
|
69
|
+
self.func,
|
70
|
+
self.tool.args_schema.model_json_schema(),
|
71
|
+
)
|
72
|
+
return function_declaration
|
@@ -0,0 +1,62 @@
|
|
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 TYPE_CHECKING
|
18
|
+
from typing import Union
|
19
|
+
|
20
|
+
from pydantic import TypeAdapter
|
21
|
+
from typing_extensions import override
|
22
|
+
|
23
|
+
from ..examples import example_util
|
24
|
+
from ..examples.base_example_provider import BaseExampleProvider
|
25
|
+
from ..examples.example import Example
|
26
|
+
from .base_tool import BaseTool
|
27
|
+
from .tool_context import ToolContext
|
28
|
+
|
29
|
+
if TYPE_CHECKING:
|
30
|
+
from ..models.llm_request import LlmRequest
|
31
|
+
|
32
|
+
|
33
|
+
class ExampleTool(BaseTool):
|
34
|
+
"""A tool that adds (few-shot) examples to the LLM request.
|
35
|
+
|
36
|
+
Attributes:
|
37
|
+
examples: The examples to add to the LLM request.
|
38
|
+
"""
|
39
|
+
|
40
|
+
def __init__(self, examples: Union[list[Example], BaseExampleProvider]):
|
41
|
+
# Name and description are not used because this tool only changes
|
42
|
+
# llm_request.
|
43
|
+
super().__init__(name='example_tool', description='example tool')
|
44
|
+
self.examples = (
|
45
|
+
TypeAdapter(list[Example]).validate_python(examples)
|
46
|
+
if isinstance(examples, list)
|
47
|
+
else examples
|
48
|
+
)
|
49
|
+
|
50
|
+
@override
|
51
|
+
async def process_llm_request(
|
52
|
+
self, *, tool_context: ToolContext, llm_request: LlmRequest
|
53
|
+
) -> None:
|
54
|
+
parts = tool_context.user_content.parts
|
55
|
+
if not parts or not parts[0].text:
|
56
|
+
return
|
57
|
+
|
58
|
+
llm_request.append_instructions([
|
59
|
+
example_util.build_example_si(
|
60
|
+
self.examples, parts[0].text, llm_request.model
|
61
|
+
)
|
62
|
+
])
|
@@ -0,0 +1,23 @@
|
|
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 .tool_context import ToolContext
|
16
|
+
|
17
|
+
|
18
|
+
def exit_loop(tool_context: ToolContext):
|
19
|
+
"""Exits the loop.
|
20
|
+
|
21
|
+
Call this function only when you are instructed to do so.
|
22
|
+
"""
|
23
|
+
tool_context.actions.escalate = True
|