Files
codex c12febe029
PR and Push Build/Test / build-and-test (push) Successful in 9m47s
Centralize summary frontmatter metadata
2026-05-27 12:55:20 +02:00

105 lines
3.9 KiB
C#

using System.Text;
using MeetingAssistant.MeetingNotes;
using Microsoft.Extensions.Options;
namespace MeetingAssistant.Summary;
public interface IMeetingSummaryFailureWriter
{
Task<MeetingSummaryRunResult> WriteAsync(
MeetingSessionArtifacts artifacts,
Exception exception,
CancellationToken cancellationToken);
Task<MeetingSummaryRunResult> WriteAsync(
MeetingSessionArtifacts artifacts,
Exception exception,
MeetingAssistantOptions options,
CancellationToken cancellationToken)
{
return WriteAsync(artifacts, exception, cancellationToken);
}
}
public sealed class MeetingSummaryFailureWriter : IMeetingSummaryFailureWriter
{
private readonly MeetingAssistantOptions options;
private readonly IMeetingNoteStore meetingNoteStore;
public MeetingSummaryFailureWriter(
IOptions<MeetingAssistantOptions> options,
IMeetingNoteStore meetingNoteStore)
{
this.options = options.Value;
this.meetingNoteStore = meetingNoteStore;
}
public async Task<MeetingSummaryRunResult> WriteAsync(
MeetingSessionArtifacts artifacts,
Exception exception,
CancellationToken cancellationToken)
{
return await WriteAsync(artifacts, exception, options, cancellationToken);
}
public async Task<MeetingSummaryRunResult> WriteAsync(
MeetingSessionArtifacts artifacts,
Exception exception,
MeetingAssistantOptions options,
CancellationToken cancellationToken)
{
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.SummaryPath)!);
var meetingNote = File.Exists(artifacts.MeetingNotePath)
? await meetingNoteStore.ReadAsync(artifacts.MeetingNotePath, cancellationToken)
: new MeetingNote("", new MeetingNoteFrontmatter(), "");
var frontmatter = await MeetingSummaryFrontmatterFactory.CreateAsync(
artifacts,
meetingNote,
MeetingArtifactFrontmatterRenderer.DefaultTitle(meetingNote, "Meeting Summary"),
cancellationToken);
await File.WriteAllTextAsync(
artifacts.SummaryPath,
MeetingArtifactFrontmatterRenderer.Render(
frontmatter,
RenderFailureMarkdown(artifacts, exception, options)),
cancellationToken);
return new MeetingSummaryRunResult(
artifacts.SummaryPath,
"Summary generation failed. See the summary file for error details.",
Succeeded: false,
Error: exception.Message);
}
private static string RenderFailureMarkdown(
MeetingSessionArtifacts artifacts,
Exception exception,
MeetingAssistantOptions options)
{
var builder = new StringBuilder();
builder.AppendLine("# Meeting Summary");
builder.AppendLine();
builder.AppendLine("## Summary Generation Failed");
builder.AppendLine();
builder.AppendLine($"Summary generation failed at {DateTimeOffset.Now:O}.");
builder.AppendLine();
builder.AppendLine(MeetingNoteActionLinks.CreateSummaryRetryLink(
options.Api.PublicBaseUrl,
artifacts.SummaryPath));
builder.AppendLine();
builder.AppendLine("## Error");
builder.AppendLine();
builder.AppendLine("```text");
builder.AppendLine(exception.ToString().Replace("```", "` ` `", StringComparison.Ordinal));
builder.AppendLine("```");
builder.AppendLine();
builder.AppendLine("## Meeting Artifacts");
builder.AppendLine();
builder.AppendLine($"- Meeting note: `{artifacts.MeetingNotePath}`");
builder.AppendLine($"- Transcript: `{artifacts.TranscriptPath}`");
builder.AppendLine($"- Assistant context: `{artifacts.AssistantContextPath}`");
builder.AppendLine($"- Summary: `{artifacts.SummaryPath}`");
return builder.ToString();
}
}