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>
So the app builds against the final shape: each [[template.lora]] gains
`strength` (the scale when on, default 1.0) and `min` / `max` (the
slider's range, default 0.0-1.5).
- POST /enhance `loras` takes true / false or a scale: true = strength,
false or <= 0 = off, a scale is clamped to min..max.
- The scale multiplies each node's exported strength_model /
strength_clip, so 1.0 = as exported and a high/low pair keeps its
ratio.
- Jobs and the job view store the resolved scale per id (0 = off);
GET /enhance/templates lists strength, min and max.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A template can offer optional LoRAs the app turns on or off.
- enhance.toml: [[template.lora]] { id, label, default } per template.
Each id drives every workflow node titled `imageapi:lora:<id>`, so
Wan's high- and low-noise pair share one switch.
- POST /enhance takes `loras: {id: bool}`; a missing id uses its default,
an id the template doesn't offer is a 400. Off sets strength_model
(and strength_clip when present) to 0, so the graph is never rewired.
- The resolved switches are stored on the job (new enhance_jobs.loras
JSON column) and returned in the job view, so a retry or adjust can
repeat them; GET /enhance/templates lists each template's switches.
- A lora-titled node without a declaration keeps its exported strength,
and a declaration without nodes isn't offered; both are startup
warnings. A lora-titled node without a numeric strength_model fails
the template.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Groundwork for Enhance "Animate" (#208): a video made from a photo.
- Version linking reads the XMP link from MP4 / MOV too (top-level uuid box
with the XMP UUID, mdat seeked over), at ingest and on Enhance approve.
- New kind `animated`, a derived clip (CLIP_KINDS): hidden behind the photo
like a version, but not counted in photo_version_counts / version_count,
never a display choice (400 clip_not_displayable), and listed as `clips`
in GET /image/versions. Approve returns the clip entry.
- Templates whose imageapi:save is ImageApiSaveVideoVersion report
output "video" in /enhance/templates (no enhance.toml change). Previews
already relay ComfyUI's content type (video/mp4).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SeedVR2VideoUpscaler (the new Sharpen / Rescue templates) rejects seeds
above 2^32 - 1 at validation, and the 52-bit seeds made every job fail with
"Value ... bigger than max of 4294967295: seed". 32 bits is still plenty of
variety for the Fibo templates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>