"""Gestiona la cola y el historial de un servidor ComfyUI via su API HTTP. Funcion impura: hace red (HTTP GET/POST). Solo stdlib (urllib, json). Completa lo que comfyui_interrupt_queue no cubre. interrupt_queue corta el prompt en ejecucion; esta funcion expone las cuatro operaciones restantes de la cola: - "status": GET /queue -> cuantos prompts se ejecutan ahora (queue_running) y cuantos estan encolados pendientes (queue_pending). - "clear": POST /queue {"clear": true} -> vacia los pendientes de golpe. - "delete": POST /queue {"delete": [prompt_id]} -> borra un prompt concreto de la cola de pendientes (requiere prompt_id). - "history": GET /history -> numero de prompts ya ejecutados que el servidor recuerda (history_count). NO lanza excepcion en fallo de red: degrada a {ok: False, error}. """ import json import urllib.error import urllib.request def comfyui_queue_manage( action: str, *, server: str = "127.0.0.1:8188", prompt_id: str | None = None, ) -> dict: """Opera la cola/historial de ComfyUI: status, clear, delete o history. Args: action: operacion a realizar. Una de: - "status": lee el estado de la cola. - "clear": vacia los prompts pendientes (POST /queue {"clear": true}). - "delete": borra un prompt concreto (POST /queue {"delete": [id]}); requiere prompt_id. - "history": cuenta los prompts en el historial (GET /history). server: host:port del servidor ComfyUI sin esquema (default "127.0.0.1:8188"). keyword-only. prompt_id: id del prompt a borrar; obligatorio solo para action="delete". keyword-only. Returns: dict con: - ok (bool): True si la operacion se completo sin error. - action (str): la accion solicitada (eco). - queue_running (int): prompts ejecutandose ahora (status/clear/delete). - queue_pending (int): prompts encolados pendientes (status/clear/delete). - history_count (int): numero de prompts en el historial (action=history). - error (str): mensaje de error; cadena vacia si todo OK. """ out = { "ok": False, "action": action, "queue_running": 0, "queue_pending": 0, "history_count": 0, "error": "", } base = f"http://{server}" valid = {"status", "clear", "delete", "history"} if action not in valid: out["error"] = f"action desconocida: {action!r}; usa una de {sorted(valid)}" return out def _read_queue() -> bool: """Rellena queue_running/queue_pending desde GET /queue. True si OK.""" try: with urllib.request.urlopen(f"{base}/queue", timeout=10.0) as resp: data = json.loads(resp.read()) out["queue_running"] = len(data.get("queue_running", [])) out["queue_pending"] = len(data.get("queue_pending", [])) return True except urllib.error.URLError as exc: reason = getattr(exc, "reason", exc) out["error"] = f"GET /queue fallo: no se pudo conectar a {base}/queue: {reason}" except json.JSONDecodeError as exc: out["error"] = f"GET /queue fallo: respuesta no es JSON valido: {exc}" return False def _post_queue(body: dict) -> bool: """POST /queue con cuerpo JSON. True si el servidor respondio sin error.""" try: payload = json.dumps(body).encode() req = urllib.request.Request( f"{base}/queue", data=payload, method="POST", headers={"Content-Type": "application/json"}, ) with urllib.request.urlopen(req, timeout=10.0): return True except urllib.error.URLError as exc: reason = getattr(exc, "reason", exc) out["error"] = f"POST /queue fallo: no se pudo conectar a {base}/queue: {reason}" return False if action == "status": out["ok"] = _read_queue() return out if action == "clear": if _post_queue({"clear": True}): out["ok"] = _read_queue() return out if action == "delete": if not prompt_id: out["error"] = "action='delete' requiere prompt_id" return out if _post_queue({"delete": [prompt_id]}): out["ok"] = _read_queue() return out # action == "history" try: with urllib.request.urlopen(f"{base}/history", timeout=15.0) as resp: hist = json.loads(resp.read()) out["history_count"] = len(hist) if isinstance(hist, dict) else 0 out["ok"] = True except urllib.error.URLError as exc: reason = getattr(exc, "reason", exc) out["error"] = f"GET /history fallo: no se pudo conectar a {base}/history: {reason}" except json.JSONDecodeError as exc: out["error"] = f"GET /history fallo: respuesta no es JSON valido: {exc}" return out if __name__ == "__main__": import sys act = sys.argv[1] if len(sys.argv) > 1 else "status" pid = sys.argv[2] if len(sys.argv) > 2 else None res = comfyui_queue_manage(act, prompt_id=pid) print(json.dumps(res, indent=2))