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
6 changes: 4 additions & 2 deletions agentstack/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from .cli import configure_default_model, welcome_message, get_validated_input
from .cli import configure_default_model, welcome_message, get_validated_input, parse_insertion_point
from .init import init_project
from .wizard import run_wizard
from .run import run_project
from .tools import list_tools, add_tool
from .tools import list_tools, add_tool, remove_tool
from .tasks import add_task
from .agents import add_agent
from .templates import insert_template, export_template

34 changes: 34 additions & 0 deletions agentstack/cli/agents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import Optional
from agentstack import conf
from agentstack import repo
from agentstack.cli import configure_default_model, parse_insertion_point
from agentstack import generation


def add_agent(
name: str,
role: Optional[str] = None,
goal: Optional[str] = None,
backstory: Optional[str] = None,
llm: Optional[str] = None,
position: Optional[str] = None,
):
"""
Add an agent to the user's project.
"""
conf.assert_project()
if not llm:
configure_default_model()
_position = parse_insertion_point(position)

repo.commit_user_changes()
with repo.Transaction() as commit:
commit.add_message(f"Added agent {name}")
generation.add_agent(
name=name,
role=role,
goal=goal,
backstory=backstory,
llm=llm,
position=_position,
)
16 changes: 16 additions & 0 deletions agentstack/cli/cli.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from typing import Optional
import os, sys
from art import text2art
import inquirer
from agentstack import conf, log
from agentstack.conf import ConfigFile
from agentstack.exceptions import ValidationError
from agentstack.utils import validator_not_empty, is_snake_case
from agentstack.generation import InsertionPoint


