mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-16 19:59:56 +02:00
PROJ_SNAPSHOT était le dernier réglage qui gardait la conversation au Go : la façade la tient désormais dans tous les cas (LOKI_CHAT=go reste la porte de sortie). facadeChatBlocker et la décision prise une fois par processus disparaissent. Go (facade_projsnap.go) : - /internal/v1/turn/view, avec la clé et l'agent : tête du tour portant le bloc figé (ou le vivant à rafraîchir), préambule sans date ni dossier, et la décision projsnap (rafraîchir, mise à jour à poser, instantané à ranger, clé et système du tour) ; dry pour le préchauffage ; - /internal/v1/turn/projsnap/refresh : bloc vivant et instantané qu'il devient, pour une compaction en plein tour. Rust : - ChatService::assemble_turn, partagé par le tour et la relance du builder : instantané rangé avec la discussion, mise à jour posée en tête du dernier message utilisateur (prependCtxUpdate), historique nettoyé au rafraîchissement ; - TurnHost::project_refresh après une compaction ou une réduction en plein tour (replaceProjectHead) ; l'instantané posé devient celui de la discussion ; - le préchauffage demande la vue en dry et garde les mises à jour tant que le bloc n'est pas rafraîchi. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016tcGfJWefW5kUGoC2wL8cv
95 lines
3.2 KiB
Go
95 lines
3.2 KiB
Go
package loki
|
|
|
|
import (
|
|
"net/http"
|
|
)
|
|
|
|
// facade_projsnap.go — PROJ_SNAPSHOT pour le tour tenu par la façade (lot 34
|
|
// de la migration). La façade range l'instantané avec la discussion (il est
|
|
// persisté avec elle, champ proj_snap) et pose les <context_update> dans son
|
|
// historique ; le Go, qui lit le contexte du projet (description, index
|
|
// mémoire, trackers, consignes du dépôt, date et dossier de travail), décide :
|
|
//
|
|
// - /internal/v1/turn/view, avec la clé et l'agent : la tête du tour porte
|
|
// le bloc figé (ou le vivant s'il faut rafraîchir), et projsnap dit quoi
|
|
// faire de la discussion — rafraîchir (instantané neuf, blocs retirés de
|
|
// l'historique) ou poser une mise à jour en tête du dernier message
|
|
// utilisateur. dry : la même décision pour le préchauffage, sans rien
|
|
// rendre à ranger ;
|
|
// - /internal/v1/turn/projsnap/refresh : une compaction ou une réduction
|
|
// réécrit l'historique en plein tour, le bloc vivant remplace le figé et
|
|
// devient l'instantané du tour suivant.
|
|
|
|
// projSnapView : les pièces de turnView avec la clé (assembleTurn, chemin
|
|
// PROJ_SNAPSHOT). snap : l'instantané de la discussion (nil : aucun).
|
|
func projSnapView(caps Caps, snap *projSnapshot, dry bool) map[string]any {
|
|
cfg := ReadConfig()
|
|
// Date et dossier de travail : dans le bloc, plus dans le système.
|
|
caps.envInCtx = true
|
|
asOf := projSnapNow()
|
|
live := projSnapCapture(caps, asOf)
|
|
key := projSnapKey(caps, cfg)
|
|
tools := EnabledTools(caps)
|
|
if tools == nil {
|
|
tools = []Tool{}
|
|
}
|
|
head := []Message{}
|
|
if sp := readSysPrompt(); sp != "" {
|
|
head = append(head, Message{Role: "system", Content: sp})
|
|
}
|
|
sysHash := projSnapSysHash(InjectSkills(append([]Message(nil), head...), caps, tools), tools)
|
|
refresh, delta, tok := projSnapDecide(snap, live, key, sysHash, asOf)
|
|
block := live.msgs
|
|
if !refresh {
|
|
block = snap.Msgs
|
|
}
|
|
out := map[string]any{"refresh": refresh, "key": key, "sys_hash": sysHash}
|
|
if !dry {
|
|
switch {
|
|
case refresh:
|
|
out["snap"] = newProjSnapshot(live, key, sysHash)
|
|
case delta != "":
|
|
// Rangé par la façade seulement si la mise à jour a trouvé un
|
|
// message utilisateur où se poser (projSnapApplyLocked).
|
|
next := *snap
|
|
next.State = live.state
|
|
next.DeltaTok += tok
|
|
out["snap"] = &next
|
|
out["delta"] = delta
|
|
default:
|
|
out["snap"] = snap
|
|
}
|
|
}
|
|
return map[string]any{
|
|
"head": append(head, block...),
|
|
"prefix": injectPrefix(caps, tools),
|
|
"tools": tools,
|
|
"projsnap": out,
|
|
}
|
|
}
|
|
|
|
// handleInternalTurnProjSnapRefresh : POST {"caps","key","sys_hash"} →
|
|
// {"block":[…],"snap":{…}} — le bloc vivant et l'instantané qu'il devient
|
|
// (projSnapTurn.refresh).
|
|
func handleInternalTurnProjSnapRefresh(w http.ResponseWriter, r *http.Request) {
|
|
var in struct {
|
|
Caps Caps `json:"caps"`
|
|
Key string `json:"key"`
|
|
SysHash string `json:"sys_hash"`
|
|
}
|
|
if !readInternalJSON(w, r, &in) {
|
|
return
|
|
}
|
|
caps := in.Caps
|
|
caps.envInCtx = true
|
|
live := projSnapCapture(caps, projSnapNow())
|
|
block := live.msgs
|
|
if block == nil {
|
|
block = []Message{}
|
|
}
|
|
sendJSON(w, http.StatusOK, map[string]any{
|
|
"block": block,
|
|
"snap": newProjSnapshot(live, in.Key, in.SysHash),
|
|
})
|
|
}
|