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.
- {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/METADATA +2 -2
- {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/RECORD +53 -51
- agents/adk_base/.template/templateconfig.yaml +1 -1
- agents/adk_gemini_fullstack/.template/templateconfig.yaml +1 -1
- agents/agentic_rag/.template/templateconfig.yaml +1 -1
- agents/agentic_rag/README.md +1 -1
- agents/live_api/tests/integration/test_server_e2e.py +7 -1
- llm.txt +3 -2
- src/base_template/Makefile +4 -3
- src/base_template/README.md +7 -2
- src/base_template/deployment/README.md +6 -121
- src/base_template/deployment/terraform/github.tf +284 -0
- src/base_template/deployment/terraform/providers.tf +5 -0
- src/base_template/deployment/terraform/variables.tf +40 -1
- src/base_template/deployment/terraform/vars/env.tfvars +7 -1
- src/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %} +43 -0
- src/base_template/deployment/terraform/{build_triggers.tf → {% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} } +33 -18
- src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +114 -0
- src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml +65 -0
- src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +170 -0
- 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
- src/base_template/{deployment/cd/staging.yaml → {% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml } +7 -7
- src/cli/commands/create.py +120 -4
- src/cli/commands/list.py +1 -1
- src/cli/commands/setup_cicd.py +292 -298
- src/cli/utils/cicd.py +19 -7
- src/cli/utils/remote_template.py +4 -4
- src/cli/utils/template.py +67 -19
- src/deployment_targets/cloud_run/app/server.py +19 -0
- src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +4 -3
- src/deployment_targets/cloud_run/deployment/terraform/service.tf +4 -3
- src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +35 -0
- src/deployment_targets/cloud_run/tests/load_test/README.md +1 -1
- src/frontends/live_api_react/frontend/package-lock.json +19 -16
- src/frontends/streamlit/frontend/side_bar.py +1 -1
- src/frontends/streamlit/frontend/utils/chat_utils.py +1 -1
- src/frontends/streamlit/frontend/utils/local_chat_history.py +2 -2
- src/resources/docs/adk-cheatsheet.md +1 -1
- src/resources/locks/uv-adk_base-agent_engine.lock +164 -131
- src/resources/locks/uv-adk_base-cloud_run.lock +177 -144
- src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +164 -131
- src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +177 -144
- src/resources/locks/uv-agentic_rag-agent_engine.lock +223 -190
- src/resources/locks/uv-agentic_rag-cloud_run.lock +251 -218
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +315 -485
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +358 -531
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock +281 -249
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock +323 -290
- src/resources/locks/uv-live_api-cloud_run.lock +350 -327
- src/resources/setup_cicd/cicd_variables.tf +0 -41
- src/resources/setup_cicd/github.tf +0 -87
- src/resources/setup_cicd/providers.tf +0 -39
- {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/entry_points.txt +0 -0
- {agent_starter_pack-0.9.2.dist-info → agent_starter_pack-0.10.0.dist-info}/licenses/LICENSE +0 -0
- /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=${
|
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=${
|
30
|
+
- "DATA_STORE_ID=${_DATA_STORE_ID_PROD}"
|
31
31
|
{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
32
|
-
- "VECTOR_SEARCH_INDEX=${
|
33
|
-
- "VECTOR_SEARCH_INDEX_ENDPOINT=${
|
34
|
-
- "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=${
|
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=${
|
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=${
|
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=${
|
30
|
+
- "DATA_STORE_ID=${_DATA_STORE_ID_STAGING}"
|
31
31
|
{%- elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
32
|
-
- "VECTOR_SEARCH_INDEX=${
|
33
|
-
- "VECTOR_SEARCH_INDEX_ENDPOINT=${
|
34
|
-
- "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=${
|
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=${
|
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
|
|
src/cli/commands/create.py
CHANGED
@@ -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
|
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
|
-
|
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)
|