129 lines
4.8 KiB
Python
129 lines
4.8 KiB
Python
"""Participant Service - unified service for users and agents in chat rooms."""
|
|
import logging
|
|
from typing import Dict, Any, Optional, AsyncGenerator
|
|
|
|
from luxx.agents.base import BaseAgent
|
|
from luxx.agents.registry import agent_registry
|
|
from luxx.models.participant import Participant
|
|
from luxx.services.room import chat_room_service
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ParticipantService:
|
|
"""Unified service for managing participants in chat rooms."""
|
|
|
|
def __init__(self):
|
|
self._active_agents: Dict[str, BaseAgent] = {}
|
|
self._active_users: Dict[int, Any] = {}
|
|
|
|
def _cm(self):
|
|
"""Lazy import connection manager."""
|
|
from luxx.services.room_ws import connection_manager
|
|
return connection_manager
|
|
|
|
# ==================== Agent ====================
|
|
|
|
def register_agent(self, agent: BaseAgent) -> Participant:
|
|
self._active_agents[agent.agent_id] = agent
|
|
agent_registry.register(agent)
|
|
return Participant.from_agent(
|
|
agent.agent_id, agent.name, agent.role, agent.avatar,
|
|
agent.auto_response, agent.mention_trigger, agent.priority
|
|
)
|
|
|
|
def unregister_agent(self, agent_id: str) -> bool:
|
|
if agent_id in self._active_agents:
|
|
del self._active_agents[agent_id]
|
|
agent_registry.unregister(agent_id)
|
|
return True
|
|
return False
|
|
|
|
def get_agent_participant(self, agent_id: str) -> Optional[Participant]:
|
|
agent = self._active_agents.get(agent_id) or chat_room_service.get_agent(agent_id)
|
|
if agent:
|
|
if agent_id not in self._active_agents:
|
|
self._active_agents[agent_id] = agent
|
|
return Participant.from_agent(
|
|
agent.agent_id, agent.name, agent.role, agent.avatar,
|
|
agent.auto_response, agent.mention_trigger, agent.priority
|
|
)
|
|
return None
|
|
|
|
# ==================== User ====================
|
|
|
|
def register_user(self, user) -> Participant:
|
|
self._active_users[user.id] = user
|
|
return Participant.from_user(user)
|
|
|
|
def get_user_participant(self, user_id: int) -> Optional[Participant]:
|
|
user = self._active_users.get(user_id)
|
|
if not user:
|
|
from luxx.core.database import SessionLocal
|
|
from luxx.models.user import User
|
|
db = SessionLocal()
|
|
try:
|
|
user = db.query(User).filter(User.id == user_id).first()
|
|
if user:
|
|
self._active_users[user_id] = user
|
|
finally:
|
|
db.close()
|
|
return Participant.from_user(user) if user else None
|
|
|
|
# ==================== Unified ====================
|
|
|
|
def get_participant(self, participant_id: str, ptype: str = "user") -> Optional[Participant]:
|
|
if ptype == "agent":
|
|
return self.get_agent_participant(participant_id)
|
|
try:
|
|
return self.get_user_participant(int(participant_id))
|
|
except (ValueError, TypeError):
|
|
return None
|
|
|
|
# ==================== Messages ====================
|
|
|
|
async def process_message(
|
|
self, room_id: str, content: str, sender_id: str,
|
|
sender_name: str, sender_type: str = "user", context: Dict = None
|
|
) -> AsyncGenerator[Dict[str, Any], None]:
|
|
cm = self._cm()
|
|
|
|
msg = chat_room_service.save_message(room_id, sender_type, sender_id, sender_name, content)
|
|
await cm.broadcast_to_room(room_id, {"event": "message", "data": msg})
|
|
|
|
room_agents = chat_room_service.get_room_agents(room_id)
|
|
if sender_type == "agent":
|
|
room_agents = [a for a in room_agents if a.agent_id != sender_id]
|
|
|
|
for agent in room_agents:
|
|
await cm.broadcast_to_room(room_id, {
|
|
"event": "typing",
|
|
"data": {"agent_id": agent.agent_id, "agent_name": agent.name, "is_typing": True}
|
|
})
|
|
|
|
ctx = (context or {})
|
|
ctx.update({"sender_type": sender_type, "sender_id": sender_id, "username": sender_name})
|
|
|
|
async for event in chat_room_service.process_message(room_id, content, sender_id, sender_name, ctx):
|
|
yield event
|
|
|
|
for agent in room_agents:
|
|
await cm.broadcast_to_room(room_id, {
|
|
"event": "typing",
|
|
"data": {"agent_id": agent.agent_id, "agent_name": agent.name, "is_typing": False}
|
|
})
|
|
|
|
async def send_message(
|
|
self, room_id: str, participant_id: str,
|
|
participant_type: str, participant_name: str, content: str
|
|
):
|
|
cm = self._cm()
|
|
msg = chat_room_service.save_message(
|
|
room_id, participant_type, participant_id, participant_name, content
|
|
)
|
|
await cm.broadcast_to_room(room_id, {"event": "message", "data": msg})
|
|
return msg
|
|
|
|
|
|
participant_service = ParticipantService()
|