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,117 @@
|
|
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
|
+
"""Credential fetcher for OpenID Connect."""
|
16
|
+
|
17
|
+
from typing import Optional
|
18
|
+
|
19
|
+
from .....auth.auth_credential import AuthCredential
|
20
|
+
from .....auth.auth_credential import AuthCredentialTypes
|
21
|
+
from .....auth.auth_credential import HttpAuth
|
22
|
+
from .....auth.auth_credential import HttpCredentials
|
23
|
+
from .....auth.auth_schemes import AuthScheme
|
24
|
+
from .....auth.auth_schemes import AuthSchemeType
|
25
|
+
from .base_credential_exchanger import BaseAuthCredentialExchanger
|
26
|
+
|
27
|
+
|
28
|
+
class OAuth2CredentialExchanger(BaseAuthCredentialExchanger):
|
29
|
+
"""Fetches credentials for OAuth2 and OpenID Connect."""
|
30
|
+
|
31
|
+
def _check_scheme_credential_type(
|
32
|
+
self,
|
33
|
+
auth_scheme: AuthScheme,
|
34
|
+
auth_credential: Optional[AuthCredential] = None,
|
35
|
+
):
|
36
|
+
if not auth_credential:
|
37
|
+
raise ValueError(
|
38
|
+
"auth_credential is empty. Please create AuthCredential using"
|
39
|
+
" OAuth2Auth."
|
40
|
+
)
|
41
|
+
|
42
|
+
if auth_scheme.type_ not in (
|
43
|
+
AuthSchemeType.openIdConnect,
|
44
|
+
AuthSchemeType.oauth2,
|
45
|
+
):
|
46
|
+
raise ValueError(
|
47
|
+
"Invalid security scheme, expect AuthSchemeType.openIdConnect or "
|
48
|
+
f"AuthSchemeType.oauth2 auth scheme, but got {auth_scheme.type_}"
|
49
|
+
)
|
50
|
+
|
51
|
+
if not auth_credential.oauth2 and not auth_credential.http:
|
52
|
+
raise ValueError(
|
53
|
+
"auth_credential is not configured with oauth2. Please"
|
54
|
+
" create AuthCredential and set OAuth2Auth."
|
55
|
+
)
|
56
|
+
|
57
|
+
def generate_auth_token(
|
58
|
+
self,
|
59
|
+
auth_credential: Optional[AuthCredential] = None,
|
60
|
+
) -> AuthCredential:
|
61
|
+
"""Generates an auth token from the authorization response.
|
62
|
+
|
63
|
+
Args:
|
64
|
+
auth_scheme: The OpenID Connect or OAuth2 auth scheme.
|
65
|
+
auth_credential: The auth credential.
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
An AuthCredential object containing the HTTP bearer access token. If the
|
69
|
+
HTTO bearer token cannot be generated, return the origianl credential
|
70
|
+
"""
|
71
|
+
|
72
|
+
if "access_token" not in auth_credential.oauth2.token:
|
73
|
+
return auth_credential
|
74
|
+
|
75
|
+
# Return the access token as a bearer token.
|
76
|
+
updated_credential = AuthCredential(
|
77
|
+
auth_type=AuthCredentialTypes.HTTP, # Store as a bearer token
|
78
|
+
http=HttpAuth(
|
79
|
+
scheme="bearer",
|
80
|
+
credentials=HttpCredentials(
|
81
|
+
token=auth_credential.oauth2.token["access_token"]
|
82
|
+
),
|
83
|
+
),
|
84
|
+
)
|
85
|
+
return updated_credential
|
86
|
+
|
87
|
+
def exchange_credential(
|
88
|
+
self,
|
89
|
+
auth_scheme: AuthScheme,
|
90
|
+
auth_credential: Optional[AuthCredential] = None,
|
91
|
+
) -> AuthCredential:
|
92
|
+
"""Exchanges the OpenID Connect auth credential for an access token or an auth URI.
|
93
|
+
|
94
|
+
Args:
|
95
|
+
auth_scheme: The auth scheme.
|
96
|
+
auth_credential: The auth credential.
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
An AuthCredential object containing the HTTP Bearer access token.
|
100
|
+
|
101
|
+
Raises:
|
102
|
+
ValueError: If the auth scheme or auth credential is invalid.
|
103
|
+
"""
|
104
|
+
# TODO(cheliu): Implement token refresh flow
|
105
|
+
|
106
|
+
self._check_scheme_credential_type(auth_scheme, auth_credential)
|
107
|
+
|
108
|
+
# If token is already HTTPBearer token, do nothing assuming that this token
|
109
|
+
# is valid.
|
110
|
+
if auth_credential.http:
|
111
|
+
return auth_credential
|
112
|
+
|
113
|
+
# If access token is exchanged, exchange a HTTPBearer token.
|
114
|
+
if auth_credential.oauth2.token:
|
115
|
+
return self.generate_auth_token(auth_credential)
|
116
|
+
|
117
|
+
return None
|
@@ -0,0 +1,97 @@
|
|
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
|
+
"""Credential fetcher for Google Service Account."""
|
16
|
+
|
17
|
+
from typing import Optional
|
18
|
+
|
19
|
+
import google.auth
|
20
|
+
from google.auth.transport.requests import Request
|
21
|
+
from google.oauth2 import service_account
|
22
|
+
import google.oauth2.credentials
|
23
|
+
|
24
|
+
from .....auth.auth_credential import (
|
25
|
+
AuthCredential,
|
26
|
+
AuthCredentialTypes,
|
27
|
+
HttpAuth,
|
28
|
+
HttpCredentials,
|
29
|
+
)
|
30
|
+
from .....auth.auth_schemes import AuthScheme
|
31
|
+
from .base_credential_exchanger import AuthCredentialMissingError, BaseAuthCredentialExchanger
|
32
|
+
|
33
|
+
|
34
|
+
class ServiceAccountCredentialExchanger(BaseAuthCredentialExchanger):
|
35
|
+
"""Fetches credentials for Google Service Account.
|
36
|
+
|
37
|
+
Uses the default service credential if `use_default_credential = True`.
|
38
|
+
Otherwise, uses the service account credential provided in the auth
|
39
|
+
credential.
|
40
|
+
"""
|
41
|
+
|
42
|
+
def exchange_credential(
|
43
|
+
self,
|
44
|
+
auth_scheme: AuthScheme,
|
45
|
+
auth_credential: Optional[AuthCredential] = None,
|
46
|
+
) -> AuthCredential:
|
47
|
+
"""Exchanges the service account auth credential for an access token.
|
48
|
+
|
49
|
+
If auth_credential contains a service account credential, it will be used
|
50
|
+
to fetch an access token. Otherwise, the default service credential will be
|
51
|
+
used for fetching an access token.
|
52
|
+
|
53
|
+
Args:
|
54
|
+
auth_scheme: The auth scheme.
|
55
|
+
auth_credential: The auth credential.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
An AuthCredential in HTTPBearer format, containing the access token.
|
59
|
+
"""
|
60
|
+
if (
|
61
|
+
auth_credential is None
|
62
|
+
or auth_credential.service_account is None
|
63
|
+
or (
|
64
|
+
auth_credential.service_account.service_account_credential is None
|
65
|
+
and not auth_credential.service_account.use_default_credential
|
66
|
+
)
|
67
|
+
):
|
68
|
+
raise AuthCredentialMissingError(
|
69
|
+
"Service account credentials are missing. Please provide them, or set"
|
70
|
+
" `use_default_credential = True` to use application default"
|
71
|
+
" credential in a hosted service like Cloud Run."
|
72
|
+
)
|
73
|
+
|
74
|
+
try:
|
75
|
+
if auth_credential.service_account.use_default_credential:
|
76
|
+
credentials, _ = google.auth.default()
|
77
|
+
else:
|
78
|
+
config = auth_credential.service_account
|
79
|
+
credentials = service_account.Credentials.from_service_account_info(
|
80
|
+
config.service_account_credential.model_dump(), scopes=config.scopes
|
81
|
+
)
|
82
|
+
|
83
|
+
credentials.refresh(Request())
|
84
|
+
|
85
|
+
updated_credential = AuthCredential(
|
86
|
+
auth_type=AuthCredentialTypes.HTTP, # Store as a bearer token
|
87
|
+
http=HttpAuth(
|
88
|
+
scheme="bearer",
|
89
|
+
credentials=HttpCredentials(token=credentials.token),
|
90
|
+
),
|
91
|
+
)
|
92
|
+
return updated_credential
|
93
|
+
|
94
|
+
except Exception as e:
|
95
|
+
raise AuthCredentialMissingError(
|
96
|
+
f"Failed to exchange service account token: {e}"
|
97
|
+
) from e
|
@@ -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 . import common
|
16
|
+
|
17
|
+
__all__ = [
|
18
|
+
'common',
|
19
|
+
]
|
@@ -0,0 +1,300 @@
|
|
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 keyword
|
16
|
+
import re
|
17
|
+
from typing import Any
|
18
|
+
from typing import Dict
|
19
|
+
from typing import List
|
20
|
+
from typing import Optional
|
21
|
+
from typing import Union
|
22
|
+
|
23
|
+
from fastapi.openapi.models import Response
|
24
|
+
from fastapi.openapi.models import Schema
|
25
|
+
from pydantic import BaseModel
|
26
|
+
from pydantic import Field
|
27
|
+
from pydantic import model_serializer
|
28
|
+
|
29
|
+
|
30
|
+
def to_snake_case(text: str) -> str:
|
31
|
+
"""Converts a string into snake_case.
|
32
|
+
|
33
|
+
Handles lowerCamelCase, UpperCamelCase, or space-separated case, acronyms
|
34
|
+
(e.g., "REST API") and consecutive uppercase letters correctly. Also handles
|
35
|
+
mixed cases with and without spaces.
|
36
|
+
|
37
|
+
Examples:
|
38
|
+
```
|
39
|
+
to_snake_case('camelCase') -> 'camel_case'
|
40
|
+
to_snake_case('UpperCamelCase') -> 'upper_camel_case'
|
41
|
+
to_snake_case('space separated') -> 'space_separated'
|
42
|
+
```
|
43
|
+
|
44
|
+
Args:
|
45
|
+
text: The input string.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
The snake_case version of the string.
|
49
|
+
"""
|
50
|
+
|
51
|
+
# Handle spaces and non-alphanumeric characters (replace with underscores)
|
52
|
+
text = re.sub(r'[^a-zA-Z0-9]+', '_', text)
|
53
|
+
|
54
|
+
# Insert underscores before uppercase letters (handling both CamelCases)
|
55
|
+
text = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', text) # lowerCamelCase
|
56
|
+
text = re.sub(
|
57
|
+
r'([A-Z]+)([A-Z][a-z])', r'\1_\2', text
|
58
|
+
) # UpperCamelCase and acronyms
|
59
|
+
|
60
|
+
# Convert to lowercase
|
61
|
+
text = text.lower()
|
62
|
+
|
63
|
+
# Remove consecutive underscores (clean up extra underscores)
|
64
|
+
text = re.sub(r'_+', '_', text)
|
65
|
+
|
66
|
+
# Remove leading and trailing underscores
|
67
|
+
text = text.strip('_')
|
68
|
+
|
69
|
+
return text
|
70
|
+
|
71
|
+
|
72
|
+
def rename_python_keywords(s: str, prefix: str = 'param_') -> str:
|
73
|
+
"""Renames Python keywords by adding a prefix.
|
74
|
+
|
75
|
+
Example:
|
76
|
+
```
|
77
|
+
rename_python_keywords('if') -> 'param_if'
|
78
|
+
rename_python_keywords('for') -> 'param_for'
|
79
|
+
```
|
80
|
+
|
81
|
+
Args:
|
82
|
+
s: The input string.
|
83
|
+
prefix: The prefix to add to the keyword.
|
84
|
+
|
85
|
+
Returns:
|
86
|
+
The renamed string.
|
87
|
+
"""
|
88
|
+
if keyword.iskeyword(s):
|
89
|
+
return prefix + s
|
90
|
+
return s
|
91
|
+
|
92
|
+
|
93
|
+
class ApiParameter(BaseModel):
|
94
|
+
"""Data class representing a function parameter."""
|
95
|
+
|
96
|
+
original_name: str
|
97
|
+
param_location: str
|
98
|
+
param_schema: Union[str, Schema]
|
99
|
+
description: Optional[str] = ''
|
100
|
+
py_name: Optional[str] = ''
|
101
|
+
type_value: type[Any] = Field(default=None, init_var=False)
|
102
|
+
type_hint: str = Field(default=None, init_var=False)
|
103
|
+
|
104
|
+
def model_post_init(self, _: Any):
|
105
|
+
self.py_name = (
|
106
|
+
self.py_name
|
107
|
+
if self.py_name
|
108
|
+
else rename_python_keywords(to_snake_case(self.original_name))
|
109
|
+
)
|
110
|
+
if isinstance(self.param_schema, str):
|
111
|
+
self.param_schema = Schema.model_validate_json(self.param_schema)
|
112
|
+
|
113
|
+
self.description = self.description or self.param_schema.description or ''
|
114
|
+
self.type_value = TypeHintHelper.get_type_value(self.param_schema)
|
115
|
+
self.type_hint = TypeHintHelper.get_type_hint(self.param_schema)
|
116
|
+
return self
|
117
|
+
|
118
|
+
@model_serializer
|
119
|
+
def _serialize(self):
|
120
|
+
return {
|
121
|
+
'original_name': self.original_name,
|
122
|
+
'param_location': self.param_location,
|
123
|
+
'param_schema': self.param_schema,
|
124
|
+
'description': self.description,
|
125
|
+
'py_name': self.py_name,
|
126
|
+
}
|
127
|
+
|
128
|
+
def __str__(self):
|
129
|
+
return f'{self.py_name}: {self.type_hint}'
|
130
|
+
|
131
|
+
def to_arg_string(self):
|
132
|
+
"""Converts the parameter to an argument string for function call."""
|
133
|
+
return f'{self.py_name}={self.py_name}'
|
134
|
+
|
135
|
+
def to_dict_property(self):
|
136
|
+
"""Converts the parameter to a key:value string for dict property."""
|
137
|
+
return f'"{self.py_name}": {self.py_name}'
|
138
|
+
|
139
|
+
def to_pydoc_string(self):
|
140
|
+
"""Converts the parameter to a PyDoc parameter docstr."""
|
141
|
+
return PydocHelper.generate_param_doc(self)
|
142
|
+
|
143
|
+
|
144
|
+
class TypeHintHelper:
|
145
|
+
"""Helper class for generating type hints."""
|
146
|
+
|
147
|
+
@staticmethod
|
148
|
+
def get_type_value(schema: Schema) -> Any:
|
149
|
+
"""Generates the Python type value for a given parameter."""
|
150
|
+
param_type = schema.type if schema.type else Any
|
151
|
+
|
152
|
+
if param_type == 'integer':
|
153
|
+
return int
|
154
|
+
elif param_type == 'number':
|
155
|
+
return float
|
156
|
+
elif param_type == 'boolean':
|
157
|
+
return bool
|
158
|
+
elif param_type == 'string':
|
159
|
+
return str
|
160
|
+
elif param_type == 'array':
|
161
|
+
items_type = Any
|
162
|
+
if schema.items and schema.items.type:
|
163
|
+
items_type = schema.items.type
|
164
|
+
|
165
|
+
if items_type == 'object':
|
166
|
+
return List[Dict[str, Any]]
|
167
|
+
else:
|
168
|
+
type_map = {
|
169
|
+
'integer': int,
|
170
|
+
'number': float,
|
171
|
+
'boolean': bool,
|
172
|
+
'string': str,
|
173
|
+
'object': Dict[str, Any],
|
174
|
+
'array': List[Any],
|
175
|
+
}
|
176
|
+
return List[type_map.get(items_type, 'Any')]
|
177
|
+
elif param_type == 'object':
|
178
|
+
return Dict[str, Any]
|
179
|
+
else:
|
180
|
+
return Any
|
181
|
+
|
182
|
+
@staticmethod
|
183
|
+
def get_type_hint(schema: Schema) -> str:
|
184
|
+
"""Generates the Python type in string for a given parameter."""
|
185
|
+
param_type = schema.type if schema.type else 'Any'
|
186
|
+
|
187
|
+
if param_type == 'integer':
|
188
|
+
return 'int'
|
189
|
+
elif param_type == 'number':
|
190
|
+
return 'float'
|
191
|
+
elif param_type == 'boolean':
|
192
|
+
return 'bool'
|
193
|
+
elif param_type == 'string':
|
194
|
+
return 'str'
|
195
|
+
elif param_type == 'array':
|
196
|
+
items_type = 'Any'
|
197
|
+
if schema.items and schema.items.type:
|
198
|
+
items_type = schema.items.type
|
199
|
+
|
200
|
+
if items_type == 'object':
|
201
|
+
return 'List[Dict[str, Any]]'
|
202
|
+
else:
|
203
|
+
type_map = {
|
204
|
+
'integer': 'int',
|
205
|
+
'number': 'float',
|
206
|
+
'boolean': 'bool',
|
207
|
+
'string': 'str',
|
208
|
+
}
|
209
|
+
return f"List[{type_map.get(items_type, 'Any')}]"
|
210
|
+
elif param_type == 'object':
|
211
|
+
return 'Dict[str, Any]'
|
212
|
+
else:
|
213
|
+
return 'Any'
|
214
|
+
|
215
|
+
|
216
|
+
class PydocHelper:
|
217
|
+
"""Helper class for generating PyDoc strings."""
|
218
|
+
|
219
|
+
@staticmethod
|
220
|
+
def generate_param_doc(
|
221
|
+
param: ApiParameter,
|
222
|
+
) -> str:
|
223
|
+
"""Generates a parameter documentation string.
|
224
|
+
|
225
|
+
Args:
|
226
|
+
param: ApiParameter - The parameter to generate the documentation for.
|
227
|
+
|
228
|
+
Returns:
|
229
|
+
str: The generated parameter Python documentation string.
|
230
|
+
"""
|
231
|
+
description = param.description.strip() if param.description else ''
|
232
|
+
param_doc = f'{param.py_name} ({param.type_hint}): {description}'
|
233
|
+
|
234
|
+
if param.param_schema.type == 'object':
|
235
|
+
properties = param.param_schema.properties
|
236
|
+
if properties:
|
237
|
+
param_doc += ' Object properties:\n'
|
238
|
+
for prop_name, prop_details in properties.items():
|
239
|
+
prop_desc = prop_details.description or ''
|
240
|
+
prop_type = TypeHintHelper.get_type_hint(prop_details)
|
241
|
+
param_doc += f' {prop_name} ({prop_type}): {prop_desc}\n'
|
242
|
+
|
243
|
+
return param_doc
|
244
|
+
|
245
|
+
@staticmethod
|
246
|
+
def generate_return_doc(responses: Dict[str, Response]) -> str:
|
247
|
+
"""Generates a return value documentation string.
|
248
|
+
|
249
|
+
Args:
|
250
|
+
responses: Dict[str, TypedDict[Response]] - Response in an OpenAPI
|
251
|
+
Operation
|
252
|
+
|
253
|
+
Returns:
|
254
|
+
str: The generated return value Python documentation string.
|
255
|
+
"""
|
256
|
+
return_doc = ''
|
257
|
+
|
258
|
+
# Only consider 2xx responses for return type hinting.
|
259
|
+
# Returns the 2xx response with the smallest status code number and with
|
260
|
+
# content defined.
|
261
|
+
sorted_responses = sorted(responses.items(), key=lambda item: int(item[0]))
|
262
|
+
qualified_response = next(
|
263
|
+
filter(
|
264
|
+
lambda r: r[0].startswith('2') and r[1].content,
|
265
|
+
sorted_responses,
|
266
|
+
),
|
267
|
+
None,
|
268
|
+
)
|
269
|
+
if not qualified_response:
|
270
|
+
return ''
|
271
|
+
response_details = qualified_response[1]
|
272
|
+
|
273
|
+
description = (response_details.description or '').strip()
|
274
|
+
content = response_details.content or {}
|
275
|
+
|
276
|
+
# Generate return type hint and properties for the first response type.
|
277
|
+
# TODO(cheliu): Handle multiple content types.
|
278
|
+
for _, schema_details in content.items():
|
279
|
+
schema = schema_details.schema_ or {}
|
280
|
+
|
281
|
+
# Use a dummy Parameter object for return type hinting.
|
282
|
+
dummy_param = ApiParameter(
|
283
|
+
original_name='', param_location='', param_schema=schema
|
284
|
+
)
|
285
|
+
return_doc = f'Returns ({dummy_param.type_hint}): {description}'
|
286
|
+
|
287
|
+
response_type = schema.type or 'Any'
|
288
|
+
if response_type != 'object':
|
289
|
+
break
|
290
|
+
properties = schema.properties
|
291
|
+
if not properties:
|
292
|
+
break
|
293
|
+
return_doc += ' Object properties:\n'
|
294
|
+
for prop_name, prop_details in properties.items():
|
295
|
+
prop_desc = prop_details.description or ''
|
296
|
+
prop_type = TypeHintHelper.get_type_hint(prop_details)
|
297
|
+
return_doc += f' {prop_name} ({prop_type}): {prop_desc}\n'
|
298
|
+
break
|
299
|
+
|
300
|
+
return return_doc
|
@@ -0,0 +1,32 @@
|
|
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 .openapi_spec_parser import OpenApiSpecParser, OperationEndpoint, ParsedOperation
|
16
|
+
from .openapi_toolset import OpenAPIToolset
|
17
|
+
from .operation_parser import OperationParser
|
18
|
+
from .rest_api_tool import AuthPreparationState, RestApiTool, snake_to_lower_camel, to_gemini_schema
|
19
|
+
from .tool_auth_handler import ToolAuthHandler
|
20
|
+
|
21
|
+
__all__ = [
|
22
|
+
'OpenApiSpecParser',
|
23
|
+
'OperationEndpoint',
|
24
|
+
'ParsedOperation',
|
25
|
+
'OpenAPIToolset',
|
26
|
+
'OperationParser',
|
27
|
+
'RestApiTool',
|
28
|
+
'to_gemini_schema',
|
29
|
+
'snake_to_lower_camel',
|
30
|
+
'AuthPreparationState',
|
31
|
+
'ToolAuthHandler',
|
32
|
+
]
|