refactor: remove SPADE dependencies
Did not look at tests yet, this is a very non-final commit. ref: N25B-300
This commit is contained in:
87
src/control_backend/core/agent_system.py
Normal file
87
src/control_backend/core/agent_system.py
Normal file
@@ -0,0 +1,87 @@
|
||||
import asyncio
|
||||
import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any
|
||||
|
||||
# Central directory to resolve agent names to instances
|
||||
_agent_directory: dict[str, "BaseAgent"] = {}
|
||||
|
||||
|
||||
@dataclass
|
||||
class InternalMessage:
|
||||
to: str
|
||||
sender: str
|
||||
body: str
|
||||
thread: str | None = None
|
||||
metadata: dict[str, Any] = field(default_factory=dict)
|
||||
|
||||
|
||||
class AgentDirectory:
|
||||
@staticmethod
|
||||
def register(name: str, agent: "BaseAgent"):
|
||||
_agent_directory[name] = agent
|
||||
|
||||
@staticmethod
|
||||
def get(name: str) -> "BaseAgent | None":
|
||||
return _agent_directory.get(name)
|
||||
|
||||
|
||||
class BaseAgent(ABC):
|
||||
logger: logging.Logger
|
||||
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
self.jid = name # present for backwards compatibility
|
||||
self.inbox: asyncio.Queue[InternalMessage] = asyncio.Queue()
|
||||
self._tasks: set[asyncio.Task] = set()
|
||||
self._running = False
|
||||
|
||||
# Register immediately
|
||||
AgentDirectory.register(name, self)
|
||||
|
||||
@abstractmethod
|
||||
async def setup(self):
|
||||
"""Override this to initialize resources."""
|
||||
pass
|
||||
|
||||
async def start(self):
|
||||
"""Starts the agent and its loops."""
|
||||
self.logger.info(f"Starting agent {self.name}")
|
||||
self._running = True
|
||||
await self.setup()
|
||||
|
||||
# Start processing inbox
|
||||
await self.add_background_task(self._process_inbox())
|
||||
|
||||
async def stop(self):
|
||||
"""Stops the agent."""
|
||||
self._running = False
|
||||
for task in self._tasks:
|
||||
task.cancel()
|
||||
self.logger.info(f"Agent {self.name} stopped")
|
||||
|
||||
async def send(self, message: InternalMessage):
|
||||
target = AgentDirectory.get(message.to)
|
||||
if target:
|
||||
await target.inbox.put(message)
|
||||
else:
|
||||
self.logger.warning(f"Attempted to send message to unknown agent: {message.to}")
|
||||
|
||||
async def _process_inbox(self):
|
||||
"""Default loop: equivalent to a CyclicBehaviour receiving messages."""
|
||||
while self._running:
|
||||
msg = await self.inbox.get()
|
||||
await self.handle_message(msg)
|
||||
|
||||
async def handle_message(self, msg: InternalMessage):
|
||||
"""Override this to handle incoming messages."""
|
||||
raise NotImplementedError
|
||||
|
||||
async def add_background_task(self, coro):
|
||||
"""Helper to run cyclic behaviors."""
|
||||
task = asyncio.create_task(coro)
|
||||
self._tasks.add(task)
|
||||
task.add_done_callback(self._tasks.discard)
|
||||
|
||||
# await asyncio.sleep(1)
|
||||
Reference in New Issue
Block a user