170 lines
5.2 KiB
C#
170 lines
5.2 KiB
C#
internal static partial class Program
|
|
{
|
|
static FragmentService NewService()
|
|
{
|
|
IFragmentRepository repo = new InMemoryFragmentRepository();
|
|
return new FragmentService(repo);
|
|
}
|
|
|
|
static Entry NewEntry()
|
|
{
|
|
var dbService = new JournalDatabaseService(new JournalConfigService());
|
|
var session = new DatabaseSessionService(dbService);
|
|
return new Entry(
|
|
NewService(),
|
|
new EntrySearchService(),
|
|
new VaultStorageService(new VaultCryptoService()),
|
|
dbService,
|
|
session,
|
|
new JournalConfigService(),
|
|
new DisabledAiService("none"),
|
|
new DisabledSpeechBridgeService("none"),
|
|
new EntryFileService(new DiskEntryFileRepository()),
|
|
new ListService(new SqliteListRepository(session)),
|
|
new TodoService(new SqliteTodoRepository(session)),
|
|
new CommandLogger());
|
|
}
|
|
|
|
static IJournalDatabaseService NewDatabaseService() => new JournalDatabaseService(new JournalConfigService());
|
|
|
|
static Dictionary<string, string> ReadVaultEntryTexts(string vaultPath, string password)
|
|
{
|
|
var crypto = new VaultCryptoService();
|
|
var encrypted = File.ReadAllBytes(vaultPath);
|
|
var zipBytes = crypto.DecryptData(encrypted, password);
|
|
|
|
using var stream = new MemoryStream(zipBytes);
|
|
using var archive = new ZipArchive(stream, ZipArchiveMode.Read);
|
|
var result = new Dictionary<string, string>(StringComparer.Ordinal);
|
|
foreach (var entry in archive.Entries)
|
|
{
|
|
if (string.IsNullOrEmpty(entry.Name))
|
|
continue;
|
|
|
|
using var reader = new StreamReader(entry.Open());
|
|
result[entry.Name] = reader.ReadToEnd();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static byte[] CreateZipBytes(Dictionary<string, string> files)
|
|
{
|
|
using var stream = new MemoryStream();
|
|
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: true))
|
|
{
|
|
foreach (var (name, content) in files)
|
|
{
|
|
var entry = archive.CreateEntry(name);
|
|
using var writer = new StreamWriter(entry.Open());
|
|
writer.Write(content);
|
|
}
|
|
}
|
|
return stream.ToArray();
|
|
}
|
|
|
|
static void WriteSearchFixtureFiles(string root)
|
|
{
|
|
File.WriteAllText(Path.Combine(root, "2026-02-01.md"), """
|
|
Date: 2026-02-01
|
|
## Summary
|
|
Alpha common
|
|
## Reflection
|
|
focus area
|
|
- [x] med taken
|
|
!TRIGGER #stress
|
|
fragment one
|
|
""");
|
|
|
|
File.WriteAllText(Path.Combine(root, "2026-02-05.md"), """
|
|
Date: 2026-02-05
|
|
## Summary
|
|
Beta common
|
|
## Reflection
|
|
other notes
|
|
- [ ] drink water
|
|
!NOTE #daily
|
|
fragment two
|
|
""");
|
|
|
|
File.WriteAllText(Path.Combine(root, "2026-03-01.md"), """
|
|
Date: 2026-03-01
|
|
## Summary
|
|
Gamma unique
|
|
## Reflection
|
|
nothing related
|
|
!NOTE #other
|
|
fragment three
|
|
""");
|
|
}
|
|
|
|
static (int ExitCode, string Stdout, string Stderr) CaptureConsole(Func<int> action)
|
|
{
|
|
var originalOut = Console.Out;
|
|
var originalError = Console.Error;
|
|
using var stdout = new StringWriter();
|
|
using var stderr = new StringWriter();
|
|
|
|
try
|
|
{
|
|
Console.SetOut(stdout);
|
|
Console.SetError(stderr);
|
|
var exitCode = action();
|
|
return (exitCode, stdout.ToString(), stderr.ToString());
|
|
}
|
|
finally
|
|
{
|
|
Console.SetOut(originalOut);
|
|
Console.SetError(originalError);
|
|
}
|
|
}
|
|
|
|
static JournalConfig BuildAiConfig(string sidecarScriptPath, int timeoutMs)
|
|
{
|
|
var baseConfig = new JournalConfigService().Current;
|
|
var pythonExe = Environment.GetEnvironmentVariable("JOURNAL_PYTHON_EXE");
|
|
if (string.IsNullOrWhiteSpace(pythonExe))
|
|
pythonExe = "python";
|
|
|
|
return baseConfig with
|
|
{
|
|
AiProvider = "python-sidecar",
|
|
PythonExecutable = pythonExe,
|
|
PythonAiSidecarPath = sidecarScriptPath,
|
|
AiSidecarTimeoutMs = timeoutMs
|
|
};
|
|
}
|
|
|
|
static async Task<List<TransportFixture>> LoadTransportFixturesAsync()
|
|
{
|
|
var path = Path.Combine(AppContext.BaseDirectory, "Fixtures", "transport_cases.json");
|
|
if (!File.Exists(path))
|
|
throw new FileNotFoundException($"Transport fixture file not found: {path}");
|
|
|
|
var json = await File.ReadAllTextAsync(path);
|
|
return JsonSerializer.Deserialize<List<TransportFixture>>(json, new JsonSerializerOptions
|
|
{
|
|
PropertyNameCaseInsensitive = true
|
|
}) ?? [];
|
|
}
|
|
|
|
static JsonValueKind ParseValueKind(string value) => value.Trim().ToLowerInvariant() switch
|
|
{
|
|
"array" => JsonValueKind.Array,
|
|
"object" => JsonValueKind.Object,
|
|
"null" => JsonValueKind.Null,
|
|
"string" => JsonValueKind.String,
|
|
"number" => JsonValueKind.Number,
|
|
"true" => JsonValueKind.True,
|
|
"false" => JsonValueKind.False,
|
|
_ => throw new InvalidOperationException($"Unsupported JsonValueKind '{value}' in transport fixture.")
|
|
};
|
|
|
|
static void Assert(bool condition, string message)
|
|
{
|
|
if (!condition)
|
|
throw new InvalidOperationException(message);
|
|
}
|
|
}
|
|
|