From e0e51180633a7307bfc8ec77cba252ea3535d930 Mon Sep 17 00:00:00 2001 From: nathaninline Date: Wed, 22 Jul 2026 09:44:55 +0200 Subject: [PATCH] v0.4.4 : le bouton mise a jour redemarre automatiquement jean-link Apres une MAJ depuis l'UI, plus besoin de SSH sur le serveur pour finir : sur Linux/systemd le service jean-link est relance tout seul (differe + --no-block, la reponse HTTP part d'abord ; jean.service/llama-server n'est PAS touche pour ne pas recharger le modele). La cle E2E survit au restart, l'UI se reconnecte seule. Poste client/Windows : comportement inchange (message d'indice). --- main.go | 2 +- resource_windows_amd64.syso | Bin 8340 -> 8340 bytes resource_windows_arm64.syso | Bin 8340 -> 8340 bytes ui/index.html | 7 ++++++- update.go | 33 +++++++++++++++++++++++++++++++-- versioninfo.json | 6 +++--- 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 581cbf8..51b457e 100644 --- a/main.go +++ b/main.go @@ -16,7 +16,7 @@ import ( "strings" ) -const Version = "0.4.3" +const Version = "0.4.4" func main() { // Migration one-shot des anciens skills (SKILLS//SKILL.md) vers la diff --git a/resource_windows_amd64.syso b/resource_windows_amd64.syso index 2971cd3c9aeaccfefc3cc3fbe9bd9e0883d1faa7..9e3f9488cf0f993b74452f4da229efb93dae7091 100644 GIT binary patch delta 36 ncmbQ@IK^>;lnf^e0}BHPuxwVA5oBUC*=#Bo%m}19<+&LFgcb(Y delta 36 ncmbQ@IK^>;lnf^`0}BHPFmG0t5oBUC-fSut%m}19<+&LFgVP4m diff --git a/resource_windows_arm64.syso b/resource_windows_arm64.syso index 21ff86f6635b89ae18da130989180ec3dfa7bbf0..310c5e6bb7c16e42dffa633dbe3dcff72b522dfe 100644 GIT binary patch delta 36 ncmbQ@IK^>;lnf^e0}BHPuxwVA5oBUC*=#Bo%m}19<+&LFgcb(Y delta 36 ncmbQ@IK^>;lnf^`0}BHPFmG0t5oBUC-fSut%m}19<+&LFgVP4m diff --git a/ui/index.html b/ui/index.html index fbfcdbe..a18bf7d 100644 --- a/ui/index.html +++ b/ui/index.html @@ -672,7 +672,12 @@ async function applyUpdate(){ msg.textContent='Téléchargement et installation…'; try{ const r=await jpost('/api/update/apply',{}); - if(r.ok){ msg.innerHTML='✓ Installé en v'+r.version+'.
'+(r.restart||''); } + if(r.ok){ + msg.innerHTML='✓ Installé en v'+r.version+'.
'+(r.restart||''); + // Redémarrage auto du service côté serveur : le flux va se couper puis + // reconnecter tout seul (connectStream boucle). On rafraîchit l'état après. + if(r.restarting){ toast('mise à jour appliquée — reconnexion…'); setTimeout(loadAll, 6000); } + } else { msg.textContent='Échec : '+(r.error||'inconnu'); } }catch(e){ msg.textContent='Erreur pendant la mise à jour (réessaie).'; } } diff --git a/update.go b/update.go index 3391e30..735961b 100644 --- a/update.go +++ b/update.go @@ -6,6 +6,7 @@ import ( "io" "net/http" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -263,14 +264,42 @@ func handleUpdateCheck(w http.ResponseWriter, r *http.Request) { } // handleUpdateApply (POST /api/update/apply) : télécharge et installe la dernière -// version, puis renvoie la version installée + l'indice de redémarrage. +// version. Sur un serveur Linux/systemd, relance ensuite AUTOMATIQUEMENT le service +// jean-link (celui qui sert l'UI, le chat et le tunnel) pour appliquer la MAJ sans +// avoir à SSH — voir restartAfterUpdate. Renvoie la version + le message de statut. func handleUpdateApply(w http.ResponseWriter, r *http.Request) { newVer, err := applyUpdate() if err != nil { sendJSON(w, 200, map[string]any{"ok": false, "error": err.Error()}) return } - sendJSON(w, 200, map[string]any{"ok": true, "version": newVer, "restart": restartHintText()}) + restarting, msg := restartAfterUpdate() + if !restarting { + msg = restartHintText() + } + sendJSON(w, 200, map[string]any{"ok": true, "version": newVer, "restart": msg, "restarting": restarting}) +} + +// restartAfterUpdate relance le service jean-link juste après une MAJ déclenchée +// depuis l'UI, pour éviter le SSH manuel. Conditions : Linux/systemd + jean-link +// actif (le service tourne en root → systemctl passe sans sudo). On NE touche PAS à +// jean.service (llama-server) pour ne pas recharger le modèle (long et inattendu +// depuis un bouton « mettre à jour »). Le redémarrage est DIFFÉRÉ (la réponse HTTP +// doit partir d'abord) et lancé en --no-block : systemd enregistre le job puis nous +// arrête/relance ; la clé E2E (.e2e_key) survit au restart, donc pas de ré-appairage +// et l'UI se reconnecte toute seule (boucle de reconnexion du flux). Renvoie +// (déclenché, message). Non-serveur (poste client, Windows) → (false, ""). +func restartAfterUpdate() (bool, string) { + if runtime.GOOS != "linux" || !linkServiceActive() { + return false, "" + } + go func() { + time.Sleep(1500 * time.Millisecond) // laisser la réponse HTTP atteindre le client + // --no-block : on enregistre le job puis on rend la main ; systemd exécute le + // stop/start même si ce process (et le client systemctl) sont tués entre-temps. + _ = exec.Command("systemctl", "--no-block", "restart", linkServiceName).Run() + }() + return true, "Service " + linkServiceName + " redémarré automatiquement — la page va se reconnecter seule (le modèle n'est pas rechargé)." } func restartHintText() string { diff --git a/versioninfo.json b/versioninfo.json index 71417b8..18d709d 100644 --- a/versioninfo.json +++ b/versioninfo.json @@ -3,13 +3,13 @@ "FileVersion": { "Major": 0, "Minor": 4, - "Patch": 3, + "Patch": 4, "Build": 0 }, "ProductVersion": { "Major": 0, "Minor": 4, - "Patch": 3, + "Patch": 4, "Build": 0 }, "FileFlagsMask": "3f", @@ -25,7 +25,7 @@ "LegalCopyright": "Copyright (c) 2026 Jean contributors. MIT License.", "OriginalFilename": "jean.exe", "ProductName": "Jean", - "ProductVersion": "0.4.3", + "ProductVersion": "0.4.4", "Comments": "https://github.com/nathaninline/jean — projet open source (MIT)" }, "VarFileInfo": {