mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Arborescence unifiee et installateurs simplifies
- provisionDataDir unique pour les trois plateformes (six dossiers, config par defaut) - plus de modele config.env duplique dans chaque installateur - plus d'alias jean pose a l'installation
This commit is contained in:
1 parent
2455d9f402
commit
6de356f649
9 files changed
+93
-240
No files matched your search
@@ -17,36 +17,11 @@ import (
|
||||
// sur « systemctl: command not found » / « /etc/default/ajean », cf. issue #4).
|
||||
// Implémentation prudente ; à valider sur une machine Apple.
|
||||
|
||||
const configTemplate = `# Configuration AJEAN — édite-moi puis: ajean restart
|
||||
# Le service launchd lit ce fichier et lance ton binaire llama.cpp.
|
||||
|
||||
# Chemins
|
||||
BIN="/usr/local/bin/llama-server"
|
||||
MODEL="/Users/USER/models/your-model.gguf"
|
||||
|
||||
# Serveur
|
||||
PORT="8080"
|
||||
HOST="0.0.0.0"
|
||||
|
||||
# Inference
|
||||
CTX="32768"
|
||||
BATCH="2048"
|
||||
UBATCH="512"
|
||||
NGL="999"
|
||||
|
||||
# Args supplémentaires passés à llama-server
|
||||
EXTRA_ARGS=""
|
||||
`
|
||||
|
||||
// launchdPlistTemplate — champs formatés : Label, chemin du binaire, UserName,
|
||||
// WorkingDirectory, AJEAN_HOME, AJEAN_HOME, StandardOutPath, StandardErrorPath.
|
||||
// WorkingDirectory, AJEAN_HOME, StandardOutPath, StandardErrorPath.
|
||||
// KeepAlive/SuccessfulExit=false ≈ Restart=on-failure ; RunAtLoad relance au
|
||||
// boot une fois chargé avec `-w`.
|
||||
//
|
||||
// Le chemin du binaire est injecté et non codé en dur : il a changé avec le
|
||||
// renommage, et un plist figé sur l'ancien chemin donnerait un daemon qui refuse
|
||||
// de démarrer. Les deux variables d'environnement sont posées car le code lit
|
||||
// encore AJEAN_HOME en héritage.
|
||||
const launchdPlistTemplate = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
@@ -60,7 +35,7 @@ const launchdPlistTemplate = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<key>UserName</key><string>%s</string>
|
||||
<key>WorkingDirectory</key><string>%s</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict><key>AJEAN_HOME</key><string>%s</string><key>AJEAN_HOME</key><string>%s</string></dict>
|
||||
<dict><key>AJEAN_HOME</key><string>%s</string></dict>
|
||||
<key>RunAtLoad</key><true/>
|
||||
<key>KeepAlive</key>
|
||||
<dict><key>SuccessfulExit</key><false/></dict>
|
||||
@@ -87,14 +62,6 @@ func cmdInstall(args []string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("utilisateur '%s' introuvable: %w", targetUser, err)
|
||||
}
|
||||
// Migration de l'agencement ajean -> ajean AVANT de résoudre les chemins :
|
||||
// `install` est root et délibéré, c'est le bon moment. Ne fait rien si la
|
||||
// machine est déjà en ajean, ou si l'utilisateur a imposé un chemin.
|
||||
if err := migrateLayout(defaultLayoutPlan()); err != nil {
|
||||
return err
|
||||
}
|
||||
resetResolvedHome() // le dossier a pu changer à l'instant
|
||||
|
||||
ajeanHome := defaultAjeanHome()
|
||||
if v := os.Getenv("AJEAN_HOME"); v != "" {
|
||||
ajeanHome = v
|
||||
@@ -105,27 +72,12 @@ func cmdInstall(args []string) error {
|
||||
fmt.Printf(" AJEAN_HOME = %s\n", ajeanHome)
|
||||
fmt.Printf(" service = %s (launchd)\n", svc)
|
||||
|
||||
// 1. Répertoires
|
||||
// Plus de dossier SKILLS : les skills ont ete fondus dans la memoire.
|
||||
// On ne le CREE plus, mais on continue de le LIRE une fois au demarrage
|
||||
// pour reprendre ceux d'une ancienne installation (migrateSkillsToMemory).
|
||||
for _, d := range []string{ajeanHome, filepath.Join(ajeanHome, "configs")} {
|
||||
if err := os.MkdirAll(d, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
// 1. Arborescence + configuration de départ
|
||||
if err := provisionDataDir(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. config.env si absent
|
||||
conf := filepath.Join(ajeanHome, "config.env")
|
||||
if _, err := os.Stat(conf); os.IsNotExist(err) {
|
||||
body := strings.ReplaceAll(configTemplate, "USER", targetUser)
|
||||
if err := os.WriteFile(conf, []byte(body), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s écrit %s\n", green("✓"), conf)
|
||||
}
|
||||
|
||||
// 3. Symlink idempotent vers /usr/local/bin/ajean — même garde-fou que Linux
|
||||
// 2. Symlink idempotent vers /usr/local/bin/ajean — même garde-fou que Linux
|
||||
// (issue #5 : ne pas se lier sur soi-même si on tourne déjà depuis la cible).
|
||||
self, err := os.Executable()
|
||||
if err != nil {
|
||||
@@ -154,38 +106,24 @@ func cmdInstall(args []string) error {
|
||||
fmt.Printf(" %s %s -> %s\n", green("✓"), target, self)
|
||||
}
|
||||
|
||||
// 3 bis. Alias hérité : `ajean` doit rester tapable (voir sys_paths.go).
|
||||
if alias := legacyExePath(); alias != target {
|
||||
if rp, e := filepath.EvalSymlinks(alias); e != nil || rp != self {
|
||||
_ = os.Remove(alias)
|
||||
if err := os.Symlink(target, alias); err != nil {
|
||||
fmt.Printf(" %s alias %s non créé (%v) — « ajean » reste disponible\n", yellow("[info]"), alias, err)
|
||||
} else {
|
||||
fmt.Printf(" %s %s -> %s (alias hérité)\n", green("✓"), alias, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. /etc/default/ajean pour que les invocations CLI résolvent AJEAN_HOME.
|
||||
// Les deux clés sont écrites : des scripts d'utilisateurs sourcent ce fichier
|
||||
// et lisent encore $AJEAN_HOME.
|
||||
// 3. /etc/default/ajean pour que les invocations CLI résolvent AJEAN_HOME.
|
||||
_ = os.MkdirAll("/etc/default", 0o755)
|
||||
defaults := fmt.Sprintf("# Generated by ajean install — racine des configs/memoire/presets\nAJEAN_HOME=%s\nJEAN_HOME=%s\n", ajeanHome, ajeanHome)
|
||||
defaults := fmt.Sprintf("# Généré par ajean install — racine des données\nAJEAN_HOME=%s\n", ajeanHome)
|
||||
if err := os.WriteFile("/etc/default/ajean", []byte(defaults), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s /etc/default/ajean\n", green("✓"))
|
||||
|
||||
// 5. LaunchDaemon plist (le log va sous AJEAN_HOME, accessible au user cible)
|
||||
// 4. LaunchDaemon plist (le log va sous AJEAN_HOME, accessible au user cible)
|
||||
logPath := filepath.Join(ajeanHome, svc+".log")
|
||||
plist := fmt.Sprintf(launchdPlistTemplate, launchdLabel(svc), target, targetUser, ajeanHome, ajeanHome, ajeanHome, logPath, logPath)
|
||||
plist := fmt.Sprintf(launchdPlistTemplate, launchdLabel(svc), target, targetUser, ajeanHome, ajeanHome, logPath, logPath)
|
||||
plistPath := launchdPlistPath(svc)
|
||||
if err := os.WriteFile(plistPath, []byte(plist), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf(" %s %s\n", green("✓"), plistPath)
|
||||
|
||||
// 6. chown AJEAN_HOME au user cible
|
||||
// 5. chown AJEAN_HOME au user cible
|
||||
chown(ajeanHome, u)
|
||||
|
||||
fmt.Println()
|
||||
@@ -208,13 +146,12 @@ func cmdUninstall(args []string) error {
|
||||
launchdPlistPath(svc),
|
||||
"/etc/default/ajean",
|
||||
installedExePath(),
|
||||
legacyExePath(),
|
||||
} {
|
||||
if err := os.Remove(p); err == nil {
|
||||
fmt.Printf(" %s %s\n", green("✓"), p)
|
||||
}
|
||||
}
|
||||
// On ne supprime jamais AJEAN_HOME automatiquement (modèles, configs).
|
||||
// On ne supprime jamais AJEAN_HOME automatiquement (modèles, presets).
|
||||
fmt.Println(dim("(données utilisateur conservées — supprime $AJEAN_HOME manuellement si tu veux purger)"))
|
||||
fmt.Println(green("[ok]") + " désinstallé")
|
||||
return nil
|
||||
|
||||
Reference in new issue
Block a user