feat(ai): assistant AI multi-contexte + ergonomie sidebar et clavier
CI / lint (push) Successful in 1m12s
CI / security (push) Successful in 43s
CI / test (push) Successful in 1m10s
CI / build (push) Successful in 35s
CI / e2e (push) Successful in 11m47s
Desktop Build / build-windows (push) Canceled after 0s
Desktop Build / build-linux (push) Canceled after 0s

Contexte:
- Repertoire (mode historique BooksLM, via menu contextuel dossier)
- Documents (bouton flottant quand des documents sont ouverts)
- General (bouton flottant sans document: aide app + creation de fichiers)
- Le contexte est affiche dans le header; suggestions adaptees au mode
- Blocs obsigate-action rendus en carte avec bouton Appliquer (pas d'execution auto)

Backend:
- /api/ai/bookslm/context et /chat acceptent mode + context_files
- collect_files_context(), empty_context(), build_general_system_prompt()
- mode documents degrade vers general si aucun fichier lisible

Corrige:
- bouton flottant passait le chemin d'un fichier comme repertoire -> erreur
  'Aucun fichier markdown trouve dans ce dossier'
- panneau precedent masque (localStorage) ne se rouvrait plus
- selecteur fournisseur/modele deplace sur une ligne dediee (header actions visibles)
- Entree envoie, Ctrl+Entree insere un saut de ligne

Tests: test_bookslm.py (+13) et tests/frontend/ai.test.mjs (+8)
This commit is contained in:
2026-09-11 09:11:00 -04:00
parent 62023acd4d
commit d6fdcef4d4
14 changed files with 1049 additions and 214 deletions
+34 -8
View File
@@ -9130,18 +9130,30 @@ body.popup-mode .content-area {
}
.bookslm-btn-toggle:hover { color: var(--accent); background: var(--surface2); }
.bookslm-header { display: flex; align-items: center; gap: 8px;
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; }
padding: 10px 12px; border-bottom: 1px solid var(--border); }
.bookslm-header .bookslm-context-icon { display: flex; color: var(--accent); flex-shrink: 0; }
.bookslm-header-titles { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.bookslm-header-titles .bookslm-title { font-size: 13px; font-weight: 600;
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bookslm-header-titles .bookslm-subtitle { font-size: 11px; color: var(--text-secondary);
overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bookslm-header-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.bookslm-header button { background: none; border: none; cursor: pointer;
color: var(--text-secondary); font-size: 16px; padding: 4px 8px; border-radius: 4px; }
color: var(--text-secondary); padding: 5px; border-radius: 6px; display: flex; align-items: center; }
.bookslm-header button:hover { background: var(--surface2); color: var(--text-primary); }
/* Provider/model picker on its own row so the header actions never get hidden. */
.bookslm-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
padding: 8px 12px; border-bottom: 1px solid var(--border); background: var(--bg-secondary); }
.bookslm-toolbar-label { font-size: 11px; color: var(--text-secondary);
text-transform: uppercase; letter-spacing: .04em; flex-shrink: 0; }
.bookslm-toolbar .ai-picker { margin-left: 0; padding-left: 0; border-left: none;
flex-wrap: wrap; row-gap: 4px; }
.bookslm-toolbar .ai-picker select { max-width: 200px; }
.bookslm-panel.fullscreen { width: 100vw; }
.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-status-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bookslm-status .bookslm-status-error { color: #f87171; }
.bookslm-status .bookslm-context-bar { flex: 1; height: 4px; border-radius: 2px;
background: var(--surface2); overflow: hidden; }
.bookslm-status .bookslm-context-fill { height: 100%; border-radius: 2px; background: var(--accent); transition: width 0.3s; }
@@ -9165,6 +9177,20 @@ body.popup-mode .content-area {
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-input-hint { padding: 0 16px 10px; font-size: 10px; color: var(--text-secondary);
text-align: right; border-top: none; }
/* Action cards proposed by the General assistant (file/dir creation). */
.bookslm-actions { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.bookslm-action { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
border: 1px solid var(--border); border-radius: 8px; background: var(--bg-primary); }
.bookslm-action.done { opacity: 0.65; }
.bookslm-action-meta { flex: 1; display: flex; align-items: center; gap: 6px; font-size: 12px;
color: var(--text-primary); word-break: break-word; }
.bookslm-action-icon { flex-shrink: 0; }
.bookslm-action-apply { padding: 5px 12px; border-radius: 6px; border: none;
background: var(--accent); color: #fff; cursor: pointer; font-size: 12px; flex-shrink: 0; }
.bookslm-action-apply:disabled { opacity: 0.6; cursor: default; }
.bookslm-action-apply:not(:disabled):hover { filter: brightness(1.08); }
.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);
background: var(--surface); color: var(--text-secondary); cursor: pointer; font-size: 13px; text-align: left; }