mirror of
https://github.com/Comfy-Org/comfy-remote-nodes.git
synced 2026-11-04 23:37:22 +00:00
[PR #15] [MERGED] Parse DYNAMIC_COMBO + AUTOGROW inputs into real V3 IO objects #15
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-remote-nodes#15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-remote-nodes/pull/15
Author: @Kosinkadink
Created: 5/16/2026
Status: ✅ Merged
Merged: 5/16/2026
Merged by: @Kosinkadink
Base:
main← Head:feat/dynamic-combo-autogrow-parser📝 Commits (1)
37b77f8Parse DYNAMIC_COMBO + AUTOGROW inputs into real V3 IO objects📊 Changes
2 files changed (+705 additions, -19 deletions)
View changed files
➕
notes/run_dynamic_combo_parser.py(+526 -0)📝
proxy_node.py(+179 -19)📄 Description
What
proxy_node._parse_input_specpreviously had explicit branches only for the primitive V3 input types (STRING/INT/FLOAT/BOOLEAN/COMBO/IMAGE/VIDEO/AUDIO/MASK); every otherio_typestring — including the two V3 dynamic input typesDYNAMIC_COMBOandAUTOGROW— fell through to the opaqueIO.Custom(io_type).Inputbucket.Server-side runtime validation already worked (rules-extraction at
_rules_from_input_specwalks__branches__and__template__), but on the frontend every Topaz / Magnific / Vidu / Luma / Wan / Bria / Grok / ElevenLabs / HitPaw provider that declares aDynamicComborendered as one opaque socket instead of the branch-selector dropdown with per-branch sub-widgets the V3 IO is designed to produce.How
Refactor the parser so the construction logic is shared between two entry points (top-level descriptor inputs use the 2-tuple
[io_type, options]form; DynamicCombo branch sub-inputs use the 3-tuple[name, io_type, options]form) and add real handlers for both dynamic types:_parse_input_spec(name, spec, optional)— top-level entry, signature unchanged. Strips the[io_type, options]head and delegates._parse_named_input_spec(spec, optional)— branch-sub-input entry. Strips the leading name and delegates._build_input(name, io_type, options, optional)— shared constructor dispatch. The newDYNAMIC_COMBObranch buildsIO.DynamicCombo.Input(name, options=[IO.DynamicCombo.Option(key, inputs=[...]), ...])by recursing into_parse_named_input_specfor each branch sub-input; the newAUTOGROWbranch buildsIO.Autogrow.Input(name, template=IO.Autogrow.TemplatePrefix(...))(orTemplateNames) by recursing into_parse_input_specfor the template entry.The flattened RNP wire dialect for
AUTOGROW(template is a flat[io_type, options]entry directly, withprefix/min/maxornames/minas siblings oftemplate) is what every server provider already emits (e.g.grok.py:_grok_v2_model_subinputs); the parser mirrors that shape rather than the upstreamAutogrow.Input.as_dictnested form.Guardrails
"false"branch carries"inputs": [])."moderation","inputs", etc.) — not always"model".__branches__enforcement covers runtime presence.DynamicCombo.Input/Autogrow.Input) are rejected at parse time, mirroring the upstream_AutogrowTemplate.__init__assert.DYNAMIC_COMBO/AUTOGROWspecs returnNone(caller logs + skips the descriptor) instead of degrading to a single opaque socket — the opaque fallthrough is reserved for genuinely unknown io_type strings, not for known-but-broken dynamic specs.advancedonly routes to primitiveWidgetInputconstructors; the dynamic constructors don't accept it.Why no capability gate in this PR
The two dynamic io_type strings are already V3-canonical so a legacy client without the parser fix sees the same opaque-socket degradation it sees today (just rendered as
Custom("DYNAMIC_COMBO")instead of the real DynamicCombo input). AddingCapability.DYNAMIC_COMBO/Capability.AUTOGROWwould require pairing the cap with real descriptor-load-time enforcement (server-side filtering of/object_infoor client-side rejection based onrequired_capabilities); neither exists yet, so adding caps now would just be inert metadata. The cap pair is the right follow-up alongside the enforcement plumbing.Smoke test
notes/run_dynamic_combo_parser.py— 8 checks covering:"false"branch).voiceN) + primitive STRING._collect_local_validateoutput byte-identical before/after.All 8 checks pass; the previously-merged
notes/run_model3d_decoder.py(PR #14) also still passes (no regression on the existing IO path).What this unblocks
Client-side parsing for every server provider that declares a
DynamicCombofield, including Bria image-edit / remove-bg moderation, Grok V2 image-edit, Grok VideoReference, Grok VideoExtend, HitPaw video enhance, Magnific portrait_mode / advanced_settings, ElevenLabs T2S / Dialogue model selectors, and ByteDance Seedance2 T2V. These all rendered as opaque sockets today; they now render with real branch-selector dropdowns and per-branch sub-widgets.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.