You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kev/Drawer/AI/Service/ChatSessionManager.cs

210 lines
6.0 KiB
C#

using System.Linq;
using AI.Models;
namespace AI.Service
{
/// <summary>
/// 管理多个聊天会话;会话存储以 YAML 文件持久化到 Sessions 目录。
/// </summary>
public class ChatSessionManager
{
private readonly Dictionary<string, ChatSession> _sessions = new();
private readonly object _lock = new object();
private ChatSession? _currentSession;
private readonly SessionStorage _storage;
public ChatSessionManager(SessionStorage? sessionStorage = null)
{
_storage = sessionStorage ?? new SessionStorage();
LoadSessionsFromDisk();
}
/// <summary>
/// 会话列表变化事件
/// </summary>
public event EventHandler? SessionsChanged;
/// <summary>
/// 当前会话变化事件
/// </summary>
public event EventHandler<ChatSession?>? CurrentSessionChanged;
/// <summary>
/// 获取所有会话(按更新时间倒序)
/// </summary>
public IEnumerable<ChatSession> GetAllSessions()
{
lock (_lock)
{
return _sessions.Values.OrderByDescending(s => s.UpdatedAt).ToList();
}
}
/// <summary>
/// 根据ID获取会话
/// </summary>
public ChatSession? GetSession(string sessionId)
{
lock (_lock)
{
return _sessions.TryGetValue(sessionId, out var session) ? session : null;
}
}
/// <summary>
/// 获取或设置当前活跃会话
/// </summary>
public ChatSession? CurrentSession
{
get
{
lock (_lock)
{
return _currentSession;
}
}
set
{
lock (_lock)
{
if (_currentSession != value)
{
_currentSession = value;
CurrentSessionChanged?.Invoke(this, value);
}
}
}
}
/// <summary>
/// 创建新会话并设置为当前会话;会订阅存储变更并持久化到 YAML 文件。
/// </summary>
public ChatSession CreateSession(string? title = null)
{
var session = new ChatSession(title: title);
session.Store.StoreChanged += (_, _) => SaveSession(session);
lock (_lock)
{
_sessions[session.Id] = session;
}
SaveSession(session);
CurrentSession = session;
SessionsChanged?.Invoke(this, EventArgs.Empty);
return session;
}
/// <summary>
/// 将会话保存到 YAML 文件
/// </summary>
public void SaveSession(ChatSession session)
{
if (session == null) return;
try
{
_storage.Save(session);
}
catch
{
// 持久化失败不抛,避免影响主流程
}
}
/// <summary>
/// 删除会话(同时删除对应 YAML 文件)
/// </summary>
public bool DeleteSession(string sessionId)
{
ChatSession? deletedSession = null;
lock (_lock)
{
if (_sessions.TryGetValue(sessionId, out deletedSession))
{
_sessions.Remove(sessionId);
if (_currentSession?.Id == sessionId)
{
_currentSession = _sessions.Values.OrderByDescending(s => s.UpdatedAt).FirstOrDefault();
CurrentSessionChanged?.Invoke(this, _currentSession);
}
}
}
if (deletedSession != null)
{
try { _storage.Delete(sessionId); } catch { }
SessionsChanged?.Invoke(this, EventArgs.Empty);
return true;
}
return false;
}
/// <summary>
/// 切换当前会话
/// </summary>
public bool SwitchToSession(string sessionId)
{
var session = GetSession(sessionId);
if (session != null)
{
CurrentSession = session;
return true;
}
return false;
}
/// <summary>
/// 获取当前活跃会话数量
/// </summary>
public int SessionCount
{
get
{
lock (_lock)
{
return _sessions.Count;
}
}
}
/// <summary>
/// 检查会话是否存在
/// </summary>
public bool SessionExists(string sessionId)
{
lock (_lock)
{
return _sessions.ContainsKey(sessionId);
}
}
private void LoadSessionsFromDisk()
{
try
{
var loaded = _storage.LoadAll().ToList();
if (loaded.Count == 0)
{
return;
}
lock (_lock)
{
foreach (var session in loaded)
{
session.Store.StoreChanged += (_, _) => SaveSession(session);
_sessions[session.Id] = session;
}
_currentSession = loaded.FirstOrDefault();
if (_currentSession != null)
{
CurrentSessionChanged?.Invoke(this, _currentSession);
}
}
SessionsChanged?.Invoke(this, EventArgs.Empty);
}
catch
{
// 加载失败则保持空列表,后续可新建会话
}
}
}
}