Skip to content

Commit 0ddad90

Browse files
committed
enforce snake_case
1 parent 8fc43ee commit 0ddad90

File tree

3 files changed

+70
-38
lines changed

3 files changed

+70
-38
lines changed

agentstack/cli/cli.py

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
from .agentstack_data import FrameworkData, ProjectMetadata, ProjectStructure, CookiecutterData
1515
from agentstack.logger import log
1616
from .. import generation
17-
from ..utils import open_json_file, term_color
17+
from ..utils import open_json_file, term_color, is_snake_case
1818

1919

2020
def init_project_builder(slug_name: Optional[str] = None, skip_wizard: bool = False):
21+
if slug_name and not is_snake_case(slug_name):
22+
print(term_color("Project name must be snake case", 'red'))
23+
return
24+
2125
if skip_wizard:
2226
project_details = {
2327
"name": slug_name or "new_agentstack_project",
@@ -118,24 +122,30 @@ def ask_design() -> dict:
118122
while make_agent:
119123
print('---')
120124
print(f"Agent #{len(agents)+1}")
121-
agent = inquirer.prompt([
122-
inquirer.Text("name", message="What's the name of this agent? (snake_case)"),
123-
inquirer.Text("role", message="What role does this agent have?"),
124-
inquirer.Text("goal", message="What is the goal of the agent?"),
125-
inquirer.Text("backstory", message="Give your agent a backstory"),
126-
# TODO: make a list #2
127-
inquirer.Text('model', message="What LLM should this agent use? (any LiteLLM provider)", default="openai/gpt-4"),
128-
# inquirer.List("model", message="What LLM should this agent use? (any LiteLLM provider)", choices=[
129-
# 'mixtral_llm',
130-
# 'mixtral_llm',
131-
# ]),
132-
inquirer.Confirm(
133-
"another",
134-
message="Create another agent?"
135-
),
136-
])
137-
138-
make_agent = agent['another']
125+
126+
agent_incomplete = True
127+
agent = None
128+
while agent_incomplete:
129+
agent = inquirer.prompt([
130+
inquirer.Text("name", message="What's the name of this agent? (snake_case)"),
131+
inquirer.Text("role", message="What role does this agent have?"),
132+
inquirer.Text("goal", message="What is the goal of the agent?"),
133+
inquirer.Text("backstory", message="Give your agent a backstory"),
134+
# TODO: make a list - #2
135+
inquirer.Text('model', message="What LLM should this agent use? (any LiteLLM provider)", default="openai/gpt-4"),
136+
# inquirer.List("model", message="What LLM should this agent use? (any LiteLLM provider)", choices=[
137+
# 'mixtral_llm',
138+
# 'mixtral_llm',
139+
# ]),
140+
])
141+
142+
if not is_snake_case(agent['name']):
143+
print(term_color("Error: Agent name must be snake case - Try again", 'red'))
144+
agent_incomplete = True
145+
else:
146+
agent_incomplete = False
147+
148+
make_agent = inquirer.confirm(message="Create another agent?")
139149
agents.append(agent)
140150

141151
print('')
@@ -153,20 +163,26 @@ def ask_design() -> dict:
153163
while make_task:
154164
print('---')
155165
print(f"Task #{len(tasks) + 1}")
156-
task = inquirer.prompt([
157-
inquirer.Text("name", message="What's the name of this task?"),
158-
inquirer.Text("description", message="Describe the task in more detail"),
159-
inquirer.Text("expected_output",
160-
message="What do you expect the result to look like? (ex: A 5 bullet point summary of the email)"),
161-
inquirer.List("agent", message="Which agent should be assigned this task?",
162-
choices=[a['name'] for a in agents], ),
163-
inquirer.Confirm(
164-
"another",
165-
message="Create another task?"
166-
),
167-
])
168-
169-
make_task = task['another']
166+
167+
task_incomplete = True
168+
task = None
169+
while task_incomplete:
170+
task = inquirer.prompt([
171+
inquirer.Text("name", message="What's the name of this task? (snake_case)"),
172+
inquirer.Text("description", message="Describe the task in more detail"),
173+
inquirer.Text("expected_output",
174+
message="What do you expect the result to look like? (ex: A 5 bullet point summary of the email)"),
175+
inquirer.List("agent", message="Which agent should be assigned this task?",
176+
choices=[a['name'] for a in agents], ),
177+
])
178+
179+
if not is_snake_case(task['name']):
180+
print(term_color("Error: Task name must be snake case - Try again", 'red'))
181+
task_incomplete = True
182+
else:
183+
task_incomplete = False
184+
185+
make_task = inquirer.confirm(message="Create another task?")
170186
tasks.append(task)
171187

172188
print('')
@@ -220,14 +236,18 @@ def ask_tools() -> list:
220236

221237

222238
def ask_project_details(slug_name: Optional[str] = None) -> dict:
223-
questions = [
239+
questions = inquirer.prompt([
224240
inquirer.Text("name", message="What's the name of your project (snake_case)", default=slug_name or ''),
225241
inquirer.Text("version", message="What's the initial version", default="0.1.0"),
226242
inquirer.Text("description", message="Enter a description for your project"),
227243
inquirer.Text("author", message="Who's the author (your name)?"),
228-
]
244+
])
245+
246+
if not is_snake_case(questions['name']):
247+
print(term_color("Project name must be snake case", 'red'))
248+
return ask_project_details(slug_name)
229249

230-
return inquirer.prompt(questions)
250+
return questions
231251

232252

233253
def insert_template(project_details: dict, framework_name: str, design: dict):

agentstack/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,8 @@ def term_color(text: str, color: str) -> str:
7070
return "\033[92m{}\033[00m".format(text)
7171
else:
7272
return text
73+
74+
75+
def is_snake_case(string: str):
76+
return bool(re.match('^[a-z0-9_]+$', string))
77+

tests/test_utils.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
22

3-
from agentstack.utils import clean_input
3+
from agentstack.utils import clean_input, is_snake_case
44

55

66
class TestUtils(unittest.TestCase):
@@ -10,4 +10,11 @@ def test_clean_input_no_change(self):
1010

1111
def test_clean_input_remove_space(self):
1212
cleaned = clean_input('test project')
13-
self.assertEqual('test_project', cleaned)
13+
self.assertEqual('test_project', cleaned)
14+
15+
def test_is_snake_case(self):
16+
assert is_snake_case("hello_world")
17+
assert not is_snake_case("HelloWorld")
18+
assert not is_snake_case("Hello-World")
19+
assert not is_snake_case("hello-world")
20+
assert not is_snake_case("hello world")

0 commit comments

Comments
 (0)