mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-12 01:37:06 +02:00
Sélecteur Chat|Code par discussion dans le pied du composeur ; en mode chat, une détection serveur suggère la bascule (puce ignorable, jamais automatique). Conception reprise d'OpenFox (MIT), réécrite en Go — voir NOTICE.md. - Outils fichiers : read (lignes numérotées, borné), grep, glob, et le tracker « lu avant d'écrire » qui refuse write/edit sur un fichier non lu ou modifié depuis la lecture ; edit préserve les fins de ligne CRLF. - Politique d'exécution : commandes catastrophiques refusées (rm -rf /, mkfs, reboot…), chemins bornés au dossier de la discussion en mode code, mutex par fichier. - Critères d'acceptation : contrat posé via l'outil criteria (éditable dans l'UI), passe de vérification indépendante sur contexte isolé — seule habilitée à marquer « passed » — puis corrections plafonnées. - Rôles embarqués (agents/*.md) : builder, planner, verifier, explorer, code-reviewer ; badge de rôle dans le fil. - LSP : gopls / typescript-language-server / pyright (inclus dans l'image), diagnostics injectés dans le retour de write/edit. - Git natif : git_status, git_diff, git_clone (borné à la discussion). - Jobs d'arrière-plan bash_bg/bash_tail (serveur de dev, build long). - Auto-retry : un appel d'outil écrit en texte (default_api:…, <tool_call>…) relance le tour une fois avec consigne corrective. - Outil ask : question à choix rendue en carte à boutons. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.5 KiB
Go
68 lines
2.5 KiB
Go
package loki
|
|
|
|
// code_tracker.go — suivi « lu avant d'écrire » (file-tracker d'OpenFox, réécrit
|
|
// en Go — voir NOTICE.md). Le modèle doit avoir LU un fichier (outil read) avant
|
|
// de le modifier (edit) ou de l'écraser (write sur un fichier existant), et sa
|
|
// lecture doit être plus récente que la dernière modification du fichier sur le
|
|
// disque. Ça bloque les deux corruptions silencieuses classiques :
|
|
// - réécrire un fichier jamais ouvert (le modèle « devine » son contenu) ;
|
|
// - éditer d'après une lecture périmée (le fichier a changé entre-temps —
|
|
// autre outil, job d'arrière-plan, utilisateur).
|
|
//
|
|
// L'état est en mémoire, par discussion : un redémarrage oublie tout, et le
|
|
// modèle relit — c'est le comportement voulu, pas un bug.
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
trackerMu sync.Mutex
|
|
trackerReads = map[string]time.Time{} // conv + chemin → instant de la lecture
|
|
)
|
|
|
|
func trackerKey(path string) string {
|
|
return convEnsureActive() + "\x00" + filepath.Clean(path)
|
|
}
|
|
|
|
// trackerNoteRead enregistre qu'un fichier vient d'être lu (outil read).
|
|
func trackerNoteRead(path string) {
|
|
trackerMu.Lock()
|
|
trackerReads[trackerKey(path)] = time.Now()
|
|
trackerMu.Unlock()
|
|
}
|
|
|
|
// trackerNoteWrite : après une écriture réussie, la version sur disque est celle
|
|
// que le modèle vient de produire — il la « connaît ». Sans cette note, éditer
|
|
// un fichier qu'on vient soi-même d'écrire serait refusé.
|
|
func trackerNoteWrite(path string) {
|
|
trackerNoteRead(path)
|
|
}
|
|
|
|
// trackerCheck vérifie qu'une modification est sûre. forWrite distingue write
|
|
// (autorisé sur un fichier INEXISTANT sans lecture préalable — création) de
|
|
// edit (le fichier doit exister ET avoir été lu).
|
|
// Renvoie "" si c'est bon, sinon le message de refus pour le modèle.
|
|
func trackerCheck(path string, forWrite bool) string {
|
|
fi, statErr := os.Stat(path)
|
|
if statErr != nil {
|
|
if forWrite {
|
|
return "" // création d'un fichier neuf : rien à relire
|
|
}
|
|
return "" // edit sur fichier absent : fileEdit renverra sa propre erreur claire
|
|
}
|
|
trackerMu.Lock()
|
|
readAt, seen := trackerReads[trackerKey(path)]
|
|
trackerMu.Unlock()
|
|
if !seen {
|
|
return "[refusé] " + path + " existe mais tu ne l'as pas lu dans cette discussion. Lis-le d'abord (outil read), puis modifie-le."
|
|
}
|
|
if fi.ModTime().After(readAt) {
|
|
return "[refusé] " + path + " a changé sur le disque depuis ta lecture. Relis-le (outil read) avant de le modifier."
|
|
}
|
|
return ""
|
|
}
|