Commit Graph
122 Commits
Author SHA1 Message Date
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
Jason HokuandClaude Opus 4.7 e570f6b58b fix: Run Settings — start_at_job persistence + unconditional override emission
Three issues in 7a2c3c9:

1. start_at_job's onchange handler used setDirtyCanvas() instead of
   saveState() — changes never reached the lora_config widget value.
   Fixed to call saveState().

2. The 6 run-settings emissions were gated on "non-default" values
   (e.g. lora_triggerwords_mode only emitted when != "None"). Result:
   a user setting Builder UI to its default could not override the
   Generator widget if the user had previously set that widget to
   something non-default. Builder UI is now authoritative — emit all
   values unconditionally. start_at_job and image_format also
   switched to unconditional emission for consistency.

3. session_name had no plumbing path. Added emission in
   state_to_configs_json and an override branch in sampler_node so
   the Builder UI's session_name field overrides the generator widget.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 13:25:10 -07:00
Jason HokuandClaude Opus 4.7 f18cc833ea chore: render Run Settings above Distribution Settings (very top of UI)
User wanted Run Settings to be the FIRST section, above everything
including Distribution Settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:29:55 -07:00
Jason HokuandClaude Opus 4.7 7a2c3c905e feat: Builder UI Run Settings — top-of-UI placement + 6 generator-node overrides
Phase 1 of consolidating run-level config into the Builder UI. The
Builder UI's "Run Settings" section is now rendered at the TOP of the UI
(was previously below config arrays) and gains six new fields with help
tooltips:

- overwrite_existing (bool, default false)
- flush_batch_every (int, default 4)
- lora_triggerwords_mode (enum: None / Append To End / Append To Start /
  Read From Config, default None)
- save_conditioning_cache_to_file (bool, default false)
- enable_model_cache (bool, default false)
- vae_batch_size (int, default 4, range -1..64)

State plumbs through state_to_configs_json -> _session_settings ->
sampler_node.run_tests -> run_generation_loop. Builder UI values
override the corresponding widgets on UltimateSamplerGrid when set
(non-default). Widget values remain the fallback so existing workflows
keep working without changes.

Logs an "⚙️ <name> overridden by Builder UI: <value>" line whenever an
override fires, so it's obvious in the console.

Next: once the user has tested this thoroughly, the corresponding
widgets on the SamplerGridTester node can be removed/hidden to
simplify the generator UX (deferred — coordinate with user).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 09:21:14 -07:00
Jason HokuandClaude Opus 4.7 35e6be3a54 fix: include preview panel CSS + drop JSON Preview sidebar nav (orphan)
These changes belong with the earlier "preview panel uses /configbuilder/preview"
work (b6e2344) but were dropped from that commit. Folding in now:

- Adds .cb-preview-panel + resize-handle + header/content CSS used by the
  renderPreviewSection function shipped in 991631a.
- Removes the obsolete addNavIcon("📄", "JSON Preview", ...) sidebar entry.
- Cleans the cb-sec-preview ID out of the scroll-spy section list.

No behavior change beyond what was already committed — fills in the
visual/CSS gap the committed JS depends on.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 12:59:51 -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 4fb4fea5ed fix: lock Compare Strengths to single-bracket form (no Cartesian)
When the user types '0.5, 1.0' they want 2 outputs (lora at 0.5, lora
at 1.0 — both model and clip mirroring), not 4 outputs (Cartesian
m×c). The bug was that we wrote both _model AND _clip side-channel
arrays, so Python emitted 'name:[m]:[c]' which the orchestrator
correctly interpreted as Cartesian.

JS: collapse the two-input compare section to a single 'Strengths:'
input. Never write _clip to lora_weight_arrays.

Python: process_lora_array now emits 'name:[m_arr]' (no clip part)
when only _model array is present. The generator's existing
parse_lora_definition defaults clip=model when the third segment
is missing, giving N configs with locked semantics.

Drops the Cartesian path entirely. Backward compat retained: if a
saved workflow has both arrays (legacy), the dual-bracket form is
still emitted so the orchestrator can Cartesian-expand as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 11:27:39 -07:00
Jason HokuandClaude Opus 4.7 2913fc606a feat: unified Compare Strengths section with labeled Model+Clip inputs
Replaces the two separate '+ Compare Strengths' / '+ Compare CLIP'
buttons with a single button that toggles a section showing two
labeled inputs ('Model Strengths:' and 'Clip Strengths:'). When
Strength Lock is ON, only the Model input shows (CLIP mirrors
automatically — same as today).

