diff --git a/lib/store/settings.ts b/lib/store/settings.ts index 13de265ae5..4d988f9570 100644 --- a/lib/store/settings.ts +++ b/lib/store/settings.ts @@ -1325,11 +1325,15 @@ export const useSettingsStore = create()( if (models?.length) recoveredVideoModel = models[0].id; } + const llmModels = validLLMProvider + ? (newProvidersConfig[validLLMProvider as ProviderId]?.models ?? []) + : []; const validLLMModel = validLLMProvider - ? validateModel( - state.modelId, - newProvidersConfig[validLLMProvider as ProviderId]?.models ?? [], - ) + ? validateModel(state.modelId, llmModels) || + (newProvidersConfig[validLLMProvider as ProviderId]?.isServerConfigured + ? llmModels[0]?.id + : '') || + '' : ''; const imageModels = IMAGE_PROVIDERS[validImageProvider as ImageProviderId]?.models ?? []; diff --git a/tests/store/settings-server-sync.test.ts b/tests/store/settings-server-sync.test.ts index bc7a1208d3..f3abfda7cd 100644 --- a/tests/store/settings-server-sync.test.ts +++ b/tests/store/settings-server-sync.test.ts @@ -41,6 +41,18 @@ vi.mock('@/lib/ai/providers', () => ({ { id: 'claude-haiku-4-5', name: 'Claude Haiku 4.5' }, ], }, + deepseek: { + id: 'deepseek', + name: 'DeepSeek', + type: 'openai', + defaultBaseUrl: 'https://api.deepseek.com/v1', + requiresApiKey: true, + icon: '/logos/deepseek.svg', + models: [ + { id: 'deepseek-v4-pro', name: 'DeepSeek V4 Pro' }, + { id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash' }, + ], + }, }, })); @@ -506,6 +518,23 @@ describe('fetchServerProviders — provider availability sync', () => { expect(store.getState().modelId).toBe('gpt-4o'); }); + it('selects the server LLM model when provider fallback replaces the default provider', async () => { + const store = await getStore(); + + expect(store.getState().providerId).toBe('openai'); + expect(store.getState().modelId).toBe(''); + + mockServerResponse({ + providers: { + deepseek: { models: ['deepseek-chat'] }, + }, + }); + await store.getState().fetchServerProviders(); + + expect(store.getState().providerId).toBe('deepseek'); + expect(store.getState().modelId).toBe('deepseek-chat'); + }); + // ---- Error handling ---- it('does not modify state when fetch returns non-ok response', async () => {