feat(ml): auto-commit con 7 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
"""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))
|
||||
Reference in New Issue
Block a user