diff --git a/CLAUDE.md b/CLAUDE.md index 8376440..6ecc15e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ LlmRun: eseguibile C# (.NET 10, Windows) che invoca Claude Code (`claude -p`) da Tutto in [Program.cs](Program.cs): top-level statements per la CLI e la classe `Gui` (Form) per la GUI. Entrambe costruiscono un `ProcessStartInfo` per `claude -p ` con `ArgumentList` (niente quoting manuale). Nessuna dipendenza esterna. - CLI: stdout/stderr ereditati (streaming), exit code propagato, 127 se `claude` non è nel PATH. -- GUI: output rediretto e mostrato riga per riga. +- GUI: output rediretto e mostrato riga per riga. Barra impostazioni con ComboBox modello (editabile, voci "Nome versione (id)"; lista hardcoded in `Gui.Models`, da aggiornare quando escono nuovi modelli) ed effort → `--model` / `--effort`, omessi se "predefinito". ## Vincoli non ovvi diff --git a/Program.cs b/Program.cs index ab2e2e7..4ad786a 100644 --- a/Program.cs +++ b/Program.cs @@ -37,15 +37,32 @@ static ProcessStartInfo NewClaude(string prompt) class Gui : Form { - readonly TextBox prompt = new() { Dock = DockStyle.Top, Multiline = true, Height = 80, AcceptsReturn = true }; + readonly TextBox prompt = new() { Dock = DockStyle.Top, Multiline = true, Height = 120, AcceptsReturn = true }; readonly Button send = new() { Dock = DockStyle.Top, Text = "Invia a Claude", Height = 32 }; readonly TextBox output = new() { Dock = DockStyle.Fill, Multiline = true, ReadOnly = true, ScrollBars = ScrollBars.Vertical }; + record Model(string Label, string Id) { public override string ToString() => Label; } + static readonly Model[] Models = + [ + new("Fable 5.1 (claude-fable-5-1)", "claude-fable-5-1"), + new("Opus 5.5 (claude-opus-5-5)", "claude-opus-5-5"), + new("Sonnet 5.5 (claude-sonnet-5-5)", "claude-sonnet-5-5"), + new("Haiku 5.5 (claude-haiku-5-5)", "claude-haiku-5-5"), + ]; + const string Default = "predefinito"; + readonly ComboBox model = new() { DropDownStyle = ComboBoxStyle.DropDown, Width = 300 }; // editabile: ID completo + readonly ComboBox effort = new() { DropDownStyle = ComboBoxStyle.DropDownList, Width = 100 }; + public Gui() { Text = "LlmRun"; - Width = 700; Height = 500; - Controls.Add(output); Controls.Add(send); Controls.Add(prompt); // Fill per primo: l'ordine inverso dei Dock + Width = 1000; Height = 700; + model.Items.Add(Default); model.Items.AddRange(Models); model.SelectedIndex = 0; + effort.Items.AddRange([Default, "low", "medium", "high", "xhigh", "max"]); effort.SelectedIndex = 0; + var settings = new FlowLayoutPanel { Dock = DockStyle.Top, Height = 32, Padding = new Padding(4) }; + settings.Controls.AddRange([new Label { Text = "Modello", AutoSize = true, Margin = new Padding(0, 6, 0, 0) }, model, + new Label { Text = "Effort", AutoSize = true, Margin = new Padding(8, 6, 0, 0) }, effort]); + Controls.Add(output); Controls.Add(send); Controls.Add(prompt); Controls.Add(settings); // Fill per primo: l'ordine inverso dei Dock send.Click += async (_, _) => await Run(); } @@ -56,7 +73,7 @@ class Gui : Form output.Clear(); try { - var psi = Program_NewClaude(prompt.Text); + var psi = NewClaude(prompt.Text); using var p = Process.Start(psi)!; p.StandardInput.Close(); void Append(string? l) { if (l != null) BeginInvoke(() => output.AppendText(l + Environment.NewLine)); } @@ -70,7 +87,7 @@ class Gui : Form finally { send.Enabled = true; } } - static ProcessStartInfo Program_NewClaude(string prompt) + ProcessStartInfo NewClaude(string prompt) { var psi = new ProcessStartInfo("claude") { @@ -81,6 +98,8 @@ class Gui : Form }; psi.ArgumentList.Add("-p"); psi.ArgumentList.Add(prompt); + foreach (var (flag, value) in new[] { ("--model", model.SelectedItem is Model m ? m.Id : model.Text.Trim()), ("--effort", effort.Text) }) + if (value != "" && value != Default) { psi.ArgumentList.Add(flag); psi.ArgumentList.Add(value); } return psi; } } diff --git a/README.md b/README.md index 36a275a..5c7f85d 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ GUI (nessun argomento): si apre una finestra con campo prompt, pulsante e output dotnet run ``` +Nella GUI, la barra in alto permette di scegliere **modello** (con versione) ed **effort** di ragionamento ("predefinito" = nessun flag, vale la config di `claude`). + CLI (con argomenti): il prompt viene stampato su terminale, l'exit code è quello di `claude`. ``` dotnet run -- "spiega questo progetto" diff --git a/docs/MVP.md b/docs/MVP.md index b68ec70..9d7373d 100644 --- a/docs/MVP.md +++ b/docs/MVP.md @@ -18,6 +18,9 @@ Tutti gli argomenti sono uniti in un unico prompt. ## GUI Senza argomenti si apre una finestra WinForms (prompt, pulsante, output) che usa lo stesso lancio di `claude -p`. Con argomenti resta la CLI. +La GUI ha una barra impostazioni con due menu: **Modello** (predefinito, Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5: ogni voce mostra versione e ID completo, che è ciò che viene passato a `claude`; oppure ID digitato a mano) e **Effort** (predefinito, low, medium, high, xhigh, max). Passati a `claude` come `--model` / `--effort`; con "predefinito" il flag viene omesso. Solo GUI: la CLI non li espone ancora. + +La finestra si apre a 1000x700 e output e prompt si ridimensionano con essa. ## Scelte tecniche - .NET 8+, un solo `Program.cs`, nessuna dipendenza esterna. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index dde7d26..cf686e2 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -14,7 +14,8 @@ Dettagli dell'MVP in [MVP.md](MVP.md). ## Fase 2 — Robustezza - [ ] Input del prompt da stdin e da file - [ ] Timeout e cancellazione (Ctrl+C propagato al figlio) -- [ ] Opzioni passate a `claude` (`--model`, `--allowedTools`, `--output-format`) +- [x] GUI: scelta di modello (`--model`) ed effort (`--effort`) +- [ ] CLI: stesse opzioni; inoltre `--allowedTools`, `--output-format` ## Fase 3 — Oltre - [ ] Modalità sessione (`--resume` / `--continue`)