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.
- {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/METADATA +2 -1
- {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/RECORD +27 -29
- src/base_template/Makefile +18 -6
- src/base_template/README.md +13 -48
- src/cli/commands/create.py +54 -53
- src/cli/commands/enhance.py +6 -2
- src/cli/commands/list.py +65 -26
- src/cli/utils/gcp.py +122 -1
- src/cli/utils/remote_template.py +175 -4
- src/cli/utils/template.py +72 -1
- src/deployment_targets/cloud_run/Dockerfile +16 -0
- src/deployment_targets/cloud_run/{{cookiecutter.agent_directory}}/server.py +49 -1
- src/frontends/live_api_react/frontend/package-lock.json +9 -9
- src/frontends/live_api_react/frontend/src/App.tsx +3 -2
- src/frontends/live_api_react/frontend/src/utils/multimodal-live-client.ts +3 -1
- src/resources/locks/uv-adk_base-agent_engine.lock +452 -452
- src/resources/locks/uv-adk_base-cloud_run.lock +571 -568
- src/resources/locks/uv-agentic_rag-agent_engine.lock +565 -566
- src/resources/locks/uv-agentic_rag-cloud_run.lock +716 -713
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +729 -735
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +923 -940
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock +658 -664
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock +852 -869
- src/resources/locks/uv-live_api-cloud_run.lock +758 -775
- src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +0 -3938
- src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +0 -4501
- {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.12.0.dist-info → agent_starter_pack-0.13.0.dist-info}/entry_points.txt +0 -0
- {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.
|
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=
|
42
|
-
src/base_template/README.md,sha256=
|
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=
|
76
|
-
src/cli/commands/enhance.py,sha256=
|
77
|
-
src/cli/commands/list.py,sha256=
|
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=
|
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=
|
85
|
-
src/cli/utils/template.py,sha256=
|
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=
|
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=
|
109
|
-
src/frontends/live_api_react/frontend/package-lock.json,sha256=
|
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=
|
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=
|
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=
|
162
|
-
src/resources/locks/uv-adk_base-cloud_run.lock,sha256=
|
163
|
-
src/resources/locks/uv-
|
164
|
-
src/resources/locks/uv-
|
165
|
-
src/resources/locks/uv-
|
166
|
-
src/resources/locks/uv-
|
167
|
-
src/resources/locks/uv-
|
168
|
-
src/resources/locks/uv-
|
169
|
-
src/resources/locks/uv-
|
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.
|
176
|
-
agent_starter_pack-0.
|
177
|
-
agent_starter_pack-0.
|
178
|
-
agent_starter_pack-0.
|
179
|
-
agent_starter_pack-0.
|
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,,
|
src/base_template/Makefile
CHANGED
@@ -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 %}
|
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
|
-
|
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
|
src/base_template/README.md
CHANGED
@@ -92,12 +92,12 @@ Here’s the recommended workflow for local development:
|
|
92
92
|
make install
|
93
93
|
```
|
94
94
|
|
95
|
-
2. **Start the
|
96
|
-
|
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
|
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
|
-
|
117
|
-
|
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
|
123
|
+
This launches the Streamlit application, which connects to the backend server at `http://localhost:8000`.
|
124
|
+
</details>
|
125
|
+
<br>
|
122
126
|
|
123
|
-
|
124
|
-
* Open
|
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
|
-
**
|
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.
|
src/cli/commands/create.py
CHANGED
@@ -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,
|
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
|
-
#
|
778
|
-
|
779
|
-
agent_count = 1
|
809
|
+
# Use shared ADK discovery function
|
810
|
+
from ..utils.remote_template import discover_adk_agents
|
780
811
|
|
781
|
-
|
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]{
|
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(
|
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(
|
src/cli/commands/enhance.py
CHANGED
@@ -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
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
54
|
-
if not config:
|
55
|
-
continue
|
58
|
+
adk_agents = discover_adk_agents(base_path)
|
56
59
|
|
57
|
-
|
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
|
-
|
60
|
-
|
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
|
-
|
69
|
-
relative_path = template_root.relative_to(base_path)
|
77
|
+
config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
|
70
78
|
|
71
|
-
|
72
|
-
|
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
|
-
|
75
|
-
|
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
|
-
|
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")
|