Spaces:
Runtime error
Runtime error
Update backend/orchestrator.py
Browse files- backend/orchestrator.py +36 -12
backend/orchestrator.py
CHANGED
|
@@ -8,7 +8,7 @@ import ast
|
|
| 8 |
from typing import Optional, Dict, Any
|
| 9 |
|
| 10 |
from .database import update_project_status, get_project
|
| 11 |
-
from .tools import get_project_dir, create_file, read_file, zip_project, scrape_web, document_requirements, create_design_spec
|
| 12 |
from .agents import ROLE_PROMPTS
|
| 13 |
from models.loader import generate_with_model
|
| 14 |
|
|
@@ -65,16 +65,14 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 65 |
"max_turns": 60,
|
| 66 |
"current_task_index": 0,
|
| 67 |
"error_state": None,
|
| 68 |
-
"phase": "requirements_gathering"
|
| 69 |
}
|
| 70 |
|
| 71 |
next_agent = "business_analyst"
|
| 72 |
|
| 73 |
-
# --- PHASED EXECUTION LOOP ---
|
| 74 |
while project_context["turn"] < project_context["max_turns"]:
|
| 75 |
log_step("ORCHESTRATOR", f"Current Phase: {project_context['phase'].replace('_', ' ').title()}")
|
| 76 |
|
| 77 |
-
# --- PHASE 1: REQUIREMENTS GATHERING ---
|
| 78 |
if project_context["phase"] == "requirements_gathering":
|
| 79 |
prompt = f"""You are the Business Analyst. The user's request is: {project_context['initial_prompt']}.
|
| 80 |
Based on this, generate a list of functional requirements."""
|
|
@@ -89,7 +87,6 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 89 |
next_agent = "ux_ui_designer"
|
| 90 |
else: raise ValueError("Business Analyst failed to provide a valid output.")
|
| 91 |
|
| 92 |
-
# --- PHASE 2: UX/UI DESIGN ---
|
| 93 |
elif project_context["phase"] == "design_phase":
|
| 94 |
prompt = f"""You are the UX/UI Designer. The documented requirements are: {project_context['requirements']}.
|
| 95 |
Create a detailed user interface design plan based on these requirements."""
|
|
@@ -101,7 +98,6 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 101 |
log_step("UX/UI DESIGNER", "Design specification created.", str(designer_output["design"]))
|
| 102 |
create_design_spec(project_dir, json.dumps(designer_output, indent=2))
|
| 103 |
|
| 104 |
-
# Now, a Planner is needed to break down the design into coding tasks
|
| 105 |
log_step("ORCHESTRATOR", "Design is complete. Briefing the Planner to create a coding plan.")
|
| 106 |
planner_prompt = f"Project brief: {project_context['initial_prompt']}\nRequirements: {project_context['requirements']}\nDesign: {project_context['design']}\nCreate a step-by-step plan for the developers. Assign tasks to 'worker_backend_coder', 'worker_front_end_coder', or 'worker_tester'."
|
| 107 |
planner_response = generate_with_model("planner", planner_prompt)
|
|
@@ -111,10 +107,9 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 111 |
project_context["detailed_plan"] = planner_output["plan"]
|
| 112 |
log_step("PLANNER", "Coding plan created.", f"Plan: {project_context['detailed_plan']}")
|
| 113 |
project_context["phase"] = "development"
|
| 114 |
-
next_agent = "manager"
|
| 115 |
else: raise ValueError("UX/UI Designer failed to provide a valid output.")
|
| 116 |
|
| 117 |
-
# --- PHASE 3: DEVELOPMENT AND DEBUGGING ---
|
| 118 |
elif project_context["phase"] == "development":
|
| 119 |
if project_context["current_task_index"] >= len(project_context["detailed_plan"]):
|
| 120 |
log_step("ORCHESTRATOR", "All planned tasks completed. Instructing Manager to finish project.")
|
|
@@ -148,12 +143,10 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 148 |
log_step(next_agent.replace("_", " ").title(), f"Decided to perform action: `{action}` with args: `{args}`")
|
| 149 |
|
| 150 |
if action == "delegate_coder":
|
| 151 |
-
# This needs to be a bit smarter to delegate to the right coder
|
| 152 |
next_agent = current_plan_step["responsible_agent"]
|
| 153 |
project_context["current_task"] = args[0]
|
| 154 |
project_context["last_action_result"] = f"Task delegated to {next_agent.replace('_', ' ')}."
|
| 155 |
-
|
| 156 |
-
# --- Handle new worker agent actions ---
|
| 157 |
elif action in ["write_code", "write_test", "task_complete"]:
|
| 158 |
if action == "write_code" and len(args) >= 2: create_file(project_dir, args[0], args[1])
|
| 159 |
if action == "write_test" and len(args) >= 2: create_file(project_dir, args[0], args[1])
|
|
@@ -161,6 +154,37 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 161 |
project_context["last_action_result"] = f"Worker finished task and saved to file. Moving to next step in the plan."
|
| 162 |
project_context["current_task_index"] += 1
|
| 163 |
next_agent = "manager"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
elif action == "propose_fix":
|
| 166 |
fix_description = args[2]
|
|
@@ -182,7 +206,7 @@ def run_agent_chain(project_id, user_id, initial_prompt):
|
|
| 182 |
url = args[0]
|
| 183 |
scraped_content = scrape_web(url)
|
| 184 |
project_context["last_action_result"] = f"Scraping result from {url}:\n\n{scraped_content}"
|
| 185 |
-
continue
|
| 186 |
|
| 187 |
elif action == "finish_project":
|
| 188 |
log_step("MANAGER", "Project is ready for final packaging.")
|
|
|
|
| 8 |
from typing import Optional, Dict, Any
|
| 9 |
|
| 10 |
from .database import update_project_status, get_project
|
| 11 |
+
from .tools import get_project_dir, create_file, read_file, zip_project, scrape_web, document_requirements, create_design_spec, run_test_in_sandbox, run_bandit
|
| 12 |
from .agents import ROLE_PROMPTS
|
| 13 |
from models.loader import generate_with_model
|
| 14 |
|
|
|
|
| 65 |
"max_turns": 60,
|
| 66 |
"current_task_index": 0,
|
| 67 |
"error_state": None,
|
| 68 |
+
"phase": "requirements_gathering"
|
| 69 |
}
|
| 70 |
|
| 71 |
next_agent = "business_analyst"
|
| 72 |
|
|
|
|
| 73 |
while project_context["turn"] < project_context["max_turns"]:
|
| 74 |
log_step("ORCHESTRATOR", f"Current Phase: {project_context['phase'].replace('_', ' ').title()}")
|
| 75 |
|
|
|
|
| 76 |
if project_context["phase"] == "requirements_gathering":
|
| 77 |
prompt = f"""You are the Business Analyst. The user's request is: {project_context['initial_prompt']}.
|
| 78 |
Based on this, generate a list of functional requirements."""
|
|
|
|
| 87 |
next_agent = "ux_ui_designer"
|
| 88 |
else: raise ValueError("Business Analyst failed to provide a valid output.")
|
| 89 |
|
|
|
|
| 90 |
elif project_context["phase"] == "design_phase":
|
| 91 |
prompt = f"""You are the UX/UI Designer. The documented requirements are: {project_context['requirements']}.
|
| 92 |
Create a detailed user interface design plan based on these requirements."""
|
|
|
|
| 98 |
log_step("UX/UI DESIGNER", "Design specification created.", str(designer_output["design"]))
|
| 99 |
create_design_spec(project_dir, json.dumps(designer_output, indent=2))
|
| 100 |
|
|
|
|
| 101 |
log_step("ORCHESTRATOR", "Design is complete. Briefing the Planner to create a coding plan.")
|
| 102 |
planner_prompt = f"Project brief: {project_context['initial_prompt']}\nRequirements: {project_context['requirements']}\nDesign: {project_context['design']}\nCreate a step-by-step plan for the developers. Assign tasks to 'worker_backend_coder', 'worker_front_end_coder', or 'worker_tester'."
|
| 103 |
planner_response = generate_with_model("planner", planner_prompt)
|
|
|
|
| 107 |
project_context["detailed_plan"] = planner_output["plan"]
|
| 108 |
log_step("PLANNER", "Coding plan created.", f"Plan: {project_context['detailed_plan']}")
|
| 109 |
project_context["phase"] = "development"
|
| 110 |
+
next_agent = "manager"
|
| 111 |
else: raise ValueError("UX/UI Designer failed to provide a valid output.")
|
| 112 |
|
|
|
|
| 113 |
elif project_context["phase"] == "development":
|
| 114 |
if project_context["current_task_index"] >= len(project_context["detailed_plan"]):
|
| 115 |
log_step("ORCHESTRATOR", "All planned tasks completed. Instructing Manager to finish project.")
|
|
|
|
| 143 |
log_step(next_agent.replace("_", " ").title(), f"Decided to perform action: `{action}` with args: `{args}`")
|
| 144 |
|
| 145 |
if action == "delegate_coder":
|
|
|
|
| 146 |
next_agent = current_plan_step["responsible_agent"]
|
| 147 |
project_context["current_task"] = args[0]
|
| 148 |
project_context["last_action_result"] = f"Task delegated to {next_agent.replace('_', ' ')}."
|
| 149 |
+
|
|
|
|
| 150 |
elif action in ["write_code", "write_test", "task_complete"]:
|
| 151 |
if action == "write_code" and len(args) >= 2: create_file(project_dir, args[0], args[1])
|
| 152 |
if action == "write_test" and len(args) >= 2: create_file(project_dir, args[0], args[1])
|
|
|
|
| 154 |
project_context["last_action_result"] = f"Worker finished task and saved to file. Moving to next step in the plan."
|
| 155 |
project_context["current_task_index"] += 1
|
| 156 |
next_agent = "manager"
|
| 157 |
+
|
| 158 |
+
elif action == "run_test":
|
| 159 |
+
if not args: raise ValueError("Missing file path for run_test.")
|
| 160 |
+
test_file_path = args[0]
|
| 161 |
+
test_output = run_test_in_sandbox(project_dir, test_file_path)
|
| 162 |
+
|
| 163 |
+
project_context["last_action_result"] = f"Test run for {test_file_path}:\n{test_output}"
|
| 164 |
+
log_step("TESTER", "Test run complete.", test_output)
|
| 165 |
+
|
| 166 |
+
if "Sandbox Execution Error" in test_output or "Traceback (most recent call last)" in test_output:
|
| 167 |
+
log_step("ORCHESTRATOR", "Tests failed. Handing over to Debugger.")
|
| 168 |
+
next_agent = "debugger"
|
| 169 |
+
project_context["error_state"] = test_output
|
| 170 |
+
else:
|
| 171 |
+
log_step("ORCHESTRATOR", "Tests passed. Continuing with the plan.")
|
| 172 |
+
project_context["current_task_index"] += 1
|
| 173 |
+
next_agent = "manager"
|
| 174 |
+
|
| 175 |
+
elif action == "run_bandit":
|
| 176 |
+
bandit_report = run_bandit(project_dir)
|
| 177 |
+
project_context["last_action_result"] = f"Bandit Analysis Report:\n{bandit_report}"
|
| 178 |
+
log_step("CODE ANALYST", "Static analysis complete.", bandit_report)
|
| 179 |
+
|
| 180 |
+
if "issues" in bandit_report and json.loads(bandit_report)["results"]:
|
| 181 |
+
log_step("ORCHESTRATOR", "Bandit found security issues. Handing over to Debugger.")
|
| 182 |
+
next_agent = "debugger"
|
| 183 |
+
project_context["error_state"] = bandit_report
|
| 184 |
+
else:
|
| 185 |
+
log_step("ORCHESTRATOR", "No issues found by Bandit. Continuing with the plan.")
|
| 186 |
+
project_context["current_task_index"] += 1
|
| 187 |
+
next_agent = "manager"
|
| 188 |
|
| 189 |
elif action == "propose_fix":
|
| 190 |
fix_description = args[2]
|
|
|
|
| 206 |
url = args[0]
|
| 207 |
scraped_content = scrape_web(url)
|
| 208 |
project_context["last_action_result"] = f"Scraping result from {url}:\n\n{scraped_content}"
|
| 209 |
+
continue
|
| 210 |
|
| 211 |
elif action == "finish_project":
|
| 212 |
log_step("MANAGER", "Project is ready for final packaging.")
|