Make meeting lifecycle stateful

This commit is contained in:
2026-05-27 12:55:17 +02:00
parent d607b957bb
commit e85274829a
91 changed files with 4076 additions and 479 deletions
@@ -30,6 +30,37 @@ public sealed class AsrDiagnosticEndpointTests
Assert.StartsWith("endpoint-bytes:", segment.Text, StringComparison.Ordinal);
}
[Fact]
public async Task NamedProfileEndpointPassesProfileToConfiguredProvider()
{
var pipelineFactory = new CapturingProfileSpeechRecognitionPipelineFactory();
await using var factory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration((_, configuration) =>
{
configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
["MeetingAssistant:FunAsr:Backend:Enabled"] = "false",
["MeetingAssistant:LaunchProfiles:english:Hotkey:Toggle"] = "Ctrl+Alt+E",
["MeetingAssistant:LaunchProfiles:english:AzureSpeech:Language"] = "en-US"
});
});
builder.ConfigureTestServices(services =>
{
services.RemoveAll<ISpeechRecognitionPipelineFactory>();
services.AddSingleton<ISpeechRecognitionPipelineFactory>(pipelineFactory);
});
});
using var client = factory.CreateClient();
var wavPath = Path.Combine(AppContext.BaseDirectory, "Fixtures", "sample-16khz-mono.wav");
using var response = await client.PostAsJsonAsync("/profiles/english/asr/transcribe-file", new { path = wavPath });
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("english", pipelineFactory.LastProfileName);
}
[Fact]
public async Task EndpointReportsProviderFailuresAsBadGateway()
{
@@ -179,6 +210,24 @@ public sealed class AsrDiagnosticEndpointTests
}
}
private sealed class CapturingProfileSpeechRecognitionPipelineFactory : ISpeechRecognitionPipelineFactory
{
public string? LastProfileName { get; private set; }
public ISpeechRecognitionPipeline Create()
{
return Create(null);
}
public ISpeechRecognitionPipeline Create(string? launchProfileName)
{
LastProfileName = launchProfileName;
return new TestSpeechRecognitionPipeline(
new EndpointFakeTranscriptionProvider(),
(_, liveSegments, _, _) => Task.FromResult(liveSegments));
}
}
private sealed class TestSpeechRecognitionPipeline : StreamingSpeechRecognitionPipeline
{
private readonly Func<string, IReadOnlyList<TranscriptionSegment>, SpeechRecognitionPipelineOptions, CancellationToken, Task<IReadOnlyList<TranscriptionSegment>>> finalize;