"""Interrumpe la generacion en curso de ComfyUI y, opcionalmente, vacia la cola. Funcion impura: hace red (HTTP POST /interrupt, POST /queue, GET /queue). Solo stdlib (urllib, json). POST /interrupt corta el prompt que ComfyUI esta ejecutando ahora mismo: NO vacia los pendientes, solo aborta el actual y el siguiente arranca de inmediato. Para vaciar de golpe los pendientes hay que ademas hacer POST /queue con {"clear": true} (lo que activa el flag clear_pending). GET /queue se consulta al final para reportar cuantos trabajos quedan en cola tras la operacion (queue_remaining). NO lanza excepcion en fallo de red: devuelve un dict de estado {ok: False, error}. """ import json import urllib.error import urllib.request def comfyui_interrupt_queue( *, clear_pending: bool = False, server: str = "127.0.0.1:8188", timeout: float = 10.0, ) -> dict: """Corta la generacion en curso de ComfyUI y devuelve el estado de la cola. Args: clear_pending: si True, ademas de cortar el prompt en ejecucion vacia la cola de pendientes con POST /queue {"clear": true}. keyword-only. server: host:port del servidor ComfyUI sin esquema (default "127.0.0.1:8188"). keyword-only. timeout: timeout de cada peticion HTTP en segundos (default 10.0). keyword-only. Returns: dict con: - ok (bool): True si el interrupt, la lectura de la cola y (si se pidio) el clear tuvieron exito. - interrupted (bool): True si el POST /interrupt respondio sin error. - cleared (bool): True si clear_pending era True y el POST /queue {"clear": true} respondio sin error; False si no se pidio o fallo. - queue_remaining (int): trabajos que quedan en cola tras la operacion (queue_running + queue_pending segun GET /queue al final). - error (str): mensaje de error si algo fallo; cadena vacia si todo OK. """ out = { "ok": False, "interrupted": False, "cleared": False, "queue_remaining": 0, "error": "", } base = f"http://{server}" # 1. POST /interrupt (cuerpo vacio): corta el prompt en ejecucion. try: req = urllib.request.Request(f"{base}/interrupt", data=b"", method="POST") with urllib.request.urlopen(req, timeout=timeout): out["interrupted"] = True except urllib.error.URLError as exc: reason = getattr(exc, "reason", exc) out["error"] = f"interrupt fallo: no se pudo conectar a {base}/interrupt: {reason}" return out # 2. Opcional: POST /queue {"clear": true} para vaciar los pendientes. if clear_pending: try: payload = json.dumps({"clear": True}).encode() req = urllib.request.Request( f"{base}/queue", data=payload, method="POST", headers={"Content-Type": "application/json"}, ) with urllib.request.urlopen(req, timeout=timeout): out["cleared"] = True except urllib.error.URLError as exc: reason = getattr(exc, "reason", exc) out["error"] = f"clear fallo: no se pudo conectar a {base}/queue: {reason}" return out # 3. GET /queue: cuantos trabajos quedan en cola tras la operacion. try: with urllib.request.urlopen(f"{base}/queue", timeout=timeout) as resp: data = json.loads(resp.read()) running = len(data.get("queue_running", [])) pending = len(data.get("queue_pending", [])) out["queue_remaining"] = running + pending out["ok"] = True except urllib.error.URLError as exc: reason = getattr(exc, "reason", exc) out["error"] = f"queue fallo: no se pudo conectar a {base}/queue: {reason}" except json.JSONDecodeError as exc: out["error"] = f"queue fallo: respuesta no es JSON valido: {exc}" return out if __name__ == "__main__": import sys clear = "--clear" in sys.argv[1:] res = comfyui_interrupt_queue(clear_pending=clear) print( f"ok={res['ok']} interrupted={res['interrupted']} " f"cleared={res['cleared']} queue_remaining={res['queue_remaining']} " f"error={res['error']!r}" )