NEXON / backend /api /routes /websocket.py
ashishMenon05
fix(backend): fix syntax error in reset handler and properly flush UI terminal logs
174293c
import json
from datetime import datetime
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from typing import List
from utils.logger import logger
router = APIRouter()
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
logger.info(f"WebSocket connected. Total: {len(self.active_connections)}")
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
logger.info(f"WebSocket disconnected. Total: {len(self.active_connections)}")
async def broadcast(self, event_type: str, payload: dict):
message = {
"type": event_type,
"timestamp": datetime.utcnow().isoformat(),
**payload
}
for connection in self.active_connections:
try:
await connection.send_json(message)
except Exception as e:
logger.error(f"Error sending broadcast: {e}")
manager = ConnectionManager()
broadcast = manager.broadcast
@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await manager.connect(websocket)
try:
from core.episode_manager import episode_manager
from api.routes.openenv import start_simulation
while True:
data = await websocket.receive_text()
try:
cmd = json.loads(data)
action = cmd.get("action")
if action == "start":
logger.info("UI Command: START")
await start_simulation()
elif action == "pause":
episode_manager.is_paused = not episode_manager.is_paused
logger.info(f"UI Command: PAUSE -> {episode_manager.is_paused}")
# Broadcast both the pause flag and a status string for the UI header
await broadcast("system_status", {
"paused": episode_manager.is_paused,
"status": "PAUSED" if episode_manager.is_paused else "INVESTIGATING"
})
elif action == "reset":
logger.info("UI Command: RESET")
await episode_manager.reset(task="software-incident", broadcast_episode=False)
await broadcast("system_status", {"paused": False, "status": "READY", "active": False})
elif action == "force_end":
logger.info("UI Command: FORCE_END")
if episode_manager.env and episode_manager.env.active_episode:
episode_manager.env.active_episode.done = True
episode_manager.env.active_episode.fix_verified = True
# Immediately update local status and broadcast to UI
await broadcast("system_status", {"status": "COMPLETED", "active": False})
except Exception as e:
logger.error(f"Error handling WS command: {e}")
except WebSocketDisconnect:
manager.disconnect(websocket)