agent-starter-pack 0.9.2__py3-none-any.whl → 0.10.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 (56) hide show
  1. {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/METADATA +2 -2
  2. {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/RECORD +53 -51
  3. agents/adk_base/.template/templateconfig.yaml +1 -1
  4. agents/adk_gemini_fullstack/.template/templateconfig.yaml +1 -1
  5. agents/agentic_rag/.template/templateconfig.yaml +1 -1
  6. agents/agentic_rag/README.md +1 -1
  7. agents/live_api/tests/integration/test_server_e2e.py +7 -1
  8. llm.txt +3 -2
  9. src/base_template/Makefile +4 -3
  10. src/base_template/README.md +7 -2
  11. src/base_template/deployment/README.md +6 -121
  12. src/base_template/deployment/terraform/github.tf +284 -0
  13. src/base_template/deployment/terraform/providers.tf +5 -0
  14. src/base_template/deployment/terraform/variables.tf +40 -1
  15. src/base_template/deployment/terraform/vars/env.tfvars +7 -1
  16. src/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %} +43 -0
  17. src/base_template/deployment/terraform/{build_triggers.tf → {% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} } +33 -18
  18. src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +114 -0
  19. src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml +65 -0
  20. src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +170 -0
  21. src/base_template/{deployment/cd/deploy-to-prod.yaml → {% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml } +7 -7
  22. src/base_template/{deployment/cd/staging.yaml → {% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml } +7 -7
  23. src/cli/commands/create.py +120 -4
  24. src/cli/commands/list.py +1 -1
  25. src/cli/commands/setup_cicd.py +292 -298
  26. src/cli/utils/cicd.py +19 -7
  27. src/cli/utils/remote_template.py +4 -4
  28. src/cli/utils/template.py +67 -19
  29. src/deployment_targets/cloud_run/app/server.py +19 -0
  30. src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +4 -3
  31. src/deployment_targets/cloud_run/deployment/terraform/service.tf +4 -3
  32. src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +35 -0
  33. src/deployment_targets/cloud_run/tests/load_test/README.md +1 -1
  34. src/frontends/live_api_react/frontend/package-lock.json +19 -16
  35. src/frontends/streamlit/frontend/side_bar.py +1 -1
  36. src/frontends/streamlit/frontend/utils/chat_utils.py +1 -1
  37. src/frontends/streamlit/frontend/utils/local_chat_history.py +2 -2
  38. src/resources/docs/adk-cheatsheet.md +1 -1
  39. src/resources/locks/uv-adk_base-agent_engine.lock +164 -131
  40. src/resources/locks/uv-adk_base-cloud_run.lock +177 -144
  41. src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +164 -131
  42. src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +177 -144
  43. src/resources/locks/uv-agentic_rag-agent_engine.lock +223 -190
  44. src/resources/locks/uv-agentic_rag-cloud_run.lock +251 -218
  45. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +315 -485
  46. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +358 -531
  47. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +281 -249
  48. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +323 -290
  49. src/resources/locks/uv-live_api-cloud_run.lock +350 -327
  50. src/resources/setup_cicd/cicd_variables.tf +0 -41
  51. src/resources/setup_cicd/github.tf +0 -87
  52. src/resources/setup_cicd/providers.tf +0 -39
  53. {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/WHEEL +0 -0
  54. {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/entry_points.txt +0 -0
  55. {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/licenses/LICENSE +0 -0
  56. /src/base_template/{deployment/ci → {% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}}/pr_checks.yaml +0 -0
@@ -0,0 +1,65 @@
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
+ name: PR Checks
16
+
17
+ on:
18
+ pull_request:
19
+ branches:
20
+ - main
21
+ paths:
22
+ - 'app/**'
23
+ - 'data_ingestion/**'
24
+ - 'tests/**'
25
+ - 'deployment/**'
26
+ - 'uv.lock'
27
+ {%- if cookiecutter.data_ingestion %}
28
+ - 'data_ingestion/**'
29
+ {%- endif %}
30
+
31
+ jobs:
32
+ test:
33
+ runs-on: ubuntu-latest
34
+ permissions:
35
+ contents: 'read'
36
+ id-token: 'write'
37
+ steps:
38
+ - name: Checkout code
39
+ uses: actions/checkout@v4
40
+
41
+ - id: 'auth'
42
+ name: 'Authenticate to Google Cloud'
43
+ uses: 'google-github-actions/auth@v2'
44
+ with:
45
+ workload_identity_provider: 'projects/{% raw %}${{ vars.GCP_PROJECT_NUMBER }}{% endraw %}/locations/global/workloadIdentityPools/{% raw %}${{ secrets.WIF_POOL_ID }}{% endraw %}/providers/{% raw %}${{ secrets.WIF_PROVIDER_ID }}{% endraw %}'
46
+ service_account: '{% raw %}${{ secrets.GCP_SERVICE_ACCOUNT }}{% endraw %}'
47
+ create_credentials_file: true
48
+ project_id: {% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}
49
+
50
+
51
+ - name: Set up Python 3.11
52
+ uses: actions/setup-python@v4
53
+ with:
54
+ python-version: '3.11'
55
+
56
+ - name: Install uv and dependencies
57
+ run: |
58
+ pip install uv==0.6.12
59
+ uv sync --locked
60
+
61
+ - name: Run unit tests
62
+ run: uv run pytest tests/unit
63
+
64
+ - name: Run integration tests
65
+ run: uv run pytest tests/integration
@@ -0,0 +1,170 @@
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
+ name: Deploy to Staging
16
+
17
+ on:
18
+ push:
19
+ branches:
20
+ - main
21
+ paths:
22
+ - 'app/**'
23
+ - 'data_ingestion/**'
24
+ - 'tests/**'
25
+ - 'deployment/**'
26
+ - 'uv.lock'
27
+
28
+ jobs:
29
+ deploy_and_test_staging:
30
+ runs-on: ubuntu-latest
31
+ permissions:
32
+ contents: 'read'
33
+ id-token: 'write'
34
+
35
+ steps:
36
+ - name: Checkout code
37
+ uses: actions/checkout@v4
38
+
39
+ - name: Set up Python 3.11
40
+ uses: actions/setup-python@v4
41
+ with:
42
+ python-version: '3.11'
43
+
44
+ - id: 'auth'
45
+ name: 'Authenticate to Google Cloud'
46
+ uses: 'google-github-actions/auth@v2'
47
+ with:
48
+ workload_identity_provider: 'projects/{% raw %}${{ vars.GCP_PROJECT_NUMBER }}{% endraw %}/locations/global/workloadIdentityPools/{% raw %}${{ secrets.WIF_POOL_ID }}{% endraw %}/providers/{% raw %}${{ secrets.WIF_PROVIDER_ID }}{% endraw %}'
49
+ service_account: '{% raw %}${{ secrets.GCP_SERVICE_ACCOUNT }}{% endraw %}'
50
+ create_credentials_file: true
51
+ project_id: {% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}
52
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
53
+
54
+ - name: Set up Cloud SDK
55
+ uses: 'google-github-actions/setup-gcloud@v2'
56
+ {%- endif %}
57
+ {%- if cookiecutter.data_ingestion %}
58
+
59
+ - name: Deploy data ingestion pipeline (Staging)
60
+ run: |
61
+ cd data_ingestion && pip install uv==0.6.12 && cd data_ingestion_pipeline && \
62
+ uv sync --locked && uv run python submit_pipeline.py
63
+ env:
64
+ PIPELINE_ROOT: {% raw %}${{ vars.PIPELINE_GCS_ROOT_STAGING }}{% endraw %}
65
+ REGION: {% raw %}${{ vars.REGION }}{% endraw %}
66
+ {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
67
+ DATA_STORE_REGION: {% raw %}${{ vars.DATA_STORE_REGION }}{% endraw %}
68
+ DATA_STORE_ID: {% raw %}${{ vars.DATA_STORE_ID_STAGING }}{% endraw %}
69
+ {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
70
+ VECTOR_SEARCH_INDEX: {% raw %}${{ vars.VECTOR_SEARCH_INDEX_STAGING }}{% endraw %}
71
+ VECTOR_SEARCH_INDEX_ENDPOINT: {% raw %}${{ vars.VECTOR_SEARCH_INDEX_ENDPOINT_STAGING }}{% endraw %}
72
+ VECTOR_SEARCH_BUCKET: {% raw %}${{ vars.VECTOR_SEARCH_BUCKET_STAGING }}{% endraw %}
73
+ {%- endif %}
74
+ PROJECT_ID: {% raw %}${{ vars.STAGING_PROJECT_ID }}{% endraw %}
75
+ SERVICE_ACCOUNT: {% raw %}${{ vars.PIPELINE_SA_EMAIL_STAGING }}{% endraw %}
76
+ PIPELINE_NAME: {% raw %}${{ vars.PIPELINE_NAME }}{% endraw %}
77
+ {%- endif %}
78
+
79
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
80
+
81
+ - name: Configure Docker for Artifact Registry
82
+ run: |
83
+ gcloud auth configure-docker {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev --quiet
84
+
85
+ - name: Build and Push Docker Image
86
+ run: |
87
+ docker build -t {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev/{% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}/{% raw %}${{ vars.ARTIFACT_REGISTRY_REPO_NAME }}{% endraw %}/{% raw %}${{ vars.CONTAINER_NAME }}{% endraw %} \
88
+ --build-arg COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %} .
89
+ docker push {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev/{% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}/{% raw %}${{ vars.ARTIFACT_REGISTRY_REPO_NAME }}{% endraw %}/{% raw %}${{ vars.CONTAINER_NAME }}{% endraw %}
90
+
91
+ - name: Deploy to Staging (Cloud Run)
92
+ run: |
93
+ gcloud run deploy {{cookiecutter.project_name}} \
94
+ --image {% raw %}${{ vars.REGION }}{% endraw %}-docker.pkg.dev/{% raw %}${{ vars.CICD_PROJECT_ID }}{% endraw %}/{% raw %}${{ vars.ARTIFACT_REGISTRY_REPO_NAME }}{% endraw %}/{% raw %}${{ vars.CONTAINER_NAME }}{% endraw %} \
95
+ --region {% raw %}${{ vars.REGION }}{% endraw %} \
96
+ --project {% raw %}${{ vars.STAGING_PROJECT_ID }}{% endraw %}
97
+
98
+ - name: Fetch Staging Service URL
99
+ id: fetch-url
100
+ run: |
101
+ _STAGING_URL=$(gcloud run services describe {{cookiecutter.project_name}} \
102
+ --region {% raw %}${{ vars.REGION }}{% endraw %} --project {% raw %}${{ vars.STAGING_PROJECT_ID }}{% endraw %} --format="value(status.url)")
103
+ echo "_staging_url=${_STAGING_URL}" >> $GITHUB_OUTPUT
104
+
105
+ - name: Fetch ID Token
106
+ id: fetch-token
107
+ run: |
108
+ _ID_TOKEN=$(gcloud auth print-identity-token --impersonate-service-account={% raw %}${{ secrets.GCP_SERVICE_ACCOUNT }}{% endraw %} -q)
109
+ echo "::add-mask::${_ID_TOKEN}"
110
+ echo "_id_token=${_ID_TOKEN}" >> $GITHUB_OUTPUT
111
+
112
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
113
+
114
+ - name: Install uv and dependencies
115
+ run: |
116
+ pip install uv==0.6.12
117
+ uv sync --locked
118
+
119
+ - name: Deploy to Staging (Agent Engine)
120
+ run: |
121
+ uv export --no-hashes --no-sources --no-header --no-dev --no-emit-project --no-annotate --locked > .requirements.txt
122
+ uv run app/agent_engine_app.py \
123
+ --project {% raw %}${{ vars.STAGING_PROJECT_ID }}{% endraw %} \
124
+ --location {% raw %}${{ vars.REGION }}{% endraw %} \
125
+ --set-env-vars="COMMIT_SHA={% raw %}${{ github.sha }}{% endraw %}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID={% raw %}${{ vars.DATA_STORE_ID_STAGING }}{% endraw %},DATA_STORE_REGION={% raw %}${{ vars.DATA_STORE_REGION }}{% endraw %}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX={% raw %}${{ vars.VECTOR_SEARCH_INDEX_STAGING }}{% endraw %},VECTOR_SEARCH_INDEX_ENDPOINT={% raw %}${{ vars.VECTOR_SEARCH_INDEX_ENDPOINT_STAGING }}{% endraw %},VECTOR_SEARCH_BUCKET={% raw %}${{ vars.VECTOR_SEARCH_BUCKET_STAGING }}{% endraw %}{%- endif %}{%- endif %}"
126
+
127
+ - name: Fetch Auth Token
128
+ id: fetch-token
129
+ run: |
130
+ _AUTH_TOKEN=$(gcloud auth print-access-token -q)
131
+ echo "::add-mask::${_AUTH_TOKEN}"
132
+ echo "_auth_token=${_AUTH_TOKEN}" >> $GITHUB_OUTPUT
133
+ {%- endif %}
134
+
135
+ - name: Run load test
136
+ run: |
137
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
138
+ export _ID_TOKEN="{% raw %}${{ steps.fetch-token.outputs._id_token }}{% endraw %}"
139
+ export _STAGING_URL="{% raw %}${{ steps.fetch-url.outputs._staging_url }}{% endraw %}"
140
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
141
+ export _AUTH_TOKEN="{% raw %}${{ steps.fetch-token.outputs._auth_token }}{% endraw %}"
142
+ {%- endif %}
143
+ pip install locust==2.31.1
144
+ locust -f tests/load_test/load_test.py \
145
+ --headless \
146
+ {%- if cookiecutter.deployment_target == 'cloud_run' %}
147
+ -H ${_STAGING_URL} \
148
+ -t 30s -u 10 -r 0.5 \
149
+ {%- elif cookiecutter.deployment_target == 'agent_engine' %}
150
+ -t 30s -u 2 -r 0.5 \
151
+ {%- endif %}
152
+ --csv=tests/load_test/.results/results \
153
+ --html=tests/load_test/.results/report.html
154
+
155
+ - name: Export Load Test Results to GCS
156
+ run: |
157
+ TIMESTAMP=$(date +%Y%m%d-%H%M%S)
158
+ gcloud storage cp --recursive tests/load_test/.results gs://{% raw %}${{ vars.BUCKET_NAME_LOAD_TEST_RESULTS }}{% endraw %}/results-${TIMESTAMP} --quiet
159
+ echo "_________________________________________________________________________"
160
+ echo "Load test results copied to gs://{% raw %}${{ vars.BUCKET_NAME_LOAD_TEST_RESULTS }}{% endraw %}/results-${TIMESTAMP}"
161
+ echo "HTTP link: https://console.cloud.google.com/storage/browser/{% raw %}${{ vars.BUCKET_NAME_LOAD_TEST_RESULTS }}{% endraw %}/results-${TIMESTAMP}"
162
+ echo "_________________________________________________________________________"
163
+
164
+ call_production_workflow:
165
+ needs: deploy_and_test_staging
166
+ uses: ./.github/workflows/deploy-to-prod.yaml
167
+ permissions:
168
+ contents: 'read'
169
+ id-token: 'write'
170
+ secrets: inherit
@@ -23,18 +23,18 @@ steps:
23
23
  cd data_ingestion && pip install uv==0.6.12 --user && cd data_ingestion_pipeline && \
24
24
  uv sync --locked && uv run python submit_pipeline.py
25
25
  env:
26
- - "PIPELINE_ROOT=${_PIPELINE_GCS_ROOT}"
26
+ - "PIPELINE_ROOT=${_PIPELINE_GCS_ROOT_PROD}"
27
27
  - "REGION=${_REGION}"
28
28
  {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
29
29
  - "DATA_STORE_REGION=${_DATA_STORE_REGION}"
30
- - "DATA_STORE_ID=${_DATA_STORE_ID}"
30
+ - "DATA_STORE_ID=${_DATA_STORE_ID_PROD}"
31
31
  {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
32
- - "VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX}"
33
- - "VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT}"
34
- - "VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET}"
32
+ - "VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX_PROD}"
33
+ - "VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT_PROD}"
34
+ - "VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET_PROD}"
35
35
  {%- endif %}
36
36
  - "PROJECT_ID=${_PROD_PROJECT_ID}"
37
- - "SERVICE_ACCOUNT=${_PIPELINE_SA_EMAIL}"
37
+ - "SERVICE_ACCOUNT=${_PIPELINE_SA_EMAIL_PROD}"
38
38
  - "PIPELINE_NAME=${_PIPELINE_NAME}"
39
39
  - "CRON_SCHEDULE=${_PIPELINE_CRON_SCHEDULE}"
40
40
  - "DISABLE_CACHING=TRUE"
@@ -77,7 +77,7 @@ steps:
77
77
  uv run app/agent_engine_app.py \
78
78
  --project ${_PROD_PROJECT_ID} \
79
79
  --location ${_REGION} \
80
- --set-env-vars="COMMIT_SHA=${COMMIT_SHA}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID=${_DATA_STORE_ID},DATA_STORE_REGION=${_DATA_STORE_REGION}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX},VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT},VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET}{%- endif %}{%- endif %}"
80
+ --set-env-vars="COMMIT_SHA=${COMMIT_SHA}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID=${_DATA_STORE_ID_PROD},DATA_STORE_REGION=${_DATA_STORE_REGION}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX_PROD},VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT_PROD},VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET_PROD}{%- endif %}{%- endif %}"
81
81
  env:
82
82
  - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin'
83
83
  {%- endif %}
@@ -23,18 +23,18 @@ steps:
23
23
  cd data_ingestion && pip install uv==0.6.12 --user && cd data_ingestion_pipeline && \
24
24
  uv sync --locked && uv run python submit_pipeline.py
25
25
  env:
26
- - "PIPELINE_ROOT=${_PIPELINE_GCS_ROOT}"
26
+ - "PIPELINE_ROOT=${_PIPELINE_GCS_ROOT_STAGING}"
27
27
  - "REGION=${_REGION}"
28
28
  {%- if cookiecutter.datastore_type == "vertex_ai_search" %}
29
29
  - "DATA_STORE_REGION=${_DATA_STORE_REGION}"
30
- - "DATA_STORE_ID=${_DATA_STORE_ID}"
30
+ - "DATA_STORE_ID=${_DATA_STORE_ID_STAGING}"
31
31
  {%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
32
- - "VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX}"
33
- - "VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT}"
34
- - "VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET}"
32
+ - "VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX_STAGING}"
33
+ - "VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT_STAGING}"
34
+ - "VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET_STAGING}"
35
35
  {%- endif %}
36
36
  - "PROJECT_ID=${_STAGING_PROJECT_ID}"
37
- - "SERVICE_ACCOUNT=${_PIPELINE_SA_EMAIL}"
37
+ - "SERVICE_ACCOUNT=${_PIPELINE_SA_EMAIL_STAGING}"
38
38
  - "PIPELINE_NAME=${_PIPELINE_NAME}"
39
39
  - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin'
40
40
  {%- endif %}
@@ -111,7 +111,7 @@ steps:
111
111
  uv run app/agent_engine_app.py \
112
112
  --project ${_STAGING_PROJECT_ID} \
113
113
  --location ${_REGION} \
114
- --set-env-vars="COMMIT_SHA=${COMMIT_SHA}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID=${_DATA_STORE_ID},DATA_STORE_REGION=${_DATA_STORE_REGION}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX},VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT},VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET}{%- endif %}{%- endif %}"
114
+ --set-env-vars="COMMIT_SHA=${COMMIT_SHA}{%- if cookiecutter.data_ingestion %}{%- if cookiecutter.datastore_type == "vertex_ai_search" %},DATA_STORE_ID=${_DATA_STORE_ID_STAGING},DATA_STORE_REGION=${_DATA_STORE_REGION}{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %},VECTOR_SEARCH_INDEX=${_VECTOR_SEARCH_INDEX_STAGING},VECTOR_SEARCH_INDEX_ENDPOINT=${_VECTOR_SEARCH_INDEX_ENDPOINT_STAGING},VECTOR_SEARCH_BUCKET=${_VECTOR_SEARCH_BUCKET_STAGING}{%- endif %}{%- endif %}"
115
115
  env:
116
116
  - 'PATH=/usr/local/bin:/usr/bin:~/.local/bin'
117
117
 
@@ -40,6 +40,7 @@ from ..utils.template import (
40
40
  get_template_path,
41
41
  load_template_config,
42
42
  process_template,
43
+ prompt_cicd_runner_selection,
43
44
  prompt_datastore_selection,
44
45
  prompt_deployment_target,
45
46
  prompt_session_type_selection,
@@ -96,6 +97,11 @@ def normalize_project_name(project_name: str) -> str:
96
97
  type=click.Choice(["agent_engine", "cloud_run"]),
97
98
  help="Deployment target name",
98
99
  )
100
+ @click.option(
101
+ "--cicd-runner",
102
+ type=click.Choice(["google_cloud_build", "github_actions"]),
103
+ help="CI/CD runner to use",
104
+ )
99
105
  @click.option(
100
106
  "--include-data-ingestion",
101
107
  "-i",
@@ -110,7 +116,7 @@ def normalize_project_name(project_name: str) -> str:
110
116
  )
111
117
  @click.option(
112
118
  "--session-type",
113
- type=click.Choice(["in_memory", "alloydb"]),
119
+ type=click.Choice(["in_memory", "alloydb", "agent_engine"]),
114
120
  help="Type of session storage to use",
115
121
  )
116
122
  @click.option("--debug", is_flag=True, help="Enable debug logging")
@@ -140,6 +146,7 @@ def create(
140
146
  project_name: str,
141
147
  agent: str | None,
142
148
  deployment_target: str | None,
149
+ cicd_runner: str | None,
143
150
  include_data_ingestion: bool,
144
151
  datastore: str | None,
145
152
  session_type: str | None,
@@ -430,6 +437,20 @@ def create(
430
437
  if debug and final_session_type:
431
438
  logging.debug(f"Selected session type: {final_session_type}")
432
439
 
440
+ # CI/CD runner selection
441
+ final_cicd_runner = cicd_runner
442
+ if not final_cicd_runner:
443
+ if auto_approve:
444
+ final_cicd_runner = "google_cloud_build"
445
+ console.print(
446
+ "Info: --cicd-runner not specified. Defaulting to 'google_cloud_build' in auto-approve mode.",
447
+ style="yellow",
448
+ )
449
+ else:
450
+ final_cicd_runner = prompt_cicd_runner_selection()
451
+ if debug:
452
+ logging.debug(f"Selected CI/CD runner: {final_cicd_runner}")
453
+
433
454
  # Region confirmation (if not explicitly passed)
434
455
  if (
435
456
  not auto_approve
@@ -460,7 +481,7 @@ def create(
460
481
  )
461
482
  console.print(
462
483
  "> Please check your authentication settings and permissions. "
463
- "Visit https://cloud.google.com/vertex-ai/docs/authentication for help.",
484
+ "> Visit https://cloud.google.com/vertex-ai/docs/authentication for help.",
464
485
  style="yellow",
465
486
  )
466
487
  console.print(
@@ -490,6 +511,7 @@ def create(
490
511
  template_path,
491
512
  project_name,
492
513
  deployment_target=final_deployment,
514
+ cicd_runner=final_cicd_runner,
493
515
  include_data_ingestion=include_data_ingestion,
494
516
  datastore=datastore,
495
517
  session_type=final_session_type,
@@ -584,14 +606,108 @@ def display_agent_selection(deployment_target: str | None = None) -> str:
584
606
  f"{num}. [bold]{agent['name']}[/] - [dim]{agent['description']}[/]"
585
607
  )
586
608
 
609
+ # Add special option for adk-samples
610
+ adk_samples_option = len(agents) + 1
611
+ console.print(
612
+ f"{adk_samples_option}. [bold]Browse agents from [link=https://github.com/google/adk-samples]google/adk-samples[/link][/] - [dim]Discover additional samples[/]"
613
+ )
614
+
587
615
  choice = IntPrompt.ask(
588
616
  "\nEnter the number of your template choice", default=1, show_default=True
589
617
  )
590
618
 
591
- if choice not in agents:
619
+ if choice == adk_samples_option:
620
+ return display_adk_samples_selection()
621
+ elif choice in agents:
622
+ return agents[choice]["name"]
623
+ else:
592
624
  raise ValueError(f"Invalid agent selection: {choice}")
593
625
 
594
- return agents[choice]["name"]
626
+
627
+ def display_adk_samples_selection() -> str:
628
+ """Display adk-samples agents and prompt for selection."""
629
+
630
+ from ..utils.remote_template import fetch_remote_template, parse_agent_spec
631
+
632
+ console.print("\n> Fetching agents from [bold blue]google/adk-samples[/]...")
633
+
634
+ try:
635
+ # Parse the adk-samples repository
636
+ spec = parse_agent_spec("https://github.com/google/adk-samples")
637
+ if not spec:
638
+ raise RuntimeError("Failed to parse adk-samples repository")
639
+
640
+ # Fetch the repository
641
+ repo_path, _ = fetch_remote_template(spec)
642
+
643
+ # Scan for agents in the repository
644
+ adk_agents = {}
645
+ agent_count = 1
646
+
647
+ # Search for templateconfig.yaml files to identify agents
648
+ for config_path in sorted(repo_path.glob("**/templateconfig.yaml")):
649
+ try:
650
+ import yaml
651
+
652
+ with open(config_path, encoding="utf-8") as f:
653
+ config = yaml.safe_load(f)
654
+
655
+ agent_name = config.get("name", config_path.parent.parent.name)
656
+ description = config.get("description", "No description available")
657
+
658
+ # Get the relative path from repo root
659
+ relative_path = config_path.parent.parent.relative_to(repo_path)
660
+
661
+ adk_agents[agent_count] = {
662
+ "name": agent_name,
663
+ "description": description,
664
+ "path": str(relative_path),
665
+ "spec": f"adk@{relative_path}",
666
+ }
667
+ agent_count += 1
668
+
669
+ except Exception as e:
670
+ logging.warning(
671
+ f"Could not load agent from {config_path.parent.parent}: {e}"
672
+ )
673
+
674
+ if not adk_agents:
675
+ console.print("No agents found in adk-samples repository", style="yellow")
676
+ # Fall back to local agents
677
+ return display_agent_selection()
678
+
679
+ console.print("\n> Available agents from [bold blue]google/adk-samples[/]:")
680
+ for num, agent in adk_agents.items():
681
+ console.print(
682
+ f"{num}. [bold]{agent['name']}[/] - [dim]{agent['description']}[/]"
683
+ )
684
+
685
+ # Add option to go back to local agents
686
+ back_option = len(adk_agents) + 1
687
+ console.print(
688
+ f"{back_option}. [bold]← Back to built-in agents[/] - [dim]Return to local agent selection[/]"
689
+ )
690
+
691
+ choice = IntPrompt.ask(
692
+ "\nEnter the number of your choice", default=1, show_default=True
693
+ )
694
+
695
+ if choice == back_option:
696
+ return display_agent_selection()
697
+ elif choice in adk_agents:
698
+ # Return the adk@ spec for the selected agent
699
+ selected_agent = adk_agents[choice]
700
+ console.print(
701
+ f"\n> Selected: [bold]{selected_agent['name']}[/] from adk-samples"
702
+ )
703
+ return selected_agent["spec"]
704
+ else:
705
+ raise ValueError(f"Invalid agent selection: {choice}")
706
+
707
+ except Exception as e:
708
+ console.print(f"Error fetching adk-samples agents: {e}", style="bold red")
709
+ console.print("Falling back to built-in agents...", style="yellow")
710
+ return display_agent_selection()
595
711
 
596
712
 
597
713
  def set_gcp_project(project_id: str, set_quota_project: bool = True) -> None:
src/cli/commands/list.py CHANGED
@@ -45,7 +45,7 @@ def display_agents_from_path(base_path: pathlib.Path, source_name: str) -> None:
45
45
  # Search for templateconfig.yaml files to identify agents
46
46
  for config_path in sorted(base_path.glob("**/templateconfig.yaml")):
47
47
  try:
48
- with open(config_path) as f:
48
+ with open(config_path, encoding="utf-8") as f:
49
49
  config = yaml.safe_load(f)
50
50
 
51
51
  agent_name = config.get("name", config_path.parent.parent.name)