66e664247c
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.7 KiB
2.7 KiB
Save Image + chainable sidecars (design)
Goal: A save-image node (like KJ's SaveImageKJ) that, instead of a single
caption, writes any number of sidecar text/JSON files alongside the image,
each sharing the image's base name so associations never break.
Decisions (from brainstorming):
- One unified
Sidecarnode (content + name + extension), not per-type nodes. - JSON is just a string — content is a STRING written verbatim; the extension
decides
.txtvs.json.
Nodes (backend-only — standard widgets/slots, no web JS)
Sidecar — one link in the chain
- Inputs:
content(STRING, forceInput) ·name(STRING, default"") ·extension(STRING, default.txt) ·sidecar(optionalSIDECARchain-in). - Output:
sidecar(SIDECAR) — a list; appends{content, name, ext}to the incoming chain and passes it on. Pure, no comfy imports. SIDECARis a custom type so only sidecar/save ports interconnect.
Save Image (Sidecars) — end of the chain
- Inputs:
images(IMAGE) ·filename_prefix(defaultComfyUI) ·output_folder(defaultoutput; absolute or under the ComfyUI output dir) ·sidecar(optionalSIDECAR).OUTPUT_NODE, returns the image preview. folder_paths.get_save_image_path()→base = f"{filename}_{counter:05}_"(mirrorsSaveImageKJ). Savesbase.png, then each sidecar asbase + name + ext.
Filename rule
base already ends in _, so it is the separator:
| name | ext | file |
|---|---|---|
"" |
.txt |
ComfyUI_00001_.txt (caption, shares the image base) |
"" |
.json |
ComfyUI_00001_.json |
variant_a |
.txt |
ComfyUI_00001_variant_a.txt |
Image: ComfyUI_00001_.png. Batch > 1 writes each sidecar per image.
Validation (all before any file is written → no partial output)
- Duplicate → error: two sidecars resolving to the same
name+ext(two empty-name.txt, or twovariant_a.json) raise a clearValueError. - Extension allowlist:
.txt .caption .json .yaml .yml .md .csv .tsv .xml .log .ini .toml.name/extensionsanitized to a basename; per-filecommonpathpath-traversal guard. (All copied fromSaveImageKJ.)
Code layout / testing
gates/sidecar.py— pure logic:ALLOWED_EXTENSIONS,normalize_ext,sanitize_name,append_spec,build_plan. Unit-tested (chain build, filename resolution, duplicate raises, bad-ext raises) — no torch/comfy.gates/sidecar_node.py— the two node classes; torch/PIL/folder_pathsimported lazily insidesave().build_planruns before any I/O.__init__.py— additive registration.
Rejected / deferred
- Per-type text/json nodes (unified node covers both).
- Structured JSON/dict input (string-JSON is enough).