feat(enhance): LoRA strength scale alongside the on/off switch (#218)

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>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-11-03 14:01:04 -05:00
1 parent 31da21e061
commit cc96873f86
7 files changed
+298 -110

No files matched your search

+10 -8
View File
@@ -460,7 +460,7 @@ auth and stays LAN-only, so ImageApi relays previews too.
`unreachable_grace_secs`, `default_template`, `warn_above_megapixels`,
`[[path_map]]` (`from`, `to`), `[[template]]` (`name`, `label`, `description`,
`file`, `prompt_mode`, `prompt_join`, `output_megapixels`, `[[template.lora]]`
(`id`, `label`, `default`)).
(`id`, `label`, `default`, `strength`, `min`, `max`)).
- **Templates** are API-format workflow exports, read-only (never edit them from
here). Nodes are found by `_meta.title`: `imageapi:source` (required, gets the
photo path), `imageapi:save` (required, forced to `require_approval = true`; a
@@ -469,9 +469,10 @@ auth and stays LAN-only, so ImageApi relays previews too.
`imageapi:prompt` (optional; fills the first of `text` / `prompt` / `value`),
`imageapi:reference` (optional), `imageapi:lora:<id>` (optional LoRA switches, #218:
a declared `[[template.lora]]` id drives every node with that title, e.g. Wan's high and
low pair; off = `strength_model`/`strength_clip` set to 0, never rewired; a node with no
declaration keeps its strength, a declaration with no node isn't offered; both log a
startup warning). `prompt_mode = "append"`: the user's text is joined
low pair; the resolved scale multiplies each node's exported `strength_model` /
`strength_clip` (1.0 = as exported, 0 = off, a pair keeps its ratio), never rewired; a
node with no declaration keeps its strength, a declaration with no node isn't offered;
both log a startup warning). `prompt_mode = "append"`: the user's text is joined
after the template's own prompt with `prompt_join` (default one space); empty text
leaves the prompt as is. `"replace"`: the text *is* the prompt and is required (empty
= 400); it needs a prompt node. With no `reference_path` the reference node **and
@@ -518,9 +519,10 @@ GET /enhance/templates
"prompt_mode": "append"|"replace", "prompt_required",
"accepts_reference","default","output_megapixels",
"warn_above_megapixels", "output": "image"|"video",
"loras": [{"id","label","default"}]}]}
POST /enhance {"path","template","prompt"?,"reference_path"?,"loras"?: {id: bool},"library"?} -> job
(a missing switch uses its default; an id the template doesn't offer = 400)
"loras": [{"id","label","default","strength","min","max"}]}]}
POST /enhance {"path","template","prompt"?,"reference_path"?,"loras"?: {id: bool|scale},"library"?} -> job
(true = the switch's strength, false or scale <= 0 = off, a scale is clamped to min..max;
a missing switch uses its default; an id the template doesn't offer = 400)
GET /enhance/jobs/{id} -> job
GET /enhance/jobs?path=&library= -> {"jobs": [job, ...]} newest first, discarded hidden
GET /enhance/jobs[?status=a,b] -> {"jobs": [...]} no path = the jobs manager: every photo's
@@ -537,7 +539,7 @@ POST /enhance/jobs/{id}/approve {"n"} -> a /image/versions `versions[]` (or `cli
POST /enhance/jobs/{id}/discard -> job (hidden from the list; ComfyUI untouched)
job = {"id","status","queue_position"?,"error"?,"path","library_id","template",
"prompt"?,"reference_path"?,"loras"?: {id: bool} (resolved; absent without switches),
"prompt"?,"reference_path"?,"loras"?: {id: scale} (resolved, 0 = off; absent without switches),
"created_at","updated_at",
"run_ms": <ms ComfyUI ran it, or null until finished / when ComfyUI gave no timings>,
"pending": [{"n","preview": "/enhance/jobs/{id}/preview/{n}","approved"}],