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,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
|
+
import streamlit.components.v1 as components
|
16
|
+
|
17
|
+
media_streamer = components.declare_component(
|
18
|
+
name='media_streamer', path='./media_streamer'
|
19
|
+
)
|
@@ -0,0 +1,228 @@
|
|
1
|
+
<!--
|
2
|
+
Copyright 2025 Google LLC
|
3
|
+
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
you may not use this file except in compliance with the License.
|
6
|
+
You may obtain a copy of the License at
|
7
|
+
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
See the License for the specific language governing permissions and
|
14
|
+
limitations under the License.
|
15
|
+
-->
|
16
|
+
|
17
|
+
<html>
|
18
|
+
<head>
|
19
|
+
<style type="text/css">
|
20
|
+
body {
|
21
|
+
font-family: sans-serif;
|
22
|
+
padding: 10px;
|
23
|
+
}
|
24
|
+
button {
|
25
|
+
font-size: 16px;
|
26
|
+
padding: 10px 15px;
|
27
|
+
margin-right: 10px;
|
28
|
+
}
|
29
|
+
#status {
|
30
|
+
font-weight: bold;
|
31
|
+
}
|
32
|
+
/* Mirror the preview video */
|
33
|
+
#videoPreview {
|
34
|
+
border: 1px solid #ccc;
|
35
|
+
transform: scaleX(-1);
|
36
|
+
}
|
37
|
+
</style>
|
38
|
+
</head>
|
39
|
+
<body>
|
40
|
+
<h2>Audio & Video Recorder Component</h2>
|
41
|
+
<!-- Video preview -->
|
42
|
+
<video id="videoPreview" autoplay muted playsinline width="320" height="240"></video>
|
43
|
+
<br/>
|
44
|
+
<!-- Unified start/stop buttons -->
|
45
|
+
<button id="startButton" onclick="startRecording()">Start Streaming</button>
|
46
|
+
<button id="stopButton" onclick="stopRecording()" disabled>Stop Streaming</button>
|
47
|
+
<span id="status">Idle</span>
|
48
|
+
|
49
|
+
<script type="text/javascript">
|
50
|
+
// --- Streamlit component lifecycle constants ---
|
51
|
+
const SET_COMPONENT_VALUE = "streamlit:setComponentValue";
|
52
|
+
const COMPONENT_READY = "streamlit:componentReady";
|
53
|
+
const SET_FRAME_HEIGHT = "streamlit:setFrameHeight";
|
54
|
+
const RENDER = "streamlit:render";
|
55
|
+
|
56
|
+
// Helper function to send messages to the Streamlit host.
|
57
|
+
function _sendMessage(type, data) {
|
58
|
+
const outboundData = Object.assign({ isStreamlitMessage: true, type: type }, data);
|
59
|
+
window.parent.postMessage(outboundData, "*");
|
60
|
+
}
|
61
|
+
function setFrameHeight(height) {
|
62
|
+
_sendMessage(SET_FRAME_HEIGHT, { height: height });
|
63
|
+
}
|
64
|
+
// This function sends the combined data.
|
65
|
+
function notifyHost(data) {
|
66
|
+
_sendMessage(SET_COMPONENT_VALUE, data);
|
67
|
+
}
|
68
|
+
function initialize() {
|
69
|
+
_sendMessage(COMPONENT_READY, { apiVersion: 1 });
|
70
|
+
window.addEventListener("load", function() {
|
71
|
+
setTimeout(() => setFrameHeight(document.documentElement.clientHeight), 0);
|
72
|
+
});
|
73
|
+
}
|
74
|
+
initialize();
|
75
|
+
|
76
|
+
// --- Global Variables ---
|
77
|
+
let isRecording = false;
|
78
|
+
let audioContext;
|
79
|
+
let scriptProcessor;
|
80
|
+
let audioAccumulatedChunks = [];
|
81
|
+
let audioFlushIntervalId = null;
|
82
|
+
let videoCaptureIntervalId = null;
|
83
|
+
const SAMPLE_RATE = 16000;
|
84
|
+
const BUFFER_SIZE = 4096;
|
85
|
+
let mediaStream = null; // for video (and optionally audio if needed)
|
86
|
+
|
87
|
+
// Global object to hold combined recording data.
|
88
|
+
let recordingData = {};
|
89
|
+
|
90
|
+
// Instead of calling notifyHost directly, update our combined data and send.
|
91
|
+
function sendCombinedUpdate(key, value) {
|
92
|
+
recordingData[key] = value;
|
93
|
+
notifyHost({
|
94
|
+
value: recordingData,
|
95
|
+
dataType: "json"
|
96
|
+
});
|
97
|
+
}
|
98
|
+
|
99
|
+
const videoElement = document.getElementById("videoPreview");
|
100
|
+
const statusSpan = document.getElementById("status");
|
101
|
+
const startButton = document.getElementById("startButton");
|
102
|
+
const stopButton = document.getElementById("stopButton");
|
103
|
+
|
104
|
+
// --- Start Recording: Capture both audio and video ---
|
105
|
+
async function startRecording() {
|
106
|
+
if (isRecording) return;
|
107
|
+
isRecording = true;
|
108
|
+
startButton.disabled = true;
|
109
|
+
stopButton.disabled = false;
|
110
|
+
statusSpan.innerText = "Streaming...";
|
111
|
+
|
112
|
+
// --- Setup audio recording ---
|
113
|
+
try {
|
114
|
+
audioContext = new (window.AudioContext || window.webkitAudioContext)({ sampleRate: SAMPLE_RATE });
|
115
|
+
let audioStream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
116
|
+
let mediaStreamSource = audioContext.createMediaStreamSource(audioStream);
|
117
|
+
scriptProcessor = audioContext.createScriptProcessor(BUFFER_SIZE, 1, 1);
|
118
|
+
scriptProcessor.onaudioprocess = function(event) {
|
119
|
+
let inputBuffer = event.inputBuffer;
|
120
|
+
let inputData = inputBuffer.getChannelData(0);
|
121
|
+
let pcmData = new Int16Array(inputData.length);
|
122
|
+
for (let i = 0; i < inputData.length; i++) {
|
123
|
+
let s = Math.max(-1, Math.min(1, inputData[i]));
|
124
|
+
pcmData[i] = s < 0 ? s * 0x8000 : s * 0x7FFF;
|
125
|
+
}
|
126
|
+
audioAccumulatedChunks.push(pcmData);
|
127
|
+
};
|
128
|
+
mediaStreamSource.connect(scriptProcessor);
|
129
|
+
scriptProcessor.connect(audioContext.destination);
|
130
|
+
} catch (err) {
|
131
|
+
console.error("Error accessing microphone:", err);
|
132
|
+
statusSpan.innerText = "Audio Error: " + err;
|
133
|
+
}
|
134
|
+
|
135
|
+
// --- Setup video recording ---
|
136
|
+
try {
|
137
|
+
let videoStream = await navigator.mediaDevices.getUserMedia({ video: true });
|
138
|
+
videoElement.srcObject = videoStream;
|
139
|
+
// Save the video stream so we can stop it later.
|
140
|
+
mediaStream = videoStream;
|
141
|
+
} catch (err) {
|
142
|
+
console.error("Error accessing camera:", err);
|
143
|
+
statusSpan.innerText = "Video Error: " + err;
|
144
|
+
}
|
145
|
+
|
146
|
+
// --- Start interval timers for flushing audio and capturing video ---
|
147
|
+
videoCaptureIntervalId = setInterval(captureVideoFrame, 250); // every 250ms
|
148
|
+
audioFlushIntervalId = setInterval(flushAudioChunks, 250); // every 250ms
|
149
|
+
}
|
150
|
+
|
151
|
+
// --- Stop Recording ---
|
152
|
+
function stopRecording() {
|
153
|
+
if (!isRecording) return;
|
154
|
+
isRecording = false;
|
155
|
+
startButton.disabled = false;
|
156
|
+
stopButton.disabled = true;
|
157
|
+
statusSpan.innerText = "Stopped.";
|
158
|
+
|
159
|
+
// Stop audio processing
|
160
|
+
if (scriptProcessor) {
|
161
|
+
scriptProcessor.disconnect();
|
162
|
+
scriptProcessor = null;
|
163
|
+
}
|
164
|
+
if (audioContext) {
|
165
|
+
audioContext.close();
|
166
|
+
audioContext = null;
|
167
|
+
}
|
168
|
+
if (audioFlushIntervalId) {
|
169
|
+
clearInterval(audioFlushIntervalId);
|
170
|
+
audioFlushIntervalId = null;
|
171
|
+
}
|
172
|
+
|
173
|
+
// Stop video stream
|
174
|
+
if (mediaStream) {
|
175
|
+
mediaStream.getTracks().forEach(track => track.stop());
|
176
|
+
mediaStream = null;
|
177
|
+
}
|
178
|
+
if (videoCaptureIntervalId) {
|
179
|
+
clearInterval(videoCaptureIntervalId);
|
180
|
+
videoCaptureIntervalId = null;
|
181
|
+
}
|
182
|
+
|
183
|
+
// Flush any remaining audio chunks
|
184
|
+
flushAudioChunks();
|
185
|
+
|
186
|
+
// Final notification that recording has stopped.
|
187
|
+
sendCombinedUpdate("message", "Recording stopped");
|
188
|
+
sendCombinedUpdate("isRecording", false);
|
189
|
+
}
|
190
|
+
|
191
|
+
// --- Flush accumulated audio chunks ---
|
192
|
+
function flushAudioChunks() {
|
193
|
+
if (audioAccumulatedChunks.length === 0) return;
|
194
|
+
// Combine all audio chunks into one array.
|
195
|
+
let totalLength = audioAccumulatedChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
196
|
+
let combined = new Int16Array(totalLength);
|
197
|
+
let offset = 0;
|
198
|
+
for (let chunk of audioAccumulatedChunks) {
|
199
|
+
combined.set(chunk, offset);
|
200
|
+
offset += chunk.length;
|
201
|
+
}
|
202
|
+
audioAccumulatedChunks = []; // clear accumulator
|
203
|
+
|
204
|
+
// Convert combined PCM data to a Blob.
|
205
|
+
let blob = new Blob([combined.buffer], { type: 'application/octet-stream' });
|
206
|
+
let reader = new FileReader();
|
207
|
+
reader.onloadend = function() {
|
208
|
+
// Instead of sending only audio, update the combined data.
|
209
|
+
sendCombinedUpdate("audioChunk", reader.result);
|
210
|
+
};
|
211
|
+
reader.readAsDataURL(blob);
|
212
|
+
}
|
213
|
+
|
214
|
+
// --- Capture a single video frame ---
|
215
|
+
function captureVideoFrame() {
|
216
|
+
if (!videoElement.srcObject) return;
|
217
|
+
const canvas = document.createElement("canvas");
|
218
|
+
canvas.width = videoElement.videoWidth || 320;
|
219
|
+
canvas.height = videoElement.videoHeight || 240;
|
220
|
+
const ctx = canvas.getContext("2d");
|
221
|
+
ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
|
222
|
+
let dataUrl = canvas.toDataURL("image/jpeg");
|
223
|
+
// Instead of a separate notifyHost call, update the combined data.
|
224
|
+
sendCombinedUpdate("videoFrame", dataUrl);
|
225
|
+
}
|
226
|
+
</script>
|
227
|
+
</body>
|
228
|
+
</html>
|
@@ -0,0 +1,49 @@
|
|
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 re
|
16
|
+
from typing import Any
|
17
|
+
from typing import Optional
|
18
|
+
|
19
|
+
from ...agents.base_agent import BaseAgent
|
20
|
+
from ...agents.llm_agent import LlmAgent
|
21
|
+
|
22
|
+
__all__ = [
|
23
|
+
'create_empty_state',
|
24
|
+
]
|
25
|
+
|
26
|
+
|
27
|
+
def _create_empty_state(agent: BaseAgent, all_state: dict[str, Any]):
|
28
|
+
for sub_agent in agent.sub_agents:
|
29
|
+
_create_empty_state(sub_agent, all_state)
|
30
|
+
|
31
|
+
if (
|
32
|
+
isinstance(agent, LlmAgent)
|
33
|
+
and agent.instruction
|
34
|
+
and isinstance(agent.instruction, str)
|
35
|
+
):
|
36
|
+
for key in re.findall(r'{([\w]+)}', agent.instruction):
|
37
|
+
all_state[key] = ''
|
38
|
+
|
39
|
+
|
40
|
+
def create_empty_state(
|
41
|
+
agent: BaseAgent, initialized_states: Optional[dict[str, Any]] = None
|
42
|
+
) -> dict[str, Any]:
|
43
|
+
"""Creates empty str for non-initialized states."""
|
44
|
+
non_initialized_states = {}
|
45
|
+
_create_empty_state(agent, non_initialized_states)
|
46
|
+
for key in initialized_states or {}:
|
47
|
+
if key in non_initialized_states:
|
48
|
+
del non_initialized_states[key]
|
49
|
+
return non_initialized_states
|
@@ -0,0 +1,57 @@
|
|
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 logging
|
16
|
+
import os
|
17
|
+
|
18
|
+
from dotenv import load_dotenv
|
19
|
+
|
20
|
+
logger = logging.getLogger(__file__)
|
21
|
+
|
22
|
+
|
23
|
+
def _walk_to_root_until_found(folder, filename) -> str:
|
24
|
+
checkpath = os.path.join(folder, filename)
|
25
|
+
if os.path.exists(checkpath) and os.path.isfile(checkpath):
|
26
|
+
return checkpath
|
27
|
+
|
28
|
+
parent_folder = os.path.dirname(folder)
|
29
|
+
if parent_folder == folder: # reached the root
|
30
|
+
return ''
|
31
|
+
|
32
|
+
return _walk_to_root_until_found(parent_folder, filename)
|
33
|
+
|
34
|
+
|
35
|
+
def load_dotenv_for_agent(
|
36
|
+
agent_name: str, agent_parent_folder: str, filename: str = '.env'
|
37
|
+
):
|
38
|
+
"""Lods the .env file for the agent module."""
|
39
|
+
|
40
|
+
# Gets the folder of agent_module as starting_folder
|
41
|
+
starting_folder = os.path.abspath(
|
42
|
+
os.path.join(agent_parent_folder, agent_name)
|
43
|
+
)
|
44
|
+
dotenv_file_path = _walk_to_root_until_found(starting_folder, filename)
|
45
|
+
if dotenv_file_path:
|
46
|
+
load_dotenv(dotenv_file_path, override=True, verbose=True)
|
47
|
+
logger.info(
|
48
|
+
'Loaded %s file for %s at %s',
|
49
|
+
filename,
|
50
|
+
agent_name,
|
51
|
+
dotenv_file_path,
|
52
|
+
)
|
53
|
+
logger.info(
|
54
|
+
'Reloaded %s file for %s at %s', filename, agent_name, dotenv_file_path
|
55
|
+
)
|
56
|
+
else:
|
57
|
+
logger.info('No %s file found for %s', filename, agent_name)
|
@@ -0,0 +1,93 @@
|
|
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
|
+
|
17
|
+
from ...sessions.session import Session
|
18
|
+
|
19
|
+
|
20
|
+
def convert_session_to_eval_format(session: Session) -> list[dict[str, Any]]:
|
21
|
+
"""Converts a session data into eval format.
|
22
|
+
|
23
|
+
Args:
|
24
|
+
session: The session that should be converted.
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
list: A single evaluation dataset in the required format.
|
28
|
+
"""
|
29
|
+
eval_case = []
|
30
|
+
events = session.events if session and session.events else []
|
31
|
+
|
32
|
+
for event in events:
|
33
|
+
if event.author == 'user':
|
34
|
+
if not event.content or not event.content.parts:
|
35
|
+
continue
|
36
|
+
|
37
|
+
# Extract user query
|
38
|
+
content = event.content
|
39
|
+
parts = content.parts
|
40
|
+
|
41
|
+
query = parts[0].text or ''
|
42
|
+
|
43
|
+
# Find the corresponding tool usage or response for the query
|
44
|
+
expected_tool_use = []
|
45
|
+
intermediate_agent_responses = []
|
46
|
+
|
47
|
+
# Check subsequent events to extract tool uses or responses for this turn.
|
48
|
+
for subsequent_event in events[events.index(event) + 1 :]:
|
49
|
+
event_author = subsequent_event.author or 'agent'
|
50
|
+
if event_author == 'user':
|
51
|
+
# We found an event where the author was the user. This means that a
|
52
|
+
# new turn has started. So close this turn here.
|
53
|
+
break
|
54
|
+
|
55
|
+
if not subsequent_event.content or not subsequent_event.content.parts:
|
56
|
+
continue
|
57
|
+
|
58
|
+
for subsequent_part in subsequent_event.content.parts:
|
59
|
+
# Some events have both function call and reference
|
60
|
+
|
61
|
+
if subsequent_part.function_call:
|
62
|
+
tool_name = subsequent_part.function_call.name or ''
|
63
|
+
tool_input = subsequent_part.function_call.args or {}
|
64
|
+
expected_tool_use.append({
|
65
|
+
'tool_name': tool_name,
|
66
|
+
'tool_input': tool_input,
|
67
|
+
})
|
68
|
+
elif subsequent_part.text:
|
69
|
+
# Also keep track of all the natural langauge responses that
|
70
|
+
# agent (or sub agents) generated.
|
71
|
+
intermediate_agent_responses.append(
|
72
|
+
{'author': event_author, 'text': subsequent_part.text}
|
73
|
+
)
|
74
|
+
|
75
|
+
# If we are here then either we are done reading all the events or we
|
76
|
+
# encountered an event that had content authored by the end-user.
|
77
|
+
# This, basically means an end of turn.
|
78
|
+
# We assume that the last natural langauge intermediate response is the
|
79
|
+
# final response from the agent/model. We treat that as a reference.
|
80
|
+
eval_case.append({
|
81
|
+
'query': query,
|
82
|
+
'expected_tool_use': expected_tool_use,
|
83
|
+
'expected_intermediate_agent_responses': intermediate_agent_responses[
|
84
|
+
:-1
|
85
|
+
],
|
86
|
+
'reference': (
|
87
|
+
intermediate_agent_responses[-1]['text']
|
88
|
+
if intermediate_agent_responses
|
89
|
+
else ''
|
90
|
+
),
|
91
|
+
})
|
92
|
+
|
93
|
+
return eval_case
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
import logging
|
16
|
+
import os
|
17
|
+
import tempfile
|
18
|
+
import time
|
19
|
+
|
20
|
+
LOGGING_FORMAT = (
|
21
|
+
'%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s'
|
22
|
+
)
|
23
|
+
|
24
|
+
|
25
|
+
def log_to_stderr(level=logging.INFO):
|
26
|
+
logging.basicConfig(
|
27
|
+
level=level,
|
28
|
+
format=LOGGING_FORMAT,
|
29
|
+
)
|
30
|
+
|
31
|
+
|
32
|
+
def log_to_tmp_folder(
|
33
|
+
level=logging.INFO,
|
34
|
+
*,
|
35
|
+
sub_folder: str = 'agents_log',
|
36
|
+
log_file_prefix: str = 'agent',
|
37
|
+
log_file_timestamp: str = time.strftime('%Y%m%d_%H%M%S'),
|
38
|
+
):
|
39
|
+
"""Logs to system temp folder, instead of logging to stderr.
|
40
|
+
|
41
|
+
Args
|
42
|
+
sub_folder: str = 'agents_log',
|
43
|
+
log_file_prefix: str = 'agent',
|
44
|
+
log_file_timestamp: str = time.strftime('%Y%m%d_%H%M%S'),
|
45
|
+
|
46
|
+
Returns
|
47
|
+
the log file path.
|
48
|
+
"""
|
49
|
+
log_dir = os.path.join(tempfile.gettempdir(), sub_folder)
|
50
|
+
log_filename = f'{log_file_prefix}.{log_file_timestamp}.log'
|
51
|
+
log_filepath = os.path.join(log_dir, log_filename)
|
52
|
+
|
53
|
+
os.makedirs(log_dir, exist_ok=True)
|
54
|
+
|
55
|
+
file_handler = logging.FileHandler(log_filepath, mode='w')
|
56
|
+
file_handler.setLevel(level)
|
57
|
+
file_handler.setFormatter(logging.Formatter(LOGGING_FORMAT))
|
58
|
+
|
59
|
+
root_logger = logging.getLogger()
|
60
|
+
root_logger.setLevel(level)
|
61
|
+
root_logger.handlers = [] # Clear handles to disable logging to stderr
|
62
|
+
root_logger.addHandler(file_handler)
|
63
|
+
|
64
|
+
print(f'Log setup complete: {log_filepath}')
|
65
|
+
|
66
|
+
latest_log_link = os.path.join(log_dir, f'{log_file_prefix}.latest.log')
|
67
|
+
if os.path.islink(latest_log_link):
|
68
|
+
os.unlink(latest_log_link)
|
69
|
+
os.symlink(log_filepath, latest_log_link)
|
70
|
+
|
71
|
+
print(f'To access latest log: tail -F {latest_log_link}')
|
72
|
+
return log_filepath
|
@@ -0,0 +1,49 @@
|
|
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 logging
|
16
|
+
|
17
|
+
from .base_code_executor import BaseCodeExecutor
|
18
|
+
from .code_executor_context import CodeExecutorContext
|
19
|
+
from .unsafe_local_code_executor import UnsafeLocalCodeExecutor
|
20
|
+
|
21
|
+
logger = logging.getLogger(__name__)
|
22
|
+
|
23
|
+
__all__ = [
|
24
|
+
'BaseCodeExecutor',
|
25
|
+
'CodeExecutorContext',
|
26
|
+
'UnsafeLocalCodeExecutor',
|
27
|
+
]
|
28
|
+
|
29
|
+
try:
|
30
|
+
from .vertex_ai_code_executor import VertexAiCodeExecutor
|
31
|
+
|
32
|
+
__all__.append('VertexAiCodeExecutor')
|
33
|
+
except ImportError:
|
34
|
+
logger.debug(
|
35
|
+
'The Vertex sdk is not installed. If you want to use the Vertex Code'
|
36
|
+
' Interpreter with agents, please install it. If not, you can ignore this'
|
37
|
+
' warning.'
|
38
|
+
)
|
39
|
+
|
40
|
+
try:
|
41
|
+
from .container_code_executor import ContainerCodeExecutor
|
42
|
+
|
43
|
+
__all__.append('ContainerCodeExecutor')
|
44
|
+
except ImportError:
|
45
|
+
logger.debug(
|
46
|
+
'The docker sdk is not installed. If you want to use the Container Code'
|
47
|
+
' Executor with agents, please install it. If not, you can ignore this'
|
48
|
+
' warning.'
|
49
|
+
)
|
@@ -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
|
+
import abc
|
16
|
+
from typing import List
|
17
|
+
|
18
|
+
from pydantic import BaseModel
|
19
|
+
|
20
|
+
from ..agents.invocation_context import InvocationContext
|
21
|
+
from .code_execution_utils import CodeExecutionInput
|
22
|
+
from .code_execution_utils import CodeExecutionResult
|
23
|
+
|
24
|
+
|
25
|
+
class BaseCodeExecutor(BaseModel):
|
26
|
+
"""Abstract base class for all code executors.
|
27
|
+
|
28
|
+
The code executor allows the agent to execute code blocks from model responses
|
29
|
+
and incorporate the execution results into the final response.
|
30
|
+
|
31
|
+
Attributes:
|
32
|
+
optimize_data_file: If true, extract and process data files from the model
|
33
|
+
request and attach them to the code executor. Supported data file
|
34
|
+
MimeTypes are [text/csv]. Default to False.
|
35
|
+
stateful: Whether the code executor is stateful. Default to False.
|
36
|
+
error_retry_attempts: The number of attempts to retry on consecutive code
|
37
|
+
execution errors. Default to 2.
|
38
|
+
code_block_delimiters: The list of the enclosing delimiters to identify the
|
39
|
+
code blocks.
|
40
|
+
execution_result_delimiters: The delimiters to format the code execution
|
41
|
+
result.
|
42
|
+
"""
|
43
|
+
|
44
|
+
optimize_data_file: bool = False
|
45
|
+
"""
|
46
|
+
If true, extract and process data files from the model request
|
47
|
+
and attach them to the code executor.
|
48
|
+
Supported data file MimeTypes are [text/csv].
|
49
|
+
|
50
|
+
Default to False.
|
51
|
+
"""
|
52
|
+
|
53
|
+
stateful: bool = False
|
54
|
+
"""
|
55
|
+
Whether the code executor is stateful. Default to False.
|
56
|
+
"""
|
57
|
+
|
58
|
+
error_retry_attempts: int = 2
|
59
|
+
"""
|
60
|
+
The number of attempts to retry on consecutive code execution errors. Default to 2.
|
61
|
+
"""
|
62
|
+
|
63
|
+
code_block_delimiters: List[tuple[str, str]] = [
|
64
|
+
('```tool_code\n', '\n```'),
|
65
|
+
('```python\n', '\n```'),
|
66
|
+
]
|
67
|
+
"""
|
68
|
+
The list of the enclosing delimiters to identify the code blocks.
|
69
|
+
For example, the delimiter ('```python\n', '\n```') can be
|
70
|
+
used to identify code blocks with the following format:
|
71
|
+
|
72
|
+
```python
|
73
|
+
print("hello")
|
74
|
+
```
|
75
|
+
"""
|
76
|
+
|
77
|
+
execution_result_delimiters: tuple[str, str] = ('```tool_output\n', '\n```')
|
78
|
+
"""
|
79
|
+
The delimiters to format the code execution result.
|
80
|
+
"""
|
81
|
+
|
82
|
+
@abc.abstractmethod
|
83
|
+
def execute_code(
|
84
|
+
self,
|
85
|
+
invocation_context: InvocationContext,
|
86
|
+
code_execution_input: CodeExecutionInput,
|
87
|
+
) -> CodeExecutionResult:
|
88
|
+
"""Executes code and return the code execution result.
|
89
|
+
|
90
|
+
Args:
|
91
|
+
invocation_context: The invocation context of the code execution.
|
92
|
+
code_execution_input: The code execution input.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
The code execution result.
|
96
|
+
"""
|
97
|
+
pass
|