Compare commits

...

4 Commits

Author SHA1 Message Date
44dbb093c3 feat: pass filtering fields to frontend instead of server-side filtering
Remove server-side includeOnDistributions filtering and fileByDistribution
resolution. Instead, forward requiresCustomNodes and includeOnDistributions
in the info object so the frontend handles filtering client-side.

Amp-Thread-ID: https://ampcode.com/threads/T-019c6f43-6212-7308-bea6-bfc35a486cbf
2026-02-20 02:21:55 -08:00
6797e20bcf feat: switch SubgraphManager to index.json-driven discovery with distribution filtering
Amp-Thread-ID: https://ampcode.com/threads/T-019c30d2-a605-708d-824f-35e8f3a0c2f5
2026-02-05 20:33:17 -08:00
2b70ab9ad0 Add a Create List node (#12173) 2026-02-05 01:18:21 -05:00
00efcc6cd0 Bump comfyui-frontend-package to 1.38.13 (#12238) 2026-02-05 01:17:37 -05:00
4 changed files with 97 additions and 4 deletions

View File

@ -1,6 +1,8 @@
from __future__ import annotations
from typing import TypedDict
import json
import logging
import os
import folder_paths
import glob
@ -90,15 +92,58 @@ class SubgraphManager:
return subgraphs_dict
async def get_blueprint_subgraphs(self, force_reload=False):
"""Load subgraphs from the blueprints directory."""
"""Load subgraphs from the blueprints directory using index.json for discovery."""
if not force_reload and self.cached_blueprint_subgraphs is not None:
return self.cached_blueprint_subgraphs
subgraphs_dict: dict[SubgraphEntry] = {}
blueprints_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'blueprints')
if os.path.exists(blueprints_dir):
index_path = os.path.join(blueprints_dir, "index.json")
if os.path.isfile(index_path):
try:
with open(index_path, "r", encoding="utf-8") as f:
categories = json.load(f)
except (json.JSONDecodeError, OSError) as e:
logging.error("Failed to load blueprint index %s: %s", index_path, e)
categories = []
if not isinstance(categories, list):
logging.error("Blueprint index.json is not a list: %s", index_path)
categories = []
for category in categories:
module_name = category.get("moduleName", "default")
for blueprint in category.get("blueprints", []):
name = blueprint.get("name")
if not name:
logging.warning("Blueprint entry missing 'name' in category '%s', skipping", module_name)
continue
filename = f"{name}.json"
filepath = os.path.realpath(os.path.join(blueprints_dir, filename))
if not filepath.startswith(os.path.realpath(blueprints_dir) + os.sep):
logging.warning("Blueprint path escapes blueprints directory: %s", filepath)
continue
if not os.path.isfile(filepath):
logging.warning("Blueprint file not found: %s", filepath)
continue
entry_id, entry = self._create_entry(filepath, Source.templates, module_name)
info = entry["info"]
include_on = blueprint.get("includeOnDistributions")
if include_on is not None:
info["includeOnDistributions"] = include_on
requires = blueprint.get("requiresCustomNodes")
if requires is not None:
info["requiresCustomNodes"] = requires
subgraphs_dict[entry_id] = entry
elif os.path.exists(blueprints_dir):
logging.warning("No blueprint index.json found at %s, falling back to glob", index_path)
for file in glob.glob(os.path.join(blueprints_dir, "*.json")):
if os.path.basename(file) == "index.json":
continue
file = file.replace('\\', '/')
entry_id, entry = self._create_entry(file, Source.templates, "comfyui")
subgraphs_dict[entry_id] = entry

View File

@ -0,0 +1,47 @@
from __future__ import annotations
from typing_extensions import override
from comfy_api.latest import ComfyExtension, io
class CreateList(io.ComfyNode):
@classmethod
def define_schema(cls):
template_matchtype = io.MatchType.Template("type")
template_autogrow = io.Autogrow.TemplatePrefix(
input=io.MatchType.Input("input", template=template_matchtype),
prefix="input",
)
return io.Schema(
node_id="CreateList",
display_name="Create List",
category="logic",
is_input_list=True,
search_aliases=["Image Iterator", "Text Iterator", "Iterator"],
inputs=[io.Autogrow.Input("inputs", template=template_autogrow)],
outputs=[
io.MatchType.Output(
template=template_matchtype,
is_output_list=True,
display_name="list",
),
],
)
@classmethod
def execute(cls, inputs: io.Autogrow.Type) -> io.NodeOutput:
output_list = []
for input in inputs.values():
output_list += input
return io.NodeOutput(output_list)
class ToolkitExtension(ComfyExtension):
@override
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [
CreateList,
]
async def comfy_entrypoint() -> ToolkitExtension:
return ToolkitExtension()

View File

@ -2433,7 +2433,8 @@ async def init_builtin_extra_nodes():
"nodes_image_compare.py",
"nodes_zimage.py",
"nodes_lora_debug.py",
"nodes_color.py"
"nodes_color.py",
"nodes_toolkit.py",
]
import_failed = []

View File

@ -1,4 +1,4 @@
comfyui-frontend-package==1.37.11
comfyui-frontend-package==1.38.13
comfyui-workflow-templates==0.8.31
comfyui-embedded-docs==0.4.0
torch