mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-24 07:28:13 +02:00
Contexte : PROJ_SNAPSHOT fige le bloc projet par discussion, ses changements arrivent en mise à jour, en opt-in
Le contexte du projet (description, index mémoire, trackers, AGENTS.md) part en tête du premier message utilisateur, reconstruit à chaque tour : une page créée ou une valeur de tracker notée faisait recalculer toute la conversation derrière lui, 10 à 45k tokens. Nouvelle clé PROJ_SNAPSHOT (off par défaut) : avec on, chaque discussion garde une copie datée du bloc, renvoyée à l'octet près, et les changements arrivent en tête du message suivant dans un bloc <context_update from="loki">, rangé dans l'historique. Sans la clé, la requête est identique à l'octet près (testé contre l'ancien assemblage). - en-têtes figés « as of <date> » pour l'index mémoire et les trackers, sans « answer straight from this » ; ligne fixe du système, seulement avec la clé - mises à jour par type : +/~/- par page (clé « ](fichier) »), une ligne complète par tracker (clé = slug), texte COMPLET pour la description, AGENTS.md, ou un index dont la prose a changé — jamais de diff de prose - état annoncé structuré et persisté (ProjSnap, omitempty), instantané pris sur marqueur explicite : la première page d'un projet vide arrive en mise à jour, le premier message ne bouge pas - rafraîchi (blocs retirés de tout l'historique) quand le prompt change de toute façon : compaction début/fin/manuelle, compaction ou réduction en cours de tour (bloc vivant aussitôt, rangé comme instantané : pas de recalcul de plus), système ou outils modifiés, redémarrage de Loki, réglage moteur ou modèle, projet, nom, mode mémoire, mode Code, dépôt, textes des en-têtes ; et au-delà d'un seuil de mises à jour accumulées - mise à jour posée sous c.mu avec l'epoch, après la compaction de début de tour ; texte ou multimodal ; retirée du titre, de l'export JSON, de l'entrée du résumeur et de la tâche du vérificateur - loadFrom, Reset et le chargement remettent l'instantané à zéro ; clé retirée = nettoyage ; agent off = rien du projet ; tâches et presets externes inchangés ; un sous-agent ne voit pas le bloc du tour - ordre des trackers déjà déterministe (lot 1, test existant) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7c9aa04fd9
commit
4932999d5c
13 files changed
+1444
-49
No files matched your search
+36
-11
@@ -498,23 +498,48 @@ const trackerIndexPrefix = "Trackers (tracker tool)"
|
||||
// la dernière valeur — SANS appeler l'outil : elle ne l'appelle que pour fouiller
|
||||
// l'historique ou pour modifier. Quelques lignes, jamais le contenu.
|
||||
func trackerIndexMessage() (Message, bool) {
|
||||
if memMode() != MemAlways {
|
||||
list, ok := trackerIndexList()
|
||||
if !ok {
|
||||
return Message{}, false
|
||||
}
|
||||
return renderTrackerIndex(list, ""), true
|
||||
}
|
||||
|
||||
// trackerIndexList : les trackers à annoncer, ok=false hors mode mémoire
|
||||
// proactif ou s'il n'y en a aucun. Séparé du rendu pour le bloc figé
|
||||
// (chat_projsnap.go), qui en tire aussi son état ligne à ligne.
|
||||
func trackerIndexList() ([]trackerMeta, bool) {
|
||||
if memMode() != MemAlways {
|
||||
return nil, false
|
||||
}
|
||||
list := trackerList()
|
||||
if len(list) == 0 {
|
||||
return Message{}, false
|
||||
return list, len(list) > 0
|
||||
}
|
||||
|
||||
// trackerIndexLine : la ligne d'un tracker, « nom — dernière valeur (date) ».
|
||||
func trackerIndexLine(m trackerMeta) string {
|
||||
last := ""
|
||||
if m.last != nil {
|
||||
last = " — " + m.last.Text + " (" + fmtEvent(*m.last) + ")"
|
||||
}
|
||||
return m.Name + last
|
||||
}
|
||||
|
||||
// renderTrackerIndex : le message d'index des trackers. asOf vide = la forme
|
||||
// vivante (texte d'avant PROJ_SNAPSHOT, à l'octet près). Sinon la copie figée :
|
||||
// datée, et sans « réponds directement d'ici », puisque des <context_update>
|
||||
// plus récents peuvent en remplacer des lignes.
|
||||
func renderTrackerIndex(list []trackerMeta, asOf string) Message {
|
||||
var b strings.Builder
|
||||
b.WriteString(trackerIndexPrefix + " — this is the COMPLETE list of your trackers, each with its LATEST point. To say which trackers exist or give a latest value, answer straight from this — do NOT call tracker with no arguments to list them, it would only repeat this. Call tracker(name[, when]) only to look further back in history, or with action \"add\"/\"edit\"/\"delete\" to change data.\n")
|
||||
for _, m := range list {
|
||||
last := ""
|
||||
if m.last != nil {
|
||||
last = " — " + m.last.Text + " (" + fmtEvent(*m.last) + ")"
|
||||
}
|
||||
fmt.Fprintf(&b, "- %s%s\n", m.Name, last)
|
||||
if asOf == "" {
|
||||
b.WriteString(trackerIndexPrefix + " — this is the COMPLETE list of your trackers, each with its LATEST point. To say which trackers exist or give a latest value, answer straight from this — do NOT call tracker with no arguments to list them, it would only repeat this. Call tracker(name[, when]) only to look further back in history, or with action \"add\"/\"edit\"/\"delete\" to change data.\n")
|
||||
} else {
|
||||
b.WriteString(trackerIndexPrefix + " as of " + asOf + trackerFrozenHead)
|
||||
}
|
||||
return Message{Role: "system", Content: strings.TrimRight(b.String(), "\n")}, true
|
||||
for _, m := range list {
|
||||
fmt.Fprintf(&b, "- %s\n", trackerIndexLine(m))
|
||||
}
|
||||
return Message{Role: "system", Content: strings.TrimRight(b.String(), "\n")}
|
||||
}
|
||||
|
||||
// --- outil modèle -------------------------------------------------------------
|
||||
|
||||
Reference in new issue
Block a user