Also fixes button-text-not-updating bug: previously the button
required a full re-render to swap between '+ Compare Strengths' and
'✕ Array' text, so toggling the input visible left the button stuck
at '+ Compare Strengths' until page reload. Activation now persists
arrays as [1] (Python passes through unchanged) and uses array
existence rather than length>1 as the active indicator, so reloads
correctly restore the active state.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 10:27:49 -07:00
Jason HokuandClaude Opus 4.7 991631aec4 docs: update conf-builder-readme to reflect /configbuilder/preview endpoint
convertStateToConfigs() was deleted in the previous commit; the JS
preview now POSTs to the new endpoint and Python is the sole transformer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 09:59:48 -07:00
Jason HokuandClaude Opus 4.7 b6e2344f9b feat: preview panel uses /configbuilder/preview endpoint
Replaces synchronous JS convertStateToConfigs (~280 lines) with a
debounced (800ms) fetch to the new endpoint. Preview now renders
literally what generate_config produces — drift impossible by
construction.

Stale-state badge surfaces network failures without blocking editing.
Loading placeholder appears during the first-paint debounce window.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 09:59:10 -07:00
Jason Hoku ef0062fce8 fix: ltx pickers route through modelLists object so refresh-models button updates them 2026-04-27 12:14:39 -07:00
Jason Hoku 15bd7ae2dd fix: localStorage cache version bump + persist latent_upscale_models, clearAllCaches resets all upscale fields 2026-04-27 12:07:41 -07:00
Jason Hoku 2a125cff4b fix: drag-drop and clipboard paste append to existing image input value instead of overwriting 2026-04-25 21:10:03 -07:00
Jason Hoku 1cd7a5528c feat: drag-drop + clipboard paste for ltx image input, resolve via comfy input dir 2026-04-25 21:01:00 -07:00
Jason Hoku 3adad657b6 feat: ltx image-to-video builder ui (image picker, strength sliders, compression) 2026-04-25 20:16:07 -07:00
Jason Hoku a3478c01cb fix: ltx latent_upscaler reads from latent_upscale_models/ folder, not upscale_models/ 2026-04-25 19:43:10 -07:00
Jason Hoku 0b0781f838 fix: ltx config flattening in py generate_config + trust model type before file picked 2026-04-25 19:19:48 -07:00
Jason Hoku f76c9902a0 fix: ltx state lives per-configArray, derive model_type from models[] 2026-04-25 18:37:35 -07:00
Jason Hoku fee9d41090 fix: ltx_video model picker uses diffusion_models folder, LTX badge, LTX file label 2026-04-25 18:19:08 -07:00
Jason Hoku a60f7ed7e8 feat: hide scheduler/steps/denoise/flux fields when ltx_video selected 2026-04-25 18:09:44 -07:00
Jason Hoku 35cd8b8260 feat: ltx image input + audio subsection stubs (full impl in B/C) 2026-04-25 18:05:30 -07:00
Jason Hoku aa94e6c2c2 feat: ltx stage 1 + stage 2 sampler/sigmas subsections 2026-04-25 18:04:02 -07:00
Jason Hoku 5508be8539 feat: ltx video shape subsection (duration + frame rate sliders) 2026-04-25 18:01:01 -07:00
Jason Hoku 8064c31a55 feat: ltx model files subsection (dual clip, vae, upscaler pickers) 2026-04-25 17:59:08 -07:00
Jason Hoku cc52ad679b feat: ltx settings section skeleton with conditional render on model_type 2026-04-25 17:56:17 -07:00
Jason Hoku 99f8cd0202 feat: ltx_video option in model_type dropdown 2026-04-25 17:51:18 -07:00
Jason Hoku 4f874fc628 feat: tooltips on Compare Strengths and Compare CLIP buttons explain LoRA strength sweeps 2026-04-22 17:33:47 -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 beacb02101 fix: fullscreen toggle loads correct session instead of default
When toggling fullscreen, the iframe reload was reading the session name
from the node's widget (default "my_session") instead of the session
the user had actually selected in the Dashboard picker.

Now the Dashboard sends its current session name in the fullscreen
postMessage, and the handler prefers that over the widget default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 10:32:45 -07:00
Jason HokuandClaude Opus 4.6 93016b5888 feat: partial re-render for Builder UI config sections
Add rerenderConfigSection(node, arrayIdx) that rebuilds only one config
array section instead of the entire UI. debouncedRenderUI now accepts
optional arrayIdx parameter — when provided, uses partial re-render.

