Add support for dev-only nodes. (#12106)
Some checks are pending
Python Linting / Run Ruff (push) Waiting to run
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.11, [self-hosted Linux], stable) (push) Waiting to run
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.12, [self-hosted Linux], stable) (push) Waiting to run
Full Comfy CI Workflow Runs / test-unix-nightly (12.1, , linux, 3.11, [self-hosted Linux], nightly) (push) Waiting to run
Execution Tests / test (ubuntu-latest) (push) Waiting to run
Execution Tests / test (windows-latest) (push) Waiting to run
Test server launches without errors / test (push) Waiting to run
Python Linting / Run Pylint (push) Waiting to run
Full Comfy CI Workflow Runs / test-stable (12.1, , linux, 3.10, [self-hosted Linux], stable) (push) Waiting to run
Execution Tests / test (macos-latest) (push) Waiting to run
Unit Tests / test (macos-latest) (push) Waiting to run
Unit Tests / test (ubuntu-latest) (push) Waiting to run
Unit Tests / test (windows-2022) (push) Waiting to run

When a node is declared as dev-only, it doesn't show in the default UI
unless the dev mode is enabled in the settings. The intention is to
allow nodes related to unit testing to be included in ComfyUI
distributions without confusing the average user.
This commit is contained in:
guill 2026-01-27 13:03:29 -08:00 committed by GitHub
parent 09725967cf
commit dcff27fe3f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 20 additions and 0 deletions

View File

@ -236,6 +236,8 @@ class ComfyNodeABC(ABC):
"""Flags a node as experimental, informing users that it may change or not work as expected.""" """Flags a node as experimental, informing users that it may change or not work as expected."""
DEPRECATED: bool DEPRECATED: bool
"""Flags a node as deprecated, indicating to users that they should find alternatives to this node.""" """Flags a node as deprecated, indicating to users that they should find alternatives to this node."""
DEV_ONLY: bool
"""Flags a node as dev-only, hiding it from search/menus unless dev mode is enabled."""
API_NODE: Optional[bool] API_NODE: Optional[bool]
"""Flags a node as an API node. See: https://docs.comfy.org/tutorials/api-nodes/overview.""" """Flags a node as an API node. See: https://docs.comfy.org/tutorials/api-nodes/overview."""

View File

@ -1247,6 +1247,7 @@ class NodeInfoV1:
output_node: bool=None output_node: bool=None
deprecated: bool=None deprecated: bool=None
experimental: bool=None experimental: bool=None
dev_only: bool=None
api_node: bool=None api_node: bool=None
price_badge: dict | None = None price_badge: dict | None = None
search_aliases: list[str]=None search_aliases: list[str]=None
@ -1264,6 +1265,7 @@ class NodeInfoV3:
output_node: bool=None output_node: bool=None
deprecated: bool=None deprecated: bool=None
experimental: bool=None experimental: bool=None
dev_only: bool=None
api_node: bool=None api_node: bool=None
price_badge: dict | None = None price_badge: dict | None = None
@ -1375,6 +1377,8 @@ class Schema:
"""Flags a node as deprecated, indicating to users that they should find alternatives to this node.""" """Flags a node as deprecated, indicating to users that they should find alternatives to this node."""
is_experimental: bool=False is_experimental: bool=False
"""Flags a node as experimental, informing users that it may change or not work as expected.""" """Flags a node as experimental, informing users that it may change or not work as expected."""
is_dev_only: bool=False
"""Flags a node as dev-only, hiding it from search/menus unless dev mode is enabled."""
is_api_node: bool=False is_api_node: bool=False
"""Flags a node as an API node. See: https://docs.comfy.org/tutorials/api-nodes/overview.""" """Flags a node as an API node. See: https://docs.comfy.org/tutorials/api-nodes/overview."""
price_badge: PriceBadge | None = None price_badge: PriceBadge | None = None
@ -1485,6 +1489,7 @@ class Schema:
output_node=self.is_output_node, output_node=self.is_output_node,
deprecated=self.is_deprecated, deprecated=self.is_deprecated,
experimental=self.is_experimental, experimental=self.is_experimental,
dev_only=self.is_dev_only,
api_node=self.is_api_node, api_node=self.is_api_node,
python_module=getattr(cls, "RELATIVE_PYTHON_MODULE", "nodes"), python_module=getattr(cls, "RELATIVE_PYTHON_MODULE", "nodes"),
price_badge=self.price_badge.as_dict(self.inputs) if self.price_badge is not None else None, price_badge=self.price_badge.as_dict(self.inputs) if self.price_badge is not None else None,
@ -1519,6 +1524,7 @@ class Schema:
output_node=self.is_output_node, output_node=self.is_output_node,
deprecated=self.is_deprecated, deprecated=self.is_deprecated,
experimental=self.is_experimental, experimental=self.is_experimental,
dev_only=self.is_dev_only,
api_node=self.is_api_node, api_node=self.is_api_node,
python_module=getattr(cls, "RELATIVE_PYTHON_MODULE", "nodes"), python_module=getattr(cls, "RELATIVE_PYTHON_MODULE", "nodes"),
price_badge=self.price_badge.as_dict(self.inputs) if self.price_badge is not None else None, price_badge=self.price_badge.as_dict(self.inputs) if self.price_badge is not None else None,
@ -1791,6 +1797,14 @@ class _ComfyNodeBaseInternal(_ComfyNodeInternal):
cls.GET_SCHEMA() cls.GET_SCHEMA()
return cls._DEPRECATED return cls._DEPRECATED
_DEV_ONLY = None
@final
@classproperty
def DEV_ONLY(cls): # noqa
if cls._DEV_ONLY is None:
cls.GET_SCHEMA()
return cls._DEV_ONLY
_API_NODE = None _API_NODE = None
@final @final
@classproperty @classproperty
@ -1893,6 +1907,8 @@ class _ComfyNodeBaseInternal(_ComfyNodeInternal):
cls._EXPERIMENTAL = schema.is_experimental cls._EXPERIMENTAL = schema.is_experimental
if cls._DEPRECATED is None: if cls._DEPRECATED is None:
cls._DEPRECATED = schema.is_deprecated cls._DEPRECATED = schema.is_deprecated
if cls._DEV_ONLY is None:
cls._DEV_ONLY = schema.is_dev_only
if cls._API_NODE is None: if cls._API_NODE is None:
cls._API_NODE = schema.is_api_node cls._API_NODE = schema.is_api_node
if cls._OUTPUT_NODE is None: if cls._OUTPUT_NODE is None:

View File

@ -679,6 +679,8 @@ class PromptServer():
info['deprecated'] = True info['deprecated'] = True
if getattr(obj_class, "EXPERIMENTAL", False): if getattr(obj_class, "EXPERIMENTAL", False):
info['experimental'] = True info['experimental'] = True
if getattr(obj_class, "DEV_ONLY", False):
info['dev_only'] = True
if hasattr(obj_class, 'API_NODE'): if hasattr(obj_class, 'API_NODE'):
info['api_node'] = obj_class.API_NODE info['api_node'] = obj_class.API_NODE