From 834f8d9aadac321b36230f0a3e26c605761db73c Mon Sep 17 00:00:00 2001 From: KoalaTrapLord <265133236+KoalaTrapLord@users.noreply.github.com> Date: Sun, 22 Mar 2026 01:57:12 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20Meta=20Commander=20picker=20=E2=80=94=20?= =?UTF-8?q?lazy-load,=20live=20search,=20debounce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - showMetaPicker() now guards for no backend with clear message, and lazy-loads commanders on first open (fixes race condition with Promise.all where loadMetaCommanders ran before detectBackend) - filterMetaCommanders() hits live /api/lab/meta/search endpoint when backend is connected, falls back to local array filter - Search input debounced at 250ms to avoid hammering API --- ui/ai-lab.js | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/ui/ai-lab.js b/ui/ai-lab.js index fb8fdf3..384bb87 100644 --- a/ui/ai-lab.js +++ b/ui/ai-lab.js @@ -309,7 +309,7 @@ const AiLab = (() => {
@@ -621,13 +621,31 @@ const AiLab = (() => { } } - function showMetaPicker() { + async function showMetaPicker() { const modal = document.getElementById('lab-meta-modal'); - if (modal) { - modal.classList.add('active'); - renderMetaList(metaCommanders); - document.getElementById('lab-meta-search')?.focus(); + if (!modal) return; + modal.classList.add('active'); + + if (!backendAvailable) { + const listEl = document.getElementById('lab-meta-list'); + if (listEl) { + listEl.innerHTML = ''; + } + return; } + + // Lazy-load: if we haven't fetched commanders yet, do it now + if (metaCommanders.length === 0) { + const listEl = document.getElementById('lab-meta-list'); + if (listEl) listEl.innerHTML = ''; + await loadMetaCommanders(); + } + + renderMetaList(metaCommanders); + document.getElementById('lab-meta-search')?.focus(); } function closeMetaPicker() { @@ -637,11 +655,27 @@ const AiLab = (() => { if (statusEl) statusEl.innerHTML = ''; } - function filterMetaCommanders(query) { + async function filterMetaCommanders(query) { if (!query) { renderMetaList(metaCommanders); return; } + + // When backend is available, use the live search endpoint + if (backendAvailable) { + try { + const res = await fetch(`${API_BASE}/api/lab/meta/search?q=${encodeURIComponent(query)}`); + if (res.ok) { + const data = await res.json(); + renderMetaList(data.results || []); + return; + } + } catch (err) { + console.warn('[AI Lab] Meta search failed, falling back to local filter:', err); + } + } + + // Fallback: local filter const q = query.toLowerCase(); const filtered = metaCommanders.filter(c => c.name.toLowerCase().includes(q)); renderMetaList(filtered);