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.
63 lines
2.4 KiB
Python
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]})
|