diff --git a/static/ui.js b/static/ui.js index 77ee373c..087604a5 100644 --- a/static/ui.js +++ b/static/ui.js @@ -2520,10 +2520,11 @@ async function populateModelDropdown(opts={}){ renderModelDropdown(); _positionModelDropdown(); } + const willRetry=usedConfiguredFallback && requestedFreshness!=='session_visit' && !_modelCatalogFallbackRetried; // 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, requestSeq); - if(usedConfiguredFallback && requestedFreshness!=='session_visit' && !_modelCatalogFallbackRetried){ + if(data.active_provider && !willRetry) _fetchLiveModels(data.active_provider, sel, requestSeq); + if(willRetry){ _modelCatalogFallbackRetried=true; populateModelDropdown({...opts,freshness:'session_visit'}).catch(()=>{}); } diff --git a/tests/test_4737_first_tab_model_catalog_refresh.py b/tests/test_4737_first_tab_model_catalog_refresh.py index 87b32ce5..8f69a148 100644 --- a/tests/test_4737_first_tab_model_catalog_refresh.py +++ b/tests/test_4737_first_tab_model_catalog_refresh.py @@ -121,6 +121,7 @@ function buildHarness(currentScenario) { const select = new FakeSelect(); const dropdown = new FakeNode('div'); const fetchCalls = []; + const liveFetchCalls = []; const defaultRedirectCalls = []; const customRedirectCalls = []; const fetchQueue = (currentScenario.fetchResponses || []).map((payload) => buildFetchResponse( @@ -168,18 +169,20 @@ function buildHarness(currentScenario) { return res.status === 401; }; globalThis.console = { warn() {}, debug() {}, log() {} }; - globalThis._fetchLiveModels = () => {}; + globalThis._fetchLiveModels = (provider, sel, requestSeq) => { + liveFetchCalls.push([provider, sel && sel.id ? sel.id : null, requestSeq]); + }; globalThis.fetch = async (url) => { fetchCalls.push(String(url)); if (!fetchQueue.length) throw new Error(`unexpected fetch: ${url}`); return fetchQueue.shift(); }; - return { select, fetchCalls, defaultRedirectCalls, customRedirectCalls }; + return { select, fetchCalls, liveFetchCalls, defaultRedirectCalls, customRedirectCalls }; } async function runScenario(currentScenario) { - const { select, fetchCalls, defaultRedirectCalls, customRedirectCalls } = buildHarness(currentScenario); + const { select, fetchCalls, liveFetchCalls, defaultRedirectCalls, customRedirectCalls } = buildHarness(currentScenario); let _modelDropdownRequestSeq = 0; let _modelCatalogFallbackRetried = false; eval(fnSource); @@ -198,6 +201,7 @@ async function runScenario(currentScenario) { customRedirectCalls, defaultRedirectCalls, fetchCalls, + liveFetchCalls, optionValues: select.options.map((opt) => opt.value), }; } @@ -299,6 +303,7 @@ def test_populate_model_dropdown_refetches_once_when_server_returns_empty_groups assert len(payload["fetchCalls"]) == 2 assert "freshness=session_visit" in payload["fetchCalls"][1] + assert payload["liveFetchCalls"] == [["anthropic", "modelSelect", 2]] assert "claude-opus-4" in payload["optionValues"]