Aggiunto supporto al motore CLI Antigravity (agy)
This commit is contained in:
1 parent
67d91e6a1f
commit
6bbaf7192f
12 files changed
+199
-69
No files matched your search
@@ -1,11 +1,11 @@
|
||||
# ADR-0002 — Più motori CLI (Claude Code, Codex, Antigravity) su Windows e Linux
|
||||
|
||||
- **Stato**: Accettata per Claude Code e Codex (verificati con prove reali); Antigravity resta da verificare
|
||||
- **Data**: 2026-10-15
|
||||
- **Stato**: Accettata (Claude Code, Codex, Antigravity)
|
||||
- **Data**: 2026-10-15 (aggiornato 2026-10-18 per Antigravity)
|
||||
- **Collegato a**: [ADR-0001](0001-gui-multipiattaforma-avalonia.md) (GUI e piattaforme)
|
||||
|
||||
## Contesto
|
||||
L'app lancia solo `claude -p`. Si vuole usare dalla stessa chat anche **OpenAI Codex CLI** e **Antigravity CLI** (`agy`), così come `claude` già installati da terminale dall'utente, su Windows e Linux. L'app non li installa e non gestisce login: sono programmi esterni, autenticati a parte.
|
||||
L'app lanciava solo `claude -p`. Si vuole usare dalla stessa chat anche **OpenAI Codex CLI** e **Antigravity CLI** (`agy`), così come `claude` già installati da terminale dall'utente, su Windows e Linux. L'app non li installa e non gestisce login: sono programmi esterni, autenticati a parte.
|
||||
|
||||
## Criteri di decisione
|
||||
1. Aggiungere un motore costa una definizione dichiarativa, non nuova logica sparsa.
|
||||
@@ -17,22 +17,22 @@ L'app lancia solo `claude -p`. Si vuole usare dalla stessa chat anche **OpenAI C
|
||||
- **Astrazione "motore"** in C#. Ogni motore descrive: nome e eseguibile, argomenti per il primo messaggio e per la ripresa, elenco modelli, supporto effort, modo per ottenere l'id di sessione. `RunClaude` è diventato `EngineRunner` con il motore come parametro.
|
||||
- **Rilevamento** dei motori cercando l'eseguibile nel PATH (su Windows anche le estensioni di PATHEXT). I motori assenti sono disabilitati nelle Impostazioni, con messaggio chiaro; la CLI esce con 127 come oggi.
|
||||
- **Una chat = un motore**. Il file JSON della chat memorizza il motore; il contesto di sessione non passa da un motore all'altro, quindi cambiare motore apre una nuova chat.
|
||||
- **Impostazioni** nella GUI: interruttore **CLI** (motore attivo), modello, effort. Cambiare motore apre una nuova chat; modello ed effort tornano ai valori iniziali del motore (il modello più piccolo ed effort `low`; "Predefinito" resta selezionabile) e le liste sono quelle del motore. La persistenza su disco delle impostazioni è rinviata. La CLI ottiene `--engine <id>` (`claude`, `codex`).
|
||||
- **Sessione**: per Claude Code l'id lo sceglie l'app; per Codex lo genera Codex e l'app lo legge dall'output (`thread_id`). Il JSON della chat ha quindi un campo `Engine` e un campo `SessionId` separato dall'id della chat (che resta il nome del file). I file scritti prima (senza questi campi) si leggono come chat di Claude Code con `SessionId` = id della chat.
|
||||
- **Impostazioni** nella GUI: interruttore **CLI** (motore attivo), modello, effort. Cambiare motore apre una nuova chat; modello ed effort tornano ai valori iniziali del motore (il modello più piccolo ed effort `low`; "Predefinito" resta selezionabile) e le liste sono quelle del motore. La persistenza su disco delle impostazioni è rinviata. La CLI ottiene `--engine <id>` (`claude`, `codex`, `agy`).
|
||||
- **Sessione**: per Claude Code l'id lo sceglie l'app; per Codex e Antigravity lo genera il motore e l'app lo legge dall'output (`thread_id` per Codex, `conversation_id` per Antigravity). Il JSON della chat ha quindi un campo `Engine` e un campo `SessionId` separato dall'id della chat (che resta il nome del file). I file scritti prima (senza questi campi) si leggono come chat di Claude Code con `SessionId` = id della chat.
|
||||
- **Autore dei messaggi**: l'etichetta sulle risposte e i segnaposto del composer usano il nome del motore della chat; l'elenco chat indica il motore.
|
||||
- **Permessi**: di default sola lettura / nessun bypass dei controlli; concedere di più è un'opzione esplicita.
|
||||
- **Output**: ogni motore ha un parser che lo normalizza in testo markdown prima del rendering.
|
||||
|
||||
## Comandi dei motori
|
||||
Claude Code e Codex sono verificati con prove reali (Codex 0.144.3, 2026-10-15, Linux/WSL). Antigravity deriva da documentazione e ricerche: `agy` non è installato su questa macchina.
|
||||
Claude Code, Codex e Antigravity sono verificati con prove reali (Linux/WSL, ottobre 2026).
|
||||
|
||||
| | Claude Code | Codex CLI | Antigravity CLI |
|
||||
|---|---|---|---|
|
||||
| Comando (GUI) | `claude -p <prompt>` | `codex exec --json --skip-git-repo-check -s read-only [opzioni] -- <prompt>` | `agy -p <prompt>` (da verificare) |
|
||||
| Continuare | `--session-id <guid>`, poi `--resume <guid>` | `codex exec resume --json --skip-git-repo-check -c 'sandbox_mode="read-only"' [opzioni] <id> -- <prompt>` | da verificare |
|
||||
| Modello | `--model` | `-m` / `--model` | da verificare |
|
||||
| Effort | `--effort` | `-c model_reasoning_effort=<livello>` | non noto |
|
||||
| Output usato | testo su stdout | JSONL su stdout (vedi sotto) | da verificare |
|
||||
| Comando (GUI) | `claude -p <prompt>` | `codex exec --json --skip-git-repo-check -s read-only [opzioni] -- <prompt>` | `agy --output-format json --print-timeout 120s [opzioni] -p <prompt>` |
|
||||
| Continuare | `--session-id <guid>`, poi `--resume <guid>` | `codex exec resume --json --skip-git-repo-check -c 'sandbox_mode="read-only"' [opzioni] <id> -- <prompt>` | `agy --output-format json --print-timeout 120s --conversation <id> [opzioni] -p <prompt>` |
|
||||
| Modello | `--model` | `-m` / `--model` | `--model` |
|
||||
| Effort | `--effort` | `-c model_reasoning_effort=<livello>` | `--effort` |
|
||||
| Output usato | testo su stdout | JSONL su stdout (vedi sotto) | JSON su stdout (`conversation_id`, `status`, `response`) |
|
||||
|
||||
**Codex: esito delle prove**
|
||||
- L'id di sessione non si sceglie: compare nel primo evento JSONL `{"type":"thread.started","thread_id":"<uuid>"}`. Nel testo normale compare solo nell'intestazione su stderr.
|
||||
@@ -46,17 +46,26 @@ Claude Code e Codex sono verificati con prove reali (Codex 0.144.3, 2026-10-15,
|
||||
- Il modello più piccolo di Codex è assunto essere GPT-5.6 Luna (nome e supporto agli effort inferiori: non dichiarato da OpenAI nelle prove); da rivedere quando cambia il catalogo.
|
||||
- Il catalogo modelli di Codex è dinamico (`~/.codex/models_cache.json`); l'app ne usa uno fisso, da aggiornare, con "Predefinito" e "Altro ID…" sempre disponibili.
|
||||
|
||||
**Antigravity (`agy`): esito delle prove**
|
||||
- Eseguibile nativo: ELF su Linux (`~/.gemini/bin/agy`), `.exe` nativo su Windows.
|
||||
- Permessi e sicurezza: per usare `agy` in modalità non interattiva (`-p`) in sola lettura, nel file `~/.gemini/antigravity-cli/settings.json` deve essere presente la regola `'read_file(*)'` sotto `'permissions.allow'` (altrimenti headless mode nega `read_file` con errore jetski: `a tool required the read_file permission that headless mode cannot prompt for`), mentre scritture e comandi restano negati di default. Non si passa `--mode plan` (che fallisce anch'esso con errore jetski) né `--mode auto` (non disponibile per l'account) né alcun flag `--mode`. Mai usare `--dangerously-skip-permissions`.
|
||||
- Posizione di `-p`: tutti i flag di configurazione vanno passati rigorosamente prima di `-p <prompt>`.
|
||||
- Formato output: per la GUI (`structured = true`) si passa `--output-format json`; per la CLI si omette per ereditare testo normale. L'output JSON contiene `conversation_id`, `status` ("SUCCESS") e `response` con il testo generato.
|
||||
- Sessione: l'id di sessione è un UUID generato da `agy` (`OwnsSessionId => true`), letto da `conversation_id`. La ripresa avviene passando `--conversation <sessionId>`.
|
||||
- Blocco sottoprocesso su output rediretto (issue #318): mitigato passando `--print-timeout 120s` (formato durata Go) e assicurando la chiusura immediata dello stdin.
|
||||
- Modelli ed effort: modelli fissi da catalogo `agy models`, modello più piccolo predefinito `gemini-3.0-flash-low`, effort supportati `low`, `medium`, `high`, `xhigh`, `max` (default `low`).
|
||||
|
||||
## Conseguenze
|
||||
**Positive**: un solo flusso di avvio; nuovi motori aggiungibili con una definizione; elimina la duplicazione CLI/GUI.
|
||||
**Negative**: i flag delle CLI cambiano nel tempo e vanno mantenuti; le sessioni non si trasferiscono tra motori; più superficie da testare su due sistemi operativi.
|
||||
|
||||
## Rischi e da verificare
|
||||
- [x] **Codex**: l'id di sessione lo genera Codex; letto dall'evento `thread.started` (vedi sopra).
|
||||
- [ ] **Antigravity**: segnalato un blocco di `agy -p` da sottoprocesso con output rediretto su Windows ([issue #318](https://github.com/google-antigravity/antigravity-cli/issues/318)). Provare con `--print-timeout` e prevedere un messaggio d'errore. I flag vanno messi prima di `-p`. Da provare anche su Linux.
|
||||
- [ ] **Forma dell'eseguibile**: `claude` è un .exe nativo avviabile direttamente; Codex e Antigravity, se installati con un gestore di pacchetti (es. npm), su Windows possono essere script `.cmd` che richiedono `cmd.exe /c`. Su Linux sono normali eseguibili o script con shebang. Verificare e gestire per motore.
|
||||
- [x] **Antigravity**: verificato il comando non interattivo `agy [flag] -p <prompt>`, output JSON `--output-format json`, ripresa con `--conversation`, timeout con `--print-timeout 120s` e chiusura stdin.
|
||||
- [ ] **Forma dell'eseguibile**: `claude` e `agy` sono binari nativi avviabili direttamente; per installazioni tramite gestori di pacchetti verificare eventuali script wrapper su Windows.
|
||||
- [ ] Autenticazione: ogni CLI deve essere già autenticata; l'app mostra l'errore del motore senza gestire login.
|
||||
- [x] Formato dell'output di Codex: JSONL, normalizzato in testo markdown. Antigravity ancora da verificare.
|
||||
- [x] Mappatura effort e modelli per Codex (liste fisse, da aggiornare). Antigravity da verificare.
|
||||
- [x] Formato dell'output di Codex e Antigravity: Codex JSONL, Antigravity JSON su stdout, normalizzati in testo markdown.
|
||||
- [x] Mappatura effort e modelli per Codex e Antigravity (liste fisse, da aggiornare).
|
||||
|
||||
## Riferimenti
|
||||
- Passi: [ROADMAP.md](../ROADMAP.md), Fase 4.
|
||||
|
||||
@@ -24,9 +24,10 @@ Entrambi i CLI hanno un comando di aggiornamento che controlla e, se c'è una ve
|
||||
- **Controllo prima dell'aggiornamento** (sola lettura, nessuna installazione): l'app confronta la versione installata (`<cli> --version`) con l'ultima pubblicata.
|
||||
- Claude Code: `GET https://downloads.claude.ai/claude-code-releases/latest`, testo con la versione (la stessa sorgente dell'installer nativo).
|
||||
- Codex: `GET https://api.github.com/repos/openai/codex/releases/latest`, campo `tag_name` (es. `rust-v0.162.1`, si estrae `0.162.1`).
|
||||
- Le versioni si ricavano con il primo numero `N.N.N` del testo e si confrontano come versioni. Verificate il 2026-10-15: restituivano 2.1.300 e 0.162.1.
|
||||
- Antigravity: `GET https://antigravity-cli-auto-updater-974169037036.us-central1.run.app`, testo con `Stable Version: X.Y.Z` (la sorgente dell'auto-updater ufficiale presente nel binario `agy`).
|
||||
- Le versioni si ricavano con il primo numero `N.N.N` del testo e si confrontano come versioni. Verificate il 2026-10-15 e 2026-10-18.
|
||||
- **Disponibile** (ultima > installata): la riga mostra "Aggiornamento disponibile: X", il pulsante Aggiorna è **evidenziato** (colore d'accento) e un puntino d'accento compare sul pulsante Impostazioni. **Aggiornato** (uguale o più nuova): riga neutra con "Aggiornato", pulsante normale, nessun puntino; resta cliccabile per forzare `update`. **Sconosciuto** (rete assente, risposta non valida, timeout di 10 s): "Controllo non riuscito", pulsante normale, nessun errore invasivo.
|
||||
- Quando si controlla: all'avvio, in background, e ogni volta che si apre il riquadro Impostazioni se l'ultimo controllo ha più di 5 minuti; subito dopo un aggiornamento. Mai in modo da rallentare la chat. Le richieste non inviano identificativi; l'app contatta solo i due indirizzi sopra.
|
||||
- Quando si controlla: all'avvio, in background, e ogni volta che si apre il riquadro Impostazioni se l'ultimo controllo ha più di 5 minuti; subito dopo un aggiornamento. Mai in modo da rallentare la chat. Le richieste non inviano identificativi; l'app contatta solo gli indirizzi ufficiali sopra.
|
||||
- **Flusso** di un clic: legge la versione (`<cli> --version`), lancia `<cli> update` (stdin chiuso, output catturato, tempo massimo 10 minuti), rilegge la versione e mostra l'esito sulla riga:
|
||||
- versione cambiata ⇒ "Aggiornato da X a Y";
|
||||
- exit 0 e versione invariata ⇒ "Già aggiornato (X)";
|
||||
@@ -34,12 +35,12 @@ Entrambi i CLI hanno un comando di aggiornamento che controlla e, se c'è una ve
|
||||
- Pulsanti disabilitati mentre una risposta è in corso o un altro aggiornamento è attivo; la chat non parte durante l'aggiornamento.
|
||||
- **Comando manuale** scelto dal metodo di installazione, dedotto dal percorso reale dell'eseguibile (collegamenti simbolici risolti):
|
||||
|
||||
| Percorso contiene | Metodo | Claude Code | Codex |
|
||||
|---|---|---|---|
|
||||
| `node_modules`, `.npm` | npm | `npm install -g @anthropic-ai/claude-code@latest` | `npm install -g @openai/codex@latest` |
|
||||
| `Cellar`, `homebrew`, `linuxbrew` | Homebrew | `brew upgrade claude-code` (o `claude-code@latest`) | `brew upgrade --cask codex` |
|
||||
| `WinGet`, `WindowsApps` | WinGet | `winget upgrade Anthropic.ClaudeCode` | script PowerShell di [INSTALL.md](../INSTALL.md) |
|
||||
| altro | nativo/script | `claude update` da terminale | script di installazione di [INSTALL.md](../INSTALL.md) |
|
||||
| Percorso contiene | Metodo | Claude Code | Codex | Antigravity |
|
||||
|---|---|---|---|---|
|
||||
| `node_modules`, `.npm` | npm | `npm install -g @anthropic-ai/claude-code@latest` | `npm install -g @openai/codex@latest` | `agy update` |
|
||||
| `Cellar`, `homebrew`, `linuxbrew` | Homebrew | `brew upgrade claude-code` (o `claude-code@latest`) | `brew upgrade --cask codex` | `brew upgrade agy` |
|
||||
| `WinGet`, `WindowsApps` | WinGet | `winget upgrade Anthropic.ClaudeCode` | script PowerShell di [INSTALL.md](../INSTALL.md) | `agy update` |
|
||||
| altro | nativo/script | `claude update` da terminale | script di installazione di [INSTALL.md](../INSTALL.md) | `agy update` |
|
||||
|
||||
L'app **mostra** il comando, non lo esegue: un'installazione globale con npm o un gestore di pacchetti può richiedere permessi o scelte che spettano all'utente.
|
||||
- Dopo un aggiornamento riuscito le versioni mostrate si rileggono; la chat aperta non cambia.
|
||||
|
||||
Reference in new issue
Block a user