chore: auto-commit (61 archivos)

- docs/capabilities/INDEX.md
- docs/capabilities/comfyui.md
- python/functions/browser/comfyui_export_workflow_ui.md
- python/functions/browser/comfyui_export_workflow_ui.py
- python/functions/browser/comfyui_load_workflow_ui.md
- python/functions/browser/comfyui_load_workflow_ui.py
- python/functions/browser/comfyui_queue_prompt_ui.md
- python/functions/browser/comfyui_queue_prompt_ui.py
- python/functions/browser/comfyui_refresh_nodes_ui.md
- python/functions/browser/comfyui_refresh_nodes_ui.py
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 00:30:30 +02:00
parent 495f545ec1
commit f12272d002
72 changed files with 6049 additions and 0 deletions
@@ -0,0 +1,101 @@
"""Busca modelos / LoRAs en Civitai via su API publica GET /api/v1/models.
Normaliza cada resultado a un dict pequeno y reutilizable
({name, type, base_model, version_id, download_url, nsfw}) tomando la primera
version del modelo. La busqueda publica funciona sin token; pasar un token solo
sube el rate limit y desbloquea modelos restringidos.
Impura: red (HTTP GET a civitai.com). Solo stdlib (urllib, json).
"""
import json
import urllib.error
import urllib.parse
import urllib.request
_API = "https://civitai.com/api/v1/models"
_TIMEOUT = 30.0
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:
"""Busca modelos en Civitai y devuelve resultados normalizados.
Args:
query: texto de busqueda (nombre del modelo, ej. "dreamshaper").
types: tipo(s) de modelo, CSV. Valores Civitai: Checkpoint, LORA,
TextualInversion, Controlnet, VAE, Upscaler, ... keyword-only.
base_model: filtra por modelo base (ej. "SD 1.5", "SDXL 1.0"). None no
filtra. keyword-only.
sort: orden Civitai ("Highest Rated", "Most Downloaded", "Newest").
keyword-only.
limit: numero maximo de resultados (1-100). keyword-only.
token: API token de Civitai (header Authorization Bearer). Opcional: la
busqueda publica funciona sin el. No hardcodear: pasar desde
pass/vault. keyword-only.
Returns:
dict {ok, items, count, error}. items es una lista de
{name, type, base_model, version_id, download_url, nsfw} (la 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).
"""
params = [
("query", query),
("limit", str(max(1, min(int(limit), 100)))),
("sort", sort),
]
for t in str(types).split(","):
t = t.strip()
if t:
params.append(("types", t))
if base_model:
for bm in (base_model if isinstance(base_model, (list, tuple)) else [base_model]):
params.append(("baseModels", str(bm)))
url = f"{_API}?{urllib.parse.urlencode(params)}"
headers = {"User-Agent": "fn-registry/comfyui_search_civitai_models"}
if token:
headers["Authorization"] = f"Bearer {token}"
try:
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp:
data = json.loads(resp.read())
except urllib.error.HTTPError as exc:
body = exc.read().decode(errors="replace")[:300]
return {"ok": False, "items": [], "count": 0,
"error": f"HTTP {exc.code} en {url}: {body}"}
except urllib.error.URLError as exc:
return {"ok": False, "items": [], "count": 0,
"error": f"no se pudo conectar a civitai.com: {exc.reason}"}
except json.JSONDecodeError as exc:
return {"ok": False, "items": [], "count": 0,
"error": f"respuesta no es JSON valido: {exc}"}
items = []
for model in data.get("items", []) or []:
versions = model.get("modelVersions") or []
v0 = versions[0] if versions else {}
items.append({
"name": model.get("name"),
"type": model.get("type"),
"base_model": v0.get("baseModel"),
"version_id": v0.get("id"),
"download_url": v0.get("downloadUrl"),
"nsfw": bool(model.get("nsfw", False)),
})
return {"ok": True, "items": items, "count": len(items), "error": ""}
if __name__ == "__main__":
out = comfyui_search_civitai_models("dreamshaper", limit=5)
print(out["ok"], out["count"])
for it in out["items"]:
print(f" {it['name']} [{it['base_model']}] v{it['version_id']} -> {it['download_url']}")