feat(memory): config embedders (LOT C2) + suggestion contextuelle (LOT C3) + contexte projet partagé

- LOT C2 (§14.5.3) : use cases de configuration des embedders déclaratifs
  (List/Save/Delete + DescribeEmbedderEngines : modèles ONNX recommandés,
  environnement local détecté, stratégies compilées). UI EmbedderSettings.
- LOT C3 (§14.5.5) : suggestion contextuelle best-effort à l'activation quand la
  mémoire dépasse le budget de recall sans embedder configuré (event
  EmbedderSuggested, anti-spam 1×/session, « ne plus demander »).
- Contexte projet partagé .ideai/CONTEXT.md (model-agnostic) injecté à tous les
  agents/profils au lancement, avant la persona. UI ProjectContextPanel.

Tests : backend workspace vert (0 échec) ; frontend 306/306.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-09 09:24:51 +02:00
parent 32398827fb
commit 785e9935fd
118 changed files with 5793 additions and 866 deletions

View File

@ -224,9 +224,7 @@ fn parse_transcript(body: &[u8]) -> ConversationDetails {
let output = usage.output_tokens.unwrap_or(0);
if input != 0 || output != 0 {
saw_usage = true;
token_total = token_total
.saturating_add(input)
.saturating_add(output);
token_total = token_total.saturating_add(input).saturating_add(output);
}
}
}
@ -345,10 +343,7 @@ mod tests {
#[test]
fn parse_returns_none_when_no_topic_or_usage() {
let body = concat!(
r#"{"role":"assistant","content":"no usage here"}"#,
"\n",
);
let body = concat!(r#"{"role":"assistant","content":"no usage here"}"#, "\n",);
let d = parse_transcript(body.as_bytes());
assert_eq!(d.last_topic, None);
assert_eq!(d.token_count, None);