v0.9.1 : le poste distant est integre a ajean (fini le binaire ajean-remote separe)

- nouvelle sous-commande `ajean remote install|connect|run|status|uninstall|logout`
  (reutilise internal/nodeclient), remplace le binaire cmd/ajean-remote supprime
- le service (Windows/systemd/launchd) lance desormais `ajean remote run`
- UI Postes distants : commande affichee `ajean remote install ...`
- CI release : retrait du cross-build des 6 binaires ajean-remote
This commit is contained in:
nathaninline committed 2026-08-14 09:24:40 +02:00
1 parent 1454dff2a7
commit 88d1e79e80
12 files changed
+97 -98

No files matched your search

-12
View File
@@ -114,18 +114,6 @@ jobs:
GOOS=$os GOARCH=$arch CGO_ENABLED=0 \ GOOS=$os GOARCH=$arch CGO_ENABLED=0 \
go build -trimpath -ldflags="$ldflags" -o "dist/$name" ./cmd/ajean go build -trimpath -ldflags="$ldflags" -o "dist/$name" ./cmd/ajean
done done
# Client léger « poste distant » ajean-remote : pas de CGO (ni UI ni
# systray), donc les 6 cibles se cross-compilent ici, macOS compris.
# Noms d'asset ajean-remote-<os>[-arm][.exe] — la page /download les
# présente à part (« piloter un autre PC »).
for t in linux/amd64:ajean-remote-linux linux/arm64:ajean-remote-linux-arm \
windows/amd64:ajean-remote-windows.exe windows/arm64:ajean-remote-windows-arm.exe \
darwin/amd64:ajean-remote-macos darwin/arm64:ajean-remote-macos-arm; do
target=${t%%:*}; name=${t#*:}
os=${target%/*}; arch=${target#*/}
GOOS=$os GOARCH=$arch CGO_ENABLED=0 \
go build -trimpath -ldflags="-s -w" -o "dist/$name" ./cmd/ajean-remote
done
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v4
with: with:
name: macos name: macos
+12 -8
View File
@@ -1,15 +1,19 @@
Piloter un autre PC fonctionne maintenant à distance, à travers ajean.link, sans que le relais ne voie jamais rien. Le poste distant est maintenant intégré à AJEAN : plus de binaire séparé, plus de téléchargement à part.
## Le poste distant passe par ajean.link, chiffré de bout en bout ## Une seule application
La 0.8.9 a introduit le poste distant, mais uniquement sur le réseau local. Il fonctionne désormais **depuis n'importe où**, via ajean.link — et avec la même exigence que le reste d'ajean.link : le **relais reste aveugle**. Jusqu'ici, piloter un autre PC demandait d'installer un second binaire, « ajean-remote ». C'était une application de plus à télécharger, à suivre et à mettre à jour. On l'a supprimée : tout vit désormais dans **AJEAN**.
Concrètement, l'identité d'un poste n'est plus une clé partagée mais une **paire de clés** qui lui est propre. À l'appairage, le poste scelle sa demande vers la clé publique de ton serveur : le relais ne voit ni le code, ni rien d'autre. Ensuite, tout ce qui circule entre le poste et ton serveur — les commandes de l'IA comme leurs résultats — est **chiffré de bout en bout** avec une clé que seuls ton serveur et ton poste peuvent calculer. Le relais ne transporte que de l'opaque. Sur le PC à piloter, tu installes simplement AJEAN, puis tu lances :
## Rien à changer pour toi ```
ajean remote install https://ajean.link --machine <id> --key <clé> --code <code> --allow shell,read,write,list
```
Dans **Réglages → Postes distants**, générer un code affiche maintenant deux commandes : une pour l'**accès à distance** (via ajean.link) et une pour le **réseau local** (connexion directe). Tu choisis, tu copies, tu colles sur l'autre PC. La commande s'installe en service — invisible, au démarrage, reconnexion automatique — exactement comme avant. Rien ne change au chiffrement : l'accès reste **chiffré de bout en bout**, le relais ajean.link ne voit toujours rien.
## Un client, toujours aussi léger ## Rien à changer dans ton usage
Le petit client s'appelle **ajean-remote** (quelques mégaoctets, aucune interface). Il s'installe en service — invisible, au démarrage, reconnexion automatique — et se télécharge depuis ajean.link, section « Piloter un autre PC ». Dans **Réglages → Postes distants**, générer un code affiche la commande prête à copier — à distance (via ajean.link) ou en réseau local. Seul le nom de la commande change : `ajean remote install …` au lieu de `ajean-remote install …`.
Les postes déjà appairés continuent de fonctionner sans réappairage.
Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -3,13 +3,13 @@
"FileVersion": { "FileVersion": {
"Major": 0, "Major": 0,
"Minor": 9, "Minor": 9,
"Patch": 0, "Patch": 1,
"Build": 0 "Build": 0
}, },
"ProductVersion": { "ProductVersion": {
"Major": 0, "Major": 0,
"Minor": 9, "Minor": 9,
"Patch": 0, "Patch": 1,
"Build": 0 "Build": 0
}, },
"FileFlagsMask": "3f", "FileFlagsMask": "3f",
@@ -25,7 +25,7 @@
"LegalCopyright": "Copyright (c) 2026 AJEAN contributors. MIT License.", "LegalCopyright": "Copyright (c) 2026 AJEAN contributors. MIT License.",
"OriginalFilename": "ajean.exe", "OriginalFilename": "ajean.exe",
"ProductName": "AJEAN", "ProductName": "AJEAN",
"ProductVersion": "0.9.0", "ProductVersion": "0.9.1",
"Comments": "https://github.com/nathaninline/ajean — projet open source (MIT)" "Comments": "https://github.com/nathaninline/ajean — projet open source (MIT)"
}, },
"VarFileInfo": { "VarFileInfo": {
@@ -1,13 +1,17 @@
// ajean-remote — client LÉGER « poste distant ». Binaire séparé et minuscule // Sous-commande « ajean remote » — client « poste distant » intégré au binaire
// (protocole partagé + WebSocket, sans UI ni moteur) : on l'installe sur un PC // principal. On l'installe sur un PC pour que l'IA d'un serveur AJEAN puisse agir
// pour que l'IA d'un serveur AJEAN puisse agir dessus. // dessus (shell/fichiers), chiffré de bout en bout via ajean.link (relais aveugle)
// ou en direct sur le réseau local.
// //
// ajean-remote install <url-serveur> --code CODE [--allow shell,read,write,list] [--root DIR] // ajean remote install <url-serveur> --machine ID --key CLÉ --code CODE [--allow shell,read,write,list] [--root DIR]
// appaire ce PC et l'installe en service (démarrage auto) // appaire ce PC et l'installe en service (démarrage auto)
// ajean-remote connect <url> --code CODE [...] même chose mais en avant-plan (test) // ajean remote connect <url> ... idem mais en avant-plan (test)
// ajean-remote run boucle client (utilisé par le service) // ajean remote run boucle client (utilisé par le service)
// ajean-remote status | uninstall | logout // ajean remote status | uninstall | logout
package main //
// Historiquement un binaire séparé « ajean-remote » ; fusionné dans ce binaire
// pour n'avoir qu'une seule application.
package ajean
import ( import (
"context" "context"
@@ -19,65 +23,64 @@ import (
"github.com/nathaninline/ajean/internal/nodeclient" "github.com/nathaninline/ajean/internal/nodeclient"
) )
func main() { func cmdRemote(args []string) error {
args := os.Args[1:] sub := ""
cmd := ""
if len(args) > 0 { if len(args) > 0 {
cmd = args[0] sub = args[0]
args = args[1:] args = args[1:]
} }
var err error switch sub {
switch cmd {
case "install": case "install":
err = doConnect(args, true) return remoteConnect(args, true)
case "connect": case "connect":
err = doConnect(args, false) return remoteConnect(args, false)
case "run": case "run":
err = doRun() return remoteRun()
case "uninstall": case "uninstall":
err = nodeclient.Uninstall() if err := nodeclient.Uninstall(); err != nil {
if err == nil { return err
fmt.Println("[ok] service retiré")
} }
fmt.Println("[ok] service retiré")
return nil
case "logout": case "logout":
_ = nodeclient.Uninstall() _ = nodeclient.Uninstall()
err = os.Remove(nodeclient.ConfigPath()) err := os.Remove(nodeclient.ConfigPath())
if err == nil || os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
err = nil return err
fmt.Println("[ok] configuration oubliée")
} }
fmt.Println("[ok] configuration oubliée")
return nil
case "status": case "status":
err = doStatus() return remoteStatus()
default: default:
usage() remoteUsage()
} return nil
if err != nil {
fmt.Fprintln(os.Stderr, "[err]", err)
os.Exit(1)
} }
} }
func usage() { func remoteUsage() {
fmt.Print(`ajean-remote — client léger « poste distant » pour AJEAN fmt.Print(`ajean remote — piloter CE PC depuis l'IA d'un serveur AJEAN
ajean-remote install <url-serveur> --code CODE [options] appaire + installe en service (démarrage auto, invisible) ajean remote install <url-serveur> --code CODE [options] appaire + installe en service (démarrage auto, invisible)
ajean-remote connect <url-serveur> --code CODE [options] idem en avant-plan (pour tester) ajean remote connect <url-serveur> --code CODE [options] idem en avant-plan (pour tester)
ajean-remote status état de la configuration ajean remote status état de la configuration
ajean-remote uninstall retire le service (garde la config) ajean remote uninstall retire le service (garde la config)
ajean-remote logout retire le service ET oublie la clé ajean remote logout retire le service ET oublie la clé
Options : Options :
--code CODE code d'appairage (généré dans l'UI AJEAN → Postes distants) --machine ID machine à joindre via ajean.link (fournie par l'UI → Postes distants)
--allow LISTE capacités acceptées : shell,read,write,list (défaut : ce que le serveur autorise) --key CLÉ clé publique de l'agent (le poste scelle vers elle)
--root DIR dossier autorisé (confine lecture/écriture) --code CODE code d'appairage (10 min, généré dans l'UI AJEAN → Postes distants)
--yes auto-approuve les actions (obligatoire pour le service, sans terminal) --allow LISTE capacités acceptées : shell,read,write,list (défaut : ce que le serveur autorise)
--root DIR dossier autorisé (confine lecture/écriture)
--yes auto-approuve les actions (obligatoire pour le service, sans terminal)
`) `)
} }
// doConnect appaire au besoin, sauvegarde, puis installe (service) ou lance // remoteConnect appaire au besoin, sauvegarde, puis installe (service) ou lance
// (avant-plan) selon install. // (avant-plan) selon install.
func doConnect(args []string, install bool) error { func remoteConnect(args []string, install bool) error {
f := parseFlags(args) f := parseRemoteFlags(args)
cfg, lerr := nodeclient.LoadConfig() cfg, lerr := nodeclient.LoadConfig()
needEnroll := lerr != nil || cfg.Priv == "" needEnroll := lerr != nil || cfg.Priv == ""
if f.url != "" { if f.url != "" {
@@ -91,7 +94,7 @@ func doConnect(args []string, install bool) error {
} }
if needEnroll { if needEnroll {
if cfg.ServerURL == "" { if cfg.ServerURL == "" {
return fmt.Errorf("url du serveur requise (ex: http://192.168.1.127:8090)") return fmt.Errorf("url du serveur requise (ex: https://ajean.link)")
} }
if f.code == "" { if f.code == "" {
return fmt.Errorf("code d'appairage requis : --code CODE") return fmt.Errorf("code d'appairage requis : --code CODE")
@@ -104,17 +107,16 @@ func doConnect(args []string, install bool) error {
} }
fmt.Printf("[ok] appairé (id %s)\n", cfg.ID) fmt.Printf("[ok] appairé (id %s)\n", cfg.ID)
} }
allow, root, yes := f.allow, f.root, f.yes if len(f.allow) > 0 {
if len(allow) > 0 { cfg.Caps = nodeclient.SanitizeCaps(f.allow)
cfg.Caps = nodeclient.SanitizeCaps(allow)
} }
if root != "" { if f.root != "" {
cfg.Root = root cfg.Root = f.root
} }
if cfg.Root == "" { if cfg.Root == "" {
cfg.Root = nodeclient.DataDir() + string(os.PathSeparator) + "workspace" cfg.Root = nodeclient.DataDir() + string(os.PathSeparator) + "workspace"
} }
if yes || install { if f.yes || install {
cfg.AutoYes = true // un service n'a pas de terminal pour confirmer cfg.AutoYes = true // un service n'a pas de terminal pour confirmer
} }
if cfg.Name == "" { if cfg.Name == "" {
@@ -137,15 +139,15 @@ func doConnect(args []string, install bool) error {
return nil return nil
} }
func doRun() error { func remoteRun() error {
cfg, err := nodeclient.LoadConfig() cfg, err := nodeclient.LoadConfig()
if err != nil { if err != nil {
return fmt.Errorf("aucune configuration — lance d'abord « ajean-remote install … »") return fmt.Errorf("aucune configuration — lance d'abord « ajean remote install … »")
} }
return nodeclient.RunService(cfg) return nodeclient.RunService(cfg)
} }
func doStatus() error { func remoteStatus() error {
cfg, err := nodeclient.LoadConfig() cfg, err := nodeclient.LoadConfig()
if err != nil { if err != nil {
fmt.Println("aucun poste configuré") fmt.Println("aucun poste configuré")
@@ -160,14 +162,14 @@ func doStatus() error {
return nil return nil
} }
type flags struct { type remoteFlags struct {
url, code, root, key, machine string url, code, root, key, machine string
allow []string allow []string
yes bool yes bool
} }
func parseFlags(args []string) flags { func parseRemoteFlags(args []string) remoteFlags {
var f flags var f remoteFlags
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
a := args[i] a := args[i]
next := func() string { next := func() string {
+9 -4
View File
@@ -10,7 +10,7 @@ import (
"strings" "strings"
) )
const Version = "0.9.0" const Version = "0.9.1"
// Main est le vrai main() du binaire (cmd/ajean ne fait que l'appeler). // Main est le vrai main() du binaire (cmd/ajean ne fait que l'appeler).
func Main() { func Main() {
@@ -74,6 +74,8 @@ func Main() {
mustExit(cmdWeb(args)) mustExit(cmdWeb(args))
case "link": case "link":
mustExit(cmdLink(args)) mustExit(cmdLink(args))
case "remote":
mustExit(cmdRemote(args))
case "ui": case "ui":
mustExit(cmdUI(args)) mustExit(cmdUI(args))
case "oai": case "oai":
@@ -158,9 +160,12 @@ Accès distant (ajean.link) :
link code code d'appairage (10 min, usage unique) pour le portail link code code d'appairage (10 min, usage unique) pour le portail
link status | logout état du jeton / l'oublier link status | logout état du jeton / l'oublier
Poste distant (piloter un autre PC depuis l'IA) : Poste distant (piloter CE PC depuis l'IA d'un serveur AJEAN) :
le poste s'installe avec le binaire LÉGER séparé « ajean-remote » (cmd/ajean-remote), remote install <url> --machine ID --key CLÉ --code CODE [--allow shell,read,write,list]
pas avec ce binaire : ajean-remote install <url-serveur> --code CODE appaire ce PC + installe le service (démarrage auto)
remote connect <url> … idem en avant-plan (pour tester)
remote status | uninstall | logout
(commande d'appairage prête à copier : UI web → Postes distants)
Backend llama.cpp : Backend llama.cpp :
llamacpp install clone + compile llama.cpp (CUDA/ROCm/Metal/CPU), pointe BIN dessus llamacpp install clone + compile llama.cpp (CUDA/ROCm/Metal/CPU), pointe BIN dessus
+4 -4
View File
@@ -1303,7 +1303,7 @@ button:hover{border-color:var(--dim);color:var(--text)}
</div> </div>
</div> </div>
<div id="node-block" class="gated-group"> <div id="node-block" class="gated-group">
<div class="subhead">Postes distants<span id="node-badge" class="sbadge"></span><span class="help" tabindex="0" onclick="event.preventDefault();event.stopPropagation();this.classList.toggle('open')">?<span class="tip">Pilote un <b>autre PC</b> depuis l'IA. installe le petit client <b>ajean-remote</b> sur le PC secondaire et lance <code>ajean-remote install &lt;url&gt; --code CODE</code> : il se connecte en sortant (aucun port à ouvrir) et expose à l'IA un jeu d'outils restreint (shell, fichiers). ⚠ tu décides des capacités et du dossier autorisé pour chaque poste ; le poste peut aussi demander confirmation localement.</span></span></div> <div class="subhead">Postes distants<span id="node-badge" class="sbadge"></span><span class="help" tabindex="0" onclick="event.preventDefault();event.stopPropagation();this.classList.toggle('open')">?<span class="tip">Pilote un <b>autre PC</b> depuis l'IA. installe <b>ajean</b> sur le PC secondaire et lance <code>ajean remote install &lt;url&gt; --code CODE</code> : il se connecte en sortant (aucun port à ouvrir) et expose à l'IA un jeu d'outils restreint (shell, fichiers). ⚠ tu décides des capacités et du dossier autorisé pour chaque poste ; le poste peut aussi demander confirmation localement.</span></span></div>
<div class="slist"> <div class="slist">
<div class="rowbody"> <div class="rowbody">
<div id="node-list" class="mcp-list"><div class="muted" style="font-size:12px">(aucun poste — appaire un PC pour que l'IA puisse agir dessus)</div></div> <div id="node-list" class="mcp-list"><div class="muted" style="font-size:12px">(aucun poste — appaire un PC pour que l'IA puisse agir dessus)</div></div>
@@ -1723,7 +1723,7 @@ button:hover{border-color:var(--dim);color:var(--text)}
<div class="subhead" style="margin-top:6px">Code d'appairage</div> <div class="subhead" style="margin-top:6px">Code d'appairage</div>
<div class="node-code" id="node-pair-code">——</div> <div class="node-code" id="node-pair-code">——</div>
<div class="muted" style="font-size:12px;line-height:1.5"> <div class="muted" style="font-size:12px;line-height:1.5">
Sur le PC à piloter, installe <b>ajean-remote</b> (ajean.link/download) puis lance — <b>accès à distance</b>, chiffré de bout en bout : Sur le PC à piloter, installe <b>ajean</b> (ajean.link/download) puis lance — <b>accès à distance</b>, chiffré de bout en bout :
<pre class="node-cmd" id="node-pair-cmd"></pre> <pre class="node-cmd" id="node-pair-cmd"></pre>
<span style="opacity:.8">Ou en <b>réseau local</b> (connexion directe) :</span> <span style="opacity:.8">Ou en <b>réseau local</b> (connexion directe) :</span>
<pre class="node-cmd" id="node-pair-cmd-lan"></pre> <pre class="node-cmd" id="node-pair-cmd-lan"></pre>
@@ -5509,10 +5509,10 @@ async function genNodeCode(){
// Commande d'accès À DISTANCE (partout) via ajean.link : chiffrée de bout en // Commande d'accès À DISTANCE (partout) via ajean.link : chiffrée de bout en
// bout, le relais reste aveugle. --key = clé publique de l'agent (le poste // bout, le relais reste aveugle. --key = clé publique de l'agent (le poste
// scelle vers elle), --machine = quelle machine joindre. // scelle vers elle), --machine = quelle machine joindre.
const remote = 'ajean-remote install https://ajean.link --machine '+r.machine+ const remote = 'ajean remote install https://ajean.link --machine '+r.machine+
' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg; ' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg;
// Variante RÉSEAU LOCAL (connexion directe, sans passer par le relais). // Variante RÉSEAU LOCAL (connexion directe, sans passer par le relais).
const lan = 'ajean-remote install '+location.origin+ const lan = 'ajean remote install '+location.origin+
' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg; ' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg;
document.getElementById('node-pair-cmd').textContent = remote; document.getElementById('node-pair-cmd').textContent = remote;
const lanEl = document.getElementById('node-pair-cmd-lan'); const lanEl = document.getElementById('node-pair-cmd-lan');
+2 -2
View File
@@ -147,7 +147,7 @@
</div> </div>
</div> </div>
<div id="node-block" class="gated-group"> <div id="node-block" class="gated-group">
<div class="subhead">Postes distants<span id="node-badge" class="sbadge"></span><span class="help" tabindex="0" onclick="event.preventDefault();event.stopPropagation();this.classList.toggle('open')">?<span class="tip">Pilote un <b>autre PC</b> depuis l'IA. installe le petit client <b>ajean-remote</b> sur le PC secondaire et lance <code>ajean-remote install &lt;url&gt; --code CODE</code> : il se connecte en sortant (aucun port à ouvrir) et expose à l'IA un jeu d'outils restreint (shell, fichiers). ⚠ tu décides des capacités et du dossier autorisé pour chaque poste ; le poste peut aussi demander confirmation localement.</span></span></div> <div class="subhead">Postes distants<span id="node-badge" class="sbadge"></span><span class="help" tabindex="0" onclick="event.preventDefault();event.stopPropagation();this.classList.toggle('open')">?<span class="tip">Pilote un <b>autre PC</b> depuis l'IA. installe <b>ajean</b> sur le PC secondaire et lance <code>ajean remote install &lt;url&gt; --code CODE</code> : il se connecte en sortant (aucun port à ouvrir) et expose à l'IA un jeu d'outils restreint (shell, fichiers). ⚠ tu décides des capacités et du dossier autorisé pour chaque poste ; le poste peut aussi demander confirmation localement.</span></span></div>
<div class="slist"> <div class="slist">
<div class="rowbody"> <div class="rowbody">
<div id="node-list" class="mcp-list"><div class="muted" style="font-size:12px">(aucun poste — appaire un PC pour que l'IA puisse agir dessus)</div></div> <div id="node-list" class="mcp-list"><div class="muted" style="font-size:12px">(aucun poste — appaire un PC pour que l'IA puisse agir dessus)</div></div>
@@ -567,7 +567,7 @@
<div class="subhead" style="margin-top:6px">Code d'appairage</div> <div class="subhead" style="margin-top:6px">Code d'appairage</div>
<div class="node-code" id="node-pair-code">——</div> <div class="node-code" id="node-pair-code">——</div>
<div class="muted" style="font-size:12px;line-height:1.5"> <div class="muted" style="font-size:12px;line-height:1.5">
Sur le PC à piloter, installe <b>ajean-remote</b> (ajean.link/download) puis lance — <b>accès à distance</b>, chiffré de bout en bout : Sur le PC à piloter, installe <b>ajean</b> (ajean.link/download) puis lance — <b>accès à distance</b>, chiffré de bout en bout :
<pre class="node-cmd" id="node-pair-cmd"></pre> <pre class="node-cmd" id="node-pair-cmd"></pre>
<span style="opacity:.8">Ou en <b>réseau local</b> (connexion directe) :</span> <span style="opacity:.8">Ou en <b>réseau local</b> (connexion directe) :</span>
<pre class="node-cmd" id="node-pair-cmd-lan"></pre> <pre class="node-cmd" id="node-pair-cmd-lan"></pre>
+2 -2
View File
@@ -115,10 +115,10 @@ async function genNodeCode(){
// Commande d'accès À DISTANCE (partout) via ajean.link : chiffrée de bout en // Commande d'accès À DISTANCE (partout) via ajean.link : chiffrée de bout en
// bout, le relais reste aveugle. --key = clé publique de l'agent (le poste // bout, le relais reste aveugle. --key = clé publique de l'agent (le poste
// scelle vers elle), --machine = quelle machine joindre. // scelle vers elle), --machine = quelle machine joindre.
const remote = 'ajean-remote install https://ajean.link --machine '+r.machine+ const remote = 'ajean remote install https://ajean.link --machine '+r.machine+
' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg; ' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg;
// Variante RÉSEAU LOCAL (connexion directe, sans passer par le relais). // Variante RÉSEAU LOCAL (connexion directe, sans passer par le relais).
const lan = 'ajean-remote install '+location.origin+ const lan = 'ajean remote install '+location.origin+
' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg; ' --key '+r.agent_pub+' --code '+r.code+' --allow '+allow+rootArg;
document.getElementById('node-pair-cmd').textContent = remote; document.getElementById('node-pair-cmd').textContent = remote;
const lanEl = document.getElementById('node-pair-cmd-lan'); const lanEl = document.getElementById('node-pair-cmd-lan');
+3 -3
View File
@@ -40,7 +40,7 @@ func Install() error {
case "darwin": case "darwin":
return installLaunchd(dst) 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 « ajean remote connect » via ton propre gestionnaire de démarrage", runtime.GOOS)
} }
func Uninstall() error { func Uninstall() error {
@@ -58,7 +58,7 @@ func Uninstall() error {
func installSystemd(exe string) error { func installSystemd(exe string) error {
unit := "[Unit]\nDescription=AJEAN poste distant\nAfter=network-online.target\n\n" + unit := "[Unit]\nDescription=AJEAN poste distant\nAfter=network-online.target\n\n" +
"[Service]\nExecStart=" + exe + " run\nRestart=always\nRestartSec=5\n\n" + "[Service]\nExecStart=" + exe + " remote run\nRestart=always\nRestartSec=5\n\n" +
"[Install]\nWantedBy=default.target\n" "[Install]\nWantedBy=default.target\n"
dir := filepath.Join(os.Getenv("HOME"), ".config/systemd/user") dir := filepath.Join(os.Getenv("HOME"), ".config/systemd/user")
if err := os.MkdirAll(dir, 0o755); err != nil { if err := os.MkdirAll(dir, 0o755); err != nil {
@@ -79,7 +79,7 @@ func installLaunchd(exe string) error {
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict> <plist version="1.0"><dict>
<key>Label</key><string>link.ajean.remote</string> <key>Label</key><string>link.ajean.remote</string>
<key>ProgramArguments</key><array><string>` + exe + `</string><string>run</string></array> <key>ProgramArguments</key><array><string>` + exe + `</string><string>remote</string><string>run</string></array>
<key>RunAtLoad</key><true/> <key>RunAtLoad</key><true/>
<key>KeepAlive</key><true/> <key>KeepAlive</key><true/>
</dict></plist> </dict></plist>
+2 -2
View File
@@ -73,13 +73,13 @@ func Install() error {
defer m.Disconnect() defer m.Disconnect()
if s, err := m.OpenService(serviceName); err == nil { if s, err := m.OpenService(serviceName); err == nil {
s.Close() s.Close()
return fmt.Errorf("service déjà installé — « ajean-remote uninstall » d'abord") return fmt.Errorf("service déjà installé — « ajean remote uninstall » d'abord")
} }
s, err := m.CreateService(serviceName, dst, mgr.Config{ s, err := m.CreateService(serviceName, dst, mgr.Config{
StartType: mgr.StartAutomatic, StartType: mgr.StartAutomatic,
DisplayName: "AJEAN — poste distant", DisplayName: "AJEAN — poste distant",
Description: "Pont léger permettant à votre serveur IA AJEAN d'agir sur ce PC.", Description: "Pont léger permettant à votre serveur IA AJEAN d'agir sur ce PC.",
}, "run") }, "remote", "run")
if err != nil { if err != nil {
return fmt.Errorf("création du service: %w", err) return fmt.Errorf("création du service: %w", err)
} }