mdan-cli 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +48 -1
- package/README.md +123 -0
- package/cli/mdan.py +38 -4
- package/cli/mdan_crewai.py +539 -0
- package/core/crewai_orchestrator.md +419 -0
- package/integrations/__init__.py +33 -0
- package/integrations/crewai/__init__.py +27 -0
- package/integrations/crewai/agents/__init__.py +21 -0
- package/integrations/crewai/agents/architect_agent.py +264 -0
- package/integrations/crewai/agents/dev_agent.py +271 -0
- package/integrations/crewai/agents/devops_agent.py +421 -0
- package/integrations/crewai/agents/doc_agent.py +388 -0
- package/integrations/crewai/agents/product_agent.py +203 -0
- package/integrations/crewai/agents/security_agent.py +386 -0
- package/integrations/crewai/agents/test_agent.py +358 -0
- package/integrations/crewai/agents/ux_agent.py +257 -0
- package/integrations/crewai/flows/__init__.py +13 -0
- package/integrations/crewai/flows/auto_flow.py +451 -0
- package/integrations/crewai/flows/build_flow.py +297 -0
- package/integrations/crewai/flows/debate_flow.py +422 -0
- package/integrations/crewai/flows/discovery_flow.py +267 -0
- package/integrations/crewai/orchestrator.py +558 -0
- package/integrations/crewai/skills/__init__.py +8 -0
- package/integrations/crewai/skills/skill_router.py +534 -0
- package/integrations/crewai/tools/__init__.py +11 -0
- package/integrations/crewai/tools/file_tool.py +355 -0
- package/integrations/crewai/tools/serper_tool.py +169 -0
- package/integrations/crewai/tools/sql_tool.py +435 -0
- package/package.json +1 -1
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""MDAN CrewAI CLI - CrewAI integration commands"""
|
|
3
|
+
|
|
4
|
+
import asyncio
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import click
|
|
12
|
+
except ImportError:
|
|
13
|
+
print("Error: Click is required. Install with: pip install click")
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
|
|
16
|
+
# CrewAI imports - will be loaded lazily
|
|
17
|
+
CREWAI_AVAILABLE = False
|
|
18
|
+
try:
|
|
19
|
+
from integrations.crewai.orchestrator import CrewAIOrchestrator
|
|
20
|
+
from integrations.crewai.skills.skill_router import SkillRouter
|
|
21
|
+
|
|
22
|
+
CREWAI_AVAILABLE = True
|
|
23
|
+
except ImportError:
|
|
24
|
+
CREWAI_AVAILABLE = False
|
|
25
|
+
|
|
26
|
+
# Colors
|
|
27
|
+
GREEN = "\033[0;32m"
|
|
28
|
+
RED = "\033[0;31m"
|
|
29
|
+
YELLOW = "\033[1;33m"
|
|
30
|
+
CYAN = "\033[0;36m"
|
|
31
|
+
MAGENTA = "\033[0;35m"
|
|
32
|
+
BOLD = "\033[1m"
|
|
33
|
+
NC = "\033[0m"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def run_async(coro):
|
|
37
|
+
"""Run async coroutine in sync context."""
|
|
38
|
+
try:
|
|
39
|
+
loop = asyncio.get_event_loop()
|
|
40
|
+
except RuntimeError:
|
|
41
|
+
loop = asyncio.new_event_loop()
|
|
42
|
+
asyncio.set_event_loop(loop)
|
|
43
|
+
return loop.run_until_complete(coro)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@click.group(name="crewai")
|
|
47
|
+
def crewai_cli():
|
|
48
|
+
"""CrewAI integration commands for MDAN."""
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@crewai_cli.command()
|
|
53
|
+
@click.option(
|
|
54
|
+
"--project-path", default=".", help="Project path (default: current directory)"
|
|
55
|
+
)
|
|
56
|
+
def init(project_path):
|
|
57
|
+
"""Initialize CrewAI in a project."""
|
|
58
|
+
project_path = Path(project_path).resolve()
|
|
59
|
+
|
|
60
|
+
click.echo(f"{CYAN}🚀 Initializing CrewAI in: {BOLD}{project_path}{NC}")
|
|
61
|
+
|
|
62
|
+
# Create crewai_config.yaml if it doesn't exist
|
|
63
|
+
config_file = project_path / "crewai_config.yaml"
|
|
64
|
+
|
|
65
|
+
if config_file.exists():
|
|
66
|
+
click.echo(f"{YELLOW}⚠️ CrewAI config already exists at {config_file}{NC}")
|
|
67
|
+
click.echo(f" {BOLD}Next:{NC} Edit the config file to customize your setup")
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
default_config = """# CrewAI Configuration for MDAN
|
|
71
|
+
# Copy this file and customize for your project
|
|
72
|
+
|
|
73
|
+
# LLM Configuration
|
|
74
|
+
llm:
|
|
75
|
+
provider: "openai" # openai, anthropic, local
|
|
76
|
+
model: "gpt-4"
|
|
77
|
+
temperature: 0.7
|
|
78
|
+
max_tokens: 4096
|
|
79
|
+
|
|
80
|
+
# Database Configuration (optional)
|
|
81
|
+
database:
|
|
82
|
+
type: "sqlite" # postgresql, mysql, sqlserver, sqlite
|
|
83
|
+
host: "localhost"
|
|
84
|
+
port: 5432
|
|
85
|
+
database: "mdan_db"
|
|
86
|
+
username: ""
|
|
87
|
+
password: ""
|
|
88
|
+
|
|
89
|
+
# Serper API Key (for web search)
|
|
90
|
+
serper_api_key: "${SERPER_API_KEY}"
|
|
91
|
+
|
|
92
|
+
# Auto Mode Settings
|
|
93
|
+
auto_mode:
|
|
94
|
+
enabled: true
|
|
95
|
+
save_context: true
|
|
96
|
+
context_save_threshold: 0.8 # Save at 80% token usage
|
|
97
|
+
|
|
98
|
+
# Agent Settings
|
|
99
|
+
agents:
|
|
100
|
+
product:
|
|
101
|
+
enabled: true
|
|
102
|
+
verbose: true
|
|
103
|
+
architect:
|
|
104
|
+
enabled: true
|
|
105
|
+
verbose: true
|
|
106
|
+
ux:
|
|
107
|
+
enabled: true
|
|
108
|
+
verbose: true
|
|
109
|
+
dev:
|
|
110
|
+
enabled: true
|
|
111
|
+
verbose: true
|
|
112
|
+
test:
|
|
113
|
+
enabled: true
|
|
114
|
+
verbose: true
|
|
115
|
+
security:
|
|
116
|
+
enabled: true
|
|
117
|
+
verbose: true
|
|
118
|
+
devops:
|
|
119
|
+
enabled: true
|
|
120
|
+
verbose: true
|
|
121
|
+
doc:
|
|
122
|
+
enabled: true
|
|
123
|
+
verbose: true
|
|
124
|
+
|
|
125
|
+
# Flow Settings
|
|
126
|
+
flows:
|
|
127
|
+
auto:
|
|
128
|
+
enabled: true
|
|
129
|
+
discovery:
|
|
130
|
+
enabled: true
|
|
131
|
+
build:
|
|
132
|
+
enabled: true
|
|
133
|
+
debate:
|
|
134
|
+
enabled: true
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
config_file.write_text(default_config)
|
|
138
|
+
|
|
139
|
+
# Create .env.example if it doesn't exist
|
|
140
|
+
env_example = project_path / ".env.example"
|
|
141
|
+
if not env_example.exists():
|
|
142
|
+
env_example.write_text("""# CrewAI Environment Variables
|
|
143
|
+
# Copy this to .env and fill in your values
|
|
144
|
+
|
|
145
|
+
# OpenAI API Key
|
|
146
|
+
OPENAI_API_KEY=your-openai-api-key-here
|
|
147
|
+
|
|
148
|
+
# Serper API Key (for web search)
|
|
149
|
+
SERPER_API_KEY=your-serper-api-key-here
|
|
150
|
+
|
|
151
|
+
# Database Configuration (optional)
|
|
152
|
+
DB_HOST=localhost
|
|
153
|
+
DB_PORT=5432
|
|
154
|
+
DB_NAME=mdan_db
|
|
155
|
+
DB_USER=your-db-user
|
|
156
|
+
DB_PASSWORD=your-db-password
|
|
157
|
+
""")
|
|
158
|
+
|
|
159
|
+
click.echo(f"{GREEN}✅ CrewAI initialized successfully!{NC}")
|
|
160
|
+
click.echo(f" {BOLD}Config file:{NC} {config_file}")
|
|
161
|
+
click.echo(f" {BOLD}Env example:{NC} {env_example}")
|
|
162
|
+
click.echo(f"\n {BOLD}Next:{NC}")
|
|
163
|
+
click.echo(" 1. Copy .env.example to .env and fill in your API keys")
|
|
164
|
+
click.echo(" 2. Customize crewai_config.yaml if needed")
|
|
165
|
+
click.echo(f" 3. Run: {CYAN}mdan crewai status{NC}")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@crewai_cli.command()
|
|
169
|
+
@click.argument("task")
|
|
170
|
+
@click.option(
|
|
171
|
+
"--project-path", default=".", help="Project path (default: current directory)"
|
|
172
|
+
)
|
|
173
|
+
@click.option("--save-context", is_flag=True, help="Save context after execution")
|
|
174
|
+
def auto(task, project_path, save_context):
|
|
175
|
+
"""Run autonomous mode with a task."""
|
|
176
|
+
if not CREWAI_AVAILABLE:
|
|
177
|
+
click.echo(f"{RED}❌ CrewAI integration not found{NC}")
|
|
178
|
+
click.echo(f" Install with: {CYAN}pip install -r requirements_crewai.txt{NC}")
|
|
179
|
+
click.echo(
|
|
180
|
+
f" Note: CrewAI requires Python 3.10-3.13 (current: {sys.version_info.major}.{sys.version_info.minor})"
|
|
181
|
+
)
|
|
182
|
+
sys.exit(1)
|
|
183
|
+
|
|
184
|
+
project_path = Path(project_path).resolve()
|
|
185
|
+
|
|
186
|
+
# Check for environment variables
|
|
187
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
188
|
+
click.echo(f"{RED}❌ OPENAI_API_KEY not set{NC}")
|
|
189
|
+
click.echo(f" Set it with: {CYAN}export OPENAI_API_KEY=your-key{NC}")
|
|
190
|
+
sys.exit(1)
|
|
191
|
+
|
|
192
|
+
click.echo(f"{CYAN}🚀 Starting autonomous mode...{NC}")
|
|
193
|
+
click.echo(f"{BOLD}Task:{NC} {task}\n")
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
orchestrator = CrewAIOrchestrator(
|
|
197
|
+
project_path=str(project_path),
|
|
198
|
+
auto_mode=True,
|
|
199
|
+
serper_api_key=os.getenv("SERPER_API_KEY"),
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
result = run_async(orchestrator.run_auto_mode(task))
|
|
203
|
+
|
|
204
|
+
if result.get("status") == "success":
|
|
205
|
+
click.echo(f"\n{GREEN}✅ Autonomous mode completed successfully!{NC}")
|
|
206
|
+
|
|
207
|
+
if save_context:
|
|
208
|
+
state_file = project_path / "mdan_crewai_state.json"
|
|
209
|
+
orchestrator.save_state(str(state_file))
|
|
210
|
+
click.echo(f" {BOLD}State saved:{NC} {state_file}")
|
|
211
|
+
|
|
212
|
+
# Display result summary
|
|
213
|
+
if "result" in result:
|
|
214
|
+
click.echo(f"\n{BOLD}Result:{NC}")
|
|
215
|
+
if isinstance(result["result"], dict):
|
|
216
|
+
click.echo(json.dumps(result["result"], indent=2))
|
|
217
|
+
else:
|
|
218
|
+
click.echo(str(result["result"]))
|
|
219
|
+
else:
|
|
220
|
+
click.echo(f"\n{RED}❌ Error:{NC} {result.get('error', 'Unknown error')}")
|
|
221
|
+
sys.exit(1)
|
|
222
|
+
|
|
223
|
+
except Exception as e:
|
|
224
|
+
click.echo(f"\n{RED}❌ Error:{NC} {str(e)}")
|
|
225
|
+
sys.exit(1)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@crewai_cli.command()
|
|
229
|
+
@click.argument("topic")
|
|
230
|
+
@click.option(
|
|
231
|
+
"--project-path", default=".", help="Project path (default: current directory)"
|
|
232
|
+
)
|
|
233
|
+
@click.option("--rounds", default=3, help="Number of debate rounds (default: 3)")
|
|
234
|
+
def debate(topic, project_path, rounds):
|
|
235
|
+
"""Start a multi-agent debate on a topic."""
|
|
236
|
+
if not CREWAI_AVAILABLE:
|
|
237
|
+
click.echo(f"{RED}❌ CrewAI integration not found{NC}")
|
|
238
|
+
click.echo(f" Install with: {CYAN}pip install -r requirements_crewai.txt{NC}")
|
|
239
|
+
click.echo(
|
|
240
|
+
f" Note: CrewAI requires Python 3.10-3.13 (current: {sys.version_info.major}.{sys.version_info.minor})"
|
|
241
|
+
)
|
|
242
|
+
sys.exit(1)
|
|
243
|
+
|
|
244
|
+
project_path = Path(project_path).resolve()
|
|
245
|
+
|
|
246
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
247
|
+
click.echo(f"{RED}❌ OPENAI_API_KEY not set{NC}")
|
|
248
|
+
click.echo(f" Set it with: {CYAN}export OPENAI_API_KEY=your-key{NC}")
|
|
249
|
+
sys.exit(1)
|
|
250
|
+
|
|
251
|
+
click.echo(f"{CYAN}🎯 Starting multi-agent debate...{NC}")
|
|
252
|
+
click.echo(f"{BOLD}Topic:{NC} {topic}")
|
|
253
|
+
click.echo(f"{BOLD}Rounds:{NC} {rounds}\n")
|
|
254
|
+
|
|
255
|
+
try:
|
|
256
|
+
orchestrator = CrewAIOrchestrator(
|
|
257
|
+
project_path=str(project_path),
|
|
258
|
+
serper_api_key=os.getenv("SERPER_API_KEY"),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
result = run_async(orchestrator.start_debate(topic))
|
|
262
|
+
|
|
263
|
+
if result.get("status") == "success":
|
|
264
|
+
click.echo(f"\n{GREEN}✅ Debate completed!{NC}")
|
|
265
|
+
|
|
266
|
+
if "result" in result:
|
|
267
|
+
click.echo(f"\n{BOLD}Debate Summary:{NC}")
|
|
268
|
+
if isinstance(result["result"], dict):
|
|
269
|
+
click.echo(json.dumps(result["result"], indent=2))
|
|
270
|
+
else:
|
|
271
|
+
click.echo(str(result["result"]))
|
|
272
|
+
else:
|
|
273
|
+
click.echo(f"\n{RED}❌ Error:{NC} {result.get('error', 'Unknown error')}")
|
|
274
|
+
sys.exit(1)
|
|
275
|
+
|
|
276
|
+
except Exception as e:
|
|
277
|
+
click.echo(f"\n{RED}❌ Error:{NC} {str(e)}")
|
|
278
|
+
sys.exit(1)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@crewai_cli.command()
|
|
282
|
+
@click.argument("agent_name")
|
|
283
|
+
@click.argument("task")
|
|
284
|
+
@click.option(
|
|
285
|
+
"--project-path", default=".", help="Project path (default: current directory)"
|
|
286
|
+
)
|
|
287
|
+
def agent(agent_name, task, project_path):
|
|
288
|
+
"""Execute a task with a specific agent."""
|
|
289
|
+
if not CREWAI_AVAILABLE:
|
|
290
|
+
click.echo(f"{RED}❌ CrewAI integration not found{NC}")
|
|
291
|
+
click.echo(f" Install with: {CYAN}pip install -r requirements_crewai.txt{NC}")
|
|
292
|
+
click.echo(
|
|
293
|
+
f" Note: CrewAI requires Python 3.10-3.13 (current: {sys.version_info.major}.{sys.version_info.minor})"
|
|
294
|
+
)
|
|
295
|
+
sys.exit(1)
|
|
296
|
+
|
|
297
|
+
project_path = Path(project_path).resolve()
|
|
298
|
+
|
|
299
|
+
valid_agents = [
|
|
300
|
+
"product",
|
|
301
|
+
"architect",
|
|
302
|
+
"ux",
|
|
303
|
+
"dev",
|
|
304
|
+
"test",
|
|
305
|
+
"security",
|
|
306
|
+
"devops",
|
|
307
|
+
"doc",
|
|
308
|
+
]
|
|
309
|
+
|
|
310
|
+
if agent_name not in valid_agents:
|
|
311
|
+
click.echo(f"{RED}❌ Invalid agent: {agent_name}{NC}")
|
|
312
|
+
click.echo(f" Valid agents: {', '.join(valid_agents)}")
|
|
313
|
+
sys.exit(1)
|
|
314
|
+
|
|
315
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
316
|
+
click.echo(f"{RED}❌ OPENAI_API_KEY not set{NC}")
|
|
317
|
+
click.echo(f" Set it with: {CYAN}export OPENAI_API_KEY=your-key{NC}")
|
|
318
|
+
sys.exit(1)
|
|
319
|
+
|
|
320
|
+
click.echo(f"{CYAN}🤖 Executing task with {BOLD}{agent_name}{NC} agent...")
|
|
321
|
+
click.echo(f"{BOLD}Task:{NC} {task}\n")
|
|
322
|
+
|
|
323
|
+
try:
|
|
324
|
+
orchestrator = CrewAIOrchestrator(
|
|
325
|
+
project_path=str(project_path),
|
|
326
|
+
serper_api_key=os.getenv("SERPER_API_KEY"),
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
result = run_async(orchestrator.execute_task(task))
|
|
330
|
+
|
|
331
|
+
if result.get("status") == "success":
|
|
332
|
+
click.echo(f"\n{GREEN}✅ Task completed!{NC}")
|
|
333
|
+
|
|
334
|
+
if "result" in result:
|
|
335
|
+
click.echo(f"\n{BOLD}Result:{NC}")
|
|
336
|
+
if isinstance(result["result"], dict):
|
|
337
|
+
click.echo(json.dumps(result["result"], indent=2))
|
|
338
|
+
else:
|
|
339
|
+
click.echo(str(result["result"]))
|
|
340
|
+
else:
|
|
341
|
+
click.echo(f"\n{RED}❌ Error:{NC} {result.get('error', 'Unknown error')}")
|
|
342
|
+
sys.exit(1)
|
|
343
|
+
|
|
344
|
+
except Exception as e:
|
|
345
|
+
click.echo(f"\n{RED}❌ Error:{NC} {str(e)}")
|
|
346
|
+
sys.exit(1)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
@crewai_cli.command()
|
|
350
|
+
@click.argument("flow_name")
|
|
351
|
+
@click.argument("task")
|
|
352
|
+
@click.option(
|
|
353
|
+
"--project-path", default=".", help="Project path (default: current directory)"
|
|
354
|
+
)
|
|
355
|
+
def flow(flow_name, task, project_path):
|
|
356
|
+
"""Execute a specific flow."""
|
|
357
|
+
if not CREWAI_AVAILABLE:
|
|
358
|
+
click.echo(f"{RED}❌ CrewAI integration not found{NC}")
|
|
359
|
+
click.echo(f" Install with: {CYAN}pip install -r requirements_crewai.txt{NC}")
|
|
360
|
+
click.echo(
|
|
361
|
+
f" Note: CrewAI requires Python 3.10-3.13 (current: {sys.version_info.major}.{sys.version_info.minor})"
|
|
362
|
+
)
|
|
363
|
+
sys.exit(1)
|
|
364
|
+
|
|
365
|
+
project_path = Path(project_path).resolve()
|
|
366
|
+
|
|
367
|
+
valid_flows = ["auto", "discovery", "build", "debate"]
|
|
368
|
+
|
|
369
|
+
if flow_name not in valid_flows:
|
|
370
|
+
click.echo(f"{RED}❌ Invalid flow: {flow_name}{NC}")
|
|
371
|
+
click.echo(f" Valid flows: {', '.join(valid_flows)}")
|
|
372
|
+
sys.exit(1)
|
|
373
|
+
|
|
374
|
+
if not os.getenv("OPENAI_API_KEY"):
|
|
375
|
+
click.echo(f"{RED}❌ OPENAI_API_KEY not set{NC}")
|
|
376
|
+
click.echo(f" Set it with: {CYAN}export OPENAI_API_KEY=your-key{NC}")
|
|
377
|
+
sys.exit(1)
|
|
378
|
+
|
|
379
|
+
click.echo(f"{CYAN}🔄 Executing {BOLD}{flow_name}{NC} flow...")
|
|
380
|
+
click.echo(f"{BOLD}Task:{NC} {task}\n")
|
|
381
|
+
|
|
382
|
+
try:
|
|
383
|
+
orchestrator = CrewAIOrchestrator(
|
|
384
|
+
project_path=str(project_path),
|
|
385
|
+
serper_api_key=os.getenv("SERPER_API_KEY"),
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
result = run_async(orchestrator.execute_task(task))
|
|
389
|
+
|
|
390
|
+
if result.get("status") == "success":
|
|
391
|
+
click.echo(f"\n{GREEN}✅ Flow completed!{NC}")
|
|
392
|
+
|
|
393
|
+
if "result" in result:
|
|
394
|
+
click.echo(f"\n{BOLD}Result:{NC}")
|
|
395
|
+
if isinstance(result["result"], dict):
|
|
396
|
+
click.echo(json.dumps(result["result"], indent=2))
|
|
397
|
+
else:
|
|
398
|
+
click.echo(str(result["result"]))
|
|
399
|
+
else:
|
|
400
|
+
click.echo(f"\n{RED}❌ Error:{NC} {result.get('error', 'Unknown error')}")
|
|
401
|
+
sys.exit(1)
|
|
402
|
+
|
|
403
|
+
except Exception as e:
|
|
404
|
+
click.echo(f"\n{RED}❌ Error:{NC} {str(e)}")
|
|
405
|
+
sys.exit(1)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
@crewai_cli.command()
|
|
409
|
+
def skills():
|
|
410
|
+
"""List available skills."""
|
|
411
|
+
if not CREWAI_AVAILABLE:
|
|
412
|
+
click.echo(f"{RED}❌ CrewAI integration not found{NC}")
|
|
413
|
+
click.echo(f" Install with: {CYAN}pip install -r requirements_crewai.txt{NC}")
|
|
414
|
+
click.echo(
|
|
415
|
+
f" Note: CrewAI requires Python 3.10-3.13 (current: {sys.version_info.major}.{sys.version_info.minor})"
|
|
416
|
+
)
|
|
417
|
+
sys.exit(1)
|
|
418
|
+
|
|
419
|
+
click.echo(f"{CYAN}📚 Available Skills:{NC}\n")
|
|
420
|
+
|
|
421
|
+
try:
|
|
422
|
+
router = SkillRouter()
|
|
423
|
+
all_skills = router.get_all_skills()
|
|
424
|
+
|
|
425
|
+
# Group by category
|
|
426
|
+
categories = {}
|
|
427
|
+
for skill_name, skill_info in all_skills.items():
|
|
428
|
+
category = skill_info.get("category", "General")
|
|
429
|
+
if category not in categories:
|
|
430
|
+
categories[category] = []
|
|
431
|
+
categories[category].append((skill_name, skill_info))
|
|
432
|
+
|
|
433
|
+
for category, skills in sorted(categories.items()):
|
|
434
|
+
click.echo(f"{BOLD}{category}:{NC}")
|
|
435
|
+
for skill_name, skill_info in skills:
|
|
436
|
+
description = skill_info.get("description", "No description")
|
|
437
|
+
click.echo(f" • {skill_name}: {description}")
|
|
438
|
+
click.echo()
|
|
439
|
+
|
|
440
|
+
except Exception as e:
|
|
441
|
+
click.echo(f"{RED}❌ Error loading skills: {str(e)}{NC}")
|
|
442
|
+
sys.exit(1)
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
@crewai_cli.command()
|
|
446
|
+
@click.option(
|
|
447
|
+
"--project-path", default=".", help="Project path (default: current directory)"
|
|
448
|
+
)
|
|
449
|
+
def status(project_path):
|
|
450
|
+
"""Show CrewAI status."""
|
|
451
|
+
project_path = Path(project_path).resolve()
|
|
452
|
+
|
|
453
|
+
click.echo(f"{CYAN}📊 CrewAI Status{NC}\n")
|
|
454
|
+
|
|
455
|
+
# Check if CrewAI is available
|
|
456
|
+
if not CREWAI_AVAILABLE:
|
|
457
|
+
click.echo(f"{RED}❌ CrewAI integration not found{NC}")
|
|
458
|
+
click.echo(f" Install with: {CYAN}pip install -r requirements_crewai.txt{NC}")
|
|
459
|
+
click.echo(
|
|
460
|
+
f" Note: CrewAI requires Python 3.10-3.13 (current: {sys.version_info.major}.{sys.version_info.minor})"
|
|
461
|
+
)
|
|
462
|
+
return
|
|
463
|
+
|
|
464
|
+
# Check config file
|
|
465
|
+
config_file = project_path / "crewai_config.yaml"
|
|
466
|
+
if config_file.exists():
|
|
467
|
+
click.echo(f"{GREEN}✅ Config file:{NC} {config_file}")
|
|
468
|
+
else:
|
|
469
|
+
click.echo(f"{YELLOW}⚠️ Config file not found{NC}")
|
|
470
|
+
click.echo(f" Run: {CYAN}mdan crewai init{NC}")
|
|
471
|
+
return
|
|
472
|
+
|
|
473
|
+
# Check environment variables
|
|
474
|
+
click.echo(f"\n{BOLD}Environment Variables:{NC}")
|
|
475
|
+
|
|
476
|
+
if os.getenv("OPENAI_API_KEY"):
|
|
477
|
+
click.echo(f" {GREEN}✅{NC} OPENAI_API_KEY: Set")
|
|
478
|
+
else:
|
|
479
|
+
click.echo(f" {RED}❌{NC} OPENAI_API_KEY: Not set")
|
|
480
|
+
|
|
481
|
+
if os.getenv("SERPER_API_KEY"):
|
|
482
|
+
click.echo(f" {GREEN}✅{NC} SERPER_API_KEY: Set")
|
|
483
|
+
else:
|
|
484
|
+
click.echo(f" {YELLOW}⚠️{NC} SERPER_API_KEY: Not set (optional)")
|
|
485
|
+
|
|
486
|
+
# Check state file
|
|
487
|
+
state_file = project_path / "mdan_crewai_state.json"
|
|
488
|
+
if state_file.exists():
|
|
489
|
+
click.echo(f"\n{GREEN}✅ State file:{NC} {state_file}")
|
|
490
|
+
try:
|
|
491
|
+
with open(state_file) as f:
|
|
492
|
+
state = json.load(f)
|
|
493
|
+
click.echo(
|
|
494
|
+
f" {BOLD}Current Phase:{NC} {state.get('current_phase', 'N/A')}"
|
|
495
|
+
)
|
|
496
|
+
click.echo(
|
|
497
|
+
f" {BOLD}Auto Mode:{NC} {state.get('auto_mode_enabled', False)}"
|
|
498
|
+
)
|
|
499
|
+
click.echo(
|
|
500
|
+
f" {BOLD}Tasks Completed:{NC} {len(state.get('task_history', []))}"
|
|
501
|
+
)
|
|
502
|
+
except Exception:
|
|
503
|
+
click.echo(f" {YELLOW}⚠️ Could not read state file{NC}")
|
|
504
|
+
|
|
505
|
+
# Check integrations
|
|
506
|
+
click.echo(f"\n{BOLD}Integrations:{NC}")
|
|
507
|
+
|
|
508
|
+
import importlib.util
|
|
509
|
+
|
|
510
|
+
if importlib.util.find_spec("integrations.crewai.tools.serper_tool") is not None:
|
|
511
|
+
click.echo(f" {GREEN}✅{NC} Serper Tool: Available")
|
|
512
|
+
else:
|
|
513
|
+
click.echo(f" {RED}❌{NC} Serper Tool: Not available")
|
|
514
|
+
|
|
515
|
+
if importlib.util.find_spec("integrations.crewai.tools.sql_tool") is not None:
|
|
516
|
+
click.echo(f" {GREEN}✅{NC} SQL Tool: Available")
|
|
517
|
+
else:
|
|
518
|
+
click.echo(f" {RED}❌{NC} SQL Tool: Not available")
|
|
519
|
+
|
|
520
|
+
if importlib.util.find_spec("integrations.crewai.tools.file_tool") is not None:
|
|
521
|
+
click.echo(f" {GREEN}✅{NC} File Tool: Available")
|
|
522
|
+
else:
|
|
523
|
+
click.echo(f" {RED}❌{NC} File Tool: Not available")
|
|
524
|
+
|
|
525
|
+
# List agents
|
|
526
|
+
click.echo(f"\n{BOLD}Available Agents:{NC}")
|
|
527
|
+
agents = ["product", "architect", "ux", "dev", "test", "security", "devops", "doc"]
|
|
528
|
+
for agent in agents:
|
|
529
|
+
click.echo(f" • {agent}")
|
|
530
|
+
|
|
531
|
+
# List flows
|
|
532
|
+
click.echo(f"\n{BOLD}Available Flows:{NC}")
|
|
533
|
+
flows = ["auto", "discovery", "build", "debate"]
|
|
534
|
+
for flow in flows:
|
|
535
|
+
click.echo(f" • {flow}")
|
|
536
|
+
|
|
537
|
+
|
|
538
|
+
if __name__ == "__main__":
|
|
539
|
+
crewai_cli()
|