Files
DumiFlex-ComfyUI-Wildcard-P…/wp_nodes/debug_node.py
T
DumiFlex ccbf38af99 feat(nodes): add wp_seedlist + split loop config types + wp_ prefix sweep + tooltips
Three coordinated changes to the WP_* node family.

1. New WP_SeedList node
   Emits a list of N derived seeds for a downstream loop (is_output_list).
   Three independent override toggles (override_seed / override_count /
   override_strategy) each mirror the wired Loop's base_seed / count /
   strategy. Connecting loop_config auto-flips override_count +
   override_strategy ON so the natural intent of wiring in a loop gets
   the defaults right; override_seed stays explicit opt-in.
   All emitted seeds are masked to 50 bits via the new MAX_SAFE_SEED
   constant in engine.seed_derive so values sit inside ComfyUI's
   frontend randomize range and copy-paste reproduces identically in a
   standalone sampler.

2. Context Loop type split + downstream Context seed widget lock
   Split WP_CONTEXT_LOOP_CONFIG (wire payload) from a new
   WP_CONTEXT_LOOP_WIDGET (DOM-widget-only TYPE). Loop's own widget
   mounts on the widget type; the wire type has no factory so consumers
   like WP_SeedList render their loop_config socket as a plain input
   instead of being hidden by a fallback-undefined widget.
   New graph walker hasUpstreamLoopOverridingSeed: WP_Context's widget
   glue greys out the local seed stock widget when an upstream Loop has
   override_seed ON, so users read "this value is dead while the Loop
   drives it" without inspecting the Loop config separately.

3. wp_ prefix sweep + tooltips across every WP_* node input
   Custom DOM widget input names now carry the wp_ prefix so canvas
   socket labels read as branded WP widgets: modules -> wp_modules,
   rows -> wp_rows, viewer -> wp_viewer, cleaner -> wp_cleaner,
   context_loop_config -> wp_context_loop_config. Every stock input
   across the node family gets a tooltip describing what it does and
   when to wire it from another node. Tests + comfy_api stub updated.
   CLAUDE.md notes the wp_ convention for future custom widgets.

Bundle size budget bumped 388 -> 395 KB to fit the SeedList Vue chunk
(~4.9 KB net gzip) + override lock UI; entry stays at ~4 KB gzipped.
2026-05-28 12:40:44 +03:00

63 lines
2.4 KiB
Python

"""WP_Debug — terminal node that emits the PipelineContext for UI inspection."""
import json
from comfy_api.latest import io # pyright: ignore[reportMissingImports]
from wp_nodes.types import DebugViewerInput, PipelineContext
class WPDebug(io.ComfyNode):
"""Inspect the context at any point in the chain. Terminal output node."""
@classmethod
def define_schema(cls):
return io.Schema(
node_id="WP_Debug",
display_name="WP Debug",
category="wildcard-pipeline",
inputs=[
PipelineContext.Input(
"context",
tooltip=(
"The resolved $variable context from any upstream "
"WP Context / Loop / Injector chain. Required — "
"without it the node has nothing to inspect."
),
),
DebugViewerInput.Input("wp_viewer", socketless=True),
],
outputs=[],
is_output_node=True,
not_idempotent=True,
)
@classmethod
def execute(cls, context, wp_viewer):
del wp_viewer # accepted for widget binding parity; no runtime use
# Flatten the typed ContextPayload into a single dict the
# frontend `DebugViewer.vue` consumes. User-facing variables
# sit at the top level (matching the on-the-wire ctx shape so
# the snapshot tab reads naturally). Engine-internal keys —
# `__wp_trace__`, `__wp_warnings__`, `__wp_picks__`,
# `__wp_node_seed__`, `__wp_upstream_debug__` — are also at
# top level (with the leading `__` so the snapshot tab's
# default filter strips them out, while the dedicated
# trace/picks/warnings tabs read them explicitly).
flat: dict = dict(context.context)
debug = context.debug or {}
internals = context.internals or {}
if debug.get("__wp_trace__"):
flat["__wp_trace__"] = debug["__wp_trace__"]
if debug.get("__wp_warnings__"):
flat["__wp_warnings__"] = debug["__wp_warnings__"]
if internals.get("__wp_picks__"):
flat["__wp_picks__"] = internals["__wp_picks__"]
if "node_seed" in debug:
flat["__wp_node_seed__"] = debug["node_seed"]
snapshot = json.dumps(flat, default=str, indent=2)
return io.NodeOutput(ui={"wp_debug_snapshot": [snapshot]})