diff --git a/static/ui.js b/static/ui.js index bef64a22..38ce6810 100644 --- a/static/ui.js +++ b/static/ui.js @@ -563,6 +563,11 @@ async function populateModelDropdown(){ _applyModelToDropdown(data.default_model, sel, data.active_provider||null); } if(typeof syncModelChip==='function') syncModelChip(); + const dd=$('composerModelDropdown'); + if(dd&&dd.classList.contains('open')&&typeof renderModelDropdown==='function'){ + renderModelDropdown(); + _positionModelDropdown(); + } // Kick off a background live-model fetch for the active provider. // This runs after the static list is already shown (no blocking flicker). if(data.active_provider) _fetchLiveModels(data.active_provider, sel); @@ -963,7 +968,7 @@ async function selectModelFromDropdown(value){ if(typeof sel.onchange==='function') await sel.onchange(); } -function toggleModelDropdown(){ +async function toggleModelDropdown(){ const dd=$('composerModelDropdown'); const chip=$('composerModelChip'); const sel=$('modelSelect'); @@ -974,6 +979,11 @@ function toggleModelDropdown(){ if(typeof closeWsDropdown==='function') closeWsDropdown(); if(typeof closeReasoningDropdown==='function') closeReasoningDropdown(); if(typeof closeToolsetsDropdown==='function') closeToolsetsDropdown(); + const ready=window._modelDropdownReady; + if(ready&&typeof ready.then==='function'){ + try{await ready;}catch(_){} + } + if(dd.classList.contains('open')) return; renderModelDropdown(); dd.classList.add('open'); _positionModelDropdown(); diff --git a/tests/test_issue1743_model_picker_race.py b/tests/test_issue1743_model_picker_race.py new file mode 100644 index 00000000..17530de1 --- /dev/null +++ b/tests/test_issue1743_model_picker_race.py @@ -0,0 +1,30 @@ +"""Regression coverage for #1743 model picker async catalog race.""" + +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +UI_JS = (ROOT / "static" / "ui.js").read_text() + + +def _body_between(src: str, start: str, end: str) -> str: + start_idx = src.index(start) + end_idx = src.index(end, start_idx) + return src[start_idx:end_idx] + + +def test_model_picker_open_waits_for_async_model_catalog_before_rendering(): + """Opening the visible picker must not render stale static