google-adk 0.0.1__py3-none-any.whl → 0.0.3__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/._version.py +0 -0
- 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 +148 -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-SY2WYYGV.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 +524 -0
- google/adk/cli/fast_api.py +784 -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/docs/Makefile +20 -0
- google/adk/docs/build/doctrees/google-adk.doctree +0 -0
- google/adk/docs/build/html/_sources/google-adk.rst.txt +98 -0
- google/adk/docs/build/html/_sources/index.rst.txt +7 -0
- google/adk/docs/build/html/_static/autodoc_pydantic.css +27 -0
- google/adk/docs/build/html/_static/basic.css +925 -0
- google/adk/docs/build/html/_static/debug.css +85 -0
- google/adk/docs/build/html/_static/doctools.js +156 -0
- google/adk/docs/build/html/_static/documentation_options.js +29 -0
- google/adk/docs/build/html/_static/file.png +0 -0
- google/adk/docs/build/html/_static/language_data.js +199 -0
- google/adk/docs/build/html/_static/minus.png +0 -0
- google/adk/docs/build/html/_static/plus.png +0 -0
- google/adk/docs/build/html/_static/pygments.css +274 -0
- google/adk/docs/build/html/_static/scripts/furo-extensions.js +16 -0
- google/adk/docs/build/html/_static/scripts/furo.js +19 -0
- google/adk/docs/build/html/_static/scripts/furo.js.LICENSE.txt +7 -0
- google/adk/docs/build/html/_static/scripts/furo.js.map +1 -0
- google/adk/docs/build/html/_static/searchtools.js +620 -0
- google/adk/docs/build/html/_static/skeleton.css +312 -0
- google/adk/docs/build/html/_static/sphinx_highlight.js +170 -0
- google/adk/docs/build/html/_static/styles/furo-extensions.css +18 -0
- google/adk/docs/build/html/_static/styles/furo-extensions.css.map +1 -0
- google/adk/docs/build/html/_static/styles/furo.css +18 -0
- google/adk/docs/build/html/_static/styles/furo.css.map +1 -0
- google/adk/docs/build/html/genindex.html +861 -0
- google/adk/docs/build/html/google-adk.html +5461 -0
- google/adk/docs/build/html/index.html +567 -0
- google/adk/docs/build/html/objects.inv +0 -0
- google/adk/docs/build/html/py-modindex.html +373 -0
- google/adk/docs/build/html/search.html +333 -0
- google/adk/docs/build/html/searchindex.js +17 -0
- google/adk/docs/source/conf.py +133 -0
- google/adk/docs/source/google-adk.rst +98 -0
- google/adk/docs/source/index.rst +7 -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.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.3.dist-info/METADATA +73 -0
- google_adk-0.0.3.dist-info/RECORD +340 -0
- {google_adk-0.0.1.dist-info → google_adk-0.0.3.dist-info}/WHEEL +1 -2
- google_adk-0.0.3.dist-info/entry_points.txt +3 -0
- agent_kit/__init__.py +0 -0
- google_adk-0.0.1.dist-info/LICENSE.txt +0 -170
- 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,496 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from typing import Any
|
16
|
+
from typing import Dict
|
17
|
+
from typing import List
|
18
|
+
from typing import Literal
|
19
|
+
from typing import Optional
|
20
|
+
from typing import Tuple
|
21
|
+
from typing import Union
|
22
|
+
|
23
|
+
from fastapi.openapi.models import Operation
|
24
|
+
from google.genai.types import FunctionDeclaration
|
25
|
+
from google.genai.types import Schema
|
26
|
+
import requests
|
27
|
+
from typing_extensions import override
|
28
|
+
|
29
|
+
from ....auth.auth_credential import AuthCredential
|
30
|
+
from ....auth.auth_schemes import AuthScheme
|
31
|
+
from ....tools import BaseTool
|
32
|
+
from ...tool_context import ToolContext
|
33
|
+
from ..auth.auth_helpers import credential_to_param
|
34
|
+
from ..auth.auth_helpers import dict_to_auth_scheme
|
35
|
+
from ..auth.credential_exchangers.auto_auth_credential_exchanger import AutoAuthCredentialExchanger
|
36
|
+
from ..common.common import ApiParameter
|
37
|
+
from ..common.common import to_snake_case
|
38
|
+
from .openapi_spec_parser import OperationEndpoint
|
39
|
+
from .openapi_spec_parser import ParsedOperation
|
40
|
+
from .operation_parser import OperationParser
|
41
|
+
from .tool_auth_handler import ToolAuthHandler
|
42
|
+
|
43
|
+
|
44
|
+
def snake_to_lower_camel(snake_case_string: str):
|
45
|
+
"""Converts a snake_case string to a lower_camel_case string.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
snake_case_string: The input snake_case string.
|
49
|
+
|
50
|
+
Returns:
|
51
|
+
The lower_camel_case string.
|
52
|
+
"""
|
53
|
+
if "_" not in snake_case_string:
|
54
|
+
return snake_case_string
|
55
|
+
|
56
|
+
return "".join([
|
57
|
+
s.lower() if i == 0 else s.capitalize()
|
58
|
+
for i, s in enumerate(snake_case_string.split("_"))
|
59
|
+
])
|
60
|
+
|
61
|
+
|
62
|
+
def to_gemini_schema(openapi_schema: Optional[Dict[str, Any]] = None) -> Schema:
|
63
|
+
"""Converts an OpenAPI schema dictionary to a Gemini Schema object.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
openapi_schema: The OpenAPI schema dictionary.
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
A Pydantic Schema object. Returns None if input is None.
|
70
|
+
Raises TypeError if input is not a dict.
|
71
|
+
"""
|
72
|
+
if openapi_schema is None:
|
73
|
+
return None
|
74
|
+
|
75
|
+
if not isinstance(openapi_schema, dict):
|
76
|
+
raise TypeError("openapi_schema must be a dictionary")
|
77
|
+
|
78
|
+
pydantic_schema_data = {}
|
79
|
+
|
80
|
+
# Adding this to force adding a type to an empty dict
|
81
|
+
# This avoid "... one_of or any_of must specify a type" error
|
82
|
+
if not openapi_schema.get("type"):
|
83
|
+
openapi_schema["type"] = "object"
|
84
|
+
|
85
|
+
# Adding this to avoid "properties: should be non-empty for OBJECT type" error
|
86
|
+
# See b/385165182
|
87
|
+
if openapi_schema.get("type", "") == "object" and not openapi_schema.get(
|
88
|
+
"properties"
|
89
|
+
):
|
90
|
+
openapi_schema["properties"] = {"dummy_DO_NOT_GENERATE": {"type": "string"}}
|
91
|
+
|
92
|
+
for key, value in openapi_schema.items():
|
93
|
+
snake_case_key = to_snake_case(key)
|
94
|
+
# Check if the snake_case_key exists in the Schema model's fields.
|
95
|
+
if snake_case_key in Schema.model_fields:
|
96
|
+
if snake_case_key in ["title", "default", "format"]:
|
97
|
+
# Ignore these fields as Gemini backend doesn't recognize them, and will
|
98
|
+
# throw exception if they appear in the schema.
|
99
|
+
# Format: properties[expiration].format: only 'enum' and 'date-time' are
|
100
|
+
# supported for STRING type
|
101
|
+
continue
|
102
|
+
if snake_case_key == "properties" and isinstance(value, dict):
|
103
|
+
pydantic_schema_data[snake_case_key] = {
|
104
|
+
k: to_gemini_schema(v) for k, v in value.items()
|
105
|
+
}
|
106
|
+
elif snake_case_key == "items" and isinstance(value, dict):
|
107
|
+
pydantic_schema_data[snake_case_key] = to_gemini_schema(value)
|
108
|
+
elif snake_case_key == "any_of" and isinstance(value, list):
|
109
|
+
pydantic_schema_data[snake_case_key] = [
|
110
|
+
to_gemini_schema(item) for item in value
|
111
|
+
]
|
112
|
+
# Important: Handle cases where the OpenAPI schema might contain lists
|
113
|
+
# or other structures that need to be recursively processed.
|
114
|
+
elif isinstance(value, list) and snake_case_key not in (
|
115
|
+
"enum",
|
116
|
+
"required",
|
117
|
+
"property_ordering",
|
118
|
+
):
|
119
|
+
new_list = []
|
120
|
+
for item in value:
|
121
|
+
if isinstance(item, dict):
|
122
|
+
new_list.append(to_gemini_schema(item))
|
123
|
+
else:
|
124
|
+
new_list.append(item)
|
125
|
+
pydantic_schema_data[snake_case_key] = new_list
|
126
|
+
elif isinstance(value, dict) and snake_case_key not in ("properties"):
|
127
|
+
# Handle dictionary which is neither properties or items
|
128
|
+
pydantic_schema_data[snake_case_key] = to_gemini_schema(value)
|
129
|
+
else:
|
130
|
+
# Simple value assignment (int, str, bool, etc.)
|
131
|
+
pydantic_schema_data[snake_case_key] = value
|
132
|
+
|
133
|
+
return Schema(**pydantic_schema_data)
|
134
|
+
|
135
|
+
|
136
|
+
AuthPreparationState = Literal["pending", "done"]
|
137
|
+
|
138
|
+
|
139
|
+
class RestApiTool(BaseTool):
|
140
|
+
"""A generic tool that interacts with a REST API.
|
141
|
+
|
142
|
+
* Generates request params and body
|
143
|
+
* Attaches auth credentials to API call.
|
144
|
+
|
145
|
+
Example:
|
146
|
+
```
|
147
|
+
# Each API operation in the spec will be turned into its own tool
|
148
|
+
# Name of the tool is the operationId of that operation, in snake case
|
149
|
+
operations = OperationGenerator().parse(openapi_spec_dict)
|
150
|
+
tool = [RestApiTool.from_parsed_operation(o) for o in operations]
|
151
|
+
```
|
152
|
+
"""
|
153
|
+
|
154
|
+
def __init__(
|
155
|
+
self,
|
156
|
+
name: str,
|
157
|
+
description: str,
|
158
|
+
endpoint: Union[OperationEndpoint, str],
|
159
|
+
operation: Union[Operation, str],
|
160
|
+
auth_scheme: Optional[Union[AuthScheme, str]] = None,
|
161
|
+
auth_credential: Optional[Union[AuthCredential, str]] = None,
|
162
|
+
should_parse_operation=True,
|
163
|
+
):
|
164
|
+
"""Initializes the RestApiTool with the given parameters.
|
165
|
+
|
166
|
+
To generate RestApiTool from OpenAPI Specs, use OperationGenerator.
|
167
|
+
Example:
|
168
|
+
```
|
169
|
+
# Each API operation in the spec will be turned into its own tool
|
170
|
+
# Name of the tool is the operationId of that operation, in snake case
|
171
|
+
operations = OperationGenerator().parse(openapi_spec_dict)
|
172
|
+
tool = [RestApiTool.from_parsed_operation(o) for o in operations]
|
173
|
+
```
|
174
|
+
|
175
|
+
Hint: Use google.adk.tools.openapi_tool.auth.auth_helpers to construct
|
176
|
+
auth_scheme and auth_credential.
|
177
|
+
|
178
|
+
Args:
|
179
|
+
name: The name of the tool.
|
180
|
+
description: The description of the tool.
|
181
|
+
endpoint: Include the base_url, path, and method of the tool.
|
182
|
+
operation: Pydantic object or a dict. Representing the OpenAPI Operation
|
183
|
+
object
|
184
|
+
(https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#operation-object)
|
185
|
+
auth_scheme: The auth scheme of the tool. Representing the OpenAPI
|
186
|
+
SecurityScheme object
|
187
|
+
(https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#security-scheme-object)
|
188
|
+
auth_credential: The authentication credential of the tool.
|
189
|
+
should_parse_operation: Whether to parse the operation.
|
190
|
+
"""
|
191
|
+
# Gemini restrict the length of function name to be less than 64 characters
|
192
|
+
self.name = name[:60]
|
193
|
+
self.description = description
|
194
|
+
self.endpoint = (
|
195
|
+
OperationEndpoint.model_validate_json(endpoint)
|
196
|
+
if isinstance(endpoint, str)
|
197
|
+
else endpoint
|
198
|
+
)
|
199
|
+
self.operation = (
|
200
|
+
Operation.model_validate_json(operation)
|
201
|
+
if isinstance(operation, str)
|
202
|
+
else operation
|
203
|
+
)
|
204
|
+
self.auth_credential, self.auth_scheme = None, None
|
205
|
+
|
206
|
+
self.configure_auth_credential(auth_credential)
|
207
|
+
self.configure_auth_scheme(auth_scheme)
|
208
|
+
|
209
|
+
# Private properties
|
210
|
+
self.credential_exchanger = AutoAuthCredentialExchanger()
|
211
|
+
if should_parse_operation:
|
212
|
+
self._operation_parser = OperationParser(self.operation)
|
213
|
+
|
214
|
+
@classmethod
|
215
|
+
def from_parsed_operation(cls, parsed: ParsedOperation) -> "RestApiTool":
|
216
|
+
"""Initializes the RestApiTool from a ParsedOperation object.
|
217
|
+
|
218
|
+
Args:
|
219
|
+
parsed: A ParsedOperation object.
|
220
|
+
|
221
|
+
Returns:
|
222
|
+
A RestApiTool object.
|
223
|
+
"""
|
224
|
+
operation_parser = OperationParser.load(
|
225
|
+
parsed.operation, parsed.parameters, parsed.return_value
|
226
|
+
)
|
227
|
+
|
228
|
+
tool_name = to_snake_case(operation_parser.get_function_name())
|
229
|
+
generated = cls(
|
230
|
+
name=tool_name,
|
231
|
+
description=parsed.operation.description
|
232
|
+
or parsed.operation.summary
|
233
|
+
or "",
|
234
|
+
endpoint=parsed.endpoint,
|
235
|
+
operation=parsed.operation,
|
236
|
+
auth_scheme=parsed.auth_scheme,
|
237
|
+
auth_credential=parsed.auth_credential,
|
238
|
+
)
|
239
|
+
generated._operation_parser = operation_parser
|
240
|
+
return generated
|
241
|
+
|
242
|
+
@classmethod
|
243
|
+
def from_parsed_operation_str(
|
244
|
+
cls, parsed_operation_str: str
|
245
|
+
) -> "RestApiTool":
|
246
|
+
"""Initializes the RestApiTool from a dict.
|
247
|
+
|
248
|
+
Args:
|
249
|
+
parsed: A dict representation of a ParsedOperation object.
|
250
|
+
|
251
|
+
Returns:
|
252
|
+
A RestApiTool object.
|
253
|
+
"""
|
254
|
+
operation = ParsedOperation.model_validate_json(parsed_operation_str)
|
255
|
+
return RestApiTool.from_parsed_operation(operation)
|
256
|
+
|
257
|
+
@override
|
258
|
+
def _get_declaration(self) -> FunctionDeclaration:
|
259
|
+
"""Returns the function declaration in the Gemini Schema format."""
|
260
|
+
schema_dict = self._operation_parser.get_json_schema()
|
261
|
+
parameters = to_gemini_schema(schema_dict)
|
262
|
+
function_decl = FunctionDeclaration(
|
263
|
+
name=self.name, description=self.description, parameters=parameters
|
264
|
+
)
|
265
|
+
return function_decl
|
266
|
+
|
267
|
+
def configure_auth_scheme(
|
268
|
+
self, auth_scheme: Union[AuthScheme, Dict[str, Any]]
|
269
|
+
):
|
270
|
+
"""Configures the authentication scheme for the API call.
|
271
|
+
|
272
|
+
Args:
|
273
|
+
auth_scheme: AuthScheme|dict -: The authentication scheme. The dict is
|
274
|
+
converted to a AuthScheme object.
|
275
|
+
"""
|
276
|
+
if isinstance(auth_scheme, dict):
|
277
|
+
auth_scheme = dict_to_auth_scheme(auth_scheme)
|
278
|
+
self.auth_scheme = auth_scheme
|
279
|
+
|
280
|
+
def configure_auth_credential(
|
281
|
+
self, auth_credential: Optional[Union[AuthCredential, str]] = None
|
282
|
+
):
|
283
|
+
"""Configures the authentication credential for the API call.
|
284
|
+
|
285
|
+
Args:
|
286
|
+
auth_credential: AuthCredential|dict - The authentication credential.
|
287
|
+
The dict is converted to an AuthCredential object.
|
288
|
+
"""
|
289
|
+
if isinstance(auth_credential, str):
|
290
|
+
auth_credential = AuthCredential.model_validate_json(auth_credential)
|
291
|
+
self.auth_credential = auth_credential
|
292
|
+
|
293
|
+
def _prepare_auth_request_params(
|
294
|
+
self,
|
295
|
+
auth_scheme: AuthScheme,
|
296
|
+
auth_credential: AuthCredential,
|
297
|
+
) -> Tuple[List[ApiParameter], Dict[str, Any]]:
|
298
|
+
# Handle Authentication
|
299
|
+
if not auth_scheme or not auth_credential:
|
300
|
+
return
|
301
|
+
|
302
|
+
return credential_to_param(auth_scheme, auth_credential)
|
303
|
+
|
304
|
+
def _prepare_request_params(
|
305
|
+
self, parameters: List[ApiParameter], kwargs: Dict[str, Any]
|
306
|
+
) -> Dict[str, Any]:
|
307
|
+
"""Prepares the request parameters for the API call.
|
308
|
+
|
309
|
+
Args:
|
310
|
+
parameters: A list of ApiParameter objects representing the parameters
|
311
|
+
for the API call.
|
312
|
+
kwargs: The keyword arguments passed to the call function from the Tool
|
313
|
+
caller.
|
314
|
+
|
315
|
+
Returns:
|
316
|
+
A dictionary containing the request parameters for the API call. This
|
317
|
+
initializes a requests.request() call.
|
318
|
+
|
319
|
+
Example:
|
320
|
+
self._prepare_request_params({"input_id": "test-id"})
|
321
|
+
"""
|
322
|
+
method = self.endpoint.method.lower()
|
323
|
+
if not method:
|
324
|
+
raise ValueError("Operation method not found.")
|
325
|
+
|
326
|
+
path_params: Dict[str, Any] = {}
|
327
|
+
query_params: Dict[str, Any] = {}
|
328
|
+
header_params: Dict[str, Any] = {}
|
329
|
+
cookie_params: Dict[str, Any] = {}
|
330
|
+
|
331
|
+
params_map: Dict[str, ApiParameter] = {p.py_name: p for p in parameters}
|
332
|
+
|
333
|
+
# Fill in path, query, header and cookie parameters to the request
|
334
|
+
for param_k, v in kwargs.items():
|
335
|
+
param_obj = params_map.get(param_k)
|
336
|
+
if not param_obj:
|
337
|
+
continue # If input arg not in the ApiParameter list, ignore it.
|
338
|
+
|
339
|
+
original_k = param_obj.original_name
|
340
|
+
param_location = param_obj.param_location
|
341
|
+
|
342
|
+
if param_location == "path":
|
343
|
+
path_params[original_k] = v
|
344
|
+
elif param_location == "query":
|
345
|
+
if v:
|
346
|
+
query_params[original_k] = v
|
347
|
+
elif param_location == "header":
|
348
|
+
header_params[original_k] = v
|
349
|
+
elif param_location == "cookie":
|
350
|
+
cookie_params[original_k] = v
|
351
|
+
|
352
|
+
# Construct URL
|
353
|
+
base_url = self.endpoint.base_url or ""
|
354
|
+
base_url = base_url[:-1] if base_url.endswith("/") else base_url
|
355
|
+
url = f"{base_url}{self.endpoint.path.format(**path_params)}"
|
356
|
+
|
357
|
+
# Construct body
|
358
|
+
body_kwargs: Dict[str, Any] = {}
|
359
|
+
request_body = self.operation.requestBody
|
360
|
+
if request_body:
|
361
|
+
for mime_type, media_type_object in request_body.content.items():
|
362
|
+
schema = media_type_object.schema_
|
363
|
+
body_data = None
|
364
|
+
|
365
|
+
if schema.type == "object":
|
366
|
+
body_data = {}
|
367
|
+
for param in parameters:
|
368
|
+
if param.param_location == "body" and param.py_name in kwargs:
|
369
|
+
body_data[param.original_name] = kwargs[param.py_name]
|
370
|
+
|
371
|
+
elif schema.type == "array":
|
372
|
+
for param in parameters:
|
373
|
+
if param.param_location == "body" and param.py_name == "array":
|
374
|
+
body_data = kwargs.get("array")
|
375
|
+
break
|
376
|
+
else: # like string
|
377
|
+
for param in parameters:
|
378
|
+
# original_name = '' indicating this param applies to the full body.
|
379
|
+
if param.param_location == "body" and not param.original_name:
|
380
|
+
body_data = (
|
381
|
+
kwargs.get(param.py_name) if param.py_name in kwargs else None
|
382
|
+
)
|
383
|
+
break
|
384
|
+
|
385
|
+
if mime_type == "application/json" or mime_type.endswith("+json"):
|
386
|
+
if body_data is not None:
|
387
|
+
body_kwargs["json"] = body_data
|
388
|
+
elif mime_type == "application/x-www-form-urlencoded":
|
389
|
+
body_kwargs["data"] = body_data
|
390
|
+
elif mime_type == "multipart/form-data":
|
391
|
+
body_kwargs["files"] = body_data
|
392
|
+
elif mime_type == "application/octet-stream":
|
393
|
+
body_kwargs["data"] = body_data
|
394
|
+
elif mime_type == "text/plain":
|
395
|
+
body_kwargs["data"] = body_data
|
396
|
+
|
397
|
+
if mime_type:
|
398
|
+
header_params["Content-Type"] = mime_type
|
399
|
+
break # Process only the first mime_type
|
400
|
+
|
401
|
+
filtered_query_params: Dict[str, Any] = {
|
402
|
+
k: v for k, v in query_params.items() if v is not None
|
403
|
+
}
|
404
|
+
|
405
|
+
request_params: Dict[str, Any] = {
|
406
|
+
"method": method,
|
407
|
+
"url": url,
|
408
|
+
"params": filtered_query_params,
|
409
|
+
"headers": header_params,
|
410
|
+
"cookies": cookie_params,
|
411
|
+
**body_kwargs,
|
412
|
+
}
|
413
|
+
|
414
|
+
return request_params
|
415
|
+
|
416
|
+
@override
|
417
|
+
async def run_async(
|
418
|
+
self, *, args: dict[str, Any], tool_context: Optional[ToolContext]
|
419
|
+
) -> Dict[str, Any]:
|
420
|
+
return self.call(args=args, tool_context=tool_context)
|
421
|
+
|
422
|
+
def call(
|
423
|
+
self, *, args: dict[str, Any], tool_context: Optional[ToolContext]
|
424
|
+
) -> Dict[str, Any]:
|
425
|
+
"""Executes the REST API call.
|
426
|
+
|
427
|
+
Args:
|
428
|
+
args: Keyword arguments representing the operation parameters.
|
429
|
+
tool_context: The tool context (not used here, but required by the
|
430
|
+
interface).
|
431
|
+
|
432
|
+
Returns:
|
433
|
+
The API response as a dictionary.
|
434
|
+
"""
|
435
|
+
# Prepare auth credentials for the API call
|
436
|
+
tool_auth_handler = ToolAuthHandler.from_tool_context(
|
437
|
+
tool_context, self.auth_scheme, self.auth_credential
|
438
|
+
)
|
439
|
+
auth_result = tool_auth_handler.prepare_auth_credentials()
|
440
|
+
auth_state, auth_scheme, auth_credential = (
|
441
|
+
auth_result.state,
|
442
|
+
auth_result.auth_scheme,
|
443
|
+
auth_result.auth_credential,
|
444
|
+
)
|
445
|
+
|
446
|
+
if auth_state == "pending":
|
447
|
+
return {
|
448
|
+
"pending": True,
|
449
|
+
"message": "Needs your authorization to access your data.",
|
450
|
+
}
|
451
|
+
|
452
|
+
# Attach parameters from auth into main parameters list
|
453
|
+
api_params, api_args = self._operation_parser.get_parameters().copy(), args
|
454
|
+
if auth_credential:
|
455
|
+
# Attach parameters from auth into main parameters list
|
456
|
+
auth_param, auth_args = self._prepare_auth_request_params(
|
457
|
+
auth_scheme, auth_credential
|
458
|
+
)
|
459
|
+
if auth_param and auth_args:
|
460
|
+
api_params = [auth_param] + api_params
|
461
|
+
api_args.update(auth_args)
|
462
|
+
|
463
|
+
# Got all parameters. Call the API.
|
464
|
+
request_params = self._prepare_request_params(api_params, api_args)
|
465
|
+
response = requests.request(**request_params)
|
466
|
+
|
467
|
+
# Parse API response
|
468
|
+
try:
|
469
|
+
response.raise_for_status() # Raise HTTPError for bad responses
|
470
|
+
return response.json() # Try to decode JSON
|
471
|
+
except requests.exceptions.HTTPError:
|
472
|
+
error_details = response.content.decode("utf-8")
|
473
|
+
return {
|
474
|
+
"error": (
|
475
|
+
f"Tool {self.name} execution failed. Analyze this execution error"
|
476
|
+
" and your inputs. Retry with adjustments if applicable. But"
|
477
|
+
" make sure don't retry more than 3 times. Execution Error:"
|
478
|
+
f" {error_details}"
|
479
|
+
)
|
480
|
+
}
|
481
|
+
except ValueError:
|
482
|
+
return {"text": response.text} # Return text if not JSON
|
483
|
+
|
484
|
+
def __str__(self):
|
485
|
+
return (
|
486
|
+
f'RestApiTool(name="{self.name}", description="{self.description}",'
|
487
|
+
f' endpoint="{self.endpoint}")'
|
488
|
+
)
|
489
|
+
|
490
|
+
def __repr__(self):
|
491
|
+
return (
|
492
|
+
f'RestApiTool(name="{self.name}", description="{self.description}",'
|
493
|
+
f' endpoint="{self.endpoint}", operation="{self.operation}",'
|
494
|
+
f' auth_scheme="{self.auth_scheme}",'
|
495
|
+
f' auth_credential="{self.auth_credential}")'
|
496
|
+
)
|