Commit Graph
157 Commits
Author SHA1 Message Date
Jason Hoku 4b1180dc93 Merge branch 'feat/sweep-mixed' into int/wave4 2026-11-04 18:49:26 -08:00
Jason HokuandClaude Fable 5.1 725cb79fd4 feat(sweep): mixed standard + Workflow Sweep runs; SaveWEBM/AnimatedWEBP/AnimatedPNG frame sources (Roadmap 32)
- one Generator run may hold standard configs AND workflow-sweep entries: the sweep is validated
  first (job 1 + busy check, nothing registered), the standard loop runs, then start_sweep launches
  into the same session with one global job numbering (Start At Job counts standard jobs first).
  An interrupt in the loop never starts the sweep; meta.configs_json keeps the full Builder list
  (_standard_run_meta/_completion_payload helpers; next_phase on the completion event; the
  dashboard keeps the ETA bar up with "Workflow sweep next…" and clears the 30 s hide timer on
  any later progress event)
- frame sources: FRAME_SINKS table (VHS_VideoCombine, SaveWEBM, SaveAnimatedWEBP, SaveAnimatedPNG)
  feeding the CreateVideo splice; fps read per sink, clamped to CreateVideo's 1-120 with a plan
  warning; find_output_nodes fallback names; Builder label via framesFps
- tests: 33 python (mixed routing, Start At Job translation, interrupt, pre-flight busy/invalid,
  post-loop busy, three sink fixtures, clamping, VHS golden unchanged), 2 node, 2 Playwright

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 18:48:44 -08:00
Jason Hoku 02de2bf03b Merge branch 'feat/lora-strength-rows' into int/wave4 2026-11-04 18:39:41 -08:00
Jason HokuandClaude Fable 5.1 eb745988b0 test: verify the roadmap's "needs testing" items; fix what they found
- Builder VAE beats the sampler node's remote VAE (normalize_config_vae; the GGUF pre-check
  now treats "None"/"" like Default instead of failing late)
- batch encoding interrupt: verified (no further prompt encoded after the interrupt)
- pre-encode only configs with work left: configs_needing_work() extracted and tested;
  optional-input tracking stays open (fingerprints know nothing about upstream nodes)
- omit logic: "(masterpiece)"-style terms never matched (\b next to punctuation) and a blank
  term omitted everything; fixed with lookarounds + blank skip; the Builder's omit-vs-lookup
  warning fires only when LoRA Triggerwords Mode is None (was a false positive in every other
  mode) and a console warning (omit_without_lookup_warning) prints at run start
- drag reorder: pure reorderTarget/moveItem extracted and tested; doubled handle glyph on
  text-encoder rows and non-handle drops firing a move fixed; browser pass still open
- Builder slowness: section-preset GETs cached per section (one uncached fetch per row per
  render before); three remaining hotspots recorded in Roadmap.md

Roadmap.md: items 77, 81, 104, 9, 10 marked DONE; 83 and 91 annotated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 18:39:33 -08:00
Jason HokuandClaude Fable 5.1 65e8df81c4 feat(builder): LoRA strength rows (Roadmap 12)
A "+" beside the model-strength slider adds another strength to compare (one slider when
Lock is on, model + CLIP when off; up to 8 per LoRA, duplicates greyed out). The state keeps
only the extra rows (lora_extra_strengths[name] = [{model, clip}]), row 0 stays the verbatim
base string so existing jobs keep their fingerprints. state_to_configs_json emits concrete
"name:m:c" strings on the lora axis (stacks = every combination, first LoRA slowest); the old
"Compare Strengths" comma box is removed and converted on first edit. The Iterations count
now mirrors process_lora_array (fixes the stack overcount). Dashboard: a LoRA whose name is on
every card but with several strengths keeps its label; filter buttons keep the strengths.

