feat: orchestrator MVP — webhooks, agent launcher, QG checks
This commit is contained in:
0
src/agents/__init__.py
Normal file
0
src/agents/__init__.py
Normal file
105
src/agents/launcher.py
Normal file
105
src/agents/launcher.py
Normal file
@@ -0,0 +1,105 @@
|
||||
import subprocess
|
||||
import os
|
||||
from ..config import settings
|
||||
from ..db import get_db
|
||||
|
||||
|
||||
class AgentLauncher:
|
||||
"""Launch Claude CLI agents for specific tasks."""
|
||||
|
||||
AGENT_CONFIGS = {
|
||||
"analyst": {
|
||||
"system_prompt": ".openclaw/agents/analyst.md",
|
||||
"task_file": ".task.md",
|
||||
"allowed_tools": "Read,Write,Edit,Bash",
|
||||
},
|
||||
"architect": {
|
||||
"system_prompt": ".openclaw/agents/architect.md",
|
||||
"task_file": ".task-arch.md",
|
||||
"allowed_tools": "Read,Write,Edit,Bash",
|
||||
},
|
||||
"developer": {
|
||||
"system_prompt": ".openclaw/agents/developer.md",
|
||||
"task_file": ".task-dev.md",
|
||||
"allowed_tools": "Read,Write,Edit,Bash",
|
||||
},
|
||||
"reviewer": {
|
||||
"system_prompt": ".openclaw/agents/reviewer.md",
|
||||
"task_file": ".task-review.md",
|
||||
"allowed_tools": "Read,Write,Edit,Bash",
|
||||
},
|
||||
"tester": {
|
||||
"system_prompt": ".openclaw/agents/tester.md",
|
||||
"task_file": ".task-test.md",
|
||||
"allowed_tools": "Read,Write,Edit,Bash",
|
||||
},
|
||||
}
|
||||
|
||||
def launch(self, agent: str, repo: str, task_content: str = None) -> int:
|
||||
"""
|
||||
Launch a Claude CLI agent.
|
||||
|
||||
Args:
|
||||
agent: Agent role (analyst, architect, developer, reviewer, tester)
|
||||
repo: Repository name
|
||||
task_content: Optional task content to write to task file
|
||||
|
||||
Returns:
|
||||
agent_run_id from DB
|
||||
"""
|
||||
config = self.AGENT_CONFIGS.get(agent)
|
||||
if not config:
|
||||
raise ValueError(f"Unknown agent: {agent}")
|
||||
|
||||
repo_path = os.path.join(settings.repos_dir, repo)
|
||||
if not os.path.isdir(repo_path):
|
||||
raise FileNotFoundError(f"Repo not found: {repo_path}")
|
||||
|
||||
# Write task file if content provided
|
||||
if task_content:
|
||||
task_path = os.path.join(repo_path, config["task_file"])
|
||||
with open(task_path, "w") as f:
|
||||
f.write(task_content)
|
||||
|
||||
# Record run in DB
|
||||
conn = get_db()
|
||||
cursor = conn.execute(
|
||||
"INSERT INTO agent_runs (task_id, agent) VALUES (NULL, ?)",
|
||||
(agent,),
|
||||
)
|
||||
run_id = cursor.lastrowid
|
||||
conn.commit()
|
||||
|
||||
# Prepare output log
|
||||
output_path = f"/app/data/runs/{run_id}.log"
|
||||
os.makedirs(os.path.dirname(output_path), exist_ok=True)
|
||||
|
||||
# Build shell command
|
||||
cmd = (
|
||||
f'cd {repo_path} && {settings.claude_bin} --print '
|
||||
f'"$(cat {config["task_file"]})" '
|
||||
f'--system-prompt "$(cat {config["system_prompt"]})" '
|
||||
f'--allowedTools {config["allowed_tools"]}'
|
||||
)
|
||||
|
||||
# Launch as background process
|
||||
with open(output_path, "w") as log_file:
|
||||
subprocess.Popen(
|
||||
["bash", "-c", cmd],
|
||||
stdout=log_file,
|
||||
stderr=subprocess.STDOUT,
|
||||
cwd=repo_path,
|
||||
)
|
||||
|
||||
# Update DB with output path
|
||||
conn.execute(
|
||||
"UPDATE agent_runs SET output_path = ? WHERE id = ?",
|
||||
(output_path, run_id),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
return run_id
|
||||
|
||||
|
||||
launcher = AgentLauncher()
|
||||
Reference in New Issue
Block a user