feat: Implement history tracking with new CLI commands for viewing past transcripts and usage statistics.
This commit is contained in:
102
Core/HistoryManager.cs
Normal file
102
Core/HistoryManager.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Toak.Serialization;
|
||||
|
||||
namespace Toak.Core;
|
||||
|
||||
public static class HistoryManager
|
||||
{
|
||||
private static readonly string HistoryDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "toak");
|
||||
private static readonly string HistoryFile = Path.Combine(HistoryDir, "history.jsonl");
|
||||
|
||||
public static void SaveEntry(string rawTranscript, string refinedText, string? skillName, long durationMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(HistoryDir))
|
||||
{
|
||||
Directory.CreateDirectory(HistoryDir);
|
||||
}
|
||||
|
||||
var entry = new HistoryEntry
|
||||
{
|
||||
Timestamp = DateTime.UtcNow,
|
||||
RawTranscript = rawTranscript,
|
||||
RefinedText = refinedText,
|
||||
SkillName = skillName,
|
||||
DurationMs = durationMs
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(entry, AppJsonSerializerContext.Default.HistoryEntry);
|
||||
|
||||
// Thread-safe append
|
||||
lock (HistoryFile)
|
||||
{
|
||||
File.AppendAllLines(HistoryFile, new[] { json });
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogDebug($"Failed to save history: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static List<HistoryEntry> LoadEntries()
|
||||
{
|
||||
var entries = new List<HistoryEntry>();
|
||||
if (!File.Exists(HistoryFile)) return entries;
|
||||
|
||||
try
|
||||
{
|
||||
string[] lines;
|
||||
lock (HistoryFile)
|
||||
{
|
||||
lines = File.ReadAllLines(HistoryFile);
|
||||
}
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line)) continue;
|
||||
var entry = JsonSerializer.Deserialize(line, AppJsonSerializerContext.Default.HistoryEntry);
|
||||
if (entry != null)
|
||||
{
|
||||
entries.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogDebug($"Failed to load history: {ex.Message}");
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
public static void Shred()
|
||||
{
|
||||
if (File.Exists(HistoryFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (HistoryFile)
|
||||
{
|
||||
// Securely delete
|
||||
var len = new FileInfo(HistoryFile).Length;
|
||||
using (var fs = new FileStream(HistoryFile, FileMode.Open, FileAccess.Write))
|
||||
{
|
||||
var blank = new byte[len];
|
||||
fs.Write(blank, 0, blank.Length);
|
||||
}
|
||||
File.Delete(HistoryFile);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogDebug($"Failed to shred history: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user