"""Chat Room API Routes""" from typing import List, Optional from fastapi import APIRouter, HTTPException from pydantic import BaseModel from luxx.services.room import chat_room_service router = APIRouter(prefix="/chat-rooms", tags=["chat-rooms"]) class CreateChatRoomRequest(BaseModel): name: str description: Optional[str] = None agent_ids: Optional[List[str]] = None class UpdateChatRoomRequest(BaseModel): name: Optional[str] = None description: Optional[str] = None is_active: Optional[bool] = None class SendMessageRequest(BaseModel): content: str reply_to: Optional[str] = None # Message ID to reply to mentions: Optional[List[str]] = None # Mentioned agent IDs class AddAgentRequest(BaseModel): agent_id: str def get_current_user_id() -> int: """Get current user ID from auth context""" return 1 @router.get("") async def list_chat_rooms(): """List all chat rooms""" user_id = get_current_user_id() rooms = chat_room_service.list_rooms(user_id=user_id) return {"rooms": rooms} @router.post("") async def create_chat_room(request: CreateChatRoomRequest): """Create a new chat room""" user_id = get_current_user_id() room = chat_room_service.create_room( name=request.name, owner_id=user_id, description=request.description, agent_ids=request.agent_ids ) return {"room": room} @router.get("/{room_id}") async def get_chat_room(room_id: str): """Get a chat room by ID with agents""" room = chat_room_service.get_room(room_id) if not room: raise HTTPException(status_code=404, detail="Chat room not found") return {"room": room.to_dict(include_agents=True)} @router.put("/{room_id}") async def update_chat_room(room_id: str, request: UpdateChatRoomRequest): """Update a chat room""" room = chat_room_service.update_room( room_id=room_id, name=request.name, description=request.description, is_active=request.is_active ) if not room: raise HTTPException(status_code=404, detail="Chat room not found") return {"room": room} @router.delete("/{room_id}") async def delete_chat_room(room_id: str): """Delete a chat room and all related data""" success = chat_room_service.delete_room(room_id) if not success: raise HTTPException(status_code=404, detail="Chat room not found") return {"success": True} @router.get("/{room_id}/agents") async def get_room_agents(room_id: str): """Get all agents in a chat room (from stable RoomAgent table)""" # Return both BaseAgent objects and info from RoomAgent table agents = chat_room_service.get_room_agents(room_id) agents_info = chat_room_service.get_room_agents_info(room_id) # Merge agent data agent_data = [] for agent in agents: agent_dict = agent.to_dict() # Find matching info for info in agents_info: if info.get("id") == agent.agent_id: agent_dict.update(info) break agent_data.append(agent_dict) return {"agents": agent_data, "count": len(agent_data)} @router.post("/{room_id}/agents") async def add_agent_to_room(room_id: str, request: AddAgentRequest): """Add an agent to a chat room""" success = chat_room_service.add_agent_to_room(room_id, request.agent_id) if not success: raise HTTPException(status_code=400, detail="Failed to add agent") # Return updated agents list agents = chat_room_service.get_room_agents_info(room_id) return {"success": True, "agents": agents} @router.delete("/{room_id}/agents/{agent_id}") async def remove_agent_from_room(room_id: str, agent_id: str): """Remove an agent from a chat room""" success = chat_room_service.remove_agent_from_room(room_id, agent_id) if not success: raise HTTPException(status_code=404, detail="Agent not found in room") return {"success": True} @router.get("/{room_id}/messages") async def get_room_messages(room_id: str, limit: int = 50, before_id: str = None): """Get messages from a chat room""" messages = chat_room_service.get_messages(room_id, limit=limit, before_id=before_id) return {"messages": messages, "count": len(messages)} @router.post("/{room_id}/messages") async def send_message(room_id: str, request: SendMessageRequest): """Send a message to a chat room. Returns a streaming response via SSE. This endpoint is for HTTP-based messaging. WebSocket is preferred for real-time chat. """ from fastapi.responses import StreamingResponse import json user_id = str(get_current_user_id()) user_name = "User" async def generate(): # Save user message first user_msg = chat_room_service.save_message( room_id=room_id, sender_type="user", sender_name=user_name, content=request.content, sender_id=user_id, mentions=request.mentions, parent_id=request.reply_to ) # Yield saved message event yield f"data: {json.dumps({'event': 'message', 'data': {'message': user_msg}}, ensure_ascii=False)}\n\n" # Process and stream agent responses async for event in chat_room_service.process_message( room_id=room_id, user_message=request.content, sender_id=user_id, sender_name=user_name ): yield f"data: {json.dumps(event, ensure_ascii=False)}\n\n" return StreamingResponse( generate(), media_type="text/event-stream", headers={ "Cache-Control": "no-cache", "Connection": "keep-alive", "X-Accel-Buffering": "no" } )