--- name: comfyui_search_civitai_models kind: function lang: py domain: ml version: "1.0.0" purity: impure signature: "def comfyui_search_civitai_models(query: str, *, types: str = \"Checkpoint\", base_model: str | None = None, sort: str = \"Highest Rated\", limit: int = 20, token: str | None = None) -> dict" description: "Busca modelos/LoRAs en Civitai via su API publica GET /api/v1/models y normaliza cada resultado a {name, type, base_model, version_id, download_url, nsfw} (primera version del modelo). La busqueda publica funciona SIN token; el token solo sube el rate limit y desbloquea modelos restringidos. Impura: HTTP GET a civitai.com. Solo stdlib." tags: [comfyui, ml, civitai, search, models, stable-diffusion, http] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: ["json", "urllib.error", "urllib.parse", "urllib.request"] params: - name: query desc: "Texto de busqueda (nombre del modelo, ej. 'dreamshaper')." - name: types desc: "Tipo(s) de modelo Civitai, CSV: Checkpoint, LORA, TextualInversion, Controlnet, VAE, Upscaler, ... keyword-only." - name: base_model desc: "Filtra por modelo base (ej. 'SD 1.5', 'SDXL 1.0'). None no filtra. keyword-only." - name: sort desc: "Orden Civitai: 'Highest Rated', 'Most Downloaded', 'Newest'. keyword-only." - name: limit desc: "Numero maximo de resultados (1-100). keyword-only." - name: token desc: "API token de Civitai (header Authorization Bearer). Opcional: la busqueda publica funciona sin el. No hardcodear: pasar desde pass/vault. keyword-only." output: "dict {ok, items, count, error}. items = lista de {name, type, base_model, version_id, download_url, nsfw} (primera version de cada modelo). ok=False con error si la peticion falla; una busqueda sin resultados devuelve ok=True con items=[] (no es error)." tested: false tests: [] test_file_path: "" file_path: "python/functions/ml/comfyui_search_civitai_models.py" --- ## Ejemplo ```python import sys, os sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions")) from ml.comfyui_search_civitai_models import comfyui_search_civitai_models # Busqueda publica, sin token: out = comfyui_search_civitai_models("dreamshaper", types="Checkpoint", limit=5) for it in out["items"]: print(it["name"], it["base_model"], "->", it["download_url"]) # out["items"][0] == {"name": "DreamShaper", "type": "Checkpoint", # "base_model": "SD 1.5", "version_id": 128713, # "download_url": "https://civitai.com/api/download/models/128713", "nsfw": False} # Filtrar LoRAs SDXL, con token desde pass (si lo hubiera): # import subprocess # tok = subprocess.run(["pass","civitai/api-token"], capture_output=True, text=True).stdout.strip() or None # loras = comfyui_search_civitai_models("detail", types="LORA", base_model="SDXL 1.0", token=tok) ``` El `download_url` que devuelve se pasa directo a `comfyui_download_model(url=...)` para bajar el modelo a la carpeta correcta. ## Cuando usarla Cuando necesites descubrir un checkpoint o LoRA por nombre/tema antes de descargarlo: te da el `download_url` listo para `comfyui_download_model`. Encadena con `comfyui_resolve_workflow_deps` para resolver los modelos que le faltan a un workflow ajeno. ## Gotchas - Impura: HTTP GET a `civitai.com`. Requiere conexion a internet (NO usa el server local de ComfyUI, asi que no choca con reinicios del server). - La busqueda publica funciona sin token. Sin token el rate limit es mas bajo y algunos modelos restringidos no aparecen o su `download_url` exige login. - `download_url` apunta a `api/download/models/`: muchos modelos exigen token para descargar aunque salgan en la busqueda (Civitai responde HTML de login). `comfyui_download_model` detecta ese HTML y devuelve ok=False. - Solo se devuelve la PRIMERA version de cada modelo (`modelVersions[0]`, la mas reciente). Para versiones antiguas consulta la API por `version_id`. - Una busqueda sin resultados NO es error: devuelve `ok=True, items=[], count=0`. - No hardcodear el token: pasarlo desde `pass`/vault.