Skip to content

Commit b709f03

Browse files
committed
Allow the user to select a built-in template or use an empty one on init.
1 parent 1ef2fda commit b709f03

File tree

5 files changed

+44
-18
lines changed

5 files changed

+44
-18
lines changed

agentstack/cli/init.py

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
import os, sys
22
from typing import Optional
33
from pathlib import Path
4+
import inquirer
5+
from textwrap import shorten
46

57
from agentstack import conf, log
68
from agentstack.exceptions import EnvironmentError
79
from agentstack.utils import is_snake_case
810
from agentstack import packaging
911
from agentstack import frameworks
1012
from agentstack import generation
11-
from agentstack.proj_templates import TemplateConfig
13+
from agentstack.proj_templates import get_all_templates, TemplateConfig
1214

1315
from agentstack.cli import welcome_message
1416
from agentstack.cli.wizard import run_wizard
1517
from agentstack.cli.templates import insert_template
1618

17-
DEFAULT_TEMPLATE_NAME: str = "hello_alex"
18-
1919

2020
def require_uv():
2121
try:
2222
uv_bin = packaging.get_uv_bin()
2323
assert os.path.exists(uv_bin)
2424
except (AssertionError, ImportError):
25-
message = "Error: uv is not installed.\n"
26-
message += "Full installation instructions at: https://docs.astral.sh/uv/getting-started/installation\n"
25+
message = (
26+
"Error: uv is not installed.\n"
27+
"Full installation instructions at: "
28+
"https://docs.astral.sh/uv/getting-started/installation\n"
29+
)
2730
match sys.platform:
2831
case 'linux' | 'darwin':
2932
message += "Hint: run `curl -LsSf https://astral.sh/uv/install.sh | sh`\n"
@@ -32,6 +35,28 @@ def require_uv():
3235
raise EnvironmentError(message)
3336

3437

38+
def select_template(slug_name: str, framework: Optional[str] = None) -> TemplateConfig:
39+
"""Let the user select a template from the ones available."""
40+
templates: list[TemplateConfig] = get_all_templates()
41+
template_names = [shorten(f"{t.name} - {t.description}", 80) for t in templates]
42+
43+
empty_msg = "Start with an empty project"
44+
template_choice = inquirer.list_input(
45+
message="Which template would you like to use?",
46+
choices=[empty_msg] + template_names,
47+
)
48+
template_name = template_choice.split(" - ")[0]
49+
50+
if template_name == empty_msg:
51+
return TemplateConfig(
52+
name=slug_name,
53+
description="",
54+
framework=framework or frameworks.DEFAULT_FRAMEWORK,
55+
)
56+
57+
return TemplateConfig.from_template_name(template_name)
58+
59+
3560
def init_project(
3661
slug_name: Optional[str] = None,
3762
template: Optional[str] = None,
@@ -61,16 +86,16 @@ def init_project(
6186

6287
if template and use_wizard:
6388
raise Exception("Template and wizard flags cannot be used together")
64-
89+
6590
if use_wizard:
6691
log.debug("Initializing new project with wizard.")
6792
template_data = run_wizard(slug_name)
6893
elif template:
6994
log.debug(f"Initializing new project with template: {template}")
7095
template_data = TemplateConfig.from_user_input(template)
7196
else:
72-
log.debug(f"Initializing new project with default template: {DEFAULT_TEMPLATE_NAME}")
73-
template_data = TemplateConfig.from_template_name(DEFAULT_TEMPLATE_NAME)
97+
log.debug("Initializing new project with template selection.")
98+
template_data = select_template(slug_name, framework)
7499

75100
welcome_message()
76101
log.notify("🦾 Creating a new AgentStack project...")
@@ -81,15 +106,15 @@ def init_project(
81106
if not framework in frameworks.SUPPORTED_FRAMEWORKS:
82107
raise Exception(f"Framework '{framework}' is not supported.")
83108
log.info(f"Using framework: {framework}")
84-
109+
85110
# copy the project skeleton, create a virtual environment, and install dependencies
86111
# project template is populated before the venv is created so we have a working directory
87112
insert_template(name=slug_name, template=template_data, framework=framework)
88113
log.info("Creating virtual environment...")
89114
packaging.create_venv()
90115
log.info("Installing dependencies...")
91116
packaging.install_project()
92-
117+
93118
# now we can interact with the project and add Agents, Tasks, and Tools
94119
# we allow dependencies to be installed along with these, so the project must
95120
# be fully initialized first.

agentstack/frameworks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
CREWAI,
2121
LANGGRAPH,
2222
]
23+
DEFAULT_FRAMEWORK = CREWAI
2324

2425

2526
class FrameworkModule(Protocol):

agentstack/proj_templates.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,15 @@ class Node(pydantic.BaseModel):
196196

197197
name: str
198198
description: str
199-
template_version: Literal[4]
199+
template_version: Literal[4] = CURRENT_VERSION
200200
framework: str
201-
method: str
201+
method: str = "sequential"
202202
manager_agent: Optional[str] = None
203-
agents: list[Agent]
204-
tasks: list[Task]
205-
tools: list[Tool]
206-
graph: list[list[Node]]
207-
inputs: dict[str, str] = {}
203+
agents: list[Agent] = pydantic.Field(default_factory=list)
204+
tasks: list[Task] = pydantic.Field(default_factory=list)
205+
tools: list[Tool] = pydantic.Field(default_factory=list)
206+
graph: list[list[Node]] = pydantic.Field(default_factory=list)
207+
inputs: dict[str, str] = pydantic.Field(default_factory=dict)
208208

209209
@pydantic.field_validator('graph')
210210
@classmethod
File renamed without changes.

agentstack/templates/proj_templates/hello_alex.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hello_alex",
3-
"description": "This is the start of your AgentStack project.",
3+
"description": "A simple example that opens the README and offers suggestions.",
44
"template_version": 1,
55
"framework": "crewai",
66
"agents": [{

0 commit comments

Comments
 (0)