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,498 @@
|
|
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
|
+
|
22
|
+
from fastapi.openapi.models import APIKey
|
23
|
+
from fastapi.openapi.models import APIKeyIn
|
24
|
+
from fastapi.openapi.models import HTTPBase
|
25
|
+
from fastapi.openapi.models import HTTPBearer
|
26
|
+
from fastapi.openapi.models import OAuth2
|
27
|
+
from fastapi.openapi.models import OpenIdConnect
|
28
|
+
from fastapi.openapi.models import Schema
|
29
|
+
from pydantic import BaseModel
|
30
|
+
from pydantic import ValidationError
|
31
|
+
import requests
|
32
|
+
|
33
|
+
from ....auth.auth_credential import AuthCredential
|
34
|
+
from ....auth.auth_credential import AuthCredentialTypes
|
35
|
+
from ....auth.auth_credential import HttpAuth
|
36
|
+
from ....auth.auth_credential import HttpCredentials
|
37
|
+
from ....auth.auth_credential import OAuth2Auth
|
38
|
+
from ....auth.auth_credential import ServiceAccount
|
39
|
+
from ....auth.auth_credential import ServiceAccountCredential
|
40
|
+
from ....auth.auth_schemes import AuthScheme
|
41
|
+
from ....auth.auth_schemes import AuthSchemeType
|
42
|
+
from ....auth.auth_schemes import OpenIdConnectWithConfig
|
43
|
+
from ..common.common import ApiParameter
|
44
|
+
|
45
|
+
|
46
|
+
class OpenIdConfig(BaseModel):
|
47
|
+
"""Represents OpenID Connect configuration.
|
48
|
+
|
49
|
+
Attributes:
|
50
|
+
client_id: The client ID.
|
51
|
+
auth_uri: The authorization URI.
|
52
|
+
token_uri: The token URI.
|
53
|
+
client_secret: The client secret.
|
54
|
+
|
55
|
+
Example:
|
56
|
+
config = OpenIdConfig(
|
57
|
+
client_id="your_client_id",
|
58
|
+
auth_uri="https://accounts.google.com/o/oauth2/auth",
|
59
|
+
token_uri="https://oauth2.googleapis.com/token",
|
60
|
+
client_secret="your_client_secret",
|
61
|
+
redirect
|
62
|
+
)
|
63
|
+
"""
|
64
|
+
|
65
|
+
client_id: str
|
66
|
+
auth_uri: str
|
67
|
+
token_uri: str
|
68
|
+
client_secret: str
|
69
|
+
redirect_uri: Optional[str]
|
70
|
+
|
71
|
+
|
72
|
+
def token_to_scheme_credential(
|
73
|
+
token_type: Literal["apikey", "oauth2Token"],
|
74
|
+
location: Optional[Literal["header", "query", "cookie"]] = None,
|
75
|
+
name: Optional[str] = None,
|
76
|
+
credential_value: Optional[str] = None,
|
77
|
+
) -> Tuple[AuthScheme, AuthCredential]:
|
78
|
+
"""Creates a AuthScheme and AuthCredential for API key or bearer token.
|
79
|
+
|
80
|
+
Examples:
|
81
|
+
```
|
82
|
+
# API Key in header
|
83
|
+
auth_scheme, auth_credential = token_to_scheme_credential("apikey", "header",
|
84
|
+
"X-API-Key", "your_api_key_value")
|
85
|
+
|
86
|
+
# API Key in query parameter
|
87
|
+
auth_scheme, auth_credential = token_to_scheme_credential("apikey", "query",
|
88
|
+
"api_key", "your_api_key_value")
|
89
|
+
|
90
|
+
# OAuth2 Bearer Token in Authorization header
|
91
|
+
auth_scheme, auth_credential = token_to_scheme_credential("oauth2Token",
|
92
|
+
"header", "Authorization", "your_bearer_token_value")
|
93
|
+
```
|
94
|
+
|
95
|
+
Args:
|
96
|
+
type: 'apikey' or 'oauth2Token'.
|
97
|
+
location: 'header', 'query', or 'cookie' (only 'header' for oauth2Token).
|
98
|
+
name: The name of the header, query parameter, or cookie.
|
99
|
+
credential_value: The value of the API Key/ Token.
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
Tuple: (AuthScheme, AuthCredential)
|
103
|
+
|
104
|
+
Raises:
|
105
|
+
ValueError: For invalid type or location.
|
106
|
+
"""
|
107
|
+
if token_type == "apikey":
|
108
|
+
in_: APIKeyIn
|
109
|
+
if location == "header":
|
110
|
+
in_ = APIKeyIn.header
|
111
|
+
elif location == "query":
|
112
|
+
in_ = APIKeyIn.query
|
113
|
+
elif location == "cookie":
|
114
|
+
in_ = APIKeyIn.cookie
|
115
|
+
else:
|
116
|
+
raise ValueError(f"Invalid location for apiKey: {location}")
|
117
|
+
auth_scheme = APIKey(**{
|
118
|
+
"type": AuthSchemeType.apiKey,
|
119
|
+
"in": in_,
|
120
|
+
"name": name,
|
121
|
+
})
|
122
|
+
if credential_value:
|
123
|
+
auth_credential = AuthCredential(
|
124
|
+
auth_type=AuthCredentialTypes.API_KEY, api_key=credential_value
|
125
|
+
)
|
126
|
+
else:
|
127
|
+
auth_credential = None
|
128
|
+
|
129
|
+
return auth_scheme, auth_credential
|
130
|
+
|
131
|
+
elif token_type == "oauth2Token":
|
132
|
+
# ignore location. OAuth2 Bearer Token is always in Authorization header.
|
133
|
+
auth_scheme = HTTPBearer(
|
134
|
+
bearerFormat="JWT"
|
135
|
+
) # Common format, can be omitted.
|
136
|
+
if credential_value:
|
137
|
+
auth_credential = AuthCredential(
|
138
|
+
auth_type=AuthCredentialTypes.HTTP,
|
139
|
+
http=HttpAuth(
|
140
|
+
scheme="bearer",
|
141
|
+
credentials=HttpCredentials(token=credential_value),
|
142
|
+
),
|
143
|
+
)
|
144
|
+
else:
|
145
|
+
auth_credential = None
|
146
|
+
|
147
|
+
return auth_scheme, auth_credential
|
148
|
+
|
149
|
+
else:
|
150
|
+
raise ValueError(f"Invalid security scheme type: {type}")
|
151
|
+
|
152
|
+
|
153
|
+
def service_account_dict_to_scheme_credential(
|
154
|
+
config: Dict[str, Any],
|
155
|
+
scopes: List[str],
|
156
|
+
) -> Tuple[AuthScheme, AuthCredential]:
|
157
|
+
"""Creates AuthScheme and AuthCredential for Google Service Account.
|
158
|
+
|
159
|
+
Returns a bearer token scheme, and a service account credential.
|
160
|
+
|
161
|
+
Args:
|
162
|
+
config: A ServiceAccount object containing the Google Service Account
|
163
|
+
configuration.
|
164
|
+
scopes: A list of scopes to be used.
|
165
|
+
|
166
|
+
Returns:
|
167
|
+
Tuple: (AuthScheme, AuthCredential)
|
168
|
+
"""
|
169
|
+
auth_scheme = HTTPBearer(bearerFormat="JWT")
|
170
|
+
service_account = ServiceAccount(
|
171
|
+
service_account_credential=ServiceAccountCredential.model_construct(
|
172
|
+
**config
|
173
|
+
),
|
174
|
+
scopes=scopes,
|
175
|
+
)
|
176
|
+
auth_credential = AuthCredential(
|
177
|
+
auth_type=AuthCredentialTypes.SERVICE_ACCOUNT,
|
178
|
+
service_account=service_account,
|
179
|
+
)
|
180
|
+
return auth_scheme, auth_credential
|
181
|
+
|
182
|
+
|
183
|
+
def service_account_scheme_credential(
|
184
|
+
config: ServiceAccount,
|
185
|
+
) -> Tuple[AuthScheme, AuthCredential]:
|
186
|
+
"""Creates AuthScheme and AuthCredential for Google Service Account.
|
187
|
+
|
188
|
+
Returns a bearer token scheme, and a service account credential.
|
189
|
+
|
190
|
+
Args:
|
191
|
+
config: A ServiceAccount object containing the Google Service Account
|
192
|
+
configuration.
|
193
|
+
|
194
|
+
Returns:
|
195
|
+
Tuple: (AuthScheme, AuthCredential)
|
196
|
+
"""
|
197
|
+
auth_scheme = HTTPBearer(bearerFormat="JWT")
|
198
|
+
auth_credential = AuthCredential(
|
199
|
+
auth_type=AuthCredentialTypes.SERVICE_ACCOUNT, service_account=config
|
200
|
+
)
|
201
|
+
return auth_scheme, auth_credential
|
202
|
+
|
203
|
+
|
204
|
+
def openid_dict_to_scheme_credential(
|
205
|
+
config_dict: Dict[str, Any],
|
206
|
+
scopes: List[str],
|
207
|
+
credential_dict: Dict[str, Any],
|
208
|
+
) -> Tuple[OpenIdConnectWithConfig, AuthCredential]:
|
209
|
+
"""Constructs OpenID scheme and credential from configuration and credential dictionaries.
|
210
|
+
|
211
|
+
Args:
|
212
|
+
config_dict: Dictionary containing OpenID Connect configuration, must
|
213
|
+
include at least 'authorization_endpoint' and 'token_endpoint'.
|
214
|
+
scopes: List of scopes to be used.
|
215
|
+
credential_dict: Dictionary containing credential information, must
|
216
|
+
include 'client_id', 'client_secret', and 'scopes'. May optionally
|
217
|
+
include 'redirect_uri'.
|
218
|
+
|
219
|
+
Returns:
|
220
|
+
Tuple: (OpenIdConnectWithConfig, AuthCredential)
|
221
|
+
|
222
|
+
Raises:
|
223
|
+
ValueError: If required fields are missing in the input dictionaries.
|
224
|
+
"""
|
225
|
+
|
226
|
+
# Validate and create the OpenIdConnectWithConfig scheme
|
227
|
+
try:
|
228
|
+
config_dict["scopes"] = scopes
|
229
|
+
# If user provides the OpenID Config as a static dict, it may not contain
|
230
|
+
# openIdConnect URL.
|
231
|
+
if "openIdConnectUrl" not in config_dict:
|
232
|
+
config_dict["openIdConnectUrl"] = ""
|
233
|
+
openid_scheme = OpenIdConnectWithConfig.model_validate(config_dict)
|
234
|
+
except ValidationError as e:
|
235
|
+
raise ValueError(f"Invalid OpenID Connect configuration: {e}") from e
|
236
|
+
|
237
|
+
# Attempt to adjust credential_dict if this is a key downloaded from Google
|
238
|
+
# OAuth config
|
239
|
+
if len(list(credential_dict.values())) == 1:
|
240
|
+
credential_value = list(credential_dict.values())[0]
|
241
|
+
if "client_id" in credential_value and "client_secret" in credential_value:
|
242
|
+
credential_dict = credential_value
|
243
|
+
|
244
|
+
# Validate credential_dict
|
245
|
+
required_credential_fields = ["client_id", "client_secret"]
|
246
|
+
missing_fields = [
|
247
|
+
field
|
248
|
+
for field in required_credential_fields
|
249
|
+
if field not in credential_dict
|
250
|
+
]
|
251
|
+
if missing_fields:
|
252
|
+
raise ValueError(
|
253
|
+
"Missing required fields in credential_dict:"
|
254
|
+
f" {', '.join(missing_fields)}"
|
255
|
+
)
|
256
|
+
|
257
|
+
# Construct AuthCredential
|
258
|
+
auth_credential = AuthCredential(
|
259
|
+
auth_type=AuthCredentialTypes.OPEN_ID_CONNECT,
|
260
|
+
oauth2=OAuth2Auth(
|
261
|
+
client_id=credential_dict["client_id"],
|
262
|
+
client_secret=credential_dict["client_secret"],
|
263
|
+
redirect_uri=credential_dict.get("redirect_uri", None),
|
264
|
+
),
|
265
|
+
)
|
266
|
+
|
267
|
+
return openid_scheme, auth_credential
|
268
|
+
|
269
|
+
|
270
|
+
def openid_url_to_scheme_credential(
|
271
|
+
openid_url: str, scopes: List[str], credential_dict: Dict[str, Any]
|
272
|
+
) -> Tuple[OpenIdConnectWithConfig, AuthCredential]:
|
273
|
+
"""Constructs OpenID scheme and credential from OpenID URL, scopes, and credential dictionary.
|
274
|
+
|
275
|
+
Fetches OpenID configuration from the provided URL.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
openid_url: The OpenID Connect discovery URL.
|
279
|
+
scopes: List of scopes to be used.
|
280
|
+
credential_dict: Dictionary containing credential information, must
|
281
|
+
include at least "client_id" and "client_secret", may optionally include
|
282
|
+
"redirect_uri" and "scope"
|
283
|
+
|
284
|
+
Returns:
|
285
|
+
Tuple: (AuthScheme, AuthCredential)
|
286
|
+
|
287
|
+
Raises:
|
288
|
+
ValueError: If the OpenID URL is invalid, fetching fails, or required
|
289
|
+
fields are missing.
|
290
|
+
requests.exceptions.RequestException: If there's an error during the
|
291
|
+
HTTP request.
|
292
|
+
"""
|
293
|
+
try:
|
294
|
+
response = requests.get(openid_url, timeout=10)
|
295
|
+
response.raise_for_status()
|
296
|
+
config_dict = response.json()
|
297
|
+
except requests.exceptions.RequestException as e:
|
298
|
+
raise ValueError(
|
299
|
+
f"Failed to fetch OpenID configuration from {openid_url}: {e}"
|
300
|
+
) from e
|
301
|
+
except ValueError as e:
|
302
|
+
raise ValueError(
|
303
|
+
"Invalid JSON response from OpenID configuration endpoint"
|
304
|
+
f" {openid_url}: {e}"
|
305
|
+
) from e
|
306
|
+
|
307
|
+
# Add openIdConnectUrl to config dict
|
308
|
+
config_dict["openIdConnectUrl"] = openid_url
|
309
|
+
|
310
|
+
return openid_dict_to_scheme_credential(config_dict, scopes, credential_dict)
|
311
|
+
|
312
|
+
|
313
|
+
INTERNAL_AUTH_PREFIX = "_auth_prefix_vaf_"
|
314
|
+
|
315
|
+
|
316
|
+
def credential_to_param(
|
317
|
+
auth_scheme: AuthScheme,
|
318
|
+
auth_credential: AuthCredential,
|
319
|
+
) -> Tuple[Optional[ApiParameter], Optional[Dict[str, Any]]]:
|
320
|
+
"""Converts AuthCredential and AuthScheme to a Parameter and a dictionary for additional kwargs.
|
321
|
+
|
322
|
+
This function now supports all credential types returned by the exchangers:
|
323
|
+
- API Key
|
324
|
+
- HTTP Bearer (for Bearer tokens, OAuth2, Service Account, OpenID Connect)
|
325
|
+
- OAuth2 and OpenID Connect (returns None, None, as the token is now a Bearer
|
326
|
+
token)
|
327
|
+
- Service Account (returns None, None, as the token is now a Bearer token)
|
328
|
+
|
329
|
+
Args:
|
330
|
+
auth_scheme: The AuthScheme object.
|
331
|
+
auth_credential: The AuthCredential object.
|
332
|
+
|
333
|
+
Returns:
|
334
|
+
Tuple: (ApiParameter, Dict[str, Any])
|
335
|
+
"""
|
336
|
+
if not auth_credential:
|
337
|
+
return None, None
|
338
|
+
|
339
|
+
if (
|
340
|
+
auth_scheme.type_ == AuthSchemeType.apiKey
|
341
|
+
and auth_credential
|
342
|
+
and auth_credential.api_key
|
343
|
+
):
|
344
|
+
param_name = auth_scheme.name or ""
|
345
|
+
python_name = INTERNAL_AUTH_PREFIX + param_name
|
346
|
+
if auth_scheme.in_ == APIKeyIn.header:
|
347
|
+
param_location = "header"
|
348
|
+
elif auth_scheme.in_ == APIKeyIn.query:
|
349
|
+
param_location = "query"
|
350
|
+
elif auth_scheme.in_ == APIKeyIn.cookie:
|
351
|
+
param_location = "cookie"
|
352
|
+
else:
|
353
|
+
raise ValueError(f"Invalid API Key location: {auth_scheme.in_}")
|
354
|
+
|
355
|
+
param = ApiParameter(
|
356
|
+
original_name=param_name,
|
357
|
+
param_location=param_location,
|
358
|
+
param_schema=Schema(type="string"),
|
359
|
+
description=auth_scheme.description or "",
|
360
|
+
py_name=python_name,
|
361
|
+
)
|
362
|
+
kwargs = {param.py_name: auth_credential.api_key}
|
363
|
+
return param, kwargs
|
364
|
+
|
365
|
+
# TODO(cheliu): Split handling for OpenIDConnect scheme and native HTTPBearer
|
366
|
+
# Scheme
|
367
|
+
elif (
|
368
|
+
auth_credential and auth_credential.auth_type == AuthCredentialTypes.HTTP
|
369
|
+
):
|
370
|
+
if (
|
371
|
+
auth_credential
|
372
|
+
and auth_credential.http
|
373
|
+
and auth_credential.http.credentials
|
374
|
+
and auth_credential.http.credentials.token
|
375
|
+
):
|
376
|
+
param = ApiParameter(
|
377
|
+
original_name="Authorization",
|
378
|
+
param_location="header",
|
379
|
+
param_schema=Schema(type="string"),
|
380
|
+
description=auth_scheme.description or "Bearer token",
|
381
|
+
py_name=INTERNAL_AUTH_PREFIX + "Authorization",
|
382
|
+
)
|
383
|
+
kwargs = {
|
384
|
+
param.py_name: f"Bearer {auth_credential.http.credentials.token}"
|
385
|
+
}
|
386
|
+
return param, kwargs
|
387
|
+
elif (
|
388
|
+
auth_credential
|
389
|
+
and auth_credential.http
|
390
|
+
and auth_credential.http.credentials
|
391
|
+
and (
|
392
|
+
auth_credential.http.credentials.username
|
393
|
+
or auth_credential.http.credentials.password
|
394
|
+
)
|
395
|
+
):
|
396
|
+
# Basic Auth is explicitly NOT supported
|
397
|
+
raise NotImplementedError("Basic Authentication is not supported.")
|
398
|
+
else:
|
399
|
+
raise ValueError("Invalid HTTP auth credentials")
|
400
|
+
|
401
|
+
# Service Account tokens, OAuth2 Tokens and OpenID Tokens are now handled as
|
402
|
+
# Bearer tokens.
|
403
|
+
elif (auth_scheme.type_ == AuthSchemeType.oauth2 and auth_credential) or (
|
404
|
+
auth_scheme.type_ == AuthSchemeType.openIdConnect and auth_credential
|
405
|
+
):
|
406
|
+
if (
|
407
|
+
auth_credential.http
|
408
|
+
and auth_credential.http.credentials
|
409
|
+
and auth_credential.http.credentials.token
|
410
|
+
):
|
411
|
+
param = ApiParameter(
|
412
|
+
original_name="Authorization",
|
413
|
+
param_location="header",
|
414
|
+
param_schema=Schema(type="string"),
|
415
|
+
description=auth_scheme.description or "Bearer token",
|
416
|
+
py_name=INTERNAL_AUTH_PREFIX + "Authorization",
|
417
|
+
)
|
418
|
+
kwargs = {
|
419
|
+
param.py_name: f"Bearer {auth_credential.http.credentials.token}"
|
420
|
+
}
|
421
|
+
return param, kwargs
|
422
|
+
return None, None
|
423
|
+
else:
|
424
|
+
raise ValueError("Invalid security scheme and credential combination")
|
425
|
+
|
426
|
+
|
427
|
+
def dict_to_auth_scheme(data: Dict[str, Any]) -> AuthScheme:
|
428
|
+
"""Converts a dictionary to a FastAPI AuthScheme object.
|
429
|
+
|
430
|
+
Args:
|
431
|
+
data: The dictionary representing the security scheme.
|
432
|
+
|
433
|
+
Returns:
|
434
|
+
A AuthScheme object (APIKey, HTTPBase, OAuth2, OpenIdConnect, or
|
435
|
+
HTTPBearer).
|
436
|
+
|
437
|
+
Raises:
|
438
|
+
ValueError: If the 'type' field is missing or invalid, or if the
|
439
|
+
dictionary cannot be converted to the corresponding Pydantic model.
|
440
|
+
|
441
|
+
Example:
|
442
|
+
```python
|
443
|
+
api_key_data = {
|
444
|
+
"type": "apiKey",
|
445
|
+
"in": "header",
|
446
|
+
"name": "X-API-Key",
|
447
|
+
}
|
448
|
+
api_key_scheme = dict_to_auth_scheme(api_key_data)
|
449
|
+
|
450
|
+
bearer_data = {
|
451
|
+
"type": "http",
|
452
|
+
"scheme": "bearer",
|
453
|
+
"bearerFormat": "JWT",
|
454
|
+
}
|
455
|
+
bearer_scheme = dict_to_auth_scheme(bearer_data)
|
456
|
+
|
457
|
+
|
458
|
+
oauth2_data = {
|
459
|
+
"type": "oauth2",
|
460
|
+
"flows": {
|
461
|
+
"authorizationCode": {
|
462
|
+
"authorizationUrl": "https://example.com/auth",
|
463
|
+
"tokenUrl": "https://example.com/token",
|
464
|
+
}
|
465
|
+
}
|
466
|
+
}
|
467
|
+
oauth2_scheme = dict_to_auth_scheme(oauth2_data)
|
468
|
+
|
469
|
+
openid_data = {
|
470
|
+
"type": "openIdConnect",
|
471
|
+
"openIdConnectUrl": "https://example.com/.well-known/openid-configuration"
|
472
|
+
}
|
473
|
+
openid_scheme = dict_to_auth_scheme(openid_data)
|
474
|
+
|
475
|
+
|
476
|
+
```
|
477
|
+
"""
|
478
|
+
if "type" not in data:
|
479
|
+
raise ValueError("Missing 'type' field in security scheme dictionary.")
|
480
|
+
|
481
|
+
security_type = data["type"]
|
482
|
+
try:
|
483
|
+
if security_type == "apiKey":
|
484
|
+
return APIKey.model_validate(data)
|
485
|
+
elif security_type == "http":
|
486
|
+
if data.get("scheme") == "bearer":
|
487
|
+
return HTTPBearer.model_validate(data)
|
488
|
+
else:
|
489
|
+
return HTTPBase.model_validate(data) # Generic HTTP
|
490
|
+
elif security_type == "oauth2":
|
491
|
+
return OAuth2.model_validate(data)
|
492
|
+
elif security_type == "openIdConnect":
|
493
|
+
return OpenIdConnect.model_validate(data)
|
494
|
+
else:
|
495
|
+
raise ValueError(f"Invalid security scheme type: {security_type}")
|
496
|
+
|
497
|
+
except ValidationError as e:
|
498
|
+
raise ValueError(f"Invalid security scheme data: {e}") from e
|
@@ -0,0 +1,25 @@
|
|
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 .auto_auth_credential_exchanger import AutoAuthCredentialExchanger
|
16
|
+
from .base_credential_exchanger import BaseAuthCredentialExchanger
|
17
|
+
from .oauth2_exchanger import OAuth2CredentialExchanger
|
18
|
+
from .service_account_exchanger import ServiceAccountCredentialExchanger
|
19
|
+
|
20
|
+
__all__ = [
|
21
|
+
'AutoAuthCredentialExchanger',
|
22
|
+
'BaseAuthCredentialExchanger',
|
23
|
+
'OAuth2CredentialExchanger',
|
24
|
+
'ServiceAccountCredentialExchanger',
|
25
|
+
]
|
@@ -0,0 +1,105 @@
|
|
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 Dict
|
16
|
+
from typing import Optional
|
17
|
+
from typing import Type
|
18
|
+
|
19
|
+
from .....auth.auth_credential import AuthCredential
|
20
|
+
from .....auth.auth_credential import AuthCredentialTypes
|
21
|
+
from .....auth.auth_schemes import AuthScheme
|
22
|
+
from .base_credential_exchanger import BaseAuthCredentialExchanger
|
23
|
+
from .oauth2_exchanger import OAuth2CredentialExchanger
|
24
|
+
from .service_account_exchanger import ServiceAccountCredentialExchanger
|
25
|
+
|
26
|
+
|
27
|
+
class AutoAuthCredentialExchanger(BaseAuthCredentialExchanger):
|
28
|
+
"""Automatically selects the appropriate credential exchanger based on the auth scheme.
|
29
|
+
|
30
|
+
Optionally, an override can be provided to use a specific exchanger for a
|
31
|
+
given auth scheme.
|
32
|
+
|
33
|
+
Example (common case):
|
34
|
+
```
|
35
|
+
exchanger = AutoAuthCredentialExchanger()
|
36
|
+
auth_credential = exchanger.exchange_credential(
|
37
|
+
auth_scheme=service_account_scheme,
|
38
|
+
auth_credential=service_account_credential,
|
39
|
+
)
|
40
|
+
# Returns an oauth token in the form of a bearer token.
|
41
|
+
```
|
42
|
+
|
43
|
+
Example (use CustomAuthExchanger for OAuth2):
|
44
|
+
```
|
45
|
+
exchanger = AutoAuthCredentialExchanger(
|
46
|
+
custom_exchangers={
|
47
|
+
AuthScheme.OAUTH2: CustomAuthExchanger,
|
48
|
+
}
|
49
|
+
)
|
50
|
+
```
|
51
|
+
|
52
|
+
Attributes:
|
53
|
+
exchangers: A dictionary mapping auth scheme to credential exchanger class.
|
54
|
+
"""
|
55
|
+
|
56
|
+
def __init__(
|
57
|
+
self,
|
58
|
+
custom_exchangers: Optional[
|
59
|
+
Dict[str, Type[BaseAuthCredentialExchanger]]
|
60
|
+
] = None,
|
61
|
+
):
|
62
|
+
"""Initializes the AutoAuthCredentialExchanger.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
custom_exchangers: Optional dictionary for adding or overriding auth
|
66
|
+
exchangers. The key is the auth scheme, and the value is the credential
|
67
|
+
exchanger class.
|
68
|
+
"""
|
69
|
+
self.exchangers = {
|
70
|
+
AuthCredentialTypes.OAUTH2: OAuth2CredentialExchanger,
|
71
|
+
AuthCredentialTypes.OPEN_ID_CONNECT: OAuth2CredentialExchanger,
|
72
|
+
AuthCredentialTypes.SERVICE_ACCOUNT: ServiceAccountCredentialExchanger,
|
73
|
+
}
|
74
|
+
|
75
|
+
if custom_exchangers:
|
76
|
+
self.exchangers.update(custom_exchangers)
|
77
|
+
|
78
|
+
def exchange_credential(
|
79
|
+
self,
|
80
|
+
auth_scheme: AuthScheme,
|
81
|
+
auth_credential: Optional[AuthCredential] = None,
|
82
|
+
) -> Optional[AuthCredential]:
|
83
|
+
"""Automatically exchanges for the credential uses the appropriate credential exchanger.
|
84
|
+
|
85
|
+
Args:
|
86
|
+
auth_scheme (AuthScheme): The security scheme.
|
87
|
+
auth_credential (AuthCredential): Optional. The authentication
|
88
|
+
credential.
|
89
|
+
|
90
|
+
Returns: (AuthCredential)
|
91
|
+
A new AuthCredential object containing the exchanged credential.
|
92
|
+
|
93
|
+
"""
|
94
|
+
if not auth_credential:
|
95
|
+
return None
|
96
|
+
|
97
|
+
exchanger_class = self.exchangers.get(
|
98
|
+
auth_credential.auth_type if auth_credential else None
|
99
|
+
)
|
100
|
+
|
101
|
+
if not exchanger_class:
|
102
|
+
return auth_credential
|
103
|
+
|
104
|
+
exchanger = exchanger_class()
|
105
|
+
return exchanger.exchange_credential(auth_scheme, auth_credential)
|
@@ -0,0 +1,55 @@
|
|
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 abc
|
16
|
+
from typing import Optional
|
17
|
+
|
18
|
+
from .....auth.auth_credential import (
|
19
|
+
AuthCredential,
|
20
|
+
)
|
21
|
+
from .....auth.auth_schemes import AuthScheme
|
22
|
+
|
23
|
+
|
24
|
+
class AuthCredentialMissingError(Exception):
|
25
|
+
"""Exception raised when required authentication credentials are missing."""
|
26
|
+
|
27
|
+
def __init__(self, message: str):
|
28
|
+
super().__init__(message)
|
29
|
+
self.message = message
|
30
|
+
|
31
|
+
|
32
|
+
class BaseAuthCredentialExchanger:
|
33
|
+
"""Base class for authentication credential exchangers."""
|
34
|
+
|
35
|
+
@abc.abstractmethod
|
36
|
+
def exchange_credential(
|
37
|
+
self,
|
38
|
+
auth_scheme: AuthScheme,
|
39
|
+
auth_credential: Optional[AuthCredential] = None,
|
40
|
+
) -> AuthCredential:
|
41
|
+
"""Exchanges the provided authentication credential for a usable token/credential.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
auth_scheme: The security scheme.
|
45
|
+
auth_credential: The authentication credential.
|
46
|
+
|
47
|
+
Returns:
|
48
|
+
An updated AuthCredential object containing the fetched credential.
|
49
|
+
For simple schemes like API key, it may return the original credential
|
50
|
+
if no exchange is needed.
|
51
|
+
|
52
|
+
Raises:
|
53
|
+
NotImplementedError: If the method is not implemented by a subclass.
|
54
|
+
"""
|
55
|
+
raise NotImplementedError("Subclasses must implement exchange_credential.")
|