Add taskbar controls and summary oneliner

This commit is contained in:
2026-05-27 23:31:40 +02:00
parent 7777b349a5
commit 71f1e6a0b8
22 changed files with 720 additions and 9 deletions
@@ -10,7 +10,8 @@ public sealed class MeetingSummaryInstructionBuilder : IMeetingSummaryInstructio
Use the provided tools to read the meeting transcript, assistant context, user notes, glossary, and project files.
All read tools can return the whole file or a clamped inclusive line range when from and to are supplied; use ranges for large inputs before asking for more lines.
Then write the finished meeting summary as markdown by calling write_summary. If the meeting note has no title, provide a concise title parameter to write_summary.
Then write the finished meeting summary as markdown by calling write_summary. The write_summary call requires an oneliner parameter: keep it very short, blurb-like, and concise. No line breaks. Complete sentences are not necessary; conciseness is more important.
If the meeting note has no title, provide a concise title parameter to write_summary.
Use read_meetingnote to inspect frontmatter such as title, attendees, projects, start_time, and end_time.
Use read_context and write_context as your own meeting notebook. Its frontmatter may include agenda from the calendar appointment. Record useful internal notes, missing context, requests for future tools, suggested improvements, and relevant context discovered from other sources. Keep user-facing summary content in the summary note.
Use add_dictation_word when project context, user notes, or transcript evidence show that a domain term, acronym, name, or unusual word is likely to be repeatedly mistranscribed. Add only the canonical spelling, one term at a time.
@@ -206,8 +206,19 @@ public sealed class MeetingSummaryTools
return $"Deleted identity {deletion.Identity} and relabeled transcript speaker mentions to {deletion.Replacement}.";
}
public async Task<string> WriteSummary(string markdown, string? title = null)
public async Task<string> WriteSummary(string markdown, string oneliner, string? title = null)
{
if (string.IsNullOrWhiteSpace(oneliner))
{
return "Refused: oneliner must not be empty.";
}
var trimmedOneLiner = oneliner.Trim();
if (ContainsLineBreak(trimmedOneLiner))
{
return "Refused: oneliner must be a single line.";
}
Directory.CreateDirectory(Path.GetDirectoryName(artifacts.SummaryPath)!);
var meetingNote = await ReadMeetingNoteAsync();
var summaryTitle = string.IsNullOrWhiteSpace(meetingNote.Frontmatter.Title)
@@ -218,6 +229,7 @@ public sealed class MeetingSummaryTools
meetingNote,
string.IsNullOrWhiteSpace(summaryTitle) ? "Meeting Summary" : summaryTitle,
CancellationToken.None);
frontmatter.OneLiner = trimmedOneLiner;
await File.WriteAllTextAsync(
artifacts.SummaryPath,
MeetingArtifactFrontmatterRenderer.Render(frontmatter, markdown));
@@ -225,6 +237,12 @@ public sealed class MeetingSummaryTools
return artifacts.SummaryPath;
}
private static bool ContainsLineBreak(string value)
{
return value.Contains('\n', StringComparison.Ordinal) ||
value.Contains('\r', StringComparison.Ordinal);
}
public bool SummaryWasWritten { get; private set; }
public async Task<string> WriteContext(