using Spectre.Console; namespace AnchorCli; /// /// Manages session persistence, including auto-load on startup and auto-save on exit. /// internal sealed class SessionManager { private readonly ChatSession _session; private readonly string _sessionPath; public SessionManager(ChatSession session, string sessionPath = ".anchor/session.json") { _session = session; _sessionPath = sessionPath; } /// /// Attempts to load a session from disk. Returns true if successful. /// public async Task TryLoadAsync(CancellationToken cancellationToken = default) { if (!File.Exists(_sessionPath)) { return false; } try { await _session.LoadAsync(_sessionPath, cancellationToken); AnsiConsole.MarkupLine($"[dim grey]Auto-loaded previous session.[/]"); // Print the last message if there is one if (_session.History.Count > 1) { var lastMessage = _session.History[^1]; var preview = lastMessage.Text.Length > 280 ? lastMessage.Text[..277] + "..." : lastMessage.Text; AnsiConsole.MarkupLine($"[dim grey] Last message: {Markup.Escape(preview)}[/]"); } return true; } catch { // Ignore load errors return false; } } /// /// Attempts to save the session to disk. Returns true if successful. /// public async Task TrySaveAsync(CancellationToken cancellationToken = default) { try { var directory = Path.GetDirectoryName(_sessionPath); if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) { Directory.CreateDirectory(directory); } await _session.SaveAsync(_sessionPath, cancellationToken); return true; } catch { // Ignore save errors return false; } } /// /// Saves the session after an LLM turn completes. /// public async Task SaveAfterTurnAsync(CancellationToken cancellationToken = default) { await TrySaveAsync(cancellationToken); } }