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>
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
package loki
|
|
|
|
import "testing"
|
|
|
|
// La bascule est persistée par discussion et retombe sur chat par défaut.
|
|
func TestModeParDiscussion(t *testing.T) {
|
|
withWorkspace(t)
|
|
id := convEnsureActive()
|
|
if convCodeMode() {
|
|
t.Fatal("mode code par défaut")
|
|
}
|
|
if err := setConvMode(id, "code"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !convCodeMode() {
|
|
t.Fatal("bascule sans effet")
|
|
}
|
|
dropConvMode(id)
|
|
if convCodeMode() {
|
|
t.Fatal("mode code après nettoyage")
|
|
}
|
|
}
|
|
|
|
// La détection reconnaît une tâche de code, pas la conversation ordinaire.
|
|
func TestDetectionCode(t *testing.T) {
|
|
for _, s := range []string{
|
|
"corrige le bug dans main.go",
|
|
"j'ai une stack trace : Exception in thread",
|
|
"```python\nprint('x')\n```",
|
|
"implémente la fonction de tri",
|
|
"le build casse avec une erreur de compilation",
|
|
} {
|
|
if !looksLikeCode(s) {
|
|
t.Errorf("non détecté : %q", s)
|
|
}
|
|
}
|
|
for _, s := range []string{
|
|
"quelle est la capitale de l'Australie ?",
|
|
"raconte-moi une histoire",
|
|
"quel temps fait-il demain ?",
|
|
"",
|
|
} {
|
|
if looksLikeCode(s) {
|
|
t.Errorf("détecté à tort : %q", s)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Les rôles embarqués existent tous, et le prompt du builder est court —
|
|
// la règle « ne pas regonfler » de baseSystemPrompt s'applique aussi ici.
|
|
func TestRolesEmbarques(t *testing.T) {
|
|
for _, r := range roleNames {
|
|
p := rolePrompt(r)
|
|
if p == "" {
|
|
t.Errorf("rôle %s : prompt vide", r)
|
|
}
|
|
if len(p) > 2500 {
|
|
t.Errorf("rôle %s : prompt trop long (%d octets)", r, len(p))
|
|
}
|
|
}
|
|
if rolePrompt("inexistant") != "" {
|
|
t.Error("rôle inconnu devrait rendre vide")
|
|
}
|
|
}
|
|
|
|
// wantsPlan : demande de plan reconnue, implémentation directe non.
|
|
func TestWantsPlan(t *testing.T) {
|
|
if !wantsPlan("Fais un plan avant de coder") {
|
|
t.Error("plan non reconnu")
|
|
}
|
|
if wantsPlan("corrige le bug maintenant") {
|
|
t.Error("plan détecté à tort")
|
|
}
|
|
}
|