mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-12 01:37:06 +02:00
Surface visible passee en AJEAN : aide de la CLI, messages, invite du chat terminal, commentaires, README, metadonnees Windows du binaire (InternalName / OriginalFilename). Les reglages s'appellent desormais AJEAN_* (AJEAN_HOME, AJEAN_MODEL_DIRS, AJEAN_DL_CONNS, AJEAN_LINK_URL, AJEAN_ACME_EMAIL, AJEAN_SERVICE), avec l'ancien nom JEAN_* toujours lu en second via envAny(). Ces variables sont posees a la main dans des shells, des units, des docker-compose et des scripts de deploiement qu'on ne peut pas retrouver : cesser de les lire ferait retomber silencieusement un reglage sur sa valeur par defaut. Migration one-shot du dossier de donnees retentee dans la fenetre ou l'installateur Windows a arrete toutes les instances, seule fenetre ou le rename peut aboutir. Le chemin du binaire est recalcule juste apres, sinon on reinstallerait dans le dossier qu'on vient de deplacer. Deux choses volontairement NON renommees, parce que les renommer casserait des utilisateurs sans rien apporter : - "model": "jean", le nom expose sur l'endpoint compatible OpenAI. Des integrations externes le configurent en dur. - les cles localStorage (jean-theme, jean.sys...). Les renommer reinitialiserait theme, preferences d'affichage et prompt systeme dans le navigateur de chaque utilisateur. Le plist launchd recevait /usr/local/bin/jean en dur : le chemin est desormais injecte, sinon le daemon macOS aurait refuse de demarrer apres le renommage. index.html regenere depuis ui/src via go generate.
83 lines
2.9 KiB
Go
83 lines
2.9 KiB
Go
//go:build windows
|
|
|
|
package ajean
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"testing"
|
|
)
|
|
|
|
// binaryVersion pilote la mise à jour automatique du binaire installé quand on
|
|
// lance le fichier téléchargé : si elle renvoie du vide, plus aucune mise à jour
|
|
// n'a lieu, et en silence. C'est exactement ce qui arrivait avec la première
|
|
// implémentation (exécuter `ajean version`, dont la sortie est vide pour un
|
|
// binaire en sous-système GUI). D'où ces tests sur la plomberie syscall.
|
|
func TestBinaryVersionReadsResource(t *testing.T) {
|
|
// kernel32.dll porte toujours une ressource de version.
|
|
dll := filepath.Join(os.Getenv("SystemRoot"), "System32", "kernel32.dll")
|
|
if _, err := os.Stat(dll); err != nil {
|
|
t.Skip("kernel32.dll introuvable")
|
|
}
|
|
v := binaryVersion(dll)
|
|
if !regexp.MustCompile(`^\d+\.\d+\.\d+$`).MatchString(v) {
|
|
t.Fatalf("binaryVersion(kernel32.dll) = %q, attendu une version x.y.z", v)
|
|
}
|
|
}
|
|
|
|
// Sur une machine vierge, le dossier bin n'existe pas encore : installSelf doit
|
|
// le créer. Sans ça, le premier lancement échouait sur « open
|
|
// C:\ProgramData\jean\bin\jean.exe: The system cannot find the path specified »
|
|
// et AJEAN ne s'installait jamais.
|
|
func TestInstallSelfCreatesBinDir(t *testing.T) {
|
|
binDir := filepath.Join(t.TempDir(), "jean", "bin") // deux niveaux absents
|
|
dst, err := installSelf(binDir)
|
|
if err != nil {
|
|
t.Fatalf("installSelf sur un dossier absent : %v", err)
|
|
}
|
|
if _, err := os.Stat(dst); err != nil {
|
|
t.Fatalf("binaire non écrit : %v", err)
|
|
}
|
|
}
|
|
|
|
// replaceInstalled doit écraser le binaire en place, y compris quand le fichier
|
|
// cible existe déjà, et laisser l'ancien de côté sans le confondre avec la cible.
|
|
func TestReplaceInstalled(t *testing.T) {
|
|
dir := t.TempDir()
|
|
target := filepath.Join(dir, "jean.exe")
|
|
if err := os.WriteFile(target, []byte("ancienne version"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := replaceInstalled(target); err != nil {
|
|
t.Fatalf("replaceInstalled : %v", err)
|
|
}
|
|
got, err := os.ReadFile(target)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// installSelf copie l'exécutable courant (ici le binaire de test).
|
|
self, err := os.ReadFile(os.Args[0])
|
|
if err != nil {
|
|
t.Skip("binaire de test illisible")
|
|
}
|
|
if len(got) != len(self) {
|
|
t.Fatalf("cible = %d octets, attendu %d (le binaire courant)", len(got), len(self))
|
|
}
|
|
if _, err := os.Stat(target + ".old"); err == nil {
|
|
t.Error(".old subsiste alors que la cible n'était pas verrouillée")
|
|
}
|
|
}
|
|
|
|
// Un fichier sans ressource de version doit renvoyer "" : runAsInstaller s'en
|
|
// sert pour s'abstenir plutôt que de remplacer un binaire au hasard.
|
|
func TestBinaryVersionWithoutResource(t *testing.T) {
|
|
p := filepath.Join(t.TempDir(), "vide.exe")
|
|
if err := os.WriteFile(p, []byte("pas un exe"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if v := binaryVersion(p); v != "" {
|
|
t.Fatalf("binaryVersion sur un fichier sans ressource = %q, attendu \"\"", v)
|
|
}
|
|
}
|