From 1f01a425eba02384c991a32968075d637071ecd8 Mon Sep 17 00:00:00 2001 From: Indie Sewell Date: Fri, 23 May 2025 22:38:32 +0800 Subject: [PATCH] fix: prevent model selection failures when API requests fail (fixes #3813, #3874) - Use Promise.allSettled instead of Promise.all to handle provider API failures gracefully - Fix model initialization logic in ModelPicker component - Ensures models can be selected even when some provider APIs fail --- src/core/webview/webviewMessageHandler.ts | 8 +++++++- webview-ui/src/components/settings/ModelPicker.tsx | 12 +++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 63c20febf4..6fbd3ae5e4 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -288,7 +288,8 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We case "requestRouterModels": const { apiConfiguration } = await provider.getState() - const [openRouterModels, requestyModels, glamaModels, unboundModels, litellmModels] = await Promise.all([ + // Use Promise.allSettled instead of Promise.all to handle API failures gracefully + const results = await Promise.allSettled([ getModels("openrouter", apiConfiguration.openRouterApiKey), getModels("requesty", apiConfiguration.requestyApiKey), getModels("glama", apiConfiguration.glamaApiKey), @@ -296,6 +297,11 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We getModels("litellm", apiConfiguration.litellmApiKey, apiConfiguration.litellmBaseUrl), ]) + // Extract results, using empty objects for any failed requests + const [openRouterModels, requestyModels, glamaModels, unboundModels, litellmModels] = results.map( + (result) => (result.status === "fulfilled" ? result.value : {}), + ) + provider.postMessageToWebview({ type: "routerModels", routerModels: { diff --git a/webview-ui/src/components/settings/ModelPicker.tsx b/webview-ui/src/components/settings/ModelPicker.tsx index 48dd999e38..9880c99768 100644 --- a/webview-ui/src/components/settings/ModelPicker.tsx +++ b/webview-ui/src/components/settings/ModelPicker.tsx @@ -94,12 +94,14 @@ export const ModelPicker = ({ }, []) useEffect(() => { - if (!selectedModelId && !isInitialized.current) { - const initialValue = modelIds.includes(selectedModelId) ? selectedModelId : defaultModelId - setApiConfigurationField(modelIdKey, initialValue) + if (!isInitialized.current) { + // If no model is selected or the selected model is not in the available models list, + // initialize with the default model + if (!selectedModelId || !modelIds.includes(selectedModelId)) { + setApiConfigurationField(modelIdKey, defaultModelId) + } + isInitialized.current = true } - - isInitialized.current = true }, [modelIds, setApiConfigurationField, modelIdKey, selectedModelId, defaultModelId]) return (