Skip to content

Commit 481c68d

Browse files
committed
feat(cli): add CrewAI migration wizard and smart dependency handling
- Add --migratecrew flag for easy migration from CrewAI projects - Implement environment-aware dependency management - Add automatic UV detection and setup - Update CLI documentation with new features
1 parent 9777a45 commit 481c68d

3 files changed

Lines changed: 259 additions & 33 deletions

File tree

CLI modifications.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# CLI Modifications Documentation
2+
3+
## Recent Changes
4+
5+
### 1. Environment-Aware Dependency Management
6+
The initialization process now intelligently handles dependencies based on the user's environment:
7+
8+
#### Virtual Environment Detection
9+
- Detects if user is in:
10+
- Conda environment (via `CONDA_PREFIX`)
11+
- Python virtual environment (via `VIRTUAL_ENV`)
12+
- No environment
13+
14+
#### UV Integration
15+
- Checks for UV installation
16+
- For venv + UV environments:
17+
```bash
18+
# Automatically runs:
19+
uv lock
20+
uv sync
21+
```
22+
- Shows environment-specific guidance:
23+
- Conda users: Instructions for UV in conda
24+
- Venv users without UV: UV installation steps
25+
- No environment: Full setup instructions
26+
27+
### 2. CrewAI Migration Wizard
28+
Added a new `--migratecrew` flag to facilitate migration from CrewAI projects:
29+
30+
```bash
31+
agentstack init <project_name> --migratecrew
32+
```
33+
34+
#### Features
35+
- Streamlined migration process
36+
- Only asks for essential information:
37+
- Agent names (snake_case)
38+
- Task names (snake_case)
39+
- Task-to-agent assignments
40+
- Provides placeholder comments for:
41+
- Agent roles
42+
- Agent goals
43+
- Agent backstories
44+
- Task descriptions
45+
- Expected outputs
46+
47+
#### Example Placeholders
48+
```python
49+
# Agent
50+
agent['role'] = "# Replace with your CrewAI agent's role:
51+
# Example: agent.role = 'Senior Data Analyst'"
52+
53+
# Task
54+
task['description'] = "# Replace with your CrewAI task's description:
55+
# Example: task.description = 'Analyze monthly sales data'"
56+
```
57+
58+
### 3. Flag Compatibility
59+
Updated flag validation to ensure proper usage:
60+
- `--template`: Cannot be used with `--wizard` or `--migratecrew`
61+
- `--wizard`: Cannot be used with `--template` or `--migratecrew`
62+
- `--migratecrew`: Cannot be used with `--template` or `--wizard`
63+
64+
## Usage Examples
65+
66+
### Standard Project Creation
67+
```bash
68+
agentstack init myproject
69+
```
70+
71+
### Using the Wizard
72+
```bash
73+
agentstack init myproject --wizard
74+
# or
75+
agentstack init myproject -w
76+
```
77+
78+
### Migrating from CrewAI
79+
```bash
80+
agentstack init myproject --migratecrew
81+
# or
82+
agentstack init myproject -m
83+
```
84+
85+
### Using a Template
86+
```bash
87+
agentstack init myproject --template hello_alex
88+
# or
89+
agentstack init myproject -t hello_alex
90+
```
91+
92+
## Next Steps
93+
1. Test the CrewAI migration workflow with real projects
94+
2. Consider adding automatic detection of CrewAI project structure
95+
3. Add more detailed examples in placeholder comments
96+
4. Consider adding validation for CrewAI-specific patterns

agentstack/cli/cli.py

Lines changed: 161 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,30 @@
3737
'openai/o1-preview',
3838
'openai/gpt-4-turbo',
3939
'anthropic/claude-3-opus',
40+
'azure/gpt-4o',
4041
]
4142

4243

4344
def init_project_builder(
4445
slug_name: Optional[str] = None,
4546
template: Optional[str] = None,
4647
use_wizard: bool = False,
48+
migrate_crew: bool = False,
4749
):
48-
if not slug_name and not use_wizard:
50+
if not slug_name and not use_wizard and not migrate_crew:
4951
print(term_color("Project name is required. Use `agentstack init <project_name>`", 'red'))
5052
return
5153

5254
if slug_name and not is_snake_case(slug_name):
5355
print(term_color("Project name must be snake case", 'red'))
5456
return
5557

56-
if template is not None and use_wizard:
57-
print(term_color("Template and wizard flags cannot be used together", 'red'))
58+
if template is not None and (use_wizard or migrate_crew):
59+
print(term_color("Template cannot be used with wizard or migrate flags", 'red'))
60+
return
61+
62+
if use_wizard and migrate_crew:
63+
print(term_color("Cannot use both wizard and migrate flags together", 'red'))
5864
return
5965

