singularity-llm / singularity_llm /agents /agent_manager.py
hermescures1's picture
Upload folder using huggingface_hub
32112fa verified
Raw
History Blame Contribute Delete
5.85 kB
"""Agent Manager — orchestrates all 5 persistent AI agents.
Manages the lifecycle of all agents:
- Starts/stops all agents
- Assigns goals to the best-suited agent
- Monitors agent progress
- Handles agent failures and reassignment
- Provides aggregated stats
The agents run persistently in background threads, continuously
picking up goals from the goal memory and working on them.
"""
from __future__ import annotations
import logging
import time
from typing import Any, Callable
from ..memory.goal_memory import GoalMemory, Goal
from ..memory.persistent import PersistentMemory
from .agent_base import BaseAgent
from .planner_agent import PlannerAgent
from .coder_agent import CoderAgent
from .researcher_agent import ResearcherAgent
from .reviewer_agent import ReviewerAgent
from .executor_agent import ExecutorAgent
logger = logging.getLogger(__name__)
class AgentManager:
"""Manages 5 persistent AI agents that work on goals and projects.
Agents:
1. Planner — breaks goals into steps
2. Coder — writes code, creates files
3. Researcher — gathers information
4. Reviewer — validates quality
5. Executor — runs commands, executes tools
All agents run in background threads and continuously process goals.
"""
def __init__(self, goal_memory: GoalMemory,
persistent_memory: PersistentMemory | None = None,
generate_fn: Callable[[str], str] | None = None,
tool_registry: Any = None) -> None:
self.goal_memory = goal_memory
self.persistent_memory = persistent_memory
self._generate_fn = generate_fn
self._tool_registry = tool_registry
# Create all 5 agents
self.agents: dict[str, BaseAgent] = {
"planner": PlannerAgent(goal_memory, persistent_memory, generate_fn),
"coder": CoderAgent(goal_memory, persistent_memory, generate_fn),
"researcher": ResearcherAgent(goal_memory, persistent_memory, generate_fn),
"reviewer": ReviewerAgent(goal_memory, persistent_memory, generate_fn),
"executor": ExecutorAgent(goal_memory, persistent_memory, generate_fn, tool_registry),
}
self._running = False
self._start_time = 0.0
self._stats = {
"total_goals_assigned": 0,
"total_goals_completed": 0,
"total_goals_failed": 0,
"reassignments": 0,
}
def set_generate_fn(self, fn: Callable[[str], str]) -> None:
"""Set the LLM generation function for all agents."""
self._generate_fn = fn
for agent in self.agents.values():
agent.set_generate_fn(fn)
def start_all(self) -> None:
"""Start all 5 agents."""
self._running = True
self._start_time = time.time()
for agent in self.agents.values():
agent.start()
logger.info("All 5 agents started")
def stop_all(self) -> None:
"""Stop all agents."""
self._running = False
for agent in self.agents.values():
agent.stop()
logger.info("All agents stopped")
def pause_all(self) -> None:
"""Pause all agents."""
for agent in self.agents.values():
agent.pause()
def resume_all(self) -> None:
"""Resume all agents."""
for agent in self.agents.values():
agent.resume()
def create_project(self, title: str, description: str, priority: str = "high",
tags: list[str] | None = None) -> Goal:
"""Create a new project goal and let the planner agent pick it up."""
goal = self.goal_memory.create_goal(
title=title, description=description, priority=priority,
tags=tags or ["project"],
)
self._stats["total_goals_assigned"] += 1
logger.info("Created project: %s (will be picked up by planner agent)", title)
return goal
def assign_goal(self, goal_id: str, agent_name: str) -> bool:
"""Manually assign a goal to a specific agent."""
if agent_name not in self.agents:
logger.warning("Unknown agent: %s", agent_name)
return False
result = self.goal_memory.assign_agent(goal_id, agent_name)
if result:
self._stats["total_goals_assigned"] += 1
return True
return False
def get_active_projects(self) -> list[Goal]:
"""Get all active goals/projects."""
return self.goal_memory.get_active_goals()
def get_agent_status(self) -> dict[str, Any]:
"""Get status of all agents."""
return {name: agent.get_status() for name, agent in self.agents.items()}
def get_project_progress(self) -> list[dict[str, Any]]:
"""Get progress of all active projects."""
active = self.goal_memory.get_active_goals()
return [g.as_dict() for g in active]
def get_stats(self) -> dict[str, Any]:
"""Get aggregated stats."""
agent_stats = {name: agent.get_status()["stats"] for name, agent in self.agents.items()}
goal_stats = self.goal_memory.get_stats()
total_completed = sum(s["goals_completed"] for s in agent_stats.values())
total_failed = sum(s["goals_failed"] for s in agent_stats.values())
total_steps = sum(s["steps_executed"] for s in agent_stats.values())
return {
"manager": {
**self._stats,
"running": self._running,
"uptime_s": round(time.time() - self._start_time, 1) if self._start_time else 0,
"total_goals_completed": total_completed,
"total_goals_failed": total_failed,
"total_steps_executed": total_steps,
},
"agents": agent_stats,
"goals": goal_stats,
}