Files
olivv-cs-ComfyUI-FunPack/modules/loaders/checkpoint/nodes.py
T
digital-garbageandClaude Opus 5 cf318c8c0d graph: the pipeline is slots, so a built-in node can be swapped or removed
v4 could not remove a built-in node from the pipeline and the reason was
structural: the wiring lived in code as a CORE dict nobody could reach, so
"remove this" had nothing to delete and "use a different one" had nothing to
change. Code is not a thing a user can edit.

The pipeline is now data. Three operations over it, each refusing with a
reason rather than half-doing the job:

build turns slots into the prompt ComfyUI queues, checking every link's type
and refusing a graph that cannot work. replace points a slot at any node
producing what its consumers read -- the built-in ones have no special
standing, which is what makes them replaceable rather than merely present.
remove takes a slot out and rewires what it fed to what fed it, when the
node has exactly one input matching each CONSUMED output; v4 required one
for every output a class could produce, so a spare FLOAT nobody wired made a
node unremovable.

Demonstrated against real schemas: FunPack's VAE loader swapped for core's
VAELoader, the modifiers node removed with the sampler rewired to read the
model directly, and removing the empty latent refused because nothing
upstream could feed what it fed.

Then run for real. The default pipeline, with three loader slots replaced by
one checkpoint slot, built from data, accepted by ComfyUI's own
validate_prompt, and executed by its own engine to execution_success and a
picture. Every wiring and type validated on the first attempt; the only
things ComfyUI objected to in the untouched default were the three unset
file pickers, which is correct -- a fresh install cannot know which model
you own.

Added a checkpoint loader, because the split loaders are right for LTX and
H3 and cannot read an SD-family single file at all.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-29 18:06:25 +03:00

58 lines
2.5 KiB
Python

"""One file holding a model, its text encoder and its VAE.
The split loaders are right for the families FunPack targets -- LTX and H3 ship
the diffusion model, the encoders and the VAEs separately, and pairing them is
the user's choice. The SD family does not: one checkpoint carries all three, and
without this there is no way to load one at all.
Both exist, and neither is the "real" one. A pipeline using three slots can be
replaced by one using this, which is the point of slots being replaceable.
"""
import comfy.sd
import folder_paths
from comfy_api.latest import io
from ..._core import log
class FunPackCheckpointLoader(io.ComfyNode):
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="FunPackCheckpointLoader",
display_name="FunPack Checkpoint Loader",
category="FunPack/Loaders",
description="Load a model, text encoder and VAE from one checkpoint file.",
inputs=[
io.Combo.Input("ckpt_name", options=folder_paths.get_filename_list("checkpoints")),
],
outputs=[
io.Model.Output(display_name="model"),
io.Clip.Output(display_name="clip"),
io.Vae.Output(display_name="vae"),
io.String.Output(display_name="status"),
],
)
@classmethod
def execute(cls, ckpt_name: str) -> io.NodeOutput:
path = folder_paths.get_full_path_or_raise("checkpoints", ckpt_name)
model, clip, vae, *_ = comfy.sd.load_checkpoint_guess_config(
path, output_vae=True, output_clip=True,
embedding_directory=folder_paths.get_folder_paths("embeddings"))
# Each part is reported, because a checkpoint missing its VAE or its
# encoder loads happily and then fails somewhere else entirely.
missing = [name for name, part in (("clip", clip), ("vae", vae)) if part is None]
if missing:
log.warning("FunPack Checkpoint Loader",
f"{ckpt_name} has no {' or '.join(missing)}; those outputs are empty "
f"and whatever reads them will fail")
kind = type(getattr(model, "model", model)).__name__
log.info("FunPack Checkpoint Loader", f"{ckpt_name} loaded as {kind}")
return io.NodeOutput(model, clip, vae,
f"{ckpt_name} loaded as {kind}"
+ (f" (no {', '.join(missing)})" if missing else ""))