feat(launcher): avvia e aggiorna agent-tray.exe insieme al worker #12

Merged
claudia merged 1 commit from feat/launcher-supervises-tray into main 2026-09-11 14:46:01 +00:00
Owner

L'icona nell'area di notifica (agent-tray.exe, #10) finora si installava a mano dalla cartella Esecuzione automatica e non veniva mai aggiornata. Ora la gestisce il launcher, che gia' fa lo stesso lavoro per il worker.

Auto-update

/runner/latest guadagna due campi opzionali, tray_asset_url / tray_sha256 (env GW_TRAY_LATEST_URL / GW_TRAY_LATEST_SHA256), riferiti alla stessa versione del worker. Se il gateway non li pubblica, il tray non viene toccato e l'update del runner resta identico a prima: un launcher vecchio non vede nulla di nuovo.

selfupdate.Download diventa un wrapper su DownloadAsset, riusabile per qualunque binario ruotabile dal launcher. Worker e tray hanno canali di notifica separati: un update del solo tray non interrompe le sessioni in corso.

Avvio insieme al worker

Nuovi flag, persistiti negli Arguments del servizio: -tray <path> (default accanto al launcher), -tray-args, -tray-disabled.

Il tray non puo' partire dove gira il launcher (sessione 0, senza desktop ne' area di notifica): su Windows il processo si crea nella sessione della console con WTSQueryUserToken + DuplicateTokenEx + CreateProcessAsUser e lpDesktop=winsta0\default. Tre casi degradano con grazia:

Situazione Comportamento
Nessun utente loggato (macchina appena avviata) riprova ogni 30s, l'icona compare al login
Niente SE_TCB_NAME (servizio con l'account dell'utente, come serve all'auth di claude) log esplicito + fallback documentato a install-tray.ps1, senza loop
Utente chiude l'icona dal menu (exit 0) non gliela si ripropone fino al prossimo update

Nessun canary/rollback: il tray e' cosmetico; se crasha si riparte con backoff fino a 60s.

applyPendingIfAny ora gestisce anche la prima installazione (binario base assente): e' il caso del tray che arriva via update su una macchina che non l'aveva.

Aggiunto scripts/build-launcher.sh: una release pubblica tre asset (runner, tray, launcher).

Verifica

gofmt, go vet su linux e windows/amd64, go test ./... (nuovi test: supervisione, kill per update, exit volontario, download del tray, prima installazione) e i 52 test del gateway. Build dei tre .exe ok.

⚠️ Non verificabile da Linux: il comportamento reale su Windows (token di sessione, icona, WebView2) — resta lo smoke test sulla VM.

Ticket ]po[ 73643.

L'icona nell'area di notifica (`agent-tray.exe`, #10) finora si installava a mano dalla cartella Esecuzione automatica e non veniva mai aggiornata. Ora la gestisce il **launcher**, che gia' fa lo stesso lavoro per il worker. ## Auto-update `/runner/latest` guadagna due campi **opzionali**, `tray_asset_url` / `tray_sha256` (env `GW_TRAY_LATEST_URL` / `GW_TRAY_LATEST_SHA256`), riferiti alla **stessa versione** del worker. Se il gateway non li pubblica, il tray non viene toccato e l'update del runner resta identico a prima: un launcher vecchio non vede nulla di nuovo. `selfupdate.Download` diventa un wrapper su `DownloadAsset`, riusabile per qualunque binario ruotabile dal launcher. Worker e tray hanno canali di notifica separati: **un update del solo tray non interrompe le sessioni in corso**. ## Avvio insieme al worker Nuovi flag, persistiti negli Arguments del servizio: `-tray <path>` (default accanto al launcher), `-tray-args`, `-tray-disabled`. Il tray **non puo' partire dove gira il launcher** (sessione 0, senza desktop ne' area di notifica): su Windows il processo si crea nella sessione della console con `WTSQueryUserToken` + `DuplicateTokenEx` + `CreateProcessAsUser` e `lpDesktop=winsta0\default`. Tre casi degradano con grazia: | Situazione | Comportamento | |---|---| | Nessun utente loggato (macchina appena avviata) | riprova ogni 30s, l'icona compare al login | | Niente `SE_TCB_NAME` (servizio con l'account dell'utente, come serve all'auth di `claude`) | log esplicito + fallback documentato a `install-tray.ps1`, **senza loop** | | Utente chiude l'icona dal menu (exit 0) | non gliela si ripropone fino al prossimo update | Nessun canary/rollback: il tray e' cosmetico; se crasha si riparte con backoff fino a 60s. `applyPendingIfAny` ora gestisce anche la **prima installazione** (binario base assente): e' il caso del tray che arriva via update su una macchina che non l'aveva. Aggiunto `scripts/build-launcher.sh`: una release pubblica tre asset (runner, tray, launcher). ## Verifica `gofmt`, `go vet` su linux **e** windows/amd64, `go test ./...` (nuovi test: supervisione, kill per update, exit volontario, download del tray, prima installazione) e i **52 test** del gateway. Build dei tre `.exe` ok. :warning: Non verificabile da Linux: il comportamento reale su Windows (token di sessione, icona, WebView2) — resta lo smoke test sulla VM. Ticket ]po[ **73643**.
Finora l'icona nell'area di notifica andava installata a mano dalla
cartella Esecuzione automatica e non veniva mai aggiornata. Ora la
gestisce il launcher, che gia' fa lo stesso lavoro per il worker.

Auto-update: /runner/latest guadagna due campi OPZIONALI,
tray_asset_url/tray_sha256 (env GW_TRAY_LATEST_URL/SHA256), riferiti
alla stessa versione del worker. Se il gateway non li pubblica, il tray
non viene toccato e l'update del runner procede identico a prima, quindi
un launcher vecchio non vede nulla di nuovo. selfupdate.Download diventa
un wrapper su DownloadAsset, riusabile per qualunque binario ruotabile.
Worker e tray hanno canali di notifica separati: un update del solo tray
non interrompe le sessioni in corso.

Avvio: -tray <path> (default accanto al launcher), -tray-args,
-tray-disabled, persistiti negli Arguments del servizio. Il tray NON
puo' partire dove gira il launcher (sessione 0, senza desktop): su
Windows si crea il processo nella sessione della console con
WTSQueryUserToken + DuplicateTokenEx + CreateProcessAsUser e
lpDesktop=winsta0\default. Tre casi degradano con grazia:
- nessun utente loggato -> riprova ogni 30s, l'icona compare al login;
- niente SE_TCB_NAME (servizio con l'account dell'utente, setup
  necessario per l'auth di claude) -> log esplicito e si lascia il campo
  a install-tray.ps1, senza loop;
- chiuso dall'utente dal menu (exit 0) -> non lo si ripropone fino al
  prossimo update.
Nessun canary/rollback: il tray e' cosmetico, se crasha si riparte con
backoff fino a 60s.

applyPendingIfAny ora gestisce anche la prima installazione (binario
base assente): serve al tray che arriva su una macchina che non l'aveva.

Verificato da Linux: gofmt, go vet (linux e windows/amd64), go test
./... e i 52 test del gateway. Il comportamento su Windows (token della
sessione, icona, WebView2) resta da provare a mano sulla VM.

Ticket ]po[ 73643.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
claudia referenced this pull request from a commit 2026-09-11 15:41:50 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Soltea-org/soltea-agent-gateway!12
No description provided.