ff41f4f053
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
136 lines
5.1 KiB
Python
136 lines
5.1 KiB
Python
"""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))
|