Implement custom portrait generation: update API, UI, and localization to support user-defined prompts for portraits, replacing half-body option with custom variant.
ci / server (push) Failing after 3m38s
ci / client (push) Failing after 14s

This commit is contained in:
Leonid Pershin
2026-08-20 05:16:40 +03:00
parent df0aaad403
commit ac0470bbc4
19 changed files with 301 additions and 76 deletions
+9 -5
View File
@@ -246,7 +246,7 @@ internal static class SchoolEndpoints
if (!PortraitKindParser.TryParse(kind, out var portraitKind))
{
return Problem(StatusCodes.Status400BadRequest, "invalid-query", "kind must be avatar, half, or full.");
return Problem(StatusCodes.Status400BadRequest, "invalid-query", "kind must be avatar, custom, or full.");
}
var lookup = await portraits.EnsurePersonAsync(id, personId, cancellationToken);
@@ -274,6 +274,7 @@ internal static class SchoolEndpoints
int id,
string personId,
string? kind,
GeneratePortraitRequest? body,
PortraitService portraits,
CancellationToken cancellationToken) =>
{
@@ -284,7 +285,7 @@ internal static class SchoolEndpoints
if (!PortraitKindParser.TryParse(kind, out var portraitKind))
{
return Problem(StatusCodes.Status400BadRequest, "invalid-query", "kind must be avatar, half, or full.");
return Problem(StatusCodes.Status400BadRequest, "invalid-query", "kind must be avatar, custom, or full.");
}
if (!portraits.IsGenerationEnabled)
@@ -292,7 +293,7 @@ internal static class SchoolEndpoints
return Problem(StatusCodes.Status503ServiceUnavailable, "swarmui-not-configured", "SwarmUI is not configured.");
}
var result = await portraits.GenerateAsync(id, personId, portraitKind, cancellationToken);
var result = await portraits.GenerateAsync(id, personId, portraitKind, body?.PromptExtra, cancellationToken);
return result.Outcome switch
{
PortraitGenerationOutcome.Succeeded => Results.Created(
@@ -300,8 +301,11 @@ internal static class SchoolEndpoints
new PortraitResponse(
PortraitKindParser.ToApiValue(portraitKind),
result.HasAvatar,
result.HasHalfBody,
result.HasFullBody)),
result.HasCustom,
result.HasFullBody,
result.CustomPortraitPrompt)),
PortraitGenerationOutcome.InvalidPrompt =>
Problem(StatusCodes.Status400BadRequest, "invalid-body", "Custom portraits need a non-empty promptExtra up to 2000 characters."),
PortraitGenerationOutcome.UnknownPerson =>
Problem(StatusCodes.Status404NotFound, "unknown-person", "That person is not in the school."),
PortraitGenerationOutcome.NotConfigured =>