agent-starter-pack 0.7.0__py3-none-any.whl → 0.8.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.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/METADATA +5 -5
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/RECORD +57 -55
- agents/README.md +7 -0
- agents/adk_base/notebooks/adk_app_testing.ipynb +8 -6
- agents/adk_base/template/.templateconfig.yaml +3 -1
- agents/adk_gemini_fullstack/notebooks/adk_app_testing.ipynb +8 -6
- agents/adk_gemini_fullstack/template/.templateconfig.yaml +2 -1
- agents/agentic_rag/notebooks/adk_app_testing.ipynb +8 -6
- agents/agentic_rag/template/.templateconfig.yaml +2 -1
- agents/crewai_coding_crew/template/.templateconfig.yaml +1 -1
- llm.txt +22 -9
- src/base_template/.gitignore +0 -1
- src/base_template/README.md +5 -2
- src/base_template/deployment/cd/deploy-to-prod.yaml +1 -16
- src/base_template/deployment/cd/staging.yaml +4 -19
- src/base_template/deployment/terraform/apis.tf +2 -2
- src/base_template/deployment/terraform/build_triggers.tf +5 -5
- src/base_template/deployment/terraform/dev/apis.tf +8 -1
- src/base_template/deployment/terraform/dev/variables.tf +3 -1
- src/base_template/deployment/terraform/iam.tf +8 -8
- src/base_template/deployment/terraform/locals.tf +9 -2
- src/base_template/deployment/terraform/log_sinks.tf +2 -2
- src/base_template/deployment/terraform/service_accounts.tf +3 -3
- src/base_template/deployment/terraform/storage.tf +7 -7
- src/base_template/deployment/terraform/variables.tf +3 -0
- src/base_template/pyproject.toml +4 -3
- src/cli/commands/create.py +38 -0
- src/cli/commands/setup_cicd.py +2 -2
- src/cli/utils/cicd.py +6 -3
- src/cli/utils/template.py +34 -9
- src/deployment_targets/agent_engine/app/agent_engine_app.py +7 -7
- src/deployment_targets/agent_engine/tests/load_test/README.md +1 -6
- src/deployment_targets/agent_engine/tests/load_test/load_test.py +13 -3
- src/deployment_targets/cloud_run/Dockerfile +3 -0
- src/deployment_targets/cloud_run/app/server.py +18 -0
- src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +231 -0
- src/deployment_targets/cloud_run/deployment/terraform/service.tf +360 -0
- src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +8 -5
- src/deployment_targets/cloud_run/tests/load_test/README.md +2 -2
- src/deployment_targets/cloud_run/tests/load_test/load_test.py +21 -17
- src/frontends/adk_gemini_fullstack/frontend/src/App.tsx +2 -3
- src/resources/docs/adk-cheatsheet.md +1 -1
- src/resources/locks/uv-adk_base-agent_engine.lock +805 -200
- src/resources/locks/uv-adk_base-cloud_run.lock +1085 -234
- src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +805 -200
- src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +1085 -234
- src/resources/locks/uv-agentic_rag-agent_engine.lock +386 -283
- src/resources/locks/uv-agentic_rag-cloud_run.lock +513 -349
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +492 -497
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +671 -613
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock +500 -391
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock +682 -510
- src/resources/locks/uv-live_api-cloud_run.lock +686 -486
- src/resources/setup_cicd/github.tf +2 -2
- src/deployment_targets/cloud_run/uv.lock +0 -6952
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/entry_points.txt +0 -0
- {agent_starter_pack-0.7.0.dist-info → agent_starter_pack-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -39,7 +39,7 @@ resource "google_cloudbuild_trigger" "pr_checks" {
|
|
39
39
|
{% endif %}
|
40
40
|
]
|
41
41
|
include_build_logs = "INCLUDE_BUILD_LOGS_WITH_STATUS"
|
42
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
42
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
43
43
|
}
|
44
44
|
|
45
45
|
# b. Create CD pipeline trigger
|
@@ -85,13 +85,13 @@ resource "google_cloudbuild_trigger" "cd_pipeline" {
|
|
85
85
|
{% elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
86
86
|
_VECTOR_SEARCH_INDEX = resource.google_vertex_ai_index.vector_search_index_staging.id
|
87
87
|
_VECTOR_SEARCH_INDEX_ENDPOINT = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_staging.id
|
88
|
-
_VECTOR_SEARCH_BUCKET =
|
88
|
+
_VECTOR_SEARCH_BUCKET = resource.google_storage_bucket.vector_search_data_bucket["staging"].url
|
89
89
|
|
90
90
|
{% endif %}
|
91
91
|
{% endif %}
|
92
92
|
# Your other CD Pipeline substitutions
|
93
93
|
}
|
94
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
94
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
95
95
|
|
96
96
|
}
|
97
97
|
|
@@ -128,11 +128,11 @@ resource "google_cloudbuild_trigger" "deploy_to_prod_pipeline" {
|
|
128
128
|
{% elif cookiecutter.datastore_type == "vertex_ai_vector_search" %}
|
129
129
|
_VECTOR_SEARCH_INDEX = resource.google_vertex_ai_index.vector_search_index_prod.id
|
130
130
|
_VECTOR_SEARCH_INDEX_ENDPOINT = resource.google_vertex_ai_index_endpoint.vector_search_index_endpoint_prod.id
|
131
|
-
_VECTOR_SEARCH_BUCKET =
|
131
|
+
_VECTOR_SEARCH_BUCKET = resource.google_storage_bucket.vector_search_data_bucket["prod"].url
|
132
132
|
{% endif %}
|
133
133
|
{% endif %}
|
134
134
|
# Your other Deploy to Prod Pipeline substitutions
|
135
135
|
}
|
136
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
136
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
137
137
|
|
138
138
|
}
|
@@ -24,7 +24,14 @@ locals {
|
|
24
24
|
"bigquery.googleapis.com",
|
25
25
|
"serviceusage.googleapis.com",
|
26
26
|
"logging.googleapis.com",
|
27
|
-
"cloudtrace.googleapis.com"
|
27
|
+
"cloudtrace.googleapis.com",
|
28
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
29
|
+
"compute.googleapis.com",
|
30
|
+
"servicenetworking.googleapis.com",
|
31
|
+
"alloydb.googleapis.com",
|
32
|
+
"secretmanager.googleapis.com",
|
33
|
+
"dns.googleapis.com"
|
34
|
+
{%- endif %}
|
28
35
|
]
|
29
36
|
}
|
30
37
|
|
@@ -54,6 +54,9 @@ variable "agentengine_sa_roles" {
|
|
54
54
|
{% endif %}
|
55
55
|
type = list(string)
|
56
56
|
default = [
|
57
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
58
|
+
"roles/secretmanager.secretAccessor",
|
59
|
+
{%- endif %}
|
57
60
|
"roles/aiplatform.user",
|
58
61
|
"roles/discoveryengine.editor",
|
59
62
|
"roles/logging.logWriter",
|
@@ -61,7 +64,6 @@ variable "agentengine_sa_roles" {
|
|
61
64
|
"roles/storage.admin"
|
62
65
|
]
|
63
66
|
}
|
64
|
-
|
65
67
|
{% if cookiecutter.data_ingestion %}
|
66
68
|
|
67
69
|
variable "pipelines_roles" {
|
@@ -25,7 +25,7 @@ resource "google_project_iam_member" "cicd_project_roles" {
|
|
25
25
|
project = var.cicd_runner_project_id
|
26
26
|
role = each.value
|
27
27
|
member = "serviceAccount:${resource.google_service_account.cicd_runner_sa.email}"
|
28
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
28
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
29
29
|
|
30
30
|
}
|
31
31
|
|
@@ -42,7 +42,7 @@ resource "google_project_iam_member" "other_projects_roles" {
|
|
42
42
|
project = each.value.project_id
|
43
43
|
role = each.value.role
|
44
44
|
member = "serviceAccount:${resource.google_service_account.cicd_runner_sa.email}"
|
45
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
45
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
46
46
|
}
|
47
47
|
{% if cookiecutter.deployment_target == 'cloud_run' %}
|
48
48
|
# 3. Allow Cloud Run service SA to pull containers stored in the CICD project
|
@@ -52,7 +52,7 @@ resource "google_project_iam_member" "cicd_run_invoker_artifact_registry_reader"
|
|
52
52
|
|
53
53
|
role = "roles/artifactregistry.reader"
|
54
54
|
member = "serviceAccount:service-${data.google_project.projects[each.key].number}@serverless-robot-prod.iam.gserviceaccount.com"
|
55
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
55
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
56
56
|
|
57
57
|
}
|
58
58
|
|
@@ -69,7 +69,7 @@ resource "google_project_iam_member" "cloud_run_app_sa_roles" {
|
|
69
69
|
project = each.value.project
|
70
70
|
role = each.value.role
|
71
71
|
member = "serviceAccount:${google_service_account.cloud_run_app_sa[split(",", each.key)[0]].email}"
|
72
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
72
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
73
73
|
}
|
74
74
|
{% elif cookiecutter.deployment_target == 'agent_engine' %}
|
75
75
|
resource "google_project_service_identity" "vertex_sa" {
|
@@ -92,7 +92,7 @@ resource "google_project_iam_member" "vertex_ai_sa_permissions" {
|
|
92
92
|
project = each.value.project
|
93
93
|
role = each.value.role
|
94
94
|
member = "serviceAccount:service-${data.google_project.projects[split("_", each.key)[0]].number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
|
95
|
-
depends_on = [resource.google_project_service.
|
95
|
+
depends_on = [resource.google_project_service.deploy_project_services, resource.google_project_service_identity.vertex_sa]
|
96
96
|
}
|
97
97
|
{% endif %}
|
98
98
|
|
@@ -101,14 +101,14 @@ resource "google_service_account_iam_member" "cicd_run_invoker_token_creator" {
|
|
101
101
|
service_account_id = google_service_account.cicd_runner_sa.name
|
102
102
|
role = "roles/iam.serviceAccountTokenCreator"
|
103
103
|
member = "serviceAccount:${resource.google_service_account.cicd_runner_sa.email}"
|
104
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
104
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
105
105
|
}
|
106
106
|
# Special assignment: Allow the CICD SA to impersonate himself for trigger creation
|
107
107
|
resource "google_service_account_iam_member" "cicd_run_invoker_account_user" {
|
108
108
|
service_account_id = google_service_account.cicd_runner_sa.name
|
109
109
|
role = "roles/iam.serviceAccountUser"
|
110
110
|
member = "serviceAccount:${resource.google_service_account.cicd_runner_sa.email}"
|
111
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
111
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
112
112
|
}
|
113
113
|
|
114
114
|
{%- if cookiecutter.data_ingestion %}
|
@@ -125,6 +125,6 @@ resource "google_project_iam_member" "vertexai_pipeline_sa_roles" {
|
|
125
125
|
project = each.value.project
|
126
126
|
role = each.value.role
|
127
127
|
member = "serviceAccount:${google_service_account.vertexai_pipeline_app_sa[split(",", each.key)[0]].email}"
|
128
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
128
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
129
129
|
}
|
130
130
|
{%- endif %}
|
@@ -23,7 +23,7 @@ locals {
|
|
23
23
|
"cloudtrace.googleapis.com"
|
24
24
|
]
|
25
25
|
|
26
|
-
|
26
|
+
deploy_project_services = [
|
27
27
|
"aiplatform.googleapis.com",
|
28
28
|
"run.googleapis.com",
|
29
29
|
"discoveryengine.googleapis.com",
|
@@ -32,7 +32,14 @@ locals {
|
|
32
32
|
"bigquery.googleapis.com",
|
33
33
|
"serviceusage.googleapis.com",
|
34
34
|
"logging.googleapis.com",
|
35
|
-
"cloudtrace.googleapis.com"
|
35
|
+
"cloudtrace.googleapis.com",
|
36
|
+
{%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
|
37
|
+
"compute.googleapis.com",
|
38
|
+
"servicenetworking.googleapis.com",
|
39
|
+
"alloydb.googleapis.com",
|
40
|
+
"secretmanager.googleapis.com",
|
41
|
+
"dns.googleapis.com"
|
42
|
+
{%- endif %}
|
36
43
|
]
|
37
44
|
|
38
45
|
deploy_project_ids = {
|
@@ -26,7 +26,7 @@ resource "google_bigquery_dataset" "feedback_dataset" {
|
|
26
26
|
dataset_id = replace("${var.project_name}_feedback", "-", "_")
|
27
27
|
friendly_name = "${var.project_name}_feedback"
|
28
28
|
location = var.region
|
29
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
29
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
30
30
|
}
|
31
31
|
|
32
32
|
resource "google_bigquery_dataset" "telemetry_logs_dataset" {
|
@@ -35,7 +35,7 @@ resource "google_bigquery_dataset" "telemetry_logs_dataset" {
|
|
35
35
|
dataset_id = replace("${var.project_name}_telemetry", "-", "_")
|
36
36
|
friendly_name = "${var.project_name}_telemetry"
|
37
37
|
location = var.region
|
38
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
38
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
39
39
|
}
|
40
40
|
|
41
41
|
module "log_export_to_bigquery" {
|
@@ -16,7 +16,7 @@ resource "google_service_account" "cicd_runner_sa" {
|
|
16
16
|
account_id = "${var.project_name}-cb"
|
17
17
|
display_name = "CICD Runner SA"
|
18
18
|
project = var.cicd_runner_project_id
|
19
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
19
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
20
20
|
}
|
21
21
|
{% if cookiecutter.deployment_target == 'cloud_run' %}
|
22
22
|
resource "google_service_account" "cloud_run_app_sa" {
|
@@ -25,7 +25,7 @@ resource "google_service_account" "cloud_run_app_sa" {
|
|
25
25
|
account_id = "${var.project_name}-cr"
|
26
26
|
display_name = "Cloud Run Generative AI app SA"
|
27
27
|
project = each.value
|
28
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
28
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
29
29
|
}
|
30
30
|
{% endif %}
|
31
31
|
|
@@ -37,6 +37,6 @@ resource "google_service_account" "vertexai_pipeline_app_sa" {
|
|
37
37
|
account_id = "${var.project_name}-rag"
|
38
38
|
display_name = "Vertex AI Pipeline app SA"
|
39
39
|
project = each.value
|
40
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
40
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
41
41
|
}
|
42
42
|
{% endif %}
|
@@ -23,7 +23,7 @@ resource "google_storage_bucket" "bucket_load_test_results" {
|
|
23
23
|
project = var.cicd_runner_project_id
|
24
24
|
uniform_bucket_level_access = true
|
25
25
|
force_destroy = true
|
26
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
26
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
27
27
|
}
|
28
28
|
|
29
29
|
resource "google_storage_bucket" "logs_data_bucket" {
|
@@ -34,7 +34,7 @@ resource "google_storage_bucket" "logs_data_bucket" {
|
|
34
34
|
uniform_bucket_level_access = true
|
35
35
|
force_destroy = true
|
36
36
|
|
37
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
37
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
38
38
|
}
|
39
39
|
{% if cookiecutter.deployment_target == 'cloud_run' %}
|
40
40
|
resource "google_artifact_registry_repository" "repo-artifacts-genai" {
|
@@ -43,7 +43,7 @@ resource "google_artifact_registry_repository" "repo-artifacts-genai" {
|
|
43
43
|
description = "Repo for Generative AI applications"
|
44
44
|
format = "DOCKER"
|
45
45
|
project = var.cicd_runner_project_id
|
46
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
46
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
47
47
|
}
|
48
48
|
{% endif %}
|
49
49
|
|
@@ -56,7 +56,7 @@ resource "google_storage_bucket" "data_ingestion_pipeline_gcs_root" {
|
|
56
56
|
uniform_bucket_level_access = true
|
57
57
|
force_destroy = true
|
58
58
|
|
59
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
59
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
60
60
|
}
|
61
61
|
|
62
62
|
{% if cookiecutter.datastore_type == "vertex_ai_search" %}
|
@@ -71,7 +71,7 @@ resource "google_discovery_engine_data_store" "data_store_staging" {
|
|
71
71
|
solution_types = ["SOLUTION_TYPE_SEARCH"]
|
72
72
|
create_advanced_site_search = false
|
73
73
|
provider = google.staging_billing_override
|
74
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
74
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
75
75
|
}
|
76
76
|
|
77
77
|
resource "google_discovery_engine_search_engine" "search_engine_staging" {
|
@@ -97,7 +97,7 @@ resource "google_discovery_engine_data_store" "data_store_prod" {
|
|
97
97
|
solution_types = ["SOLUTION_TYPE_SEARCH"]
|
98
98
|
create_advanced_site_search = false
|
99
99
|
provider = google.prod_billing_override
|
100
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
100
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
101
101
|
}
|
102
102
|
|
103
103
|
resource "google_discovery_engine_search_engine" "search_engine_prod" {
|
@@ -122,7 +122,7 @@ resource "google_storage_bucket" "vector_search_data_bucket" {
|
|
122
122
|
uniform_bucket_level_access = true
|
123
123
|
force_destroy = true
|
124
124
|
|
125
|
-
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
125
|
+
depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
|
126
126
|
}
|
127
127
|
|
128
128
|
resource "google_vertex_ai_index" "vector_search_index_staging" {
|
@@ -76,6 +76,7 @@ variable "agentengine_sa_roles" {
|
|
76
76
|
default = [
|
77
77
|
{%- if cookiecutter.deployment_target == 'cloud_run' %}
|
78
78
|
"roles/run.invoker",
|
79
|
+
"roles/secretmanager.secretAccessor",
|
79
80
|
{%- endif %}
|
80
81
|
"roles/aiplatform.user",
|
81
82
|
"roles/discoveryengine.editor",
|
@@ -84,6 +85,8 @@ variable "agentengine_sa_roles" {
|
|
84
85
|
"roles/storage.admin"
|
85
86
|
]
|
86
87
|
}
|
88
|
+
{%- if cookiecutter.deployment_target == 'cloud_run' %}
|
89
|
+
{%- endif %}
|
87
90
|
|
88
91
|
variable "cicd_roles" {
|
89
92
|
description = "List of roles to assign to the CICD runner service account in the CICD project"
|
src/base_template/pyproject.toml
CHANGED
@@ -16,11 +16,12 @@ dependencies = [
|
|
16
16
|
{%- endif %}
|
17
17
|
"google-cloud-logging~=3.11.4",
|
18
18
|
{%- if cookiecutter.deployment_target == 'cloud_run' %}
|
19
|
-
"google-cloud-aiplatform[evaluation]~=1.
|
19
|
+
"google-cloud-aiplatform[evaluation]~=1.101.0",
|
20
20
|
"fastapi~=0.115.8",
|
21
|
-
"uvicorn~=0.34.0"
|
21
|
+
"uvicorn~=0.34.0",
|
22
|
+
"psycopg2-binary>=2.9.10",
|
22
23
|
{%- elif cookiecutter.deployment_target == 'agent_engine' %}
|
23
|
-
"google-cloud-aiplatform[evaluation,agent-engines]~=1.
|
24
|
+
"google-cloud-aiplatform[evaluation,agent-engines]~=1.101.0"
|
24
25
|
{%- endif %}
|
25
26
|
]
|
26
27
|
{% if cookiecutter.deployment_target == 'cloud_run' %}
|
src/cli/commands/create.py
CHANGED
@@ -32,6 +32,7 @@ from ..utils.template import (
|
|
32
32
|
process_template,
|
33
33
|
prompt_datastore_selection,
|
34
34
|
prompt_deployment_target,
|
35
|
+
prompt_session_type_selection,
|
35
36
|
)
|
36
37
|
|
37
38
|
console = Console()
|
@@ -93,6 +94,11 @@ def normalize_project_name(project_name: str) -> str:
|
|
93
94
|
type=click.Choice(DATASTORE_TYPES),
|
94
95
|
help="Type of datastore to use for data ingestion (requires --include-data-ingestion)",
|
95
96
|
)
|
97
|
+
@click.option(
|
98
|
+
"--session-type",
|
99
|
+
type=click.Choice(["in_memory", "alloydb"]),
|
100
|
+
help="Type of session storage to use",
|
101
|
+
)
|
96
102
|
@click.option("--debug", is_flag=True, help="Enable debug logging")
|
97
103
|
@click.option(
|
98
104
|
"--output-dir",
|
@@ -122,6 +128,7 @@ def create(
|
|
122
128
|
deployment_target: str | None,
|
123
129
|
include_data_ingestion: bool,
|
124
130
|
datastore: str | None,
|
131
|
+
session_type: str | None,
|
125
132
|
debug: bool,
|
126
133
|
output_dir: str | None,
|
127
134
|
auto_approve: bool,
|
@@ -232,6 +239,36 @@ def create(
|
|
232
239
|
if debug:
|
233
240
|
logging.debug(f"Selected deployment target: {final_deployment}")
|
234
241
|
|
242
|
+
# Session type validation and selection (only for agents that require session management)
|
243
|
+
final_session_type = session_type
|
244
|
+
|
245
|
+
# Check if agent requires session management
|
246
|
+
requires_session = config.get("settings", {}).get("requires_session", False)
|
247
|
+
|
248
|
+
if requires_session:
|
249
|
+
if final_deployment == "agent_engine" and session_type:
|
250
|
+
console.print(
|
251
|
+
"Error: --session-type cannot be used with agent_engine deployment target. "
|
252
|
+
"Agent Engine handles session management internally.",
|
253
|
+
style="bold red",
|
254
|
+
)
|
255
|
+
return
|
256
|
+
|
257
|
+
if final_deployment == "cloud_run" and not session_type:
|
258
|
+
final_session_type = prompt_session_type_selection()
|
259
|
+
else:
|
260
|
+
# Agents that don't require session management always use in-memory sessions
|
261
|
+
final_session_type = "in_memory"
|
262
|
+
if session_type and session_type != "in_memory":
|
263
|
+
console.print(
|
264
|
+
"Warning: Session type options are only available for agents that require session management. "
|
265
|
+
"Using in-memory sessions for this agent.",
|
266
|
+
style="yellow",
|
267
|
+
)
|
268
|
+
|
269
|
+
if debug and final_session_type:
|
270
|
+
logging.debug(f"Selected session type: {final_session_type}")
|
271
|
+
|
235
272
|
# Region confirmation (if not explicitly passed)
|
236
273
|
if (
|
237
274
|
not auto_approve
|
@@ -289,6 +326,7 @@ def create(
|
|
289
326
|
deployment_target=final_deployment,
|
290
327
|
include_data_ingestion=include_data_ingestion,
|
291
328
|
datastore=datastore,
|
329
|
+
session_type=final_session_type,
|
292
330
|
output_dir=destination_dir,
|
293
331
|
)
|
294
332
|
|
src/cli/commands/setup_cicd.py
CHANGED
@@ -168,8 +168,8 @@ def update_build_triggers(tf_dir: Path) -> None:
|
|
168
168
|
|
169
169
|
# Add repository dependency to all trigger resources
|
170
170
|
modified_content = content.replace(
|
171
|
-
"depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
172
|
-
"depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.
|
171
|
+
"depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]",
|
172
|
+
"depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services, google_cloudbuildv2_repository.repo]",
|
173
173
|
)
|
174
174
|
|
175
175
|
# Update repository reference in all triggers
|
src/cli/utils/cicd.py
CHANGED
@@ -212,7 +212,10 @@ def create_github_connection(
|
|
212
212
|
return secret_id, app_installation_id
|
213
213
|
elif status == "PENDING_USER_OAUTH" or status == "PENDING_INSTALL_APP":
|
214
214
|
if attempt < max_retries - 1: # Don't print waiting on last attempt
|
215
|
-
console.print("⏳ Waiting for
|
215
|
+
console.print("⏳ Waiting for authorization...")
|
216
|
+
print(
|
217
|
+
f"Console: https://console.cloud.google.com/cloud-build/repositories?project={project_id}"
|
218
|
+
)
|
216
219
|
# Extract and print the action URI for user authentication
|
217
220
|
try:
|
218
221
|
action_uri = (
|
@@ -225,9 +228,9 @@ def create_github_connection(
|
|
225
228
|
"\n🔑 Authentication Required:", style="bold yellow"
|
226
229
|
)
|
227
230
|
console.print(
|
228
|
-
f"Please visit [link={action_uri}]this page[/link] to authenticate Cloud Build with GitHub:"
|
231
|
+
f"Please visit [link={action_uri}][bold blue]this page[/bold blue][/link] to authenticate Cloud Build with GitHub:"
|
229
232
|
)
|
230
|
-
|
233
|
+
print(f"\n{action_uri}\n")
|
231
234
|
console.print(
|
232
235
|
"(Copy and paste the link into your browser if clicking doesn't work)"
|
233
236
|
)
|
src/cli/utils/template.py
CHANGED
@@ -206,6 +206,36 @@ def prompt_deployment_target(agent_name: str) -> str:
|
|
206
206
|
return targets[choice - 1]
|
207
207
|
|
208
208
|
|
209
|
+
def prompt_session_type_selection() -> str:
|
210
|
+
"""Ask user to select a session type for Cloud Run deployment."""
|
211
|
+
console = Console()
|
212
|
+
|
213
|
+
session_types = {
|
214
|
+
"in_memory": {
|
215
|
+
"display_name": "In-memory session",
|
216
|
+
"description": "Session data stored in memory - ideal for stateless applications",
|
217
|
+
},
|
218
|
+
"alloydb": {
|
219
|
+
"display_name": "AlloyDB",
|
220
|
+
"description": "Use AlloyDB for session management. Comes with terraform resources for deployment.",
|
221
|
+
},
|
222
|
+
}
|
223
|
+
|
224
|
+
console.print("\n> Please select a session type:")
|
225
|
+
for idx, (_key, info) in enumerate(session_types.items(), 1):
|
226
|
+
console.print(
|
227
|
+
f"{idx}. [bold]{info['display_name']}[/] - [dim]{info['description']}[/]"
|
228
|
+
)
|
229
|
+
|
230
|
+
choice = IntPrompt.ask(
|
231
|
+
"\nEnter the number of your session type choice",
|
232
|
+
default=1,
|
233
|
+
show_default=True,
|
234
|
+
)
|
235
|
+
|
236
|
+
return list(session_types.keys())[choice - 1]
|
237
|
+
|
238
|
+
|
209
239
|
def prompt_datastore_selection(
|
210
240
|
agent_name: str, from_cli_flag: bool = False
|
211
241
|
) -> str | None:
|
@@ -365,6 +395,7 @@ def process_template(
|
|
365
395
|
deployment_target: str | None = None,
|
366
396
|
include_data_ingestion: bool = False,
|
367
397
|
datastore: str | None = None,
|
398
|
+
session_type: str | None = None,
|
368
399
|
output_dir: pathlib.Path | None = None,
|
369
400
|
) -> None:
|
370
401
|
"""Process the template directory and create a new project.
|
@@ -375,6 +406,8 @@ def process_template(
|
|
375
406
|
project_name: Name of the project to create
|
376
407
|
deployment_target: Optional deployment target (agent_engine or cloud_run)
|
377
408
|
include_data_ingestion: Whether to include data pipeline components
|
409
|
+
datastore: Optional datastore type for data ingestion
|
410
|
+
session_type: Optional session type for cloud_run deployment
|
378
411
|
output_dir: Optional output directory path, defaults to current directory
|
379
412
|
"""
|
380
413
|
logging.debug(f"Processing template from {template_dir}")
|
@@ -467,15 +500,6 @@ def process_template(
|
|
467
500
|
agent_folder, project_folder, agent_name, overwrite=True
|
468
501
|
)
|
469
502
|
|
470
|
-
# Copy agent README.md if it exists
|
471
|
-
agent_readme = agent_path / "README.md"
|
472
|
-
if agent_readme.exists():
|
473
|
-
agent_readme_dest = project_template / "agent_README.md"
|
474
|
-
shutil.copy2(agent_readme, agent_readme_dest)
|
475
|
-
logging.debug(
|
476
|
-
f"Copied agent README from {agent_readme} to {agent_readme_dest}"
|
477
|
-
)
|
478
|
-
|
479
503
|
# Load and validate template config first
|
480
504
|
template_path = pathlib.Path(template_dir)
|
481
505
|
config = load_template_config(template_path)
|
@@ -536,6 +560,7 @@ def process_template(
|
|
536
560
|
"settings": settings,
|
537
561
|
"tags": tags,
|
538
562
|
"deployment_target": deployment_target or "",
|
563
|
+
"session_type": session_type or "",
|
539
564
|
"frontend_type": frontend_type,
|
540
565
|
"extra_dependencies": [extra_deps],
|
541
566
|
"data_ingestion": include_data_ingestion,
|
@@ -12,14 +12,13 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
-
# mypy: disable-error-code="attr-defined"
|
15
|
+
# mypy: disable-error-code="attr-defined,arg-type"
|
16
16
|
{%- if "adk" in cookiecutter.tags %}
|
17
17
|
import copy
|
18
18
|
import datetime
|
19
19
|
import json
|
20
20
|
import logging
|
21
21
|
import os
|
22
|
-
from collections.abc import Mapping, Sequence
|
23
22
|
from typing import Any
|
24
23
|
|
25
24
|
import google.auth
|
@@ -57,7 +56,7 @@ class AgentEngineApp(AdkApp):
|
|
57
56
|
feedback_obj = Feedback.model_validate(feedback)
|
58
57
|
self.logger.log_struct(feedback_obj.model_dump(), severity="INFO")
|
59
58
|
|
60
|
-
def register_operations(self) ->
|
59
|
+
def register_operations(self) -> dict[str, list[str]]:
|
61
60
|
"""Registers the operations of the Agent.
|
62
61
|
|
63
62
|
Extends the base operations to include feedback registration functionality.
|
@@ -69,9 +68,10 @@ class AgentEngineApp(AdkApp):
|
|
69
68
|
def clone(self) -> "AgentEngineApp":
|
70
69
|
"""Returns a clone of the ADK application."""
|
71
70
|
template_attributes = self._tmpl_attrs
|
71
|
+
|
72
72
|
return self.__class__(
|
73
|
-
agent=copy.deepcopy(template_attributes
|
74
|
-
enable_tracing=template_attributes.get("enable_tracing"),
|
73
|
+
agent=copy.deepcopy(template_attributes["agent"]),
|
74
|
+
enable_tracing=bool(template_attributes.get("enable_tracing", False)),
|
75
75
|
session_service_builder=template_attributes.get("session_service_builder"),
|
76
76
|
artifact_service_builder=template_attributes.get(
|
77
77
|
"artifact_service_builder"
|
@@ -83,7 +83,7 @@ import datetime
|
|
83
83
|
import json
|
84
84
|
import logging
|
85
85
|
import os
|
86
|
-
from collections.abc import Iterable, Mapping
|
86
|
+
from collections.abc import Iterable, Mapping
|
87
87
|
from typing import (
|
88
88
|
Any,
|
89
89
|
)
|
@@ -182,7 +182,7 @@ class AgentEngineApp:
|
|
182
182
|
feedback_obj = Feedback.model_validate(feedback)
|
183
183
|
self.logger.log_struct(feedback_obj.model_dump(), severity="INFO")
|
184
184
|
|
185
|
-
def register_operations(self) ->
|
185
|
+
def register_operations(self) -> dict[str, list[str]]:
|
186
186
|
"""Registers the operations of the Agent.
|
187
187
|
|
188
188
|
This mapping defines how different operation modes (e.g., "", "stream")
|
@@ -18,12 +18,7 @@ Follow these steps to execute load tests:
|
|
18
18
|
It's recommended to use a separate terminal tab and create a virtual environment for Locust to avoid conflicts with your application's Python environment.
|
19
19
|
|
20
20
|
```bash
|
21
|
-
|
22
|
-
python3 -m venv .locust_env
|
23
|
-
source .locust_env/bin/activate
|
24
|
-
|
25
|
-
# Install required packages
|
26
|
-
pip install locust==2.31.1 "google-cloud-aiplatform[langchain,reasoningengine]>=1.77.0"
|
21
|
+
python3 -m venv .locust_env && source .locust_env/bin/activate && pip install locust==2.31.1
|
27
22
|
```
|
28
23
|
|
29
24
|
**3. Execute the Load Test:**
|
@@ -91,15 +91,25 @@ class ChatStreamUser(HttpUser):
|
|
91
91
|
events = []
|
92
92
|
for line in response.iter_lines():
|
93
93
|
if line:
|
94
|
-
|
95
|
-
events.append(
|
94
|
+
line_str = line.decode("utf-8")
|
95
|
+
events.append(line_str)
|
96
|
+
|
97
|
+
if "429 Too Many Requests" in line_str:
|
98
|
+
self.environment.events.request.fire(
|
99
|
+
request_type="POST",
|
100
|
+
name=f"{url_path} rate_limited 429s",
|
101
|
+
response_time=0,
|
102
|
+
response_length=len(line),
|
103
|
+
response=response,
|
104
|
+
context={},
|
105
|
+
)
|
96
106
|
end_time = time.time()
|
97
107
|
total_time = end_time - start_time
|
98
108
|
self.environment.events.request.fire(
|
99
109
|
request_type="POST",
|
100
110
|
name="/stream_messages end",
|
101
111
|
response_time=total_time * 1000, # Convert to milliseconds
|
102
|
-
response_length=len(
|
112
|
+
response_length=len(events),
|
103
113
|
response=response,
|
104
114
|
context={},
|
105
115
|
)
|
@@ -43,11 +43,29 @@ provider.add_span_processor(processor)
|
|
43
43
|
trace.set_tracer_provider(provider)
|
44
44
|
|
45
45
|
AGENT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
46
|
+
|
47
|
+
{%- if cookiecutter.session_type == "alloydb" %}
|
48
|
+
# AlloyDB session configuration
|
49
|
+
db_user = os.environ.get("DB_USER", "postgres")
|
50
|
+
db_name = os.environ.get("DB_NAME", "postgres")
|
51
|
+
db_pass = os.environ.get("DB_PASS")
|
52
|
+
db_host = os.environ.get("DB_HOST")
|
53
|
+
|
54
|
+
# Set session_service_uri if database credentials are available
|
55
|
+
session_service_uri = None
|
56
|
+
if db_host and db_pass:
|
57
|
+
session_service_uri = f"postgresql://{db_user}:{db_pass}@{db_host}:5432/{db_name}"
|
58
|
+
{%- else %}
|
59
|
+
# In-memory session configuration - no persistent storage
|
60
|
+
session_service_uri = None
|
61
|
+
{%- endif %}
|
62
|
+
|
46
63
|
app: FastAPI = get_fast_api_app(
|
47
64
|
agents_dir=AGENT_DIR,
|
48
65
|
web=True,
|
49
66
|
artifact_service_uri=bucket_name,
|
50
67
|
allow_origins=allow_origins,
|
68
|
+
session_service_uri=session_service_uri,
|
51
69
|
)
|
52
70
|
app.title = "{{cookiecutter.project_name}}"
|
53
71
|
app.description = "API for interacting with the Agent {{cookiecutter.project_name}}"
|