Every node's own OUTPUTS were invisible on its own panel in the pipeline editor -- wiring an input already let you pick a source, but opening the node that PRODUCES something told you nothing about what it makes or whether anything reads it. Found live, by a real user just looking at a node, after two full review rounds that only ever checked the consuming side. Fixed with a read-only "Outputs" section per node, naming each output, its type, and who (if anyone) currently wires from it. Also: model family detection. core/probe.py reads a safetensors header (tensor names only, no weights) and asks every installed model module, through the same capability-lookup mechanism already used for empty_latent/decode, whether the file is its own -- core never names a family itself. A real, adversarially-found bug in the ported signature: one of MiniMax H3's three candidate prefixes doesn't correspond to any prefix ComfyUI's own loader actually resolves to, traced through comfy/model_detection.py and comfy/sd.py -- the probe could have called a file H3 that ComfyUI's real loader would refuse. Removed, and pinned with a dedicated test module. A second finding narrowed the folder search to only the folders FunPack's own loaders actually read from. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
82 lines
2.8 KiB
Python
82 lines
2.8 KiB
Python
"""detect(): whether a set of tensor names is MiniMax H3's own.
|
|
|
|
Pinned against ComfyUI's real prefix-resolution algorithm
|
|
(comfy/model_detection.py's unet_prefix_from_state_dict, and what
|
|
comfy/sd.py's load_diffusion_model_state_dict does with its answer) rather
|
|
than only against this module's own idea of what a "reasonable" prefix
|
|
looks like -- a probe that says yes to a file ComfyUI's real loader would
|
|
refuse is worse than one that says "not detected", which is exactly the
|
|
failure a prior review round found and this file exists to pin shut.
|
|
"""
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _needs_comfy(comfyui):
|
|
"""Only needed to import the module under test, which imports comfy.* at
|
|
module level -- detect() itself touches no comfy API."""
|
|
|
|
|
|
def _module():
|
|
from modules.models import minimax_h3
|
|
return minimax_h3
|
|
|
|
|
|
def _keys(prefix, *, both=True):
|
|
names = ["video_patch_proj.weight", "audio_patch_proj.weight"]
|
|
if not both:
|
|
names = names[:1]
|
|
return {f"{prefix}{n}" for n in names}
|
|
|
|
|
|
def test_bare_keys_are_recognised():
|
|
"""A standalone unet-only file: ComfyUI's own prefix guess strips
|
|
nothing for this layout (no key starts with "model."), so the ORIGINAL
|
|
unprefixed keys are what its real loader ends up reading."""
|
|
m = _module()
|
|
assert m.detect(_keys(""))
|
|
|
|
|
|
def test_model_diffusion_model_prefix_is_recognised():
|
|
"""The first, and only H3-relevant, candidate
|
|
unet_prefix_from_state_dict actually tries for a full-checkpoint
|
|
layout."""
|
|
m = _module()
|
|
assert m.detect(_keys("model.diffusion_model."))
|
|
|
|
|
|
def test_bare_diffusion_model_prefix_is_not_recognised():
|
|
"""Found by adversarial review: this prefix is not one of the three real
|
|
candidates ComfyUI's own unet_prefix_from_state_dict tries, and tracing
|
|
what its fallback guess ("model.") does with a state dict keyed this way
|
|
shows ComfyUI's real loader would never find these tensors either -- so
|
|
this probe must not claim it can."""
|
|
m = _module()
|
|
assert not m.detect(_keys("diffusion_model."))
|
|
|
|
|
|
def test_only_one_of_the_two_signature_keys_is_not_enough():
|
|
m = _module()
|
|
assert not m.detect(_keys("", both=False))
|
|
assert not m.detect(_keys("model.diffusion_model.", both=False))
|
|
|
|
|
|
def test_the_two_signature_keys_split_across_different_prefixes_do_not_match():
|
|
"""One tensor under one prefix, the other under a different one -- not a
|
|
real file's shape, and must not be read as one by accident."""
|
|
m = _module()
|
|
mixed = {"video_patch_proj.weight",
|
|
"model.diffusion_model.audio_patch_proj.weight"}
|
|
assert not m.detect(mixed)
|
|
|
|
|
|
def test_unrelated_keys_are_not_recognised():
|
|
m = _module()
|
|
assert not m.detect({"model.diffusion_model.unrelated.weight", "vae.decoder.weight"})
|
|
|
|
|
|
def test_an_empty_key_set_is_not_recognised():
|
|
m = _module()
|
|
assert not m.detect(set())
|