Commit Graph
71 Commits
Author SHA1 Message Date
Jason HokuandClaude Fable 5.1 198138e51c perf(encode): prepare the text encoder once per pre-encode loop, not once per prompt
ComfyUI's CLIP.encode_from_tokens() calls load_model() -> model_management.load_models_gpu()
on every encode. With the dynamic VRAM loader (comfy_aimdo, 0.4x+) that re-runs
ModelPatcherDynamic.load() for a model that is already resident: a walk over every module plus
free_memory bookkeeping, visible as one

    Model MOSSImageTEModel_ prepared for dynamic VRAM loading. 7002MB Staged. ...

log line per prompt (N prompts -> N+1 lines). USCG's pre-encode paid it once per prompt, and
again on the single-encode paths (model switch, distributed, upscale, Florence2 hires).

Measured on the 5060 Ti (ComfyUI 0.42.5), MOSS-Image TE = Qwen3.5-9B w4a8, same process state:
  template path (CLIPTextEncode), per prompt ....... 0.92 s   (re-prepare every encode)
  USCG batch encode with pinned_clip, per prompt ... 0.84 s   (one prepare per pass)
  USCG job, 21 prompts + 21 one-step images ........ 36.8 s -> 33.0 s
  for scale: SDXL 0.15 s, Krea 2 0.29 s, Qwen-Image 0.32 s per prompt on the template path
The rest is the encoder forward itself: ~0.55 s fixed + ~2 ms/token for Qwen3.5-9B (24 of its
32 layers are Gated DeltaNet run through the pure-torch chunked recurrence, fp32 compute), so
a 60-prompt MOSS grid still spends ~50 s encoding before the first image. That part is
identical to the official workflow.

batch_encoding.pinned_clip(clip, texts): load once through load_model() (sized by the longest
text so any memory estimate still runs), shadow clip.load_model with a no-op for the block,
restore on exit or exception, nesting safe. encode_pair_cached(): positive+negative with one
load, nothing when both are cached. The pre-encode summary line now prints total time and
ms/prompt.

Applied to batch_encode_with_cache, the model-switch pre-encode in the main loop, the
distributed group pre-encode and per-job encode, the deferred-upscale re-encode fallback, the
dashboard upscale runner and the Florence2 hires step.

Tests: tests/test_pinned_clip.py (10) against the real batch_encoding module; the conftest
stub gained pinned_clip/encode_pair_cached. 137 passed, same 15 pre-existing torch-stub failures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 22:16:43 -08:00
Jason HokuandClaude Fable 5.1 e17021ee8c fix(moss): empty latent follows the model's latent ratio; moss_image CLIP type; Skip Layer Guidance option
MOSS-Image (Flux.2 latent: 128ch, 16 px per cell) jobs were built with the
SD-era `h // 8`, so every image sampled a latent with 4x the cells and decoded
at 2x the requested size (832x1216 -> 1664x2432): ~10x slower than the official
ComfyUI template (~120 s vs ~10 s per image on the 5060 Ti).

- model_loader: get_latent_downscale_ratio() reads latent_format.spacial_downscale_ratio
  (8 for SD/SDXL/Flux.1, 16 for the Flux.2 family); make_empty_latent() builds the
  job latent and warns when WxH is not a multiple of the ratio. Both orchestrator
  latent sites (main loop + distributed worker) use it; hires-fix latent upscale,
  tiled hires sampling and VAE tiling divisors no longer assume 8.
- CLIP type: resolve_clip_type() warns on unknown types instead of silently using
  stable_diffusion, and when clip_type is left at the default it follows the
  detected model family (MOSSImage -> moss_image, Flux2 -> flux2, ...). MOSS loaded
  as a generic Qwen3.5 TE before (wrong chat template). The Builder's CLIP Type
  list is now read from ComfyUI's CLIPLoader/DualCLIPLoader (static list = fallback,
  now including moss_image); LS_CACHE_VERSION 3 refreshes cached lists.
- Skip Layer Guidance: new Extra Model & Sampling sub-group wrapping
  SkipLayerGuidanceDiTSimple (double/single layers, start/end %), plumbed like Deep
  Shrink (builder emission, expand_configs, orchestrator, generate_image). Defaults
  match the official MOSS-Image workflow (single block 22, 0-50%).
- tests: latent geometry + clip type resolution, dynamic clip type lists, SLG
  config emission/expansion (24 new; the 15 pre-existing torch-stub failures unchanged).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 20:23:10 -08:00
