Enhance SwarmUI settings by adding a scheduler property and updating the client to send clip stop at layer instead of clip skip. Added tests to verify the new behavior.
ci / server (push) Failing after 3m41s
ci / client (push) Failing after 14s

This commit is contained in:
Leonid Pershin
2026-08-20 05:02:44 +03:00
parent f603cdd9a9
commit 9225327d31
10 changed files with 487 additions and 2 deletions
@@ -72,6 +72,63 @@ public class SwarmUiClientTests
Task.FromResult(new HttpResponseMessage(HttpStatusCode.ServiceUnavailable));
}
[Fact]
public async Task GenerateAsync_SendsClipStopAtLayerForClipSkip()
{
var handler = new CapturingHandler();
var http = new HttpClient(handler) { BaseAddress = new Uri("http://swarm.test/") };
var client = new SwarmUiClient(
http,
Options.Create(new SwarmUiOptions { BaseUrl = "http://swarm.test", TimeoutSeconds = 30 }),
NullLogger<SwarmUiClient>.Instance);
var settings = new SwarmUiSettings
{
Model = "model.safetensors",
Steps = 4,
CfgScale = 2,
ClipSkip = 2,
Sampler = "dpmpp_sde",
Scheduler = "karras",
Avatar = new SwarmUiSettings.SwarmUiPreset { Width = 512, Height = 512 },
};
await client.GenerateAsync("a student", "bad", settings, PortraitKind.Avatar, CancellationToken.None);
using var document = JsonDocument.Parse(handler.GenerateBody!);
Assert.Equal(-2, document.RootElement.GetProperty("clipstopatlayer").GetInt32());
Assert.False(document.RootElement.TryGetProperty("clipskip", out _));
}
private sealed class CapturingHandler : HttpMessageHandler
{
public string? GenerateBody { get; private set; }
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.RequestUri!.AbsolutePath.Contains("GetNewSession", StringComparison.Ordinal))
{
var session = JsonSerializer.Serialize(new { session_id = "sess-1" });
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(session, Encoding.UTF8, "application/json"),
};
}
if (request.RequestUri.AbsolutePath.Contains("GenerateText2Image", StringComparison.Ordinal))
{
GenerateBody = request.Content is null ? null : await request.Content.ReadAsStringAsync(cancellationToken);
var payload = JsonSerializer.Serialize(new { images = new[] { "data:image/png;base64,iVBORw0KGgo=" } });
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(payload, Encoding.UTF8, "application/json"),
};
}
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
}
private sealed class FakeHandler : HttpMessageHandler
{
public List<string> Requests { get; } = [];