Split SwarmUI portraits into a model catalog and layered prompts.

Picker is Swarm intersect config, preset style/shot inherit model defaults, and living saves lift the old preset shape.
This commit is contained in:
Leonid Pershin
2026-08-20 14:08:11 +03:00
parent cc9ea18480
commit 81fd3f6181
20 changed files with 1142 additions and 179 deletions
+16 -12
View File
@@ -495,9 +495,9 @@ is `image/png`. Opening the card does not generate; use POST when the player ask
### `POST /api/schools/{id}/people/{personId}/portrait`
Generates (or regenerates) a portrait through SwarmUI on the server. Same `kind` query as GET.
For `kind=custom` the body is `{ "promptExtra": "..." }` — appended to the base SwarmUI prompt and
the person's body/clothing; required, non-empty, at most 2000 characters. Avatar and full-body POST
need no body.
For `kind=custom` the body is `{ "promptExtra": "..." }` — appended after the shot type (and the
model/style layers), then the person's appearance and clothing; required, non-empty, at most 2000
characters. Avatar and full-body POST need no body.
Success is `201` with `{ "kind", "hasAvatar", "hasCustom", "hasFullBody", "customPortraitPrompt" }` and a `Location` header pointing
at GET. SwarmUI is not configured when `SwarmUi:BaseUrl` is empty — `503` `swarmui-not-configured`.
Swarm errors are `502` `swarmui-unavailable`; a slow backend is `504` `swarmui-timeout`. Files
@@ -506,8 +506,8 @@ land under `saves/{id}.portraits/` and survive until the school is deleted.
### `GET /api/schools/{id}/people/{personId}/portrait/prompt`
Returns the positive and negative prompts SwarmUI would receive, without generating an image.
Same `kind` query as GET portrait. For `kind=custom`, optional query `promptExtra` is appended to
the base prompt; when omitted, the last saved custom prompt is used if one exists. Unknown school
Same `kind` query as GET portrait. For `kind=custom`, optional query `promptExtra` is appended after
the shot type; when omitted, the last saved custom prompt is used if one exists. Unknown school
is `404` `unknown-school`; unknown person is `404` `unknown-person`. Invalid `kind` is
`400` `invalid-query`; custom without a usable prompt is `400` `invalid-body`.
@@ -527,21 +527,25 @@ so the client can disable generate buttons and show reachability without trying
### `GET /api/settings/swarmui`
Returns the **default** SwarmUI preset template (`swarmui.json`): named presets (model, steps,
sampler, LoRA lists, per-kind sizes/prompts), `activePresetId` and `ageRules`. A new school copies
this into its save as `portraitSettings`. Living schools generate from that copy, not from this
file.
Returns the **default** SwarmUI template (`swarmui.json`): a `models` catalog (id, default
generation knobs, usually empty base positive/negative), named presets (model id, `style`, extra
negative, optional generation overrides, per-kind size/`shotType`), `activePresetId` and `ageRules`.
The model picker in the UI is Swarm's list intersected with `models`. A new school copies this into
its save as `portraitSettings`. Living schools generate from that copy, not from this file. Older
saves without `models` lift on load (`positive``style`, kind `positive``shotType`).
### `PUT /api/settings/swarmui`
Replaces the default template after validation. Invalid preset ids, age rules or numeric ranges
Replaces the default template after validation. Invalid model/preset ids, age rules or numeric ranges
return `400` `invalid-body`. Already-created schools keep the copy they were created with.
### `GET /api/settings/swarmui/discovery`
When SwarmUI is configured and reachable, proxies `ListT2IParams` and returns
`{ connected, models, loras, samplers, schedulers }` for the settings UI comboboxes. When SwarmUI
is off or unreachable, `connected` is false and the lists are empty.
`{ connected, models, loras, samplers, schedulers }` for the settings UI. The client hides Swarm
models that are missing from the template catalog. When SwarmUI is off or unreachable, `connected`
is false and the lists are empty; the picker then shows the catalog ids so fields can be filled
manually.
### `GET /api/schools/{id}/dress-rules`