Public Access
Make meeting lifecycle stateful
This commit is contained in:
@@ -17,6 +17,7 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
|
||||
public async Task CreateAssistantContextAsync(
|
||||
MeetingSessionArtifacts artifacts,
|
||||
MeetingNote meetingNote,
|
||||
string agenda,
|
||||
DateTimeOffset? scheduledEnd,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -25,7 +26,8 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
|
||||
var content = Render(
|
||||
artifacts,
|
||||
AssistantContextState.Transcribing,
|
||||
meetingNote,
|
||||
AssistantContextState.CollectingMetadata,
|
||||
agenda,
|
||||
scheduledEnd,
|
||||
"# Assistant Context" + Environment.NewLine + Environment.NewLine + "## Live Context" + Environment.NewLine);
|
||||
@@ -45,12 +47,13 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
: new MarkdownDocument(false, "", "## Live Context" + Environment.NewLine);
|
||||
var body = existing.Body;
|
||||
var existingFrontmatter = ReadFrontmatter(existing.Frontmatter);
|
||||
var metadata = existingFrontmatter.ToMeetingArtifactMetadata();
|
||||
var agenda = existingFrontmatter.Agenda ?? "";
|
||||
var scheduledEnd = ParseDateTime(existingFrontmatter.ScheduledEnd);
|
||||
|
||||
await File.WriteAllTextAsync(
|
||||
artifacts.AssistantContextPath,
|
||||
Render(artifacts, state, agenda, scheduledEnd, body),
|
||||
Render(artifacts, metadata, state, agenda, scheduledEnd, body),
|
||||
cancellationToken);
|
||||
logger.LogInformation(
|
||||
"Updated assistant context note {AssistantContextPath} state to {State}",
|
||||
@@ -60,6 +63,7 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
|
||||
public async Task UpdateAssistantContextMetadataAsync(
|
||||
MeetingSessionArtifacts artifacts,
|
||||
MeetingNote meetingNote,
|
||||
string agenda,
|
||||
DateTimeOffset? scheduledEnd,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -73,29 +77,68 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
|
||||
await File.WriteAllTextAsync(
|
||||
artifacts.AssistantContextPath,
|
||||
Render(artifacts, state, agenda, scheduledEnd, existing.Body),
|
||||
Render(artifacts, meetingNote, state, agenda, scheduledEnd, existing.Body),
|
||||
cancellationToken);
|
||||
logger.LogInformation(
|
||||
"Updated assistant context note {AssistantContextPath} calendar metadata",
|
||||
artifacts.AssistantContextPath);
|
||||
}
|
||||
|
||||
public async Task UpdateAssistantContextMeetingAsync(
|
||||
MeetingSessionArtifacts artifacts,
|
||||
MeetingNote meetingNote,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.AssistantContextPath)!);
|
||||
var existing = File.Exists(artifacts.AssistantContextPath)
|
||||
? MarkdownDocumentParser.SplitOptional(await File.ReadAllTextAsync(artifacts.AssistantContextPath, cancellationToken))
|
||||
: new MarkdownDocument(false, "", "## Live Context" + Environment.NewLine);
|
||||
var existingFrontmatter = ReadFrontmatter(existing.Frontmatter);
|
||||
var state = ParseState(existingFrontmatter.State);
|
||||
var agenda = existingFrontmatter.Agenda ?? "";
|
||||
var scheduledEnd = ParseDateTime(existingFrontmatter.ScheduledEnd);
|
||||
|
||||
await File.WriteAllTextAsync(
|
||||
artifacts.AssistantContextPath,
|
||||
Render(artifacts, meetingNote, state, agenda, scheduledEnd, existing.Body),
|
||||
cancellationToken);
|
||||
logger.LogInformation(
|
||||
"Updated assistant context note {AssistantContextPath} meeting metadata",
|
||||
artifacts.AssistantContextPath);
|
||||
}
|
||||
|
||||
private static string Render(
|
||||
MeetingSessionArtifacts artifacts,
|
||||
MeetingNote meetingNote,
|
||||
AssistantContextState state,
|
||||
string? agenda,
|
||||
DateTimeOffset? scheduledEnd,
|
||||
string body)
|
||||
{
|
||||
var frontmatter = new MeetingArtifactFrontmatter
|
||||
{
|
||||
Meeting = ObsidianLink.ToWikiLink(artifacts.MeetingNotePath, artifacts.AssistantContextPath, "Meeting Note"),
|
||||
Transcript = ObsidianLink.ToWikiLink(artifacts.TranscriptPath, artifacts.AssistantContextPath, "Transcript"),
|
||||
Summary = ObsidianLink.ToWikiLink(artifacts.SummaryPath, artifacts.AssistantContextPath, "Summary"),
|
||||
State = ToYamlState(state),
|
||||
Agenda = agenda ?? "",
|
||||
ScheduledEnd = scheduledEnd
|
||||
};
|
||||
var metadata = new AssistantContextMeetingMetadata(
|
||||
meetingNote.Frontmatter.Title,
|
||||
meetingNote.Frontmatter.StartTime,
|
||||
meetingNote.Frontmatter.EndTime);
|
||||
return Render(artifacts, metadata, state, agenda, scheduledEnd, body);
|
||||
}
|
||||
|
||||
private static string Render(
|
||||
MeetingSessionArtifacts artifacts,
|
||||
AssistantContextMeetingMetadata metadata,
|
||||
AssistantContextState state,
|
||||
string? agenda,
|
||||
DateTimeOffset? scheduledEnd,
|
||||
string body)
|
||||
{
|
||||
var frontmatter = MeetingArtifactFrontmatterRenderer.Create(
|
||||
artifacts,
|
||||
metadata.Title,
|
||||
metadata.StartTime,
|
||||
metadata.EndTime,
|
||||
artifacts.AssistantContextPath,
|
||||
ToYamlState(state));
|
||||
frontmatter.Agenda = agenda ?? "";
|
||||
frontmatter.ScheduledEnd = scheduledEnd;
|
||||
|
||||
return MeetingArtifactFrontmatterRenderer.Render(
|
||||
frontmatter,
|
||||
@@ -125,23 +168,46 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
[YamlMember(Alias = "state")]
|
||||
public string? State { get; set; }
|
||||
|
||||
[YamlMember(Alias = "title")]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[YamlMember(Alias = "start_time")]
|
||||
public string? StartTime { get; set; }
|
||||
|
||||
[YamlMember(Alias = "end_time")]
|
||||
public string? EndTime { get; set; }
|
||||
|
||||
[YamlMember(Alias = "agenda")]
|
||||
public string? Agenda { get; set; }
|
||||
|
||||
[YamlMember(Alias = "scheduled_end")]
|
||||
public string? ScheduledEnd { get; set; }
|
||||
|
||||
public AssistantContextMeetingMetadata ToMeetingArtifactMetadata()
|
||||
{
|
||||
return new AssistantContextMeetingMetadata(
|
||||
Title ?? "",
|
||||
ParseDateTime(StartTime),
|
||||
ParseDateTime(EndTime));
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record AssistantContextMeetingMetadata(
|
||||
string Title,
|
||||
DateTimeOffset? StartTime,
|
||||
DateTimeOffset? EndTime);
|
||||
|
||||
private static AssistantContextState ParseState(string? value)
|
||||
{
|
||||
return value?.Trim().ToLowerInvariant() switch
|
||||
{
|
||||
"transcribing" => AssistantContextState.Transcribing,
|
||||
"collecting metadata" => AssistantContextState.CollectingMetadata,
|
||||
"speaker recognition" => AssistantContextState.SpeakerRecognition,
|
||||
"summarizing" => AssistantContextState.Summarizing,
|
||||
"finished" => AssistantContextState.Finished,
|
||||
"error" => AssistantContextState.Error,
|
||||
_ => AssistantContextState.Transcribing
|
||||
_ => AssistantContextState.CollectingMetadata
|
||||
};
|
||||
}
|
||||
|
||||
@@ -149,6 +215,7 @@ public sealed class MarkdownMeetingArtifactStore : IMeetingArtifactStore
|
||||
{
|
||||
return state switch
|
||||
{
|
||||
AssistantContextState.CollectingMetadata => "collecting metadata",
|
||||
AssistantContextState.Transcribing => "transcribing",
|
||||
AssistantContextState.SpeakerRecognition => "speaker recognition",
|
||||
AssistantContextState.Summarizing => "summarizing",
|
||||
|
||||
Reference in New Issue
Block a user