agent-starter-pack 0.10.1__py3-none-any.whl → 0.11.1__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.10.1.dist-info → agent_starter_pack-0.11.1.dist-info}/METADATA +10 -3
- {agent_starter_pack-0.10.1.dist-info → agent_starter_pack-0.11.1.dist-info}/RECORD +43 -49
- agents/crewai_coding_crew/.template/templateconfig.yaml +2 -2
- agents/crewai_coding_crew/tests/integration/test_agent.py +1 -1
- agents/langgraph_base_react/.template/templateconfig.yaml +1 -1
- agents/langgraph_base_react/tests/integration/test_agent.py +1 -1
- src/base_template/deployment/terraform/dev/iam.tf +12 -11
- src/base_template/deployment/terraform/dev/variables.tf +2 -7
- src/base_template/deployment/terraform/github.tf +14 -0
- src/base_template/deployment/terraform/iam.tf +10 -7
- src/base_template/deployment/terraform/service_accounts.tf +4 -5
- src/base_template/deployment/terraform/variables.tf +2 -7
- src/base_template/deployment/terraform/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}build_triggers.tf{% else %}unused_build_triggers.tf{% endif %} +4 -2
- src/base_template/pyproject.toml +2 -2
- src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/deploy-to-prod.yaml +3 -0
- src/base_template/{% if cookiecutter.cicd_runner == 'github_actions' %}.github{% else %}unused_github{% endif %}/workflows/staging.yaml +1 -0
- src/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/deploy-to-prod.yaml +1 -0
- src/base_template/{% if cookiecutter.cicd_runner == 'google_cloud_build' %}.cloudbuild{% else %}unused_.cloudbuild{% endif %}/staging.yaml +1 -0
- src/cli/commands/create.py +202 -100
- src/cli/commands/enhance.py +302 -0
- src/cli/commands/list.py +23 -11
- src/cli/main.py +2 -0
- src/cli/utils/logging.py +40 -0
- src/cli/utils/remote_template.py +55 -16
- src/cli/utils/template.py +212 -94
- src/deployment_targets/agent_engine/app/agent_engine_app.py +8 -0
- src/deployment_targets/cloud_run/app/server.py +1 -1
- src/deployment_targets/cloud_run/deployment/terraform/dev/service.tf +1 -1
- src/deployment_targets/cloud_run/deployment/terraform/service.tf +2 -2
- src/resources/locks/uv-adk_base-agent_engine.lock +312 -312
- src/resources/locks/uv-adk_base-cloud_run.lock +403 -404
- src/resources/locks/uv-adk_gemini_fullstack-agent_engine.lock +312 -312
- src/resources/locks/uv-adk_gemini_fullstack-cloud_run.lock +403 -404
- src/resources/locks/uv-agentic_rag-agent_engine.lock +371 -371
- src/resources/locks/uv-agentic_rag-cloud_run.lock +477 -478
- src/resources/locks/uv-crewai_coding_crew-agent_engine.lock +661 -591
- src/resources/locks/uv-crewai_coding_crew-cloud_run.lock +868 -760
- src/resources/locks/uv-langgraph_base_react-agent_engine.lock +496 -446
- src/resources/locks/uv-langgraph_base_react-cloud_run.lock +639 -565
- src/resources/locks/uv-live_api-cloud_run.lock +584 -510
- agents/adk_gemini_fullstack/.template/templateconfig.yaml +0 -39
- agents/adk_gemini_fullstack/README.md +0 -27
- agents/adk_gemini_fullstack/app/agent.py +0 -412
- agents/adk_gemini_fullstack/app/config.py +0 -46
- agents/adk_gemini_fullstack/notebooks/adk_app_testing.ipynb +0 -355
- agents/adk_gemini_fullstack/notebooks/evaluating_adk_agent.ipynb +0 -1528
- agents/adk_gemini_fullstack/tests/integration/test_agent.py +0 -58
- {agent_starter_pack-0.10.1.dist-info → agent_starter_pack-0.11.1.dist-info}/WHEEL +0 -0
- {agent_starter_pack-0.10.1.dist-info → agent_starter_pack-0.11.1.dist-info}/entry_points.txt +0 -0
- {agent_starter_pack-0.10.1.dist-info → agent_starter_pack-0.11.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,302 @@
|
|
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
|
+
import pathlib
|
16
|
+
|
17
|
+
import click
|
18
|
+
from rich.console import Console
|
19
|
+
from rich.prompt import IntPrompt
|
20
|
+
|
21
|
+
from ..utils.logging import display_welcome_banner, handle_cli_error
|
22
|
+
from ..utils.template import get_available_agents
|
23
|
+
from .create import (
|
24
|
+
create,
|
25
|
+
get_available_base_templates,
|
26
|
+
shared_template_options,
|
27
|
+
validate_base_template,
|
28
|
+
)
|
29
|
+
|
30
|
+
console = Console()
|
31
|
+
|
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
|
+
|
75
|
+
@click.command()
|
76
|
+
@click.pass_context
|
77
|
+
@click.argument(
|
78
|
+
"template_path",
|
79
|
+
type=click.Path(path_type=pathlib.Path),
|
80
|
+
default=".",
|
81
|
+
required=False,
|
82
|
+
)
|
83
|
+
@click.option(
|
84
|
+
"--name",
|
85
|
+
"-n",
|
86
|
+
help="Project name for templating (defaults to current directory name)",
|
87
|
+
)
|
88
|
+
@click.option(
|
89
|
+
"--base-template",
|
90
|
+
help="Base template to inherit from (e.g., adk_base, langgraph_base_react, agentic_rag)",
|
91
|
+
)
|
92
|
+
@shared_template_options
|
93
|
+
@handle_cli_error
|
94
|
+
def enhance(
|
95
|
+
ctx: click.Context,
|
96
|
+
template_path: pathlib.Path,
|
97
|
+
name: str | None,
|
98
|
+
deployment_target: str | None,
|
99
|
+
cicd_runner: str | None,
|
100
|
+
include_data_ingestion: bool,
|
101
|
+
datastore: str | None,
|
102
|
+
session_type: str | None,
|
103
|
+
debug: bool,
|
104
|
+
auto_approve: bool,
|
105
|
+
region: str,
|
106
|
+
skip_checks: bool,
|
107
|
+
base_template: str | None,
|
108
|
+
) -> None:
|
109
|
+
"""Enhance your existing project with AI agent capabilities.
|
110
|
+
|
111
|
+
This command is an alias for 'create' with --in-folder mode enabled, designed to
|
112
|
+
add agent-starter-pack features to your existing project in-place rather than
|
113
|
+
creating a new project directory.
|
114
|
+
|
115
|
+
For best compatibility, your project should follow the agent-starter-pack structure
|
116
|
+
with agent code organized in an /app folder (containing agent.py, etc.).
|
117
|
+
|
118
|
+
TEMPLATE_PATH can be:
|
119
|
+
- A local directory path (e.g., . for current directory)
|
120
|
+
- An agent name (e.g., adk_base)
|
121
|
+
- A remote template (e.g., adk@data-science)
|
122
|
+
|
123
|
+
The command will validate your project structure and provide guidance if needed.
|
124
|
+
"""
|
125
|
+
|
126
|
+
# Display welcome banner for enhance command
|
127
|
+
display_welcome_banner(enhance_mode=True)
|
128
|
+
|
129
|
+
# Validate base template if provided
|
130
|
+
if base_template and not validate_base_template(base_template):
|
131
|
+
available_templates = get_available_base_templates()
|
132
|
+
console.print(
|
133
|
+
f"Error: Base template '{base_template}' not found.", style="bold red"
|
134
|
+
)
|
135
|
+
console.print(
|
136
|
+
f"Available base templates: {', '.join(available_templates)}",
|
137
|
+
style="yellow",
|
138
|
+
)
|
139
|
+
return
|
140
|
+
|
141
|
+
# Determine project name
|
142
|
+
if name:
|
143
|
+
project_name = name
|
144
|
+
else:
|
145
|
+
# Use current directory name as default
|
146
|
+
current_dir = pathlib.Path.cwd()
|
147
|
+
project_name = current_dir.name
|
148
|
+
console.print(
|
149
|
+
f"Using current directory name as project name: {project_name}", style="dim"
|
150
|
+
)
|
151
|
+
|
152
|
+
# Show confirmation prompt for enhancement unless auto-approved
|
153
|
+
if not auto_approve:
|
154
|
+
current_dir = pathlib.Path.cwd()
|
155
|
+
console.print()
|
156
|
+
console.print(
|
157
|
+
"🚀 [blue]Ready to enhance your project with deployment capabilities[/blue]"
|
158
|
+
)
|
159
|
+
console.print(f"📂 {current_dir}")
|
160
|
+
console.print()
|
161
|
+
console.print("[bold]What will happen:[/bold]")
|
162
|
+
console.print("• New template files will be added to this directory")
|
163
|
+
console.print("• Your existing files will be preserved")
|
164
|
+
console.print("• A backup will be created before any changes")
|
165
|
+
console.print()
|
166
|
+
|
167
|
+
if not click.confirm(
|
168
|
+
f"Continue with enhancement? {click.style('[Y/n]: ', fg='blue', bold=True)}",
|
169
|
+
default=True,
|
170
|
+
show_default=False,
|
171
|
+
):
|
172
|
+
console.print("✋ [yellow]Enhancement cancelled.[/yellow]")
|
173
|
+
return
|
174
|
+
console.print()
|
175
|
+
|
176
|
+
# Determine agent specification based on template_path
|
177
|
+
if template_path == pathlib.Path("."):
|
178
|
+
# Current directory - use local@ syntax
|
179
|
+
agent_spec = "local@."
|
180
|
+
elif template_path.is_dir():
|
181
|
+
# Other local directory
|
182
|
+
agent_spec = f"local@{template_path.resolve()}"
|
183
|
+
else:
|
184
|
+
# Assume it's an agent name or remote spec
|
185
|
+
agent_spec = str(template_path)
|
186
|
+
|
187
|
+
# Show base template inheritance info early for local projects
|
188
|
+
if agent_spec.startswith("local@"):
|
189
|
+
from ..utils.remote_template import (
|
190
|
+
get_base_template_name,
|
191
|
+
load_remote_template_config,
|
192
|
+
)
|
193
|
+
|
194
|
+
# Prepare CLI overrides for base template
|
195
|
+
cli_overrides = {}
|
196
|
+
if base_template:
|
197
|
+
cli_overrides["base_template"] = base_template
|
198
|
+
|
199
|
+
# Load config from current directory for inheritance info
|
200
|
+
current_dir = pathlib.Path.cwd()
|
201
|
+
source_config = load_remote_template_config(current_dir, cli_overrides)
|
202
|
+
original_base_template_name = get_base_template_name(source_config)
|
203
|
+
|
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
|
213
|
+
console.print(
|
214
|
+
f"✅ Selected base template: [cyan]{selected_base_template}[/cyan]"
|
215
|
+
)
|
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()
|
231
|
+
|
232
|
+
# Validate project structure when using current directory template
|
233
|
+
if template_path == pathlib.Path("."):
|
234
|
+
current_dir = pathlib.Path.cwd()
|
235
|
+
app_folder = current_dir / "app"
|
236
|
+
|
237
|
+
if not app_folder.exists() or not app_folder.is_dir():
|
238
|
+
console.print()
|
239
|
+
console.print(
|
240
|
+
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
241
|
+
)
|
242
|
+
console.print("⚠️ [bold yellow]PROJECT STRUCTURE WARNING[/bold yellow] ⚠️")
|
243
|
+
console.print(
|
244
|
+
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
245
|
+
)
|
246
|
+
console.print()
|
247
|
+
console.print(
|
248
|
+
"📁 [bold]Expected Structure:[/bold] [cyan]/app[/cyan] folder containing your agent code"
|
249
|
+
)
|
250
|
+
console.print(f"📍 [bold]Current Directory:[/bold] {current_dir}")
|
251
|
+
console.print("❌ [bold red]Missing:[/bold red] /app folder")
|
252
|
+
console.print()
|
253
|
+
console.print(
|
254
|
+
"[dim]The enhance command can still proceed, but for best compatibility"
|
255
|
+
" your agent code should be organized in an /app folder structure.[/dim]"
|
256
|
+
)
|
257
|
+
console.print()
|
258
|
+
|
259
|
+
# Ask for confirmation after showing the structure warning
|
260
|
+
console.print(
|
261
|
+
"💡 [dim]Consider creating an /app folder for better compatibility.[/dim]"
|
262
|
+
)
|
263
|
+
console.print()
|
264
|
+
|
265
|
+
if not auto_approve:
|
266
|
+
if not click.confirm(
|
267
|
+
"Continue with enhancement despite missing /app folder?",
|
268
|
+
default=True,
|
269
|
+
):
|
270
|
+
console.print("✋ [yellow]Enhancement cancelled.[/yellow]")
|
271
|
+
return
|
272
|
+
else:
|
273
|
+
# Check for common agent files
|
274
|
+
agent_py = app_folder / "agent.py"
|
275
|
+
if agent_py.exists():
|
276
|
+
console.print(
|
277
|
+
"Detected existing agent structure with [cyan]/app/agent.py[/cyan]"
|
278
|
+
)
|
279
|
+
else:
|
280
|
+
console.print(
|
281
|
+
"ℹ️ [blue]Found /app folder[/blue] - ensure your agent code is properly organized within it"
|
282
|
+
)
|
283
|
+
|
284
|
+
# Call the create command with in-folder mode enabled
|
285
|
+
ctx.invoke(
|
286
|
+
create,
|
287
|
+
project_name=project_name,
|
288
|
+
agent=agent_spec,
|
289
|
+
deployment_target=deployment_target,
|
290
|
+
cicd_runner=cicd_runner,
|
291
|
+
include_data_ingestion=include_data_ingestion,
|
292
|
+
datastore=datastore,
|
293
|
+
session_type=session_type,
|
294
|
+
debug=debug,
|
295
|
+
output_dir=None, # Use current directory
|
296
|
+
auto_approve=auto_approve,
|
297
|
+
region=region,
|
298
|
+
skip_checks=skip_checks,
|
299
|
+
in_folder=True, # Always use in-folder mode for enhance
|
300
|
+
base_template=base_template,
|
301
|
+
skip_welcome=True, # Skip welcome message since enhance shows its own
|
302
|
+
)
|
src/cli/commands/list.py
CHANGED
@@ -16,7 +16,7 @@ import logging
|
|
16
16
|
import pathlib
|
17
17
|
|
18
18
|
import click
|
19
|
-
import
|
19
|
+
import tomllib
|
20
20
|
from rich.console import Console
|
21
21
|
from rich.table import Table
|
22
22
|
|
@@ -42,25 +42,37 @@ def display_agents_from_path(base_path: pathlib.Path, source_name: str) -> None:
|
|
42
42
|
return
|
43
43
|
|
44
44
|
found_agents = False
|
45
|
-
# Search for
|
46
|
-
for config_path in sorted(base_path.glob("**/
|
45
|
+
# Search for pyproject.toml files to identify agents (explicit opt-in)
|
46
|
+
for config_path in sorted(base_path.glob("**/pyproject.toml")):
|
47
47
|
try:
|
48
|
-
with open(config_path,
|
49
|
-
|
48
|
+
with open(config_path, "rb") as f:
|
49
|
+
pyproject_data = tomllib.load(f)
|
50
50
|
|
51
|
-
|
52
|
-
|
51
|
+
config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
|
52
|
+
|
53
|
+
# Skip pyproject.toml files that don't have agent-starter-pack config
|
54
|
+
if not config:
|
55
|
+
continue
|
56
|
+
|
57
|
+
template_root = config_path.parent
|
58
|
+
|
59
|
+
# Use fallbacks to [project] section if needed
|
60
|
+
project_info = pyproject_data.get("project", {})
|
61
|
+
agent_name = (
|
62
|
+
config.get("name") or project_info.get("name") or template_root.name
|
63
|
+
)
|
64
|
+
description = (
|
65
|
+
config.get("description") or project_info.get("description") or ""
|
66
|
+
)
|
53
67
|
|
54
68
|
# Display the agent's path relative to the scanned directory
|
55
|
-
relative_path =
|
69
|
+
relative_path = template_root.relative_to(base_path)
|
56
70
|
|
57
71
|
table.add_row(agent_name, f"/{relative_path}", description)
|
58
72
|
found_agents = True
|
59
73
|
|
60
74
|
except Exception as e:
|
61
|
-
logging.warning(
|
62
|
-
f"Could not load agent from {config_path.parent.parent}: {e}"
|
63
|
-
)
|
75
|
+
logging.warning(f"Could not load agent from {config_path.parent}: {e}")
|
64
76
|
|
65
77
|
if not found_agents:
|
66
78
|
console.print(f"No agents found in {source_name}", style="yellow")
|
src/cli/main.py
CHANGED
@@ -18,6 +18,7 @@ import click
|
|
18
18
|
from rich.console import Console
|
19
19
|
|
20
20
|
from .commands.create import create
|
21
|
+
from .commands.enhance import enhance
|
21
22
|
from .commands.list import list_agents
|
22
23
|
from .commands.setup_cicd import setup_cicd
|
23
24
|
from .utils import display_update_message
|
@@ -53,6 +54,7 @@ def cli() -> None:
|
|
53
54
|
|
54
55
|
# Register commands
|
55
56
|
cli.add_command(create)
|
57
|
+
cli.add_command(enhance)
|
56
58
|
cli.add_command(setup_cicd)
|
57
59
|
cli.add_command(list_agents, name="list")
|
58
60
|
|
src/cli/utils/logging.py
CHANGED
@@ -24,6 +24,46 @@ console = Console()
|
|
24
24
|
F = TypeVar("F", bound=Callable[..., Any])
|
25
25
|
|
26
26
|
|
27
|
+
def display_welcome_banner(
|
28
|
+
agent: str | None = None, enhance_mode: bool = False
|
29
|
+
) -> None:
|
30
|
+
"""Display the Agent Starter Pack welcome banner.
|
31
|
+
|
32
|
+
Args:
|
33
|
+
agent: Optional agent specification to customize the welcome message
|
34
|
+
enhance_mode: Whether this is for enhancement mode
|
35
|
+
"""
|
36
|
+
if enhance_mode:
|
37
|
+
console.print(
|
38
|
+
"\n=== Google Cloud Agent Starter Pack 🚀===",
|
39
|
+
style="bold blue",
|
40
|
+
)
|
41
|
+
console.print(
|
42
|
+
"Enhancing your existing project with production-ready agent capabilities!\n",
|
43
|
+
style="green",
|
44
|
+
)
|
45
|
+
elif agent and agent.startswith("adk@"):
|
46
|
+
console.print(
|
47
|
+
"\n=== Welcome to [link=https://github.com/google/adk-samples]google/adk-samples[/link]! ✨ ===",
|
48
|
+
style="bold blue",
|
49
|
+
)
|
50
|
+
console.print(
|
51
|
+
"Powered by [link=https://goo.gle/agent-starter-pack]Google Cloud - Agent Starter Pack [/link]\n",
|
52
|
+
)
|
53
|
+
console.print(
|
54
|
+
"This tool will help you create an end-to-end production-ready AI agent in Google Cloud!\n"
|
55
|
+
)
|
56
|
+
else:
|
57
|
+
console.print(
|
58
|
+
"\n=== Google Cloud Agent Starter Pack 🚀===",
|
59
|
+
style="bold blue",
|
60
|
+
)
|
61
|
+
console.print("Welcome to the Agent Starter Pack!")
|
62
|
+
console.print(
|
63
|
+
"This tool will help you create an end-to-end production-ready AI agent in Google Cloud!\n"
|
64
|
+
)
|
65
|
+
|
66
|
+
|
27
67
|
def handle_cli_error(f: F) -> F:
|
28
68
|
"""Decorator to handle CLI errors gracefully.
|
29
69
|
|
src/cli/utils/remote_template.py
CHANGED
@@ -22,7 +22,7 @@ import tempfile
|
|
22
22
|
from dataclasses import dataclass
|
23
23
|
from typing import Any
|
24
24
|
|
25
|
-
import
|
25
|
+
import tomllib
|
26
26
|
from jinja2 import Environment
|
27
27
|
|
28
28
|
|
@@ -183,27 +183,66 @@ def fetch_remote_template(
|
|
183
183
|
) from e
|
184
184
|
|
185
185
|
|
186
|
-
def load_remote_template_config(
|
187
|
-
|
186
|
+
def load_remote_template_config(
|
187
|
+
template_dir: pathlib.Path, cli_overrides: dict[str, Any] | None = None
|
188
|
+
) -> dict[str, Any]:
|
189
|
+
"""Load template configuration from remote template's pyproject.toml with CLI overrides.
|
190
|
+
|
191
|
+
Loads configuration from [tool.agent-starter-pack] section with fallbacks
|
192
|
+
to [project] section for name and description if not specified. CLI overrides
|
193
|
+
take precedence over all other sources.
|
188
194
|
|
189
195
|
Args:
|
190
196
|
template_dir: Path to template directory
|
197
|
+
cli_overrides: Configuration overrides from CLI (takes highest precedence)
|
191
198
|
|
192
199
|
Returns:
|
193
|
-
Template configuration dictionary
|
200
|
+
Template configuration dictionary with merged sources
|
194
201
|
"""
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
202
|
+
config = {}
|
203
|
+
|
204
|
+
# Start with defaults
|
205
|
+
defaults = {
|
206
|
+
"base_template": "adk_base",
|
207
|
+
"name": template_dir.name,
|
208
|
+
"description": "",
|
209
|
+
}
|
210
|
+
config.update(defaults)
|
211
|
+
|
212
|
+
# Load from pyproject.toml if it exists
|
213
|
+
pyproject_path = template_dir / "pyproject.toml"
|
214
|
+
if pyproject_path.exists():
|
215
|
+
try:
|
216
|
+
with open(pyproject_path, "rb") as f:
|
217
|
+
pyproject_data = tomllib.load(f)
|
218
|
+
|
219
|
+
# Extract the agent-starter-pack configuration
|
220
|
+
toml_config = pyproject_data.get("tool", {}).get("agent-starter-pack", {})
|
221
|
+
|
222
|
+
# Fallback to [project] fields if not specified in agent-starter-pack section
|
223
|
+
project_info = pyproject_data.get("project", {})
|
224
|
+
|
225
|
+
# Apply pyproject.toml configuration (overrides defaults)
|
226
|
+
if toml_config:
|
227
|
+
config.update(toml_config)
|
228
|
+
|
229
|
+
# Apply [project] fallbacks if not already set
|
230
|
+
if "name" not in toml_config and "name" in project_info:
|
231
|
+
config["name"] = project_info["name"]
|
232
|
+
|
233
|
+
if "description" not in toml_config and "description" in project_info:
|
234
|
+
config["description"] = project_info["description"]
|
235
|
+
|
236
|
+
logging.debug(f"Loaded template config from {pyproject_path}")
|
237
|
+
except Exception as e:
|
238
|
+
logging.error(f"Error loading pyproject.toml config: {e}")
|
239
|
+
|
240
|
+
# Apply CLI overrides (highest precedence) using deep merge
|
241
|
+
if cli_overrides:
|
242
|
+
config = merge_template_configs(config, cli_overrides)
|
243
|
+
logging.debug(f"Applied CLI overrides: {cli_overrides}")
|
244
|
+
|
245
|
+
return config
|
207
246
|
|
208
247
|
|
209
248
|
def get_base_template_name(config: dict[str, Any]) -> str:
|