PREFERRED_MODELS = [
Expand Down Expand Up @@ -78,3 +80,17 @@ def get_validated_input(
raise ValidationError("Input must be in snake_case")
return value


def parse_insertion_point(position: Optional[str] = None) -> Optional[InsertionPoint]:
"""
Parse an insertion point CLI argument into an InsertionPoint enum.
"""
if position is None:
return None # defer assumptions

valid_positions = {x.value for x in InsertionPoint}
if position not in valid_positions:
raise ValueError(f"Position must be one of {','.join(valid_positions)}.")

return next(x for x in InsertionPoint if x.value == position)

22 changes: 14 additions & 8 deletions agentstack/cli/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from agentstack import packaging
from agentstack import frameworks
from agentstack import generation
from agentstack import repo
from agentstack.proj_templates import get_all_templates, TemplateConfig

from agentstack.cli import welcome_message
Expand Down Expand Up @@ -127,18 +128,23 @@ def init_project(
packaging.create_venv()
log.info("Installing dependencies...")
packaging.install_project()
repo.init() # initialize git repo

# now we can interact with the project and add Agents, Tasks, and Tools
# we allow dependencies to be installed along with these, so the project must
# be fully initialized first.
for task in template_data.tasks:
generation.add_task(**task.model_dump())

for agent in template_data.agents:
generation.add_agent(**agent.model_dump())

for tool in template_data.tools:
generation.add_tool(**tool.model_dump())
with repo.Transaction() as commit:
for task in template_data.tasks:
commit.add_message(f"Added task {task.name}")
generation.add_task(**task.model_dump())

for agent in template_data.agents:
commit.add_message(f"Added agent {agent.name}")
generation.add_agent(**agent.model_dump())

for tool in template_data.tools:
commit.add_message(f"Added tool {tool.name}")
generation.add_tool(**tool.model_dump())

log.success("🚀 AgentStack project generated successfully!\n")
log.info(
Expand Down
1 change: 1 addition & 0 deletions agentstack/cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def _import_project_module(path: Path):

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

if conf.get_framework() not in frameworks.SUPPORTED_FRAMEWORKS:
Expand Down
30 changes: 30 additions & 0 deletions agentstack/cli/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Optional
from agentstack import conf
from agentstack import repo
from agentstack.cli import parse_insertion_point
from agentstack import generation


def add_task(
name: str,
description: Optional[str] = None,
expected_output: Optional[str] = None,
agent: Optional[str] = None,
position: Optional[str] = None,
):
"""
Add a task to the user's project.
"""
conf.assert_project()
_position = parse_insertion_point(position)

repo.commit_user_changes()
with repo.Transaction() as commit:
commit.add_message(f"Added task {name}")
generation.add_task(
name=name,
description=description,
expected_output=expected_output,
agent=agent,
position=_position,
)
2 changes: 2 additions & 0 deletions agentstack/cli/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def export_template(output_filename: str):
"""
Export the current project as a template.
"""
conf.assert_project()

try:
metadata = ProjectFile()
except Exception as e:
Expand Down
23 changes: 22 additions & 1 deletion agentstack/cli/tools.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from typing import Optional
import itertools
import inquirer
from agentstack import conf
from agentstack.utils import term_color
from agentstack import generation
from agentstack import repo
from agentstack._tools import get_all_tools
from agentstack.agents import get_all_agents

Expand Down Expand Up @@ -43,6 +45,8 @@ def add_tool(tool_name: Optional[str], agents=Optional[list[str]]):
- add the tool to the user's project
- add the tool to the specified agents or all agents if none are specified
"""
conf.assert_project()

if not tool_name:
# ask the user for the tool name
tools_list = [
Expand Down Expand Up @@ -71,4 +75,21 @@ def add_tool(tool_name: Optional[str], agents=Optional[list[str]]):
return # user cancelled the prompt

assert tool_name # appease type checker
generation.add_tool(tool_name, agents=agents)

repo.commit_user_changes()
with repo.Transaction() as commit:
commit.add_message(f"Added tool {tool_name}")
generation.add_tool(tool_name, agents=agents)


def remove_tool(tool_name: str):
"""
Remove a tool from the user's project.
"""
conf.assert_project()

repo.commit_user_changes()
with repo.Transaction() as commit:
commit.add_message(f"Removed tool {tool_name}")
generation.remove_tool(tool_name)

5 changes: 5 additions & 0 deletions agentstack/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
# The path to the project directory ie. working directory.
PATH: Path = Path()


def assert_project() -> None:
try:
ConfigFile()
return
except FileNotFoundError:
raise Exception("Could not find agentstack.json, are you in an AgentStack project directory?")


def set_path(path: Union[str, Path, None]):
"""Set the path to the project directory."""
global PATH
Expand Down Expand Up @@ -83,6 +85,8 @@ class ConfigFile(BaseModel):
The template used to generate the project.
template_version: Optional[str]
The version of the template system used to generate the project.
use_git: Optional[bool]
Whether to use git for automatic commits of you project.
"""

framework: str = DEFAULT_FRAMEWORK # TODO this should probably default to None
Expand All @@ -92,6 +96,7 @@ class ConfigFile(BaseModel):
agentstack_version: Optional[str] = get_version()
template: Optional[str] = None
template_version: Optional[str] = None
use_git: Optional[bool] = True

def __init__(self):
if os.path.exists(PATH / CONFIG_FILENAME):
Expand Down
13 changes: 12 additions & 1 deletion agentstack/generation/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
from .gen_utils import InsertionPoint, parse_insertion_point
from enum import Enum
from .agent_generation import add_agent
from .task_generation import add_task
from .tool_generation import add_tool, remove_tool
from .files import EnvFile, ProjectFile


class InsertionPoint(Enum):
"""
Enum for specifying where to insert generated code.
"""

BEGIN = 'begin'
END = 'end'


11 changes: 6 additions & 5 deletions agentstack/generation/agent_generation.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import sys
from typing import Optional
from typing import TYPE_CHECKING, Optional
from agentstack import log
from agentstack.exceptions import ValidationError
from agentstack.conf import ConfigFile
from agentstack.generation import parse_insertion_point
from agentstack import frameworks
from agentstack.utils import verify_agentstack_project
from agentstack.agents import AgentConfig, AGENTS_FILENAME

if TYPE_CHECKING:
from agentstack.generation import InsertionPoint


def add_agent(
name: str,
Expand All @@ -16,7 +18,7 @@ def add_agent(
backstory: Optional[str] = None,
llm: Optional[str] = None,
allow_delegation: Optional[bool] = None,
position: Optional[str] = None,
position: Optional['InsertionPoint'] = None,
):
agentstack_config = ConfigFile()
verify_agentstack_project()
Expand All @@ -31,9 +33,8 @@ def add_agent(
if allow_delegation:
log.warning("Agent allow_delegation is not implemented.")

_position = parse_insertion_point(position)
try:
frameworks.add_agent(agent, _position)
frameworks.add_agent(agent, position)
except ValidationError as e:
raise ValidationError(f"Error adding agent to project:\n{e}")

Expand Down
95 changes: 0 additions & 95 deletions agentstack/generation/gen_utils.py

This file was deleted.

Loading