6066
template_data = None
@@ -96,6 +102,14 @@ def init_project_builder(
96102
design = ask_design()
97103
tools = ask_tools()
98104

105+
elif migrate_crew:
106+
welcome_message()
107+
project_details = ask_project_details(slug_name)
108+
welcome_message()
109+
framework = ask_framework()
110+
design = ask_migrate_crew()
111+
tools = ask_tools()
112+
99113
else:
100114
welcome_message()
101115
# the user has started a new project; let's give them something to work with
@@ -121,6 +135,19 @@ def init_project_builder(
121135
# Set project path in configuration
122136
conf.set_path(project_details['name'])
123137

138+
# Check virtual environment and UV status
139+
in_conda = os.environ.get('CONDA_PREFIX') is not None
140+
in_venv = os.environ.get('VIRTUAL_ENV') is not None
141+
142+
# Check if UV is installed
143+
has_uv = False
144+
try:
145+
import subprocess
146+
subprocess.run(["uv", "--version"], capture_output=True, check=True)
147+
has_uv = True
148+
except (subprocess.CalledProcessError, FileNotFoundError):
149+
pass
150+
124151
# Add tools if specified
125152
if tools:
126153
for tool_data in tools:
@@ -131,23 +158,60 @@ def init_project_builder(
131158
"🚀 \033[92mAgentStack project generated successfully!\033[0m\n\n"
132159
" Next steps:\n"
133160
f" cd {project_details['name']}\n\n"
134-
" Make sure you have UV installed. This handles the project's dependencies:\n"
135-
" pip install uv\n\n"
136-
" Create and activate virtual environment:\n"
137-
" uv venv\n"
138-
" source .venv/bin/activate\n\n"
139-
" Initialize UV and install dependencies:\n"
140-
" uv lock\n"
141-
" uv sync\n"
142-
#" uv pip install -e .\n\n"
161+
)
162+
163+
if in_venv and has_uv:
164+
# If we're in a venv and have UV, automatically handle dependencies
165+
print("📦 Virtual environment and UV detected! Setting up dependencies automatically...")
166+
os.chdir(project_details['name'])
167+
try:
168+
subprocess.run(["uv", "lock"], check=True)
169+
subprocess.run(["uv", "sync"], check=True)
170+
os.chdir('..')
171+
print("✨ Dependencies installed successfully in your current virtual environment!\n")
172+
except subprocess.CalledProcessError:
173+
os.chdir('..')
174+
print("❌ Failed to install dependencies. You may need to create a new virtual environment:\n"
175+
" uv venv\n"
176+
" source .venv/bin/activate\n"
177+
" uv lock\n"
178+
" uv sync\n")
179+
elif in_conda:
180+
print(
181+
" 📦 Conda environment detected!\n"
182+
" You can use UV directly in your conda environment:\n"
183+
" pip install uv\n"
184+
" uv lock\n"
185+
" uv sync\n\n"
186+
)
187+
elif in_venv:
188+
print(
189+
" 📦 Virtual environment detected!\n"
190+
" Install UV to handle dependencies:\n"
191+
" pip install uv\n"
192+
" uv lock\n"
193+
" uv sync\n\n"
194+
)
195+
else:
196+
print(
197+
" Make sure you have UV installed. This handles the project's dependencies:\n"
198+
" pip install uv\n\n"
199+
" Create and activate virtual environment:\n"
200+
" uv venv\n"
201+
" source .venv/bin/activate\n\n"
202+
" Initialize UV and install dependencies:\n"
203+
" uv lock\n"
204+
" uv sync\n"
205+
)
206+
207+
print(
143208
" You can create a new agent with:\n"
144209
" agentstack generate agent <agent_name>\n\n"
145210
" You can create a new task with:\n"
146211
" agentstack generate task <task_name>\n\n"
147212
" Finally, try running your agent with:\n"
148213
" agentstack run\n\n"
149214
" Run `agentstack quickstart` or `agentstack docs` for next steps.\n"
150-
151215
)
152216

153217

@@ -295,7 +359,7 @@ def ask_design() -> dict:
295359
print(title)
296360

297361
print("""
298-
🪄 welcome to the agent builder wizard!! 🪄
362+
🪄 Welcome to the agent builder wWzard!! 🪄
299363
300364
First we need to create the agents that will work together to accomplish tasks:
301365
""")
@@ -337,6 +401,89 @@ def ask_design() -> dict:
337401
return {'tasks': tasks, 'agents': agents}
338402

339403

404+
def ask_migrate_crew() -> dict:
405+
os.system("cls" if os.name == "nt" else "clear")
406+
title = text2art("CrewAI Migration", font="shimrod")
407+
print(title)
408+
409+
print("""
410+
🚀 Welcome to the CrewAI Migration Wizard!
411+
412+
This wizard will help you migrate your existing CrewAI project to AgentStack.
413+
We'll create placeholders for your agents and tasks - you'll just need to fill in your existing implementations.
414+
""")
415+
416+
make_agent = True
417+
agents = []
418+
while make_agent:
419+
print('---')
420+
print(f"Agent #{len(agents)+1}")
421+
agent = {}
422+
423+
# Only ask for the name, provide placeholders for the rest
424+
agent['name'] = get_validated_input(
425+
"What's the name of this agent from your CrewAI project? (snake_case)",
426+
min_length=3,
427+
snake_case=True
428+
)
429+
430+
agent['role'] = "# Replace with your CrewAI agent's role:\n# Example: agent.role = 'Senior Data Analyst'"
431+
agent['goal'] = "# Replace with your CrewAI agent's goal:\n# Example: agent.goal = 'Analyze and interpret complex data sets'"
432+
agent['backstory'] = "# Replace with your CrewAI agent's backstory:\n# Example: agent.backstory = 'Expert in data analysis with 10 years of experience'"
433+
agent['model'] = PREFERRED_MODELS[0] # Default to first model, can be changed later
434+
435+
agents.append(agent)
436+
make_agent = inquirer.confirm(message="Add another agent from your CrewAI project?")
437+
438+
print('')
439+
for x in range(3):
440+
time.sleep(0.3)
441+
print('.')
442+
print('Great! Agents structure created! Now for the tasks...')
443+
print('')
444+
445+
make_task = True
446+
tasks = []
447+
while make_task:
448+
print('---')
449+
print(f"Task #{len(tasks) + 1}")
450+
task = {}
451+
452+
# Only ask for name and assigned agent
453+
task['name'] = get_validated_input(
454+
"What's the name of this task from your CrewAI project? (snake_case)",
455+
min_length=3,
456+
snake_case=True
457+
)
458+
459+
task['description'] = "# Replace with your CrewAI task's description:\n# Example: task.description = 'Analyze monthly sales data'"
460+
task['expected_output'] = "# Replace with your CrewAI task's expected output:\n# Example: task.expected_output = 'A comprehensive sales analysis report'"
461+
462+
task['agent'] = inquirer.list_input(
463+
message="Which agent should be assigned this task?",
464+
choices=[a['name'] for a in agents],
465+
)
466+
467+
tasks.append(task)
468+
make_task = inquirer.confirm(message="Add another task from your CrewAI project?")
469+
470+
print('')
471+
for x in range(3):
472+
time.sleep(0.3)
473+
print('.')
474+
print('Migration structure created! (ノ>ω<)ノ :。・:*:・゚'★,。・:*:・゚'☆')
475+
476+
print("""
477+
✨ Next Steps:
478+
1. Navigate to your project directory
479+
2. Find the generated agent and task files
480+
3. Replace the placeholder comments with your existing CrewAI implementations
481+
4. Run your migrated project with `agentstack run`
482+
""")
483+
484+
return {'tasks': tasks, 'agents': agents}
485+
486+
340487
def ask_tools() -> list:
341488
use_tools = inquirer.confirm(
342489
message="Do you want to add agent tools now? (you can do this later with `agentstack tools add <tool_name>`)",
@@ -461,24 +608,6 @@ def insert_template(
461608
# os.system("poetry install")
462609
# os.system("cls" if os.name == "nt" else "clear")
463610
# TODO: add `agentstack docs` command
464-
print(
465-
"\n"
466-
"🚀 \033[92mAgentStack project generated successfully!\033[0m\n\n"
467-
" Next steps:\n"
468-
f" cd {project_metadata.project_slug}\n\n"
469-
" Make sure you have UV installed:\n"
470-
" pip install uv\n\n"
471-
" Create and activate virtual environment:\n"
472-
" uv venv\n"
473-
" source .venv/bin/activate\n\n"
474-
" Initialize UV and install dependencies:\n"
475-
" uv lock\n"
476-
" uv sync\n"
477-
" uv pip install -e .\n\n"
478-
" Finally, try running your agent with:\n"
479-
" agentstack run\n\n"
480-
" Run `agentstack quickstart` or `agentstack docs` for next steps.\n"
481-
)
482611

483612

484613
def export_template(output_filename: str):

agentstack/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def main():
5959
)
6060
init_parser.add_argument("slug_name", nargs="?", help="The directory name to place the project in")
6161
init_parser.add_argument("--wizard", "-w", action="store_true", help="Use the setup wizard")
62+
init_parser.add_argument("--migratecrew", "-m", action="store_true", help="Migrate from an existing CrewAI project")
6263
init_parser.add_argument("--template", "-t", help="Agent template to use")
6364

6465
# 'run' command
@@ -166,7 +167,7 @@ def main():
166167
elif args.command in ["templates"]:
167168
webbrowser.open("https://docs.agentstack.sh/quickstart")
168169
elif args.command in ["init", "i"]:
169-
init_project_builder(args.slug_name, args.template, args.wizard)
170+
init_project_builder(args.slug_name, args.template, args.wizard, args.migratecrew)
170171
elif args.command in ["run", "r"]:
171172
run_project(command=args.function, debug=args.debug, cli_args=extra_args)
172173
elif args.command in ['generate', 'g']:

0 commit comments

Comments
 (0)