mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
Rebaptise AJEAN en Loki (fork, lignée conservée)
- module github.com/R0m1k3/Loki, cmd/loki, internal/loki (package loki) - LOKI_HOME, LOKI_MODEL_DIRS, LOKI_SERVICE, LOKI_DL_CONNS ; /etc/loki ; units loki-engine / loki-ui ; binaire et aide CLI - updateRepo pointe sur R0m1k3/Loki (l'auto-update ne tirera plus les binaires AJEAN amont) Conservé à l'identique : le domaine ajean.link (service de tunnel amont), les littéraux de migration 0.7.x (migrate_07.go), RELEASE_NOTES.md et LICENSE (historique et licence de l'amont). go build/vet/test : verts.
This commit is contained in:
157 files changed
+928
-928
No files matched your search
@@ -1,9 +1,9 @@
|
||||
// Package nodeclient est le CLIENT léger « poste distant ». Il tourne sur un PC
|
||||
// secondaire, s'appaire une fois avec le serveur ajean, puis ouvre une connexion
|
||||
// secondaire, s'appaire une fois avec le serveur loki, puis ouvre une connexion
|
||||
// SORTANTE et exécute — sous contrôle local — les demandes de l'IA.
|
||||
//
|
||||
// Volontairement autonome : dépend seulement de nodewire (protocole partagé,
|
||||
// zéro dépendance) et de coder/websocket. AUCUN import d'ajean → binaire de
|
||||
// zéro dépendance) et de coder/websocket. AUCUN import d'loki → binaire de
|
||||
// quelques Mo, sans UI ni moteur.
|
||||
//
|
||||
// Sécurité côté poste : allowlist locale des capacités, confinement des fichiers
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
|
||||
"github.com/coder/websocket"
|
||||
"github.com/coder/websocket/wsjson"
|
||||
"github.com/nathaninline/ajean/internal/nodewire"
|
||||
"github.com/R0m1k3/Loki/internal/nodewire"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -69,20 +69,20 @@ func (c Config) baseURL() string {
|
||||
}
|
||||
|
||||
// dataDir est le dossier de données du poste. Sur Windows : C:\ProgramData\
|
||||
// ajean-remote — MACHINE-WIDE, pour que le service (qui tourne en LocalSystem) lise
|
||||
// loki-remote — MACHINE-WIDE, pour que le service (qui tourne en LocalSystem) lise
|
||||
// la MÊME config que celle écrite par `install` (le profil utilisateur de
|
||||
// LocalSystem est différent du tien). Ailleurs : dossier de config utilisateur.
|
||||
func dataDir() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
if pd := os.Getenv("ProgramData"); pd != "" {
|
||||
return filepath.Join(pd, "ajean-remote")
|
||||
return filepath.Join(pd, "loki-remote")
|
||||
}
|
||||
}
|
||||
dir, err := os.UserConfigDir()
|
||||
if err != nil || dir == "" {
|
||||
dir, _ = os.Getwd()
|
||||
}
|
||||
return filepath.Join(dir, "ajean-remote")
|
||||
return filepath.Join(dir, "loki-remote")
|
||||
}
|
||||
|
||||
// ConfigPath renvoie le chemin du fichier de configuration.
|
||||
@@ -91,7 +91,7 @@ func ConfigPath() string { return filepath.Join(dataDir(), "config.json") }
|
||||
// InstalledExePath est l'emplacement stable où `install` copie le binaire, pour
|
||||
// qu'il survive à la suppression du téléchargement.
|
||||
func InstalledExePath() string {
|
||||
name := "ajean-remote"
|
||||
name := "loki-remote"
|
||||
if runtime.GOOS == "windows" {
|
||||
name += ".exe"
|
||||
}
|
||||
|
||||
@@ -40,16 +40,16 @@ func Install() error {
|
||||
case "darwin":
|
||||
return installLaunchd(dst)
|
||||
}
|
||||
return fmt.Errorf("installation auto non gérée sur %s — lance « ajean remote connect » via ton propre gestionnaire de démarrage", runtime.GOOS)
|
||||
return fmt.Errorf("installation auto non gérée sur %s — lance « loki remote connect » via ton propre gestionnaire de démarrage", runtime.GOOS)
|
||||
}
|
||||
|
||||
func Uninstall() error {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
_ = exec.Command("systemctl", "--user", "disable", "--now", "ajean-remote.service").Run()
|
||||
return os.Remove(filepath.Join(os.Getenv("HOME"), ".config/systemd/user/ajean-remote.service"))
|
||||
_ = exec.Command("systemctl", "--user", "disable", "--now", "loki-remote.service").Run()
|
||||
return os.Remove(filepath.Join(os.Getenv("HOME"), ".config/systemd/user/loki-remote.service"))
|
||||
case "darwin":
|
||||
p := filepath.Join(os.Getenv("HOME"), "Library/LaunchAgents/link.ajean.remote.plist")
|
||||
p := filepath.Join(os.Getenv("HOME"), "Library/LaunchAgents/link.loki.remote.plist")
|
||||
_ = exec.Command("launchctl", "unload", p).Run()
|
||||
return os.Remove(p)
|
||||
}
|
||||
@@ -57,18 +57,18 @@ func Uninstall() error {
|
||||
}
|
||||
|
||||
func installSystemd(exe string) error {
|
||||
unit := "[Unit]\nDescription=AJEAN poste distant\nAfter=network-online.target\n\n" +
|
||||
unit := "[Unit]\nDescription=Loki poste distant\nAfter=network-online.target\n\n" +
|
||||
"[Service]\nExecStart=" + exe + " remote run\nRestart=always\nRestartSec=5\n\n" +
|
||||
"[Install]\nWantedBy=default.target\n"
|
||||
dir := filepath.Join(os.Getenv("HOME"), ".config/systemd/user")
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "ajean-remote.service"), []byte(unit), 0o644); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(dir, "loki-remote.service"), []byte(unit), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = exec.Command("systemctl", "--user", "daemon-reload").Run()
|
||||
if err := exec.Command("systemctl", "--user", "enable", "--now", "ajean-remote.service").Run(); err != nil {
|
||||
if err := exec.Command("systemctl", "--user", "enable", "--now", "loki-remote.service").Run(); err != nil {
|
||||
return fmt.Errorf("systemctl --user enable: %w (astuce : « loginctl enable-linger %s » pour survivre à la déconnexion)", err, os.Getenv("USER"))
|
||||
}
|
||||
return nil
|
||||
@@ -78,7 +78,7 @@ func installLaunchd(exe string) error {
|
||||
plist := `<?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"><dict>
|
||||
<key>Label</key><string>link.ajean.remote</string>
|
||||
<key>Label</key><string>link.loki.remote</string>
|
||||
<key>ProgramArguments</key><array><string>` + exe + `</string><string>remote</string><string>run</string></array>
|
||||
<key>RunAtLoad</key><true/>
|
||||
<key>KeepAlive</key><true/>
|
||||
@@ -88,7 +88,7 @@ func installLaunchd(exe string) error {
|
||||
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
p := filepath.Join(dir, "link.ajean.remote.plist")
|
||||
p := filepath.Join(dir, "link.loki.remote.plist")
|
||||
if err := os.WriteFile(p, []byte(plist), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func copyFile(src, dst string) error {
|
||||
// Ré-installation : Linux refuse d'ÉCRASER l'image d'un binaire en cours
|
||||
// (ETXTBSY « text file busy ») mais autorise à le DÉLIER — le service vivant
|
||||
// garde son inode ouvert, et le nouveau fichier prend la place du nom. Sans ce
|
||||
// unlink, « ajean remote install » relancé échouait tant que le service tournait.
|
||||
// unlink, « loki remote install » relancé échouait tant que le service tournait.
|
||||
_ = os.Remove(dst)
|
||||
return os.WriteFile(dst, b, 0o755)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"golang.org/x/sys/windows/svc/mgr"
|
||||
)
|
||||
|
||||
const serviceName = "AjeanRemote"
|
||||
const serviceName = "LokiRemote"
|
||||
|
||||
// RunService lance la boucle client : en vrai service Windows si on est démarré
|
||||
// par le gestionnaire de services, sinon en avant-plan (utile pour `run` lancé
|
||||
@@ -61,11 +61,11 @@ func Install() error {
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ré-installation : un service AjeanRemote déjà présent tient ajean-remote.exe
|
||||
// Ré-installation : un service LokiRemote déjà présent tient loki-remote.exe
|
||||
// OUVERT (verrou Windows sur l'image d'un processus en cours) → la copie
|
||||
// échouerait avec « used by another process » et CreateService avec « déjà
|
||||
// installé ». On le retire d'abord (best-effort : absent = rien à faire), ce qui
|
||||
// arrête le service et libère le fichier, rendant « ajean remote install »
|
||||
// arrête le service et libère le fichier, rendant « loki remote install »
|
||||
// ré-exécutable tel quel — sans imposer un « uninstall » manuel préalable.
|
||||
_ = Uninstall()
|
||||
if abs, _ := filepath.Abs(self); abs != dst {
|
||||
@@ -80,8 +80,8 @@ func Install() error {
|
||||
defer m.Disconnect()
|
||||
s, err := m.CreateService(serviceName, dst, mgr.Config{
|
||||
StartType: mgr.StartAutomatic,
|
||||
DisplayName: "AJEAN — poste distant",
|
||||
Description: "Pont léger permettant à votre serveur IA AJEAN d'agir sur ce PC.",
|
||||
DisplayName: "Loki — poste distant",
|
||||
Description: "Pont léger permettant à votre serveur IA Loki d'agir sur ce PC.",
|
||||
}, "remote", "run")
|
||||
if err != nil {
|
||||
return fmt.Errorf("création du service: %w", err)
|
||||
|
||||
Reference in new issue
Block a user