- Journal.DevTool: C# TUI dev tool (SDT) using Spectre.Console - Phosphor green (#00FF41) terminal aesthetic with amber/red accents - Grouped build target menu driven by devtool.json config - Topological dependency resolver for DependsOn chains - Live stdout/stderr streaming per target step - Interactive environment variable editor (dropdown + free-text) - Toolchain management screen: Python venv create/install/upgrade, Node npm install - Workspace switcher: reads sdt-workspace.json, hot-switches between projects - Outputs as 'sdt' executable (net10.0) - devtool.json: project config for SDT - All build targets: sidecar, web, webgateway, tauri, tauri-nsis, all (virtual) - Dev targets: run-gateway - Test targets: test (smoke), gate (migration) - Cache targets: nuget-export, nuget-import - Toolchains: Python 3.14 (cpu/gpu/nlp profiles) + Node/npm (Journal.App) - Env vars: AI provider, log level, NLP backend, path overrides - justfile: just command runner recipes wrapping existing scripts - Correct dependency ordering (sidecar before tauri, web before webgateway) - OS-aware runtime detection (win-x64 / linux-x64) - Recipes: sidecar, web, webgateway, tauri, tauri-nsis, all, run, dev-app, test, gate, build, nuget-export/import, sdt - Journal.slnx: added Journal.DevTool project
58 lines
2.0 KiB
C#
58 lines
2.0 KiB
C#
using Sdt.Config;
|
|
using Sdt.Tui;
|
|
using Spectre.Console;
|
|
|
|
// ── Workspace + project discovery ────────────────────────────────────────────
|
|
|
|
var workspaceResult = WorkspaceLoader.FindAndLoad();
|
|
var projectResult = ConfigLoader.FindAndLoad();
|
|
|
|
if (projectResult is null)
|
|
{
|
|
AnsiConsole.MarkupLine($"[bold {Theme.Red}]SDT:[/] [{Theme.Amber}]No devtool.json found[/] in current directory or any parent.");
|
|
AnsiConsole.MarkupLine(Theme.Faint("Create a devtool.json in your project root to get started."));
|
|
return 1;
|
|
}
|
|
|
|
// ── Main run loop (handles workspace project switching) ───────────────────────
|
|
|
|
var (currentConfig, currentRoot) = projectResult.Value;
|
|
var (workspace, workspaceRoot) = workspaceResult.HasValue
|
|
? (workspaceResult.Value.Config, workspaceResult.Value.WorkspaceRoot)
|
|
: ((WorkspaceConfig?)null, (string?)null);
|
|
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
var app = new App(currentConfig, currentRoot, workspace, workspaceRoot);
|
|
var result = await app.RunAsync();
|
|
|
|
if (result.Reason == AppExitReason.Quit)
|
|
break;
|
|
|
|
// User switched projects — reload config from new root
|
|
if (result.Reason == AppExitReason.SwitchProject && result.NewProjectRoot is not null)
|
|
{
|
|
var loaded = ConfigLoader.FindAndLoad(result.NewProjectRoot);
|
|
if (loaded is null)
|
|
{
|
|
AnsiConsole.MarkupLine(Theme.Fail($"No devtool.json found at: {result.NewProjectRoot}"));
|
|
AnsiConsole.MarkupLine(Theme.Faint("Press any key to stay on current project..."));
|
|
Console.ReadKey(intercept: true);
|
|
continue; // go back to current app
|
|
}
|
|
|
|
(currentConfig, currentRoot) = loaded.Value;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
AnsiConsole.MarkupLine(Theme.Fail($"Fatal: {ex.Message}"));
|
|
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything);
|
|
return 1;
|
|
}
|