using System; using System.Collections.Generic; using System.Linq; using Microsoft.SemanticKernel.ChatCompletion; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; namespace AI.Models.Store { /// /// 会话存储序列化用的 DTO(YAML 根为 entries 列表) /// public class ConversationStoreDto { public List Entries { get; set; } = new(); } /// /// 单条存储条目的 DTO /// public class ConversationEntryDto { public string Kind { get; set; } = string.Empty; public string? Role { get; set; } public string? Content { get; set; } public string? Type { get; set; } public string? Payload { get; set; } } /// /// 会话级结构化存储,作为 UI 与 Prompt 构建的唯一事实来源。 /// 持有有序的 ConversationEntry 列表,支持追加文本与特殊消息。 /// 每个 ChatSession 持有一份 ConversationStore 实例。 /// public class ConversationStore { private readonly List _entries = new(); private static readonly ISerializer _yamlSerializer = new SerializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .Build(); private static readonly IDeserializer _yamlDeserializer = new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) .IgnoreUnmatchedProperties() .Build(); /// /// 有序条目列表(只读视图) /// public IReadOnlyList Entries => _entries; /// /// 存储内容变更时触发(用于持久化层按需保存) /// public event EventHandler? StoreChanged; /// /// 追加一条文本消息 /// public void AppendText(AuthorRole role, string content) { _entries.Add(new TextConversationEntry(role, content ?? string.Empty)); StoreChanged?.Invoke(this, EventArgs.Empty); } /// /// 追加一条特殊消息(type + YAML 载荷) /// public void AppendSpecial(string type, string yamlPayload) { _entries.Add(new SpecialConversationEntry(type ?? string.Empty, yamlPayload ?? string.Empty)); StoreChanged?.Invoke(this, EventArgs.Empty); } /// /// 清空存储(用于测试或重置) /// public void Clear() { _entries.Clear(); } /// /// 移除最后一条条目(用于回滚等) /// /// 是否移除了条目 public bool RemoveLast() { if (_entries.Count == 0) return false; _entries.RemoveAt(_entries.Count - 1); return true; } /// /// 条目数量 /// public int Count => _entries.Count; /// /// 序列化为 YAML 字符串(仅 entries 列表,用于嵌入会话文件或单独观察) /// public string ToYaml() { var dto = new ConversationStoreDto { Entries = ConversationEntryMapper.ToDtoList(_entries) }; return _yamlSerializer.Serialize(dto); } /// /// 从 YAML 字符串加载并替换当前存储内容(先清空再按序追加) /// public void LoadFromYaml(string yaml) { if (string.IsNullOrWhiteSpace(yaml)) { Clear(); return; } var dto = _yamlDeserializer.Deserialize(yaml); LoadFromEntries(dto?.Entries); } /// /// 从 DTO 条目列表加载并替换当前存储(先清空再按序追加),用于会话文件反序列化 /// public void LoadFromEntries(IEnumerable? entries) { _entries.Clear(); _entries.AddRange(ConversationEntryMapper.ToEntryList(entries)); } } }