Skip to content

Commit 30d3c1f

Browse files
committed
Merge branch 'main' into framework-llamaindex
# Conflicts: # agentstack/cli/init.py
2 parents b388f6c + d77ae7d commit 30d3c1f

29 files changed

Lines changed: 722 additions & 170 deletions

File tree

agentstack/_tools/file_read/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"category": "computer-control",
44
"tools": ["read_file"],
55
"description": "Read contents of files",
6-
"url": "https://github.com/AgentOps-AI/AgentStack/tree/main/agentstack/tools/file_read",
6+
"url": "https://docs.agentstack.sh/tools/tool/file_read",
77
"dependencies": []
88
}

agentstack/cli/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
from .cli import configure_default_model, welcome_message, get_validated_input
1+
from .cli import configure_default_model, welcome_message, get_validated_input, parse_insertion_point
22
from .init import init_project
33
from .wizard import run_wizard
44
from .run import run_project
5-
from .tools import list_tools, add_tool
5+
from .tools import list_tools, add_tool, remove_tool
6+
from .tasks import add_task
7+
from .agents import add_agent
68
from .templates import insert_template, export_template
79

agentstack/cli/agents.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from typing import Optional
2+
from agentstack import conf
3+
from agentstack import repo
4+
from agentstack.cli import configure_default_model, parse_insertion_point
5+
from agentstack import generation
6+
7+
8+
def add_agent(
9+
name: str,
10+
role: Optional[str] = None,
11+
goal: Optional[str] = None,
12+
backstory: Optional[str] = None,
13+
llm: Optional[str] = None,
14+
position: Optional[str] = None,
15+
):
16+
"""
17+
Add an agent to the user's project.
18+
"""
19+
conf.assert_project()
20+
if not llm:
21+
configure_default_model()
22+
_position = parse_insertion_point(position)
23+
24+
repo.commit_user_changes()
25+
with repo.Transaction() as commit:
26+
commit.add_message(f"Added agent {name}")
27+
generation.add_agent(
28+
name=name,
29+
role=role,
30+
goal=goal,
31+
backstory=backstory,
32+
llm=llm,
33+
position=_position,
34+
)

agentstack/cli/cli.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
from typing import Optional
12
import os, sys
23
from art import text2art
34
import inquirer
45
from agentstack import conf, log
56
from agentstack.conf import ConfigFile
67
from agentstack.exceptions import ValidationError
78
from agentstack.utils import validator_not_empty, is_snake_case
9+
from agentstack.generation import InsertionPoint
810

911

