feat(memory): clôture du sujet mémoire — bascule adaptative live + panneau UI (§14.5.5)

Pièce 1 (backend) : state.rs câble AdaptiveMemoryRecall via build_memory_recall,
piloté par le profil embedder chargé depuis embedder.json (fallback none). Défaut
none ⇒ NaiveMemoryRecall nu (comportement inchangé, StubEmbedder jamais touché,
zéro dépendance lourde). Instance de recall partagée (RecallMemory + LaunchAgent).
Chargement du profil isolé sur un runtime dédié (évite le block_on imbriqué).

Pièce 2 (frontend) : feature mémoire complète en miroir de skills —
MemoryGateway (port) + TauriMemoryGateway + MockMemoryGateway, types domaine
Memory/MemoryIndexEntry/MemoryType, MemoryPanel/MemoryEditor/useMemory, onglet
sidebar « Memory » dans ProjectsView. CRUD par slug, liens [[slug]] résolus.

Le sujet mémoire est clos : CRUD .md + index + rappel adaptatif + injection à
l'activation des agents + UI de gestion. Embedder concret ONNX/HTTP reste un
follow-up (défaut none = pleinement fonctionnel sans dépendance).

Tests: backend 57 binaires verts, frontend 285 tests verts, typecheck OK.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 13:28:27 +02:00
parent 2435857cbf
commit f3bc3f20d8
16 changed files with 1414 additions and 10 deletions

View File

@ -0,0 +1,71 @@
/**
* Tauri adapter for {@link MemoryGateway} (L14).
*
* Commands use snake_case (Tauri convention); payload keys are camelCase
* (matching the backend DTO `#[serde(rename_all = "camelCase")]`), consistent
* with the other adapters in this directory. Mutating commands that take a
* structured request (`create_memory`, `update_memory`, `recall_memory`) wrap
* their fields under a `request` key; the read commands pass their args flat.
* Identity is the immutable **slug**, so `updateMemory` never sends a name.
*/
import { invoke } from "@tauri-apps/api/core";
import type { Memory, MemoryIndexEntry, MemoryLink, MemoryType } from "@/domain";
import type { CreateMemoryInput, MemoryGateway } from "@/ports";
export class TauriMemoryGateway implements MemoryGateway {
listMemories(projectId: string): Promise<Memory[]> {
return invoke<Memory[]>("list_memories", { projectId });
}
getMemory(projectId: string, slug: string): Promise<Memory> {
return invoke<Memory>("get_memory", { projectId, slug });
}
createMemory(input: CreateMemoryInput): Promise<Memory> {
return invoke<Memory>("create_memory", {
request: {
projectId: input.projectId,
name: input.name,
description: input.description,
type: input.type,
content: input.content,
},
});
}
updateMemory(
projectId: string,
slug: string,
description: string,
type: MemoryType,
content: string,
): Promise<Memory> {
return invoke<Memory>("update_memory", {
request: { projectId, slug, description, type, content },
});
}
async deleteMemory(projectId: string, slug: string): Promise<void> {
await invoke("delete_memory", { projectId, slug });
}
readIndex(projectId: string): Promise<MemoryIndexEntry[]> {
return invoke<MemoryIndexEntry[]>("read_memory_index", { projectId });
}
resolveLinks(projectId: string, slug: string): Promise<MemoryLink[]> {
return invoke<MemoryLink[]>("resolve_memory_links", { projectId, slug });
}
recall(
projectId: string,
text: string,
tokenBudget: number,
): Promise<MemoryIndexEntry[]> {
return invoke<MemoryIndexEntry[]>("recall_memory", {
request: { projectId, text, tokenBudget },
});
}
}