agent-starter-pack 0.3.3__py3-none-any.whl → 0.21.0__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.
- agent_starter_pack/agents/README.md +7 -0
- agents/langgraph_base_react/template/.templateconfig.yaml → agent_starter_pack/agents/adk_a2a_base/.template/templateconfig.yaml +5 -10
- agent_starter_pack/agents/adk_a2a_base/README.md +37 -0
- src/deployment_targets/cloud_run/Dockerfile → agent_starter_pack/agents/adk_a2a_base/app/__init__.py +2 -14
- agent_starter_pack/agents/adk_a2a_base/app/agent.py +70 -0
- agent_starter_pack/agents/adk_a2a_base/notebooks/adk_a2a_app_testing.ipynb +583 -0
- agents/crewai_coding_crew/notebooks/evaluating_crewai_agent.ipynb → agent_starter_pack/agents/adk_a2a_base/notebooks/evaluating_adk_agent.ipynb +163 -199
- {agents/adk_base → agent_starter_pack/agents/adk_a2a_base}/tests/integration/test_agent.py +2 -2
- agents/adk_base/template/.templateconfig.yaml → agent_starter_pack/agents/adk_base/.template/templateconfig.yaml +4 -1
- {agents → agent_starter_pack/agents}/adk_base/README.md +1 -1
- agent_starter_pack/agents/adk_base/app/__init__.py +17 -0
- {agents → agent_starter_pack/agents}/adk_base/app/agent.py +5 -2
- {agents → agent_starter_pack/agents}/adk_base/notebooks/adk_app_testing.ipynb +128 -82
- agents/langgraph_base_react/notebooks/evaluating_langgraph_agent.ipynb → agent_starter_pack/agents/adk_base/notebooks/evaluating_adk_agent.ipynb +181 -207
- agent_starter_pack/agents/adk_base/tests/integration/test_agent.py +58 -0
- agents/crewai_coding_crew/template/.templateconfig.yaml → agent_starter_pack/agents/adk_live/.template/templateconfig.yaml +5 -9
- agent_starter_pack/agents/adk_live/README.md +32 -0
- agent_starter_pack/agents/adk_live/app/__init__.py +17 -0
- agent_starter_pack/agents/adk_live/app/agent.py +51 -0
- agent_starter_pack/agents/adk_live/tests/unit/test_dummy.py +38 -0
- agents/agentic_rag/template/.templateconfig.yaml → agent_starter_pack/agents/agentic_rag/.template/templateconfig.yaml +7 -3
- {agents → agent_starter_pack/agents}/agentic_rag/README.md +1 -1
- agent_starter_pack/agents/agentic_rag/app/__init__.py +17 -0
- {agents → agent_starter_pack/agents}/agentic_rag/app/agent.py +8 -4
- {agents → agent_starter_pack/agents}/agentic_rag/notebooks/adk_app_testing.ipynb +128 -82
- agent_starter_pack/agents/agentic_rag/notebooks/evaluating_adk_agent.ipynb +1535 -0
- {agents → agent_starter_pack/agents}/agentic_rag/tests/integration/test_agent.py +3 -3
- agent_starter_pack/agents/langgraph_base/.template/templateconfig.yaml +31 -0
- agent_starter_pack/agents/langgraph_base/README.md +30 -0
- agent_starter_pack/agents/langgraph_base/app/__init__.py +17 -0
- agent_starter_pack/agents/langgraph_base/app/agent.py +34 -0
- {agents/crewai_coding_crew → agent_starter_pack/agents/langgraph_base}/notebooks/evaluating_langgraph_agent.ipynb +30 -17
- {agents/langgraph_base_react → agent_starter_pack/agents/langgraph_base}/tests/integration/test_agent.py +2 -2
- {src → agent_starter_pack}/base_template/.gitignore +5 -3
- agent_starter_pack/base_template/GEMINI.md +5 -0
- agent_starter_pack/base_template/Makefile +339 -0
- agent_starter_pack/base_template/README.md +267 -0
- agent_starter_pack/base_template/deployment/README.md +11 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/apis.tf +2 -2
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/apis.tf +6 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/iam.tf +12 -11
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/providers.tf +5 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/storage.tf +1 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/variables.tf +10 -10
- agent_starter_pack/base_template/deployment/terraform/dev/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +193 -0
- agent_starter_pack/base_template/deployment/terraform/github.tf +337 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/iam.tf +20 -41
- {src → agent_starter_pack}/base_template/deployment/terraform/locals.tf +10 -3
- {src/resources/setup_cicd → agent_starter_pack/base_template/deployment/terraform}/providers.tf +8 -1
- {src → agent_starter_pack}/base_template/deployment/terraform/service_accounts.tf +7 -8
- agent_starter_pack/base_template/deployment/terraform/sql/completions.sql +138 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/storage.tf +7 -16
- {src → agent_starter_pack}/base_template/deployment/terraform/variables.tf +61 -28
- {src → agent_starter_pack}/base_template/deployment/terraform/vars/env.tfvars +6 -1
- agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %} +43 -0
- src/base_template/deployment/terraform/build_triggers.tf → agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +55 -38
- agent_starter_pack/base_template/deployment/terraform/{% if cookiecutter.is_adk %}telemetry.tf{% else %}unused_telemetry.tf{% endif %} +206 -0
- {src → agent_starter_pack}/base_template/pyproject.toml +24 -37
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +132 -0
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml +65 -0
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +259 -0
- src/base_template/deployment/cd/deploy-to-prod.yaml → agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +38 -30
- src/base_template/deployment/ci/pr_checks.yaml → agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/pr_checks.yaml +5 -5
- agent_starter_pack/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +322 -0
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/telemetry.py +96 -0
- {src/base_template/app/utils → agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils}/typing.py +7 -9
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/__init__.py +25 -0
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}converters{% else %}unused_converters{% endif %}/part_converter.py +138 -0
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/__init__.py +13 -0
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/a2a_agent_executor.py +265 -0
- agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_a2a and cookiecutter.agent_name == 'langgraph_base' %}executor{% else %}unused_executor{% endif %}/task_result_aggregator.py +152 -0
- agent_starter_pack/cli/commands/create.py +1256 -0
- agent_starter_pack/cli/commands/enhance.py +611 -0
- agent_starter_pack/cli/commands/list.py +203 -0
- agent_starter_pack/cli/commands/register_gemini_enterprise.py +1070 -0
- agent_starter_pack/cli/commands/setup_cicd.py +862 -0
- {src → agent_starter_pack}/cli/main.py +10 -2
- {src → agent_starter_pack}/cli/utils/cicd.py +139 -48
- agent_starter_pack/cli/utils/gcp.py +263 -0
- agent_starter_pack/cli/utils/logging.py +103 -0
- agent_starter_pack/cli/utils/remote_template.py +677 -0
- agent_starter_pack/cli/utils/template.py +1466 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/components/process_data.py +1 -1
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/submit_pipeline.py +20 -6
- {src → agent_starter_pack}/data_ingestion/pyproject.toml +1 -0
- {src → agent_starter_pack}/data_ingestion/uv.lock +602 -494
- agent_starter_pack/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +484 -0
- agent_starter_pack/deployment_targets/agent_engine/tests/load_test/README.md +84 -0
- agent_starter_pack/deployment_targets/agent_engine/tests/load_test/load_test.py +424 -0
- agent_starter_pack/deployment_targets/agent_engine/tests/{% if cookiecutter.is_a2a %}helpers.py{% else %}unused_helpers.py{% endif %} +138 -0
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py +263 -0
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/deploy.py +414 -0
- agent_starter_pack/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/app_utils/{% if cookiecutter.is_adk_live %}expose_app.py{% else %}unused_expose_app.py{% endif %} +519 -0
- agent_starter_pack/deployment_targets/cloud_run/Dockerfile +51 -0
- agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +243 -0
- agent_starter_pack/deployment_targets/cloud_run/deployment/terraform/service.tf +417 -0
- agent_starter_pack/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +705 -0
- agent_starter_pack/deployment_targets/cloud_run/tests/load_test/.results/.placeholder +321 -0
- agent_starter_pack/deployment_targets/cloud_run/tests/load_test/README.md +165 -0
- agent_starter_pack/deployment_targets/cloud_run/tests/load_test/load_test.py +329 -0
- agent_starter_pack/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/fast_api_app.py +556 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/package-lock.json +79 -1044
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/package.json +1 -9
- agent_starter_pack/frontends/adk_live_react/frontend/src/App.tsx +65 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/Logger.tsx +8 -3
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/logger.scss +26 -0
- agent_starter_pack/frontends/adk_live_react/frontend/src/components/side-panel/SidePanel.tsx +516 -0
- agent_starter_pack/frontends/adk_live_react/frontend/src/components/side-panel/side-panel.scss +563 -0
- agent_starter_pack/frontends/adk_live_react/frontend/src/components/transcription-preview/TranscriptionPreview.tsx +106 -0
- agent_starter_pack/frontends/adk_live_react/frontend/src/components/transcription-preview/transcription-preview.scss +150 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-live-api.ts +8 -2
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/multimodal-live-types.ts +40 -2
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audio-recorder.ts +1 -1
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audio-streamer.ts +1 -1
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/multimodal-live-client.ts +210 -24
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/utils.ts +27 -5
- agent_starter_pack/resources/docs/adk-cheatsheet.md +1628 -0
- agent_starter_pack/resources/locks/uv-adk_a2a_base-agent_engine.lock +4966 -0
- agent_starter_pack/resources/locks/uv-adk_a2a_base-cloud_run.lock +5011 -0
- agent_starter_pack/resources/locks/uv-adk_base-agent_engine.lock +4946 -0
- agent_starter_pack/resources/locks/uv-adk_base-cloud_run.lock +4991 -0
- agent_starter_pack/resources/locks/uv-adk_live-agent_engine.lock +4963 -0
- agent_starter_pack/resources/locks/uv-adk_live-cloud_run.lock +5006 -0
- agent_starter_pack/resources/locks/uv-agentic_rag-agent_engine.lock +5487 -0
- agent_starter_pack/resources/locks/uv-agentic_rag-cloud_run.lock +5532 -0
- agent_starter_pack/resources/locks/uv-langgraph_base-agent_engine.lock +5788 -0
- agent_starter_pack/resources/locks/uv-langgraph_base-cloud_run.lock +5811 -0
- {src → agent_starter_pack}/utils/generate_locks.py +15 -12
- {src → agent_starter_pack}/utils/lock_utils.py +4 -7
- {src → agent_starter_pack}/utils/watch_and_rebuild.py +2 -2
- agent_starter_pack-0.21.0.dist-info/METADATA +182 -0
- agent_starter_pack-0.21.0.dist-info/RECORD +171 -0
- agent_starter_pack-0.21.0.dist-info/entry_points.txt +2 -0
- llm.txt +362 -0
- agent_starter_pack-0.3.3.dist-info/METADATA +0 -164
- agent_starter_pack-0.3.3.dist-info/RECORD +0 -176
- agent_starter_pack-0.3.3.dist-info/entry_points.txt +0 -2
- agents/crewai_coding_crew/README.md +0 -34
- agents/crewai_coding_crew/app/agent.py +0 -86
- agents/crewai_coding_crew/app/crew/config/agents.yaml +0 -39
- agents/crewai_coding_crew/app/crew/config/tasks.yaml +0 -37
- agents/crewai_coding_crew/app/crew/crew.py +0 -71
- agents/crewai_coding_crew/tests/integration/test_agent.py +0 -47
- agents/langgraph_base_react/README.md +0 -9
- agents/langgraph_base_react/app/agent.py +0 -73
- agents/live_api/README.md +0 -37
- agents/live_api/app/agent.py +0 -78
- agents/live_api/app/server.py +0 -196
- agents/live_api/app/templates.py +0 -51
- agents/live_api/app/vector_store.py +0 -55
- agents/live_api/template/.templateconfig.yaml +0 -29
- agents/live_api/tests/integration/test_server_e2e.py +0 -254
- agents/live_api/tests/load_test/load_test.py +0 -40
- agents/live_api/tests/unit/test_server.py +0 -143
- src/base_template/Makefile +0 -72
- src/base_template/README.md +0 -208
- src/base_template/app/__init__.py +0 -3
- src/base_template/app/utils/tracing.py +0 -155
- src/base_template/deployment/README.md +0 -126
- src/base_template/deployment/cd/staging.yaml +0 -216
- src/base_template/deployment/terraform/dev/log_sinks.tf +0 -63
- src/base_template/deployment/terraform/log_sinks.tf +0 -70
- src/base_template/deployment/terraform/providers.tf +0 -37
- src/cli/commands/create.py +0 -664
- src/cli/commands/setup_cicd.py +0 -829
- src/cli/utils/gcp.py +0 -117
- src/cli/utils/logging.py +0 -51
- src/cli/utils/template.py +0 -737
- src/deployment_targets/agent_engine/app/agent_engine_app.py +0 -336
- src/deployment_targets/agent_engine/notebooks/intro_agent_engine.ipynb +0 -1025
- src/deployment_targets/agent_engine/tests/integration/test_agent_engine_app.py +0 -183
- src/deployment_targets/agent_engine/tests/load_test/README.md +0 -42
- src/deployment_targets/agent_engine/tests/load_test/load_test.py +0 -107
- src/deployment_targets/cloud_run/app/server.py +0 -154
- src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +0 -249
- src/deployment_targets/cloud_run/tests/load_test/.results/.placeholder +0 -0
- src/deployment_targets/cloud_run/tests/load_test/README.md +0 -83
- src/deployment_targets/cloud_run/tests/load_test/load_test.py +0 -118
- src/deployment_targets/cloud_run/uv.lock +0 -6952
- src/frontends/live_api_react/frontend/src/App.tsx +0 -205
- src/frontends/live_api_react/frontend/src/components/control-tray/ControlTray.tsx +0 -217
- src/frontends/live_api_react/frontend/src/components/control-tray/control-tray.scss +0 -201
- src/frontends/live_api_react/frontend/src/components/side-panel/SidePanel.tsx +0 -161
- src/frontends/live_api_react/frontend/src/components/side-panel/side-panel.scss +0 -285
- src/frontends/streamlit/frontend/side_bar.py +0 -214
- src/frontends/streamlit/frontend/streamlit_app.py +0 -265
- src/frontends/streamlit/frontend/style/app_markdown.py +0 -37
- src/frontends/streamlit/frontend/utils/chat_utils.py +0 -67
- src/frontends/streamlit/frontend/utils/local_chat_history.py +0 -125
- src/frontends/streamlit/frontend/utils/message_editing.py +0 -59
- src/frontends/streamlit/frontend/utils/multimodal_utils.py +0 -217
- src/frontends/streamlit/frontend/utils/stream_handler.py +0 -301
- src/frontends/streamlit/frontend/utils/title_summary.py +0 -94
- src/frontends/streamlit_adk/frontend/side_bar.py +0 -214
- src/frontends/streamlit_adk/frontend/streamlit_app.py +0 -314
- src/frontends/streamlit_adk/frontend/style/app_markdown.py +0 -37
- src/frontends/streamlit_adk/frontend/utils/chat_utils.py +0 -84
- src/frontends/streamlit_adk/frontend/utils/local_chat_history.py +0 -110
- src/frontends/streamlit_adk/frontend/utils/message_editing.py +0 -61
- src/frontends/streamlit_adk/frontend/utils/multimodal_utils.py +0 -223
- src/frontends/streamlit_adk/frontend/utils/stream_handler.py +0 -311
- src/frontends/streamlit_adk/frontend/utils/title_summary.py +0 -129
- src/resources/containers/data_processing/Dockerfile +0 -27
- src/resources/containers/e2e-tests/Dockerfile +0 -19
- src/resources/idx/.idx/dev.nix +0 -57
- src/resources/idx/idx-template.json +0 -21
- src/resources/idx/idx-template.nix +0 -26
- src/resources/locks/uv-adk_base-agent_engine.lock +0 -5338
- src/resources/locks/uv-adk_base-cloud_run.lock +0 -5930
- src/resources/locks/uv-agentic_rag-agent_engine.lock +0 -5528
- src/resources/locks/uv-agentic_rag-cloud_run.lock +0 -6120
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +0 -6231
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +0 -6839
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock +0 -5233
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock +0 -5862
- src/resources/locks/uv-live_api-cloud_run.lock +0 -5832
- src/resources/setup_cicd/cicd_variables.tf +0 -41
- src/resources/setup_cicd/github.tf +0 -87
- {agents → agent_starter_pack/agents}/agentic_rag/app/retrievers.py +0 -0
- {agents → agent_starter_pack/agents}/agentic_rag/app/templates.py +0 -0
- {src → agent_starter_pack}/base_template/deployment/terraform/dev/vars/env.tfvars +0 -0
- {src → agent_starter_pack}/base_template/tests/unit/test_dummy.py +0 -0
- {src/deployment_targets/agent_engine/app/utils → agent_starter_pack/base_template/{{cookiecutter.agent_directory}}/app_utils}/gcs.py +0 -0
- {src → agent_starter_pack}/cli/utils/__init__.py +0 -0
- {src → agent_starter_pack}/cli/utils/datastores.py +0 -0
- {src → agent_starter_pack}/cli/utils/version.py +0 -0
- {src → agent_starter_pack}/data_ingestion/README.md +0 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/components/ingest_data.py +0 -0
- {src → agent_starter_pack}/data_ingestion/data_ingestion_pipeline/pipeline.py +0 -0
- {src → agent_starter_pack}/deployment_targets/agent_engine/deployment_metadata.json +0 -0
- {src → agent_starter_pack}/deployment_targets/agent_engine/tests/load_test/.results/.placeholder +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/favicon.ico +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/index.html +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/public/robots.txt +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.scss +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/App.test.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/audio-pulse/AudioPulse.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/audio-pulse/audio-pulse.scss +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/components/logger/mock-logs.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/contexts/LiveAPIContext.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-media-stream-mux.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-screen-capture.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/hooks/use-webcam.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/index.css +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/index.tsx +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/react-app-env.d.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/reportWebVitals.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/setupTests.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/audioworklet-registry.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/store-logger.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/worklets/audio-processing.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/src/utils/worklets/vol-meter.ts +0 -0
- {src/frontends/live_api_react → agent_starter_pack/frontends/adk_live_react}/frontend/tsconfig.json +0 -0
- {agent_starter_pack-0.3.3.dist-info → agent_starter_pack-0.21.0.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.3.3.dist-info → agent_starter_pack-0.21.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,677 @@
|
|
|
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 pathlib
|
|
18
|
+
import re
|
|
19
|
+
import shutil
|
|
20
|
+
import subprocess
|
|
21
|
+
import sys
|
|
22
|
+
import tempfile
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
if sys.version_info >= (3, 11):
|
|
27
|
+
import tomllib
|
|
28
|
+
else:
|
|
29
|
+
import tomli as tomllib
|
|
30
|
+
from jinja2 import Environment
|
|
31
|
+
from packaging import version as pkg_version
|
|
32
|
+
from rich.console import Console
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass
|
|
36
|
+
class RemoteTemplateSpec:
|
|
37
|
+
"""Parsed remote template specification."""
|
|
38
|
+
|
|
39
|
+
repo_url: str
|
|
40
|
+
template_path: str
|
|
41
|
+
git_ref: str
|
|
42
|
+
is_adk_samples: bool = False
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def parse_agent_spec(agent_spec: str) -> RemoteTemplateSpec | None:
|
|
46
|
+
"""Parse agent specification to determine if it's a remote template.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
agent_spec: Agent specification string
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
RemoteTemplateSpec if remote template, None if local template
|
|
53
|
+
"""
|
|
54
|
+
# Check for local@ prefix
|
|
55
|
+
if agent_spec.startswith("local@"):
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
# Check for adk@ shortcut
|
|
59
|
+
if agent_spec.startswith("adk@"):
|
|
60
|
+
sample_name = agent_spec[4:] # Remove "adk@" prefix
|
|
61
|
+
return RemoteTemplateSpec(
|
|
62
|
+
repo_url="https://github.com/google/adk-samples",
|
|
63
|
+
template_path=f"python/agents/{sample_name}",
|
|
64
|
+
git_ref="main",
|
|
65
|
+
is_adk_samples=True,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# GitHub /tree/ URL pattern
|
|
69
|
+
tree_pattern = r"^(https?://[^/]+/[^/]+/[^/]+)/tree/([^/]+)/(.*)$"
|
|
70
|
+
match = re.match(tree_pattern, agent_spec)
|
|
71
|
+
if match:
|
|
72
|
+
repo_url = match.group(1)
|
|
73
|
+
git_ref = match.group(2)
|
|
74
|
+
template_path = match.group(3)
|
|
75
|
+
return RemoteTemplateSpec(
|
|
76
|
+
repo_url=repo_url,
|
|
77
|
+
template_path=template_path.strip("/"),
|
|
78
|
+
git_ref=git_ref,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# General remote pattern: <repo_url>[/<path>][@<ref>]
|
|
82
|
+
# Handles github.com, gitlab.com, etc.
|
|
83
|
+
remote_pattern = r"^(https?://[^/]+/[^/]+/[^/]+)(?:/(.*?))?(?:@([^/]+))?/?$"
|
|
84
|
+
match = re.match(remote_pattern, agent_spec)
|
|
85
|
+
if match:
|
|
86
|
+
repo_url = match.group(1)
|
|
87
|
+
template_path_with_ref = match.group(2) or ""
|
|
88
|
+
git_ref_from_url = match.group(3)
|
|
89
|
+
|
|
90
|
+
# Separate path and ref if ref is part of the path
|
|
91
|
+
template_path = template_path_with_ref
|
|
92
|
+
git_ref = git_ref_from_url or "main"
|
|
93
|
+
|
|
94
|
+
if "@" in template_path:
|
|
95
|
+
path_parts = template_path.split("@")
|
|
96
|
+
template_path = path_parts[0]
|
|
97
|
+
git_ref = path_parts[1]
|
|
98
|
+
|
|
99
|
+
# Check if this is the ADK samples repository
|
|
100
|
+
is_adk_samples = repo_url == "https://github.com/google/adk-samples"
|
|
101
|
+
|
|
102
|
+
return RemoteTemplateSpec(
|
|
103
|
+
repo_url=repo_url,
|
|
104
|
+
template_path=template_path.strip("/"),
|
|
105
|
+
git_ref=git_ref,
|
|
106
|
+
is_adk_samples=is_adk_samples,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# GitHub shorthand: <org>/<repo>[/<path>][@<ref>]
|
|
110
|
+
github_shorthand_pattern = r"^([^/]+)/([^/]+)(?:/(.*?))?(?:@([^/]+))?/?$"
|
|
111
|
+
match = re.match(github_shorthand_pattern, agent_spec)
|
|
112
|
+
if match and "/" in agent_spec: # Ensure it has at least one slash
|
|
113
|
+
org = match.group(1)
|
|
114
|
+
repo = match.group(2)
|
|
115
|
+
template_path = match.group(3) or ""
|
|
116
|
+
git_ref = match.group(4) or "main"
|
|
117
|
+
|
|
118
|
+
# Check if this is the ADK samples repository
|
|
119
|
+
is_adk_samples = org == "google" and repo == "adk-samples"
|
|
120
|
+
|
|
121
|
+
return RemoteTemplateSpec(
|
|
122
|
+
repo_url=f"https://github.com/{org}/{repo}",
|
|
123
|
+
template_path=template_path,
|
|
124
|
+
git_ref=git_ref,
|
|
125
|
+
is_adk_samples=is_adk_samples,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
return None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def check_and_execute_with_version_lock(
|
|
132
|
+
template_dir: pathlib.Path,
|
|
133
|
+
original_agent_spec: str | None = None,
|
|
134
|
+
locked: bool = False,
|
|
135
|
+
) -> bool:
|
|
136
|
+
"""Check if remote template has agent-starter-pack version lock and execute if found.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
template_dir: Path to the fetched template directory
|
|
140
|
+
original_agent_spec: The original agent spec (remote URL) to replace with local path
|
|
141
|
+
locked: Whether this is already a locked execution (prevents recursion)
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
True if version lock was found and executed, False otherwise
|
|
145
|
+
"""
|
|
146
|
+
# Skip version locking if we're already in a locked execution (prevents recursion)
|
|
147
|
+
if locked:
|
|
148
|
+
return False
|
|
149
|
+
uv_lock_path = template_dir / "uv.lock"
|
|
150
|
+
version = parse_agent_starter_pack_version_from_lock(uv_lock_path)
|
|
151
|
+
|
|
152
|
+
if version:
|
|
153
|
+
console = Console()
|
|
154
|
+
console.print(
|
|
155
|
+
f"🔒 Remote template requires agent-starter-pack version {version}",
|
|
156
|
+
style="bold blue",
|
|
157
|
+
)
|
|
158
|
+
console.print(
|
|
159
|
+
f"📦 Switching to version {version}...",
|
|
160
|
+
style="dim",
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
# Reconstruct the original command but with version constraint
|
|
164
|
+
import sys
|
|
165
|
+
|
|
166
|
+
original_args = sys.argv[1:] # Skip 'agent-starter-pack' or script name
|
|
167
|
+
|
|
168
|
+
# Add version lock specific parameters and handle remote URL replacement
|
|
169
|
+
if original_agent_spec:
|
|
170
|
+
# Check if --agent flag exists in original args
|
|
171
|
+
agent_flag_exists = "--agent" in original_args or "-a" in original_args
|
|
172
|
+
|
|
173
|
+
if agent_flag_exists:
|
|
174
|
+
# Replace remote agent spec with local path
|
|
175
|
+
original_args = [
|
|
176
|
+
f"local@{template_dir}" if arg == original_agent_spec else arg
|
|
177
|
+
for arg in original_args
|
|
178
|
+
]
|
|
179
|
+
else:
|
|
180
|
+
# Agent was selected interactively, add --agent flag
|
|
181
|
+
original_args.extend(["--agent", f"local@{template_dir}"])
|
|
182
|
+
|
|
183
|
+
# Add version lock flags only for ASP versions 0.14.1 and above
|
|
184
|
+
if pkg_version.parse(version) > pkg_version.parse("0.14.1"):
|
|
185
|
+
original_args.extend(["--skip-welcome", "--locked"])
|
|
186
|
+
|
|
187
|
+
try:
|
|
188
|
+
# Check if uvx is available
|
|
189
|
+
subprocess.run(["uvx", "--version"], capture_output=True, check=True)
|
|
190
|
+
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
191
|
+
console.print(
|
|
192
|
+
f"❌ Remote template requires agent-starter-pack version {version}, but 'uvx' is not installed",
|
|
193
|
+
style="bold red",
|
|
194
|
+
)
|
|
195
|
+
console.print(
|
|
196
|
+
"💡 Install uv to use version-locked remote templates:",
|
|
197
|
+
style="bold blue",
|
|
198
|
+
)
|
|
199
|
+
console.print(" curl -LsSf https://astral.sh/uv/install.sh | sh")
|
|
200
|
+
console.print(
|
|
201
|
+
" OR visit: https://docs.astral.sh/uv/getting-started/installation/"
|
|
202
|
+
)
|
|
203
|
+
sys.exit(1)
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
# Execute uvx with the locked version
|
|
207
|
+
cmd = ["uvx", f"agent-starter-pack@{version}", *original_args]
|
|
208
|
+
logging.debug(f"Executing nested command: {' '.join(cmd)}")
|
|
209
|
+
subprocess.run(cmd, check=True)
|
|
210
|
+
return True
|
|
211
|
+
|
|
212
|
+
except subprocess.CalledProcessError as e:
|
|
213
|
+
console.print(
|
|
214
|
+
f"❌ Failed to execute with locked version {version}: {e}",
|
|
215
|
+
style="bold red",
|
|
216
|
+
)
|
|
217
|
+
console.print(
|
|
218
|
+
"⚠️ Continuing with current version, but compatibility is not guaranteed",
|
|
219
|
+
style="yellow",
|
|
220
|
+
)
|
|
221
|
+
# Continue with current execution instead of failing completely
|
|
222
|
+
|
|
223
|
+
return False
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def fetch_remote_template(
|
|
227
|
+
spec: RemoteTemplateSpec,
|
|
228
|
+
original_agent_spec: str | None = None,
|
|
229
|
+
locked: bool = False,
|
|
230
|
+
) -> tuple[pathlib.Path, pathlib.Path]:
|
|
231
|
+
"""Fetch remote template and return path to template directory.
|
|
232
|
+
|
|
233
|
+
Uses Git to clone the remote repository. If the template contains a uv.lock
|
|
234
|
+
with agent-starter-pack version constraint, will execute nested uvx command.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
spec: Remote template specification
|
|
238
|
+
original_agent_spec: Original agent spec string (used to prevent recursion)
|
|
239
|
+
locked: Whether this is already a locked execution (prevents recursion)
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
A tuple containing:
|
|
243
|
+
- Path to the fetched template directory.
|
|
244
|
+
- Path to the top-level temporary directory that should be cleaned up.
|
|
245
|
+
"""
|
|
246
|
+
temp_dir = tempfile.mkdtemp(prefix="asp_remote_template_")
|
|
247
|
+
temp_path = pathlib.Path(temp_dir)
|
|
248
|
+
repo_path = temp_path / "repo"
|
|
249
|
+
|
|
250
|
+
# Attempt Git Clone
|
|
251
|
+
try:
|
|
252
|
+
clone_url = spec.repo_url
|
|
253
|
+
clone_cmd = [
|
|
254
|
+
"git",
|
|
255
|
+
"clone",
|
|
256
|
+
"--depth",
|
|
257
|
+
"1",
|
|
258
|
+
"--branch",
|
|
259
|
+
spec.git_ref,
|
|
260
|
+
clone_url,
|
|
261
|
+
str(repo_path),
|
|
262
|
+
]
|
|
263
|
+
logging.debug(
|
|
264
|
+
f"Attempting to clone remote template with Git: {' '.join(clone_cmd)}"
|
|
265
|
+
)
|
|
266
|
+
# GIT_TERMINAL_PROMPT=0 prevents git from prompting for credentials
|
|
267
|
+
subprocess.run(
|
|
268
|
+
clone_cmd,
|
|
269
|
+
capture_output=True,
|
|
270
|
+
text=True,
|
|
271
|
+
check=True,
|
|
272
|
+
encoding="utf-8",
|
|
273
|
+
env={**os.environ, "GIT_TERMINAL_PROMPT": "0"},
|
|
274
|
+
)
|
|
275
|
+
logging.debug("Git clone successful.")
|
|
276
|
+
except subprocess.CalledProcessError as e:
|
|
277
|
+
shutil.rmtree(temp_path, ignore_errors=True)
|
|
278
|
+
raise RuntimeError(f"Git clone failed: {e.stderr.strip()}") from e
|
|
279
|
+
|
|
280
|
+
# Process the successfully fetched template
|
|
281
|
+
try:
|
|
282
|
+
if spec.template_path:
|
|
283
|
+
template_dir = repo_path / spec.template_path
|
|
284
|
+
else:
|
|
285
|
+
template_dir = repo_path
|
|
286
|
+
|
|
287
|
+
if not template_dir.exists():
|
|
288
|
+
raise FileNotFoundError(
|
|
289
|
+
f"Template path not found in the repository: {spec.template_path}"
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Check for version lock and execute nested command if found
|
|
293
|
+
if check_and_execute_with_version_lock(
|
|
294
|
+
template_dir, original_agent_spec, locked
|
|
295
|
+
):
|
|
296
|
+
# If we executed with locked version, the nested process will handle everything
|
|
297
|
+
# Clean up and exit successfully
|
|
298
|
+
shutil.rmtree(temp_path, ignore_errors=True)
|
|
299
|
+
# Exit with success since the nested command will handle the rest
|
|
300
|
+
sys.exit(0)
|
|
301
|
+
|
|
302
|
+
return template_dir, temp_path
|
|
303
|
+
except Exception as e:
|
|
304
|
+
# Clean up on error
|
|
305
|
+
shutil.rmtree(temp_path, ignore_errors=True)
|
|
306
|
+
raise RuntimeError(
|
|
307
|
+
f"An unexpected error occurred after fetching remote template: {e}"
|
|
308
|
+
) from e
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def _infer_agent_directory_for_adk(
|
|
312
|
+
template_dir: pathlib.Path, is_adk_sample: bool
|
|
313
|
+
) -> dict[str, Any]:
|
|
314
|
+
"""Infer agent configuration for ADK samples only using Python conventions.
|
|
315
|
+
|
|
316
|
+
Args:
|
|
317
|
+
template_dir: Path to template directory
|
|
318
|
+
is_adk_sample: Whether this is an ADK sample
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
Dictionary with inferred configuration, or empty dict if not ADK sample
|
|
322
|
+
"""
|
|
323
|
+
if not is_adk_sample:
|
|
324
|
+
return {}
|
|
325
|
+
|
|
326
|
+
# Convert folder name to Python package convention (hyphens to underscores)
|
|
327
|
+
folder_name = template_dir.name
|
|
328
|
+
agent_directory = folder_name.replace("-", "_")
|
|
329
|
+
|
|
330
|
+
logging.debug(
|
|
331
|
+
f"Inferred agent_directory '{agent_directory}' from folder name '{folder_name}' for ADK sample"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
return {
|
|
335
|
+
"settings": {
|
|
336
|
+
"agent_directory": agent_directory,
|
|
337
|
+
},
|
|
338
|
+
"has_explicit_config": False, # Track that this was inferred
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def load_remote_template_config(
|
|
343
|
+
template_dir: pathlib.Path,
|
|
344
|
+
cli_overrides: dict[str, Any] | None = None,
|
|
345
|
+
is_adk_sample: bool = False,
|
|
346
|
+
) -> dict[str, Any]:
|
|
347
|
+
"""Load template configuration from remote template's pyproject.toml with CLI overrides.
|
|
348
|
+
|
|
349
|
+
Loads configuration from [tool.agent-starter-pack] section with fallbacks
|
|
350
|
+
to [project] section for name and description if not specified. CLI overrides
|
|
351
|
+
take precedence over all other sources. For ADK samples without explicit config,
|
|
352
|
+
uses smart inference for agent directory naming.
|
|
353
|
+
|
|
354
|
+
Args:
|
|
355
|
+
template_dir: Path to template directory
|
|
356
|
+
cli_overrides: Configuration overrides from CLI (takes highest precedence)
|
|
357
|
+
is_adk_sample: Whether this is an ADK sample (enables smart inference)
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
Template configuration dictionary with merged sources
|
|
361
|
+
"""
|
|
362
|
+
config: dict[str, Any] = {}
|
|
363
|
+
has_explicit_config = False
|
|
364
|
+
|
|
365
|
+
# Start with defaults
|
|
366
|
+
defaults = {
|
|
367
|
+
"base_template": "adk_base",
|
|
368
|
+
"name": template_dir.name,
|
|
369
|
+
"description": "",
|
|
370
|
+
"agent_directory": "app", # Default for non-ADK samples
|
|
371
|
+
}
|
|
372
|
+
config.update(defaults)
|
|
373
|
+
|
|
374
|
+
# Load from pyproject.toml if it exists
|
|
375
|
+
pyproject_path = template_dir / "pyproject.toml"
|
|
376
|
+
if pyproject_path.exists():
|
|
377
|
+
try:
|
|
378
|
+
with open(pyproject_path, "rb") as f:
|
|
379
|
+
pyproject_data = tomllib.load(f)
|
|
380
|
+
|
|
381
|
+
# Extract the agent-starter-pack configuration
|
|
382
|
+
toml_config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
|
|
383
|
+
|
|
384
|
+
# Fallback to [project] fields if not specified in agent-starter-pack section
|
|
385
|
+
project_info = pyproject_data.get("project", {})
|
|
386
|
+
|
|
387
|
+
# Track if we have explicit configuration
|
|
388
|
+
has_explicit_config = bool(toml_config)
|
|
389
|
+
|
|
390
|
+
# Apply pyproject.toml configuration (overrides defaults)
|
|
391
|
+
if toml_config:
|
|
392
|
+
config.update(toml_config)
|
|
393
|
+
logging.debug("Found explicit [tool.agent-starter-pack] configuration")
|
|
394
|
+
|
|
395
|
+
# Apply [project] fallbacks if not already set
|
|
396
|
+
if "name" not in toml_config and "name" in project_info:
|
|
397
|
+
config["name"] = project_info["name"]
|
|
398
|
+
|
|
399
|
+
if "description" not in toml_config and "description" in project_info:
|
|
400
|
+
config["description"] = project_info["description"]
|
|
401
|
+
|
|
402
|
+
logging.debug(f"Loaded template config from {pyproject_path}")
|
|
403
|
+
except Exception as e:
|
|
404
|
+
logging.error(f"Error loading pyproject.toml config: {e}")
|
|
405
|
+
else:
|
|
406
|
+
# No pyproject.toml found
|
|
407
|
+
if is_adk_sample:
|
|
408
|
+
logging.debug(
|
|
409
|
+
f"No pyproject.toml found for ADK sample {template_dir.name}, will use inference"
|
|
410
|
+
)
|
|
411
|
+
else:
|
|
412
|
+
logging.debug(
|
|
413
|
+
f"No pyproject.toml found for template {template_dir.name}, using defaults"
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
# Apply ADK inference if no explicit config and this is an ADK sample
|
|
417
|
+
if not has_explicit_config and is_adk_sample:
|
|
418
|
+
try:
|
|
419
|
+
inferred_config = _infer_agent_directory_for_adk(
|
|
420
|
+
template_dir, is_adk_sample
|
|
421
|
+
)
|
|
422
|
+
config.update(inferred_config)
|
|
423
|
+
logging.debug("Applied ADK inference for template without explicit config")
|
|
424
|
+
except Exception as e:
|
|
425
|
+
logging.warning(f"Failed to apply ADK inference for {template_dir}: {e}")
|
|
426
|
+
# Continue with default configuration
|
|
427
|
+
|
|
428
|
+
# Add metadata about configuration source
|
|
429
|
+
config["has_explicit_config"] = bool(has_explicit_config)
|
|
430
|
+
|
|
431
|
+
# Apply CLI overrides (highest precedence) using deep merge
|
|
432
|
+
if cli_overrides:
|
|
433
|
+
config = merge_template_configs(config, cli_overrides)
|
|
434
|
+
logging.debug(f"Applied CLI overrides: {cli_overrides}")
|
|
435
|
+
|
|
436
|
+
return config
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
def get_base_template_name(config: dict[str, Any]) -> str:
|
|
440
|
+
"""Get base template name from remote template config.
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
config: Template configuration dictionary
|
|
444
|
+
|
|
445
|
+
Returns:
|
|
446
|
+
Base template name (defaults to "adk_base")
|
|
447
|
+
"""
|
|
448
|
+
return config.get("base_template", "adk_base")
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def merge_template_configs(
|
|
452
|
+
base_config: dict[str, Any], remote_config: dict[str, Any]
|
|
453
|
+
) -> dict[str, Any]:
|
|
454
|
+
"""Merge base template config with remote template config using a deep merge.
|
|
455
|
+
|
|
456
|
+
Args:
|
|
457
|
+
base_config: Base template configuration
|
|
458
|
+
remote_config: Remote template configuration
|
|
459
|
+
|
|
460
|
+
Returns:
|
|
461
|
+
Merged configuration with remote overriding base
|
|
462
|
+
"""
|
|
463
|
+
import copy
|
|
464
|
+
|
|
465
|
+
def deep_merge(d1: dict[str, Any], d2: dict[str, Any]) -> dict[str, Any]:
|
|
466
|
+
"""Recursively merges d2 into d1."""
|
|
467
|
+
for k, v in d2.items():
|
|
468
|
+
if k in d1 and isinstance(d1[k], dict) and isinstance(v, dict):
|
|
469
|
+
d1[k] = deep_merge(d1[k], v)
|
|
470
|
+
else:
|
|
471
|
+
d1[k] = v
|
|
472
|
+
return d1
|
|
473
|
+
|
|
474
|
+
# Start with a deep copy of the base to avoid modifying it
|
|
475
|
+
merged_config = copy.deepcopy(base_config)
|
|
476
|
+
|
|
477
|
+
# Perform the deep merge
|
|
478
|
+
return deep_merge(merged_config, remote_config)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def discover_adk_agents(repo_path: pathlib.Path) -> dict[int, dict[str, Any]]:
|
|
482
|
+
"""Discover and load all ADK agents from a repository with inference support.
|
|
483
|
+
|
|
484
|
+
Args:
|
|
485
|
+
repo_path: Path to the cloned ADK samples repository
|
|
486
|
+
|
|
487
|
+
Returns:
|
|
488
|
+
Dictionary mapping agent numbers to agent info with keys:
|
|
489
|
+
- name: Agent display name
|
|
490
|
+
- description: Agent description
|
|
491
|
+
- path: Relative path from repo root
|
|
492
|
+
- spec: adk@ specification string
|
|
493
|
+
- has_explicit_config: Whether agent has explicit configuration
|
|
494
|
+
"""
|
|
495
|
+
import logging
|
|
496
|
+
|
|
497
|
+
adk_agents = {}
|
|
498
|
+
|
|
499
|
+
# Search specifically for agents in python/agents/* directories
|
|
500
|
+
agents_dir = repo_path / "python" / "agents"
|
|
501
|
+
logging.debug(f"Looking for agents in: {agents_dir}")
|
|
502
|
+
if agents_dir.exists():
|
|
503
|
+
all_items = list(agents_dir.iterdir())
|
|
504
|
+
logging.debug(
|
|
505
|
+
f"Found items in agents directory: {[item.name for item in all_items]}"
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
# Collect all agents first, then sort by configuration type
|
|
509
|
+
all_agents = []
|
|
510
|
+
|
|
511
|
+
for agent_dir in sorted(agents_dir.iterdir()):
|
|
512
|
+
if not agent_dir.is_dir():
|
|
513
|
+
logging.debug(f"Skipping non-directory: {agent_dir.name}")
|
|
514
|
+
continue
|
|
515
|
+
logging.debug(f"Processing agent directory: {agent_dir.name}")
|
|
516
|
+
|
|
517
|
+
try:
|
|
518
|
+
# Load configuration with ADK inference support
|
|
519
|
+
config = load_remote_template_config(
|
|
520
|
+
template_dir=agent_dir, is_adk_sample=True
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
agent_name = config.get("name", agent_dir.name)
|
|
524
|
+
description = config.get("description", "")
|
|
525
|
+
has_explicit_config = config.get("has_explicit_config", False)
|
|
526
|
+
|
|
527
|
+
# Get the relative path from repo root
|
|
528
|
+
relative_path = agent_dir.relative_to(repo_path)
|
|
529
|
+
agent_spec_name = agent_dir.name
|
|
530
|
+
|
|
531
|
+
agent_info = {
|
|
532
|
+
"name": agent_name,
|
|
533
|
+
"description": description,
|
|
534
|
+
"path": str(relative_path),
|
|
535
|
+
"spec": f"adk@{agent_spec_name}",
|
|
536
|
+
"has_explicit_config": has_explicit_config,
|
|
537
|
+
}
|
|
538
|
+
all_agents.append(agent_info)
|
|
539
|
+
|
|
540
|
+
except Exception as e:
|
|
541
|
+
logging.warning(f"Could not load agent from {agent_dir}: {e}")
|
|
542
|
+
|
|
543
|
+
# Sort agents: explicit config first, then inferred (both alphabetically within their groups)
|
|
544
|
+
all_agents.sort(key=lambda x: (not x["has_explicit_config"], x["name"].lower()))
|
|
545
|
+
|
|
546
|
+
# Convert to numbered dictionary
|
|
547
|
+
for i, agent_info in enumerate(all_agents, 1):
|
|
548
|
+
adk_agents[i] = agent_info
|
|
549
|
+
|
|
550
|
+
return adk_agents
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def display_adk_caveat_if_needed(agents: dict[int, dict[str, Any]]) -> None:
|
|
554
|
+
"""Display helpful note for agents that use inference.
|
|
555
|
+
|
|
556
|
+
Args:
|
|
557
|
+
agents: Dictionary of agent info from discover_adk_agents
|
|
558
|
+
"""
|
|
559
|
+
console = Console()
|
|
560
|
+
inferred_agents = [
|
|
561
|
+
a for a in agents.values() if not a.get("has_explicit_config", True)
|
|
562
|
+
]
|
|
563
|
+
if inferred_agents:
|
|
564
|
+
console.print(
|
|
565
|
+
"\n[blue]ℹ️ Note: Agents marked with * are templated using starter pack heuristics for ADK samples.[/]"
|
|
566
|
+
)
|
|
567
|
+
console.print(
|
|
568
|
+
"[dim] The starter pack attempts to create a working codebase, but you'll need to follow the generated README for complete setup.[/]"
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
def parse_agent_starter_pack_version_from_lock(
|
|
573
|
+
uv_lock_path: pathlib.Path,
|
|
574
|
+
) -> str | None:
|
|
575
|
+
"""Parse agent-starter-pack version from uv.lock file.
|
|
576
|
+
|
|
577
|
+
Args:
|
|
578
|
+
uv_lock_path: Path to uv.lock file
|
|
579
|
+
|
|
580
|
+
Returns:
|
|
581
|
+
Version string if found, None otherwise
|
|
582
|
+
"""
|
|
583
|
+
if not uv_lock_path.exists():
|
|
584
|
+
return None
|
|
585
|
+
|
|
586
|
+
try:
|
|
587
|
+
with open(uv_lock_path, "rb") as f:
|
|
588
|
+
lock_data = tomllib.load(f)
|
|
589
|
+
|
|
590
|
+
# Look for agent-starter-pack in the packages section
|
|
591
|
+
packages = lock_data.get("package", [])
|
|
592
|
+
for package in packages:
|
|
593
|
+
if package.get("name") == "agent-starter-pack":
|
|
594
|
+
version = package.get("version")
|
|
595
|
+
if version:
|
|
596
|
+
logging.debug(
|
|
597
|
+
f"Found agent-starter-pack version {version} in uv.lock"
|
|
598
|
+
)
|
|
599
|
+
return version
|
|
600
|
+
|
|
601
|
+
except Exception as e:
|
|
602
|
+
logging.warning(f"Error parsing uv.lock file {uv_lock_path}: {e}")
|
|
603
|
+
|
|
604
|
+
return None
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def render_and_merge_makefiles(
|
|
608
|
+
base_template_path: pathlib.Path,
|
|
609
|
+
final_destination: pathlib.Path,
|
|
610
|
+
cookiecutter_config: dict,
|
|
611
|
+
remote_template_path: pathlib.Path | None = None,
|
|
612
|
+
) -> None:
|
|
613
|
+
"""
|
|
614
|
+
Renders the base and remote Makefiles separately, then merges them.
|
|
615
|
+
|
|
616
|
+
If remote_template_path is not provided, only the base Makefile is rendered.
|
|
617
|
+
"""
|
|
618
|
+
|
|
619
|
+
env = Environment()
|
|
620
|
+
|
|
621
|
+
# Render the base Makefile
|
|
622
|
+
base_makefile_path = base_template_path / "Makefile"
|
|
623
|
+
if base_makefile_path.exists():
|
|
624
|
+
with open(base_makefile_path, encoding="utf-8") as f:
|
|
625
|
+
base_template = env.from_string(f.read())
|
|
626
|
+
rendered_base_makefile = base_template.render(cookiecutter=cookiecutter_config)
|
|
627
|
+
else:
|
|
628
|
+
rendered_base_makefile = ""
|
|
629
|
+
|
|
630
|
+
# Render the remote Makefile if a path is provided
|
|
631
|
+
rendered_remote_makefile = ""
|
|
632
|
+
if remote_template_path:
|
|
633
|
+
remote_makefile_path = remote_template_path / "Makefile"
|
|
634
|
+
if remote_makefile_path.exists():
|
|
635
|
+
with open(remote_makefile_path, encoding="utf-8") as f:
|
|
636
|
+
remote_template = env.from_string(f.read())
|
|
637
|
+
rendered_remote_makefile = remote_template.render(
|
|
638
|
+
cookiecutter=cookiecutter_config
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
# Merge the rendered Makefiles
|
|
642
|
+
if rendered_base_makefile and rendered_remote_makefile:
|
|
643
|
+
# A simple merge: remote content first, then append missing commands from base
|
|
644
|
+
base_commands = set(
|
|
645
|
+
re.findall(r"^([a-zA-Z0-9_-]+):", rendered_base_makefile, re.MULTILINE)
|
|
646
|
+
)
|
|
647
|
+
remote_commands = set(
|
|
648
|
+
re.findall(r"^([a-zA-Z0-9_-]+):", rendered_remote_makefile, re.MULTILINE)
|
|
649
|
+
)
|
|
650
|
+
missing_commands = base_commands - remote_commands
|
|
651
|
+
|
|
652
|
+
if missing_commands:
|
|
653
|
+
commands_to_append = ["\n\n# --- Commands from Agent Starter Pack ---\n\n"]
|
|
654
|
+
for command in sorted(missing_commands):
|
|
655
|
+
command_block_match = re.search(
|
|
656
|
+
rf"^{command}:.*?(?=\n\n(?:^#.*\n)*?^[a-zA-Z0-9_-]+:|" + r"\Z)",
|
|
657
|
+
rendered_base_makefile,
|
|
658
|
+
re.MULTILINE | re.DOTALL,
|
|
659
|
+
)
|
|
660
|
+
if command_block_match:
|
|
661
|
+
commands_to_append.append(command_block_match.group(0))
|
|
662
|
+
commands_to_append.append("\n\n")
|
|
663
|
+
|
|
664
|
+
final_makefile_content = rendered_remote_makefile + "".join(
|
|
665
|
+
commands_to_append
|
|
666
|
+
)
|
|
667
|
+
else:
|
|
668
|
+
final_makefile_content = rendered_remote_makefile
|
|
669
|
+
elif rendered_remote_makefile:
|
|
670
|
+
final_makefile_content = rendered_remote_makefile
|
|
671
|
+
else:
|
|
672
|
+
final_makefile_content = rendered_base_makefile
|
|
673
|
+
|
|
674
|
+
# Write the final merged Makefile
|
|
675
|
+
with open(final_destination / "Makefile", "w", encoding="utf-8") as f:
|
|
676
|
+
f.write(final_makefile_content)
|
|
677
|
+
logging.debug("Rendered and merged Makefile written to final destination.")
|