agent-starter-pack 0.7.1__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.
Files changed (57) hide show
  1. {agent_starter_pack-0.7.1.dist-info → agent_starter_pack-0.8.0.dist-info}/METADATA +5 -5
  2. {agent_starter_pack-0.7.1.dist-info → agent_starter_pack-0.8.0.dist-info}/RECORD +56 -54
  3. agents/README.md +7 -0
  4. agents/adk_base/notebooks/adk_app_testing.ipynb +8 -6
  5. agents/adk_base/template/.templateconfig.yaml +3 -1
  6. agents/adk_gemini_fullstack/notebooks/adk_app_testing.ipynb +8 -6
  7. agents/adk_gemini_fullstack/template/.templateconfig.yaml +2 -1
  8. agents/agentic_rag/notebooks/adk_app_testing.ipynb +8 -6
  9. agents/agentic_rag/template/.templateconfig.yaml +2 -1
  10. agents/crewai_coding_crew/template/.templateconfig.yaml +1 -1
  11. llm.txt +7 -0
  12. src/base_template/README.md +2 -2
  13. src/base_template/deployment/cd/deploy-to-prod.yaml +1 -16
  14. src/base_template/deployment/cd/staging.yaml +4 -19
  15. src/base_template/deployment/terraform/apis.tf +2 -2
  16. src/base_template/deployment/terraform/build_triggers.tf +5 -5
  17. src/base_template/deployment/terraform/dev/apis.tf +8 -1
  18. src/base_template/deployment/terraform/dev/variables.tf +3 -1
  19. src/base_template/deployment/terraform/iam.tf +8 -8
  20. src/base_template/deployment/terraform/locals.tf +9 -2
  21. src/base_template/deployment/terraform/log_sinks.tf +2 -2
  22. src/base_template/deployment/terraform/service_accounts.tf +3 -3
  23. src/base_template/deployment/terraform/storage.tf +7 -7
  24. src/base_template/deployment/terraform/variables.tf +3 -0
  25. src/base_template/pyproject.toml +4 -3
  26. src/cli/commands/create.py +38 -0
  27. src/cli/commands/setup_cicd.py +2 -2
  28. src/cli/utils/cicd.py +2 -2
  29. src/cli/utils/template.py +34 -0
  30. src/deployment_targets/agent_engine/app/agent_engine_app.py +7 -7
  31. src/deployment_targets/agent_engine/tests/load_test/README.md +1 -6
  32. src/deployment_targets/agent_engine/tests/load_test/load_test.py +13 -3
  33. src/deployment_targets/cloud_run/Dockerfile +3 -0
  34. src/deployment_targets/cloud_run/app/server.py +18 -0
  35. src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +231 -0
  36. src/deployment_targets/cloud_run/deployment/terraform/service.tf +360 -0
  37. src/deployment_targets/cloud_run/tests/integration/test_server_e2e.py +8 -5
  38. src/deployment_targets/cloud_run/tests/load_test/README.md +2 -2
  39. src/deployment_targets/cloud_run/tests/load_test/load_test.py +21 -17
  40. src/frontends/adk_gemini_fullstack/frontend/src/App.tsx +2 -3
  41. src/resources/docs/adk-cheatsheet.md +1 -1
  42. src/resources/locks/uv-adk_base-agent_engine.lock +805 -200
  43. src/resources/locks/uv-adk_base-cloud_run.lock +1085 -234
  44. src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +805 -200
  45. src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +1085 -234
  46. src/resources/locks/uv-agentic_rag-agent_engine.lock +386 -283
  47. src/resources/locks/uv-agentic_rag-cloud_run.lock +513 -349
  48. src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +492 -497
  49. src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +671 -613
  50. src/resources/locks/uv-langgraph_base_react-agent_engine.lock +500 -391
  51. src/resources/locks/uv-langgraph_base_react-cloud_run.lock +682 -510
  52. src/resources/locks/uv-live_api-cloud_run.lock +686 -486
  53. src/resources/setup_cicd/github.tf +2 -2
  54. src/deployment_targets/cloud_run/uv.lock +0 -6952
  55. {agent_starter_pack-0.7.1.dist-info → agent_starter_pack-0.8.0.dist-info}/WHEEL +0 -0
  56. {agent_starter_pack-0.7.1.dist-info → agent_starter_pack-0.8.0.dist-info}/entry_points.txt +0 -0
  57. {agent_starter_pack-0.7.1.dist-info → agent_starter_pack-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services, resource.google_project_service_identity.vertex_sa]
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.shared_services]
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.shared_services]
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.shared_services]
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
- shared_services = [
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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.shared_services]
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"
@@ -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.99.0",
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.99.0"
24
+ "google-cloud-aiplatform[evaluation,agent-engines]~=1.101.0"
24
25
  {%- endif %}
25
26
  ]
26
27
  {% if cookiecutter.deployment_target == 'cloud_run' %}
@@ -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
 
@@ -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.shared_services]",
172
- "depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.shared_services, google_cloudbuildv2_repository.repo]",
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
@@ -228,9 +228,9 @@ def create_github_connection(
228
228
  "\n🔑 Authentication Required:", style="bold yellow"
229
229
  )
230
230
  console.print(
231
- 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:"
232
232
  )
233
- console.print(f"{action_uri}", style="bold blue")
233
+ print(f"\n{action_uri}\n")
234
234
  console.print(
235
235
  "(Copy and paste the link into your browser if clicking doesn't work)"
236
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}")
@@ -527,6 +560,7 @@ def process_template(
527
560
  "settings": settings,
528
561
  "tags": tags,
529
562
  "deployment_target": deployment_target or "",
563
+ "session_type": session_type or "",
530
564
  "frontend_type": frontend_type,
531
565
  "extra_dependencies": [extra_deps],
532
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) -> Mapping[str, Sequence]:
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.get("agent")),
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, Sequence
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) -> Mapping[str, Sequence]:
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
- # Create and activate virtual environment
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
- event = json.loads(line)
95
- events.append(event)
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(json.dumps(events)),
112
+ response_length=len(events),
103
113
  response=response,
104
114
  context={},
105
115
  )
@@ -24,6 +24,9 @@ COPY ./app ./app
24
24
 
25
25
  RUN uv sync --frozen
26
26
 
27
+ ARG COMMIT_SHA=""
28
+ ENV COMMIT_SHA=${COMMIT_SHA}
29
+
27
30
  EXPOSE 8080
28
31
 
29
32
  CMD ["uv", "run", "uvicorn", "app.server:app", "--host", "0.0.0.0", "--port", "8080"]
@@ -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}}"