mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Socle du renommage jean -> AJEAN, sans aucun impact visible pour le parc installe. Trois briques : - module github.com/nathaninline/ajean, cmd/ajean, internal/ajean, package ajean. Purement interne. - AjeanHome() remplace JeanHome(). Les defauts deviennent %ProgramData%\ajean et /etc/ajean, avec migration du dossier existant au premier lancement. La migration est un os.Rename dans le dossier parent de l'ancien chemin : intra-volume, donc atomique et instantane meme avec des .gguf de plusieurs dizaines de Go. Si le rename echoue (handle ouvert sous Windows, droits, volume en lecture seule) on CONTINUE sur l'ancien chemin et on retentera : jamais de copie, jamais de suppression, le pire cas est "rien n'a bouge". $AJEAN_HOME et $JEAN_HOME restent tous deux honores, ainsi que /etc/default/ajean et /etc/default/jean : un chemin impose a la main est un ordre, on ne le migre pas. - l'auto-MAJ accepte desormais ajean-<os>-<arch> ET jean-<os>-<arch>, dans cet ordre. Indispensable dans les deux sens : les binaires deja installes ne connaissent que jean-*, et ce binaire-ci doit pouvoir s'installer depuis une release anterieure au renommage. Couvert par des tests, dont le repli quand un handle ouvert bloque le rename sous Windows.
88 lines
3.0 KiB
Go
88 lines
3.0 KiB
Go
//go:build darwin
|
|
|
|
package ajean
|
|
|
|
// sys_console_darwin.go — détection du lancement « par clic » sous macOS.
|
|
//
|
|
// Sur macOS il n'y a pas d'équivalent d'AttachConsole : un binaire lancé depuis
|
|
// le Finder hérite quand même de descripteurs stdout/stderr (vers les logs
|
|
// système). Le signal fiable, c'est l'emplacement de l'exécutable : la release
|
|
// publie un bundle Jean.app dont le binaire vit dans
|
|
// Jean.app/Contents/MacOS/jean. Si on tourne depuis là, c'est un double-clic
|
|
// dans le Finder → expérience « application » (UI web + navigateur), exactement
|
|
// comme le double-clic sur jean.exe sous Windows.
|
|
//
|
|
// Le même binaire copié dans /usr/local/bin garde évidemment le comportement CLI.
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func setupConsole() bool {
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
return true
|
|
}
|
|
if p, err := filepath.EvalSymlinks(exe); err == nil {
|
|
exe = p
|
|
}
|
|
// .../Jean.app/Contents/MacOS/jean
|
|
if strings.HasSuffix(filepath.Dir(exe), "/Contents/MacOS") {
|
|
fixFinderPath()
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// appWarning signale une situation de lancement qui casse Jean de façon peu
|
|
// évidente. Aujourd'hui : l'App Translocation de Gatekeeper. Une app non signée
|
|
// ouverte depuis Téléchargements est exécutée depuis une copie en LECTURE SEULE
|
|
// sous /private/var/folders/…/AppTranslocation/<uuid>/, à un chemin différent à
|
|
// CHAQUE lancement. Conséquences vécues : plusieurs instances qui se marchent
|
|
// dessus (la seconde trouve le port 8090 occupé et se contente d'ouvrir l'UI de
|
|
// la première, souvent une version périmée), des process fantômes issus de
|
|
// copies précédentes, et une mise à jour en place impossible.
|
|
// Le remède est côté utilisateur : déplacer Jean.app dans /Applications.
|
|
func appWarning() string {
|
|
exe, err := os.Executable()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
if !strings.Contains(exe, "/AppTranslocation/") {
|
|
return ""
|
|
}
|
|
return "AJEAN tourne depuis une copie temporaire en lecture seule (App Translocation de macOS). " +
|
|
"Fermez l'app, déplacez Jean.app dans le dossier Applications, puis rouvrez-la — " +
|
|
"sinon chaque lancement crée une instance séparée et les mises à jour du moteur échouent."
|
|
}
|
|
|
|
// fixFinderPath complète le PATH famélique hérité du Finder. Une app lancée par
|
|
// LaunchServices reçoit /usr/bin:/bin:/usr/sbin:/sbin — pas les dossiers de
|
|
// Homebrew : sans ça, Jean ne voit ni `brew`, ni `cmake`, ni `git`, et la
|
|
// compilation d'un backend échoue alors que les outils sont bien installés.
|
|
func fixFinderPath() {
|
|
extra := []string{
|
|
"/opt/homebrew/bin", "/opt/homebrew/sbin", // Homebrew Apple Silicon
|
|
"/usr/local/bin", "/usr/local/sbin", // Homebrew Intel
|
|
"/opt/local/bin", // MacPorts
|
|
}
|
|
path := os.Getenv("PATH")
|
|
have := map[string]bool{}
|
|
for _, p := range strings.Split(path, ":") {
|
|
have[p] = true
|
|
}
|
|
var add []string
|
|
for _, p := range extra {
|
|
if !have[p] {
|
|
if fi, err := os.Stat(p); err == nil && fi.IsDir() {
|
|
add = append(add, p)
|
|
}
|
|
}
|
|
}
|
|
if len(add) > 0 {
|
|
_ = os.Setenv("PATH", strings.Join(add, ":")+":"+path)
|
|
}
|
|
}
|