Files starting with a leading separator line (e.g. "----" on line 1)
caused the first prompt to be silently dropped on every parse. The
separator regex requires \n before the hyphens, so the very first
separator was never matched — merging it into the first block and
making it unparseable.
Fixed by stripping any leading separator before splitting.
Affects all prompt files in the standard format.
Adds a second-generation metadata save node alongside the existing one.
V1 is frozen and unchanged so saved workflows keep working; all new
capability lands in V2.
New in V2:
- Extra metadata key/value pairs that grow on demand. Fill the last
pair and another appears; clear the trailing ones and the surplus is
pruned. Values can be typed or wired. Up to 32 pairs.
- Metadata-aware filename tokens. %extra:KEY% resolves any custom field,
and a bare %KEY% falls back to any captured metadata value such as
%Sampler% or %Steps%. Matching is case-insensitive and unresolved
tokens are logged rather than silently baked into the filename.
- Configurable file numbering: filename_numbering (always/on_conflict),
numbering_start, and numbering_padding. The first file can now be
_00001 instead of unnumbered.
- filename and filepath string outputs for chaining downstream.
- output_format reduced from 6 entries to 3, with the sidecar workflow
JSON promoted to its own save_workflow_json toggle.
- quality is now an integer 1-100 instead of four preset buckets.
Implementation notes:
- Both node versions live in one package and share a single set of
execution hooks. hook._SaveNodeClass becomes _SaveNodeClasses (a set)
so the pre-hooks can identify either node. A separate folder per
version would re-apply ComfyUI's execution monkey-patches once per
copy and duplicate the model hash cache.
- Only the first extra pair is declared. The frontend extension in
web/js/civitai_metasave_v2.js creates the rest, so the optional block
is wrapped in a FlexibleOptionalInputType whose __contains__ always
returns True. That is what lets ComfyUI accept undeclared inputs and
pass them through to **kwargs. Technique adapted from rgthree-comfy.
- Each dynamically created widget is paired with a matching input socket
via addInput(..., { widget: { name } }), mirroring what ComfyUI's own
addInputWidget does, so the new fields are connectable.
- Widget edits are detected by watching the value property rather than
widget.callback, which does not fire on every edit path in recent
frontends.
- ComfyUI's native COMFY_AUTOGROW_V3 was evaluated and works, but it is
resolved during the socket pass of addInputs(), which runs before the
widget pass, so its initial groups render above the node's ordinary
widgets instead of below. The pair parser accepts both the underscore
and the dotted autogrow naming, so switching later needs no change
on the Python side.
- Substituted filename token values are sanitised for filesystem safety.
A literal / in filename_prefix still creates a subfolder; slashes
inside substituted values become underscores.
- File numbering scans the directory with listdir rather than glob,
since a base name containing prompt text can include [ ] * ? which
glob would misinterpret.
- Extra metadata treats only None as absent, so a wired integer 0 (a
prompt index or counter on its first item) is recorded rather than
dropped.
Also in this release:
- Both save nodes moved to the category "YFG/Save".
- Random Prompt From File reports range clamping instead of applying it
silently. An inverted range (range_end below range_start) collapsed
the pool to a single entry, which in incremental_no_wrap looked
identical to a finished walk. Bounds are still clamped rather than
rejected, but every adjustment is now named in the console, and the
end-of-range notice states the range it walked.
- README documents V2 in full, including the filename token table and
the dynamic field behaviour.