diff --git a/client/src/MediaControl.tsx b/client/src/MediaControl.tsx index 53d8580..1c7ef41 100644 --- a/client/src/MediaControl.tsx +++ b/client/src/MediaControl.tsx @@ -953,7 +953,7 @@ const MediaAgent = (props: MediaAgentProps) => { if (media && joinStatus.status === "Not joined" && readyState === ReadyState.OPEN) { console.log(`media-agent - Initiating media join for ${session.name}`); setJoinStatus({ status: "Joining" }); - sendJsonMessage({ type: "join" }); + sendJsonMessage({ type: "join", data: {} }); } }, [media, joinStatus.status, sendJsonMessage, readyState, session.name]); diff --git a/server/main.py b/server/main.py index 87470fd..d45d053 100644 --- a/server/main.py +++ b/server/main.py @@ -1727,13 +1727,13 @@ async def lobby_join( await websocket.accept() if lobby_id is None: await websocket.send_json( - {"type": "error", "error": "Invalid or missing lobby"} + {"type": "error", "data": {"error": "Invalid or missing lobby"}} ) await websocket.close() return if session_id is None: await websocket.send_json( - {"type": "error", "error": "Invalid or missing session"} + {"type": "error", "data": {"error": "Invalid or missing session"}} ) await websocket.close() return @@ -1741,7 +1741,7 @@ async def lobby_join( if not session: # logger.error(f"Invalid session ID {session_id}") await websocket.send_json( - {"type": "error", "error": f"Invalid session ID {session_id}"} + {"type": "error", "data": {"error": f"Invalid session ID {session_id}"}} ) await websocket.close() return @@ -1750,7 +1750,7 @@ async def lobby_join( try: lobby = getLobby(lobby_id) except Exception as e: - await websocket.send_json({"type": "error", "error": str(e)}) + await websocket.send_json({"type": "error", "data": {"error": str(e)}}) await websocket.close() return @@ -1815,7 +1815,7 @@ async def lobby_join( data: dict[str, Any] | None = packet.get("data", None) if not type: logger.error(f"{session.getName()} - Invalid request: {packet}") - await websocket.send_json({"type": "error", "error": "Invalid request"}) + await websocket.send_json({"type": "error", "data": {"error": "Invalid request"}}) continue # logger.info(f"{session.getName()} <- RAW Rx: {data}") match type: @@ -1823,7 +1823,7 @@ async def lobby_join( if not data: logger.error(f"{session.getName()} - set_name missing data") await websocket.send_json( - {"type": "error", "error": "set_name missing data"} + {"type": "error", "data": {"error": "set_name missing data"}} ) continue name = data.get("name") @@ -1832,7 +1832,7 @@ async def lobby_join( if not name: logger.error(f"{session.getName()} - Name required") await websocket.send_json( - {"type": "error", "error": "Name required"} + {"type": "error", "data": {"error": "Name required"}} ) continue # Name takeover / password logic @@ -1868,7 +1868,7 @@ async def lobby_join( f"{session.getName()} - Name already taken (no password set)" ) await websocket.send_json( - {"type": "error", "error": "Name already taken"} + {"type": "error", "data": {"error": "Name already taken"}} ) continue @@ -2030,7 +2030,7 @@ async def lobby_join( f"{session.getName()} - relayICECandidate missing data" ) await websocket.send_json( - {"type": "error", "error": "relayICECandidate missing data"} + {"type": "error", "data": {"error": "relayICECandidate missing data"}} ) continue @@ -2043,7 +2043,7 @@ async def lobby_join( f"{session.short}:{session.name} <- relayICECandidate - Not an RTC peer ({session.id})" ) await websocket.send_json( - {"type": "error", "error": "Not joined to lobby"} + {"type": "error", "data": {"error": "Not joined to lobby"}} ) continue session_peers = session.lobby_peers[lobby.id] @@ -2109,7 +2109,7 @@ async def lobby_join( f"{session.short}:{session.name} <- relaySessionDescription - Not an RTC peer ({session.id})" ) await websocket.send_json( - {"type": "error", "error": "Not joined to lobby"} + {"type": "error", "data": {"error": "Not joined to lobby"}} ) continue @@ -2168,7 +2168,7 @@ async def lobby_join( # Simple status check - just respond with success to keep connection alive logger.debug(f"{session.getName()} <- status_check") await websocket.send_json( - {"type": "status_ok", "timestamp": time.time()} + {"type": "status_ok", "data": {"timestamp": time.time()}} ) case _: diff --git a/shared/models.py b/shared/models.py index a9f0e6a..fd14f45 100644 --- a/shared/models.py +++ b/shared/models.py @@ -194,7 +194,7 @@ class WebSocketMessageModel(BaseModel): """Base model for all WebSocket messages""" type: str - data: ( + data: Optional[ JoinStatusModel | UserJoinedModel | LobbyStateModel @@ -209,7 +209,7 @@ class WebSocketMessageModel(BaseModel): | ChatMessagesListModel | WebSocketErrorModel | Dict[str, str] - ) # Generic dict for simple messages + ] = None # Generic dict for simple messages, optional for status messages # ============================================================================= diff --git a/voicebot/logger.py b/voicebot/logger.py index b6116e3..f961404 100644 --- a/voicebot/logger.py +++ b/voicebot/logger.py @@ -4,8 +4,8 @@ import logging import time from typing import Optional, Tuple -#logging_level = os.getenv("LOGGING_LEVEL", "INFO").upper() -logging_level = os.getenv("LOGGING_LEVEL", "DEBUG").upper() +logging_level = os.getenv("LOGGING_LEVEL", "INFO").upper() +#logging_level = os.getenv("LOGGING_LEVEL", "DEBUG").upper() class RelativePathFormatter(logging.Formatter): diff --git a/voicebot/webrtc_signaling.py b/voicebot/webrtc_signaling.py index 97d9e7d..9388fed 100644 --- a/voicebot/webrtc_signaling.py +++ b/voicebot/webrtc_signaling.py @@ -469,9 +469,11 @@ class WebRTCSignalingClient: ws = cast(WebSocketProtocol, self.websocket) # Build message with explicit type to avoid type narrowing - message: dict[str, object] = {"type": message_type} - if data is not None: - message["data"] = data + # Always include data field to match WebSocketMessageModel + message: dict[str, object] = { + "type": message_type, + "data": data if data is not None else {} + } try: logger.debug(f"_send_message: Sending {message_type} with data: {data}") @@ -563,6 +565,9 @@ class WebRTCSignalingClient: ) if msg_type == "addPeer": + if data is None: + logger.error("addPeer message missing required data") + return try: validated = AddPeerModel.model_validate(data) except ValidationError as e: @@ -623,11 +628,11 @@ class WebRTCSignalingClient: logger.info(f"Received update message: {validated}") elif msg_type == "status_check": # Handle status check messages - these are used to verify connection - logger.debug(f"Received status check message: {data}") + logger.debug(f"Received status check message with data: {data}") # No special processing needed for status checks, just acknowledge receipt elif msg_type == "status_ok": # Handle status_ok response from server - logger.debug(f"Received status_ok from server: {data}") + logger.debug(f"Received status_ok from server with data: {data}") # This confirms the connection is healthy elif msg_type == "chat_message": logger.info("Received chat message")