feat(ml): comfyui_export_skill_template — skills (recetas) como grafos cargables en el navegador
Cierra el gap receta->grafo del grupo comfyui-skill. La función impura comfyui_export_skill_template compila una skill a template API format (exports/<slug>.template.json) y, con ui_graph=True, genera el UI graph posicionado vía CDP (load_workflow_ui + export_workflow_ui) en la carpeta nativa de la UI (~/ComfyUI/user/default/workflows/<slug>.json), de modo que la skill aparece en el menú Workflows del navegador y se abre como grafo visual. Sin navegador, deja el template API y reporta el fallback (no falla). - 4 tests offline (golden + edge + 2 error paths). - Página madre comfyui-skill.md: fila en la tabla del grupo + sección "Skills como grafos en el navegador". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,7 @@ de texto). `blocks[].type` ∈ {`facedetailer`, `hires_fix`}.
|
||||
| ID | Firma corta | Qué hace | Purity |
|
||||
|---|---|---|---|
|
||||
| [comfyui_build_skill_workflow_py_ml](../../python/functions/ml/comfyui_build_skill_workflow.md) | `build_skill_workflow(recipe, subject, *, seed=0) -> dict` | Compila una receta a un workflow en API format: despacha al builder base, sustituye `{subject}` + trigger_words, encadena LoRAs y aplica los blocks en orden. `SkillWorkflowError` si la base es desconocida o requiere imagen. | **pura** |
|
||||
| [comfyui_export_skill_template_py_ml](../../python/functions/ml/comfyui_export_skill_template.md) | `export_skill_template(slug, *, ui_graph=False, port=9222, ...) -> dict` | Exporta una skill a artefactos cargables como GRAFO: template API en `exports/<slug>.template.json` y, con `ui_graph=True`, el UI graph posicionado (vía `load_workflow_ui`+`export_workflow_ui` por CDP) en la carpeta nativa `~/ComfyUI/user/default/workflows/<slug>.json` (menú Workflows del navegador). Sin navegador, deja el template API y reporta el fallback. | impura |
|
||||
| [comfyui_inject_hires_fix_py_ml](../../python/functions/ml/comfyui_inject_hires_fix.md) | `comfyui_inject_hires_fix(workflow, *, upscale_by=1.5, denoise=0.4, steps=20, ...) -> dict` | Inyecta una 2ª pasada hires-fix (UpscaleModelLoader + UltimateSDUpscale) sobre un workflow ya construido, repuntando el SaveImage. Versión encadenable-sobre-dict del builder hermano. | **pura** |
|
||||
| [comfyui_save_skill_py_ml](../../python/functions/ml/comfyui_save_skill.md) | `comfyui_save_skill(recipe, *, library_dir=None) -> dict` | Valida el schema mínimo y escribe `recipe.json` + snapshot `versions/vN.json` + growth_log + INDEX.md. No muta la receta (round-trip con load). | impura |
|
||||
| [comfyui_load_skill_py_ml](../../python/functions/ml/comfyui_load_skill.md) | `comfyui_load_skill(slug, *, version=None, library_dir=None) -> dict` | Lee `recipe.json` (actual) o un snapshot `versions/vN.json`. Slug/versión inexistente → `{ok:False}` sin lanzar. | impura |
|
||||
@@ -164,6 +165,42 @@ Pasos concretos:
|
||||
Así `versions/` y `growth_log` reflejan **versiones de receta con mejora demostrada**, mientras
|
||||
`score_mean` es la telemetría de calidad media de la versión vigente.
|
||||
|
||||
## Skills como grafos en el navegador
|
||||
|
||||
Una skill no vive solo como receta JSON: se exporta a un **grafo de ComfyUI cargable como tal en el
|
||||
navegador**. `comfyui_export_skill_template` cierra ese hueco (receta → grafo):
|
||||
|
||||
```python
|
||||
from ml.comfyui_export_skill_template import export_skill_template
|
||||
|
||||
# Headless (sin navegador): congela el template API junto a la skill.
|
||||
export_skill_template("portrait_cinematic_sd15")
|
||||
# -> exports/portrait_cinematic_sd15.template.json (API format, node-template reproducible)
|
||||
|
||||
# Con navegador (pestaña ComfyUI abierta en CDP 9222): además el grafo visual posicionado.
|
||||
out = export_skill_template("portrait_cinematic_sd15", ui_graph=True, port=9222)
|
||||
# -> ~/ComfyUI/user/default/workflows/portrait_cinematic_sd15.json (aparece en el menú Workflows)
|
||||
```
|
||||
|
||||
Dos formatos, dos usos:
|
||||
|
||||
- **API format** (`exports/<slug>.template.json`) — el dict `{node_id:{class_type,inputs}}`. Se
|
||||
carga con `comfyui_load_workflow_ui` (`app.loadApiJson`, litegraph lo auto-posiciona) o va directo
|
||||
a `comfyui_submit_workflow`. Es el node-template versionable de la skill.
|
||||
- **UI graph** (`~/ComfyUI/user/default/workflows/<slug>.json` + copia en `exports/<slug>.ui.json`)
|
||||
— `nodes`/`links`/`pos` (`app.graph.serialize()`). La carpeta nativa de la UI **solo** acepta este
|
||||
formato; por eso solo se escribe con `ui_graph=True` (se genera vía CDP cargando el API en la UI y
|
||||
serializando el grafo posicionado). Es el que se abre como grafo visual desde el menú Workflows.
|
||||
|
||||
**Fotos ↔ grafo.** Cada PNG de ComfyUI lleva su workflow embebido (chunk `prompt`, API format).
|
||||
`comfyui_import_workflow_png` lo recupera, de modo que toda muestra de una skill queda asociada a su
|
||||
grafo reproducible 1:1 (ver `INDEX.md` de la librería: `samples/<base>.png` + `samples/<base>.graph.json`).
|
||||
|
||||
**No destructivo en el navegador**: `ui_graph=True` reemplaza el grafo in-memory de la pestaña. Si
|
||||
hay trabajo sin guardar (título con `*`), respalda antes con
|
||||
`comfyui_export_workflow_ui(api_format=True, save_path=...)` y restáuralo después con
|
||||
`comfyui_load_workflow_ui`.
|
||||
|
||||
## Fronteras
|
||||
|
||||
- **No genera ni descarga modelos**: una skill referencia checkpoints/LoRAs por nombre; deben
|
||||
|
||||
Reference in New Issue
Block a user