1
0

feat: Implement history tracking with new CLI commands for viewing past transcripts and usage statistics.

This commit is contained in:
2026-02-28 14:06:58 +01:00
parent eadbd8d46d
commit a08838fbc4
12 changed files with 349 additions and 4 deletions

102
Core/HistoryManager.cs Normal file
View 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}");
}
}
}
}