mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-12 01:37:06 +02:00
Deux reprises d'AJEAN autour des tâches planifiées. Dossier de scripts (/data/scripts) : un dossier durable À CÔTÉ de memory, hors du workspace. Le workspace est jetable — supprimer une discussion emporte ses fichiers — donc un script qu'on veut garder n'y avait pas sa place. Le briefing machine l'annonce à l'IA, qui y écrit et y lance ses scripts normalement. Tâche « script seul » (Task.Kind/Script) : le planificateur lance le script sans charger le modèle ni consommer un token, sa sortie devient le compte-rendu, et l'UI l'affiche comme n'importe quelle tâche. Elle tourne hors du verrou de génération — d'où un registre à part pour l'afficher « en cours » et l'arrêter (/api/tasks/stop), et un « tester » qui n'attend ni le verrou ni le moteur. Sélecteur Consigne IA / Script seul dans la modale. Outils task_list/create/update/delete : l'IA se donne elle-même rappels et veilles récurrentes, cloisonnés par projet (dans un projet, elle ne voit et ne pilote que ses tâches). Le budget du préambule passe de 8600 à 11000 caractères, avec le palier documenté dans le test. Dossier mémoire réservé à ses outils : bash, write et edit ne le touchent plus (guardToolOnly*). Un `cat memory/…` contournait l'index MEMORY.md, et c'est la condition d'un chiffrement de la mémoire à venir. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K6CAgoLJzufeA8rZTSpSpY
89 lines
2.9 KiB
Go
89 lines
2.9 KiB
Go
package loki
|
|
|
|
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 (`loki where`) et dans l'UI.
|
|
|
|
type lokiPaths struct {
|
|
Home string `json:"home"` // LOKI_HOME : racine des données
|
|
Database string `json:"database"` // loki.db : config, préférences, conversation, clés
|
|
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"`
|
|
Scripts string `json:"scripts"` // scripts durables de l'agent (hors workspace jetable)
|
|
Presets string `json:"presets"`
|
|
Models string `json:"models"`
|
|
Backends string `json:"backends"`
|
|
}
|
|
|
|
// installedExePath est l'emplacement canonique du binaire après installation.
|
|
// Il diffère par plateforme : sous Unix les installateurs posent /usr/local/bin/loki
|
|
// (c'est ce que référencent les unités systemd et le plist launchd) ; sous Windows,
|
|
// faute d'équivalent, on utilise LOKI_HOME\bin ajouté au PATH utilisateur.
|
|
func installedExePath() string {
|
|
if runtime.GOOS == "windows" {
|
|
return filepath.Join(binDir(), "loki.exe")
|
|
}
|
|
return "/usr/local/bin/loki"
|
|
}
|
|
|
|
func currentPaths() lokiPaths {
|
|
exe, _ := os.Executable()
|
|
if resolved, err := filepath.EvalSymlinks(exe); err == nil {
|
|
exe = resolved
|
|
}
|
|
return lokiPaths{
|
|
Home: LokiHome(),
|
|
Database: dbPath(),
|
|
Exe: exe,
|
|
Installed: installedExePath(),
|
|
Workspace: agentWorkspace(),
|
|
Memory: memoryDir(),
|
|
Scripts: scriptsDir(),
|
|
Presets: presetsDir(),
|
|
Models: modelsDir(),
|
|
Backends: backendsDir(),
|
|
}
|
|
}
|
|
|
|
func cmdWhere(args []string) error {
|
|
p := currentPaths()
|
|
fmt.Printf("Emplacements Loki\n\n")
|
|
for _, row := range [][2]string{
|
|
{"données (LOKI_HOME)", p.Home},
|
|
{"base", p.Database},
|
|
{"binaire en cours", p.Exe},
|
|
{"binaire installé", p.Installed},
|
|
{"travail de l'agent", p.Workspace},
|
|
{"mémoire", p.Memory},
|
|
{"scripts", p.Scripts},
|
|
{"presets", p.Presets},
|
|
{"modèles", p.Models},
|
|
{"backends", p.Backends},
|
|
} {
|
|
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())
|
|
}
|