Tests: 33 python (shared fixture, byte-identical output without the key, expand_configs end to
end, xfail for the pre-existing folder-drop bug), 8 node, 10 Playwright (the Builder modules
load from the fake origin with the real state_to_configs_json answering the preview).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 18:39:25 -08:00
Jason HokuandClaude Fable 5.1 0e563a19cb feat(prompts): COUPLE regional prompts via native masked conditioning (#11)
`base COUPLE left | right` (2-4 equal columns; COUPLE(rows) for bands; region ` :w` weight)
splits a prompt into an unmasked base cond plus one masked cond per region, blended by
ComfyUI's own mask/mask_strength path (latent-couple style, one extra UNet pass per region,
works for every model family). COUPLE is parsed first; each part still takes AND/CAT/AVG/BREAK.

- regional_prompt.py: parser, join helpers (byte-identical output without COUPLE, cache keys
  depend on it), size-independent region tags, latent-size mask builder with tile/crop frames,
  apply_regional_masks at sample time
- batch_encoding: COUPLE prompts take the combinator path (never the batched TE path)
- conditioning_cache: conditioning_v2 keeps every entry and extra key (the old format silently
  dropped AND prompts); legacy entries are a one-time miss
- trigger words, model suffix and HiRes append_end land in the base, not the last region
- tiled HiRes and Florence2 crops pass their frame; invalid syntax stops the run early;
  LTX video warns; Builder tooltip + README section + ProjectStructure/AI-CONTEXT
- 107 new tests (parser, masks, encoding, cache round trip, source guards)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 17:50:15 -08:00
Jason HokuandClaude Fable 5.1 f88129cb37 fix: ultrareview slice C (workflow sweep) findings
- append_items never replaces an unreadable manifest with a fresh one (raises, file untouched) and
  writes through the retrying atomic helper; the sweep spec write retries PermissionError too
- breaker only pauses while jobs remain; a paused sweep with nothing in flight or pending completes
  instead of blocking new sweeps with SweepBusy
- sampler IS_CHANGED returns NaN when configs_json is linked (absent from kwargs), so a re-queued
  sweep is never served from ComfyUI's cache
- Start At Job # = N skips N-1 jobs like the orchestrator
- dry_run / api_start expand the sweep in an executor, off the event loop
- Builder sweep section re-reads configArray.workflow on every render (load/remove replaced it)
- favorites export and GENERATE NEW skip workflow-sweep items (no template)
- Pairwise Review excludes all wf_* per-job keys
- test: same-sweep attach waits for the feeder's first enqueue (pre-existing race)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 16:44:19 -08:00
Jason HokuandClaude Fable 5.1 e35030f0a4 fix: ultrareview slice D (waves 2+3) findings
- lazy shell: SAVE never persists __uscg_lazy__ (saveState guard + save_manifest pop); the manifest
  fetch route heals files that already carry it
- dashboard node: a Builder session switch does a full reload (session_name from the payload, not
  the stale widget) instead of re-fetching the old session
- dashboard node: window message handlers only accept a dashboard iframe as source
- scanned ids are namespaced by session (same relpath in two sessions no longer collides on merge);
  rescan merge donates each old id once and only via unambiguous basenames