1012
PREFERRED_MODELS = [
@@ -78,3 +80,17 @@ def get_validated_input(
7880
raise ValidationError("Input must be in snake_case")
7981
return value
8082

83+
84+
def parse_insertion_point(position: Optional[str] = None) -> Optional[InsertionPoint]:
85+
"""
86+
Parse an insertion point CLI argument into an InsertionPoint enum.
87+
"""
88+
if position is None:
89+
return None # defer assumptions
90+
91+
valid_positions = {x.value for x in InsertionPoint}
92+
if position not in valid_positions:
93+
raise ValueError(f"Position must be one of {','.join(valid_positions)}.")
94+
95+
return next(x for x in InsertionPoint if x.value == position)
96+

agentstack/cli/init.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from agentstack import packaging
1111
from agentstack import frameworks
1212
from agentstack import generation
13+
from agentstack import repo
1314
from agentstack.templates import get_all_templates, TemplateConfig
1415

1516
from agentstack.cli import welcome_message
@@ -76,24 +77,31 @@ def init_project(
7677
- install dependencies
7778
- insert Tasks, Agents and Tools
7879
"""
79-
require_uv()
80-
8180
# TODO prevent the user from passing the --path argument to init
82-
if slug_name:
83-
if not is_snake_case(slug_name):
84-
raise Exception("Project name must be snake_case")
85-
conf.set_path(conf.PATH / slug_name)
86-
else:
87-
raise Exception("No project directory specified.\n Run `agentstack init <project_name>`")
88-
89-
if os.path.exists(conf.PATH): # cookiecutter requires the directory to not exist
90-
raise Exception(f"Directory already exists: {conf.PATH}")
91-
9281
if template and use_wizard:
9382
raise Exception("Template and wizard flags cannot be used together")
9483

84+
require_uv()
9585
welcome_message()
9686

87+
if not slug_name:
88+
log.info(
89+
"Provide a project name. This will be used to create a new directory in the "
90+
"current path and will be used as the project name. 🐍 Must be snake_case."
91+
)
92+
slug_name = inquirer.text(
93+
message="Project name (snake_case)",
94+
)
95+
96+
if not slug_name:
97+
raise Exception("Project name cannot be empty")
98+
if not is_snake_case(slug_name):
99+
raise Exception("Project name must be snake_case")
100+
101+
conf.set_path(conf.PATH / slug_name)
102+
if os.path.exists(conf.PATH): # cookiecutter requires the directory to not exist
103+
raise Exception(f"Directory already exists: {conf.PATH}")
104+
97105
if use_wizard:
98106
log.debug("Initializing new project with wizard.")
99107
template_data = run_wizard(slug_name)
@@ -120,18 +128,23 @@ def init_project(
120128
packaging.create_venv()
121129
log.info("Installing dependencies...")
122130
packaging.install_project()
131+
repo.init() # initialize git repo
123132

124133
# now we can interact with the project and add Agents, Tasks, and Tools
125134
# we allow dependencies to be installed along with these, so the project must
126135
# be fully initialized first.
127-
for task in template_data.tasks:
128-
generation.add_task(**task.model_dump())
129-
130-
for agent in template_data.agents:
131-
generation.add_agent(**agent.model_dump())
132-
133-
for tool in template_data.tools:
134-
generation.add_tool(**tool.model_dump())
136+
with repo.Transaction() as commit:
137+
for task in template_data.tasks:
138+
commit.add_message(f"Added task {task.name}")
139+
generation.add_task(**task.model_dump())
140+
141+
for agent in template_data.agents:
142+
commit.add_message(f"Added agent {agent.name}")
143+
generation.add_agent(**agent.model_dump())
144+
145+
for tool in template_data.tools:
146+
commit.add_message(f"Added tool {tool.name}")
147+
generation.add_tool(**tool.model_dump())
135148

136149
log.success("🚀 AgentStack project generated successfully!\n")
137150
log.info(

agentstack/cli/run.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def _import_project_module(path: Path):
9696

9797
def run_project(command: str = 'run', cli_args: Optional[List[str]] = None):
9898
"""Validate that the project is ready to run and then run it."""
99+
conf.assert_project()
99100
verify_agentstack_project()
100101

101102
if conf.get_framework() not in frameworks.SUPPORTED_FRAMEWORKS:

agentstack/cli/tasks.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from typing import Optional
2+
from agentstack import conf
3+
from agentstack import repo
4+
from agentstack.cli import parse_insertion_point
5+
from agentstack import generation
6+
7+
8+
def add_task(
9+
name: str,
10+
description: Optional[str] = None,
11+
expected_output: Optional[str] = None,
12+
agent: Optional[str] = None,
13+
position: Optional[str] = None,
14+
):
15+
"""
16+
Add a task to the user's project.
17+
"""
18+
conf.assert_project()
19+
_position = parse_insertion_point(position)
20+
21+
repo.commit_user_changes()
22+
with repo.Transaction() as commit:
23+
commit.add_message(f"Added task {name}")
24+
generation.add_task(
25+
name=name,
26+
description=description,
27+
expected_output=expected_output,
28+
agent=agent,
29+
position=_position,
30+
)

agentstack/cli/templates.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def export_template(output_filename: str):
6969
"""
7070
Export the current project as a template.
7171
"""
72+
conf.assert_project()
73+
7274
try:
7375
metadata = ProjectFile()
7476
except Exception as e:

0 commit comments

Comments
 (0)