Public Access
Add meeting workflow automation
This commit is contained in:
@@ -4,6 +4,7 @@ using MeetingAssistant.Speakers;
|
||||
using MeetingAssistant.Transcription;
|
||||
using MeetingAssistant.MeetingNotes;
|
||||
using MeetingAssistant.Summary;
|
||||
using MeetingAssistant.Workflow;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -634,6 +635,41 @@ public sealed class RecordingCoordinatorTests
|
||||
Assert.Equal(["Chris <chris@example.com>"], attendees);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StopRemovesIdentifiedSpeakerAliasDuplicatesWhenCanonicalAttendeeExists()
|
||||
{
|
||||
var audioSource = new CapturedChunkThenCancelAudioSource(new AudioChunk(new byte[] { 1, 0, 2, 0 }, 16000, 1));
|
||||
var noteStore = new InMemoryMeetingNoteStore();
|
||||
var finalizer = new CapturingTranscriptFinalizer(
|
||||
[
|
||||
new TranscriptionSegment(TimeSpan.Zero, TimeSpan.FromSeconds(1), "Guest03", "hello")
|
||||
]);
|
||||
var coordinator = new MeetingRecordingCoordinator(
|
||||
audioSource,
|
||||
new TestSpeechRecognitionPipelineFactory(new FinalSegmentOnAudioCompletionProvider(), finalizer.FinalizeAsync),
|
||||
new InMemoryTranscriptStore(),
|
||||
noteStore,
|
||||
new CapturingMeetingNoteOpener(),
|
||||
new InMemoryMeetingArtifactStore(),
|
||||
new InMemoryRecordedAudioStore(),
|
||||
new CapturingMeetingSummaryPipeline(),
|
||||
Options.Create(new MeetingAssistantOptions()),
|
||||
NullLogger<MeetingRecordingCoordinator>.Instance,
|
||||
speakerIdentificationService: new FixedSpeakerIdentificationService(
|
||||
"Guest03",
|
||||
"Christopher",
|
||||
["Christopher", "Chris"]));
|
||||
|
||||
await coordinator.StartAsync(CancellationToken.None);
|
||||
noteStore.UpdateAttendees(["Ada", "Christopher", "Chris <chris@example.com>", "Chris"]);
|
||||
await audioSource.WaitUntilCapturedAsync();
|
||||
|
||||
await coordinator.StopAsync(CancellationToken.None);
|
||||
|
||||
var attendees = Assert.IsType<List<string>>(noteStore.SavedNote?.Frontmatter.Attendees);
|
||||
Assert.Equal(["Ada", "Christopher"], attendees);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LiveSpeakerIdentityMatchRelabelsCurrentAndFutureTranscriptSegments()
|
||||
{
|
||||
@@ -975,6 +1011,43 @@ public sealed class RecordingCoordinatorTests
|
||||
artifactStore.States);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RecordingLifecycleRunsMeetingWorkflowEvents()
|
||||
{
|
||||
var audioSource = new CapturedChunkThenCancelAudioSource(new AudioChunk([1, 0, 2, 0], 16000, 1));
|
||||
var workflowEngine = new CapturingMeetingWorkflowEngine();
|
||||
var finalizer = new CapturingTranscriptFinalizer(
|
||||
[new TranscriptionSegment(TimeSpan.Zero, TimeSpan.FromSeconds(1), "Guest03", "hello")]);
|
||||
var coordinator = new MeetingRecordingCoordinator(
|
||||
audioSource,
|
||||
new TestSpeechRecognitionPipelineFactory(
|
||||
new FinalSegmentOnAudioCompletionProvider(),
|
||||
finalizer.FinalizeAsync),
|
||||
new InMemoryTranscriptStore(),
|
||||
new InMemoryMeetingNoteStore(),
|
||||
new CapturingMeetingNoteOpener(),
|
||||
new InMemoryMeetingArtifactStore(),
|
||||
new InMemoryRecordedAudioStore(),
|
||||
new CapturingMeetingSummaryPipeline(),
|
||||
Options.Create(CreateOptionsWithoutFinalizer()),
|
||||
NullLogger<MeetingRecordingCoordinator>.Instance,
|
||||
speakerIdentificationService: new FixedSpeakerIdentificationService("Guest03", "Chris"),
|
||||
meetingWorkflowEngine: workflowEngine);
|
||||
|
||||
await coordinator.StartAsync(CancellationToken.None);
|
||||
await audioSource.WaitUntilCapturedAsync();
|
||||
await coordinator.StopAsync(CancellationToken.None);
|
||||
|
||||
Assert.Contains(workflowEngine.Events, e => e.Type == MeetingWorkflowEventType.Created);
|
||||
Assert.Contains(workflowEngine.Events, e =>
|
||||
e.Type == MeetingWorkflowEventType.StateTransition &&
|
||||
e.FromState == AssistantContextState.CollectingMetadata &&
|
||||
e.ToState == AssistantContextState.Transcribing);
|
||||
Assert.Contains(workflowEngine.Events, e =>
|
||||
e.Type == MeetingWorkflowEventType.SpeakerIdentified &&
|
||||
e.SpeakerName == "Chris");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VaultTranscriptStoreCreatesConfiguredFolderAndAppendsSegments()
|
||||
{
|
||||
@@ -1309,6 +1382,20 @@ public sealed class RecordingCoordinatorTests
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class CapturingMeetingWorkflowEngine : IMeetingWorkflowEngine
|
||||
{
|
||||
public List<MeetingWorkflowEvent> Events { get; } = [];
|
||||
|
||||
public Task RunAsync(
|
||||
MeetingWorkflowEvent workflowEvent,
|
||||
MeetingAssistantOptions options,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Events.Add(workflowEvent);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class InMemoryMeetingArtifactStore : IMeetingArtifactStore
|
||||
{
|
||||
public MeetingSessionArtifacts? CreatedArtifacts { get; private set; }
|
||||
|
||||
Reference in New Issue
Block a user