* feat(nodes): add Easy_Utility — INT → padded STRING dispatcher First mode `int_to_padded_string`: takes an INT widget (with up/down arrows) and emits a zero-padded STRING (default `001`, no `v` prefix). The downstream `koolook_versioning.resolve_version_token` prepends `v` and re-pads, so wiring this into `EasyAIPipeline.version` / `Easy_VideoCombine.version` yields the standard `vNNN` token at execution. Designed for extension: the `mode` widget shipped from day one so adding further conversions (string→int, formatting variants, etc.) doesn't rewire saved workflows. Note: the previously-attempted JS preview-resolver refactor that aimed to fix the "preview shows stale version" bug was reverted in this worktree before commit — it didn't actually fix the bug (the real cause is the JS resolver not descending into ComfyUI subgraphs) and it broke shot_name resolution in the process. The preview-resolver work is NOT in this commit; only the Python node + tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(nodes): guard version widget against pysssss .replace crash PR #180 added a STRING `version` widget to EasyAIPipeline and Easy_VideoCombine. Three workflow states leave widget.value undefined or non-string when graphToPrompt iterates widgets: - Pre-#180 workflows replay an INT (e.g. `1`) into the new STRING slot. - Widget-to-input conversion voids the value in newer LiteGraph. - Easy_VideoCombine's dict-based widgets_values omits the new key entirely on workflows saved before #180. With pysssss/ComfyUI-Custom-Scripts installed, presetText.js patches every STRING TextWidget.serializeValue to run callbacks that do `value.replace(...)` for `{variable}` substitution. Any of the states above crashes graphToPrompt and turns Run into a no-op for the whole workflow ("Cannot read properties of undefined (reading 'replace')"). Fix: trap `widget.value` reads/writes on the version widget via `Object.defineProperty` so the property is always coerced to a string regardless of caller. `configurable: true` so downstream code can still override the descriptor if it needs to. Tests: 231 passing; both JS files parse OK. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(ai-pipeline): resolve subgraph version preview * feat(video): add path-aware load video node * fix(ai-pipeline): preview connected text names * fix(pr184): address review cleanup --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ComfyUI-Koolook documentation
Three audience buckets — pick where to look based on what you're trying to do.
| If you want to … | Go to | One-line description |
|---|---|---|
| Use a node in your ComfyUI workflow | user_guide/ |
Per-node guides, screenshots, recipes |
| Look something up — a term, a node ID, a list | reference/ |
Glossary, node inventory, spec sheets |
| Cut a release / fork a node / debug CI / hit the Comfy Registry API | maintainers/ |
Releasing, Registry API, Node versioning rules |
| Compare UI design proposals before implementation | designs/ |
Focused mockups and screenshots for in-progress UX decisions |
| Run AI-assisted model evaluation loops | automations/ |
Visual loop overview, setup contract, per-model findings, and /make-card workflow |
Files that intentionally stay at the repo root
| File | Why it's not in docs/ |
|---|---|
../README.md |
GitHub repo home + Comfy Registry pulls description from here |
../LICENSE |
pyproject.toml references it; GitHub recognizes the license badge from this path only |
../CHANGELOG.md |
Changelog parsers and release tooling expect it at root |
../CLAUDE.md |
Claude Code reads project-level agent instructions from <repo>/CLAUDE.md |