mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Bug trouve en testant la migration sur une vraie machine (5,4 Go, 51 351 fichiers). Le rename du dossier reussissait, mais config.env contenait BIN=C:\ProgramData\jean\backends\llama.cpp\build\bin\Release\llama-server.exe soit un chemin ABSOLU vers le dossier qu'on venait de renommer. Resultat : le dossier migre intact, et llama-server ne demarre plus. Ca touche tous ceux qui ont fait un `llamacpp install`, donc le cas nominal, pas un cas limite. Les presets de configs/ portent le meme BIN et etaient touches pareil (deux presets concernes sur la machine de test). Apres un rename reussi, on reecrit donc les references a l'ancien chemin dans les fichiers de config qu'on ecrit nous-memes : config.env, model_dirs.json, mcp.json, webprefs.json et les presets de configs/. Les deux ecritures de separateur sont couvertes, Windows acceptant \ et / dans une meme valeur. Restreint a ces fichiers texte : on ne reecrit pas a l'aveugle les 51 000 fichiers d'un dossier de donnees. Les fichiers d'etat du service sont repris au passage (jean.pid/jean.log -> ajean.pid/ajean.log), meme raison que pour le worker de lien : le PID dit si le service tourne, l'ignorer ferait demarrer un second service. Non traite volontairement : l'arborescence de build llama.cpp (CMakeCache.txt et consorts) contient aussi des chemins absolus. Elle est regenerable par `ajean llamacpp update` et la reecrire en masse serait plus risque qu'utile. Verifie de bout en bout sur la machine de test : service demarre, llama-server chargé depuis le nouveau chemin, /health ok, completion reelle ok. Deux tests ajoutes reproduisant le cas.
88 lines
3.1 KiB
Go
88 lines
3.1 KiB
Go
package ajean
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
)
|
|
|
|
// « Où sont mes fichiers ? » — la question que personne ne devrait avoir à poser.
|
|
// Un binaire unique qui s'auto-installe au premier lancement rend les
|
|
// emplacements invisibles : on ne sait plus si le .exe qu'on a double-cliqué EST
|
|
// l'application ou seulement un installateur, ni où atterrissent la config, les
|
|
// modèles et les fichiers que l'agent écrit. On centralise donc la réponse ici,
|
|
// et on l'expose à la fois en ligne de commande (`ajean where`) et dans l'UI.
|
|
|
|
type ajeanPaths struct {
|
|
Home string `json:"home"` // AJEAN_HOME : racine des données
|
|
Config string `json:"config"` // config.env
|
|
Exe string `json:"exe"` // binaire en cours d'exécution
|
|
Installed string `json:"installed"` // binaire installé (peut différer de Exe)
|
|
Workspace string `json:"workspace"` // dossier de travail du mode agent
|
|
Memory string `json:"memory"`
|
|
Presets string `json:"presets"`
|
|
}
|
|
|
|
// installedExePath est l'emplacement canonique du binaire après installation.
|
|
// Il diffère par plateforme : sous Unix les installateurs posent /usr/local/bin/ajean
|
|
// (c'est ce que référencent les unités systemd et le plist launchd) ; sous Windows,
|
|
// faute d'équivalent, on utilise AJEAN_HOME\bin ajouté au PATH utilisateur.
|
|
func installedExePath() string { return exePathNamed("ajean") }
|
|
|
|
// legacyExePath est l'emplacement d'avant le renommage. L'installation continue
|
|
// d'y poser un alias : `jean` reste tapable indéfiniment. Ça ne coûte qu'un lien
|
|
// et ça préserve les habitudes, les scripts cron, les alias shell et les tutos
|
|
// déjà écrits par les utilisateurs — dont on ne contrôle aucun.
|
|
func legacyExePath() string { return exePathNamed("jean") }
|
|
|
|
func exePathNamed(name string) string {
|
|
if runtime.GOOS == "windows" {
|
|
return filepath.Join(AjeanHome(), "bin", name+".exe")
|
|
}
|
|
return "/usr/local/bin/" + name
|
|
}
|
|
|
|
func currentPaths() ajeanPaths {
|
|
exe, _ := os.Executable()
|
|
if resolved, err := filepath.EvalSymlinks(exe); err == nil {
|
|
exe = resolved
|
|
}
|
|
return ajeanPaths{
|
|
Home: AjeanHome(),
|
|
Config: confPath(),
|
|
Exe: exe,
|
|
Installed: installedExePath(),
|
|
Workspace: agentWorkspace(),
|
|
Memory: memoryDir(),
|
|
Presets: presetsDir(),
|
|
}
|
|
}
|
|
|
|
func cmdWhere(args []string) error {
|
|
p := currentPaths()
|
|
fmt.Printf("Emplacements AJEAN\n\n")
|
|
for _, row := range [][2]string{
|
|
{"données (AJEAN_HOME)", p.Home},
|
|
{"configuration", p.Config},
|
|
{"binaire en cours", p.Exe},
|
|
{"binaire installé", p.Installed},
|
|
{"travail de l'agent", p.Workspace},
|
|
{"mémoire", p.Memory},
|
|
{"presets", p.Presets},
|
|
} {
|
|
fmt.Printf(" %-20s %s\n", row[0], row[1])
|
|
}
|
|
if p.Exe != p.Installed {
|
|
fmt.Printf("\n%s tu exécutes une copie qui n'est PAS le binaire installé.\n", dim("[info]"))
|
|
fmt.Printf(" Les mises à jour depuis l'application ne modifient que la copie lancée.\n")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// handlePaths (GET /api/paths) alimente le bloc « Emplacements » de l'UI.
|
|
func handlePaths(w http.ResponseWriter, r *http.Request) {
|
|
sendJSON(w, 200, currentPaths())
|
|
}
|