Public Access
120 lines
3.6 KiB
C#
120 lines
3.6 KiB
C#
using DiffPlex.DiffBuilder;
|
|
using DiffPlex.DiffBuilder.Model;
|
|
using MeetingAssistant.MeetingNotes;
|
|
using System.Text;
|
|
|
|
namespace MeetingAssistant.Summary;
|
|
|
|
public sealed class SummaryAgentWriteAudit
|
|
{
|
|
private readonly MeetingSessionArtifacts artifacts;
|
|
private readonly List<FileChange> changes = [];
|
|
|
|
public SummaryAgentWriteAudit(MeetingSessionArtifacts artifacts)
|
|
{
|
|
this.artifacts = artifacts;
|
|
}
|
|
|
|
public async Task CaptureFileWriteAsync(
|
|
string path,
|
|
Func<Task> writeOperation,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var fullPath = Path.GetFullPath(path);
|
|
var before = File.Exists(fullPath)
|
|
? await File.ReadAllTextAsync(fullPath, cancellationToken)
|
|
: "";
|
|
await writeOperation();
|
|
var after = File.Exists(fullPath)
|
|
? await File.ReadAllTextAsync(fullPath, cancellationToken)
|
|
: "";
|
|
Capture(fullPath, before, after, cancellationToken);
|
|
}
|
|
|
|
public void Capture(
|
|
string path,
|
|
string before,
|
|
string after,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
var fullPath = Path.GetFullPath(path);
|
|
if (IsOwnedArtifact(fullPath) || string.Equals(before, after, StringComparison.Ordinal))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var diffLines = CreateDiffLines(before, after);
|
|
if (diffLines.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
changes.Add(new FileChange(fullPath, diffLines));
|
|
}
|
|
|
|
public async Task AppendToAssistantContextAsync(CancellationToken cancellationToken)
|
|
{
|
|
if (changes.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!File.Exists(artifacts.AssistantContextPath))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var existing = await File.ReadAllTextAsync(artifacts.AssistantContextPath, cancellationToken);
|
|
var builder = new StringBuilder();
|
|
if (!string.IsNullOrEmpty(existing) && !existing.EndsWith(Environment.NewLine, StringComparison.Ordinal))
|
|
{
|
|
builder.AppendLine();
|
|
}
|
|
|
|
builder.AppendLine();
|
|
builder.AppendLine("## Summary Agent External File Changes");
|
|
builder.AppendLine();
|
|
foreach (var change in changes)
|
|
{
|
|
builder.AppendLine($"### {change.Path}");
|
|
builder.AppendLine();
|
|
builder.AppendLine("```diff");
|
|
foreach (var line in change.DiffLines)
|
|
{
|
|
builder.AppendLine(line);
|
|
}
|
|
|
|
builder.AppendLine("```");
|
|
builder.AppendLine();
|
|
}
|
|
|
|
await File.AppendAllTextAsync(artifacts.AssistantContextPath, builder.ToString(), cancellationToken);
|
|
}
|
|
|
|
private bool IsOwnedArtifact(string fullPath)
|
|
{
|
|
return IsSamePath(fullPath, artifacts.SummaryPath) ||
|
|
IsSamePath(fullPath, artifacts.AssistantContextPath);
|
|
}
|
|
|
|
private static bool IsSamePath(string first, string second)
|
|
{
|
|
return string.Equals(
|
|
Path.GetFullPath(first),
|
|
Path.GetFullPath(second),
|
|
StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
private static List<string> CreateDiffLines(string before, string after)
|
|
{
|
|
var model = InlineDiffBuilder.Diff(before, after);
|
|
return model.Lines
|
|
.Where(line => line.Type is ChangeType.Deleted or ChangeType.Inserted)
|
|
.Select(line => $"{(line.Type == ChangeType.Inserted ? "+" : "-")} {line.Text}")
|
|
.ToList();
|
|
}
|
|
|
|
private sealed record FileChange(string Path, IReadOnlyList<string> DiffLines);
|
|
}
|