feat(enhance): pick LoRAs from ComfyUI per job (#220)

Templates with `imageapi:lora-slot:<n>:high|low` nodes take LoRAs picked
per job from a catalog built live from ComfyUI.

- Catalog: ComfyUI's LoraLoaderModelOnly `lora_name` choices (cached
  60 s, re-read when a submit names an unknown id), paired by High/Low
  name tokens (StyleHigh/StyleLow, x-HIGH/x-LOW, x_high_noise/...). Files
  the workflow already loads outside the slots (lightx2v, switches) and
  `[template.catalog] exclude` substrings never show; ids derive from the
  names so they stay stable.
- POST /enhance `slots: [{lora, scale?}]` fills the slots in order: each
  pick sets the slot nodes' lora_name and scales their exported strength;
  unused slots run at 0, so the graph is never rewired. More picks than
  slots, duplicates or unknown ids are 400s.
- GET /enhance/templates gains `slots` and `catalog: {loras, strength,
  min, max}`; jobs store and return the picks (new enhance_jobs.lora_slots
  JSON column).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-11-03 16:28:23 -05:00
1 parent 6fffca9989
commit e2cf18678f
15 files changed
+1454 -33

No files matched your search

+14
View File
@@ -87,3 +87,17 @@ default = false # default: false; used when the request omi
strength = 1.0 # default: 1.0; the scale when on without a number
min = 0.0 # default: 0.0; slider range while on (a requested
max = 1.5 # default: 1.5; scale is clamped; <= 0 is off)
# Picked LoRAs (#220): LoRA loader nodes titled "imageapi:lora-slot:<n>:high"
# and ":low" (n = 1, 2, ... without gaps) are slots the app fills from a
# catalog, one picked LoRA per slot. The catalog is every LoRA file ComfyUI
# lists whose name pairs as High/Low (StyleHigh/StyleLow, x-HIGH/x-LOW,
# x_high_noise/x_low_noise), minus the LoRAs the workflow already loads
# (lightx2v, switches); a new download shows up within a minute. A pick's
# scale multiplies the slot's exported strength; unused slots run at 0.
# Settings for the template above (all optional):
[template.catalog]
strength = 1.0 # default: 1.0; a pick's scale when the request gives none
min = 0.0 # default: 0.0; slider range (a requested scale is
max = 1.5 # default: 1.5; clamped; <= 0 leaves the slot unused)
exclude = [] # default: []; file-name substrings never offered