fix(ai+editeur): BUG-046 erreur lisible et vault réel pour l'ajout IA au document; BUG-045 fin de la double scrollbar
BUG-046: 'Ajouter du texte au document courant' échouait avec 'Échec de l'action: [object Object]'. Trois causes corrigées: - continuation de confirmation sans payload -> second Appliquer POSTait sans 'message' (422); le payload d'origine est désormais transmis - detail 422 FastAPI (tableau d'objets) stringifié tel quel -> nouvelle _responseError() qui aplatit en message lisible - prompt documents/dossier muet sur le vault -> le modèle inventait 'vault: test' et append_to_file échouait en silence; build_system_prompt nomme le vault et enjoint les outils d'écriture de l'utiliser exactement BUG-045: double barre de défilement dans l'éditeur Editer (fichiers longs): #editor-body overflow:auto + cm-editor height:100% sous la barre IA -> corps et scroller CodeMirror défilant tous les deux. Flex column, seul le scroller défile; override global .cm-scroller retiré. SW v20. Vérifié: pytest 1038, ruff backend 0, tests frontend AI 84/84, editor-inline 25/25, validate-imports 38 modules; Playwright sur l'instance de test (un seul conteneur scrollable) et flux agent complet append_to_file ok=true sur fichier réel
This commit is contained in:
@@ -191,6 +191,34 @@ async function main() {
|
||||
panel.remove();
|
||||
});
|
||||
|
||||
// ── 4a-bis. BUG-046: readable errors + payload carry-over on confirmation resume ──
|
||||
await test("_responseError flattens FastAPI 422 array details (no [object Object])", async () => {
|
||||
const b = new BooksLM();
|
||||
const resp422 = {
|
||||
status: 422,
|
||||
json: async () => ({ detail: [{ type: "missing", loc: ["body", "message"], msg: "Field required", input: {} }] }),
|
||||
};
|
||||
const err422 = await b._responseError(resp422);
|
||||
assert.equal(err422.message, "Field required", `got "${err422.message}"`);
|
||||
assert.ok(!err422.message.includes("[object Object]"), "must never stringify to [object Object]");
|
||||
|
||||
const respStr = { status: 400, json: async () => ({ detail: "vault invalide" }) };
|
||||
assert.equal((await b._responseError(respStr)).message, "vault invalide");
|
||||
|
||||
const respEmpty = { status: 500, json: async () => { throw new Error("no body"); } };
|
||||
assert.equal((await b._responseError(respEmpty)).message, "HTTP 500");
|
||||
});
|
||||
|
||||
await test("confirmation resume keeps the payload and formats errors (BUG-046)", async () => {
|
||||
const { readFileSync } = await import("node:fs");
|
||||
const src = readFileSync(path.join(JS_DIR, "bookslm.js"), "utf-8");
|
||||
const apply = src.slice(src.indexOf("async _applyConfirmation"));
|
||||
assert.match(apply, /payload:\s*msg\.payload\s*\?\s*\{[^\n]*\.\.\.msg\.payload[^\n]*\}\s*:\s*null/,
|
||||
"continuation must inherit the original request payload (no null payload)");
|
||||
assert.match(apply, /await this\._responseError\(resp\)/,
|
||||
"resume path must format non-OK responses via _responseError");
|
||||
});
|
||||
|
||||
// ── 4b. Notion-style thread: top-anchored latest post, provider/model tag, action bar ──
|
||||
await test("thread renders chronologically (user post above its answer)", () => {
|
||||
const b = new BooksLM();
|
||||
|
||||
Reference in New Issue
Block a user