From feaf9a423e88828a8a85f86538b517b301da6d4e Mon Sep 17 00:00:00 2001 From: Rod Boev Date: Wed, 1 Jul 2026 16:30:34 -0400 Subject: [PATCH] fix(#4737): retry even when the synth fallback is empty --- static/ui.js | 10 ++++- ...st_4737_first_tab_model_catalog_refresh.py | 38 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/static/ui.js b/static/ui.js index 087604a5..7345f48b 100644 --- a/static/ui.js +++ b/static/ui.js @@ -2477,8 +2477,15 @@ async function populateModelDropdown(opts={}){ const groups=usedConfiguredFallback ? _synthGroupsFromConfigured() : data.groups; + const willRetry=usedConfiguredFallback && requestedFreshness!=='session_visit' && !_modelCatalogFallbackRetried; - if(!groups.length) return; // no server groups and no configured fallback + if(!groups.length){ + if(willRetry){ + _modelCatalogFallbackRetried=true; + populateModelDropdown({...opts,freshness:'session_visit'}).catch(()=>{}); + } + return; // no server groups and no configured fallback + } const previousSelection=_captureModelDropdownSelection(sel); // Clear existing options sel.innerHTML=''; @@ -2520,7 +2527,6 @@ 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 && !willRetry) _fetchLiveModels(data.active_provider, sel, requestSeq); diff --git a/tests/test_4737_first_tab_model_catalog_refresh.py b/tests/test_4737_first_tab_model_catalog_refresh.py index 8f69a148..91aeb017 100644 --- a/tests/test_4737_first_tab_model_catalog_refresh.py +++ b/tests/test_4737_first_tab_model_catalog_refresh.py @@ -366,6 +366,44 @@ def test_populate_model_dropdown_retries_at_most_once_even_if_refetch_is_still_e assert payload["optionValues"] == ["claude-sonnet-4"] +def test_populate_model_dropdown_retries_when_synth_fallback_is_empty(driver_path): + payload = _run( + driver_path, + { + "fetchResponses": [ + { + "active_provider": "anthropic", + "default_model": "claude-sonnet-4", + "configured_model_badges": { + "@anthropic:claude-sonnet-4": {"provider": "anthropic"}, + }, + "groups": [], + }, + { + "active_provider": "anthropic", + "default_model": "claude-sonnet-4", + "configured_model_badges": { + "claude-sonnet-4": {"provider": "anthropic"}, + }, + "groups": [ + { + "provider": "Anthropic", + "provider_id": "anthropic", + "models": [ + {"id": "claude-sonnet-4", "label": "Claude Sonnet 4"}, + ], + } + ], + }, + ], + }, + ) + + assert len(payload["fetchCalls"]) == 2 + assert payload["fetchCalls"][1].endswith("freshness=session_visit") + assert payload["optionValues"] == ["claude-sonnet-4"] + + def test_populate_model_dropdown_retry_preserves_custom_redirect_handler(driver_path): payload = _run( driver_path,