--- name: comfyui_validate_workflow kind: function lang: py domain: ml version: "1.0.0" purity: impure signature: "def comfyui_validate_workflow(workflow: dict, server: str = \"127.0.0.1:8188\", timeout: float = 30.0) -> dict" description: "Valida un workflow ComfyUI (API format) contra el catalogo /object_info de un servidor vivo: cruza los class_type contra los nodos disponibles y los nombres de modelos (ckpt/lora/vae/controlnet/...) contra los combos enumerados de cada nodo. Devuelve nodos y modelos faltantes ANTES de encolar, evitando un HTTP 400. Compone comfyui_object_info. Impura: HTTP GET." tags: [comfyui, ml, validation, workflow, stable-diffusion] uses_functions: [comfyui_object_info_py_ml] uses_types: [] returns: [] returns_optional: false error_type: error_go_core imports: [] params: - name: workflow desc: "dict en API format ({node_id: {class_type, inputs}}) a validar." - name: server desc: "host:port del servidor ComfyUI sin esquema. Debe estar vivo para consultar /object_info." - name: timeout desc: "Timeout de la consulta HTTP en segundos." output: "dict {ok, valid, missing_nodes, missing_models, error}. ok = se pudo consultar el servidor; valid = sin nodos ni modelos faltantes; missing_nodes = class_type ausentes; missing_models = lista de {node, input, value} con valores de modelo fuera del combo; error = motivo si ok=False." tested: false tests: [] test_file_path: "" file_path: "python/functions/ml/comfyui_validate_workflow.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions")) from ml.comfyui_build_txt2img_workflow import comfyui_build_txt2img_workflow from ml.comfyui_validate_workflow import comfyui_validate_workflow wf = comfyui_build_txt2img_workflow("dreamshaper_8.safetensors", "a cat") res = comfyui_validate_workflow(wf) # server 127.0.0.1:8188 vivo # res == {"ok": True, "valid": True, "missing_nodes": [], "missing_models": [], "error": ""} bad = comfyui_build_txt2img_workflow("no_existe.safetensors", "a cat") res2 = comfyui_validate_workflow(bad) # res2["valid"] == False # res2["missing_models"] == [{"node": "4", "input": "ckpt_name", "value": "no_existe.safetensors"}] ``` El bloque de arriba se lanza con el python del venv. El `if __name__ == "__main__"` del archivo valida un txt2img de ejemplo contra el server local (`python/.venv/bin/python3 python/functions/ml/comfyui_validate_workflow.py`). Nota: `./fn run` posicional no aplica porque el primer arg es un dict (workflow), no un escalar de CLI. ## Cuando usarla Siempre ANTES de `comfyui_submit_workflow`, sobre todo con workflows importados de internet (JSON/PNG ajenos) o que mezclen checkpoints/LoRAs que quiza no tengas descargados. Te dice exactamente que nodos custom faltan (a instalar) y que modelos faltan (a descargar) sin gastar un encolado fallido en el servidor. ## Gotchas - Impura: hace HTTP GET a `/object_info`. Requiere el servidor vivo; si esta caido o reiniciandose, devuelve `{ok: False, error: ...}` (no lanza). Reintenta tu. - `missing_models` solo cubre inputs de modelo conocidos (ckpt_name, lora_name, vae_name, control_net_name, model_name, unet_name, clip_name, style_model_name, gligen_name) cuyo valor sea un string fuera del combo enumerado. No valida rangos numericos ni tipos de conexion. - Detecta nodos custom faltantes por class_type ausente en /object_info, pero NO resuelve de que repo instalarlos (eso es trabajo de resolve_workflow_deps, P1). - `sampler_name`/`scheduler` invalidos NO se reportan como missing_models (no son modelos); el servidor los rechazaria al encolar.