fix: harden per-GPU preview outputs after review

- Typed serverless pools validate the unpruned workflow, so a preview on
  any new slot failed the whole run; both serverless compilers now accept
  every Collector output slot (COLLECTOR_OUTPUT_COUNT).
- Serverless pools are config workers: their serverless:<pool>:<job>
  participants now share the pool's worker_N slot instead of overflowing.
- A worker returning only empty frames no longer raises in the preview
  split (the combined batch already skipped them).
- Worker previews are views into the combined batch, not a second copy,
  and a frame-count guard skips them rather than misattribute frames.
- Frontend: one shared config fetch per load; unnamed slots drop their
  saved label instead of storing a redundant one.
- Tooltip notes that the per-GPU outputs are unavailable downstream of
  Ultimate SD Upscale Distributed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
speedyrulz
2026-10-31 16:42:40 -04:00
co-authored by Claude Fable 5.1
parent 18ff755001
commit 339719ece7
8 changed files with 217 additions and 50 deletions
+2 -1
View File
@@ -16,6 +16,7 @@ from graphlib import CycleError, TopologicalSorter
from ...serverless_bridge.contract import SOCKET_KINDS, VALUE_SOCKETS, identifier, validate_bindings
from ...serverless_bridge.image_transfer import DEFAULT_FORMAT, validate_options
from .serverless_prompt import (
COLLECTOR_OUTPUT_COUNT,
_PRIMITIVE_NODES,
_REMOVED_SCALAR_NODES,
_is_link,
@@ -99,7 +100,7 @@ def _validate_prompt(prepared_prompt, *, require_collectors=True):
if source_class in _REMOVED_SCALAR_NODES or source_class in _PRIMITIVE_NODES:
if slot != 0:
raise ValueError(f"invalid output slot {slot} for scalar node {source_id!r}")
elif source_class == _COLLECTOR and slot >= len(COLLECTOR_SOCKETS):
elif source_class == _COLLECTOR and slot >= COLLECTOR_OUTPUT_COUNT:
raise ValueError(f"invalid output slot {slot} for collector {source_id!r}")
parents.add(source_id)
dependencies[node_id] = parents
+5 -1
View File
@@ -29,8 +29,12 @@ _PRIMITIVE_NODES = {
"PrimitiveInt": 0,
"PrimitiveString": "",
}
# DistributedCollector outputs: images, audio, then the per-GPU previews
# (PER_GPU_OUTPUT_NAMES in nodes/collector.py). Previews are valid link
# sources in a workflow even though a pool only ever returns images and audio.
COLLECTOR_OUTPUT_COUNT = 2 + 9
_REMOVED_NODE_OUTPUTS = {
"DistributedCollector": {0, 1},
"DistributedCollector": set(range(COLLECTOR_OUTPUT_COUNT)),
"DistributedSeed": {0},
"DistributedValue": {0},
"DistributedModelName": {0},