Jason Hoku efc506332b refactor(orchestrator): route distribution branch through facade
- Replaces direct imports of distribution_manager/routes with `from . import distribution`.
- All DistributionManager(...) / set_distribution_manager(...) /
  notify_workers_to_start(...) / stop_all_workers(...) / _get_master_url()
  calls now go through the facade.
- Early-exit guard at distribution branch entry raises clear install
  instructions when the companion plugin isn't installed.
- create_manager call passes three callbacks (job_completed_check,
  build_prompt_with_triggers, get_model_cache_key) so the companion's
  DistributionManager can avoid bidirectional imports back into main USCG.
- _get_master_url() function deleted (moved to companion's usrv_dist_socket).
- _send_distribution_status moved into generation_orchestrator (it was just
  a PromptServer.send_sync helper, no network).

The 3 distribution_*.py files in main USCG are now unreferenced. Deletion
happens in subsequent commits.
2026-05-19 15:11:46 -07:00
Jason Hoku 44f32b06ba fix(orchestrator): pivot empty-URL error to install instructions when companion missing
When Remote URL VAE is configured but the companion plugin
(ComfyUI-USCG-RemoteVAE) isn't installed, the Builder UI shows an install
card and saves an empty URL ('remote:'). extract_remote_vae_url() was
raising a misleading 'URL is empty' message at run time.

Now: if companion is missing -> RuntimeError with install instructions
       if companion is installed but URL is empty -> original message

Discovered during Phase C smoke test.
2026-05-19 13:42:56 -07:00
Jason Hoku f20a17d6ea refactor(orchestrator): drop HF_ENDPOINTS import; pass endpoint name to worker
The companion plugin (ComfyUI-USCG-RemoteVAE) resolves endpoint names to
URLs internally. Main USCG no longer needs the URL allowlist - it only
passes the endpoint NAME (e.g. 'SDXL') through the worker.
2026-05-19 13:19:19 -07:00
Jason Hoku d4b88b0420 fix: florence2 — avoid duplicate model load + soft_empty_cache between items
User report: 'Allocation on device 0 would exceed allowed memory' OOM mid
Florence2 beam search on a 2-image batch with 8 GiB VRAM. Currently allocated
15.5 GiB on what should be a 3-5 GiB workload.

Root cause: dashboard upscale_runner ALREADY loaded meta.model into VRAM as
its session base. My from_manifest path then called load_checkpoint() for
item.model — same checkpoint name, but a SECOND full copy in VRAM (a fresh
ModelPatcher with its own UNet+CLIP+VAE weights). For SDXL that's ~7 GiB
duplicated. Plus the Florence2 model on top.

Fix:
- Pass session_model_name from upscale_runner / orchestrator into Florence2
- _get_or_load_checkpoint_lora short-circuits when item.model == session_model_name:
  reuse the session's base handles and just apply the item's LoRAs on top
  (load_loras_for_preencoding is a cheap patch, no weight reload)
- Different model name → still does a fresh full load (correct behavior)
- Add comfy.model_management.soft_empty_cache() at end of run_florence2_step
  to release intermediate KSampler latents and beam-search buffers before
  the next item iterates

96/96 tests still green (the new branch is covered by the existing
test_from_manifest_caches_by_combo + test_from_builder_returns_fallback
cases; same-model short-circuit doesn't change observable behavior for
those mocks).
2026-05-18 12:16:10 -07:00
Jason Hoku d8b553e7a9 fix: florence2_hires inline path — insert(0) + set upscale_produced
Ordering bug: my dispatch used existing_data['items'].append(meta) which puts
new entries at the END of the list. The canonical pattern at L2255 uses
insert(0, meta) (newest first, matches flush_batch_with_vae's order). Result:
Florence2 outputs appeared in wrong position relative to other images.

Duplicate base bug: my dispatch never set upscale_produced = True. That flag
gates whether the BASE image gets saved at L2337 — without it, every Florence2
run produced TWO manifest entries (the inpainted result AND the un-inpainted
base), with the same gen_index. Also added rejected:False to match the
canonical entry shape.
2026-05-18 09:13:30 -07:00
Jason Hoku 90dcdc9551 fix: florence2_hires inline path — use upscale_random, not bare random
UnboundLocalError at runtime: 'cannot access local variable random where it
is not associated with a value'. Cause: Python scopes 'random' as a local
of the entire _run_jobs function (it's imported as a bare name later in the
function at L2471 etc), so any earlier reference triggers UnboundLocalError.

The inline upscale loop imports 'import random as upscale_random' at L1797
specifically to avoid this — my Florence2 code (and seedvr2's at L2035)
used bare 'random.randint' which shadowed the local. Switched both my sites
+ the pre-existing seedvr2 site to upscale_random.

Tests still 96/96 green.
2026-05-18 08:43:46 -07:00
Jason Hoku 448cea1516 fix: florence2_hires inline path — use create_image_metadata, not dict(meta)
'meta' isn't assigned until L2324, AFTER the inline upscale loop. My
dispatch used dict(meta) twice (sentinel + success), both NameError'd at
runtime with 'cannot access local variable meta where it is not associated
with a value'. Switched both to create_image_metadata(conf, ...) matching
the normal hires/model upscale pattern at L2184.

(The pre-existing seedvr2 inline dispatch at L2025 has the same bug —
out of scope for this fix.)
2026-05-18 08:33:32 -07:00
Jason Hoku 6e399091fa fix: florence2_hires — wire dispatch into the INLINE upscale path
The inline upscale loop in generation_orchestrator._run_jobs (~L1875) runs
per-job when 'Upscale Pipeline' is enabled in the Builder. It had a seedvr2
elif but no florence2_hires elif — so my mode fell through to combos=[] and
silently did nothing. (The upscale_runner.py path I wired previously only
covers DASHBOARD-triggered upscales, not inline runs.)

Adds the parallel florence2_hires dispatch to the inline path:
- Decodes the just-generated latent to PIL via decode_latent_with_vae
- Forces model_source='from_builder' (the loaded model is what we want for
  inline runs; from_manifest would trigger a redundant reload)
- Honors no-detection sentinel + chained-step re-encode flow
- Manifest entry has upscale_source='inline' (vs 'dashboard' for the
  dashboard path)

Preflight guard uses a module-global since 'job' doesn't exist in this
scope (each job is just a loop iteration here).

Test count unchanged (96 passing) — this is plumbing-only; unit tests
already cover run_florence2_step + manifest builders. Real-Comfy smoke
test is the verification.
2026-05-18 07:27:13 -07:00
Jason HokuandClaude Opus 4.7 580fcc2f58 fix: orchestrator normalizes "None" VAE to "Default" at every read site
The state_to_configs_json fix (a3ad111) correctly omits the "vae" key
when nothing is selected, but the orchestrator still crashed when a
config carried "vae": "None" from any other path — legacy saved state,
Revise modal edits, distributed worker job specs, etc. Even a fresh
Builder UI node could trigger this if any consumer pushed "None" back
into the entry.

Defense in depth: at all 4 read sites in generation_orchestrator.py,
normalize "None"/"none"/empty/falsy values to "Default" before the
"!= Default" gate that decides whether to load a per-config VAE. With
"Default" the orchestrator falls back to the checkpoint's bundled VAE
instead of calling load_vae_by_name("None") which raises
FileNotFoundError.

Sites normalized: check_if_job_completed VAE comparison (~line 227),
first-conf VAE load (~line 1029, the user's crash trace), per-config
VAE switching in the main loop (~line 1454), distributed-mode VAE
switching (~line 2885).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 15:33:16 -07:00
Jason HokuandClaude Sonnet 4.6 7c809e5dfb feat: integrate Kohya Deep Shrink (PatchModelAddDownscale) into Builder UI
Adds a new SUB-GROUP 4 in the Builder UI's "Extra Model & Sampling
Options" section with all 7 params from ComfyUI's built-in
PatchModelAddDownscale node:
- block_number (int, default 3)
- downscale_factor (float, default 2.0)
- start_percent / end_percent (float 0-1, default 0.0 / 0.35)
- downscale_after_skip (bool, default true)
- downscale_method / upscale_method (combo: bicubic/nearest-exact/
  bilinear/area/bislerp, default bicubic)

Toggle checkbox controls whether the patch is applied. State plumbs:
config_array.use_deep_shrink/* (JS) -> state_to_configs_json -> per-
config entries -> expand_configs base_combos -> generate_image -> looks
up PatchModelAddDownscale via NODE_CLASS_MAPPINGS and calls .patch() to
patch the model before sampling. Logs an "Applied
PatchModelAddDownscale" line on each gen for visibility.

Mirrors the existing model_sampling_override / use_advanced_sampling
patterns for consistency. Hidden on LTX video config arrays since the
patch targets the SDXL/SD UNet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 12:22:25 -07:00
Jason HokuandClaude Opus 4.7 5804ac7309 fix: ETA progress shows effective progress (existing + new) not iteration idx
User feedback: when 25/26 items already exist and only 1 new is being
generated, dashboard showed "job 14/26" or similar (skip path doesn't
update progress). Now displays effective progress: existing_count +
new_completed / total. So a session with 25 pre-existing shows 25/26
immediately, then 26/26 after the 1 new gen.

- Adds new_completed counter (separate from loop-index current_job)
- Replaces current_job with existing_count+new_completed in dashboard-
  facing log/send_sync (lines 2107, 2114, 2123, 2133)
- Sends an initial progress update right after pre-flight so the user
  sees the correct "already done" count before the first gen, clearing
  any stale values from a prior run
- Other current_job references (LTX dispatch, image-gen log, start_at_job
  gate, periodic save, final send, distributed mode) keep iteration-
  index semantic — different contexts

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 10:26:04 -07:00
Jason HokuandClaude Opus 4.7 1f5adeb799 fix: extend image_format plumbing to remote VAE / upscales / distributed
Commit 490c519 added a webp/png/jpg dropdown but only flush_batch_with_vae
honored it. Three other save sites still hardcoded WEBP:
- flush_batch_with_remote_vae (image_generation.py)
- upscale_runner.py (3 sites in inline + deferred upscale paths)
- distribution_worker.py (PIL bytes shipped back to master)

Now all save sites read image_format from session_settings (orchestrator)
or the job spec (distributed) and match the format/extension.

Changes:
- remote_vae.py: RemoteVAEDecodeWorker accepts image_format kwarg; _worker
  uses it to pick format/extension at save time (the real save site for the
  remote VAE path — flush_batch_with_remote_vae only queues to the worker)
- generation_orchestrator.py: passes image_format to all RemoteVAEDecodeWorker
  constructors (initialize_remote_vae + 3 per-config sites); adds image_format
  to all 8 existing_data["meta"] writes so upscale_runner can read it from disk
- upscale_runner.py: reads image_format from manifest meta at thread start;
  uses _fmt/_ext locals at all 3 save sites (seedvr2, latent-decode, PIL)
- distribution_manager.py: injects _session_image_format into worker job
  config alongside existing _session_cooldown passthrough
- distribution_worker.py: reads _session_image_format from config; encodes
  bytes in the chosen format; stamps _image_ext on meta so master uses it
- distribution_routes.py: pops _image_ext from meta to build filename with
  correct extension before writing bytes to disk

Default behavior unchanged: all paths fall back to webp if image_format
is absent or unrecognised.

Code review found this in 490c519.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:29:52 -07:00
Jason HokuandClaude Opus 4.7 490c5196ef feat: configurable image save format (webp/png/jpg)
Adds a dropdown to the Builder UI's Run Settings section letting users
pick the saved image file format. Default remains webp (current
behavior). State plumbed through state_to_configs_json ->
_session_settings -> orchestrator -> save_image_to_disk.

PNG users will see lossless saves; JPG users smaller files at quality 95.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:05:10 -07:00
Jason HokuandClaude Opus 4.7 c45058adf3 feat: pre-flight scan counts already-existing configs in ETA
Scans the planned configs list once before the generation loop and
counts how many already have output files on disk (the same skip path
used by check_if_job_completed). Displays the count in the running
ETA line: "job X/Y (P%) | ETA: ... | N existing".

Helps users gauge how much actual work remains when re-running a
session that's been partially completed in a prior run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:02:19 -07:00
Jason Hoku fe73850d81 fix: ltx uses sampler resolutions widget for width/height (was hardcoded 446x576) 2026-04-25 21:31:06 -07:00
Jason Hoku cdd230ef52 fix: disable ltx skip-on-exists, use timestamp suffix for filename uniqueness 2026-04-25 21:04:25 -07:00
Jason Hoku f6bb5a0ef5 fix: ltx manifest entries get timestamp-based id matching image-gen pattern 2026-04-25 20:53:38 -07:00
Jason Hoku 20acff8a1e fix: ltx manifest entry includes 'file' key (/view? URL) for dashboard video loading 2026-04-25 20:46:27 -07:00
Jason Hoku 3d9d27617d fix: ltx output filename includes config hash so meaningful changes break skip-on-exists 2026-04-25 20:34:53 -07:00
Jason Hoku fd9f191d22 fix: ltx mp4 saves to images/ subfolder, manifest image_path for dashboard load 2026-04-25 20:12:53 -07:00
Jason Hoku 655816c9c9 fix: move ltx dispatch above image-gen log/build_prompt that assume sampler/steps keys 2026-04-25 19:29:23 -07:00
Jason Hoku f533c4755a fix: skip pre-encoding stage for ltx_video runs (uses dual-clip internally) 2026-04-25 19:26:53 -07:00
Jason Hoku 0d5d0aa723 fix: exempt ltx_video configs from non-checkpoint VAE validation 2026-04-25 19:25:04 -07:00
Jason Hoku 7ff5059dee feat: ltx_video dispatch in main generation loop 2026-04-25 17:58:42 -07:00
Jason Hoku d58f00a4d0 feat: ltx manifest entry builder, video media_type (manifest_utils.py untouched) 2026-04-25 17:53:30 -07:00
Jason Hoku 166ca832b2 feat: ltx-aware sort order for cache locality 2026-04-25 17:51:42 -07:00
Jason Hoku dca70cb90f feat: cache key for ltx_video model_type 2026-04-25 16:48:32 -07:00
Jason HokuandClaude Opus 4.6 9e7911aa23 feat: SeedVR2 upscale mode in Builder UI and Dashboard
Adds SeedVR2 as a new upscale mode alongside HiRes Fix, Model Upscale,
and Model+HiRes. Requires ComfyUI-SeedVR2_VideoUpscaler to be installed
as a dependency — the plugin calls its nodes programmatically.

Data Model:
- New seedvr2 options object on each upscale step with all SeedVR2
  parameters: dit_model, resolution, max_resolution, seed,
  color_correction, batch_size, noise scales, blocks_to_swap,
  attention_mode, offload_device, cache_model, VAE tiling options
- _defaultSeedVR2Options() / createDefaultSeedVR2Options() helpers
- Migration: ensureStepFields adds seedvr2 defaults to existing configs

Builder UI (conf-builder-config-management.js):
- "SeedVR2 Upscale" added to mode dropdown
- When selected, shows full SeedVR2 settings: DiT model selection
  (10 variants: 3B/7B x fp16/fp8/GGUF/sharp), resolution, seed,
  color correction, noise scales, batch size, VRAM optimization
  (blocks_to_swap, attention_mode, offload), VAE tiling with
  conditional encode/decode tile size and overlap fields

Dashboard (logic_upscale_modal.js):
- Same SeedVR2 mode and fields in renderPipelineEditor via _renderStep
- All fields use existing _makeSelect/_makeNumber/_makeCheckbox helpers

Python Execution (image_generation.py):
- New seedvr2_upscale(pil_image, seedvr2_config) function
- Imports SeedVR2 nodes from NODE_CLASS_MAPPINGS at runtime
- Calls SeedVR2LoadDiTModel → SeedVR2LoadVAEModel → SeedVR2VideoUpscaler
- Converts PIL→tensor→SeedVR2→tensor→PIL
- Clear error if SeedVR2 not installed

Pipeline Integration (generation_orchestrator.py):
- Inline upscale path: mode=="seedvr2" branch decodes current latent
  to PIL, calls seedvr2_upscale, saves result, updates manifest
- Supports chained steps: non-final SeedVR2 steps re-encode to latent
  for the next step in the pipeline

Preset compatible: seedvr2 config serializes naturally as JSON, saved
and loaded with upscale presets without any special handling.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:29:00 -07:00
Jason HokuandClaude Opus 4.6 1d86313fcc fix: distribution wait loop timeout prevents infinite block
The master's wait-for-workers loop could block forever if a worker
crashed without cleanup, leaving a job in "Claimed" state. The
_release_timed_out_jobs() was only called during claim_job, never
during the wait loop.

Fixes:
- Call release_timed_out_jobs() every 5s during the wait loop to
  reclaim jobs from dead workers (no heartbeat)
- Add configurable wait_timeout (default 600s/10min) from distribution
  config — after timeout, force-reclaim all remaining claimed jobs and
  proceed to finalization instead of looping forever
- Add public release_timed_out_jobs() method to DistributionManager
- Remaining jobs after timeout are marked completed and abandoned with
  a warning, unblocking the ComfyUI queue

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 09:59:57 -07:00
Jason HokuandClaude Opus 4.6 d46ec6a9b0 feat: upscaling support in distributed mode
Workers now generate base images only, and the master runs all upscale
pipelines after distributed generation completes. Uses the existing
run_deferred_upscales() function. The warning message now says upscales
will run on master after collection instead of "not supported."

Builds deferred queue from all generated items in existing_data, runs
after remote VAE cleanup but before final manifest save.

Also adds model count endpoint for fast change detection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:27:25 -07:00
Jason HokuandClaude Opus 4.6 5ee1834587 feat: LoRA weight array Cartesian expansion in generation pipeline
Add _expand_lora_weight_arrays() that expands bracket notation in LoRA
strength fields into Cartesian product of configs:
  lora1:[0.5, 1.0]:1.0 + lora2:0.8:[0.7, 1.0] → 4 configs

Distinguishes weight arrays (brackets in strength after :) from folder
random syntax (brackets in name before :). Runs before folder expansion
so both features work together correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:05:58 -07:00
Jason HokuandClaude Opus 4.6 7d7324d880 fix: worker submission race condition after master finishes
The delayed manager cleanup used a flat 30s timer, which could expire
before a slow worker finished submitting its last result. Now polls
every 10s (up to 5 minutes) checking if any registered workers still
have recent heartbeats before cleaning up the manager.

Also added clarifying comment on submit_result route — it intentionally
does NOT check is_active, only manager existence, to accept late
submissions from workers that were mid-generation when master finished.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:50:12 -07:00
Jason HokuandClaude Opus 4.6 9b8f01ea48 feat: add Start At Job # option for custom job resume/skipping
New 'Run Settings' section in Builder UI with a job number input.
When set > 0, the generation loop skips all jobs before that number.
Useful for resuming at a specific point without relying on
auto-detection. Flows through session settings to the orchestrator.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 16:00:43 -07:00
Jason HokuandClaude Opus 4.6 dd104b521a feat: implement deferred upscales with run_deferred_upscales()
When run_upscales_at_end is enabled, inline upscale is skipped and
jobs are queued. After generation completes (before cleanup), the
deferred phase loads base images from disk, VAE-encodes them, and
runs full pipeline chains. Includes resume support, interrupt handling,
and progress reporting with phase="upscaling".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 02:30:28 -07:00
Jason HokuandClaude Opus 4.6 9cf556d886 fix: prompt ordering and duration metric with upscaling
- Replace set() with ordered list dedup for batch encoding so prompts
  generate in the order they're written in the config array
- Track cumulative upscale duration so the time metric includes both
  generation and all upscale steps instead of just the last upscale

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 18:00:47 -07:00
JasonHokuandClaude Opus 4.6 89b6ce4eb1 feat: upscale pipelines system + save pre-upscale + HiRes prompt adjust
Replace flat upscale configs with pipeline/steps/repeat architecture:
- Pipelines run independently from base image
- Steps chain sequentially within a pipeline
- Steps support repeat count for iterative refinement

Add "Save Pre-Upscaled Output" option to also keep the base image.

Add "Adjust Prompt During HiRes Fix" with prepend/append/replace
behaviors. HiRes-adjusted prompts are batch pre-encoded for efficiency.
Results written to manifest metadata and exposed as label overlays.

Fix fmtVal scoping error in buildLabelOverlay (was referenced outside
the upscale block where it was defined).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 15:33:04 -07:00
JasonHokuandClaude Opus 4.6 2bded1cf6c fix: upscaling manifest issues — correct file URL, add id field, skip base image
Three bugs fixed:
1. Upscaled images used bare 'filename=...' instead of full '/view?filename=...&type=output&subfolder=...' URL format, causing 404s in dashboard
2. Upscaled manifest entries missing 'id' and 'rejected' fields, causing holes in dashboard grid
3. Base (non-upscaled) images were still saved to pending_batch when upscaling was enabled — now only upscaled final versions appear in output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 03:29:11 -07:00
JasonHokuandClaude Opus 4.6 b443184316 fix: prevent crash on empty model name and correct upscale_size for model_only mode
Skip upscale combos that require a model when none is selected.
Use effective_size=2.0 for model_only mode instead of 1.0 which
would resize the model output back to original resolution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:36:48 -07:00
JasonHokuandClaude Opus 4.6 9555aad4d9 feat: array-based upscaling with Cartesian expansion in orchestrator
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:26:00 -07:00
JasonHokuandClaude Opus 4.6 91b8598ac3 feat: add seed settings, canvas flicker fix, upscaling & GPU cooldown
- Seed: expanded per-gen behavior + new full run seed behavior (random/increment/decrement before/after entire run)
- Canvas: fix flicker during simultaneous pan+zoom via requestAnimationFrame batching
- Upscaling: 3 session-level modes (HiRes fix, model upscale, model+HiRes) with tiled VAE support
- Cooldown: configurable GPU breaks between generations with optional VRAM clearing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 14:00:06 -07:00
JasonHokuandClaude Opus 4.6 d404420042 fix: disable job skip/resume when optional inputs are connected
Previously, check_if_job_completed() with optional inputs would only
match on sampler/scheduler/steps/cfg/denoise/seed — skipping model,
prompt, and lora checks. This caused false positive matches, skipping
jobs even when the user changed models via optional input nodes.

Now returns -1 (no match) immediately when has_optional_inputs=True,
forcing all jobs to re-generate since upstream changes can't be detected.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:53:55 -08:00
JasonHokuandClaude Opus 4.6 38b766cc92 fix: preserve all conditioning extra dict keys during worker serialization
The conditioning serialization was only preserving pooled_output, dropping
critical keys like attention_mask that Wan/T5 models need for proper
sampling. This caused KSampler to produce NaN latents on distributed workers.
Includes backwards compatibility with old serialization format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 14:38:54 -08:00
JasonHokuandClaude Opus 4.6 f6f21e309d fix: remove force_patch_weights for Dynamic VRAM compatibility
ComfyUI v16.3's Dynamic VRAM uses ModelPatcherDynamic which asserts
force_patch_weights=False. Removed the flag from both CLIP GPU loading
calls to match ComfyUI's own CLIP.load_model() pattern. Backwards
compatible with older ComfyUI versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:09:49 -08:00
JasonHokuandClaude Opus 4.6 5e7ad22cc7 fix: backslash in f-string, dashboard focus stealing, VAE config priority, column hotkeys
- Fix Python 3.10 SyntaxError: extract backslash replace() out of f-string
  expression in config_builder_node.py (issue #12)

- Fix dashboard iframe stealing focus from ComfyUI on every live update
  by removing viewport.focus() from render/update paths in logic_virtual.js

- Intercept Ctrl+S in dashboard iframe and forward to ComfyUI parent
  window so workflow save works instead of triggering browser Save As dialog

- Config Builder VAE settings now override sampler node's remote_vae_endpoint
  via config_overrides_vae flag in generation_orchestrator.py flush logic

- Fix Shift+1-9 column hotkeys: use e.code instead of e.key since Shift
  produces symbols (!@#$) not digits for e.key on standard keyboards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:41:44 -08:00
JasonHokuandClaude Opus 4.6 a4060351bd Fix claim_timeout default from 300 to 600 in orchestrator
The DistributionManager, config builder, and UI all already used 600 as
the default, but the orchestrator's fallback was still 300. This caused
premature job reclaim when workers loaded models for the first time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 23:41:59 -08:00
JasonHokuandClaude Opus 4.6 fddffd7a8c Add worker model sync and upcoming models pre-fetching
Worker downloads missing models from master via HTTP before processing.
Background pre-fetch thread downloads upcoming models during job execution.
Distribution manager scans pending queue for unique model references.
Job claim responses include upcoming_models list when sync enabled.
Master passes sync_models_to_workers flag to workers via start_worker.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:15:54 -08:00
JasonHokuandClaude Opus 4.6 aadae6d94a feat: per-config resolutions — builder UI, config expansion, generation override
Each config array can now have its own resolution list displayed as chips with
categorized preset dropdown (SD 1.5/SDXL/Flux × Square/Portrait/Landscape) plus
custom W×H input. Resolutions flow through configs_json, expand in the Cartesian
product, and override the sampler's global resolutions_json on a per-config basis.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 04:24:15 -08:00
JasonHokuandClaude Opus 4.6 c8f8bfae7a feat: pass extra model & sampling options through orchestrator to generate_image
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 18:25:02 -08:00