Public Access
Update meeting summary agent UI
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace MeetingAssistant.Workflow;
|
||||
|
||||
public sealed class WorkflowRulesEditorChatViewModel
|
||||
{
|
||||
private const string ThinkingPlaceholder = "Thinking...";
|
||||
private readonly IWorkflowRulesEditorChatPipeline pipeline;
|
||||
|
||||
public WorkflowRulesEditorChatViewModel(IWorkflowRulesEditorChatPipeline pipeline)
|
||||
@@ -11,13 +13,15 @@ public sealed class WorkflowRulesEditorChatViewModel
|
||||
this.pipeline = pipeline;
|
||||
}
|
||||
|
||||
public ObservableCollection<WorkflowRulesEditorChatMessage> Messages { get; } = [];
|
||||
public ObservableCollection<WorkflowRulesEditorConversationItem> Messages { get; } = [];
|
||||
|
||||
public ObservableCollection<string> ActivityMessages { get; } = [];
|
||||
|
||||
public string Draft { get; set; } = "";
|
||||
|
||||
public bool IsThinking { get; private set; }
|
||||
|
||||
public string ActivityMessage { get; private set; } = "Thinking...";
|
||||
public string ActivityMessage { get; private set; } = ThinkingPlaceholder;
|
||||
|
||||
public event EventHandler? Changed;
|
||||
|
||||
@@ -30,10 +34,19 @@ public sealed class WorkflowRulesEditorChatViewModel
|
||||
}
|
||||
|
||||
Draft = "";
|
||||
var priorConversation = Messages.ToList();
|
||||
Messages.Add(new WorkflowRulesEditorChatMessage(WorkflowRulesEditorChatRole.User, prompt));
|
||||
var startedAt = Stopwatch.GetTimestamp();
|
||||
var activityLines = new List<string>();
|
||||
var hasVisibleThinking = false;
|
||||
var activityContext = SynchronizationContext.Current;
|
||||
var priorConversation = Messages
|
||||
.Select(item => item.Message)
|
||||
.OfType<WorkflowRulesEditorChatMessage>()
|
||||
.ToList();
|
||||
Messages.Add(WorkflowRulesEditorConversationItem.ChatMessage(
|
||||
new WorkflowRulesEditorChatMessage(WorkflowRulesEditorChatRole.User, prompt)));
|
||||
ActivityMessages.Clear();
|
||||
IsThinking = true;
|
||||
ActivityMessage = "Thinking...";
|
||||
ActivityMessage = ThinkingPlaceholder;
|
||||
OnChanged();
|
||||
|
||||
try
|
||||
@@ -42,36 +55,121 @@ public sealed class WorkflowRulesEditorChatViewModel
|
||||
priorConversation,
|
||||
prompt,
|
||||
cancellationToken,
|
||||
SetActivityMessage);
|
||||
Messages.Clear();
|
||||
foreach (var message in result.Conversation)
|
||||
{
|
||||
Messages.Add(message);
|
||||
}
|
||||
update => hasVisibleThinking |= ApplyActivityUpdate(activityContext, update, activityLines));
|
||||
AddCompletedActivity(startedAt, activityLines, hasVisibleThinking);
|
||||
Messages.Add(WorkflowRulesEditorConversationItem.ChatMessage(
|
||||
new WorkflowRulesEditorChatMessage(
|
||||
WorkflowRulesEditorChatRole.Agent,
|
||||
string.IsNullOrWhiteSpace(result.Response)
|
||||
? "(No response text returned.)"
|
||||
: result.Response.Trim())));
|
||||
}
|
||||
catch (Exception exception) when (exception is not OperationCanceledException || !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
Messages.Add(new WorkflowRulesEditorChatMessage(
|
||||
WorkflowRulesEditorChatRole.Agent,
|
||||
$"Settings and logs failed: {exception.Message}"));
|
||||
AddCompletedActivity(startedAt, activityLines, hasVisibleThinking);
|
||||
Messages.Add(WorkflowRulesEditorConversationItem.ChatMessage(
|
||||
new WorkflowRulesEditorChatMessage(
|
||||
WorkflowRulesEditorChatRole.Agent,
|
||||
$"Meeting Summary Agent failed: {exception.Message}")));
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsThinking = false;
|
||||
ActivityMessage = "Thinking...";
|
||||
ActivityMessages.Clear();
|
||||
ActivityMessage = ThinkingPlaceholder;
|
||||
OnChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetActivityMessage(string message)
|
||||
private bool ApplyActivityUpdate(
|
||||
SynchronizationContext? context,
|
||||
WorkflowRulesEditorActivityUpdate update,
|
||||
List<string> activityLines)
|
||||
{
|
||||
if (!IsThinking || string.IsNullOrWhiteSpace(message))
|
||||
if (context is null || SynchronizationContext.Current == context)
|
||||
{
|
||||
return;
|
||||
return ApplyActivityUpdate(update, activityLines);
|
||||
}
|
||||
|
||||
var hasVisibleThinking = false;
|
||||
Exception? exception = null;
|
||||
context.Send(
|
||||
_ =>
|
||||
{
|
||||
try
|
||||
{
|
||||
hasVisibleThinking = ApplyActivityUpdate(update, activityLines);
|
||||
}
|
||||
catch (Exception caught)
|
||||
{
|
||||
exception = caught;
|
||||
}
|
||||
},
|
||||
null);
|
||||
|
||||
if (exception is not null)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return hasVisibleThinking;
|
||||
}
|
||||
|
||||
private bool ApplyActivityUpdate(
|
||||
WorkflowRulesEditorActivityUpdate update,
|
||||
List<string> activityLines)
|
||||
{
|
||||
if (!IsThinking || string.IsNullOrWhiteSpace(update.Text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var hasVisibleThinking = false;
|
||||
if (update.Kind == WorkflowRulesEditorActivityKind.ToolCall)
|
||||
{
|
||||
var line = $"Called tool: {update.Text.Trim()}";
|
||||
ActivityMessages.Add(line);
|
||||
activityLines.Add(line);
|
||||
}
|
||||
else if (update.Kind == WorkflowRulesEditorActivityKind.Thinking)
|
||||
{
|
||||
var line = update.Text.Trim();
|
||||
ActivityMessages.Add(line);
|
||||
activityLines.Add(line);
|
||||
hasVisibleThinking = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var line = update.Text.Trim();
|
||||
ActivityMessage = line;
|
||||
activityLines.Add(line);
|
||||
}
|
||||
|
||||
ActivityMessage = message;
|
||||
OnChanged();
|
||||
return hasVisibleThinking;
|
||||
}
|
||||
|
||||
private void AddCompletedActivity(
|
||||
long startedAt,
|
||||
IReadOnlyList<string> activityLines,
|
||||
bool hasVisibleThinking)
|
||||
{
|
||||
var completedActivityLines = hasVisibleThinking
|
||||
? activityLines.ToArray()
|
||||
: new[] { ThinkingPlaceholder }.Concat(activityLines).ToArray();
|
||||
Messages.Add(WorkflowRulesEditorConversationItem.Activity(
|
||||
$"Worked for {FormatDuration(Stopwatch.GetElapsedTime(startedAt))}",
|
||||
completedActivityLines));
|
||||
}
|
||||
|
||||
private static string FormatDuration(TimeSpan duration)
|
||||
{
|
||||
if (duration.TotalMinutes >= 1)
|
||||
{
|
||||
return $"{(int)duration.TotalMinutes}m {duration.Seconds}s";
|
||||
}
|
||||
|
||||
return $"{Math.Max(0, (int)Math.Round(duration.TotalSeconds))}s";
|
||||
}
|
||||
|
||||
private void OnChanged()
|
||||
|
||||
Reference in New Issue
Block a user