feat(memory): système de mémoire projet model-agnostic (L14, LOT A+B+C)
Base de connaissance persistante par projet, indépendante de tout modèle/CLU
et de git. Cadrage archi en §14.5 (ARCHITECTURE.md), cycle Archi→Dev→Test.
LOT A — étage 1 (.md, source de vérité)
- domaine: entité Memory (+ MemorySlug, MemoryType, MemoryFrontmatter,
MemoryLink, MemoryIndexEntry), liens [[slug]], index MEMORY.md dérivé
- port MemoryStore + MemoryError, adapter FsMemoryStore (.ideai/memory/)
- application: 7 use cases (Create/Update/List/Get/Delete/ReadIndex/
ResolveLinks), From<MemoryError> for AppError
- app-tauri: commandes + DTO, events MemorySaved/MemoryDeleted
- suppression de la variante morte DomainError::MalformedFrontmatter
LOT B — rappel adaptatif (étage 1)
- port MemoryRecall + MemoryQuery, adapter NaiveMemoryRecall (troncature
au budget de tokens, court-circuit budget-0), use case RecallMemory
LOT C — étage 2 vectoriel (structure complète, zéro dépendance lourde)
- port Embedder + EmbedderError, profils déclaratifs EmbedderProfile/
EmbedderStrategy (embedder.json)
- VectorMemoryRecall (cosinus, cache .ideai/memory/.index/ gitignoré)
- AdaptiveMemoryRecall (bascule pure should_use_vector), défaut none
- HashEmbedder (déterministe, tests), StubEmbedder (onnx/server/api)
Tests: 57 binaires verts, build + clippy --workspace sans warning.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -19,19 +19,22 @@ use application::{
|
||||
OpenTerminal, OrchestratorService, ReadAgentContext, ReferenceProfiles, RenameLayout,
|
||||
ResizeTerminal, SaveProfile, SetActiveLayout, SnapshotRunningAgents,
|
||||
AssignSkillToAgent, CreateSkill, DeleteSkill, UnassignSkillFromAgent, UpdateSkill,
|
||||
CreateMemory, DeleteMemory, GetMemory, ListMemories, ReadMemoryIndex, RecallMemory,
|
||||
ResolveMemoryLinks, UpdateMemory,
|
||||
SyncAgentWithTemplate, TerminalSessions, UpdateAgentContext, UpdateTemplate, WriteToTerminal,
|
||||
};
|
||||
use domain::ports::{
|
||||
AgentContextStore, AgentRuntime, Clock, EventBus, FileSystem, GitPort, IdGenerator,
|
||||
ProcessSpawner, ProfileStore, ProjectStore, PtyPort, SkillStore, TemplateStore,
|
||||
MemoryRecall, MemoryStore, ProcessSpawner, ProfileStore, ProjectStore, PtyPort, SkillStore,
|
||||
TemplateStore,
|
||||
};
|
||||
use domain::{DomainEvent, Project, ProjectId};
|
||||
|
||||
use infrastructure::{
|
||||
ClaudeTranscriptInspector, CliAgentRuntime, FsOrchestratorWatcher, FsProfileStore,
|
||||
FsProjectStore, FsSkillStore, FsTemplateStore, Git2Repository, IdeaiContextStore,
|
||||
LocalFileSystem, LocalProcessSpawner, OrchestratorWatchHandle, PortablePtyAdapter, SystemClock,
|
||||
TokioBroadcastEventBus, UuidGenerator,
|
||||
FsMemoryStore, FsProjectStore, FsSkillStore, FsTemplateStore, Git2Repository, IdeaiContextStore,
|
||||
LocalFileSystem, LocalProcessSpawner, NaiveMemoryRecall, OrchestratorWatchHandle,
|
||||
PortablePtyAdapter, SystemClock, TokioBroadcastEventBus, UuidGenerator,
|
||||
};
|
||||
|
||||
use crate::pty::PtyBridge;
|
||||
@ -172,6 +175,25 @@ pub struct AppState {
|
||||
pub assign_skill: Arc<AssignSkillToAgent>,
|
||||
/// Unassign a skill from an agent.
|
||||
pub unassign_skill: Arc<UnassignSkillFromAgent>,
|
||||
|
||||
// --- Memory (LOT A — §14.5.1) ---
|
||||
/// Create a memory note in the project's store.
|
||||
pub create_memory: Arc<CreateMemory>,
|
||||
/// Replace an existing memory note.
|
||||
pub update_memory: Arc<UpdateMemory>,
|
||||
/// List the project's memory notes.
|
||||
pub list_memories: Arc<ListMemories>,
|
||||
/// Read one memory note by slug.
|
||||
pub get_memory: Arc<GetMemory>,
|
||||
/// Delete a memory note.
|
||||
pub delete_memory: Arc<DeleteMemory>,
|
||||
/// Read the structured `MEMORY.md` index.
|
||||
pub read_memory_index: Arc<ReadMemoryIndex>,
|
||||
/// Resolve a note's outgoing `[[slug]]` links.
|
||||
pub resolve_memory_links: Arc<ResolveMemoryLinks>,
|
||||
/// Recall the most relevant memory entries for a query within a budget
|
||||
/// (LOT B — §14.5.2).
|
||||
pub recall_memory: Arc<RecallMemory>,
|
||||
// --- Orchestrator (§14.3) ---
|
||||
/// Dispatches validated orchestrator requests to the agent/skill use cases.
|
||||
/// Shared by every per-project filesystem watcher.
|
||||
@ -458,6 +480,36 @@ impl AppState {
|
||||
Arc::clone(&events_port),
|
||||
));
|
||||
|
||||
// --- Memory store + use cases (LOT A — §14.5.1) ---
|
||||
// A single FsMemoryStore takes the project root per call (like the skill
|
||||
// store), so one instance serves every open project. The mutating use
|
||||
// cases share the event bus to announce Memory{Saved,Deleted}.
|
||||
let memory_store = Arc::new(FsMemoryStore::new(Arc::clone(&fs_port)));
|
||||
let memory_store_port = Arc::clone(&memory_store) as Arc<dyn MemoryStore>;
|
||||
let create_memory = Arc::new(CreateMemory::new(
|
||||
Arc::clone(&memory_store_port),
|
||||
Arc::clone(&events_port),
|
||||
));
|
||||
let update_memory = Arc::new(UpdateMemory::new(
|
||||
Arc::clone(&memory_store_port),
|
||||
Arc::clone(&events_port),
|
||||
));
|
||||
let list_memories = Arc::new(ListMemories::new(Arc::clone(&memory_store_port)));
|
||||
let get_memory = Arc::new(GetMemory::new(Arc::clone(&memory_store_port)));
|
||||
let delete_memory = Arc::new(DeleteMemory::new(
|
||||
Arc::clone(&memory_store_port),
|
||||
Arc::clone(&events_port),
|
||||
));
|
||||
let read_memory_index = Arc::new(ReadMemoryIndex::new(Arc::clone(&memory_store_port)));
|
||||
let resolve_memory_links =
|
||||
Arc::new(ResolveMemoryLinks::new(Arc::clone(&memory_store_port)));
|
||||
// Naïve recall (LOT B): composes the same store, returns index entries in
|
||||
// order, truncated to the token budget. The default, dependency-free
|
||||
// MemoryRecall; substitutable by a VectorMemoryRecall (LOT C).
|
||||
let memory_recall_port =
|
||||
Arc::new(NaiveMemoryRecall::new(Arc::clone(&memory_store_port))) as Arc<dyn MemoryRecall>;
|
||||
let recall_memory = Arc::new(RecallMemory::new(memory_recall_port));
|
||||
|
||||
// --- Orchestrator service (§14.3) ---
|
||||
// Dispatches file-based orchestrator requests through the *same* use cases
|
||||
// the UI drives (IdeA stays the single source of truth for the agent/skill
|
||||
@ -540,6 +592,14 @@ impl AppState {
|
||||
delete_skill,
|
||||
assign_skill,
|
||||
unassign_skill,
|
||||
create_memory,
|
||||
update_memory,
|
||||
list_memories,
|
||||
get_memory,
|
||||
delete_memory,
|
||||
read_memory_index,
|
||||
resolve_memory_links,
|
||||
recall_memory,
|
||||
orchestrator_service,
|
||||
orchestrator_watchers: Mutex::new(HashMap::new()),
|
||||
move_tab,
|
||||
|
||||
Reference in New Issue
Block a user