Public Access
Add transcript line workflow rules
PR and Push Build/Test / build-and-test (push) Failing after 13m27s
PR and Push Build/Test / build-and-test (push) Failing after 13m27s
This commit is contained in:
@@ -61,6 +61,25 @@ public sealed class RecordingCoordinatorTests
|
||||
}
|
||||
}
|
||||
|
||||
private static TranscriptionSegment ParseTranscriptLine(string line)
|
||||
{
|
||||
var bracket = line.IndexOf(']');
|
||||
var rest = bracket >= 0 && bracket + 1 < line.Length
|
||||
? line[(bracket + 1)..].TrimStart()
|
||||
: line;
|
||||
var separator = rest.IndexOf(": ", StringComparison.Ordinal);
|
||||
if (separator < 0)
|
||||
{
|
||||
return new TranscriptionSegment(TimeSpan.Zero, TimeSpan.Zero, "Unknown", rest);
|
||||
}
|
||||
|
||||
return new TranscriptionSegment(
|
||||
TimeSpan.Zero,
|
||||
TimeSpan.Zero,
|
||||
rest[..separator],
|
||||
rest[(separator + 2)..]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToggleStartsStreamingTranscriptionAndSecondToggleStopsIt()
|
||||
{
|
||||
@@ -97,6 +116,70 @@ public sealed class RecordingCoordinatorTests
|
||||
Assert.False(stopped.IsRecording);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TranscriptLineWorkflowRuleTransformsLiveTranscriptBeforePersistingMarkdown()
|
||||
{
|
||||
var root = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
|
||||
var rulesPath = Path.Combine(root, "rules.yaml");
|
||||
Directory.CreateDirectory(root);
|
||||
await File.WriteAllTextAsync(rulesPath, MeetingWorkflowTestRules.MaskedProfanityRedactionYaml);
|
||||
var options = new MeetingAssistantOptions
|
||||
{
|
||||
Vault =
|
||||
{
|
||||
BaseFolder = root,
|
||||
MeetingNotesFolder = "Notes",
|
||||
TranscriptsFolder = "Transcripts",
|
||||
AssistantContextFolder = "Context",
|
||||
SummariesFolder = "Summaries"
|
||||
},
|
||||
Automation =
|
||||
{
|
||||
RulesPath = rulesPath
|
||||
}
|
||||
};
|
||||
var audioSource = new ControlledAudioSource();
|
||||
var noteStore = new MarkdownMeetingNoteStore(
|
||||
Options.Create(options),
|
||||
NullLogger<MarkdownMeetingNoteStore>.Instance);
|
||||
var artifactStore = new MarkdownMeetingArtifactStore(
|
||||
NullLogger<MarkdownMeetingArtifactStore>.Instance);
|
||||
var coordinator = new MeetingRecordingCoordinator(
|
||||
audioSource,
|
||||
new TestSpeechRecognitionPipelineFactory(
|
||||
new FixedSegmentStreamingTranscriptionProvider(
|
||||
new TranscriptionSegment(
|
||||
TimeSpan.FromSeconds(4),
|
||||
TimeSpan.FromSeconds(5),
|
||||
"Guest-1",
|
||||
"Azure returned ***** here."))),
|
||||
new VaultTranscriptStore(
|
||||
Options.Create(options),
|
||||
NullLogger<VaultTranscriptStore>.Instance),
|
||||
noteStore,
|
||||
new CapturingMeetingNoteOpener(),
|
||||
artifactStore,
|
||||
new InMemoryRecordedAudioStore(),
|
||||
new CapturingMeetingSummaryPipeline(),
|
||||
Options.Create(options),
|
||||
NullLogger<MeetingRecordingCoordinator>.Instance,
|
||||
meetingWorkflowEngine: new MeetingWorkflowEngine(
|
||||
new FileMeetingWorkflowRulesProvider(
|
||||
NullLogger<FileMeetingWorkflowRulesProvider>.Instance),
|
||||
noteStore,
|
||||
artifactStore,
|
||||
NullLogger<MeetingWorkflowEngine>.Instance));
|
||||
|
||||
var started = await coordinator.StartAsync(CancellationToken.None);
|
||||
await audioSource.WriteAsync(new AudioChunk([1, 0], 16000, 1), CancellationToken.None);
|
||||
await WaitUntilAsync(() => FileContainsText(started.TranscriptPath!, "[redacted]"));
|
||||
await coordinator.StopAsync(CancellationToken.None);
|
||||
|
||||
var content = await File.ReadAllTextAsync(started.TranscriptPath!);
|
||||
Assert.Contains("[00:00:04] Guest-1: Azure returned [redacted] here.", content);
|
||||
Assert.DoesNotContain("*****", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartCreatesMeetingNoteLinkedToTranscriptAndOpensIt()
|
||||
{
|
||||
@@ -1897,7 +1980,7 @@ public sealed class RecordingCoordinatorTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VaultTranscriptStoreCreatesConfiguredFolderAndAppendsSegments()
|
||||
public async Task VaultTranscriptStoreCreatesConfiguredFolderAndAppendsLines()
|
||||
{
|
||||
var vaultFolder = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
|
||||
var store = new VaultTranscriptStore(
|
||||
@@ -1908,10 +1991,7 @@ public sealed class RecordingCoordinatorTests
|
||||
NullLogger<VaultTranscriptStore>.Instance);
|
||||
|
||||
var session = await store.CreateSessionAsync(CancellationToken.None);
|
||||
await store.AppendAsync(
|
||||
session,
|
||||
new TranscriptionSegment(TimeSpan.Zero, TimeSpan.FromSeconds(1), "Unknown", "hello vault"),
|
||||
CancellationToken.None);
|
||||
await store.AppendLineAsync(session, "[00:00:00] Unknown: hello vault", CancellationToken.None);
|
||||
|
||||
Assert.True(Directory.Exists(vaultFolder));
|
||||
Assert.EndsWith(".md", session.TranscriptPath, StringComparison.Ordinal);
|
||||
@@ -2079,9 +2159,9 @@ public sealed class RecordingCoordinatorTests
|
||||
return Task.FromResult(new TranscriptSession(transcriptPath));
|
||||
}
|
||||
|
||||
public Task AppendAsync(TranscriptSession session, TranscriptionSegment segment, CancellationToken cancellationToken)
|
||||
public Task AppendLineAsync(TranscriptSession session, string line, CancellationToken cancellationToken)
|
||||
{
|
||||
segments.Add(segment);
|
||||
segments.Add(ParseTranscriptLine(line));
|
||||
segmentWritten.TrySetResult();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -2108,12 +2188,12 @@ public sealed class RecordingCoordinatorTests
|
||||
|
||||
public MeetingNote? MetadataMeetingNote { get; private set; }
|
||||
|
||||
public Task ReplaceAsync(
|
||||
public Task ReplaceLinesAsync(
|
||||
TranscriptSession session,
|
||||
IReadOnlyList<TranscriptionSegment> replacementSegments,
|
||||
IReadOnlyList<string> replacementLines,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ReplacedSegments = replacementSegments;
|
||||
ReplacedSegments = replacementLines.Select(ParseTranscriptLine).ToList();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -2146,9 +2226,9 @@ public sealed class RecordingCoordinatorTests
|
||||
return Task.FromResult(new TranscriptSession($"memory-transcript-{index}.md"));
|
||||
}
|
||||
|
||||
public Task AppendAsync(TranscriptSession session, TranscriptionSegment segment, CancellationToken cancellationToken)
|
||||
public Task AppendLineAsync(TranscriptSession session, string line, CancellationToken cancellationToken)
|
||||
{
|
||||
AppendHistory.Add(new TranscriptWrite(session, segment));
|
||||
AppendHistory.Add(new TranscriptWrite(session, ParseTranscriptLine(line)));
|
||||
Interlocked.Increment(ref appendCount);
|
||||
appendObserved.TrySetResult();
|
||||
return Task.CompletedTask;
|
||||
@@ -2175,12 +2255,14 @@ public sealed class RecordingCoordinatorTests
|
||||
throw new TimeoutException($"Expected {expectedCount} transcript append(s).");
|
||||
}
|
||||
|
||||
public Task ReplaceAsync(
|
||||
public Task ReplaceLinesAsync(
|
||||
TranscriptSession session,
|
||||
IReadOnlyList<TranscriptionSegment> replacementSegments,
|
||||
IReadOnlyList<string> replacementLines,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
ReplacementHistory.Add(new TranscriptReplacement(session, replacementSegments));
|
||||
ReplacementHistory.Add(new TranscriptReplacement(
|
||||
session,
|
||||
replacementLines.Select(ParseTranscriptLine).ToList()));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -2288,6 +2370,15 @@ public sealed class RecordingCoordinatorTests
|
||||
Events.Add(workflowEvent);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<string> TransformTranscriptLineAsync(
|
||||
MeetingWorkflowEvent workflowEvent,
|
||||
MeetingAssistantOptions options,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Events.Add(workflowEvent);
|
||||
return Task.FromResult(workflowEvent.TranscriptLineText ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class CapturingMeetingScreenshotService : IMeetingScreenshotService
|
||||
@@ -2802,14 +2893,14 @@ public sealed class RecordingCoordinatorTests
|
||||
return Task.FromResult(new TranscriptSession(Path.Combine(folder, "transcript.md")));
|
||||
}
|
||||
|
||||
public Task AppendAsync(TranscriptSession session, TranscriptionSegment segment, CancellationToken cancellationToken)
|
||||
public Task AppendLineAsync(TranscriptSession session, string line, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task ReplaceAsync(
|
||||
public Task ReplaceLinesAsync(
|
||||
TranscriptSession session,
|
||||
IReadOnlyList<TranscriptionSegment> replacementSegments,
|
||||
IReadOnlyList<string> replacementLines,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
|
||||
Reference in New Issue
Block a user