- deferred upscale resume is keyed on base_fp == config_fp (fixed-seed grids upscale every cell)
- legacy distributed companion ignores the preview pass: master keeps the upscale phase
- connected latent: recompute w/h before gen_w/gen_h so 16x models record real dimensions
- Start on an identical paused sweep resumes it
- outputFromKey keeps subgraph node ids ("57:35") whole

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 15:25:46 -08:00
Jason Hoku 756bae4b9b Merge branch 'feat/lazy-manifest' into int/wave3 2026-11-04 03:31:09 -08:00
Jason HokuandClaude Fable 5.1 5cf0782ce0 feat(dashboard): lazy manifest loading, the page is a shell and the SPA fetches /config_tester/manifest
html_generator.get_html_template now emits a shell (empty fullManifest flagged
__uscg_lazy__, inline_manifest=True restores the old behaviour). New route
GET /config_tester/manifest?session=<name>: compact JSON, weak ETag, 304 on
If-None-Match, gzip, torn-read retry (logic in run_api.load_manifest_for_fetch).
/config_tester/dashboard gets gzip + content ETag. The SPA boots with one fetch
(no more double load), resync is conditional and non-destructive, and
web/dashboard.js asks the iframe to re-fetch (reload_manifest) instead of
parsing data out of the Generator's executed message. Also fixes the dead
session-name regex in dashboard_node.py.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 03:25:59 -08:00
Jason HokuandClaude Fable 5.1 7fd1a64741 feat(sweep): Builder output picker lists video sources; dashboard keeps JOB for sweep videos
No new top-level Builder field: workflow_output gains optional media/frames_from keys, emitted only
for video, so the rule-5 checklist does not apply and image configs JSON is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 03:02:38 -08:00
Jason Hoku e88d769815 Merge branch 'feat/drag-drop' into int/wave2 2026-11-04 01:10:41 -08:00
Jason Hoku cff2144ae5 Merge branch 'feat/metrics-adapter' into int/wave2 2026-11-04 01:05:06 -08:00
Jason Hoku 637fac3cf8 Merge branch 'feat/builder-polish' into int/wave2 2026-11-04 01:00:33 -08:00
Jason HokuandClaude Fable 5.1 8ce4398c4d feat(builder-polish): run-API full pass, vae drift fix, honest minimize_reloads wording
- Record session_settings + has_optional_inputs in manifest meta (run_meta_extras) so the
  Dashboard "Full pass for survivors" can queue POST /config_tester/run headless; the iframe
  falls through to it when the parent has no Builder / no queuePrompt.