This avoids the full DOM rebuild (7k+ nodes) when making changes within
a single config section (add/remove model/lora, toggle settings). Falls
back to full renderUI if the target section isn't found in the DOM.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:27:26 -07:00
Jason HokuandClaude Opus 4.6 7b437f0e2f feat: instant model loading with localStorage cache + background polling
Performance improvements for Builder UI model/LoRA loading:

localStorage persistent cache:
- Model lists cached to localStorage on first fetch
- On page reload, cached data renders instantly (no network wait)
- Cache expires after 24 hours, cleared on explicit Refresh Models
- Saves all categories: checkpoints, diffusion, GGUF, text encoders,
  VAEs, upscale models, samplers, schedulers, clip types

Background count polling:
- New /configbuilder/model_counts endpoint returns file counts per
  category (fast — uses folder_paths internal stat-based cache)
- Frontend polls every 30s, compares counts to last known values
- On change: auto-refreshes model lists and re-renders UI
- No manual Refresh Models needed when adding new models

Deduplicated /object_info:
- Shared _getObjectInfo() cache ensures the expensive /object_info
  endpoint is called at most once per session (was called 2-3x)
- getAvailableLoras() and getAvailableModels() share the cached response

Polling lifecycle:
- Starts after initial render, stops when node is removed
- Only active while ConfigBuilder node exists on canvas

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 11:13:18 -07:00
Jason HokuandClaude Opus 4.6 7bc61d47be feat: section presets for Models and LoRAs, CLIP weight array UI
Section Presets:
- Add generic /configbuilder/section_presets endpoint (GET/POST with
  ?section=models|loras|prompts query param)
- Add preset dropdown (Load/Save/Delete) to Models and LoRAs section
  headers in Builder UI
- Models presets save: models list, text_encoders, clip_type
- LoRAs presets save: loras list, weight_arrays, strength_lock

CLIP Weight Array UI:
- Add "+ Compare CLIP" button below CLIP strength slider when strength
  lock is disabled, mirroring the existing model strength array button
- Stores CLIP arrays in lora_weight_arrays[name_clip]

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:06:22 -07:00
Jason HokuandClaude Opus 4.6 7d5fbb213d perf: virtualize searchable select dropdown, fix event listener leak
- Limit dropdown to first 50 options (was creating ALL options as DOM
  nodes — 500+ for LoRAs, 100+ for models — on every focus/keystroke)
- Show "... N more — type to filter" message when truncated
- Use event delegation (single onmouseover/onmouseout/onclick on parent)
  instead of per-option event handlers
- Replace document.addEventListener("click") with input.onblur to close
  dropdown (was leaking global click listeners that accumulated on every
  re-render — 50+ listeners after a few refreshes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:06:10 -07:00
Jason HokuandClaude Opus 4.6 5fc90097dc fix: persist JSON/Visual toggle and add scrollable prompt sections
- Prompt editor JSON/Visual mode now persists in node.uiState.promptRawMode
  across Refresh Models and other re-renders (was a local variable, always
  reset to Visual)
- Added promptRawMode:{} to uiState initialization
- createPromptGroupEditor accepts optional {rawModeKey, uiState} to persist
- Positive prompt groups sections now have max-height: 1000px with overflow
  scroll, preventing long prompt lists from pushing everything down

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:50:34 -07:00
Jason HokuandClaude Opus 4.6 c971e2934d feat: full pipeline editor in dashboard upscale modal
Replace the simplified single-step config editor with renderPipelineEditor(),
a full pipeline/step UI matching the Builder UI feature set:
- Multiple pipelines with add/remove, active toggle, name, collapsible
- Multiple steps per pipeline with all settings (mode, resize, ratio,
  denoise, hires steps, tiled sampling, tiled VAE, repeat)
- Multi-model selector with searchable dropdown and chips
- HiRes prompt adjustment section
- Iteration count display per step

Also fixes:
- Preset double-entry bug: save now deduplicates by name in both
  Builder UI and dashboard modal
- Builder UI hires_force_uniform_tiles checkbox: || true -> !== false
  (was always displaying as checked regardless of stored value)
- Model list fetch: GET instead of POST (matching the endpoint)
- Modal size: 600px wide, 90vh tall for better fit
- Cancel button: sends cancel request to server during active upscale
  instead of just closing the modal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:34:13 -07:00
Jason HokuandClaude Opus 4.6 bc8e2d05cf fix: initialize preset array before async fetch, add save logging
presetSelect._presets was undefined if save was clicked before the
async fetch completed. Now initialized to [] immediately. Added
console logging to debug preset save/load flow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 00:06:05 -07:00