feat: menu + — Mémoire de l'agent — phase 4/8 (v7.54.0)
- Le moteur n'envoie jamais l'historique (system + objectif courant seulement) : chaque run repartait de zéro. Nouveau service app/services/agent_memory.py — une ligne résumé par conversation (table agent_memory, migration 31), écrite en fin de run et ré-injectée au contexte du run suivant. - context_for() : bloc « ## Mémoire de la conversation », budget 4000 car. (troncature gauche + marqueur). remember() : 1 note/échange (180 → 700 car.), 20 notes max, upsert, erreurs journalisées — un run ne peut pas échouer à cause de la mémoire. Toggle OFF = ni lecture ni écriture. - Toggle « Mémoire » dans le menu + : entrée racine à l'état réel (🧠/💭 + libellé), PATCH /api/agent/conversations/{id} avec memory_enabled ajouté au whitelist, état lu à l'ouverture et à la création, défaut AGENT_MEMORY_DEFAULT (settings.agent_memory_default) + memory_enabled dans la réponse de création. - Décision : mémoire d'espace (lignes workspace_id NULL) remise — YAGNI, rien ne l'écrivait ; noté ponytail: dans le service avec le chemin de montée. - Tests : tests/test_v754_memory.py (8) dont 2 runs réels du moteur (FakeLLM capture le prompt : mémoire présente ON / absente OFF) ; test_v751 et test_v753 adaptés (2 sections « bientôt » restantes). Suite complète 1293 verts (-n auto, 2e run ; 1 échec intermittent sur test_v56_import URL au 1er run, vert isolé + vert au run suivant = flake préexistant), ruff 0, eslint 0 problème. OpenAPI 516 chemins / 7.54.0.
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
{key:'plugins', icon:'🧩', label:'Add plugins',
|
||||
sub:'Modules on/off — bientôt (phase 8)', disabled:true},
|
||||
{key:'memory', icon:'🧠', label:'Mémoire (on/off)',
|
||||
sub:'Mémoire persistante — bientôt (phase 4)', disabled:true}
|
||||
sub:'Résumés des échanges injectés à chaque run', action:'memory'}
|
||||
];
|
||||
var FD_PLUS_FILES = [
|
||||
{key:'f-search', icon:'🔍', label:'Rechercher…',
|
||||
@@ -646,7 +646,8 @@
|
||||
if(self.llmModel) body.model = self.llmModel;
|
||||
fetch('/api/agent/conversations', {method:'POST', headers:{'X-CSRF-Token': getCsrf(), 'Content-Type':'application/json'}, body: JSON.stringify(body)})
|
||||
.then(function(r){return r.json()}).then(function(d){
|
||||
var conv = {id:d.id, title:d.title, updated_at:new Date().toISOString()};
|
||||
var conv = {id:d.id, title:d.title, memory_enabled:d.memory_enabled,
|
||||
updated_at:new Date().toISOString()};
|
||||
self.conversations.unshift(conv); self.currentConv = conv;
|
||||
self.messages = []; self.errorMsg=''; self.notice=''; self.tab='chat';
|
||||
self.contextChips = []; self.mentionOpen = false;
|
||||
@@ -663,7 +664,8 @@
|
||||
self._ensuring = fetch('/api/agent/conversations', {
|
||||
method:'POST', headers:{'X-CSRF-Token': getCsrf(), 'Content-Type':'application/json'}, body: JSON.stringify(body)
|
||||
}).then(function(r){return r.json()}).then(function(d){
|
||||
var conv = {id:d.id, title:d.title, updated_at:new Date().toISOString()};
|
||||
var conv = {id:d.id, title:d.title, memory_enabled:d.memory_enabled,
|
||||
updated_at:new Date().toISOString()};
|
||||
self.conversations.unshift(conv); self.currentConv = conv;
|
||||
self.messages = []; self.errorMsg=''; self.notice=''; self.tab='chat';
|
||||
self.contextChips = []; self.mentionOpen = false;
|
||||
@@ -1140,8 +1142,44 @@
|
||||
if(s === 'skills-edit') return []; // formulaire, pas de liste
|
||||
if(s === 'canvases') return this._canvasItems();
|
||||
if(s === 'canvas') return this._canvasActionItems();
|
||||
if(s === 'root'){
|
||||
// l'entrée Mémoire reflète l'état réel du toggle de la conversation
|
||||
var on = this.memoryOn;
|
||||
return FD_PLUS_MENU.map(function(it){
|
||||
if(it.key !== 'memory') return it;
|
||||
return {key:'memory', icon: on ? '🧠' : '💭', label:'Mémoire (on/off)',
|
||||
sub: on ? 'Activée — résumés des échanges injectés à chaque run'
|
||||
: 'Désactivée — contexte strict du run courant',
|
||||
action:'memory'};
|
||||
});
|
||||
}
|
||||
return FD_PLUS_MENU;
|
||||
},
|
||||
// État du toggle mémoire de la conversation courante (défaut : activée).
|
||||
get memoryOn(){
|
||||
if(!this.currentConv) return true;
|
||||
var v = this.currentConv.memory_enabled;
|
||||
return v === undefined || v === null ? true : !!Number(v);
|
||||
},
|
||||
// Bascule le toggle mémoire (PATCH /api/agent/conversations/{id}).
|
||||
toggleMemory(){
|
||||
var self = this, conv = this.currentConv;
|
||||
if(!conv || !conv.id){
|
||||
this.toast('Ouvrez une conversation pour activer la mémoire.', true);
|
||||
return;
|
||||
}
|
||||
var next = this.memoryOn ? 0 : 1;
|
||||
fetch('/api/agent/conversations/' + conv.id, {
|
||||
method: 'PATCH', headers: {'X-CSRF-Token': getCsrf(), 'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({memory_enabled: next})
|
||||
}).then(function(r){ return r.json().then(function(d){ return {ok: r.ok, d: d}; }); })
|
||||
.then(function(res){
|
||||
if(!res.ok){ self.toast((res.d && res.d.detail) || 'Bascule impossible.', true); return; }
|
||||
conv.memory_enabled = next;
|
||||
self.toast(next ? 'Mémoire activée — résumés injectés à chaque run.'
|
||||
: 'Mémoire désactivée — contexte strict du run courant.');
|
||||
}).catch(function(){ self.toast('Bascule impossible (réseau).', true); });
|
||||
},
|
||||
// Sous-menu Compétences : builtin (alias affiché) + installés, puis les 2 actions.
|
||||
_skillsItems(){
|
||||
var out = [];
|
||||
@@ -1319,6 +1357,7 @@
|
||||
this.plusSection = 'browse'; this.plusCrumb = []; this.plusLoadBrowse(null); return;
|
||||
}
|
||||
// ── Compétences (v7.52.0) ──
|
||||
if(it.action === 'memory'){ this.toggleMemory(); return; }
|
||||
if(it.action === 'skills'){ this.plusSection = 'skills'; this.plusFocus = 0; return; }
|
||||
if(it.action === 'skill'){ this.closePlus(); this.useSuggestion(it.suggestion); return; }
|
||||
if(it.action === 'skills-manage'){
|
||||
|
||||
Reference in New Issue
Block a user