- Exclude the deliberately omitted "vae" key from _EXPECTED_CONFIG_KEYS; test_examples asserts zero drift.
- minimize_reloads: log VAE switches + a "changed nothing" note, accurate tooltip/README wording.
- examples/README: Klein base-variant note; fix stale LTX stub comment.
- Tests: run_meta_extras, job order, state_to_configs_json, e2e full pass (new file).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:59:45 -08:00
Jason HokuandClaude Fable 5.1 e88b18a549 fix(dashboard): drag the Revise image onto Load Image / canvas, plus a Send to Load Image button (#22)
Rich dragstart (asset-info JSON, uri-list, plain, DownloadURL; reference not copy), a modal button that
fills the selected/only/new Load Image via the parent bridge, standalone Download image fallback.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:58:31 -08:00
Jason HokuandClaude Fable 5.1 3eae054c11 feat(builder): load workflow sweep sessions
Load Session restores Workflow Sweep arrays from meta.configs_json (workflowConfigToArray) and
tells the user when an older sweep session has no saved configs. Builder Start shows 'attached'.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:56:03 -08:00
Jason HokuandClaude Fable 5.1 70da77816f feat(builder): metrics adapter badge honours the status 'problem' field
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:53:06 -08:00
Jason HokuandClaude Fable 5.1 968b0dfdfc feat(sweep): attach to a running identical sweep, job_prompt route, configs in sweep meta
Identity = session + ordered job fingerprints + start_at_job + overwrite_existing; anything
else gets a clear 409. GET /config_tester/sweep/job_prompt returns one job's API prompt.
Sweep manifests now save their workflow configs in meta.configs_json.
pause/resume emit a progress event.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:52:56 -08:00
Jason Hoku d1714a2b8b Merge branch 'feat/workflow-sweep' into integration
# Conflicts:
#	README.md
#	__init__.py
#	sampler_node.py
2026-11-04 00:21:39 -08:00
Jason HokuandClaude Fable 5.1 e25c08a039 feat(workflow-sweep): Builder workflow-sweep section and dashboard labels
New ES module conf-builder-workflow-sweep.js (load API workflow, output picker,
suggested bindings, node table, axis editors, dry run modal, start/pause/resume/cancel
with status polling), wired additively into the config-array list, default state and
migrations. Dashboard ETA bar shows 'Sweep job' with an error count and hides REVISE
for workflow items. README, ProjectStructure and Roadmap updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:19:10 -08:00
Jason Hoku add7fbb2cb Merge branch 'feat/metrics' into integration
# Conflicts:
#	resources/logic_pipeline.js
#	resources/logic_state.js
#	resources/logic_ui.js
#	web/conf_builder/conf-builder-config-management.js
#	web/conf_builder/conf-builder-main.js
2026-11-04 00:16:58 -08:00
Jason Hoku 3c3fd7a49d Merge branch 'feat/preview-pass-ordering' into integration
# Conflicts:
#	tests/test_state_to_configs_json.py
#	web/conf_builder/conf-builder-main.js
2026-11-04 00:15:02 -08:00
Jason Hoku ecf01d62b8 Merge branch 'feat/batched-te' into integration
# Conflicts:
#	web/conf_builder/conf-builder-main.js
2026-11-04 00:09:39 -08:00
Jason HokuandClaude Fable 5.1 148922ee2f feat(dashboard): preview badge, Pass filter, superseded previews, full-pass button
PREVIEW badge on cards and a modal note, a Pass filter row (hidden until previews exist),
previews superseded by a full image (config_fp/base_fp match) hidden by default, a preview bar
with 'Full pass for survivors (N)'. The button asks web/dashboard.js (postMessage) to switch
Preview pass off in the matching Config Builder and call app.queuePrompt; a marked stub
covers a future run API; fallback is an instructions toast.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:09:26 -08:00
Jason HokuandClaude Fable 5.1 acee4fd545 feat(metrics): Builder Run Settings control, session-settings emission and metrics_info route
Session-level setting (not a per-config key). state_to_configs_json emits
_session_settings.metrics only when enabled and non-empty; GET
/configbuilder/metrics_info reports built-ins and scorer-pack install status.
Faster numpy fallback; README and ProjectStructure updated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:09:19 -08:00
Jason HokuandClaude Fable 5.1 ffb352fb92 feat(builder): job order and preview pass run settings
State keys job_order, preview_pass{enabled,steps,scale,cfg_override}, skip_rejected_previews,
only_favorited_previews: new-state defaults + migration, Run Settings controls, emission with
coercion in state_to_configs_json, tests, README/ProjectStructure.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:06:08 -08:00
Jason HokuandClaude Fable 5.1 98fcf0861c feat(encode): te_batch_size Run Setting wires text-encoder batching into pre-encode
batch_encode_with_cache/batch_encode_prompts take te_batch_size (default 1 =
off, DEFAULT_TE_BATCH_SIZE) and a hidden te_batch_verify; batched prompts are
cached, leftovers take the unchanged per-prompt loop, and the summary line
reports batched prompts/forwards. Builder state default + migration, Run
Settings control, state_to_configs_json emission, orchestrator read, README.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 00:05:57 -08:00
a0a164ba6f fix(ltx,builder): expand Builder prompt arrays for LTX; empty TE list; builder-schema reload
From #21: _expand_ltx_entry ran positive/negative through to_list, so the
Builder's [["p1","p2"]] reached the LTX encoder as a list; it now uses
parse_prompt_input_nested like expand_configs. The text-encoder dropdown
falls back to ["None"] when the list is empty. convertConfigsToConfigArrays
keeps the per-entry model type for builder-schema models[].

Refs #21

Co-authored-by: DRuggeri <DRuggeri@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 23:59:53 -08:00
caf8f35bec feat(builder): finish "Additional Random Seeds" run setting from PR #21
Builder Run Settings already emitted add_random_seeds_to_gens through
_session_settings; this adds the missing new-state default and the
saved-config migration, tests for the emit -> sampler_node unwrap ->
expand_configs path, and a README Run Settings entry.

The extra seeds are now derived from the base seed
(config_utils.derive_extra_seeds) instead of unseeded random.randint, as the
README always promised. Besides reproducibility this makes stop/resume work:
the skip check matches on seed, so an interrupted run can now skip the
extra-seed images it already rendered.

Ported from #21 (it conflicts after the repo restructure). Closes #21.

Co-authored-by: DRuggeri <DRuggeri@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-03 23:59:53 -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 23185fa521 feat(run-settings): add 'Additional Random Seeds' to Builder UI
Wires the existing add_random_seeds_to_gens parameter (already in
generation_orchestrator.py:824) through the full Run Settings pipeline:

1. Builder UI: state default + _addRunSetting widget (int, 0-100, default 0)
2. config_builder_node.py: emits into session_settings in configs_json
3. sampler_node.py: reads from session_settings, overrides the local variable

The generation loop already handles it — generates N extra images per config
with random seeds when > 0. Previously hardcoded to 0 with no UI path.

Based on PR #21 by external contributor, rebased onto current main with
full pipeline wiring.

Tests: 118/118 pass.
2026-05-26 11:50:48 -07:00
Jason Hoku 3e76e89192 fix(builder-ui): Florence2 Input MP step 0.01 + drop debug logs
- web/conf_builder/conf-builder-config-management.js: step 0.25 -> 0.01
  (was too coarse, matches the dashboard upscale modal renderer)
- resources/logic_upscale_modal.js: remove 2 debug console.log calls
  left in the Florence2 Input MP onChange handler
2026-05-20 00:22:30 -07:00
Jason Hoku 30f37630c4 feat(builder-ui): louder CivitAI notice + 3 new locations
Phase 3 smoke-test feedback from Jason:
- Notice is too subtle — switch from italic gray to dark-red
  prominent style (border-left, dark-red tinted bg, bold link)
- Add notice in 3 more places:
  1. Run Settings 'LoRA Triggerwords Mode' (when != None and companion
     missing — toggles dynamically on select change)
  2. 'LoRA Metadata Lookup' modal (showLoraMetadataModal)
  3. '🔎 LoRA Trigger Words Lookup' modal (Omit list lookup)

DOM methods only - no innerHTML. Placeholder pattern in modals so the
notice appears in correct visual order despite async availability check.
2026-05-19 21:37:36 -07:00
Jason Hoku 9be78fb4a9 feat(builder-ui): inline notices when CivitAI companion missing
Adds small italic notice in 3 sections when ComfyUI-USCG-CivitAI is
not installed:
1. Model 'Lookup Metadata from CivitAI' button section
2. LoRA 'Auto Append Trigger Words' section
3. LoRA 'Lookup Metadata from CivitAI' button section

Notice: 'Plugin feature — install [ComfyUI-USCG-CivitAI](github) for
auto-trigger detection + metadata lookup.'

DOM methods only - no innerHTML. Async-checks via /uscg-civitai/health.
2026-05-19 18:59:18 -07:00
Jason Hoku 87bbcaea7d refactor(builder-ui): update fetch paths to /uscg-distribution/*
Matches the namespaced routes the Distributed companion now registers.
2026-05-19 15:35:21 -07:00
Jason Hoku 5f6c2b5a95 feat(builder-ui): render install card when Distributed companion missing
Distribution panel sections now async-check for the companion via
/uscg-distribution/health. 200 → renders normal panel; 404 → renders
install card (Comfy Manager + GitHub link + Re-check button).

DOM methods only - no innerHTML. Saved Distribution settings preserved
in node.state when companion isn't installed - no data loss.
2026-05-19 15:34:01 -07:00
Jason Hoku 1ade757837 feat(builder-ui): render install card or controls based on companion presence
The 'Remote URL' VAE type now asynchronously checks for the
ComfyUI-USCG-RemoteVAE companion plugin and renders either:
- An install card (Comfy Manager / GitHub instructions + Re-check button)
  when companion is missing.
- A working preset dropdown + URL input populated from the companion's
  /uscg-remote-vae/endpoints route when companion is installed.

DOM methods only - no innerHTML. Saved configs preserve their 'remote:<url>'
value either way; no data loss when companion isn't installed.
2026-05-19 13:25:10 -07:00
Jason Hoku 4a8ab843f3 refactor(builder-ui): replace REMOTE_VAE_PRESETS with companion fetch helpers
Deletes the hardcoded REMOTE_VAE_PRESETS object. Adds cached detection
helpers isRemoteVaeAvailable() and loadRemoteVaeEndpoints() backed by
the companion's /uscg-remote-vae/health and /endpoints routes.

The if (isRemote) render block still references REMOTE_VAE_PRESETS as
of this commit; that branch is rewritten to use the new helpers in the
next commit (B8).
2026-05-19 13:22:45 -07:00
Jason Hoku fb3530d4d4 feat: florence2 — pre-detect image resize to slash vision-encoder VRAM
User insight: Florence2's vision encoder activations scale with input image
dimensions, not with the polygon complexity it outputs. Down-scaling the
source image BEFORE detection saves the bulk of Florence2-stage VRAM
(encoder is dominant over the decoder's KV cache for moderate sequence
lengths). Detection accuracy at 0.5 MP is essentially identical to full
resolution for face/region tasks because the polygon is coarse and gets
smoothed by GrowMask + feather + crop+paste-back downstream anyway.

Implementation in florence2_hires.run_florence2_step:
- Read step_config['florence2_input_mp'] (default 0.5; set 0 to disable)
- If source MP > target, common_upscale source down to target dims with
  lanczos before passing to Florence2Run
- After detection, common_upscale the returned mask back up to source dims
  with bilinear so the crop / grow / feather / inpaint / paste-back chain
  operates at full source resolution as before
- Only down-scales — never up-scales (skip when source already smaller)
- Manifest entry records florence2_input_mp + florence2_detect_resized
  for forensics
- Console log shows both src and detect dimensions per call

UI: new 'Florence2 Input MP' numeric field (range 0-4.0, step 0.25)
in BOTH the Builder UI's Florence2 sub-panel and the Dashboard's Upscale
Image modal Florence2 panel. Default 0.5. Tooltip explains the VRAM
tradeoff and that it only takes effect when source > this MP.

Mirrors createDefaultFlorence2Options() + render block in both
conf-builder-config-management.js (Builder) and logic_upscale_modal.js
(Dashboard), keeping the two UI surfaces in sync.
2026-05-19 11:11:38 -07:00
Jason Hoku 713d99b36b fix: florence2 — revert max_new_tokens 256 -> 1024 (kijai stock)
User report: 'half a face' upscaled, the other half not — classic polygon
truncation symptom. Plus 'beam search runs to 100% and fills VRAM' — Florence2
not hitting EOS within the cap because it can't generate a complete polygon
in 256 tokens, so it spends the whole budget on garbage continuations.

My earlier 256 default was a panic fix for the wrong problem. The actual
root cause of the OOM was the duplicate session-model load (fixed via
same-model short-circuit in _get_or_load_checkpoint_lora) plus stale prior-
gen models in VRAM (fixed via soft_empty_cache at upscale_runner start).
With those fixes in place, 1024 fits fine.

The model emits EOS when the polygon is complete (typically token 50-100
for a face). 1024 is the CEILING, not the typical generation length. The
KV cache is pre-allocated for the cap but doesn't actually use all of it
unless the model fails to EOS — which is exactly what happens when the
cap is too tight.

Reverted defaults across florence2_hires.py + Builder UI + Dashboard
upscale modal. Updated tooltip to explain the trade-off correctly. Bumped
UI min from 32 to 64 (32 was nonsensically low and could be hit
accidentally by step=32 spinner clicks).
2026-05-19 10:40:59 -07:00
Jason Hoku b321f95323 feat: florence2 — max_new_tokens exposed in Builder UI + Dashboard upscale modal
Default 256 (was hardcoded). Range 32-2048 step 32. Bump higher if Florence2
polygons get truncated on complex multi-face scenes; lower for VRAM savings.

Wired:
- florence2_hires.py: reads step_config.get('max_new_tokens', 256) and stores
  it on manifest_extras for forensics
- web/conf_builder/conf-builder-config-management.js: added to
  createDefaultFlorence2Options() + a numeric input next to 'Output Mask
  Select' in the Builder UI sub-panel
- resources/logic_upscale_modal.js: same in the dashboard's Upscale Image
  modal default + UI field

Tooltip explains the VRAM trade-off (~50 tokens needed for a face polygon;
256 is 5x headroom; KV cache scales linearly).
2026-05-18 12:58:40 -07:00
Jason Hoku 543ba66c2b fix: florence2 — hide irrelevant Upscale Ratios + Tiled Sampling fields; add diagnostic log
Upscale Ratios is meaningless for florence2_hires (it inpaints a region, not the
whole image — Target MP controls the internal pass size). Tiled Sampling is also
irrelevant since Florence2 crops are too small to need tiling.

Diagnostic log line: '[Florence2HiResFix] src=(WxH) crop=(WxH) requested_MP=X
-> internal_pass=(WxH)=Y MP'. This will reveal whether target_megapixels is
actually being applied to the resize step.
2026-05-18 11:06:30 -07:00
Jason Hoku af03349f2e fix: florence2_hires — remove min/max crop res from UI (Florence2 decides bbox)
User report: lowering Max Crop Res caused the crop window to miss the
detected object. Root cause: the contract-around-center logic in
_crop_image_by_mask works fine for centered bboxes but pushes the crop
window away from the bbox when the bbox is near an image edge (e.g., a face
touching the right edge of a 512-wide image with max=200 produces a crop
centered at x=296 which only partially overlaps the actual face at x>=300).

Fix per user suggestion:
- Remove min_crop_resolution + max_crop_resolution from Builder UI
- Defaults are now no-op (min=0, max=99999)
- Florence2's polygon + grow_expand + crop_padding fully determine crop region
- Python helper keeps the params for backwards compat with existing tests
2026-05-18 09:41:49 -07:00
Jason Hoku e88b4bad6f feat: builder — render Florence2 step sub-panel with 14 fields
Adds the Florence2 Hi-Res Fix option to the upscale mode dropdown and a
sub-panel that renders when selected: 4 detection fields, 4 crop/resize fields,
5 mask-shape fields (grow_expand + 4 feather sides), model/lora source dropdown,
and the no-detection dropdown. Hires sampling fields (denoise/steps/cfg/sampler
/scheduler) are reused from the existing hires_only mode rendering — Florence2
sets showHires=true so they appear naturally. Combos counter treats Florence2
as 1-output-per-input (no cartesian multiplier).
2026-05-18 01:38:03 -07:00
Jason Hoku 67eba954e1 feat: builder — default florence2 step config + load-time migration 2026-05-18 01:34:35 -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 a1cb7c3346 chore: vae_batch_size + flush_batch_every default 4 → 1
User feedback: 1 is a more sensible default for typical generation —
smaller VAE batches keep VRAM lower, and flushing every gen makes the
dashboard show progress immediately.

Updated everywhere:
- sampler_node run_tests fallback defaults (post-widget-removal)
- conf-builder-main.js initial state + migration backfill
- conf-builder-config-management.js renderRunSettingsSection
  state-init defaults + _addRunSetting defaultValue
- config_builder_node.py state_to_configs_json emit fallback +
  except-clause fallback for both fields

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 11:56:19 -07:00
Jason HokuandClaude Opus 4.7 7e9eade2c6 feat: always-visible help note on UltimateSamplerGrid node
After the widget cleanup (30e3aa9), the SamplerGridTester is nearly
empty — just one required input (configs_json), six optional sockets,
and a single output. New users won't know how to wire it.

Adds a small footnote (~44px tall) at the bottom of the node via a
non-serialized DOM widget:

  "Connect the configs_json from the Builder node to this node, and
   connect this node to the Dashboard node"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 17:34:47 -07:00
Jason HokuandClaude Opus 4.7 67cb0f5acf feat: Builder UI — larger default node size + smaller preview panel default
Two UX defaults users hit on first drop:

1. Default node size was ~200x100 (Comfy's default), making the HTML
   overlay invisible. Bumped to 720x900 on fresh create. Existing
   workflows keep their saved size (only the max-with-current is
   applied, gated by an _uscgSizeInitialized flag so the size override
   doesn't fight user resizes).

2. Output Preview panel defaulted to 450px which dominated the UI on
   smaller nodes. Reduced to 175px (~8 lines of JSON visible at the
   11px/1.4-leading default font). The drag handle still lets users
   grow it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 13:45:19 -07:00