From 0d29dd00fd654b6f64dba3dd7da51db27e26dbf3 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Mon, 7 Sep 2026 13:53:49 -0400 Subject: [PATCH] =?UTF-8?q?fix(bookslm):=20422=20+=20th=C3=A8me=20+=20pick?= =?UTF-8?q?er=20zindex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bug 1 (422): bookslm.js envoie maintenant {message, conversation_history} conformes au backend (au lieu de messages:[...]) - Bug 2 (thème BooksLM): style.css lignes 9015-9061 — suppression de tous les fallbacks hex (--bg, --muted, --text, --surface, --accent, --border) au profit des variables ObsiGate existantes (--bg-primary, --text-primary, --text-secondary, --surface, --surface2, --accent, --border). Ajout de color: var(--text-primary) sur .bookslm-panel - Bug 3 (picker zindex/flex): bookslm-picker-host + ai-picker + .bookslm-header button obtiennent flex-shrink:0 + z-index:1 pour éviter que les selects compressent ou masquent les boutons header (Nouvelle conversation / Exporter / Plein écran / Fermer) - Bug 4 (theme picker): ai.js — var(--bg-tertiary, transparent) → var(--surface), var(--border-color) → var(--border) sur tous les selects, menus et createSeparator. Plus de variables inexistantes. Tests: pytest 504 passed, frontend unit 7/7, validate-imports 30 modules 204 exports, pane-manager 9/9, ruff All checks passed. --- frontend/js/ai.js | 86 +++++++++++++++++++++--------------------- frontend/js/bookslm.js | 12 +++++- frontend/style.css | 49 +++++++++++++----------- 3 files changed, 81 insertions(+), 66 deletions(-) diff --git a/frontend/js/ai.js b/frontend/js/ai.js index 9db5955..aa46b68 100644 --- a/frontend/js/ai.js +++ b/frontend/js/ai.js @@ -68,15 +68,17 @@ async function _buildPickerUI() { const wrap = document.createElement('div'); wrap.className = 'ai-picker'; Object.assign(wrap.style, { - display: 'inline-flex', - alignItems: 'center', - gap: '4px', - marginLeft: '8px', - paddingLeft: '8px', - borderLeft: '1px solid var(--border-color)', - fontSize: '0.7rem', - color: 'var(--text-muted)', - }); + display: 'inline-flex', + alignItems: 'center', + gap: '4px', + marginLeft: '8px', + paddingLeft: '8px', + borderLeft: '1px solid var(--border)', + fontSize: '0.7rem', + color: 'var(--text-muted)', + flexShrink: '0', + zIndex: '1', + }); // Provider select const providerLabel = document.createElement('span'); @@ -86,14 +88,14 @@ async function _buildPickerUI() { const providerSelect = document.createElement('select'); providerSelect.className = 'ai-picker-select'; Object.assign(providerSelect.style, { - fontSize: '0.7rem', - background: 'var(--bg-tertiary, transparent)', - color: 'var(--text-primary)', - border: '1px solid var(--border-color)', - borderRadius: '4px', - padding: '2px 4px', - cursor: 'pointer', - }); + fontSize: '0.7rem', + background: 'var(--surface)', + color: 'var(--text-primary)', + border: '1px solid var(--border)', + borderRadius: '4px', + padding: '2px 4px', + cursor: 'pointer', + }); const defaultOpt = document.createElement('option'); defaultOpt.value = ''; @@ -111,16 +113,16 @@ async function _buildPickerUI() { const modelSelect = document.createElement('select'); modelSelect.className = 'ai-picker-model'; Object.assign(modelSelect.style, { - fontSize: '0.7rem', - background: 'var(--bg-tertiary, transparent)', - color: 'var(--text-primary)', - border: '1px solid var(--border-color)', - borderRadius: '4px', - padding: '2px 4px', - cursor: 'pointer', - minWidth: '120px', - maxWidth: '220px', - }); + fontSize: '0.7rem', + background: 'var(--surface)', + color: 'var(--text-primary)', + border: '1px solid var(--border)', + borderRadius: '4px', + padding: '2px 4px', + cursor: 'pointer', + minWidth: '120px', + maxWidth: '220px', + }); const placeholderOpt = document.createElement('option'); placeholderOpt.value = ''; placeholderOpt.textContent = t('ai.model_default'); @@ -244,12 +246,12 @@ function createMenu(items, parentEl) { const menuLeft = rect.left; Object.assign(menu.style, { - position: 'fixed', - top: menuTop + 'px', - left: menuLeft + 'px', - background: 'var(--bg-primary)', - border: '1px solid var(--border-color)', - borderRadius: '6px', + position: 'fixed', + top: menuTop + 'px', + left: menuLeft + 'px', + background: 'var(--bg-primary)', + border: '1px solid var(--border)', + borderRadius: '6px', padding: '4px 0', minWidth: '200px', maxHeight: '60vh', @@ -336,12 +338,12 @@ function createSubMenu(items, parentEl) { const menu = document.createElement('div'); menu.className = 'ai-submenu'; Object.assign(menu.style, { - position: 'absolute', - left: '100%', - top: '0', - background: 'var(--bg-primary)', - border: '1px solid var(--border-color)', - borderRadius: '6px', + position: 'absolute', + left: '100%', + top: '0', + background: 'var(--bg-primary)', + border: '1px solid var(--border)', + borderRadius: '6px', padding: '4px 0', minWidth: '180px', zIndex: '101', @@ -384,7 +386,7 @@ export async function createAIToolbar(container, getEditorView) { if (!aiConfigured) { const hint = document.createElement('div'); - hint.style.cssText = 'padding:6px 12px;font-size:0.7rem;color:var(--text-muted);border-bottom:1px solid var(--border-color)'; + hint.style.cssText = 'padding:6px 12px;font-size:0.7rem;color:var(--text-muted);border-bottom:1px solid var(--border)'; hint.textContent = t('ai.not_configured'); container.appendChild(hint); return; @@ -397,7 +399,7 @@ export async function createAIToolbar(container, getEditorView) { alignItems: 'center', gap: '2px', padding: '4px 8px', - borderBottom: '1px solid var(--border-color)', + borderBottom: '1px solid var(--border)', background: 'var(--bg-secondary)', flexWrap: 'wrap', position: 'sticky', @@ -623,7 +625,7 @@ function createDropdownBtn(text, items, tooltip = '') { function createSeparator() { const sep = document.createElement('span'); - sep.style.cssText = 'width:1px;height:16px;background:var(--border-color);margin:0 2px'; + sep.style.cssText = 'width:1px;height:16px;background:var(--border);margin:0 2px'; return sep; } diff --git a/frontend/js/bookslm.js b/frontend/js/bookslm.js index 3196888..4039ede 100644 --- a/frontend/js/bookslm.js +++ b/frontend/js/bookslm.js @@ -311,8 +311,16 @@ class BooksLM { body: JSON.stringify({ vault: this._vault, directory: this._directory, - messages: this._messages.slice(0, -1), // exclude empty assistant - context_files: this._contextFiles.map(f => f.path || f), + // The backend expects `message` + `conversation_history`, + // not a generic `messages` array. Convert before sending. + message: this._messages.length + ? this._messages[this._messages.length - 1].content + : '', + conversation_history: this._messages + .slice(0, -1) + .filter((m) => m.content && m.content.trim()) + .map((m) => ({ role: m.role, content: m.content })), + context_files: this._contextFiles.map((f) => f.path || f), provider, model, }), diff --git a/frontend/style.css b/frontend/style.css index 65760a2..c308df7 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -9015,47 +9015,52 @@ body.popup-mode .content-area { /* ── BooksLM Panel ──────────────────────────────────── */ .bookslm-panel { position: fixed; right: 0; top: 0; bottom: 0; width: 450px; - background: var(--bg, #0d0d1a); border-left: 1px solid var(--border, #333); + background: var(--bg-primary); border-left: 1px solid var(--border); z-index: 100; display: flex; flex-direction: column; transform: translateX(100%); transition: transform 300ms ease-out; - box-shadow: -4px 0 20px rgba(0,0,0,0.3); } + box-shadow: -4px 0 20px rgba(0,0,0,0.3); + color: var(--text-primary); } .bookslm-panel.open { transform: translateX(0); } .bookslm-header { display: flex; align-items: center; gap: 8px; - padding: 12px 16px; border-bottom: 1px solid var(--border, #333); + padding: 12px 16px; border-bottom: 1px solid var(--border); font-size: 14px; font-weight: 600; } .bookslm-header .bookslm-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.bookslm-header .bookslm-picker-host, +.bookslm-header .ai-picker, +.bookslm-header button { flex-shrink: 0; } +.bookslm-header .ai-picker { z-index: 1; } .bookslm-header button { background: none; border: none; cursor: pointer; - color: var(--muted, #999); font-size: 16px; padding: 4px 8px; border-radius: 4px; } -.bookslm-header button:hover { background: var(--surface2, #1e1e3a); color: var(--text, #fff); } -.bookslm-status { padding: 6px 16px; font-size: 12px; color: var(--muted, #999); - border-bottom: 1px solid var(--border, #333); display: flex; gap: 12px; align-items: center; } + color: var(--text-secondary); font-size: 16px; padding: 4px 8px; border-radius: 4px; } +.bookslm-header button:hover { background: var(--surface2); color: var(--text-primary); } +.bookslm-status { padding: 6px 16px; font-size: 12px; color: var(--text-secondary); + border-bottom: 1px solid var(--border); display: flex; gap: 12px; align-items: center; } .bookslm-status .bookslm-context-bar { flex: 1; height: 4px; border-radius: 2px; - background: var(--surface2, #1e1e3a); overflow: hidden; } -.bookslm-status .bookslm-context-fill { height: 100%; border-radius: 2px; background: var(--accent, #7C3AED); transition: width 0.3s; } + background: var(--surface2); overflow: hidden; } +.bookslm-status .bookslm-context-fill { height: 100%; border-radius: 2px; background: var(--accent); transition: width 0.3s; } .bookslm-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; } .bookslm-bubble { max-width: 85%; padding: 10px 14px; border-radius: 12px; font-size: 14px; line-height: 1.5; word-wrap: break-word; } -.bookslm-bubble.user { align-self: flex-end; background: var(--accent, #7C3AED); color: #fff; border-bottom-right-radius: 4px; } -.bookslm-bubble.assistant { align-self: flex-start; background: var(--surface2, #1e1e3a); color: var(--text, #fff); border-bottom-left-radius: 4px; } +.bookslm-bubble.user { align-self: flex-end; background: var(--accent); color: #fff; border-bottom-right-radius: 4px; } +.bookslm-bubble.assistant { align-self: flex-start; background: var(--surface2); color: var(--text-primary); border-bottom-left-radius: 4px; } .bookslm-bubble.assistant code { background: rgba(0,0,0,0.2); padding: 1px 4px; border-radius: 3px; font-size: 0.9em; } .bookslm-bubble.assistant pre { background: rgba(0,0,0,0.3); padding: 10px; border-radius: 6px; overflow-x: auto; margin: 8px 0; } .bookslm-sources { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; } .bookslm-source-badge { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; - background: var(--surface, #16162e); border: 1px solid var(--border, #333); border-radius: 12px; - font-size: 11px; color: var(--accent, #7C3AED); cursor: pointer; } -.bookslm-source-badge:hover { background: var(--surface2, #1e1e3a); } -.bookslm-input-area { display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border, #333); align-items: flex-end; } + background: var(--surface); border: 1px solid var(--border); border-radius: 12px; + font-size: 11px; color: var(--accent); cursor: pointer; } +.bookslm-source-badge:hover { background: var(--surface2); } +.bookslm-input-area { display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border); align-items: flex-end; } .bookslm-input-area textarea { flex: 1; resize: none; min-height: 36px; max-height: 120px; - padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border, #333); - background: var(--bg, #0d0d1a); color: var(--text, #fff); font-size: 14px; font-family: inherit; } -.bookslm-input-area textarea:focus { border-color: var(--accent, #7C3AED); outline: none; } + padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border); + background: var(--bg-primary); color: var(--text-primary); font-size: 14px; font-family: inherit; } +.bookslm-input-area textarea:focus { border-color: var(--accent); outline: none; } .bookslm-input-area button { padding: 8px 16px; border-radius: 8px; border: none; - background: var(--accent, #7C3AED); color: #fff; cursor: pointer; font-size: 14px; } + background: var(--accent); color: #fff; cursor: pointer; font-size: 14px; } .bookslm-input-area button:hover { opacity: 0.9; } .bookslm-input-area button:disabled { opacity: 0.5; cursor: not-allowed; } .bookslm-suggestions { display: flex; flex-direction: column; gap: 6px; padding: 8px 16px 0; } -.bookslm-suggestion { padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border, #333); - background: var(--surface, #16162e); color: var(--muted, #999); cursor: pointer; font-size: 13px; text-align: left; } -.bookslm-suggestion:hover { background: var(--surface2, #1e1e3a); color: var(--text, #fff); border-color: var(--accent, #7C3AED); } +.bookslm-suggestion { padding: 8px 12px; border-radius: 8px; border: 1px solid var(--border); + background: var(--surface); color: var(--text-secondary); cursor: pointer; font-size: 13px; text-align: left; } +.bookslm-suggestion:hover { background: var(--surface2); color: var(--text-primary); border-color: var(--accent); } @media (max-width: 768px) { .bookslm-panel { width: 100%; } }