Impostazioni: controllo e aggiornamento dei CLI con pulsante evidenziato

Sezione Aggiornamenti nel riquadro Impostazioni: per ogni CLI installato
versione, esito del controllo (disponibile, aggiornato, non riuscito) e
pulsante Aggiorna che esegue il comando ufficiale. Il pulsante e un puntino
sul pulsante Impostazioni si evidenziano solo se c'è una versione nuova. Il
controllo legge l'ultima versione dalle sorgenti ufficiali (downloads.claude.ai
e release GitHub di Codex), parte all'avvio e all'apertura del riquadro con
cache di 5 minuti e non fallisce mai in modo invasivo. L'aggiornamento ha
tempo massimo di 10 minuti, blocca invio e cambio CLI, e in caso di errore
suggerisce il comando manuale per npm, Homebrew, WinGet o installazione nativa.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
davideandClaude Sonnet 5.5 committed 2026-10-15 11:49:22 +02:00
1 parent 6498e45a0d
commit 8b20f5224e
7 files changed
+328 -16

No files matched your search

+18
View File
@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Net.Http.Headers;
namespace AgentWikiUi.Core;
@@ -24,6 +25,8 @@ abstract class Engine
/// <param name="structured">true = GUI (output catturato e da interpretare); false = CLI (output ereditato).</param>
public abstract List<string> BuildArgs(string prompt, string? sessionId, bool resume, string model, string effort, bool structured);
public abstract EngineReply Parse(int code, string stdout, string stderr);
/// <summary>Testo che annuncia l'ultima versione pubblicata (sola lettura, vedi ADR-0004). Eccezioni di rete/formato: le gestisce il chiamante.</summary>
public abstract Task<string?> FetchLatestVersionAsync(HttpClient http, CancellationToken ct);
public bool IsInstalled() => PathSearch.Find(Executable) is not null;
@@ -60,6 +63,10 @@ sealed class ClaudeEngine : Engine
public override EngineReply Parse(int code, string stdout, string stderr) =>
code == 0 ? new(stdout.Trim(), null, null) : new("", null, Failed(code, stderr.Trim()));
// Stessa sorgente dell'installer nativo: un file di testo con la versione.
public override async Task<string?> FetchLatestVersionAsync(HttpClient http, CancellationToken ct) =>
(await http.GetStringAsync("https://downloads.claude.ai/claude-code-releases/latest", ct)).Trim();
}
sealed class CodexEngine : Engine
@@ -123,6 +130,17 @@ sealed class CodexEngine : Engine
return new(lastMessage.Trim(), threadId, null);
}
// Ultima release su GitHub: tag_name tipo "rust-v0.162.1". L'API richiede lo User-Agent (impostato dal chiamante).
public override async Task<string?> FetchLatestVersionAsync(HttpClient http, CancellationToken ct)
{
using var req = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/openai/codex/releases/latest");
req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github+json"));
using var resp = await http.SendAsync(req, ct);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync(ct));
return doc.RootElement.GetProperty("tag_name").GetString();
}
// L'errore arriva come stringa che contiene un JSON {"error":{"message":…}}: si mostra il messaggio interno.
static string? InnerMessage(string? raw)
{