using System.Collections.ObjectModel; namespace MeetingAssistant.Workflow; public sealed class WorkflowRulesEditorChatViewModel { private readonly IWorkflowRulesEditorChatPipeline pipeline; public WorkflowRulesEditorChatViewModel(IWorkflowRulesEditorChatPipeline pipeline) { this.pipeline = pipeline; } public ObservableCollection Messages { get; } = []; public string Draft { get; set; } = ""; public bool IsThinking { get; private set; } public string ActivityMessage { get; private set; } = "Thinking..."; public event EventHandler? Changed; public async Task SendAsync(CancellationToken cancellationToken = default) { var prompt = Draft.Trim(); if (string.IsNullOrWhiteSpace(prompt) || IsThinking) { return; } Draft = ""; var priorConversation = Messages.ToList(); Messages.Add(new WorkflowRulesEditorChatMessage(WorkflowRulesEditorChatRole.User, prompt)); IsThinking = true; ActivityMessage = "Thinking..."; OnChanged(); try { var result = await pipeline.SendAsync( priorConversation, prompt, cancellationToken, SetActivityMessage); Messages.Clear(); foreach (var message in result.Conversation) { Messages.Add(message); } } catch (Exception exception) when (exception is not OperationCanceledException || !cancellationToken.IsCancellationRequested) { Messages.Add(new WorkflowRulesEditorChatMessage( WorkflowRulesEditorChatRole.Agent, $"Settings and logs failed: {exception.Message}")); } finally { IsThinking = false; ActivityMessage = "Thinking..."; OnChanged(); } } private void SetActivityMessage(string message) { if (!IsThinking || string.IsNullOrWhiteSpace(message)) { return; } ActivityMessage = message; OnChanged(); } private void OnChanged() { Changed?.Invoke(this, EventArgs.Empty); } }