"""GET/POST /api/server/{action}; GET /api/logs/tail""" from __future__ import annotations import logging from pathlib import Path from fastapi import APIRouter, Depends, HTTPException from web.auth import require_auth from web.deps import get_config, get_comfy router = APIRouter() logger = logging.getLogger(__name__) @router.get("/server/status") async def server_status(_: dict = Depends(require_auth)): """Return NSSM service state and HTTP health.""" config = get_config() if config is None: raise HTTPException(503, "Config not available") from commands.server import get_service_state import asyncio async def _false(): return False comfy = get_comfy() service_state, http_ok = await asyncio.gather( get_service_state(config.comfy_service_name), comfy.check_connection() if comfy else _false(), ) return {"service_state": service_state, "http_reachable": http_ok} @router.post("/server/{action}") async def server_action(action: str, _: dict = Depends(require_auth)): """Control the ComfyUI service: start | stop | restart | install | uninstall""" config = get_config() if config is None: raise HTTPException(503, "Config not available") valid_actions = {"start", "stop", "restart", "install", "uninstall"} if action not in valid_actions: raise HTTPException(400, f"Invalid action '{action}'") from commands.server import _nssm, _install_service import asyncio try: if action == "install": ok, msg = await _install_service(config) if not ok: raise HTTPException(500, msg) elif action == "uninstall": await _nssm("stop", config.comfy_service_name) await _nssm("remove", config.comfy_service_name, "confirm") elif action == "start": await _nssm("start", config.comfy_service_name) elif action == "stop": await _nssm("stop", config.comfy_service_name) elif action == "restart": await _nssm("restart", config.comfy_service_name) except HTTPException: raise except Exception as exc: raise HTTPException(500, str(exc)) return {"ok": True, "action": action} @router.get("/logs/tail") async def tail_logs(lines: int = 100, _: dict = Depends(require_auth)): """Tail the ComfyUI log file.""" config = get_config() if config is None or not config.comfy_log_dir: raise HTTPException(503, "Log directory not configured") log_dir = Path(config.comfy_log_dir) log_file = log_dir / "comfyui.log" if not log_file.exists(): return {"lines": []} try: with open(log_file, "r", encoding="utf-8", errors="replace") as f: all_lines = f.readlines() tail = all_lines[-min(lines, len(all_lines)):] return {"lines": [ln.rstrip("\n") for ln in tail]} except Exception as exc: raise HTTPException(500, str(exc))