Files
Loki/internal/jean/chat_agent.go
T
nathaninline 7b0a5dbf75 v0.6.9 : l'IA écrit enfin les fichiers directement
Nouvel outil write : créer ou réécrire un fichier passe par le disque, plus
par le shell. Sous Windows le shell est cmd.exe et son quoting cassait tout
script contenant des guillemets imbriqués (echo, python -c, base64) ; l'IA
bouclait sans jamais y arriver. Signalé par Arnaud Hocquelet.

L'outil bash annonce désormais le vrai shell de la plateforme (cmd.exe sous
Windows) au lieu de dire bash partout, pour que le modèle arrête de générer
la syntaxe d'un autre shell.

Interface : le contenu d'une écriture se remplit ligne à ligne en direct dans
la bulle (diffusé à la ligne et pas au token, pour ne pas saturer le rendu
mobile), et les compteurs +N -N passent sur l'étiquette pour rester visibles
une fois la bulle repliée.
2026-08-03 15:12:18 +02:00

85 lines
2.4 KiB
Go

package jean
import (
"fmt"
"os"
)
// Le « mode agent » est l'unique interrupteur qui donne à l'IA l'accès à ses
// outils. Quand il est actif, l'IA dispose du shell (run_shell) et de sa
// mémoire (mem_search/mem_read/mem_add/mem_edit) — les anciens « skills » ont
// été fondus dans la mémoire. Plus de drapeaux machine/skills séparés : un seul
// fichier .agent_enabled.
func agentEnabled() bool {
if _, err := os.Stat(agentFlag()); err == nil {
return true
}
// Migration : si l'un des anciens drapeaux séparés traîne encore, on
// considère le mode agent comme actif (et on le matérialise au prochain set).
if _, err := os.Stat(legacyToolsFlag()); err == nil {
return true
}
if _, err := os.Stat(legacySkillsFlag()); err == nil {
return true
}
return false
}
func setAgentEnabled(on bool) error {
_ = os.MkdirAll(JeanHome(), 0o755)
// On nettoie systématiquement les anciens drapeaux pour ne pas garder un
// état fantôme « à moitié activé » hérité de l'ancien modèle à deux toggles.
_ = os.Remove(legacyToolsFlag())
_ = os.Remove(legacySkillsFlag())
if on {
f, err := os.Create(agentFlag())
if err != nil {
return err
}
return f.Close()
}
if err := os.Remove(agentFlag()); err != nil && !os.IsNotExist(err) {
return err
}
return nil
}
func cmdAgent(args []string) error {
sub := ""
if len(args) > 0 {
sub = args[0]
}
switch sub {
case "on":
if err := setAgentEnabled(true); err != nil {
return err
}
fmt.Println(green("[ok]") + " mode agent activé — l'IA dispose du shell complet (" + shellName() + "), de l'écriture de fichiers et de sa mémoire")
case "off":
if err := setAgentEnabled(false); err != nil {
return err
}
fmt.Println(green("[ok]") + " mode agent désactivé")
case "", "status", "list":
state := dim("off")
if agentEnabled() {
state = green("on")
}
fmt.Printf("%s état: %s\n", cyan("Mode agent"), state)
fmt.Printf(" outils : %s (timeout %ds, max %ds) + write/edit + mémoire (mem_search/mem_read/mem_add/mem_edit)\n", shellName(), toolDefaultTimeout, toolMaxTimeout)
mem := MemList()
if len(mem) == 0 {
fmt.Printf(" mémoire : aucune page — crée %s/<nom>.md\n", memoryDir())
return nil
}
fmt.Printf(" mémoire (%s) :\n", memoryDir())
for _, p := range mem {
fmt.Printf(" %s %s\n", bold(p.Name), p.Title)
}
default:
return fmt.Errorf("usage: jean agent [on|off|status]")
}
return nil
}