From b711fa8f0727132dabd9b04fa0b68b8fe2b5b4d6 Mon Sep 17 00:00:00 2001 From: Edward Niewold Date: Sat, 25 Apr 2026 16:28:22 +0200 Subject: [PATCH] v1.2.1 - Removed the maximum number of inputs and outputs on the `Subworkflow` --- README.md | 2 ++ js/subworkflow.js | 7 +++---- pyproject.toml | 2 +- workflow_node.py | 26 +++++--------------------- workflow_utils.py | 1 - 5 files changed, 11 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a5b070d..b20e131 100644 --- a/README.md +++ b/README.md @@ -178,9 +178,11 @@ ComfyUI workflow JSON appears in a few different shapes depending on how it was - [ ] Used paths with macro elements are not formatted currectly when used in inner workflow? (use Video Combine node with %date:yyyy-MM-dd%/WAN/Video) - [ ] Green progress borders appear on more than one node when executing a inner workflow as part of a larger workflow. These borders should be limited to the currently executing node(s) outer workflow. - [ ] The order if inputs/outputs on the `Subworkflow` node is undetermined (probably based on the order of nodes in the inner workflow JSON). Consider adding an option to control this order. +- [ ] When a node `Subworkflow Input` is used inside a subgraph, it will not be detected as a boundary node and will not be exposed on the `Subworkflow` node. ### Version History +- v1.2.1 - Removed the maximum number of inputs and outputs on the `Subworkflow` node (was previously set to 8). - v1.2.0 - Added manual value entry for primitive `Subworkflow Input` input nodes on the `Subworkflow` node. Check README features section for details. - v1.1.0 - Added `Subworkflow Modifier`, `Subworkflow Modifier Source` (+ from URL) nodes. Combining these nodes in inner and outer workflows allows for circular links between an inner workflow input and output, without circular reference problems. - v1.0.1 - UI only nodes are now supported in inner workflows, no longer raising and error when loading. diff --git a/js/subworkflow.js b/js/subworkflow.js index 9f145ea..600056b 100644 --- a/js/subworkflow.js +++ b/js/subworkflow.js @@ -56,7 +56,6 @@ const NODE_CONFIGS = { }, }, }; -const MAX_SLOTS = 8; const LOG = "[SWF]"; const DEBUG = window.localStorage?.getItem("swf_debug") === "1"; let workflowErrorDialog = null; @@ -225,7 +224,7 @@ function updateInputSlots(node, inputs) { if (node.inputs[i].name?.startsWith("swf_in_")) node.removeInput(i); } } - inputs.slice(0, MAX_SLOTS).forEach((inp, i) => { + inputs.forEach((inp, i) => { debugLog(`updateInputSlots: adding swf_in_${i}`, inp); node.addInput(`swf_in_${i}`, swfSlotType(inp), { label: inp.slot_name }); }); @@ -233,7 +232,7 @@ function updateInputSlots(node, inputs) { } function updateOutputSlots(node, outputs) { - const needCount = Math.min(outputs.length, MAX_SLOTS); + const needCount = outputs.length; debugLog("updateOutputSlots: before", slotSummary(node.outputs)); for (let i = (node.outputs || []).length - 1; i >= 0; i--) { @@ -443,7 +442,7 @@ function _syncOverrideWidgets(node, inputs, config, pendingOverrideValues) { let pendingOffset = 0; - inputs.slice(0, MAX_SLOTS).forEach((inp, i) => { + inputs.forEach((inp, i) => { if (inp.type !== "INT" && inp.type !== "FLOAT") return; const defaultVal = (inp.default != null) ? inp.default : (inp.type === "INT" ? 0 : 0.0); diff --git a/pyproject.toml b/pyproject.toml index c6958be..5666e22 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "comfyui-subworkflow" -version = "1.2.0" +version = "1.2.1" description = "Use ComfyUI workflows as reusable subworkflows via Subworkflow Input, Subworkflow Output, and Subworkflow nodes" license = { file = "LICENSE" } requires-python = ">=3.10" diff --git a/workflow_node.py b/workflow_node.py index 6ade072..9a8a61f 100644 --- a/workflow_node.py +++ b/workflow_node.py @@ -16,7 +16,6 @@ from .workflow_utils import ( apply_control_after_generate, validate_workflow_nodes_installed, get_workflow_interface, - MAX_SLOTS, ) log = configure_logger("ComfyUI-Subworkflow") @@ -112,32 +111,17 @@ class BaseSubworkflow(io.ComfyNode): effective_inputs = _apply_primitive_overrides(data, kwargs) output_refs, graph = build_expansion(data, effective_inputs) - return cls._finalize_execution(output_refs, graph, data, reload_each_execution, pad_outputs=MAX_SLOTS) + return cls._finalize_execution(output_refs, graph, data, reload_each_execution) @classmethod - def _finalize_execution( - cls, - output_refs, - graph, - data: dict, - reload_each_execution: bool, - pad_outputs: int | None = None, - ): + def _finalize_execution(cls, output_refs, graph, data: dict, reload_each_execution: bool): if not reload_each_execution: apply_control_after_generate(data) - - if pad_outputs is not None: - while len(output_refs) < pad_outputs: - output_refs.append(None) - return io.NodeOutput(*output_refs, expand=graph.finalize()) def _subworkflow_outputs(): - return [ - io.AnyType.Output(id=f"out_{i}", display_name=f"out_{i}") - for i in range(MAX_SLOTS) - ] + return [] def _reload_input(): @@ -330,7 +314,7 @@ class SubworkflowModifierSource(BaseSubworkflow): data = cls._get_workflow_data(reload_each_execution, workflow=workflow, **kwargs) validate_workflow_nodes_installed(data) output_refs, graph = build_modifier_source_expansion(data, kwargs) - return cls._finalize_execution(output_refs, graph, data, reload_each_execution, pad_outputs=MAX_SLOTS) + return cls._finalize_execution(output_refs, graph, data, reload_each_execution) class SubworkflowModifierSourceFromURL(BaseSubworkflow): @@ -384,4 +368,4 @@ class SubworkflowModifierSourceFromURL(BaseSubworkflow): ) validate_workflow_nodes_installed(data) output_refs, graph = build_modifier_source_expansion(data, kwargs) - return cls._finalize_execution(output_refs, graph, data, reload_each_execution, pad_outputs=MAX_SLOTS) + return cls._finalize_execution(output_refs, graph, data, reload_each_execution) diff --git a/workflow_utils.py b/workflow_utils.py index 67fdedf..ddccdc6 100644 --- a/workflow_utils.py +++ b/workflow_utils.py @@ -23,7 +23,6 @@ _UUID_RE = re.compile( SWF_SUBWORKFLOW_INPUT = "SWF_SubworkflowInput" SWF_SUBWORKFLOW_OUTPUT = "SWF_SubworkflowOutput" SWF_SUBWORKFLOW_MODIFIER = "SWF_SubworkflowModifier" -MAX_SLOTS = 8 PLACEHOLDER = "" MAX_URL_WORKFLOW_BYTES = 50 * 1024 * 1024 URL_WORKFLOW_TIMEOUT = 20