192 lines
6.9 KiB
Python
Raw Normal View History

2025-11-04 05:17:27 +01:00
import json
2025-11-04 08:09:12 +01:00
import time
2025-11-04 05:17:27 +01:00
import uuid
from dataclasses import dataclass, field
2025-11-04 08:09:12 +01:00
from typing import Any, Callable, Dict, List, Optional
2025-11-04 07:52:36 +01:00
from ..memory.knowledge_store import KnowledgeStore
2025-11-04 08:09:12 +01:00
from .agent_communication import AgentCommunicationBus, AgentMessage, MessageType
from .agent_roles import AgentRole, get_agent_role
2025-11-04 05:17:27 +01:00
@dataclass
class AgentInstance:
agent_id: str
role: AgentRole
message_history: List[Dict[str, Any]] = field(default_factory=list)
context: Dict[str, Any] = field(default_factory=dict)
created_at: float = field(default_factory=time.time)
task_count: int = 0
def add_message(self, role: str, content: str):
2025-11-04 08:10:37 +01:00
self.message_history.append({"role": role, "content": content, "timestamp": time.time()})
2025-11-04 05:17:27 +01:00
def get_system_message(self) -> Dict[str, str]:
2025-11-04 08:09:12 +01:00
return {"role": "system", "content": self.role.system_prompt}
2025-11-04 05:17:27 +01:00
def get_messages_for_api(self) -> List[Dict[str, str]]:
return [self.get_system_message()] + [
2025-11-04 08:10:37 +01:00
{"role": msg["role"], "content": msg["content"]} for msg in self.message_history
2025-11-04 05:17:27 +01:00
]
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
class AgentManager:
def __init__(self, db_path: str, api_caller: Callable):
self.db_path = db_path
self.api_caller = api_caller
self.communication_bus = AgentCommunicationBus(db_path)
2025-11-04 07:52:36 +01:00
self.knowledge_store = KnowledgeStore(db_path)
2025-11-04 05:17:27 +01:00
self.active_agents: Dict[str, AgentInstance] = {}
self.session_id = str(uuid.uuid4())[:16]
def create_agent(self, role_name: str, agent_id: Optional[str] = None) -> str:
if agent_id is None:
agent_id = f"{role_name}_{str(uuid.uuid4())[:8]}"
role = get_agent_role(role_name)
2025-11-04 08:09:12 +01:00
agent = AgentInstance(agent_id=agent_id, role=role)
2025-11-04 05:17:27 +01:00
self.active_agents[agent_id] = agent
return agent_id
def get_agent(self, agent_id: str) -> Optional[AgentInstance]:
return self.active_agents.get(agent_id)
2025-11-04 08:09:12 +01:00
2025-11-04 05:17:27 +01:00
def remove_agent(self, agent_id: str) -> bool:
if agent_id in self.active_agents:
del self.active_agents[agent_id]
return True
return False
2025-11-04 08:09:12 +01:00
def execute_agent_task(
self, agent_id: str, task: str, context: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
2025-11-04 05:17:27 +01:00
agent = self.get_agent(agent_id)
if not agent:
2025-11-04 08:09:12 +01:00
return {"error": f"Agent {agent_id} not found"}
2025-11-04 05:17:27 +01:00
if context:
agent.context.update(context)
2025-11-04 08:09:12 +01:00
agent.add_message("user", task)
2025-11-04 07:52:36 +01:00
knowledge_matches = self.knowledge_store.search_entries(task, top_k=3)
2025-11-04 05:17:27 +01:00
agent.task_count += 1
messages = agent.get_messages_for_api()
2025-11-04 07:52:36 +01:00
if knowledge_matches:
knowledge_content = "Knowledge base matches based on your query:\\n"
for i, entry in enumerate(knowledge_matches, 1):
shortened_content = entry.content[:2000]
knowledge_content += f"{i}. {shortened_content}\\n\\n"
2025-11-04 08:09:12 +01:00
messages.insert(-1, {"role": "user", "content": knowledge_content})
2025-11-04 05:17:27 +01:00
try:
response = self.api_caller(
messages=messages,
temperature=agent.role.temperature,
2025-11-04 08:09:12 +01:00
max_tokens=agent.role.max_tokens,
2025-11-04 05:17:27 +01:00
)
2025-11-04 08:09:12 +01:00
if response and "choices" in response:
assistant_message = response["choices"][0]["message"]["content"]
agent.add_message("assistant", assistant_message)
2025-11-04 05:17:27 +01:00
return {
2025-11-04 08:09:12 +01:00
"success": True,
"agent_id": agent_id,
"response": assistant_message,
"role": agent.role.name,
"task_count": agent.task_count,
2025-11-04 05:17:27 +01:00
}
else:
2025-11-04 08:09:12 +01:00
return {"error": "Invalid API response", "agent_id": agent_id}
2025-11-04 05:17:27 +01:00
except Exception as e:
2025-11-04 08:09:12 +01:00
return {"error": str(e), "agent_id": agent_id}
def send_agent_message(
self,
from_agent_id: str,
to_agent_id: str,
content: str,
message_type: MessageType = MessageType.REQUEST,
metadata: Optional[Dict[str, Any]] = None,
):
2025-11-04 05:17:27 +01:00
message = AgentMessage(
from_agent=from_agent_id,
to_agent=to_agent_id,
message_type=message_type,
content=content,
metadata=metadata or {},
timestamp=time.time(),
2025-11-04 08:09:12 +01:00
message_id=str(uuid.uuid4())[:16],
2025-11-04 05:17:27 +01:00
)
self.communication_bus.send_message(message, self.session_id)
return message.message_id
2025-11-04 08:10:37 +01:00
def get_agent_messages(self, agent_id: str, unread_only: bool = True) -> List[AgentMessage]:
2025-11-04 05:17:27 +01:00
return self.communication_bus.get_messages(agent_id, unread_only)
2025-11-04 08:10:37 +01:00
def collaborate_agents(self, orchestrator_id: str, task: str, agent_roles: List[str]):
2025-11-04 05:17:27 +01:00
orchestrator = self.get_agent(orchestrator_id)
if not orchestrator:
2025-11-04 08:09:12 +01:00
orchestrator_id = self.create_agent("orchestrator")
2025-11-04 05:17:27 +01:00
orchestrator = self.get_agent(orchestrator_id)
worker_agents = []
for role in agent_roles:
agent_id = self.create_agent(role)
2025-11-04 08:09:12 +01:00
worker_agents.append({"agent_id": agent_id, "role": role})
2025-11-04 05:17:27 +01:00
2025-11-04 08:09:12 +01:00
orchestration_prompt = f"""Task: {task}
2025-11-04 05:17:27 +01:00
Available specialized agents:
{chr(10).join([f"- {a['agent_id']} ({a['role']})" for a in worker_agents])}
2025-11-04 08:09:12 +01:00
Break down the task and delegate subtasks to appropriate agents. Coordinate their work and integrate results."""
2025-11-04 05:17:27 +01:00
2025-11-04 08:10:37 +01:00
orchestrator_result = self.execute_agent_task(orchestrator_id, orchestration_prompt)
2025-11-04 05:17:27 +01:00
2025-11-04 08:09:12 +01:00
results = {"orchestrator": orchestrator_result, "agents": []}
2025-11-04 05:17:27 +01:00
for agent_info in worker_agents:
2025-11-04 08:09:12 +01:00
agent_id = agent_info["agent_id"]
2025-11-04 05:17:27 +01:00
messages = self.get_agent_messages(agent_id)
for msg in messages:
subtask = msg.content
result = self.execute_agent_task(agent_id, subtask)
2025-11-04 08:09:12 +01:00
results["agents"].append(result)
2025-11-04 05:17:27 +01:00
self.send_agent_message(
from_agent_id=agent_id,
to_agent_id=orchestrator_id,
2025-11-04 08:09:12 +01:00
content=result.get("response", ""),
message_type=MessageType.RESPONSE,
2025-11-04 05:17:27 +01:00
)
self.communication_bus.mark_as_read(msg.message_id)
return results
2025-11-04 05:57:23 +01:00
def get_session_summary(self) -> str:
2025-11-04 05:17:27 +01:00
summary = {
2025-11-04 08:09:12 +01:00
"session_id": self.session_id,
"active_agents": len(self.active_agents),
"agents": [
2025-11-04 05:17:27 +01:00
{
2025-11-04 08:09:12 +01:00
"agent_id": agent_id,
"role": agent.role.name,
"task_count": agent.task_count,
"message_count": len(agent.message_history),
2025-11-04 05:17:27 +01:00
}
for agent_id, agent in self.active_agents.items()
2025-11-04 08:09:12 +01:00
],
2025-11-04 05:17:27 +01:00
}
2025-11-04 05:57:23 +01:00
return json.dumps(summary)
2025-11-04 05:17:27 +01:00
def clear_session(self):
self.active_agents.clear()
self.communication_bus.clear_messages(session_id=self.session_id)
2025-11-04 08:09:12 +01:00
self.session_id = str(uuid.uuid4())[:16]