agent-starter-pack 0.12.0__py3-none-any.whl → 0.13.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.
Files changed (29) hide show
  1. {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/METADATA +2 -1
  2. {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/RECORD +27 -29
  3. src/base_template/Makefile +18 -6
  4. src/base_template/README.md +13 -48
  5. src/cli/commands/create.py +54 -53
  6. src/cli/commands/enhance.py +6 -2
  7. src/cli/commands/list.py +65 -26
  8. src/cli/utils/gcp.py +122 -1
  9. src/cli/utils/remote_template.py +175 -4
  10. src/cli/utils/template.py +72 -1
  11. src/deployment_targets/cloud_run/Dockerfile +16 -0
  12. src/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/server.py +49 -1
  13. src/frontends/live_api_react/frontend/package-lock.json +9 -9
  14. src/frontends/live_api_react/frontend/src/App.tsx +3 -2
  15. src/frontends/live_api_react/frontend/src/utils/multimodal-live-client.ts +3 -1
  16. src/resources/locks/uv-adk_base-agent_engine.lock +452 -452
  17. src/resources/locks/uv-adk_base-cloud_run.lock +571 -568
  18. src/resources/locks/uv-agentic_rag-agent_engine.lock +565 -566
  19. src/resources/locks/uv-agentic_rag-cloud_run.lock +716 -713
  20. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +729 -735
  21. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +923 -940
  22. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +658 -664
  23. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +852 -869
  24. src/resources/locks/uv-live_api-cloud_run.lock +758 -775
  25. src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +0 -3938
  26. src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +0 -4501
  27. {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/WHEEL +0 -0
  28. {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/entry_points.txt +0 -0
  29. {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-starter-pack
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: CLI to bootstrap production-ready Google Cloud GenAI agent projects from templates.
5
5
  Author-email: Google LLC <agent-starter-pack@google.com>
6
6
  License: Apache-2.0
@@ -12,6 +12,7 @@ Requires-Dist: cookiecutter~=2.6.0
12
12
  Requires-Dist: google-cloud-aiplatform>=1.87.0
13
13
  Requires-Dist: pyyaml>=6.0.1
14
14
  Requires-Dist: rich>=13.7.0
15
+ Requires-Dist: tomli>=1.1.0; python_version < '3.11'
15
16
  Provides-Extra: jupyter
16
17
  Requires-Dist: ipykernel>=6.29.5; extra == 'jupyter'
17
18
  Requires-Dist: jupyter; extra == 'jupyter'
@@ -38,8 +38,8 @@ agents/live_api/tests/unit/test_server.py,sha256=_tf9nHkb7aOe3lZRlyp7cVklOTOYTuX
38
38
  llm.txt,sha256=onvCAhaPcye3YWfCkQeX4Y-LWF1TsAsZ09cO_iO-i3Y,14607
39
39
  src/base_template/.gitignore,sha256=Fq0w34x4sfbwP4RqDqh6hdHNYRUEsFNI-9XONzLWBIs,2580
40
40
  src/base_template/GEMINI.md,sha256=WzscHWlQeYkKORZ-453P8KM9IHuj1kAxW-69c7Ytuwk,133
41
- src/base_template/Makefile,sha256=tUPxvZI-XyAs2cXa3L3aTh3DFkwUBYkF5BOGs0DtvIk,6267
42
- src/base_template/README.md,sha256=KkHKYpnkU7gzfvzyULlTyt7gUxkf1IcK7Y4ydceLVzc,11458
41
+ src/base_template/Makefile,sha256=8LRvbHvuj92oFr9dB3E92O39WqMKxM_kPO5t2lewOC4,6818
42
+ src/base_template/README.md,sha256=ywTmrlWmivgHAtzXQCZqNu_Hfxp51QTnX4USNgGk6kU,10040
43
43
  src/base_template/pyproject.toml,sha256=dTyxaWetB-XCKQEDV3lXxAUxtBEpustNdlAEcT8ZZpo,2932
44
44
  src/base_template/deployment/README.md,sha256=gZJvSWdQh_Mi-bZ3dmuPv7fMezIw04fgN5tq7KgglPw,692
45
45
  src/base_template/deployment/terraform/apis.tf,sha256=KX8Oe2gjT-gh9Bkntz9yIAyRjPc1gZvwOhroJ6NZVp4,1513
@@ -72,17 +72,17 @@ src/base_template/{{cookiecutter.agent_directory}}/utils/gcs.py,sha256=jKblaWOGQ
72
72
  src/base_template/{{cookiecutter.agent_directory}}/utils/tracing.py,sha256=2rv1Ukh2jTBENDwoghCItJ28l-Sjz9gMlzdojlVgJa4,6052
73
73
  src/base_template/{{cookiecutter.agent_directory}}/utils/typing.py,sha256=DP5OZC3IGvqA1XbvWt8kI3gyAK3ZjzUSL5Ca17wNeLI,4249
74
74
  src/cli/main.py,sha256=Dya7Sw3ozMTaGDcwMh_-W7udkGZHGzgAj8aBdSZaZxI,1832
75
- src/cli/commands/create.py,sha256=l2Uo_cVekBNLJA-dnBy5Lue9yUwhUStkOUmIYSvyf-8,44810
76
- src/cli/commands/enhance.py,sha256=rrELrS1BErjDiTmeyVek8bbiIoxrSUZY2eYOqiAvi2Y,15076
77
- src/cli/commands/list.py,sha256=_Xi2f1myiqEuZnfv-OkY8nPC58YhKOzYDGqh8GW9nd8,5502
75
+ src/cli/commands/create.py,sha256=qVcK3E5DzQ66QACrwDA2q-6LvCApipIcht9HCi-LT28,45331
76
+ src/cli/commands/enhance.py,sha256=4QMfU2hGHw1tZLrTYtBvpc3n6__mdSSekKMqy4OQAyE,15137
77
+ src/cli/commands/list.py,sha256=ZGol9eYB9Yon7JysMUCtpEOwdXzrApdTHzErx6KvT04,6856
78
78
  src/cli/commands/setup_cicd.py,sha256=nSgMUD4_ncYGwLWU1Fl7Ypw3GTJc8qVfjPxwZMLn4xo,32113
79
79
  src/cli/utils/__init__.py,sha256=_cTmsXGPqOtK0q8UW5164QTltbJRJFR_Efxq_BRL1-o,1311
80
80
  src/cli/utils/cicd.py,sha256=9s_OcusQznT_pSjFP60BfDBoZ5V6bwPE0QWbWdMaVlY,26515
81
81
  src/cli/utils/datastores.py,sha256=gv1V6eDcOEKx4MRNG5C3Y-VfixYq1AzQuaYMLp8QRNo,1058
82
- src/cli/utils/gcp.py,sha256=cnuCyN144eiyYc9aJNEK9JnyWN66rdevugoMdDYC1UU,4032
82
+ src/cli/utils/gcp.py,sha256=XDtQVsqnYiZl4OGhrDjRwn5vq4GpFGu9v1CRwdu39Rs,8245
83
83
  src/cli/utils/logging.py,sha256=MYPxQYXXaKCqBVOfrhEMe8lFKzpzZWjOVP2Km81X5Mk,3007
84
- src/cli/utils/remote_template.py,sha256=Uqqhz84p9zlhccUP8ucU1oRs0lCly4see5mfujP42eM,12165
85
- src/cli/utils/template.py,sha256=2CnxXTvQVM_ZnY8NlBNXuyhmIsflDe1eTUrHPFR7Qqk,46175
84
+ src/cli/utils/remote_template.py,sha256=BYdV9Bgj54UUgOTnxlkOr8xA9ZgqKSEE-lWnmpJ05UY,18529
85
+ src/cli/utils/template.py,sha256=j-f1FyvG9BuE7KTZglQ9BCYiPMbvW5z2xnr5JQLOhkg,50034
86
86
  src/cli/utils/version.py,sha256=F4udQmzniPStqWZFIgnv3Qg3l9non4mfy2An-Oveqmc,2916
87
87
  src/data_ingestion/README.md,sha256=LNxSQoJW9JozK-TbyGQLj5L_MGWNwrfLk6V6RmQ2oBQ,4032
88
88
  src/data_ingestion/pyproject.toml,sha256=-1Mf2QB8K70ICQV5UPZDpf-fN3UwEQLVzQyxfakCSTY,445
@@ -98,15 +98,15 @@ src/deployment_targets/agent_engine/tests/load_test/README.md,sha256=aQP7nDAqd2j
98
98
  src/deployment_targets/agent_engine/tests/load_test/load_test.py,sha256=USzS89bQ4qHVoQynDRSRShKzeXf1MJ0MBV4FpV40vrI,4249
99
99
  src/deployment_targets/agent_engine/tests/load_test/.results/.placeholder,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
100
  src/deployment_targets/agent_engine/{{cookiecutter.agent_directory}}/agent_engine_app.py,sha256=91idmH-p7B7Gk8iMZoUeutndUqBhXt3apxUrTE64VlM,12797
101
- src/deployment_targets/cloud_run/Dockerfile,sha256=LdVMFTcYtO7b0L3jBXbVMUlHknL41ELp3RmzIGmxOH8,978
101
+ src/deployment_targets/cloud_run/Dockerfile,sha256=rSpmFK7uJhZYwYMtxH8W7mywcCPvaoFn7gL_mXRYuF8,1449
102
102
  src/deployment_targets/cloud_run/deployment/terraform/service.tf,sha256=w3iEnyScbO0sjLPQEYfs3GmPpHTUMGeG1ghi09wSY24,10322
103
103
  src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf,sha256=VegAzMcl2ohxMvtq6bcSXfCHYzQW68usyA839oULpgk,6581
104
104
  src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py,sha256=85tA1gtbu_Z2CJqzOHgvDS-lvQFbYUMW8_mfqEc1_8I,9325
105
105
  src/deployment_targets/cloud_run/tests/load_test/README.md,sha256=clrCwgwUDr_AsivG0oLeNImTK4uke9EAWkrpS2nhIX0,2769
106
106
  src/deployment_targets/cloud_run/tests/load_test/load_test.py,sha256=kK3KaCdBFHKlni3ZVY2u4h_ugNla4o6pbhGRZlQ-haI,4270
107
107
  src/deployment_targets/cloud_run/tests/load_test/.results/.placeholder,sha256=ZbWpSgDo8bT33PstD_73aQSeN_0oo0F104NMUGuZ8lE,14903
108
- src/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/server.py,sha256=kKmjr8opUz2Z1nFw9-yKCu8T0tCBZQgWm3R9ab_l1fM,13752
109
- src/frontends/live_api_react/frontend/package-lock.json,sha256=_vWIfornMhB4lrRIwUmy4CqKGINCKjeUuYcTw2Sc_IY,734344
108
+ src/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/server.py,sha256=TKUFGNVxBlWh61owDIemiE734ENWKtWHXSAZ5Oix2t0,15463
109
+ src/frontends/live_api_react/frontend/package-lock.json,sha256=h6yK6e_GR6CeZn_C9gGJoMpLjuBExjiDFIEaC28b6lU,734344
110
110
  src/frontends/live_api_react/frontend/package.json,sha256=OBOzzDiDiESPzmbLDlZ6KM1Trit71vXdP692dI-g9Uo,1381
111
111
  src/frontends/live_api_react/frontend/tsconfig.json,sha256=cyqEhf7-Yydz-PX8_cuF8JpsyC363NDTNkrmCk0sKAo,595
112
112
  src/frontends/live_api_react/frontend/public/favicon.ico,sha256=FY9oTN01RzaJ2lZ1rCjNXsEfT1gWZJA3fPx0QMBlMCU,15086
@@ -114,7 +114,7 @@ src/frontends/live_api_react/frontend/public/index.html,sha256=tOhOQOx5kMi9WhxT-
114
114
  src/frontends/live_api_react/frontend/public/robots.txt,sha256=kNJLw79pisHhc3OVAimMzKcq3x9WT6sF9IS4xI0crdI,67
115
115
  src/frontends/live_api_react/frontend/src/App.scss,sha256=477MjERLsjhhzSS5WvROHfgdLi41F0PeW7zFTIROlH4,3472
116
116
  src/frontends/live_api_react/frontend/src/App.test.tsx,sha256=l4bj_dLHDggvlcxZZgbhXdR9oIpdCwrGglRWtSqNqUU,869
117
- src/frontends/live_api_react/frontend/src/App.tsx,sha256=5PhZTXo4gwWRvkF5dJTwu4YpWKs43bsLSl1IGXx1edY,7261
117
+ src/frontends/live_api_react/frontend/src/App.tsx,sha256=ZPGBW_hieBDLmGO4_d3DWPAin8SU1QNy4G-YkZhY6sw,7388
118
118
  src/frontends/live_api_react/frontend/src/index.css,sha256=THy1DxvcOTW4WypzWvYEL_SVAVzda1iPEQ0M6pvgNUo,950
119
119
  src/frontends/live_api_react/frontend/src/index.tsx,sha256=c3VCNMXzTZInNqpHaQUMPPwZsicO468Ujc5u3jLGLZ8,1150
120
120
  src/frontends/live_api_react/frontend/src/multimodal-live-types.ts,sha256=J52j9vfza9EyODprh9w29psdBSEygTnXZF8yJIsfsDs,6037
@@ -138,7 +138,7 @@ src/frontends/live_api_react/frontend/src/hooks/use-webcam.ts,sha256=NuTM7meIwaS
138
138
  src/frontends/live_api_react/frontend/src/utils/audio-recorder.ts,sha256=JcO69YeM7boSf1gM5VVX6cbLvGRT-dYYJjWUVBJFWbM,3699
139
139
  src/frontends/live_api_react/frontend/src/utils/audio-streamer.ts,sha256=xgtnrm_jbmKzwUkeCQiv3C7jmU7DfdaJU2su6NLpXCk,8301
140
140
  src/frontends/live_api_react/frontend/src/utils/audioworklet-registry.ts,sha256=2I1va0WszQ3-SHfSmgp5-ToOSof5H6q-rgFnlf8mGUI,1258
141
- src/frontends/live_api_react/frontend/src/utils/multimodal-live-client.ts,sha256=afOZaVZdPrTFTvZj3m1I463pBqfyd9CI6wvctieoG90,9771
141
+ src/frontends/live_api_react/frontend/src/utils/multimodal-live-client.ts,sha256=u9gVQCXtSlylnDEd9GsQ1CkCTc_1kLeZD1WdgzcGzqc,9946
142
142
  src/frontends/live_api_react/frontend/src/utils/store-logger.ts,sha256=YxS0TjiGntFPIrHVVU14WplpITzzxP2faTeAVOMvbQA,1761
143
143
  src/frontends/live_api_react/frontend/src/utils/utils.ts,sha256=qQIhLzfyCBLecU0ksQCKIbD3cIflb0hxt0SPZGdYFEo,2457
144
144
  src/frontends/live_api_react/frontend/src/utils/worklets/audio-processing.ts,sha256=ULgnXphZUfbHkRhGoPT_670WHjzaXJwWgYU0ISQRSXI,1979
@@ -158,22 +158,20 @@ src/resources/docs/adk-cheatsheet.md,sha256=nEPBJKX315NzEF0NZonvqztqYZv7iIn7k7R9
158
158
  src/resources/idx/idx-template.json,sha256=07OQZCPp45Iqor2O7Tm1e1Gmsdd-AmmUofSvA7y-oRs,793
159
159
  src/resources/idx/idx-template.nix,sha256=sesHGev_PYtVDg0J5tHkg0OO7IR1Bz2iAtl_if3Ar3M,892
160
160
  src/resources/idx/.idx/dev.nix,sha256=XQ4T1xt5I-8SVwnI37v56RFFlxa58Ko-a9G2-oelYAI,1602
161
- src/resources/locks/uv-adk_base-agent_engine.lock,sha256=XRegoR8TO1MDfCWQzjoBK9CuaC8wdUCs6cWet6c1J40,486277
162
- src/resources/locks/uv-adk_base-cloud_run.lock,sha256=RowuQWgvz2W-sMG1hSp1QCswn2POYmGKCAln_aY2tpI,640556
163
- src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock,sha256=XRegoR8TO1MDfCWQzjoBK9CuaC8wdUCs6cWet6c1J40,486277
164
- src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock,sha256=RowuQWgvz2W-sMG1hSp1QCswn2POYmGKCAln_aY2tpI,640556
165
- src/resources/locks/uv-agentic_rag-agent_engine.lock,sha256=grapMSoXHRsI9HFBz2M1XQ5eicwNvd1vf1ay2oaj_-o,544169
166
- src/resources/locks/uv-agentic_rag-cloud_run.lock,sha256=rhRWMB1SXniMFjT0p0yBrVskyDvZDxjWEtHlGJji0vs,718129
167
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock,sha256=mmZGeSNBAG3QJEeHbFFaXGh4vvhs2NNCce3kx-E55Lo,814252
168
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock,sha256=xX1Wh5CfY0T_m5DNUrQjB9NlU4M9pOw08Vost0iWGB0,1071769
169
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock,sha256=pItAia1C5B6aKU7eewW7ktqnLx60qK49g7CJOA08HEM,694504
170
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock,sha256=3LUeFAOXbNpLZBdxSBY21DxXUDLkIBIJAFV2GyO6w18,918987
171
- src/resources/locks/uv-live_api-cloud_run.lock,sha256=xOPEAiyHooNT2nMP1wbnJ2ekODdI5H0lM8h_byau1Xg,839570
161
+ src/resources/locks/uv-adk_base-agent_engine.lock,sha256=FgXP88OzdexXt3jNqKbvDY_VG1BAY7u6ZyiraYf9-sA,486366
162
+ src/resources/locks/uv-adk_base-cloud_run.lock,sha256=sdEGVQiDKgADi8EUkXpOYH6GTOzWhNGcr9M6b92Gn7A,641473
163
+ src/resources/locks/uv-agentic_rag-agent_engine.lock,sha256=kDZMz25UZEQKnCajutUKLf1s8jKSAqb0NmcOOP-mUaw,544707
164
+ src/resources/locks/uv-agentic_rag-cloud_run.lock,sha256=Faiov78Du4un0CSh4OnFys0Q-wl2VckgV-_zoVt_niI,719763
165
+ src/resources/locks/uv-crewai_coding_crew-agent_engine.lock,sha256=UI2cw-Lav3hZWeH5kumhlXzb6gJzpftxZxkd2hufbHs,813131
166
+ src/resources/locks/uv-crewai_coding_crew-cloud_run.lock,sha256=MfqIFeE_ZzjhOEeLTjY1i29r2KdALtFr3M8jfkWDZkg,1067371
167
+ src/resources/locks/uv-langgraph_base_react-agent_engine.lock,sha256=DiqTTPk5M83BlSRiPdx34wgvyRilC_CygLHH8fQ27ws,693379
168
+ src/resources/locks/uv-langgraph_base_react-cloud_run.lock,sha256=Oy7HVtZWBKJnBI6GerofAy2rwSeoC8h3K44fPrBFqng,914585
169
+ src/resources/locks/uv-live_api-cloud_run.lock,sha256=AMgJt_aeoXU3LDvZv4iph9XCVsihdHqp9XzXwcNyl3k,835168
172
170
  src/utils/generate_locks.py,sha256=6V1B8V2BEuevWnXUsxZVTrLjXwFRII8UfsIGrQqZxVs,4320
173
171
  src/utils/lock_utils.py,sha256=IFOMUWtb-ypm2Y8w8J5y2oI_-MaPuwPF_JOAAlnNudA,2275
174
172
  src/utils/watch_and_rebuild.py,sha256=vP4yIiA7E_lj5sfQdJUl8TXas6V7msDg8XWUutAC05Q,6679
175
- agent_starter_pack-0.12.0.dist-info/METADATA,sha256=_wYWKxzNhGHoEwGHpMYMz25PlhYkdl6Y1ua9mO_-IFE,11102
176
- agent_starter_pack-0.12.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
177
- agent_starter_pack-0.12.0.dist-info/entry_points.txt,sha256=U7uCxR7YulIhZ0L8R8Hui0Bsy6J7oyESBeDYJYMrQjA,56
178
- agent_starter_pack-0.12.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
179
- agent_starter_pack-0.12.0.dist-info/RECORD,,
173
+ agent_starter_pack-0.13.0.dist-info/METADATA,sha256=ppWiEr8G2BZkql1PwhCJ3KAmfeI256SngwrYlpyGySg,11155
174
+ agent_starter_pack-0.13.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
175
+ agent_starter_pack-0.13.0.dist-info/entry_points.txt,sha256=U7uCxR7YulIhZ0L8R8Hui0Bsy6J7oyESBeDYJYMrQjA,56
176
+ agent_starter_pack-0.13.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
177
+ agent_starter_pack-0.13.0.dist-info/RECORD,,
@@ -4,7 +4,7 @@ install:
4
4
  {%- if cookiecutter.settings.get("commands", {}).get("override", {}).get("install") %}
5
5
  {{cookiecutter.settings.get("commands", {}).get("override", {}).get("install")}}
6
6
  {%- else %}
7
- uv sync --dev{% if cookiecutter.agent_name != 'live_api' and "adk" not in cookiecutter.tags %} --extra streamlit{%- endif %} --extra jupyter{% if cookiecutter.agent_name == 'live_api' %} && (cd frontend && npm install){%- endif %}
7
+ uv sync --dev{% if cookiecutter.agent_name != 'live_api' and "adk" not in cookiecutter.tags %} --extra streamlit{%- endif %}{% if cookiecutter.agent_name == 'live_api' %} && (cd frontend && npm install){%- endif %}
8
8
  {%- endif %}
9
9
 
10
10
  {%- if cookiecutter.settings.get("commands", {}).get("extra", {}) %}
@@ -23,14 +23,23 @@ install:
23
23
  {%- endif %}
24
24
  {%- endfor %}{%- endif %}
25
25
 
26
+ {%- if cookiecutter.agent_name == 'live_api' %}
27
+ # Build the frontend for production
28
+ build-frontend:
29
+ (cd frontend && npm run build)
30
+
31
+ {%- endif %}
26
32
  # Launch local dev playground
27
- playground:
33
+ playground:{%- if cookiecutter.agent_name == 'live_api' %} build-frontend{%- endif %}
28
34
  {%- if cookiecutter.settings.get("commands", {}).get("override", {}).get("playground") %}
29
35
  {{cookiecutter.settings.get("commands", {}).get("override", {}).get("playground")}}
30
36
  {%- else %}
31
37
  @echo "==============================================================================="
32
38
  @echo "| 🚀 Starting your agent playground... |"
33
39
  @echo "| |"
40
+ {%- if cookiecutter.agent_name == 'live_api' %}
41
+ @echo "| 🌐 Access your app at: http://localhost:8000 |"
42
+ {%- endif %}
34
43
  @echo "| 💡 Try asking: {{cookiecutter.example_question}}|"
35
44
  {%- if "adk" in cookiecutter.tags %}
36
45
  @echo "| |"
@@ -41,11 +50,13 @@ playground:
41
50
  uv run adk web . --port 8501
42
51
  {%- else %}
43
52
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
44
- uv run uvicorn {{cookiecutter.agent_directory}}.server:app --host 0.0.0.0 --port 8000 --reload &
45
- {%- endif %}
46
53
  {%- if cookiecutter.agent_name == 'live_api' %}
47
- (cd frontend && PORT=8501 npm start)
54
+ uv run uvicorn {{cookiecutter.agent_directory}}.server:app --host 0.0.0.0 --port 8000 --reload
48
55
  {%- else %}
56
+ uv run uvicorn {{cookiecutter.agent_directory}}.server:app --host 0.0.0.0 --port 8000 --reload &
57
+ {%- endif %}
58
+ {%- endif %}
59
+ {%- if cookiecutter.agent_name != 'live_api' %}
49
60
  {% if cookiecutter.deployment_target == 'agent_engine' %}PYTHONPATH=. {% endif %}uv run streamlit run frontend/streamlit_app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false
50
61
  {%- endif %}
51
62
  {%- endif %}
@@ -84,7 +95,7 @@ local-backend:
84
95
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
85
96
  {%- if cookiecutter.agent_name == 'live_api' %}
86
97
 
87
- # Start the frontend UI for development
98
+ # Start the frontend UI separately for development (requires backend running separately)
88
99
  ui:
89
100
  (cd frontend && PORT=8501 npm start)
90
101
  {%- endif %}
@@ -122,6 +133,7 @@ test:
122
133
 
123
134
  # Run code quality checks (codespell, ruff, mypy)
124
135
  lint:
136
+ uv sync --dev --extra lint
125
137
  uv run codespell
126
138
  uv run ruff check . --diff
127
139
  uv run ruff format . --check --diff
@@ -92,12 +92,12 @@ Here’s the recommended workflow for local development:
92
92
  make install
93
93
  ```
94
94
 
95
- 2. **Start the Backend Server:**
96
- Open a terminal and run:
95
+ 2. **Start the Full Stack Server:**
96
+ The FastAPI server now serves both the backend API and frontend interface:
97
97
  ```bash
98
98
  make local-backend
99
99
  ```
100
- The backend is ready when you see `INFO: Application startup complete.` Wait for this message before starting the frontend.
100
+ The server is ready when you see `INFO: Application startup complete.` The frontend will be available at `http://localhost:8000`.
101
101
 
102
102
  <details>
103
103
  <summary><b>Optional: Use AI Studio / API Key instead of Vertex AI</b></summary>
@@ -113,47 +113,23 @@ Here’s the recommended workflow for local development:
113
113
  </details>
114
114
  <br>
115
115
 
116
- 3. **Start the Frontend UI:**
117
- Open *another* terminal and run:
116
+ <details>
117
+ <summary><b>Alternative: Run Frontend Separately</b></summary>
118
+
119
+ If you prefer to run the frontend separately (useful for frontend development), you can still use:
118
120
  ```bash
119
121
  make ui
120
122
  ```
121
- This launches the Streamlit application, which connects to the backend server (by default at `http://localhost:8000`).
123
+ This launches the Streamlit application, which connects to the backend server at `http://localhost:8000`.
124
+ </details>
125
+ <br>
122
126
 
123
- 4. **Interact and Iterate:**
124
- * Open the Streamlit UI in your browser (usually `http://localhost:8501` or `http://localhost:3001`).
127
+ 3. **Interact and Iterate:**
128
+ * Open your browser and navigate to `http://localhost:8000` to access the integrated frontend.
125
129
  * Click the play button in the UI to connect to the backend.
126
130
  * Interact with the agent! Try prompts like: *"Using the tool you have, define Governance in the context MLOPs"*
127
131
  * Modify the agent logic in `{{cookiecutter.agent_directory}}/agent.py`. The backend server (FastAPI with `uvicorn --reload`) should automatically restart when you save changes. Refresh the frontend if needed to see behavioral changes.
128
132
 
129
- <details>
130
- <summary><b>Cloud Shell Usage</b></summary>
131
-
132
- To run the agent using Google Cloud Shell:
133
-
134
- 1. **Start the Frontend:**
135
- In a Cloud Shell tab, run:
136
- ```bash
137
- make ui
138
- ```
139
- Accept prompts to use a different port if 3000 is busy. Click the `localhost:PORT` link for the web preview.
140
-
141
- 2. **Start the Backend:**
142
- Open a *new* Cloud Shell tab. Set your project: `gcloud config set project [PROJECT_ID]`. Then run:
143
- ```bash
144
- make local-backend
145
- ```
146
-
147
- 3. **Configure Backend Web Preview:**
148
- Use the Cloud Shell Web Preview feature to expose port 8000. Change the default port from 8080 to 8000. See [Cloud Shell Web Preview documentation](https://cloud.google.com/shell/docs/using-web-preview#preview_the_application).
149
-
150
- 4. **Connect Frontend to Backend:**
151
- * Copy the URL generated by the backend web preview (e.g., `https://8000-cs-....cloudshell.dev/`).
152
- * Paste this URL into the "Server URL" field in the frontend UI settings (in the first tab).
153
- * Click the "Play button" to connect.
154
-
155
- * **Note:** The feedback feature in the frontend might not work reliably in Cloud Shell due to cross-origin issues between the preview URLs.
156
- </details>
157
133
 
158
134
  </details>
159
135
  {%- else %}
@@ -183,18 +159,7 @@ gcloud config set project <your-dev-project-id>
183
159
  make backend
184
160
  ```
185
161
  {% if cookiecutter.agent_name == 'live_api' %}
186
- **Accessing the Deployed Backend Locally:**
187
-
188
- To connect your local frontend (`make ui`) to the backend deployed on Cloud Run, use the `gcloud` proxy:
189
-
190
- 1. **Start the proxy:**
191
- ```bash
192
- # Replace with your actual service name, project, and region
193
- gcloud run services proxy gemini-agent-service --port 8000 --project $PROJECT_ID --region $REGION
194
- ```
195
- Keep this terminal running.
196
-
197
- 2. **Connect Frontend:** Your deployed backend is now accessible locally at `http://localhost:8000`. Point your Streamlit UI to this address.
162
+ **Note:** For secure access to your deployed backend, consider using Identity-Aware Proxy (IAP) by running `make backend IAP=true`.
198
163
  {%- endif %}
199
164
 
200
165
  The repository includes a Terraform configuration for the setup of the Dev Google Cloud project.
@@ -19,7 +19,6 @@ import pathlib
19
19
  import shutil
20
20
  import subprocess
21
21
  import tempfile
22
- import tomllib
23
22
  from collections.abc import Callable
24
23
 
25
24
  import click
@@ -244,6 +243,8 @@ def create(
244
243
  ) -> None:
245
244
  """Create GCP-based AI agent projects from templates."""
246
245
  try:
246
+ console = Console()
247
+
247
248
  # Display welcome banner (unless skipped)
248
249
  if not skip_welcome:
249
250
  display_welcome_banner(agent)
@@ -307,6 +308,7 @@ def create(
307
308
  selected_agent = None
308
309
  template_source_path = None
309
310
  temp_dir_to_clean = None
311
+ remote_spec = None
310
312
 
311
313
  if agent:
312
314
  if agent.startswith("local@"):
@@ -348,6 +350,20 @@ def create(
348
350
  )
349
351
  temp_dir_to_clean = str(temp_dir_path)
350
352
  selected_agent = f"remote_{hash(agent)}" # Generate unique name for remote template
353
+
354
+ # Show informational message for ADK samples with smart defaults
355
+ if remote_spec.is_adk_samples:
356
+ config = load_remote_template_config(
357
+ template_source_path, is_adk_sample=True
358
+ )
359
+ if not config.get("has_explicit_config", True):
360
+ console = Console()
361
+ console.print(
362
+ "\n[blue]ℹ️ Note: The starter pack uses heuristics to template this ADK sample agent.[/]"
363
+ )
364
+ console.print(
365
+ "[dim] The starter pack attempts to create a working codebase, but you'll need to follow the generated README for complete setup.[/]"
366
+ )
351
367
  else:
352
368
  # Handle local agent selection
353
369
  agents = get_available_agents()
@@ -397,6 +413,20 @@ def create(
397
413
  temp_dir_to_clean = str(temp_dir_path)
398
414
  final_agent = f"remote_{hash(agent)}" # Generate unique name for remote template
399
415
 
416
+ # Show informational message for ADK samples with smart defaults
417
+ if remote_spec.is_adk_samples:
418
+ config = load_remote_template_config(
419
+ template_source_path, is_adk_sample=True
420
+ )
421
+ if not config.get("has_explicit_config", True):
422
+ console = Console()
423
+ console.print(
424
+ "\n[blue]ℹ️ Note: The starter pack uses heuristics to template this ADK sample agent.[/]"
425
+ )
426
+ console.print(
427
+ "[dim] The starter pack attempts to create a working codebase, but you'll need to follow the generated README for complete setup.[/]"
428
+ )
429
+
400
430
  if debug:
401
431
  logging.debug(f"Selected agent: {final_agent}")
402
432
 
@@ -409,7 +439,9 @@ def create(
409
439
 
410
440
  # Load remote template config
411
441
  source_config = load_remote_template_config(
412
- template_source_path, cli_overrides
442
+ template_source_path,
443
+ cli_overrides,
444
+ is_adk_sample=remote_spec.is_adk_samples if remote_spec else False,
413
445
  )
414
446
 
415
447
  # Remote templates now work even without pyproject.toml thanks to defaults
@@ -774,56 +806,10 @@ def display_adk_samples_selection() -> str:
774
806
  # Fetch the repository
775
807
  repo_path, _ = fetch_remote_template(spec)
776
808
 
777
- # Scan for agents in the repository
778
- adk_agents = {}
779
- agent_count = 1
809
+ # Use shared ADK discovery function
810
+ from ..utils.remote_template import discover_adk_agents
780
811
 
781
- # Search for pyproject.toml files to identify agents
782
- for config_path in sorted(repo_path.glob("**/pyproject.toml")):
783
- try:
784
- with open(config_path, "rb") as f:
785
- pyproject_data = tomllib.load(f)
786
-
787
- config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
788
-
789
- # Skip pyproject.toml files that don't have agent-starter-pack config
790
- if not config:
791
- continue
792
-
793
- template_root = config_path.parent
794
-
795
- # Use fallbacks to [project] section if needed
796
- project_info = pyproject_data.get("project", {})
797
- agent_name = (
798
- config.get("name") or project_info.get("name") or template_root.name
799
- )
800
- description = (
801
- config.get("description") or project_info.get("description") or ""
802
- )
803
-
804
- # Get the relative path from repo root
805
- relative_path = template_root.relative_to(repo_path)
806
-
807
- # For adk-samples, use just the agent name for the spec
808
- # This handles cases like python/agents/gemini-fullstack -> gemini-fullstack
809
- agent_spec_name = (
810
- relative_path.name
811
- if relative_path != relative_path.parent
812
- else str(relative_path)
813
- )
814
-
815
- adk_agents[agent_count] = {
816
- "name": agent_name,
817
- "description": description,
818
- "path": str(relative_path),
819
- "spec": f"adk@{agent_spec_name}",
820
- }
821
- agent_count += 1
822
-
823
- except Exception as e:
824
- logging.warning(
825
- f"Could not load agent from {config_path.parent.parent}: {e}"
826
- )
812
+ adk_agents = discover_adk_agents(repo_path)
827
813
 
828
814
  if not adk_agents:
829
815
  console.print("No agents found in adk-samples repository", style="yellow")
@@ -831,9 +817,19 @@ def display_adk_samples_selection() -> str:
831
817
  return display_agent_selection()
832
818
 
833
819
  console.print("\n> Available agents from [bold blue]google/adk-samples[/]:")
820
+
821
+ # Show explanation for inferred agents at the top
822
+ from ..utils.remote_template import display_adk_caveat_if_needed
823
+
824
+ display_adk_caveat_if_needed(adk_agents)
825
+
834
826
  for num, agent in adk_agents.items():
827
+ name_with_indicator = agent["name"]
828
+ if not agent.get("has_explicit_config", True):
829
+ name_with_indicator += " *"
830
+
835
831
  console.print(
836
- f"{num}. [bold]{agent['name']}[/] - [dim]{agent['description']}[/]"
832
+ f"{num}. [bold]{name_with_indicator}[/] - [dim]{agent['description']}[/]"
837
833
  )
838
834
 
839
835
  # Add option to go back to local agents
@@ -1030,18 +1026,22 @@ def _handle_credential_verification(creds_info: dict) -> dict:
1030
1026
  return creds_info
1031
1027
 
1032
1028
 
1033
- def _test_vertex_ai_connection(project_id: str, region: str) -> None:
1029
+ def _test_vertex_ai_connection(
1030
+ project_id: str, region: str, auto_approve: bool = False
1031
+ ) -> None:
1034
1032
  """Test connection to Vertex AI.
1035
1033
 
1036
1034
  Args:
1037
1035
  project_id: GCP project ID
1038
1036
  region: GCP region for deployment
1037
+ auto_approve: Whether to auto-approve API enablement
1039
1038
  """
1040
1039
  console.print("> Testing GCP and Vertex AI Connection...")
1041
1040
  try:
1042
1041
  verify_vertex_connection(
1043
1042
  project_id=project_id,
1044
1043
  location=region,
1044
+ auto_approve=auto_approve,
1045
1045
  )
1046
1046
  console.print(
1047
1047
  f"> ✓ Successfully verified connection to Vertex AI in project {project_id}"
@@ -1053,6 +1053,7 @@ def _test_vertex_ai_connection(project_id: str, region: str) -> None:
1053
1053
  f"Visit https://cloud.google.com/vertex-ai/docs/authentication for help.",
1054
1054
  style="bold red",
1055
1055
  )
1056
+ raise
1056
1057
 
1057
1058
 
1058
1059
  def replace_region_in_files(
@@ -13,12 +13,18 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import pathlib
16
+ import sys
16
17
  from typing import Any
17
18
 
18
19
  import click
19
20
  from rich.console import Console
20
21
  from rich.prompt import IntPrompt
21
22
 
23
+ if sys.version_info >= (3, 11):
24
+ import tomllib
25
+ else:
26
+ import tomli as tomllib
27
+
22
28
  from ..utils.logging import display_welcome_banner, handle_cli_error
23
29
  from ..utils.template import get_available_agents
24
30
  from .create import (
@@ -253,8 +259,6 @@ def enhance(
253
259
  pyproject_path = current_dir / "pyproject.toml"
254
260
  if pyproject_path.exists():
255
261
  try:
256
- import tomllib
257
-
258
262
  with open(pyproject_path, "rb") as f:
259
263
  pyproject_data = tomllib.load(f)
260
264
  packages = (
src/cli/commands/list.py CHANGED
@@ -14,9 +14,14 @@
14
14
 
15
15
  import logging
16
16
  import pathlib
17
- import tomllib
17
+ import sys
18
18
 
19
19
  import click
20
+
21
+ if sys.version_info >= (3, 11):
22
+ import tomllib
23
+ else:
24
+ import tomli as tomllib
20
25
  from rich.console import Console
21
26
  from rich.table import Table
22
27
 
@@ -26,7 +31,9 @@ from ..utils.template import get_available_agents
26
31
  console = Console()
27
32
 
28
33
 
29
- def display_agents_from_path(base_path: pathlib.Path, source_name: str) -> None:
34
+ def display_agents_from_path(
35
+ base_path: pathlib.Path, source_name: str, is_adk_samples: bool = False
36
+ ) -> None:
30
37
  """Scans a directory and displays available agents."""
31
38
  table = Table(
32
39
  title=f"Available agents in [bold blue]{source_name}[/]",
@@ -42,41 +49,66 @@ def display_agents_from_path(base_path: pathlib.Path, source_name: str) -> None:
42
49
  return
43
50
 
44
51
  found_agents = False
45
- # Search for pyproject.toml files to identify agents (explicit opt-in)
46
- for config_path in sorted(base_path.glob("**/pyproject.toml")):
47
- try:
48
- with open(config_path, "rb") as f:
49
- pyproject_data = tomllib.load(f)
52
+ adk_agents = {}
50
53
 
51
- config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
54
+ if is_adk_samples:
55
+ # For ADK samples, use the shared discovery function
56
+ from ..utils.remote_template import discover_adk_agents
52
57
 
53
- # Skip pyproject.toml files that don't have agent-starter-pack config
54
- if not config:
55
- continue
58
+ adk_agents = discover_adk_agents(base_path)
56
59
 
57
- template_root = config_path.parent
60
+ for agent_info in adk_agents.values():
61
+ # Add indicator for inferred agents
62
+ name_with_indicator = agent_info["name"]
63
+ if not agent_info.get("has_explicit_config", True):
64
+ name_with_indicator += " *"
58
65
 
59
- # Use fallbacks to [project] section if needed
60
- project_info = pyproject_data.get("project", {})
61
- agent_name = (
62
- config.get("name") or project_info.get("name") or template_root.name
63
- )
64
- description = (
65
- config.get("description") or project_info.get("description") or ""
66
+ table.add_row(
67
+ name_with_indicator, f"/{agent_info['path']}", agent_info["description"]
66
68
  )
69
+ found_agents = True
70
+ else:
71
+ # Original logic for non-ADK sources: Search for pyproject.toml files with explicit config
72
+ for config_path in sorted(base_path.glob("**/pyproject.toml")):
73
+ try:
74
+ with open(config_path, "rb") as f:
75
+ pyproject_data = tomllib.load(f)
67
76
 
68
- # Display the agent's path relative to the scanned directory
69
- relative_path = template_root.relative_to(base_path)
77
+ config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
70
78
 
71
- table.add_row(agent_name, f"/{relative_path}", description)
72
- found_agents = True
79
+ # Skip pyproject.toml files that don't have agent-starter-pack config
80
+ if not config:
81
+ continue
82
+
83
+ template_root = config_path.parent
84
+
85
+ # Use fallbacks to [project] section if needed
86
+ project_info = pyproject_data.get("project", {})
87
+ agent_name = (
88
+ config.get("name") or project_info.get("name") or template_root.name
89
+ )
90
+ description = (
91
+ config.get("description") or project_info.get("description") or ""
92
+ )
73
93
 
74
- except Exception as e:
75
- logging.warning(f"Could not load agent from {config_path.parent}: {e}")
94
+ # Display the agent's path relative to the scanned directory
95
+ relative_path = template_root.relative_to(base_path)
96
+
97
+ table.add_row(agent_name, f"/{relative_path}", description)
98
+ found_agents = True
99
+
100
+ except Exception as e:
101
+ logging.warning(f"Could not load agent from {config_path.parent}: {e}")
76
102
 
77
103
  if not found_agents:
78
104
  console.print(f"No agents found in {source_name}", style="yellow")
79
105
  else:
106
+ # Show explanation for inferred agents at the top (only for ADK samples)
107
+ if is_adk_samples:
108
+ from ..utils.remote_template import display_adk_caveat_if_needed
109
+
110
+ display_adk_caveat_if_needed(adk_agents)
111
+
80
112
  console.print(table)
81
113
 
82
114
 
@@ -98,7 +130,14 @@ def list_remote_agents(remote_source: str, scan_from_root: bool = False) -> None
98
130
  repo_path, template_path = template_dir_path
99
131
  scan_path = repo_path if scan_from_root else template_path
100
132
 
101
- display_agents_from_path(scan_path, remote_source)
133
+ # Check if this is ADK samples to enable inference
134
+ is_adk_samples = (
135
+ spec.is_adk_samples if hasattr(spec, "is_adk_samples") else False
136
+ )
137
+
138
+ display_agents_from_path(
139
+ scan_path, remote_source, is_adk_samples=is_adk_samples
140
+ )
102
141
 
103
142
  except (RuntimeError, FileNotFoundError) as e:
104
143
  console.print(f"Error: {e}", style="bold red")