Skip to content

Conversation

@Kosinkadink
Copy link
Collaborator

@Kosinkadink Kosinkadink commented Nov 22, 2025

Adds support for the first 3 native dynamic types: MatchType, DynamicCombo, and Autogrow. The layout of the V3 python API is also edited a bit to properly respect publicly-exposed classes/functions.

These types will not be usable unless 1) you are on latest frontend or 2) the time comes that ComfyUI's frontend version gets bumped to a version that supports these types.

I commented out the Switch node + test nodes to prevent issues until the right version of frontend arrives in ComfyUI. At that point, there will be a separate PR to enable the Switch node, and likely the addition of some nodes that will immediately make use of the dynamic types.

MatchType

Frontend PR: Comfy-Org/ComfyUI_frontend#6582

chrome_Vp58DY6YpM.mp4

Example code:

from comfy_api.latest import io
...
    @classmethod
    def define_schema(cls):
        template = io.MatchType.Template("switch")
        return io.Schema(
            node_id="ComfySwitchNode",
            display_name="Switch",
            category="logic",
            is_experimental=True,
            inputs=[
                io.Boolean.Input("switch"),
                io.MatchType.Input("on_false", template=template, lazy=True, optional=True),
                io.MatchType.Input("on_true", template=template, lazy=True, optional=True),
            ],
            outputs=[
                io.MatchType.Output(template=template, display_name="output"),
            ],
        )

DynamicCombo

Frontend PR: Comfy-Org/ComfyUI_frontend#6661

chrome_ogUbrN6YS5.mp4

Example code:

from comfy_api.latest import io
...
    @classmethod
    def define_schema(cls):
        return io.Schema(
            node_id="DCTestNode",
            display_name="DCTest",
            category="logic",
            is_output_node=True,
            inputs=[io.DynamicCombo.Input("combo", options=[
                io.DynamicCombo.Option("option1", [io.String.Input("string")]),
                io.DynamicCombo.Option("option2", [io.Int.Input("integer")]),
                io.DynamicCombo.Option("option3", [io.Image.Input("image")]),
                io.DynamicCombo.Option("option4", [
                    io.DynamicCombo.Input("subcombo", options=[
                        io.DynamicCombo.Option("opt1", [io.Float.Input("float_x"), io.Float.Input("float_y")]),
                        io.DynamicCombo.Option("opt2", [io.Mask.Input("mask1", optional=True)]),
                    ])
                ])]
            )],
            outputs=[io.AnyType.Output()],
        )

Autogrow

Frontend PR: Not made yet, here is the in-progress-branch https://github.com/Comfy-Org/ComfyUI_frontend/tree/austin/growable-inputs

(Made in early version of development, so things that should appear as 'optional' aren't.

chrome_aLLKyzqCPk.mp4

Example code:

from comfy_api.latest import io
...
# Names list
    @classmethod
    def define_schema(cls):
        template = io.Autogrow.TemplateNames(input=io.Float.Input("float"), names=["a", "b", "c"])
        return io.Schema(
            node_id="AutogrowNamesTestNode",
            display_name="AutogrowNamesTest",
            category="logic",
            inputs=[
                io.Autogrow.Input("autogrow", template=template)
            ],
            outputs=[io.String.Output()],
        )

# Prefixed
    @classmethod
    def define_schema(cls):
        template = io.Autogrow.TemplatePrefix(input=io.Float.Input("float"), prefix="float", min=1, max=10)
        return io.Schema(
            node_id="AutogrowPrefixTestNode",
            display_name="AutogrowPrefixTest",
            category="logic",
            inputs=[
                io.Autogrow.Input("autogrow", template=template)
            ],
            outputs=[io.String.Output()],
        )

Future Work

This PR also contains the schema for DynamicSlot, which is similar to DynamicCombo except the extra widgets are determined by whether or not an optional input has a connection or not. This type is not publicly exposed in V3 API right now, as the frontend work for that is not started. If that changes before this PR gets merged, I will update this.

…port for MatchType, created nodes_logic.py and added SwitchNode
…d of what is in __all__ of _io.py and _ui.py
…ata, add helper functions for dynamic behavior, preparing for restructuring dynamic type into object (not finished yet)
@yoland68 yoland68 assigned guill and unassigned yoland68 Dec 2, 2025
AustinMroz added a commit to Comfy-Org/ComfyUI_frontend that referenced this pull request Dec 2, 2025
![autogrow-optional_00002](https://github.com/user-attachments/assets/79bfe703-23d7-45fb-86ce-88baa9eaf582)

Also fixes connections to widget inputs created by a dynamic combo
breaking on reload.

Performs some refactoring to group the prior dynamic inputs code.

See also, the overarching frontend PR: comfyanonymous/ComfyUI#10832

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6830-Add-support-for-growable-inputs-2b36d73d365081c484ebc251a10aa6dd)
by [Unito](https://www.unito.io)
Copy link
Collaborator

@guill guill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments just documenting what we discussed in-person about what we're going to do in follow-up PRs.

Would slightly prefer prefixing the new function that we intend to remove with _, but good to merge either way 👍

@final
@classmethod
def INPUT_TYPES(cls, include_hidden=True, return_schema=False) -> dict[str, dict] | tuple[dict[str, dict], Schema]:
def INPUT_TYPES(cls, include_hidden=True, return_schema=False, live_inputs=None) -> dict[str, dict] | tuple[dict[str, dict], Schema, V3Data]:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note for posterity of what we discussed in-person: in a follow-up PR, we're going to want to refactor this a bit to remove the live_inputs argument from INPUT_TYPES. We really want the schema definition to be plain ol' data that we can cache or store without actually loading up the full node itself. Then, we can augment that with the dynamic information in a second pass.

def validate(self):
self.input.validate()

def expand_schema_for_dynamic(self, d: dict[str, Any], live_inputs: dict[str, Any], curr_prefix=''):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note for posterity of what we discussed in-person: in a follow-up PR, we're going to move this logic off of the class itself so that it doesn't seem like people can define their own versions of these functions when they define their own types.

I'd kind of prefer that we prefix the function with a _ since it's new, but it's not that big a deal if we just want to merge it as-is and remove it later.

@guill
Copy link
Collaborator

guill commented Dec 3, 2025

Oh, we should probably also add Execution Tests for this stuff at some point.

@comfyanonymous comfyanonymous merged commit c120eee into master Dec 3, 2025
12 checks passed
@comfyanonymous comfyanonymous deleted the v3-dynamic-combo branch December 3, 2025 05:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Core Core team dependency Core-Important

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants