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,297 @@
|
|
|
1
|
+
"""Build Flow - BUILD phase flow
|
|
2
|
+
|
|
3
|
+
Orchestrates the BUILD phase: implementation, refactoring, code review, testing, debugging.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from crewai.flow import Flow, listen, start
|
|
7
|
+
from typing import Dict, Any, Optional
|
|
8
|
+
import asyncio
|
|
9
|
+
import json
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from ..agents.dev_agent import DevAgent
|
|
13
|
+
from ..agents.security_agent import SecurityAgent
|
|
14
|
+
|
|
15
|
+
from ..tools.sql_tool import SQLTool
|
|
16
|
+
from ..tools.serper_tool import SerperTool
|
|
17
|
+
from ..tools.file_tool import FileTool
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BuildFlow(Flow):
|
|
21
|
+
"""BUILD phase flow for implementation and development."""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
project_path: str,
|
|
26
|
+
llm=None,
|
|
27
|
+
sql_config: Optional[Dict[str, Any]] = None,
|
|
28
|
+
serper_api_key: Optional[str] = None,
|
|
29
|
+
):
|
|
30
|
+
"""Initialize Build Flow.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
project_path: Path to the project directory
|
|
34
|
+
llm: Language model instance
|
|
35
|
+
sql_config: SQL database configuration
|
|
36
|
+
serper_api_key: Serper API key for web search
|
|
37
|
+
"""
|
|
38
|
+
super().__init__()
|
|
39
|
+
self.project_path = Path(project_path)
|
|
40
|
+
self.llm = llm
|
|
41
|
+
|
|
42
|
+
# Initialize tools
|
|
43
|
+
self.sql_tool = SQLTool(**sql_config) if sql_config else None
|
|
44
|
+
self.serper_tool = (
|
|
45
|
+
SerperTool(api_key=serper_api_key) if serper_api_key else None
|
|
46
|
+
)
|
|
47
|
+
self.file_tool = FileTool(base_path=project_path)
|
|
48
|
+
|
|
49
|
+
# Initialize agents
|
|
50
|
+
self.dev_agent = DevAgent(
|
|
51
|
+
sql_tool=self.sql_tool,
|
|
52
|
+
serper_tool=self.serper_tool,
|
|
53
|
+
file_tool=self.file_tool,
|
|
54
|
+
llm=llm,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
self.security_agent = SecurityAgent(
|
|
58
|
+
sql_tool=self.sql_tool,
|
|
59
|
+
serper_tool=self.serper_tool,
|
|
60
|
+
file_tool=self.file_tool,
|
|
61
|
+
llm=llm,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Flow state
|
|
65
|
+
self.state = {
|
|
66
|
+
"current_step": None,
|
|
67
|
+
"project_context": {},
|
|
68
|
+
"step_results": {},
|
|
69
|
+
"errors": [],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@start
|
|
73
|
+
async def load_context(self, design_context: str):
|
|
74
|
+
"""Load design context and architecture."""
|
|
75
|
+
self.state["current_step"] = "load_context"
|
|
76
|
+
|
|
77
|
+
print("๐ Loading design context...")
|
|
78
|
+
|
|
79
|
+
# Load project state if exists
|
|
80
|
+
state_file = self.project_path / "MDAN-STATE.json"
|
|
81
|
+
if state_file.exists():
|
|
82
|
+
with open(state_file, "r") as f:
|
|
83
|
+
self.state["project_context"] = json.load(f)
|
|
84
|
+
else:
|
|
85
|
+
self.state["project_context"] = {
|
|
86
|
+
"project_name": self.project_path.name,
|
|
87
|
+
"design_context": design_context,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
self.state["step_results"]["load_context"] = {
|
|
91
|
+
"status": "completed",
|
|
92
|
+
"context": self.state["project_context"],
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return self.state["project_context"]
|
|
96
|
+
|
|
97
|
+
@listen(load_context)
|
|
98
|
+
async def implement_features(self, context: Dict[str, Any]):
|
|
99
|
+
"""Implement features based on design."""
|
|
100
|
+
self.state["current_step"] = "implement_features"
|
|
101
|
+
|
|
102
|
+
print("๐ป Implementing features...")
|
|
103
|
+
|
|
104
|
+
task = self.dev_agent.create_implementation_task(str(context))
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
result = await asyncio.to_thread(task.execute)
|
|
108
|
+
self.state["step_results"]["implement_features"] = {
|
|
109
|
+
"status": "completed",
|
|
110
|
+
"result": result,
|
|
111
|
+
}
|
|
112
|
+
print("โ
Features implemented successfully")
|
|
113
|
+
return result
|
|
114
|
+
except Exception as e:
|
|
115
|
+
self.state["errors"].append(f"Implementation error: {str(e)}")
|
|
116
|
+
print(f"โ Error implementing features: {str(e)}")
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
@listen(implement_features)
|
|
120
|
+
async def security_review(self, implementation_result: Any):
|
|
121
|
+
"""Conduct security review of implementation."""
|
|
122
|
+
self.state["current_step"] = "security_review"
|
|
123
|
+
|
|
124
|
+
print("๐ Conducting security review...")
|
|
125
|
+
|
|
126
|
+
task = self.security_agent.create_security_review_task(
|
|
127
|
+
str(implementation_result)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
result = await asyncio.to_thread(task.execute)
|
|
132
|
+
self.state["step_results"]["security_review"] = {
|
|
133
|
+
"status": "completed",
|
|
134
|
+
"result": result,
|
|
135
|
+
}
|
|
136
|
+
print("โ
Security review completed")
|
|
137
|
+
return result
|
|
138
|
+
except Exception as e:
|
|
139
|
+
self.state["errors"].append(f"Security review error: {str(e)}")
|
|
140
|
+
print(f"โ Error in security review: {str(e)}")
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
@listen(security_review)
|
|
144
|
+
async def refactor_code(self, security_result: Any):
|
|
145
|
+
"""Refactor code based on feedback."""
|
|
146
|
+
self.state["current_step"] = "refactor_code"
|
|
147
|
+
|
|
148
|
+
print("๐ง Refactoring code...")
|
|
149
|
+
|
|
150
|
+
task = self.dev_agent.create_refactoring_task(str(security_result))
|
|
151
|
+
|
|
152
|
+
try:
|
|
153
|
+
result = await asyncio.to_thread(task.execute)
|
|
154
|
+
self.state["step_results"]["refactor_code"] = {
|
|
155
|
+
"status": "completed",
|
|
156
|
+
"result": result,
|
|
157
|
+
}
|
|
158
|
+
print("โ
Code refactored successfully")
|
|
159
|
+
return result
|
|
160
|
+
except Exception as e:
|
|
161
|
+
self.state["errors"].append(f"Refactoring error: {str(e)}")
|
|
162
|
+
print(f"โ Error refactoring code: {str(e)}")
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
@listen(refactor_code)
|
|
166
|
+
async def code_review(self, refactor_result: Any):
|
|
167
|
+
"""Conduct code review."""
|
|
168
|
+
self.state["current_step"] = "code_review"
|
|
169
|
+
|
|
170
|
+
print("๐ Conducting code review...")
|
|
171
|
+
|
|
172
|
+
task = self.dev_agent.create_code_review_task(str(refactor_result))
|
|
173
|
+
|
|
174
|
+
try:
|
|
175
|
+
result = await asyncio.to_thread(task.execute)
|
|
176
|
+
self.state["step_results"]["code_review"] = {
|
|
177
|
+
"status": "completed",
|
|
178
|
+
"result": result,
|
|
179
|
+
}
|
|
180
|
+
print("โ
Code review completed")
|
|
181
|
+
return result
|
|
182
|
+
except Exception as e:
|
|
183
|
+
self.state["errors"].append(f"Code review error: {str(e)}")
|
|
184
|
+
print(f"โ Error in code review: {str(e)}")
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
@listen(code_review)
|
|
188
|
+
async def write_tests(self, review_result: Any):
|
|
189
|
+
"""Write tests for the implementation."""
|
|
190
|
+
self.state["current_step"] = "write_tests"
|
|
191
|
+
|
|
192
|
+
print("๐งช Writing tests...")
|
|
193
|
+
|
|
194
|
+
task = self.dev_agent.create_testing_task(str(review_result))
|
|
195
|
+
|
|
196
|
+
try:
|
|
197
|
+
result = await asyncio.to_thread(task.execute)
|
|
198
|
+
self.state["step_results"]["write_tests"] = {
|
|
199
|
+
"status": "completed",
|
|
200
|
+
"result": result,
|
|
201
|
+
}
|
|
202
|
+
print("โ
Tests written successfully")
|
|
203
|
+
return result
|
|
204
|
+
except Exception as e:
|
|
205
|
+
self.state["errors"].append(f"Test writing error: {str(e)}")
|
|
206
|
+
print(f"โ Error writing tests: {str(e)}")
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
@listen(write_tests)
|
|
210
|
+
async def debug_issues(self, test_result: Any):
|
|
211
|
+
"""Debug any issues found."""
|
|
212
|
+
self.state["current_step"] = "debug_issues"
|
|
213
|
+
|
|
214
|
+
print("๐ Debugging issues...")
|
|
215
|
+
|
|
216
|
+
task = self.dev_agent.create_debugging_task(str(test_result))
|
|
217
|
+
|
|
218
|
+
try:
|
|
219
|
+
result = await asyncio.to_thread(task.execute)
|
|
220
|
+
self.state["step_results"]["debug_issues"] = {
|
|
221
|
+
"status": "completed",
|
|
222
|
+
"result": result,
|
|
223
|
+
}
|
|
224
|
+
print("โ
Debugging completed")
|
|
225
|
+
return result
|
|
226
|
+
except Exception as e:
|
|
227
|
+
self.state["errors"].append(f"Debugging error: {str(e)}")
|
|
228
|
+
print(f"โ Error debugging: {str(e)}")
|
|
229
|
+
return None
|
|
230
|
+
|
|
231
|
+
@listen(debug_issues)
|
|
232
|
+
async def finalize_build(self, debug_result: Any):
|
|
233
|
+
"""Finalize BUILD phase."""
|
|
234
|
+
print("โจ BUILD phase completed!")
|
|
235
|
+
|
|
236
|
+
# Update project state
|
|
237
|
+
self.state["project_context"]["phases_completed"] = self.state[
|
|
238
|
+
"project_context"
|
|
239
|
+
].get("phases_completed", [])
|
|
240
|
+
if "BUILD" not in self.state["project_context"]["phases_completed"]:
|
|
241
|
+
self.state["project_context"]["phases_completed"].append("BUILD")
|
|
242
|
+
self.state["project_context"]["current_phase"] = "BUILD_COMPLETED"
|
|
243
|
+
|
|
244
|
+
# Save state
|
|
245
|
+
state_file = self.project_path / "MDAN-STATE.json"
|
|
246
|
+
with open(state_file, "w") as f:
|
|
247
|
+
json.dump(self.state["project_context"], f, indent=2)
|
|
248
|
+
|
|
249
|
+
print(f"โ
Project state saved to {state_file}")
|
|
250
|
+
|
|
251
|
+
if self.state["errors"]:
|
|
252
|
+
print(f"\nโ ๏ธ Errors encountered: {len(self.state['errors'])}")
|
|
253
|
+
for error in self.state["errors"]:
|
|
254
|
+
print(f" - {error}")
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
"status": "completed",
|
|
258
|
+
"steps": self.state["step_results"],
|
|
259
|
+
"errors": self.state["errors"],
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
def get_state(self) -> Dict[str, Any]:
|
|
263
|
+
"""Get current flow state.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Current flow state
|
|
267
|
+
"""
|
|
268
|
+
return self.state
|
|
269
|
+
|
|
270
|
+
def save_context(self, filepath: str):
|
|
271
|
+
"""Save flow context to file.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
filepath: Path to save context
|
|
275
|
+
"""
|
|
276
|
+
context = {"state": self.state, "project_path": str(self.project_path)}
|
|
277
|
+
with open(filepath, "w") as f:
|
|
278
|
+
json.dump(context, f, indent=2)
|
|
279
|
+
|
|
280
|
+
@classmethod
|
|
281
|
+
def load_context(cls, filepath: str, llm=None) -> "BuildFlow":
|
|
282
|
+
"""Load flow context from file.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
filepath: Path to load context from
|
|
286
|
+
llm: Language model instance
|
|
287
|
+
|
|
288
|
+
Returns:
|
|
289
|
+
BuildFlow instance with loaded context
|
|
290
|
+
"""
|
|
291
|
+
with open(filepath, "r") as f:
|
|
292
|
+
context = json.load(f)
|
|
293
|
+
|
|
294
|
+
flow = cls(project_path=context["project_path"], llm=llm)
|
|
295
|
+
flow.state = context["state"]
|
|
296
|
+
|
|
297
|
+
return flow
|