Files
meeting-assistant/MeetingAssistant.Tests/MeetingSummaryToolTests.cs
T
2026-05-27 12:55:17 +02:00

208 lines
9.9 KiB
C#

using MeetingAssistant.MeetingNotes;
using MeetingAssistant.Summary;
using MeetingAssistant.Transcription;
using Microsoft.Extensions.Options;
namespace MeetingAssistant.Tests;
public sealed class MeetingSummaryToolTests
{
[Fact]
public async Task ToolsReadMeetingInputsAndWriteSummaryNote()
{
var root = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
var artifacts = new MeetingSessionArtifacts(
MeetingNotePath: Path.Combine(root, "Meetings", "Notes", "meeting.md"),
TranscriptPath: Path.Combine(root, "Meetings", "Transcripts", "transcript.md"),
AssistantContextPath: Path.Combine(root, "Meetings", "Assistant Context", "context.md"),
SummaryPath: Path.Combine(root, "Meetings", "Summaries", "summary.md"));
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.MeetingNotePath)!);
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.TranscriptPath)!);
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.AssistantContextPath)!);
await File.WriteAllTextAsync(
artifacts.MeetingNotePath,
"""
---
title: Meeting
start_time: "2026-05-20T10:00:00.0000000+02:00"
end_time: "2026-05-20T10:30:00.0000000+02:00"
attendees:
- Ada
projects:
- Meeting Assistant
transcript: "[[../Transcripts/transcript|Transcript]]"
assistant_context: "[[../Assistant Context/context|Assistant Context]]"
summary: "[[../Summaries/summary|Summary]]"
---
User note line.
""");
await File.WriteAllTextAsync(artifacts.TranscriptPath, "Ada: Transcript line.");
await File.WriteAllTextAsync(artifacts.AssistantContextPath, "Context line.");
var tools = new MeetingSummaryTools(artifacts);
Assert.Equal("Ada: Transcript line.", await tools.ReadTranscript());
Assert.Contains("title: Meeting", await tools.ReadMeetingNote());
Assert.Equal("Context line.", await tools.ReadContext());
Assert.Equal("User note line.", await tools.ReadUserNotes());
Assert.Equal("", await tools.ReadGlossary());
var result = await tools.WriteSummary("# Summary\n\n- Done.");
Assert.Equal(artifacts.SummaryPath, result);
var summary = await File.ReadAllTextAsync(artifacts.SummaryPath);
Assert.Contains("title: Meeting", summary);
Assert.Contains("start_time: \"2026-05-20T10:00:00.0000000+02:00\"", summary);
Assert.Contains("end_time: \"2026-05-20T10:30:00.0000000+02:00\"", summary);
Assert.Contains("meeting: \"[[../Notes/meeting|Meeting Note]]\"", summary);
Assert.Contains("transcript: \"[[../Transcripts/transcript|Transcript]]\"", summary);
Assert.Contains("assistant_context: \"[[../Assistant Context/context|Assistant Context]]\"", summary);
Assert.DoesNotContain("summary:", summary);
Assert.Contains("# Summary\n\n- Done.", summary);
}
[Fact]
public async Task ReadToolsSupportClampedLineRanges()
{
var root = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
var artifacts = new MeetingSessionArtifacts(
MeetingNotePath: Path.Combine(root, "Meetings", "Notes", "meeting.md"),
TranscriptPath: Path.Combine(root, "Meetings", "Transcripts", "transcript.md"),
AssistantContextPath: Path.Combine(root, "Meetings", "Assistant Context", "context.md"),
SummaryPath: Path.Combine(root, "Meetings", "Summaries", "summary.md"));
var glossaryPath = Path.Combine(root, "Meetings", "dictation-words.md");
var projectRoot = Path.Combine(root, "Projects", "Project A");
var projectFile = Path.Combine(projectRoot, "notes.md");
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.MeetingNotePath)!);
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.TranscriptPath)!);
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.AssistantContextPath)!);
Directory.CreateDirectory(Path.GetDirectoryName(glossaryPath)!);
Directory.CreateDirectory(projectRoot);
await File.WriteAllTextAsync(
artifacts.MeetingNotePath,
"""
---
projects:
- Project A
---
note one
note two
note three
""");
await File.WriteAllTextAsync(artifacts.TranscriptPath, "transcript one\ntranscript two\ntranscript three");
await File.WriteAllTextAsync(artifacts.AssistantContextPath, "context one\ncontext two\ncontext three");
await File.WriteAllTextAsync(glossaryPath, "word one\nword two\nword three");
await File.WriteAllTextAsync(projectFile, "project one\nproject two\nproject three");
var tools = new MeetingSummaryTools(
artifacts,
new MeetingAssistantOptions
{
Vault =
{
DictationWordsPath = glossaryPath,
ProjectsFolder = Path.Combine(root, "Projects")
}
});
Assert.Equal("transcript two", await tools.ReadTranscript(from: 2, to: 2));
Assert.Equal("context two\ncontext three", await tools.ReadContext(from: 2, to: 9));
Assert.Equal("note two\nnote three", await tools.ReadUserNotes(from: 2, to: 99));
Assert.Equal("word two", await tools.ReadGlossary(from: 2, to: 2));
Assert.Equal("project two", await tools.ReadProjectFile("Project A", "notes.md", from: 2, to: 2));
Assert.Equal("", await tools.ReadTranscript(from: 3, to: 2));
}
[Fact]
public async Task ToolsWriteAssistantContextBodyWithLineModes()
{
var root = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
var artifacts = new MeetingSessionArtifacts(
MeetingNotePath: Path.Combine(root, "Meetings", "Notes", "meeting.md"),
TranscriptPath: Path.Combine(root, "Meetings", "Transcripts", "transcript.md"),
AssistantContextPath: Path.Combine(root, "Meetings", "Assistant Context", "context.md"),
SummaryPath: Path.Combine(root, "Meetings", "Summaries", "summary.md"));
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.AssistantContextPath)!);
await File.WriteAllTextAsync(
artifacts.AssistantContextPath,
"""
---
meeting: "[[../Notes/meeting|Meeting Note]]"
transcript: "[[../Transcripts/transcript|Transcript]]"
summary: "[[../Summaries/summary|Summary]]"
state: summarizing
---
line one
line two
""");
var tools = new MeetingSummaryTools(artifacts);
await tools.WriteContext("inserted", insert: 2);
await tools.WriteContext("replacement", from: 1, to: 1);
var context = await File.ReadAllTextAsync(artifacts.AssistantContextPath);
Assert.Contains("state: summarizing", context);
Assert.Contains("replacement\ninserted\nline two", context);
}
[Fact]
public async Task ExternalAgentWritesAreAppendedToAssistantContextAsDiffs()
{
var root = Path.Combine(Path.GetTempPath(), "meeting-assistant-tests", Guid.NewGuid().ToString("N"));
var projectsRoot = Path.Combine(root, "Projects");
var projectRoot = Path.Combine(projectsRoot, "MeetingAssistant");
var projectFile = Path.Combine(projectRoot, "notes.md");
var dictionaryPath = Path.Combine(root, "Meetings", "Dictionary.md");
var artifacts = new MeetingSessionArtifacts(
MeetingNotePath: Path.Combine(root, "Meetings", "Notes", "meeting.md"),
TranscriptPath: Path.Combine(root, "Meetings", "Transcripts", "transcript.md"),
AssistantContextPath: Path.Combine(root, "Meetings", "Assistant Context", "context.md"),
SummaryPath: Path.Combine(root, "Meetings", "Summaries", "summary.md"));
Directory.CreateDirectory(projectRoot);
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.MeetingNotePath)!);
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.AssistantContextPath)!);
await File.WriteAllTextAsync(projectFile, "one\ntwo\nthree");
await File.WriteAllTextAsync(
artifacts.MeetingNotePath,
"""
---
title: Meeting
projects:
- MeetingAssistant
---
""");
await File.WriteAllTextAsync(artifacts.AssistantContextPath, "Context before.");
var options = new MeetingAssistantOptions
{
Vault =
{
DictationWordsPath = dictionaryPath,
ProjectsFolder = projectsRoot
}
};
var audit = new SummaryAgentWriteAudit(artifacts);
var tools = new MeetingSummaryTools(
artifacts,
options,
new MarkdownDictationWordStore(Options.Create(options)),
audit);
await tools.WriteContext("owned context");
await tools.WriteSummary("owned summary");
await tools.WriteProjectFile("MeetingAssistant", "notes.md", "TWO", from: 2, to: 2);
await tools.AddDictationWord("PBI");
await audit.AppendToAssistantContextAsync(CancellationToken.None);
var context = await File.ReadAllTextAsync(artifacts.AssistantContextPath);
Assert.Contains("## Summary Agent External File Changes", context);
Assert.Contains(projectFile, context);
Assert.Contains("- two", context);
Assert.Contains("+ TWO", context);
Assert.Contains(dictionaryPath, context);
Assert.Contains("+ - PBI", context);
Assert.DoesNotContain("owned summary", context);
Assert.DoesNotContain("- Context before.", context);
}
}