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,346 @@
|
|
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
|
+
"""Forked from google3/third_party/py/google/genai/_automatic_function_calling_util.py temporarily."""
|
16
|
+
|
17
|
+
import inspect
|
18
|
+
from types import FunctionType
|
19
|
+
from typing import Any
|
20
|
+
from typing import Callable
|
21
|
+
from typing import Dict
|
22
|
+
from typing import Literal
|
23
|
+
from typing import Optional
|
24
|
+
from typing import Union
|
25
|
+
|
26
|
+
from google.genai import types
|
27
|
+
import pydantic
|
28
|
+
from pydantic import BaseModel
|
29
|
+
from pydantic import create_model
|
30
|
+
from pydantic import fields as pydantic_fields
|
31
|
+
|
32
|
+
from . import function_parameter_parse_util
|
33
|
+
|
34
|
+
_py_type_2_schema_type = {
|
35
|
+
'str': types.Type.STRING,
|
36
|
+
'int': types.Type.INTEGER,
|
37
|
+
'float': types.Type.NUMBER,
|
38
|
+
'bool': types.Type.BOOLEAN,
|
39
|
+
'string': types.Type.STRING,
|
40
|
+
'integer': types.Type.INTEGER,
|
41
|
+
'number': types.Type.NUMBER,
|
42
|
+
'boolean': types.Type.BOOLEAN,
|
43
|
+
'list': types.Type.ARRAY,
|
44
|
+
'array': types.Type.ARRAY,
|
45
|
+
'tuple': types.Type.ARRAY,
|
46
|
+
'object': types.Type.OBJECT,
|
47
|
+
'Dict': types.Type.OBJECT,
|
48
|
+
'List': types.Type.ARRAY,
|
49
|
+
'Tuple': types.Type.ARRAY,
|
50
|
+
'Any': types.Type.TYPE_UNSPECIFIED,
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
def _get_fields_dict(func: Callable) -> Dict:
|
55
|
+
param_signature = dict(inspect.signature(func).parameters)
|
56
|
+
fields_dict = {
|
57
|
+
name: (
|
58
|
+
# 1. We infer the argument type here: use Any rather than None so
|
59
|
+
# it will not try to auto-infer the type based on the default value.
|
60
|
+
(
|
61
|
+
param.annotation
|
62
|
+
if param.annotation != inspect.Parameter.empty
|
63
|
+
else Any
|
64
|
+
),
|
65
|
+
pydantic.Field(
|
66
|
+
# 2. We do not support default values for now.
|
67
|
+
default=(
|
68
|
+
param.default
|
69
|
+
if param.default != inspect.Parameter.empty
|
70
|
+
# ! Need to use Undefined instead of None
|
71
|
+
else pydantic_fields.PydanticUndefined
|
72
|
+
),
|
73
|
+
# 3. Do not support parameter description for now.
|
74
|
+
description=None,
|
75
|
+
),
|
76
|
+
)
|
77
|
+
for name, param in param_signature.items()
|
78
|
+
# We do not support *args or **kwargs
|
79
|
+
if param.kind
|
80
|
+
in (
|
81
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
82
|
+
inspect.Parameter.KEYWORD_ONLY,
|
83
|
+
inspect.Parameter.POSITIONAL_ONLY,
|
84
|
+
)
|
85
|
+
}
|
86
|
+
return fields_dict
|
87
|
+
|
88
|
+
|
89
|
+
def _annotate_nullable_fields(schema: Dict):
|
90
|
+
for _, property_schema in schema.get('properties', {}).items():
|
91
|
+
# for Optional[T], the pydantic schema is:
|
92
|
+
# {
|
93
|
+
# "type": "object",
|
94
|
+
# "properties": {
|
95
|
+
# "anyOf": [
|
96
|
+
# {
|
97
|
+
# "type": "null"
|
98
|
+
# },
|
99
|
+
# {
|
100
|
+
# "type": "T"
|
101
|
+
# }
|
102
|
+
# ]
|
103
|
+
# }
|
104
|
+
# }
|
105
|
+
for type_ in property_schema.get('anyOf', []):
|
106
|
+
if type_.get('type') == 'null':
|
107
|
+
property_schema['nullable'] = True
|
108
|
+
property_schema['anyOf'].remove(type_)
|
109
|
+
break
|
110
|
+
|
111
|
+
|
112
|
+
def _annotate_required_fields(schema: Dict):
|
113
|
+
required = [
|
114
|
+
field_name
|
115
|
+
for field_name, field_schema in schema.get('properties', {}).items()
|
116
|
+
if not field_schema.get('nullable') and 'default' not in field_schema
|
117
|
+
]
|
118
|
+
schema['required'] = required
|
119
|
+
|
120
|
+
|
121
|
+
def _remove_any_of(schema: Dict):
|
122
|
+
for _, property_schema in schema.get('properties', {}).items():
|
123
|
+
union_types = property_schema.pop('anyOf', None)
|
124
|
+
# Take the first non-null type.
|
125
|
+
if union_types:
|
126
|
+
for type_ in union_types:
|
127
|
+
if type_.get('type') != 'null':
|
128
|
+
property_schema.update(type_)
|
129
|
+
|
130
|
+
|
131
|
+
def _remove_default(schema: Dict):
|
132
|
+
for _, property_schema in schema.get('properties', {}).items():
|
133
|
+
property_schema.pop('default', None)
|
134
|
+
|
135
|
+
|
136
|
+
def _remove_nullable(schema: Dict):
|
137
|
+
for _, property_schema in schema.get('properties', {}).items():
|
138
|
+
property_schema.pop('nullable', None)
|
139
|
+
|
140
|
+
|
141
|
+
def _remove_title(schema: Dict):
|
142
|
+
for _, property_schema in schema.get('properties', {}).items():
|
143
|
+
property_schema.pop('title', None)
|
144
|
+
|
145
|
+
|
146
|
+
def _get_pydantic_schema(func: Callable) -> Dict:
|
147
|
+
fields_dict = _get_fields_dict(func)
|
148
|
+
if 'tool_context' in fields_dict.keys():
|
149
|
+
fields_dict.pop('tool_context')
|
150
|
+
return pydantic.create_model(func.__name__, **fields_dict).model_json_schema()
|
151
|
+
|
152
|
+
|
153
|
+
def _process_pydantic_schema(vertexai: bool, schema: Dict) -> Dict:
|
154
|
+
_annotate_nullable_fields(schema)
|
155
|
+
_annotate_required_fields(schema)
|
156
|
+
if not vertexai:
|
157
|
+
_remove_any_of(schema)
|
158
|
+
_remove_default(schema)
|
159
|
+
_remove_nullable(schema)
|
160
|
+
_remove_title(schema)
|
161
|
+
return schema
|
162
|
+
|
163
|
+
|
164
|
+
def _map_pydantic_type_to_property_schema(property_schema: Dict):
|
165
|
+
if 'type' in property_schema:
|
166
|
+
property_schema['type'] = _py_type_2_schema_type.get(
|
167
|
+
property_schema['type'], 'TYPE_UNSPECIFIED'
|
168
|
+
)
|
169
|
+
if property_schema['type'] == 'ARRAY':
|
170
|
+
_map_pydantic_type_to_property_schema(property_schema['items'])
|
171
|
+
for type_ in property_schema.get('anyOf', []):
|
172
|
+
if 'type' in type_:
|
173
|
+
type_['type'] = _py_type_2_schema_type.get(
|
174
|
+
type_['type'], 'TYPE_UNSPECIFIED'
|
175
|
+
)
|
176
|
+
# TODO: To investigate. Unclear why a Type is needed with 'anyOf' to
|
177
|
+
# avoid google.genai.errors.ClientError: 400 INVALID_ARGUMENT.
|
178
|
+
property_schema['type'] = type_['type']
|
179
|
+
|
180
|
+
|
181
|
+
def _map_pydantic_type_to_schema_type(schema: Dict):
|
182
|
+
for _, property_schema in schema.get('properties', {}).items():
|
183
|
+
_map_pydantic_type_to_property_schema(property_schema)
|
184
|
+
|
185
|
+
|
186
|
+
def _get_return_type(func: Callable) -> Any:
|
187
|
+
return _py_type_2_schema_type.get(
|
188
|
+
inspect.signature(func).return_annotation.__name__,
|
189
|
+
inspect.signature(func).return_annotation.__name__,
|
190
|
+
)
|
191
|
+
|
192
|
+
|
193
|
+
def build_function_declaration(
|
194
|
+
func: Union[Callable, BaseModel],
|
195
|
+
ignore_params: Optional[list[str]] = None,
|
196
|
+
variant: Literal['GOOGLE_AI', 'VERTEX_AI', 'DEFAULT'] = 'GOOGLE_AI',
|
197
|
+
) -> types.FunctionDeclaration:
|
198
|
+
signature = inspect.signature(func)
|
199
|
+
should_update_signature = False
|
200
|
+
new_func = None
|
201
|
+
if not ignore_params:
|
202
|
+
ignore_params = []
|
203
|
+
for name, _ in signature.parameters.items():
|
204
|
+
if name in ignore_params:
|
205
|
+
should_update_signature = True
|
206
|
+
break
|
207
|
+
if should_update_signature:
|
208
|
+
new_params = [
|
209
|
+
param
|
210
|
+
for name, param in signature.parameters.items()
|
211
|
+
if name not in ignore_params
|
212
|
+
]
|
213
|
+
if isinstance(func, type):
|
214
|
+
fields = {
|
215
|
+
name: (param.annotation, param.default)
|
216
|
+
for name, param in signature.parameters.items()
|
217
|
+
if name not in ignore_params
|
218
|
+
}
|
219
|
+
new_func = create_model(func.__name__, **fields)
|
220
|
+
else:
|
221
|
+
new_sig = signature.replace(parameters=new_params)
|
222
|
+
new_func = FunctionType(
|
223
|
+
func.__code__,
|
224
|
+
func.__globals__,
|
225
|
+
func.__name__,
|
226
|
+
func.__defaults__,
|
227
|
+
func.__closure__,
|
228
|
+
)
|
229
|
+
new_func.__signature__ = new_sig
|
230
|
+
|
231
|
+
return (
|
232
|
+
from_function_with_options(func, variant)
|
233
|
+
if not should_update_signature
|
234
|
+
else from_function_with_options(new_func, variant)
|
235
|
+
)
|
236
|
+
|
237
|
+
|
238
|
+
def build_function_declaration_for_langchain(
|
239
|
+
vertexai: bool, name, description, func, param_pydantic_schema
|
240
|
+
) -> types.FunctionDeclaration:
|
241
|
+
param_pydantic_schema = _process_pydantic_schema(
|
242
|
+
vertexai, {'properties': param_pydantic_schema}
|
243
|
+
)['properties']
|
244
|
+
param_copy = param_pydantic_schema.copy()
|
245
|
+
required_fields = param_copy.pop('required', [])
|
246
|
+
before_param_pydantic_schema = {
|
247
|
+
'properties': param_copy,
|
248
|
+
'required': required_fields,
|
249
|
+
}
|
250
|
+
return build_function_declaration_util(
|
251
|
+
vertexai, name, description, func, before_param_pydantic_schema
|
252
|
+
)
|
253
|
+
|
254
|
+
|
255
|
+
def build_function_declaration_for_params_for_crewai(
|
256
|
+
vertexai: bool, name, description, func, param_pydantic_schema
|
257
|
+
) -> types.FunctionDeclaration:
|
258
|
+
param_pydantic_schema = _process_pydantic_schema(
|
259
|
+
vertexai, param_pydantic_schema
|
260
|
+
)
|
261
|
+
param_copy = param_pydantic_schema.copy()
|
262
|
+
return build_function_declaration_util(
|
263
|
+
vertexai, name, description, func, param_copy
|
264
|
+
)
|
265
|
+
|
266
|
+
|
267
|
+
def build_function_declaration_util(
|
268
|
+
vertexai: bool, name, description, func, before_param_pydantic_schema
|
269
|
+
) -> types.FunctionDeclaration:
|
270
|
+
_map_pydantic_type_to_schema_type(before_param_pydantic_schema)
|
271
|
+
properties = before_param_pydantic_schema.get('properties', {})
|
272
|
+
function_declaration = types.FunctionDeclaration(
|
273
|
+
parameters=types.Schema(
|
274
|
+
type='OBJECT',
|
275
|
+
properties=properties,
|
276
|
+
)
|
277
|
+
if properties
|
278
|
+
else None,
|
279
|
+
description=description,
|
280
|
+
name=name,
|
281
|
+
)
|
282
|
+
if vertexai and isinstance(func, Callable):
|
283
|
+
return_pydantic_schema = _get_return_type(func)
|
284
|
+
function_declaration.response = types.Schema(
|
285
|
+
type=return_pydantic_schema,
|
286
|
+
)
|
287
|
+
return function_declaration
|
288
|
+
|
289
|
+
|
290
|
+
def from_function_with_options(
|
291
|
+
func: Callable,
|
292
|
+
variant: Literal['GOOGLE_AI', 'VERTEX_AI', 'DEFAULT'] = 'GOOGLE_AI',
|
293
|
+
) -> 'types.FunctionDeclaration':
|
294
|
+
|
295
|
+
supported_variants = ['GOOGLE_AI', 'VERTEX_AI', 'DEFAULT']
|
296
|
+
if variant not in supported_variants:
|
297
|
+
raise ValueError(
|
298
|
+
f'Unsupported variant: {variant}. Supported variants are:'
|
299
|
+
f' {", ".join(supported_variants)}'
|
300
|
+
)
|
301
|
+
|
302
|
+
parameters_properties = {}
|
303
|
+
for name, param in inspect.signature(func).parameters.items():
|
304
|
+
if param.kind in (
|
305
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
306
|
+
inspect.Parameter.KEYWORD_ONLY,
|
307
|
+
inspect.Parameter.POSITIONAL_ONLY,
|
308
|
+
):
|
309
|
+
schema = function_parameter_parse_util._parse_schema_from_parameter(
|
310
|
+
variant, param, func.__name__
|
311
|
+
)
|
312
|
+
parameters_properties[name] = schema
|
313
|
+
declaration = types.FunctionDeclaration(
|
314
|
+
name=func.__name__,
|
315
|
+
description=func.__doc__,
|
316
|
+
)
|
317
|
+
if parameters_properties:
|
318
|
+
declaration.parameters = types.Schema(
|
319
|
+
type='OBJECT',
|
320
|
+
properties=parameters_properties,
|
321
|
+
)
|
322
|
+
if variant == 'VERTEX_AI':
|
323
|
+
declaration.parameters.required = (
|
324
|
+
function_parameter_parse_util._get_required_fields(
|
325
|
+
declaration.parameters
|
326
|
+
)
|
327
|
+
)
|
328
|
+
if not variant == 'VERTEX_AI':
|
329
|
+
return declaration
|
330
|
+
|
331
|
+
return_annotation = inspect.signature(func).return_annotation
|
332
|
+
if return_annotation is inspect._empty:
|
333
|
+
return declaration
|
334
|
+
|
335
|
+
declaration.response = (
|
336
|
+
function_parameter_parse_util._parse_schema_from_parameter(
|
337
|
+
variant,
|
338
|
+
inspect.Parameter(
|
339
|
+
'return_value',
|
340
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
341
|
+
annotation=return_annotation,
|
342
|
+
),
|
343
|
+
func.__name__,
|
344
|
+
)
|
345
|
+
)
|
346
|
+
return declaration
|
@@ -0,0 +1,176 @@
|
|
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 Any
|
18
|
+
from typing import TYPE_CHECKING
|
19
|
+
|
20
|
+
from google.genai import types
|
21
|
+
from pydantic import model_validator
|
22
|
+
from typing_extensions import override
|
23
|
+
|
24
|
+
from ..memory.in_memory_memory_service import InMemoryMemoryService
|
25
|
+
from ..runners import Runner
|
26
|
+
from ..sessions.in_memory_session_service import InMemorySessionService
|
27
|
+
from . import _automatic_function_calling_util
|
28
|
+
from .base_tool import BaseTool
|
29
|
+
from .tool_context import ToolContext
|
30
|
+
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
from ..agents.base_agent import BaseAgent
|
33
|
+
from ..agents.llm_agent import LlmAgent
|
34
|
+
|
35
|
+
|
36
|
+
class AgentTool(BaseTool):
|
37
|
+
"""A tool that wraps an agent.
|
38
|
+
|
39
|
+
This tool allows an agent to be called as a tool within a larger application.
|
40
|
+
The agent's input schema is used to define the tool's input parameters, and
|
41
|
+
the agent's output is returned as the tool's result.
|
42
|
+
|
43
|
+
Attributes:
|
44
|
+
agent: The agent to wrap.
|
45
|
+
skip_summarization: Whether to skip summarization of the agent output.
|
46
|
+
"""
|
47
|
+
|
48
|
+
def __init__(self, agent: BaseAgent):
|
49
|
+
self.agent = agent
|
50
|
+
self.skip_summarization: bool = False
|
51
|
+
"""Whether to skip summarization of the agent output."""
|
52
|
+
|
53
|
+
super().__init__(name=agent.name, description=agent.description)
|
54
|
+
|
55
|
+
@model_validator(mode='before')
|
56
|
+
@classmethod
|
57
|
+
def populate_name(cls, data: Any) -> Any:
|
58
|
+
data['name'] = data['agent'].name
|
59
|
+
return data
|
60
|
+
|
61
|
+
@override
|
62
|
+
def _get_declaration(self) -> types.FunctionDeclaration:
|
63
|
+
from ..agents.llm_agent import LlmAgent
|
64
|
+
|
65
|
+
if isinstance(self.agent, LlmAgent) and self.agent.input_schema:
|
66
|
+
result = _automatic_function_calling_util.build_function_declaration(
|
67
|
+
func=self.agent.input_schema, variant=self._api_variant
|
68
|
+
)
|
69
|
+
else:
|
70
|
+
result = types.FunctionDeclaration(
|
71
|
+
parameters=types.Schema(
|
72
|
+
type=types.Type.OBJECT,
|
73
|
+
properties={
|
74
|
+
'request': types.Schema(
|
75
|
+
type=types.Type.STRING,
|
76
|
+
),
|
77
|
+
},
|
78
|
+
required=['request'],
|
79
|
+
),
|
80
|
+
description=self.agent.description,
|
81
|
+
name=self.name,
|
82
|
+
)
|
83
|
+
result.name = self.name
|
84
|
+
return result
|
85
|
+
|
86
|
+
@override
|
87
|
+
async def run_async(
|
88
|
+
self,
|
89
|
+
*,
|
90
|
+
args: dict[str, Any],
|
91
|
+
tool_context: ToolContext,
|
92
|
+
) -> Any:
|
93
|
+
from ..agents.llm_agent import LlmAgent
|
94
|
+
|
95
|
+
if self.skip_summarization:
|
96
|
+
tool_context.actions.skip_summarization = True
|
97
|
+
|
98
|
+
if isinstance(self.agent, LlmAgent) and self.agent.input_schema:
|
99
|
+
input_value = self.agent.input_schema.model_validate(args)
|
100
|
+
else:
|
101
|
+
input_value = args['request']
|
102
|
+
|
103
|
+
if isinstance(self.agent, LlmAgent) and self.agent.input_schema:
|
104
|
+
if isinstance(input_value, dict):
|
105
|
+
input_value = self.agent.input_schema.model_validate(input_value)
|
106
|
+
if not isinstance(input_value, self.agent.input_schema):
|
107
|
+
raise ValueError(
|
108
|
+
f'Input value {input_value} is not of type'
|
109
|
+
f' `{self.agent.input_schema}`.'
|
110
|
+
)
|
111
|
+
content = types.Content(
|
112
|
+
role='user',
|
113
|
+
parts=[
|
114
|
+
types.Part.from_text(
|
115
|
+
text=input_value.model_dump_json(exclude_none=True)
|
116
|
+
)
|
117
|
+
],
|
118
|
+
)
|
119
|
+
else:
|
120
|
+
content = types.Content(
|
121
|
+
role='user',
|
122
|
+
parts=[types.Part.from_text(text=input_value)],
|
123
|
+
)
|
124
|
+
runner = Runner(
|
125
|
+
app_name=self.agent.name,
|
126
|
+
agent=self.agent,
|
127
|
+
# TODO(kech): Remove the access to the invocation context.
|
128
|
+
# It seems we don't need re-use artifact_service if we forward below.
|
129
|
+
artifact_service=tool_context._invocation_context.artifact_service,
|
130
|
+
session_service=InMemorySessionService(),
|
131
|
+
memory_service=InMemoryMemoryService(),
|
132
|
+
)
|
133
|
+
session = runner.session_service.create_session(
|
134
|
+
app_name=self.agent.name,
|
135
|
+
user_id='tmp_user',
|
136
|
+
state=tool_context.state.to_dict(),
|
137
|
+
)
|
138
|
+
|
139
|
+
last_event = None
|
140
|
+
async for event in runner.run_async(
|
141
|
+
user_id=session.user_id, session_id=session.id, new_message=content
|
142
|
+
):
|
143
|
+
# Forward state delta to parent session.
|
144
|
+
if event.actions.state_delta:
|
145
|
+
tool_context.state.update(event.actions.state_delta)
|
146
|
+
last_event = event
|
147
|
+
|
148
|
+
if runner.artifact_service:
|
149
|
+
# Forward all artifacts to parent session.
|
150
|
+
for artifact_name in runner.artifact_service.list_artifact_keys(
|
151
|
+
app_name=session.app_name,
|
152
|
+
user_id=session.user_id,
|
153
|
+
session_id=session.id,
|
154
|
+
):
|
155
|
+
if artifact := runner.artifact_service.load_artifact(
|
156
|
+
app_name=session.app_name,
|
157
|
+
user_id=session.user_id,
|
158
|
+
session_id=session.id,
|
159
|
+
filename=artifact_name,
|
160
|
+
):
|
161
|
+
tool_context.save_artifact(filename=artifact_name, artifact=artifact)
|
162
|
+
|
163
|
+
if (
|
164
|
+
not last_event
|
165
|
+
or not last_event.content
|
166
|
+
or not last_event.content.parts
|
167
|
+
or not last_event.content.parts[0].text
|
168
|
+
):
|
169
|
+
return ''
|
170
|
+
if isinstance(self.agent, LlmAgent) and self.agent.output_schema:
|
171
|
+
tool_result = self.agent.output_schema.model_validate_json(
|
172
|
+
last_event.content.parts[0].text
|
173
|
+
).model_dump(exclude_none=True)
|
174
|
+
else:
|
175
|
+
tool_result = last_event.content.parts[0].text
|
176
|
+
return tool_result
|
@@ -0,0 +1,19 @@
|
|
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 .apihub_toolset import APIHubToolset
|
16
|
+
|
17
|
+
__all__ = [
|
18
|
+
'APIHubToolset',
|
19
|
+
]
|