Les 5 évolutions : plan, auto-critique, RAG, vérif HTML, benchmark

1. Plan-puis-exécute (enhance.make_plan) : les demandes complexes sont
   décomposées en 3-5 étapes (event SSE 'plan', carte PLAN dans le fil,
   meta.plan persisté) ; le plan guide l'agent et le moteur code.
2. Auto-critique « Qualité + » (enhance.self_review, toggle Intelligence) :
   critique éclair puis révision de la réponse (event 'revision').
3. Mémoire long-terme RAG (rag.py) : échanges vectorisés via /api/embed
   (modèle d'embedding auto-détecté), rappel cosinus top-3 inter-sessions
   injecté en contexte, indexation en arrière-plan, élagage à 2000 souvenirs.
4. Vérification HTML (tools.check_html) : références locales cassées et
   balises déséquilibrées ; branchée sur l'auto-vérification des outils ET
   sur le moteur code avec une passe d'auto-correction Aider.
5. Benchmark intégré (bench.py + /api/bench) : 5 épreuves notées /100
   (appel d'outil, code exécuté en sous-processus isolé, consignes, JSON,
   format), streaming SSE, scores stockés ; carte BENCHMARK dans l'UI.

Config : plan_mode / self_review / rag_enabled / embed_model + carte
Intelligence (3 toggles). Client SSE : events plan/revision ; PlanCard.

Tests : heuristique+parsing du plan, révision, index/rappel RAG (exclusion
de la session courante), html_check, bench 100/100 sur modèle simulé,
intégration chat HTTP (event plan + meta persisté), build front.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVay7z3y7q2gEe54ByAE6N
This commit is contained in:
Claude committed 2026-07-07 11:47:46 +00:00
1 parent cf1444f7c0
commit d9be1c4dda
15 files changed
+960 -24

No files matched your search

+80 -1
View File
@@ -89,7 +89,13 @@ export interface Message {
role: "user" | "assistant";
content: string;
model?: string;
meta?: { tools?: ToolCall[]; stats?: MessageStats; thinking?: string } | null;
meta?: {
tools?: ToolCall[];
stats?: MessageStats;
thinking?: string;
plan?: string[];
engine?: string;
} | null;
created_at: number;
}
@@ -105,6 +111,75 @@ export interface AgentConfig {
tools: Record<string, boolean>;
confirm_shell: boolean;
think: boolean;
code_model: string;
plan_mode: boolean;
self_review: boolean;
rag_enabled: boolean;
embed_model: string;
}
// ── Benchmark de modèles ─────────────────────────────────────────────────
export interface BenchDetail {
task: string;
score: number;
detail: string;
}
export interface BenchResult {
score: number;
details: BenchDetail[];
at: number;
}
export async function getBenchScores(): Promise<Record<string, BenchResult>> {
const res = await fetch("/api/bench");
return (await res.json()).scores;
}
/** Lance le benchmark d'un modèle en streamant la progression. */
export async function runBench(
model: string,
onProgress: (task: string, score: number | null, detail?: string) => void
): Promise<BenchResult | null> {
const res = await fetch("/api/bench", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ model }),
});
if (!res.body) return null;
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
let final: BenchResult | null = null;
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const events = buffer.split("\n\n");
buffer = events.pop() ?? "";
for (const block of events) {
let event = "";
let data = "";
for (const line of block.split("\n")) {
if (line.startsWith("event: ")) event = line.slice(7).trim();
else if (line.startsWith("data: ")) data += line.slice(6);
}
if (!data) continue;
try {
const payload = JSON.parse(data);
if (event === "task_start") onProgress(payload.task, null);
else if (event === "task_done")
onProgress(payload.task, payload.score, payload.detail);
else if (event === "done")
final = { score: payload.score, details: payload.details, at: Date.now() / 1000 };
} catch {
/* bloc partiel */
}
}
}
return final;
}
export async function runShell(
@@ -204,6 +279,8 @@ export async function streamChat(
onToolConfirm: (command: string) => void;
onStatus: (msg: string) => void;
onNotice: (msg: string) => void;
onPlan?: (steps: string[]) => void;
onRevision?: (content: string) => void;
onDone: (full: string) => void;
onError: (msg: string) => void;
onAbort?: () => void;
@@ -265,6 +342,8 @@ export async function streamChat(
try {
const payload = JSON.parse(dataLines.join("\n"));
if (event === "token") handlers.onToken(payload.content);
else if (event === "plan") handlers.onPlan?.(payload.steps);
else if (event === "revision") handlers.onRevision?.(payload.content);
else if (event === "thinking") handlers.onThinking(payload.content);
else if (event === "status") handlers.onStatus(payload.message);
else if (event === "notice") handlers.onNotice(payload.message);