From 6c7d7b4506779639d1402e5cf5519bfb4def3933 Mon Sep 17 00:00:00 2001 From: Bruno Charest Date: Sat, 30 May 2026 19:57:39 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20hover=20fonc=C3=A9=20+=20/api/ai/status?= =?UTF-8?q?=20+=20cache=20toolbar=20si=20pas=20de=20cl=C3=A9=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/ai_routes.py | 18 +++++++++++++++++- frontend/js/ai.js | 25 ++++++++++++++++++++----- frontend/js/utils.js | 2 +- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/backend/ai_routes.py b/backend/ai_routes.py index 5638d62..a22590a 100644 --- a/backend/ai_routes.py +++ b/backend/ai_routes.py @@ -10,13 +10,29 @@ from backend.ai import ( ai_simplify, ai_change_tone, ai_translate, ai_explain, ai_summarize, ai_continue_writing, ai_custom_rewrite, ai_convert_to_list, ai_convert_to_table, ai_generate_frontmatter, ai_inline_complete, - ai_convert_to_canvas, + ai_convert_to_canvas, DEFAULT_PROVIDER, PROVIDERS, ) logger = logging.getLogger("obsigate.ai_routes") router = APIRouter(prefix="/api/ai", tags=["AI"]) +@router.get("/status") +async def api_status(): + """Check if AI is configured and which providers are available.""" + providers = {} + for name, cfg in PROVIDERS.items(): + providers[name] = { + "available": bool(cfg["api_key"]), + "model": cfg["model"] if cfg["api_key"] else None, + } + return { + "configured": any(p["available"] for p in providers.values()), + "default_provider": DEFAULT_PROVIDER, + "providers": providers, + } + + class AIRequest(BaseModel): text: str = Field(..., description="Input text to process", min_length=1) instruction: Optional[str] = Field(None, description="Custom instruction for rewrite") diff --git a/frontend/js/ai.js b/frontend/js/ai.js index 7b5f2c5..f31bc0f 100644 --- a/frontend/js/ai.js +++ b/frontend/js/ai.js @@ -111,7 +111,7 @@ function createMenu(items, parentEl) { el.appendChild(arrow); } el.addEventListener('mouseenter', () => { - el.style.background = 'var(--bg-secondary)'; + el.style.background = 'rgba(255,255,255,0.06)'; // Show submenu if (item.children) { const sub = el.querySelector('.ai-submenu'); @@ -171,7 +171,7 @@ function createSubMenu(items, parentEl) { whiteSpace: 'nowrap', }); el.innerHTML = item.label; - el.addEventListener('mouseenter', () => { el.style.background = 'var(--bg-secondary)'; }); + el.addEventListener('mouseenter', () => { el.style.background = 'rgba(255,255,255,0.06)'; }); el.addEventListener('mouseleave', () => { el.style.background = ''; }); el.addEventListener('click', (e) => { e.stopPropagation(); @@ -186,7 +186,22 @@ function createSubMenu(items, parentEl) { } // ── Main AI Toolbar ── -export function createAIToolbar(container, getEditorView) { +export async function createAIToolbar(container, getEditorView) { + // Check if AI is configured + let aiConfigured = false; + try { + const status = await api('/api/ai/status'); + aiConfigured = status.configured; + } catch { aiConfigured = false; } + + 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.textContent = '⚠️ AI non configuré — ajouter DEEPSEEK_API_KEY, OPENROUTER_API_KEY ou GEMINI_API_KEY dans .env'; + container.appendChild(hint); + return; + } + const toolbar = document.createElement('div'); toolbar.className = 'ai-toolbar'; Object.assign(toolbar.style, { @@ -195,7 +210,7 @@ export function createAIToolbar(container, getEditorView) { gap: '2px', padding: '4px 8px', borderBottom: '1px solid var(--border-color)', - background: 'var(--bg-secondary)', + background: '#2a2a2a', flexWrap: 'wrap', }); @@ -347,7 +362,7 @@ function createDropdownBtn(text, items) { e.stopPropagation(); createMenu(items, btn); }); - btn.addEventListener('mouseenter', () => { btn.style.background = 'var(--bg-hover)'; }); + btn.addEventListener('mouseenter', () => { btn.style.background = 'rgba(255,255,255,0.08)'; }); btn.addEventListener('mouseleave', () => { btn.style.background = ''; }); return btn; } diff --git a/frontend/js/utils.js b/frontend/js/utils.js index 3b57f5e..795114b 100644 --- a/frontend/js/utils.js +++ b/frontend/js/utils.js @@ -379,7 +379,7 @@ async function openEditor(vaultName, filePath) { // Set up AI toolbar (recreate each time editor opens) const container = document.getElementById('ai-toolbar-container'); - if (container && !container.querySelector('.ai-toolbar')) { + if (container && !container.querySelector('.ai-toolbar') && !container.querySelector('div')) { createAIToolbar(container, () => state.editorView || null); }