refactor: apply Single Responsibility Principle to Program.cs and ReplLoop.cs
extracted responsibilities from Program.cs (208→46 lines) and ReplLoop.cs (274→174 lines) into focused service classes: HeaderRenderer, SessionManager, ApplicationStartup, ResponseStreamer, SpinnerService, UsageDisplayer, and ContextCompactionService. Each class now has a single, well-defined responsibility, improving testability and maintainability.
This commit is contained in:
83
SessionManager.cs
Normal file
83
SessionManager.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace AnchorCli;
|
||||
|
||||
/// <summary>
|
||||
/// Manages session persistence, including auto-load on startup and auto-save on exit.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to load a session from disk. Returns true if successful.
|
||||
/// </summary>
|
||||
public async Task<bool> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to save the session to disk. Returns true if successful.
|
||||
/// </summary>
|
||||
public async Task<bool> 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves the session after an LLM turn completes.
|
||||
/// </summary>
|
||||
public async Task SaveAfterTurnAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
await TrySaveAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user