Skip to content

Commit d77ae7d

Browse files
authored
Merge pull request #281 from tcdent/repo
Automatic git commits for changes.
2 parents 9386961 + 41b4408 commit d77ae7d

File tree

25 files changed

+671
-156
lines changed

25 files changed

+671
-156
lines changed

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: 14 additions & 8 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.proj_templates import get_all_templates, TemplateConfig
1415

1516
from agentstack.cli import welcome_message
@@ -127,18 +128,23 @@ def init_project(
127128
packaging.create_venv()
128129
log.info("Installing dependencies...")
129130
packaging.install_project()
131+
repo.init() # initialize git repo
130132

131133
# now we can interact with the project and add Agents, Tasks, and Tools
132134
# we allow dependencies to be installed along with these, so the project must
133135
# be fully initialized first.
134-
for task in template_data.tasks:
135-
generation.add_task(**task.model_dump())
136-
137-
for agent in template_data.agents:
138-
generation.add_agent(**agent.model_dump())
139-
140-
for tool in template_data.tools:
141-
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())
142148

143149
log.success("🚀 AgentStack project generated successfully!\n")
144150
log.info(

agentstack/cli/run.py

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

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

100101
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:

agentstack/cli/tools.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from typing import Optional
22
import itertools
33
import inquirer
4+
from agentstack import conf
45
from agentstack.utils import term_color
56
from agentstack import generation
7+
from agentstack import repo
68
from agentstack._tools import get_all_tools
79
from agentstack.agents import get_all_agents
810

@@ -43,6 +45,8 @@ def add_tool(tool_name: Optional[str], agents=Optional[list[str]]):
4345
- add the tool to the user's project
4446
- add the tool to the specified agents or all agents if none are specified
4547
"""
48+
conf.assert_project()
49+
4650
if not tool_name:
4751
# ask the user for the tool name
4852
tools_list = [
@@ -71,4 +75,21 @@ def add_tool(tool_name: Optional[str], agents=Optional[list[str]]):
7175
return # user cancelled the prompt
7276

7377
assert tool_name # appease type checker
74-
generation.add_tool(tool_name, agents=agents)
78+
79+
repo.commit_user_changes()
80+
with repo.Transaction() as commit:
81+
commit.add_message(f"Added tool {tool_name}")
82+
generation.add_tool(tool_name, agents=agents)
83+
84+
85+
def remove_tool(tool_name: str):
86+
"""
87+
Remove a tool from the user's project.
88+
"""
89+
conf.assert_project()
90+
91+
repo.commit_user_changes()
92+
with repo.Transaction() as commit:
93+
commit.add_message(f"Removed tool {tool_name}")
94+
generation.remove_tool(tool_name)
95+

agentstack/conf.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
# The path to the project directory ie. working directory.
1515
PATH: Path = Path()
1616

17+
1718
def assert_project() -> None:
1819
try:
1920
ConfigFile()
2021
return
2122
except FileNotFoundError:
2223
raise Exception("Could not find agentstack.json, are you in an AgentStack project directory?")
2324

25+
2426
def set_path(path: Union[str, Path, None]):
2527
"""Set the path to the project directory."""
2628
global PATH
@@ -83,6 +85,8 @@ class ConfigFile(BaseModel):
8385
The template used to generate the project.
8486
template_version: Optional[str]
8587
The version of the template system used to generate the project.
88+
use_git: Optional[bool]
89+
Whether to use git for automatic commits of you project.
8690
"""
8791

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

96101
def __init__(self):
97102
if os.path.exists(PATH / CONFIG_FILENAME):

agentstack/generation/__init__.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1-
from .gen_utils import InsertionPoint, parse_insertion_point
1+
from enum import Enum
22
from .agent_generation import add_agent
33
from .task_generation import add_task
44
from .tool_generation import add_tool, remove_tool
55
from .files import EnvFile, ProjectFile
6+
7+
8+
class InsertionPoint(Enum):
9+
"""
10+
Enum for specifying where to insert generated code.
11+
"""
12+
13+
BEGIN = 'begin'
14+
END = 'end'
15+
16+

0 commit comments

Comments
 (0)