Files
ComfyUI-Dataset-Gates/docs/plans/2026-06-29-sidecar-save-design.md
2026-07-01 13:58:29 +02:00

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 Sidecar node (content + name + extension), not per-type nodes.
  • JSON is just a string — content is a STRING written verbatim; the extension decides .txt vs .json.

Nodes (backend-only — standard widgets/slots, no web JS)

  • Inputs: content (STRING, forceInput) · name (STRING, default "") · extension (STRING, default .txt) · sidecar (optional SIDECAR chain-in).
  • Output: sidecar (SIDECAR) — a list; appends {content, name, ext} to the incoming chain and passes it on. Pure, no comfy imports.
  • SIDECAR is a custom type so only sidecar/save ports interconnect.

Save Image (Sidecars) — end of the chain

  • Inputs: images (IMAGE) · filename_prefix (default ComfyUI) · output_folder (default output; absolute or under the ComfyUI output dir) · sidecar (optional SIDECAR). OUTPUT_NODE, returns the image preview.
  • folder_paths.get_save_image_path()base = f"{filename}_{counter:05}_" (mirrors SaveImageKJ). Saves base.png, then each sidecar as base + 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 two variant_a.json) raise a clear ValueError.
  • Extension allowlist: .txt .caption .json .yaml .yml .md .csv .tsv .xml .log .ini .toml. name/extension sanitized to a basename; per-file commonpath path-traversal guard. (All copied from SaveImageKJ.)

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_paths imported lazily inside save(). build_plan runs 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).