| File: Model\Assistant\ChatViewModel.cs | Web Access |
| Project: src\src\Aspire.Dashboard\Aspire.Dashboard.csproj (Aspire.Dashboard) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Web; using Aspire.Dashboard.Model.Markdown; using Microsoft.Extensions.AI; namespace Aspire.Dashboard.Model.Assistant; public sealed class ChatViewModel { private static long s_nextId; public ChatViewModel(bool isUserMessage) { Id = Interlocked.Increment(ref s_nextId); ElementId = $"chat-message-{Id}"; IsUserMessage = isUserMessage; } private string? _markdown; public long Id { get; } public string ElementId { get; } public bool IsUserMessage { get; } public bool IsComplete { get; set; } public bool IsLiked { get; set; } public bool IsDisliked { get; set; } public string PromptText { get; set; } = string.Empty; public string Html { get; set; } = string.Empty; public string? ErrorMessage { get; set; } public bool IsForbidden { get; set; } public DateTime? LimitResetDate { get; set; } private readonly List<ChatMessageViewModelBase> _chatMessages = new(); public int ChatMessageCount => _chatMessages.Count; public IEnumerable<ChatMessage> GetChatMessages() { foreach (var chatMessageViewModel in _chatMessages) { yield return chatMessageViewModel.GetChatMessage(); } } public void AddChatMessage(ChatMessage chatMessage) { _chatMessages.Add(new StaticChatMessageViewModel(chatMessage)); } public void AddChatMessage(Func<ChatMessage> chatMessageProvider) { _chatMessages.Add(new DynamicChatMessageViewModel(chatMessageProvider)); } public void AppendMarkdown(string markdown, MarkdownProcessor markdownProcessor, bool inCompleteDocument = false, bool suppressSurroundingParagraph = false) { _markdown += markdown; Html = markdownProcessor.ToHtml(_markdown, inCompleteDocument: inCompleteDocument, suppressSurroundingParagraph: suppressSurroundingParagraph); } public void SetText(string text) { _markdown = null; // Prevent user injecting HTML into the page. var newText = HttpUtility.HtmlEncode(text); // New lines in message should be preserved in displayed text. newText = newText.Replace("\r\n", "<br />", StringComparison.Ordinal) .Replace("\r", "<br />", StringComparison.Ordinal) .Replace("\n", "<br />", StringComparison.Ordinal); Html = newText; } public void ClearMarkdown() { _markdown = null; Html = string.Empty; } private abstract class ChatMessageViewModelBase { public abstract ChatMessage GetChatMessage(); } private sealed class DynamicChatMessageViewModel : ChatMessageViewModelBase { private readonly Func<ChatMessage> _chatMessageProvider; public DynamicChatMessageViewModel(Func<ChatMessage> chatMessageProvider) { _chatMessageProvider = chatMessageProvider; } public override ChatMessage GetChatMessage() { return _chatMessageProvider(); } } private sealed class StaticChatMessageViewModel : ChatMessageViewModelBase { private readonly ChatMessage _chatMessage; public StaticChatMessageViewModel(ChatMessage chatMessage) { _chatMessage = chatMessage; } public override ChatMessage GetChatMessage() { return _chatMessage; } } }