agent-starter-pack 0.11.0__py3-none-any.whl → 0.11.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-starter-pack
3
- Version: 0.11.0
3
+ Version: 0.11.2
4
4
  Summary: CLI to bootstrap production-ready Google Cloud GenAI agent projects from templates.
5
5
  Author-email: Google LLC <agent-starter-pack@google.com>
6
6
  License: Apache-2.0
@@ -75,6 +75,14 @@ This command handles creating the project without needing to pre-install the pac
75
75
 
76
76
  **That's it!** You now have a fully functional agent project—complete with backend, frontend, and deployment infrastructure—ready for you to explore and customize.
77
77
 
78
+ ### 🔧 Enhance Existing Agents
79
+
80
+ Already have an agent? Add production-ready deployment and infrastructure:
81
+
82
+ ```bash
83
+ agent-starter-pack enhance my-existing-agent
84
+ ```
85
+
78
86
  See [Installation Guide](https://googlecloudplatform.github.io/agent-starter-pack/guide/installation) for more options, or try with zero setup in [Firebase Studio](https://studio.firebase.google.com/new?template=https%3A%2F%2Fgithub.com%2FGoogleCloudPlatform%2Fagent-starter-pack%2Ftree%2Fmain%2Fsrc%2Fresources%2Fidx) or [Cloud Shell](https://shell.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https%3A%2F%2Fgithub.com%2Feliasecchig%2Fasp-open-in-cloud-shell&cloudshell_print=open-in-cs).
79
87
 
80
88
  ---
@@ -84,7 +92,6 @@ See [Installation Guide](https://googlecloudplatform.github.io/agent-starter-pac
84
92
  | Agent Name | Description |
85
93
  |-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
86
94
  | `adk_base` | A base ReAct agent implemented using Google's [Agent Development Kit](https://github.com/google/adk-python) |
87
- | `adk_gemini_fullstack` | A production-ready fullstack research agent with Gemini that demonstrates complex agentic workflows, modular agent design, and Human-in-the-Loop steps. [ADK Samples](https://github.com/google/adk-samples/tree/main/python/agents/gemini-fullstack) |
88
95
  | `agentic_rag` | A RAG agent for document retrieval and Q&A. Supporting [Vertex AI Search](https://cloud.google.com/generative-ai-app-builder/docs/enterprise-search-introduction) and [Vector Search](https://cloud.google.com/vertex-ai/docs/vector-search/overview). |
89
96
  | `langgraph_base_react` | An agent implementing a base ReAct agent using LangGraph |
90
97
  | `crewai_coding_crew` | A multi-agent system implemented with CrewAI created to support coding activities |
@@ -5,13 +5,6 @@ agents/adk_base/app/agent.py,sha256=6Q6QegQDxEaAck989DPIb3ArHMZtw_YJBqhHFqg-UjQ,
5
5
  agents/adk_base/notebooks/adk_app_testing.ipynb,sha256=wgFzBo7hX393NVzy3ZfZHncs1ptiQbM_8he3XxJu4yM,9763
6
6
  agents/adk_base/notebooks/evaluating_adk_agent.ipynb,sha256=OMTiT3gAFWPvE9pPL8z7tsDwOU-l8wem5wH-OXPPlvk,56805
7
7
  agents/adk_base/tests/integration/test_agent.py,sha256=VypgpEWrQegJBgc58V-BlIsbqh-Hii-hwmkwcz5feFw,1969
8
- agents/adk_gemini_fullstack/README.md,sha256=yQFFcESALj5Q6eweyIyPx__U74obUM88aCBJYNV2UWs,1674
9
- agents/adk_gemini_fullstack/.template/templateconfig.yaml,sha256=BFlIFsm1g0xmIg4g0jkQ8MpW_EJPRXi4gPYjgIIsAEg,1745
10
- agents/adk_gemini_fullstack/app/agent.py,sha256=NXOkYFxDccJaSq55CTS-UYY8z5-WgBZqexII0Ybzk9c,22662
11
- agents/adk_gemini_fullstack/app/config.py,sha256=x--axECPKWW3oLANKz2_4zzHEBIU7if8iYNZRjlTNV0,1563
12
- agents/adk_gemini_fullstack/notebooks/adk_app_testing.ipynb,sha256=wgFzBo7hX393NVzy3ZfZHncs1ptiQbM_8he3XxJu4yM,9763
13
- agents/adk_gemini_fullstack/notebooks/evaluating_adk_agent.ipynb,sha256=OMTiT3gAFWPvE9pPL8z7tsDwOU-l8wem5wH-OXPPlvk,56805
14
- agents/adk_gemini_fullstack/tests/integration/test_agent.py,sha256=VypgpEWrQegJBgc58V-BlIsbqh-Hii-hwmkwcz5feFw,1969
15
8
  agents/agentic_rag/README.md,sha256=cPeY_XGt79ava22PIM0x92oi67R-TnlEKBQGpK1MOkA,2262
16
9
  agents/agentic_rag/.template/templateconfig.yaml,sha256=Gfw3FOjj3XNxoXn6WGwC2PG59f4qB3p2cYTQ49ykvJc,1248
17
10
  agents/agentic_rag/app/agent.py,sha256=tKtzez7vGu6JgMWmZN7QrKkyLBvHu1ondAuICjKoC-g,3983
@@ -54,13 +47,13 @@ src/base_template/app/utils/typing.py,sha256=DP5OZC3IGvqA1XbvWt8kI3gyAK3ZjzUSL5C
54
47
  src/base_template/deployment/README.md,sha256=gZJvSWdQh_Mi-bZ3dmuPv7fMezIw04fgN5tq7KgglPw,692
55
48
  src/base_template/deployment/terraform/apis.tf,sha256=KX8Oe2gjT-gh9Bkntz9yIAyRjPc1gZvwOhroJ6NZVp4,1513
56
49
  src/base_template/deployment/terraform/github.tf,sha256=KhfNBAzeUH9jDr8FOw_DiypesA5AEC8IZT1PRqntSt8,10838
57
- src/base_template/deployment/terraform/iam.tf,sha256=1u0qY-4srkhRirRI9kuQE0GAAYBeP5cTztA-w2N4FH8,5657
50
+ src/base_template/deployment/terraform/iam.tf,sha256=I70ROOjXcYiqxtzuak6n0ZNhkjH6vjOzykXQG1Zi1dE,4700
58
51
  src/base_template/deployment/terraform/locals.tf,sha256=nvjlavqWRL6e-iIqfIRvsai5JY9l6KhRGcwJQFRdu_U,1653
59
52
  src/base_template/deployment/terraform/log_sinks.tf,sha256=eAGh_dCjOKUQjylkqp1fNM9cfE4QB9HSEovjD6_G9Lg,2971
60
53
  src/base_template/deployment/terraform/providers.tf,sha256=wNWvXJbpvV3njDYO8t4s6DdDkL0dQpWgkPsmJw61ABM,1167
61
54
  src/base_template/deployment/terraform/service_accounts.tf,sha256=iSRrRzxL16pZHel5cZDzC7m15IRTRv8qMxkcg4nd30o,1672
62
55
  src/base_template/deployment/terraform/storage.tf,sha256=W0l34U7Ql2wdegfWsWfKzaEooaMaTL2TkU18KM_Vuys,8695
63
- src/base_template/deployment/terraform/variables.tf,sha256=RudiaEVsIrRSCIHDMWs857gMghenUeZR5g_34kDuoXY,6733
56
+ src/base_template/deployment/terraform/variables.tf,sha256=JD-lvsVYSgE0pR15ZJhmNAn2SAWo5CNDCofXGNVJy1o,6749
64
57
  src/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'github_actions' %}wif.tf{% else %}unused_wif.tf{% endif %},sha256=rCupUnvaTVj75ahJOckNuzlQ-xcLTik_HpqXzVEEB5g,2666
65
58
  src/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %},sha256=wb8Frd95PF0PHDRoh9v3QF5kpF-Fi-GDcD7mKmTxGJ8,6813
66
59
  src/base_template/deployment/terraform/dev/apis.tf,sha256=R5fyLQGHsZy7JyDdFpuNzUBute6Rn9xR32zIMjkGxzc,1592
@@ -68,11 +61,11 @@ src/base_template/deployment/terraform/dev/iam.tf,sha256=q8dfqbMNSpgMXW96hP7rnAp
68
61
  src/base_template/deployment/terraform/dev/log_sinks.tf,sha256=uVdMtDdd8MnxtKhqzVaYqadE11P3r4fs2IdgNecxM4I,2671
69
62
  src/base_template/deployment/terraform/dev/providers.tf,sha256=1S9jCh48d6ailVZ1e14EHsUUDSp7DyGZGExJwViFCkM,900
70
63
  src/base_template/deployment/terraform/dev/storage.tf,sha256=1mgLs21SUhfcoRICqd7BqUlEVAVGeN3kMsQ4UAQLOh8,4654
71
- src/base_template/deployment/terraform/dev/variables.tf,sha256=JMo3BQ57t8OTRiNUb9cz1zoWYCOMMhi67Hx0UZ_kZko,4072
64
+ src/base_template/deployment/terraform/dev/variables.tf,sha256=l95zljQbchR6b--wJGJJcCAu89FqsR3UqAiCz_bH7to,4089
72
65
  src/base_template/deployment/terraform/dev/vars/env.tfvars,sha256=LoQMjh1AAMR-MGfaSCsVMjdoYTk2T4oS4D9vMH54CdQ,714
73
66
  src/base_template/deployment/terraform/vars/env.tfvars,sha256=Jyc36pt-0xNMwQsoXucad0QAWFMeGe67fdimCKXx-tw,1411
74
67
  src/base_template/tests/unit/test_dummy.py,sha256=2exfCH8qhkZrLWvK04ZxNTO9MV3fdTbZkJN3uK6zvok,850
75
- src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml,sha256=A9NbH0l-NqbwfPI5d2SxxKuMuwcAUbbErhTxYWYsSxc,5667
68
+ src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml,sha256=I9uwH0mpuQQU3wbqaniWMb37UPEUnbY4o1YhRJ5egM8,5739
76
69
  src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/pr_checks.yaml,sha256=vy51dSiRFEFlFq9eEWuUsemG0jXj3VL4lCRMcodPiok,1981
77
70
  src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml,sha256=fYX-IBKHD-gSoFNLpAJUM0v2okL32AbMTn-eJpstSqU,8494
78
71
  src/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml,sha256=Zv3oE3YC8P2iYJ2_ie1PPo0HjNLxiMkY3IwJrS0bFcM,3703
@@ -80,9 +73,9 @@ src/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.clou
80
73
  src/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml,sha256=Spy8ziGCHUtY5hqSIiIDTTywjmSoUw8N1YlwGo0aL04,7367
81
74
  src/cli/main.py,sha256=Dya7Sw3ozMTaGDcwMh_-W7udkGZHGzgAj8aBdSZaZxI,1832
82
75
  src/cli/commands/create.py,sha256=mUFukCCpuFV6bgS-JmQEZ6D-zB-_ddxmTMeuygrhogI,43876
83
- src/cli/commands/enhance.py,sha256=Evi4UigR8zMUwP99D116w1W-ZKmlIy1hXRPWz4EH_E4,9372
76
+ src/cli/commands/enhance.py,sha256=KcSLRmhNDxbQa_XoJqcXtC16enyx8FWq20bkpmLSpyQ,11370
84
77
  src/cli/commands/list.py,sha256=qey_XDoJkjBvvuVMilFqjMUdBRmbHkSyqGeM23E3xHM,5502
85
- src/cli/commands/setup_cicd.py,sha256=ZgpMrYHXg3B_u5h5PxvVuC4T7Q2uQTYMNMwBBOlcKmg,32250
78
+ src/cli/commands/setup_cicd.py,sha256=nSgMUD4_ncYGwLWU1Fl7Ypw3GTJc8qVfjPxwZMLn4xo,32113
86
79
  src/cli/utils/__init__.py,sha256=_cTmsXGPqOtK0q8UW5164QTltbJRJFR_Efxq_BRL1-o,1311
87
80
  src/cli/utils/cicd.py,sha256=9s_OcusQznT_pSjFP60BfDBoZ5V6bwPE0QWbWdMaVlY,26515
88
81
  src/cli/utils/datastores.py,sha256=gv1V6eDcOEKx4MRNG5C3Y-VfixYq1AzQuaYMLp8QRNo,1058
@@ -204,8 +197,8 @@ src/resources/locks/uv-live_api-cloud_run.lock,sha256=xOPEAiyHooNT2nMP1wbnJ2ekOD
204
197
  src/utils/generate_locks.py,sha256=6V1B8V2BEuevWnXUsxZVTrLjXwFRII8UfsIGrQqZxVs,4320
205
198
  src/utils/lock_utils.py,sha256=IFOMUWtb-ypm2Y8w8J5y2oI_-MaPuwPF_JOAAlnNudA,2275
206
199
  src/utils/watch_and_rebuild.py,sha256=vP4yIiA7E_lj5sfQdJUl8TXas6V7msDg8XWUutAC05Q,6679
207
- agent_starter_pack-0.11.0.dist-info/METADATA,sha256=I6ucqd79L2lMuuIQTi4hn1BXKD587zEHizRnB8mtvGU,11209
208
- agent_starter_pack-0.11.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
209
- agent_starter_pack-0.11.0.dist-info/entry_points.txt,sha256=U7uCxR7YulIhZ0L8R8Hui0Bsy6J7oyESBeDYJYMrQjA,56
210
- agent_starter_pack-0.11.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
211
- agent_starter_pack-0.11.0.dist-info/RECORD,,
200
+ agent_starter_pack-0.11.2.dist-info/METADATA,sha256=TKkrd80Yfxfp3hFQKQCwakKeLulHCfqEprBiVty9P38,11102
201
+ agent_starter_pack-0.11.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
202
+ agent_starter_pack-0.11.2.dist-info/entry_points.txt,sha256=U7uCxR7YulIhZ0L8R8Hui0Bsy6J7oyESBeDYJYMrQjA,56
203
+ agent_starter_pack-0.11.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
204
+ agent_starter_pack-0.11.2.dist-info/RECORD,,
@@ -49,14 +49,15 @@ variable "app_sa_roles" {
49
49
  description = "List of roles to assign to the application service account"
50
50
  type = list(string)
51
51
  default = [
52
- {%- if "adk" in cookiecutter.tags and cookiecutter.session_type == "alloydb" %}
52
+ {%- if cookiecutter.session_type == "alloydb" %}
53
53
  "roles/secretmanager.secretAccessor",
54
54
  {%- endif %}
55
55
  "roles/aiplatform.user",
56
56
  "roles/discoveryengine.editor",
57
57
  "roles/logging.logWriter",
58
58
  "roles/cloudtrace.agent",
59
- "roles/storage.admin"
59
+ "roles/storage.admin",
60
+ "roles/serviceusage.serviceUsageConsumer",
60
61
  ]
61
62
  }
62
63
  {% if cookiecutter.data_ingestion %}
@@ -44,19 +44,7 @@ resource "google_project_iam_member" "other_projects_roles" {
44
44
  member = "serviceAccount:${resource.google_service_account.cicd_runner_sa.email}"
45
45
  depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
46
46
  }
47
- {% if cookiecutter.deployment_target == 'cloud_run' %}
48
- # 3. Allow Cloud Run service SA to pull containers stored in the CICD project
49
- resource "google_project_iam_member" "cicd_run_invoker_artifact_registry_reader" {
50
- for_each = local.deploy_project_ids
51
- project = var.cicd_runner_project_id
52
-
53
- role = "roles/artifactregistry.reader"
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.deploy_project_services]
56
-
57
- }
58
-
59
- # 4. Grant application SA the required permissions to run the application
47
+ # 3. Grant application SA the required permissions to run the application
60
48
  resource "google_project_iam_member" "app_sa_roles" {
61
49
  for_each = {
62
50
  for pair in setproduct(keys(local.deploy_project_ids), var.app_sa_roles) :
@@ -72,33 +60,21 @@ resource "google_project_iam_member" "app_sa_roles" {
72
60
  depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
73
61
  }
74
62
 
75
- {% endif %}
76
-
77
- {% if cookiecutter.deployment_target == 'agent_engine' %}
78
- resource "google_project_service_identity" "vertex_sa" {
63
+ {% if cookiecutter.deployment_target == 'cloud_run' %}
64
+ # 4. Allow Cloud Run service SA to pull containers stored in the CICD project
65
+ resource "google_project_iam_member" "cicd_run_invoker_artifact_registry_reader" {
79
66
  for_each = local.deploy_project_ids
80
- provider = google-beta
81
- project = each.value
82
- service = "aiplatform.googleapis.com"
83
- }
67
+ project = var.cicd_runner_project_id
84
68
 
85
- # 5. Grant required permissions to Vertex AI Service Agent SA for Agent Engine
86
- resource "google_project_iam_member" "vertex_ai_sa_permissions" {
87
- for_each = {
88
- for pair in setproduct(keys(local.deploy_project_ids), var.app_sa_roles) :
89
- "${pair[0]}_${pair[1]}" => {
90
- project = local.deploy_project_ids[pair[0]]
91
- role = pair[1]
92
- }
93
- }
69
+ role = "roles/artifactregistry.reader"
70
+ member = "serviceAccount:service-${data.google_project.projects[each.key].number}@serverless-robot-prod.iam.gserviceaccount.com"
71
+ depends_on = [resource.google_project_service.cicd_services, resource.google_project_service.deploy_project_services]
94
72
 
95
- project = each.value.project
96
- role = each.value.role
97
- member = "serviceAccount:service-${data.google_project.projects[split("_", each.key)[0]].number}@gcp-sa-aiplatform-re.iam.gserviceaccount.com"
98
- depends_on = [resource.google_project_service.deploy_project_services, resource.google_project_service_identity.vertex_sa]
99
73
  }
74
+
100
75
  {% endif %}
101
76
 
77
+
102
78
  # Special assignment: Allow the CICD SA to create tokens
103
79
  resource "google_service_account_iam_member" "cicd_run_invoker_token_creator" {
104
80
  service_account_id = google_service_account.cicd_runner_sa.name
@@ -70,15 +70,15 @@ variable "app_sa_roles" {
70
70
  description = "List of roles to assign to the application service account"
71
71
  type = list(string)
72
72
  default = [
73
- {%- if cookiecutter.deployment_target == 'cloud_run' %}
74
- "roles/run.invoker",
73
+ {%- if cookiecutter.session_type == "alloydb" %}
75
74
  "roles/secretmanager.secretAccessor",
76
75
  {%- endif %}
77
76
  "roles/aiplatform.user",
78
77
  "roles/discoveryengine.editor",
79
78
  "roles/logging.logWriter",
80
79
  "roles/cloudtrace.agent",
81
- "roles/storage.admin"
80
+ "roles/storage.admin",
81
+ "roles/serviceusage.serviceUsageConsumer",
82
82
  ]
83
83
  }
84
84
  {%- if cookiecutter.deployment_target == 'cloud_run' %}
@@ -64,10 +64,12 @@ jobs:
64
64
  uses: 'google-github-actions/setup-gcloud@v2'
65
65
  {%- endif %}
66
66
 
67
+ {%- if cookiecutter.deployment_target == 'agent_engine' %}
67
68
  - name: Install uv and dependencies
68
69
  run: |
69
70
  pip install uv==0.6.12
70
71
  uv sync --locked
72
+ {%- endif %}
71
73
 
72
74
  {%- if cookiecutter.data_ingestion %}
73
75
  - name: Deploy data ingestion pipeline (Production)
@@ -16,8 +16,10 @@ import pathlib
16
16
 
17
17
  import click
18
18
  from rich.console import Console
19
+ from rich.prompt import IntPrompt
19
20
 
20
21
  from ..utils.logging import display_welcome_banner, handle_cli_error
22
+ from ..utils.template import get_available_agents
21
23
  from .create import (
22
24
  create,
23
25
  get_available_base_templates,
@@ -28,6 +30,48 @@ from .create import (
28
30
  console = Console()
29
31
 
30
32
 
33
+ def display_base_template_selection(current_base: str) -> str:
34
+ """Display available base templates and prompt for selection."""
35
+ agents = get_available_agents()
36
+
37
+ if not agents:
38
+ raise click.ClickException("No base templates available")
39
+
40
+ console.print()
41
+ console.print("🔧 [bold]Base Template Selection[/bold]")
42
+ console.print()
43
+ console.print(f"Your project currently inherits from: [cyan]{current_base}[/cyan]")
44
+ console.print("Available base templates:")
45
+
46
+ # Create a mapping of choices to agent names
47
+ template_choices = {}
48
+ choice_num = 1
49
+ current_choice = None
50
+
51
+ for _num, agent in agents.items():
52
+ template_choices[choice_num] = agent["name"]
53
+ current_indicator = " (current)" if agent["name"] == current_base else ""
54
+ console.print(
55
+ f" {choice_num}. [bold]{agent['name']}[/]{current_indicator} - [dim]{agent['description']}[/]"
56
+ )
57
+ if agent["name"] == current_base:
58
+ current_choice = choice_num
59
+ choice_num += 1
60
+
61
+ if current_choice is None:
62
+ current_choice = 1
63
+
64
+ console.print()
65
+ choice = IntPrompt.ask(
66
+ "Select base template", default=current_choice, show_default=True
67
+ )
68
+
69
+ if choice in template_choices:
70
+ return template_choices[choice]
71
+ else:
72
+ raise ValueError(f"Invalid base template selection: {choice}")
73
+
74
+
31
75
  @click.command()
32
76
  @click.pass_context
33
77
  @click.argument(
@@ -155,25 +199,35 @@ def enhance(
155
199
  # Load config from current directory for inheritance info
156
200
  current_dir = pathlib.Path.cwd()
157
201
  source_config = load_remote_template_config(current_dir, cli_overrides)
158
- base_template_name = get_base_template_name(source_config)
159
-
160
- console.print()
161
- console.print(
162
- f"Template inherits from base: [cyan][link=https://github.com/GoogleCloudPlatform/agent-starter-pack/tree/main/agents/{base_template_name}]{base_template_name}[/link][/cyan]"
163
- )
202
+ original_base_template_name = get_base_template_name(source_config)
164
203
 
165
- # Show available alternatives and guidance
166
- available_bases = get_available_base_templates()
167
- if len(available_bases) > 1:
168
- other_bases = [b for b in available_bases if b != base_template_name]
169
- if other_bases:
170
- console.print(
171
- f"[dim]💡 To use a different base template (e.g., {', '.join(other_bases[:2])}), use:[/dim]"
172
- )
204
+ # Interactive base template selection if not provided via CLI and not auto-approved
205
+ if not base_template and not auto_approve:
206
+ selected_base_template = display_base_template_selection(
207
+ original_base_template_name
208
+ )
209
+ if selected_base_template != original_base_template_name:
210
+ # Update CLI overrides with the selected base template
211
+ cli_overrides["base_template"] = selected_base_template
212
+ base_template = selected_base_template
173
213
  console.print(
174
- "[dim] asp enhance . --base-template langgraph_base_react[/dim]"
214
+ f" Selected base template: [cyan]{selected_base_template}[/cyan]"
175
215
  )
176
- console.print()
216
+ console.print()
217
+
218
+ # Reload config with potential base template override
219
+ if cli_overrides.get("base_template"):
220
+ source_config = load_remote_template_config(current_dir, cli_overrides)
221
+
222
+ base_template_name = get_base_template_name(source_config)
223
+
224
+ # Show current inheritance info
225
+ if not auto_approve or base_template:
226
+ console.print()
227
+ console.print(
228
+ f"Template inherits from base: [cyan][link=https://github.com/GoogleCloudPlatform/agent-starter-pack/tree/main/agents/{base_template_name}]{base_template_name}[/link][/cyan]"
229
+ )
230
+ console.print()
177
231
 
178
232
  # Validate project structure when using current directory template
179
233
  if template_path == pathlib.Path("."):
@@ -48,7 +48,7 @@ def display_intro_message() -> None:
48
48
  "This command helps set up a basic CI/CD pipeline for development and testing purposes."
49
49
  )
50
50
  console.print("It will:")
51
- console.print("- Create a GitHub repository and connect it to Cloud Build")
51
+ console.print("- Create a GitHub repository and connect it to your CI/CD runner")
52
52
  console.print("- Set up development environment infrastructure")
53
53
  console.print("- Configure basic CI/CD triggers for PR checks and deployments")
54
54
  console.print(
@@ -218,6 +218,34 @@ def validate_working_directory() -> None:
218
218
  )
219
219
 
220
220
 
221
+ def detect_region_from_terraform_vars() -> str | None:
222
+ """Detect region from Terraform vars file.
223
+
224
+ Returns:
225
+ str | None: The detected region, or None if not found or is default
226
+ """
227
+ try:
228
+ tf_vars_path = Path("deployment/terraform/vars/env.tfvars")
229
+ if not tf_vars_path.exists():
230
+ return None
231
+
232
+ with open(tf_vars_path, encoding="utf-8") as f:
233
+ content = f.read()
234
+
235
+ # Look for region = "value" pattern
236
+ region_match = re.search(r'region\s*=\s*"([^"]+)"', content)
237
+ if region_match:
238
+ detected_region = region_match.group(1)
239
+ # Don't auto-detect if it's the default value
240
+ if detected_region != "us-central1":
241
+ return detected_region
242
+
243
+ return None
244
+ except Exception:
245
+ # If any error occurs, return None to use default
246
+ return None
247
+
248
+
221
249
  def update_build_triggers(tf_dir: Path) -> None:
222
250
  """Update build triggers configuration."""
223
251
  build_triggers_path = tf_dir / "build_triggers.tf"
@@ -427,7 +455,9 @@ console = Console()
427
455
  @click.option(
428
456
  "--cicd-project", help="CICD project ID (defaults to prod project if not specified)"
429
457
  )
430
- @click.option("--region", default="us-central1", help="GCP region")
458
+ @click.option(
459
+ "--region", help="GCP region (auto-detects from Terraform vars if not specified)"
460
+ )
431
461
  @click.option("--repository-name", help="Repository name (optional)")
432
462
  @click.option(
433
463
  "--repository-owner",
@@ -468,7 +498,7 @@ def setup_cicd(
468
498
  staging_project: str | None,
469
499
  prod_project: str | None,
470
500
  cicd_project: str | None,
471
- region: str,
501
+ region: str | None,
472
502
  repository_name: str | None,
473
503
  repository_owner: str | None,
474
504
  host_connection_name: str | None,
@@ -502,23 +532,24 @@ def setup_cicd(
502
532
  cicd_project = prod_project
503
533
  console.print(f"Using production project '{prod_project}' for CI/CD resources")
504
534
 
505
- console.print(
506
- "\n⚠️ WARNING: The setup-cicd command is experimental and may have unexpected behavior.",
507
- style="bold yellow",
508
- )
509
- console.print("Please report any issues you encounter.\n")
535
+ # Auto-detect region if not provided
536
+ if region is None:
537
+ detected_region = detect_region_from_terraform_vars()
538
+ if detected_region:
539
+ region = detected_region
540
+ console.print(f"Auto-detected region from Terraform vars: {region}")
541
+ else:
542
+ region = "us-central1"
543
+ console.print(f"Using default region: {region}")
544
+ else:
545
+ console.print(f"Using provided region: {region}")
510
546
 
511
- console.print("\n📋 About this command:", style="bold blue")
512
- console.print(
513
- "This command helps set up a basic CI/CD pipeline for development and testing purposes."
514
- )
515
- console.print("It will:")
516
- console.print("- Create a GitHub repository and connect it to Cloud Build")
517
- console.print("- Set up development environment infrastructure")
518
- console.print("- Configure basic CI/CD triggers for PR checks and deployments")
519
- console.print(
520
- "- Configure remote Terraform state in GCS (use --local-state to use local state instead)"
521
- )
547
+ # Auto-detect CI/CD runner based on Terraform files (moved earlier)
548
+ tf_dir = Path("deployment/terraform")
549
+ is_github_actions = (tf_dir / "wif.tf").exists() and (tf_dir / "github.tf").exists()
550
+ cicd_runner = "github_actions" if is_github_actions else "google_cloud_build"
551
+
552
+ display_intro_message()
522
553
 
523
554
  console.print("\n⚡ Production Setup Note:", style="bold yellow")
524
555
  console.print(
@@ -537,28 +568,6 @@ def setup_cicd(
537
568
  console.print("\n🛑 Setup cancelled by user", style="bold yellow")
538
569
  return
539
570
 
540
- console.print(
541
- "This command helps set up a basic CI/CD pipeline for development and testing purposes."
542
- )
543
- console.print("It will:")
544
- console.print("- Create a GitHub repository and connect it to Cloud Build")
545
- console.print("- Set up development environment infrastructure")
546
- console.print("- Configure basic CI/CD triggers for PR checks and deployments")
547
- console.print(
548
- "- Configure remote Terraform state in GCS (use --local-state to use local state instead)"
549
- )
550
-
551
- console.print("\n⚡ Production Setup Note:", style="bold yellow")
552
- console.print(
553
- "For production deployments and maximum flexibility, we recommend following"
554
- )
555
- console.print("the manual setup instructions in deployment/README.md")
556
- console.print("This will give you more control over:")
557
- console.print("- Security configurations")
558
- console.print("- Custom deployment workflows")
559
- console.print("- Environment-specific settings")
560
- console.print("- Advanced CI/CD pipeline customization\n")
561
-
562
571
  if debug:
563
572
  logging.basicConfig(level=logging.DEBUG)
564
573
  console.print("> Debug mode enabled")
@@ -1,39 +0,0 @@
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
- description: "A production-ready fullstack research agent that uses Gemini to strategize, research, and synthesize comprehensive reports with human-in-the-loop collaboration"
16
- example_question: "A report on the latest Google I/O event"
17
- settings:
18
- requires_data_ingestion: false
19
- requires_session: true
20
- deployment_targets: ["agent_engine", "cloud_run"]
21
- extra_dependencies: ["google-adk~=1.8.0"]
22
- tags: ["adk"]
23
- frontend_type: "adk_gemini_fullstack"
24
- interactive_command: "dev"
25
- commands:
26
- override:
27
- install: "uv sync --dev --extra jupyter && npm --prefix frontend install"
28
- extra:
29
- dev:
30
- command: 'make dev-backend & make dev-frontend'
31
- description: "Start the ADK API server and React frontend development server simultaneously"
32
- dev-backend:
33
- command:
34
- agent_engine: 'uv run adk api_server app --allow_origins="*"'
35
- cloud_run: 'ALLOW_ORIGINS="*" uv run uvicorn app.server:app --host 0.0.0.0 --port 8000 --reload'
36
- description: "Start the ADK API server"
37
- dev-frontend:
38
- command: 'npm --prefix frontend run dev'
39
- description: "Start the React frontend development server"
@@ -1,27 +0,0 @@
1
- # Gemini Fullstack Agent Development Kit (ADK) Quickstart
2
-
3
- > 🔍 **Sample Agent**: This agent is part of the [ADK Samples](https://github.com/google/adk-samples/tree/main/python/agents/gemini-fullstack) collection, showcasing agent implementations using the Agent Development Kit.
4
-
5
- The **Gemini Fullstack Agent Development Kit (ADK) Quickstart** is a production-ready blueprint for building a sophisticated, fullstack research agent with Gemini. It's built to demonstrate how the ADK helps structure complex agentic workflows, build modular agents, and incorporate critical Human-in-the-Loop (HITL) steps.
6
-
7
- <table>
8
- <thead>
9
- <tr>
10
- <th colspan="2">Key Features</th>
11
- </tr>
12
- </thead>
13
- <tbody>
14
- <tr>
15
- <td>🏗️</td>
16
- <td><strong>Fullstack & Production-Ready:</strong> A complete React frontend and ADK-powered FastAPI backend, with deployment options for <a href="https://cloud.google.com/run">Google Cloud Run</a> and <a href="https://cloud.google.com/vertex-ai/generative-ai/docs/agent-engine/overview">Vertex AI Agent Engine</a>.</td>
17
- </tr>
18
- <tr>
19
- <td>🧠</td>
20
- <td><strong>Advanced Agentic Workflow:</strong> The agent uses Gemini to <strong>strategize</strong> a multi-step plan, <strong>reflect</strong> on findings to identify gaps, and <strong>synthesize</strong> a final, comprehensive report.</td>
21
- </tr>
22
- <tr>
23
- <td>🔄</td>
24
- <td><strong>Iterative & Human-in-the-Loop Research:</strong> Involves the user for plan approval, then autonomously loops through searching (via Gemini function calling) and refining its results until it has gathered sufficient information.</td>
25
- </tr>
26
- </tbody>
27
- </table>