using System.Diagnostics; namespace AgentWikiUi.Core; record ModelOption(string Label, string Id); static class Catalog { // Da aggiornare quando escono nuovi modelli. public static readonly ModelOption[] Models = [ new("Fable 5.1", "claude-fable-5-1"), new("Opus 5.5", "claude-opus-5-5"), new("Sonnet 5.5", "claude-sonnet-5-5"), new("Haiku 5.5", "claude-haiku-5-5"), ]; public static readonly string[] Efforts = ["low", "medium", "high", "xhigh", "max"]; } record RunResult(int Code, string Out, string Err); // Unico punto di avvio di `claude`, condiviso da CLI e GUI. static class Claude { // sessionId null = nessun contesto (CLI). Model/effort vuoti = flag omessi. public static ProcessStartInfo CreateStart(string prompt, bool redirectOutput, string? sessionId = null, bool resume = false, string model = "", string effort = "") { var psi = new ProcessStartInfo("claude") { WorkingDirectory = AppContext.BaseDirectory, // mai la cwd del chiamante né Assembly.Location (vuoto in single-file) UseShellExecute = false, RedirectStandardInput = true, // chiuso subito dal chiamante: evita l'attesa di stdin di claude RedirectStandardOutput = redirectOutput, RedirectStandardError = redirectOutput, CreateNoWindow = true, }; psi.ArgumentList.Add("-p"); psi.ArgumentList.Add(prompt); if (sessionId is not null) { psi.ArgumentList.Add(resume ? "--resume" : "--session-id"); psi.ArgumentList.Add(sessionId); } foreach (var (flag, value) in new[] { ("--model", model), ("--effort", effort) }) if (value != "") { psi.ArgumentList.Add(flag); psi.ArgumentList.Add(value); } return psi; } // CLI: stdout/stderr ereditati (streaming), exit code propagato, 127 se `claude` manca. public static int RunInherited(string prompt) { try { using var p = Process.Start(CreateStart(prompt, redirectOutput: false))!; p.StandardInput.Close(); p.WaitForExit(); return p.ExitCode; } catch (System.ComponentModel.Win32Exception) { Console.Error.WriteLine("'claude' non trovato nel PATH."); return 127; } } // GUI: output catturato. Win32Exception se `claude` non è nel PATH. public static async Task RunCapturedAsync(string prompt, string sessionId, bool resume, string model, string effort) { using var p = Process.Start(CreateStart(prompt, redirectOutput: true, sessionId, resume, model, effort))!; p.StandardInput.Close(); var o = p.StandardOutput.ReadToEndAsync(); var e = p.StandardError.ReadToEndAsync(); await p.WaitForExitAsync(); return new(p.ExitCode, (await o).Trim(), (await e).Trim()); } }