From 903e8ecbb07d185044464851708d9f7277fc55ec Mon Sep 17 00:00:00 2001 From: Ibrahim Khan <2005ibrahimkhan@gmail.com> Date: Fri, 26 Jun 2026 09:38:09 -0700 Subject: [PATCH] fix(providers): preserve add-provider form selection on background reload (#1838) loadProviders dropped the __add_provider__ sentinel selection during a background provider refresh because it is not a real provider id, which navigated users out of the in-progress Add provider form and discarded their unsaved input. Preserve the sentinel alongside real provider ids. Fixes #1765 --- packages/ui/src/stores/useConfigStore.test.ts | 19 +++++++++++++++++++ packages/ui/src/stores/useConfigStore.ts | 8 +++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/stores/useConfigStore.test.ts b/packages/ui/src/stores/useConfigStore.test.ts index 5b6c79e1..e587c703 100644 --- a/packages/ui/src/stores/useConfigStore.test.ts +++ b/packages/ui/src/stores/useConfigStore.test.ts @@ -389,6 +389,25 @@ describe('useConfigStore provider persistence', () => { expect(state.currentVariant).toBe('fast'); }); + test('provider reload preserves the add-provider sentinel selection', async () => { + // The user has opened the "Add provider" form, which sets selectedProviderId + // to the sentinel. A background provider refresh must not navigate them away + // (and discard their unsaved input) just because the sentinel is not a real + // provider id. See issue #1765. + useConfigStore.setState({ + activeDirectoryKey: DIRECTORY, + currentProviderId: 'live', + currentModelId: 'live-model', + selectedProviderId: '__add_provider__', + directoryScoped: {}, + }); + + liveProviderId = 'live'; + await useConfigStore.getState().loadProviders({ source: 'test:add-provider' }); + + expect(useConfigStore.getState().selectedProviderId).toBe('__add_provider__'); + }); + test('setAgent applies settings default variant for an agent configured model', () => { useSessionUIStore.setState({ currentSessionId: 'ses_agent_default_variant' }); useConfigStore.setState({ diff --git a/packages/ui/src/stores/useConfigStore.ts b/packages/ui/src/stores/useConfigStore.ts index 246e994b..2563b092 100644 --- a/packages/ui/src/stores/useConfigStore.ts +++ b/packages/ui/src/stores/useConfigStore.ts @@ -30,6 +30,9 @@ const STT_SILENCE_HOLD_MS_MAX = 10000; const FALLBACK_PROVIDER_ID = "opencode"; const FALLBACK_MODEL_ID = "big-pickle"; +// Sentinel selectedProviderId used by the providers UI while the "Add provider" +// form is open. It is intentionally not a real provider id. +const ADD_PROVIDER_SENTINEL = "__add_provider__"; const GIT_UTILITY_PROVIDER_ID = "zen"; const GIT_UTILITY_PREFERRED_MODEL_ID = "big-pickle"; const PROVIDER_CONFIG_REFRESH_CONCURRENCY = 4; @@ -1573,7 +1576,10 @@ export const useConfigStore = create()( const currentSelectedProviderId = state.activeDirectoryKey === directoryKey ? state.selectedProviderId : baseSnapshot.selectedProviderId; - const selectedProviderId = processedProviders.some((provider) => provider.id === currentSelectedProviderId) + // Preserve the add-provider sentinel so a background refresh does not + // navigate the user out of the in-progress add-provider form (issue #1765). + const selectedProviderId = currentSelectedProviderId === ADD_PROVIDER_SENTINEL + || processedProviders.some((provider) => provider.id === currentSelectedProviderId) ? currentSelectedProviderId : (resolvedModel?.providerId ?? processedProviders[0]?.id ?? "");