diff --git a/smart_metadata_reader/adapters/conditioning.py b/smart_metadata_reader/adapters/conditioning.py index 2c6cf3d..eded3d7 100644 --- a/smart_metadata_reader/adapters/conditioning.py +++ b/smart_metadata_reader/adapters/conditioning.py @@ -4,12 +4,16 @@ from ..models import NodeRecord ROLE_FIELD_ORDER = { - "positive": ("positive", "positive_conditioning", "base_positive"), - "negative": ("negative", "negative_conditioning", "base_negative"), + "positive": ("conditioning", "positive", "positive_conditioning", "base_positive"), + "negative": ("negative", "negative_conditioning", "base_negative", "conditioning"), } KNOWN_CONDITIONING_MARKERS = ( "controlnetapply", + "controlnet", + "control_net", + "apply controlnet", + "comfyroll", "inpaintmodelconditioning", "conditioningcombine", "conditioningconcat", @@ -24,7 +28,9 @@ KNOWN_CONDITIONING_MARKERS = ( class ConditioningAdapter: def matches(self, node: NodeRecord) -> bool: lowered = node.class_type.lower() - return any(marker in lowered for marker in KNOWN_CONDITIONING_MARKERS) + if any(marker in lowered for marker in KNOWN_CONDITIONING_MARKERS): + return any(_is_conditioning_field(field) for field in node.inputs) + return False def fields_for_role(self, node: NodeRecord, role: str) -> list[str]: role_fields = [ diff --git a/tests/test_conditioning_resolver.py b/tests/test_conditioning_resolver.py index f1389db..71b549e 100644 --- a/tests/test_conditioning_resolver.py +++ b/tests/test_conditioning_resolver.py @@ -64,6 +64,75 @@ def test_resolves_controlnet_apply_advanced_passthrough(): assert segment_texts(resolver.resolve_positive(sampler)) == ["advanced positive"] +def test_resolves_cr_apply_controlnet_conditioning_passthrough_without_parameters(): + prompt = { + "1": {"class_type": "KSampler", "inputs": {"positive": ["150", 0]}}, + "2": {"class_type": "CLIPTextEncode", "inputs": {"text": "real positive prompt"}}, + "3": {"class_type": "ControlNetLoader", "inputs": {"control_net_name": "control_net"}}, + "150": { + "class_type": "CR Apply ControlNet", + "inputs": { + "conditioning": ["2", 0], + "image": "control_image.png", + "strength": 0.3, + "control_net": ["3", 0], + }, + }, + } + + resolver, sampler = resolver_for(prompt) + segments = resolver.resolve_positive(sampler) + positive = merge_prompt_segments(segments) + + assert positive == "real positive prompt" + assert "control_image.png" not in positive + assert "0.3" not in positive + assert "control_net" not in positive + assert "CR Apply ControlNet 150" in resolver.debug_trace + + +def test_resolves_cr_apply_controlnet_complex_upstream_text_chain(): + prompt = { + "1": {"class_type": "KSampler", "inputs": {"positive": ["150", 0]}}, + "2": {"class_type": "CLIPTextEncode", "inputs": {"text": ["3", 0]}}, + "3": { + "class_type": "StringFunction|pysssss", + "inputs": { + "action": "append", + "text_a": "role_lora_trigger, character_name,", + "text_b": ["4", 0], + "text_c": ["5", 0], + }, + }, + "4": { + "class_type": "ShowText|pysssss", + "inputs": {"text_0": "1girl, solo, stage lights"}, + }, + "5": { + "class_type": "DeepTranslatorTextNode", + "inputs": {"text": "nude, huge breasts"}, + }, + "150": { + "class_type": "CR Apply ControlNet", + "inputs": { + "conditioning": ["2", 0], + "image": "control_image.png", + "strength": 0.3, + }, + }, + } + + resolver, sampler = resolver_for(prompt) + positive = merge_prompt_segments(resolver.resolve_positive(sampler)) + + assert "role_lora_trigger" in positive + assert "character_name" in positive + assert "1girl, solo, stage lights" in positive + assert "nude, huge breasts" in positive + assert "control_image.png" not in positive + assert "0.3" not in positive + + def test_resolves_inpaint_model_conditioning_passthrough(): prompt = { "1": {"class_type": "KSampler", "inputs": {"positive": ["3", 0]}},