From 0ddad90f89214e93a30df010198994de929bf2e3 Mon Sep 17 00:00:00 2001 From: Braelyn Boynton Date: Wed, 30 Oct 2024 13:24:37 -0700 Subject: [PATCH] enforce snake_case --- agentstack/cli/cli.py | 92 ++++++++++++++++++++++++++----------------- agentstack/utils.py | 5 +++ tests/test_utils.py | 11 +++++- 3 files changed, 70 insertions(+), 38 deletions(-) diff --git a/agentstack/cli/cli.py b/agentstack/cli/cli.py index ea600d4..ac4ecd8 100644 --- a/agentstack/cli/cli.py +++ b/agentstack/cli/cli.py @@ -14,10 +14,14 @@ from .agentstack_data import FrameworkData, ProjectMetadata, ProjectStructure, CookiecutterData from agentstack.logger import log from .. import generation -from ..utils import open_json_file, term_color +from ..utils import open_json_file, term_color, is_snake_case def init_project_builder(slug_name: Optional[str] = None, skip_wizard: bool = False): + if slug_name and not is_snake_case(slug_name): + print(term_color("Project name must be snake case", 'red')) + return + if skip_wizard: project_details = { "name": slug_name or "new_agentstack_project", @@ -118,24 +122,30 @@ def ask_design() -> dict: while make_agent: print('---') print(f"Agent #{len(agents)+1}") - agent = inquirer.prompt([ - inquirer.Text("name", message="What's the name of this agent? (snake_case)"), - inquirer.Text("role", message="What role does this agent have?"), - inquirer.Text("goal", message="What is the goal of the agent?"), - inquirer.Text("backstory", message="Give your agent a backstory"), - # TODO: make a list #2 - inquirer.Text('model', message="What LLM should this agent use? (any LiteLLM provider)", default="openai/gpt-4"), - # inquirer.List("model", message="What LLM should this agent use? (any LiteLLM provider)", choices=[ - # 'mixtral_llm', - # 'mixtral_llm', - # ]), - inquirer.Confirm( - "another", - message="Create another agent?" - ), - ]) - - make_agent = agent['another'] + + agent_incomplete = True + agent = None + while agent_incomplete: + agent = inquirer.prompt([ + inquirer.Text("name", message="What's the name of this agent? (snake_case)"), + inquirer.Text("role", message="What role does this agent have?"), + inquirer.Text("goal", message="What is the goal of the agent?"), + inquirer.Text("backstory", message="Give your agent a backstory"), + # TODO: make a list - #2 + inquirer.Text('model', message="What LLM should this agent use? (any LiteLLM provider)", default="openai/gpt-4"), + # inquirer.List("model", message="What LLM should this agent use? (any LiteLLM provider)", choices=[ + # 'mixtral_llm', + # 'mixtral_llm', + # ]), + ]) + + if not is_snake_case(agent['name']): + print(term_color("Error: Agent name must be snake case - Try again", 'red')) + agent_incomplete = True + else: + agent_incomplete = False + + make_agent = inquirer.confirm(message="Create another agent?") agents.append(agent) print('') @@ -153,20 +163,26 @@ def ask_design() -> dict: while make_task: print('---') print(f"Task #{len(tasks) + 1}") - task = inquirer.prompt([ - inquirer.Text("name", message="What's the name of this task?"), - inquirer.Text("description", message="Describe the task in more detail"), - inquirer.Text("expected_output", - message="What do you expect the result to look like? (ex: A 5 bullet point summary of the email)"), - inquirer.List("agent", message="Which agent should be assigned this task?", - choices=[a['name'] for a in agents], ), - inquirer.Confirm( - "another", - message="Create another task?" - ), - ]) - - make_task = task['another'] + + task_incomplete = True + task = None + while task_incomplete: + task = inquirer.prompt([ + inquirer.Text("name", message="What's the name of this task? (snake_case)"), + inquirer.Text("description", message="Describe the task in more detail"), + inquirer.Text("expected_output", + message="What do you expect the result to look like? (ex: A 5 bullet point summary of the email)"), + inquirer.List("agent", message="Which agent should be assigned this task?", + choices=[a['name'] for a in agents], ), + ]) + + if not is_snake_case(task['name']): + print(term_color("Error: Task name must be snake case - Try again", 'red')) + task_incomplete = True + else: + task_incomplete = False + + make_task = inquirer.confirm(message="Create another task?") tasks.append(task) print('') @@ -220,14 +236,18 @@ def ask_tools() -> list: def ask_project_details(slug_name: Optional[str] = None) -> dict: - questions = [ + questions = inquirer.prompt([ inquirer.Text("name", message="What's the name of your project (snake_case)", default=slug_name or ''), inquirer.Text("version", message="What's the initial version", default="0.1.0"), inquirer.Text("description", message="Enter a description for your project"), inquirer.Text("author", message="Who's the author (your name)?"), - ] + ]) + + if not is_snake_case(questions['name']): + print(term_color("Project name must be snake case", 'red')) + return ask_project_details(slug_name) - return inquirer.prompt(questions) + return questions def insert_template(project_details: dict, framework_name: str, design: dict): diff --git a/agentstack/utils.py b/agentstack/utils.py index d9309b8..b7a12c0 100644 --- a/agentstack/utils.py +++ b/agentstack/utils.py @@ -70,3 +70,8 @@ def term_color(text: str, color: str) -> str: return "\033[92m{}\033[00m".format(text) else: return text + + +def is_snake_case(string: str): + return bool(re.match('^[a-z0-9_]+$', string)) + diff --git a/tests/test_utils.py b/tests/test_utils.py index 0b0fc51..720965d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,6 +1,6 @@ import unittest -from agentstack.utils import clean_input +from agentstack.utils import clean_input, is_snake_case class TestUtils(unittest.TestCase): @@ -10,4 +10,11 @@ def test_clean_input_no_change(self): def test_clean_input_remove_space(self): cleaned = clean_input('test project') - self.assertEqual('test_project', cleaned) \ No newline at end of file + self.assertEqual('test_project', cleaned) + + def test_is_snake_case(self): + assert is_snake_case("hello_world") + assert not is_snake_case("HelloWorld") + assert not is_snake_case("Hello-World") + assert not is_snake_case("hello-world") + assert not is_snake_case("hello world")