Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions agent_starter_pack/base_templates/go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ make local-backend # In one terminal
make load-test # In another terminal
```

## Keeping Up-to-Date

To upgrade this project to the latest agent-starter-pack version:

```bash
uvx agent-starter-pack upgrade
```

This intelligently merges updates while preserving your customizations. Use `--dry-run` to preview changes first. See the [upgrade CLI reference](https://googlecloudplatform.github.io/agent-starter-pack/cli/upgrade.html) for details.

## Learn More

- [ADK for Go Documentation](https://google.github.io/adk-docs/)
Expand Down
10 changes: 10 additions & 0 deletions agent_starter_pack/base_templates/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,14 @@ The application provides two levels of observability:
{%- endif %}

See the [observability guide](https://googlecloudplatform.github.io/agent-starter-pack/guide/observability.html) for detailed instructions, example queries, and visualization options.

## Keeping Up-to-Date

To upgrade this project to the latest agent-starter-pack version:

```bash
uvx agent-starter-pack upgrade
```

This intelligently merges updates while preserving your customizations. Use `--dry-run` to preview changes first. See the [upgrade CLI reference](https://googlecloudplatform.github.io/agent-starter-pack/cli/upgrade.html) for details.
{%- endif %}
64 changes: 28 additions & 36 deletions agent_starter_pack/cli/commands/enhance.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
else:
import tomli as tomllib

from ..utils.language import (
detect_language,
get_asp_config_for_language,
)
from ..utils.logging import display_welcome_banner, handle_cli_error
from ..utils.template import (
get_available_agents,
Expand Down Expand Up @@ -66,6 +70,8 @@
def get_project_asp_config(project_dir: pathlib.Path) -> dict[str, Any] | None:
"""Read agent-starter-pack config from project's .asp.toml or pyproject.toml.

Uses shared language utilities for config detection.

For Go projects, config is stored in .asp.toml under [project].
For Python projects, config is stored in pyproject.toml under [tool.agent-starter-pack].

Expand All @@ -77,45 +83,31 @@ def get_project_asp_config(project_dir: pathlib.Path) -> dict[str, Any] | None:
The returned dict has a consistent structure with keys:
- base_template, asp_version, agent_directory, create_params, language
"""
# First, check for .asp.toml (Go projects)
asp_toml_path = project_dir / ".asp.toml"
if asp_toml_path.exists():
try:
with open(asp_toml_path, "rb") as f:
asp_data = tomllib.load(f)

# Config is stored under [project] in .asp.toml
project_config = asp_data.get("project", {})
if project_config:
# Normalize to match pyproject.toml structure
return {
"base_template": project_config.get("base_template"),
"asp_version": project_config.get("version"),
"agent_directory": project_config.get("agent_directory", "agent"),
"language": project_config.get("language", "go"),
"create_params": {
"deployment_target": project_config.get("deployment_target"),
"cicd_runner": project_config.get("cicd_runner"),
},
}
except Exception as e:
logging.debug(f"Could not read config from .asp.toml: {e}")

# Fall back to pyproject.toml (Python projects)
pyproject_path = project_dir / "pyproject.toml"
if not pyproject_path.exists():
return None
# Detect language first
language = detect_language(project_dir)

try:
with open(pyproject_path, "rb") as f:
pyproject_data = tomllib.load(f)

# Config is stored under [tool.agent-starter-pack]
return pyproject_data.get("tool", {}).get("agent-starter-pack")
except Exception as e:
logging.debug(f"Could not read config from pyproject.toml: {e}")
# Get config using shared utility
config = get_asp_config_for_language(project_dir, language)
if not config:
return None

# For Go projects, normalize the config structure
if language == "go":
return {
"base_template": config.get("base_template"),
"asp_version": config.get("version"),
"agent_directory": config.get("agent_directory", "agent"),
"language": config.get("language", "go"),
"create_params": {
"deployment_target": config.get("deployment_target"),
"cicd_runner": config.get("cicd_runner"),
},
}

# For Python, add language key and return as-is
config["language"] = language
return config


def _should_skip_config_value(value: Any) -> bool:
"""Check if a config value should be skipped (empty, none, skip, etc.)."""
Expand Down
127 changes: 5 additions & 122 deletions agent_starter_pack/cli/commands/extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
from jinja2 import Environment, FileSystemLoader, StrictUndefined
from rich.console import Console

from ..utils.language import (
LANGUAGE_CONFIGS,
detect_language,
get_asp_config_for_language,
)
from ..utils.logging import handle_cli_error

# Path to base templates directory
Expand Down Expand Up @@ -83,36 +88,6 @@
"langgraph",
}

# =============================================================================
# Language Configuration
# =============================================================================
# To add a new language, add an entry with the required keys.

LANGUAGE_CONFIGS: dict[str, dict[str, Any]] = {
"python": {
"detection_files": ["pyproject.toml"],
"config_file": "pyproject.toml",
"config_path": ["tool", "agent-starter-pack"],
"project_files": ["pyproject.toml"],
"lock_file": "uv.lock",
"lock_command": ["uv", "lock"],
"lock_command_name": "uv lock",
"strip_dependencies": True,
"display_name": "Python",
},
"go": {
"detection_files": ["go.mod"],
"config_file": ".asp.toml",
"config_path": ["project"],
"project_files": ["go.mod", "go.sum", ".asp.toml"],
"lock_file": "go.sum",
"lock_command": ["go", "mod", "tidy"],
"lock_command_name": "go mod tidy",
"strip_dependencies": False,
"display_name": "Go",
},
}


def get_asp_config(project_dir: pathlib.Path) -> dict[str, Any] | None:
"""Read agent-starter-pack config from project's pyproject.toml.
Expand Down Expand Up @@ -170,98 +145,6 @@ def detect_agent_directory(
return "app" # Default fallback


def detect_language(project_dir: pathlib.Path) -> str:
"""Detect the project language using LANGUAGE_CONFIGS.

Detection order:
1. Check .asp.toml for explicit language field
2. Check for language-specific detection files (go.mod, pyproject.toml, etc.)
3. Default to Python

Args:
project_dir: Path to the project directory

Returns:
Language key (e.g., 'python', 'go')
"""
# First, check .asp.toml for explicit language declaration
asp_toml_path = project_dir / ".asp.toml"
if asp_toml_path.exists():
try:
with open(asp_toml_path, "rb") as f:
asp_data = tomllib.load(f)
language = asp_data.get("project", {}).get("language")
if language and language in LANGUAGE_CONFIGS:
return language
except Exception:
pass

# Check each language's detection files (non-Python first to avoid false positives)
# Python has pyproject.toml which is common, so check other languages first
for lang in ["go", "python"]: # Order matters: more specific first
config = LANGUAGE_CONFIGS.get(lang)
if config:
for detection_file in config.get("detection_files", []):
if (project_dir / detection_file).exists():
# For Python, also need to check it's not just a pyproject.toml
# for a Go project (Go projects don't have pyproject.toml)
if lang == "python":
# Only return python if no other language indicators exist
return lang
return lang

# Default to Python
return "python"


def get_asp_config_for_language(
project_dir: pathlib.Path, language: str
) -> dict[str, Any] | None:
"""Read ASP config based on language configuration.

Uses LANGUAGE_CONFIGS to determine where to look for config.

Args:
project_dir: Path to the project directory
language: Language key (e.g., 'python', 'go')

Returns:
The ASP config dict if found, None otherwise
"""
lang_config = LANGUAGE_CONFIGS.get(language)
if not lang_config:
return None

config_file = lang_config.get("config_file")
config_path = lang_config.get("config_path", [])

if not config_file:
return None

config_file_path = project_dir / config_file
if not config_file_path.exists():
return None

try:
with open(config_file_path, "rb") as f:
data = tomllib.load(f)

# Navigate to the config path (e.g., ["tool", "agent-starter-pack"])
result = data
for key in config_path:
if isinstance(result, dict):
result = result.get(key)
else:
return None
if result is None:
return None

return result if isinstance(result, dict) else None
except Exception as e:
logging.debug(f"Could not read config from {config_file}: {e}")
return None


def copy_project_files(
source_dir: pathlib.Path,
output_dir: pathlib.Path,
Expand Down
Loading