Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions webview-ui/src/components/settings/ApiOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,30 @@ const ApiOptions = ({
}))
: []

return availableModels
}, [selectedProvider, organizationAllowList, selectedModelId])
const modelOptions = [...availableModels]

// Include the currently selected model if it's been removed
if (selectedModelId && !modelOptions.find((opt) => opt.value === selectedModelId)) {
modelOptions.unshift({
value: selectedModelId,
label: `${selectedModelId} (${t("settings:providers.modelUnavailable")})`,
})
}

return modelOptions
}, [selectedProvider, organizationAllowList, selectedModelId, t])

const onProviderChange = useCallback(
(value: ProviderName) => {
// Check if the current model is removed (not in the filtered models list)
const currentProviderModels = MODELS_BY_PROVIDER[selectedProvider]
const isModelRemoved =
selectedModelId &&
currentProviderModels &&
!Object.keys(
filterModels(currentProviderModels, selectedProvider, organizationAllowList) || {},
).includes(selectedModelId)

setApiConfigurationField("apiProvider", value)

// It would be much easier to have a single attribute that stores
Expand All @@ -301,9 +320,7 @@ const ApiOptions = ({
// in case we haven't set a default value for a provider
if (!defaultValue) return

// only set default if no model is set, but don't reset invalid models
// let users see and decide what to do with invalid model selections
const shouldSetDefault = !modelId
const shouldSetDefault = !modelId || isModelRemoved

if (shouldSetDefault) {
setApiConfigurationField(field, defaultValue, false)
Expand Down Expand Up @@ -368,7 +385,7 @@ const ApiOptions = ({
)
}
},
[setApiConfigurationField, apiConfiguration],
[setApiConfigurationField, apiConfiguration, selectedProvider, selectedModelId, organizationAllowList],
)

const modelValidationError = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,4 +563,48 @@ describe("ApiOptions", () => {
expect(screen.queryByTestId("litellm-provider")).not.toBeInTheDocument()
})
})

describe("Removed model handling", () => {
it("renders without errors when a removed model is selected", () => {
// This test verifies that the component handles removed models gracefully
// by still rendering the UI without crashing
const mockSetApiConfigurationField = vi.fn()

renderApiOptions({
apiConfiguration: {
apiProvider: "anthropic",
apiModelId: "claude-2.1", // A model that might be removed
},
setApiConfigurationField: mockSetApiConfigurationField,
})

// Verify the component rendered successfully
expect(screen.getByTestId("provider-select")).toBeInTheDocument()

// The component should render even with a potentially removed model
// The actual model validation and fallback is handled by the API
})

it("allows provider switching even with a removed model", () => {
const mockSetApiConfigurationField = vi.fn()

renderApiOptions({
apiConfiguration: {
apiProvider: "anthropic",
apiModelId: "claude-2.1", // A model that might be removed
},
setApiConfigurationField: mockSetApiConfigurationField,
})

// Find and change the provider select
const providerSelect = screen.getByTestId("provider-select").querySelector("select")
expect(providerSelect).toBeInTheDocument()

// Switch to a different provider
fireEvent.change(providerSelect!, { target: { value: "openai" } })

// Verify that the provider change was registered
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("apiProvider", "openai")
})
})
})
4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ca/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/de/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/en/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@
"description": "Save different API configurations to quickly switch between providers and settings.",
"apiProvider": "API Provider",
"model": "Model",
"modelUnavailable": "unavailable",
"nameEmpty": "Name cannot be empty",
"nameExists": "A profile with this name already exists",
"deleteProfile": "Delete Profile",
Expand Down Expand Up @@ -799,7 +800,8 @@
"label": "Model",
"searchPlaceholder": "Search",
"noMatchFound": "No match found",
"useCustomModel": "Use custom: {{modelId}}"
"useCustomModel": "Use custom: {{modelId}}",
"unavailable": "unavailable"
},
"footer": {
"feedback": "If you have any questions or feedback, feel free to open an issue at <githubLink>github.com/RooCodeInc/Roo-Code</githubLink> or join <redditLink>reddit.com/r/RooCode</redditLink> or <discordLink>discord.gg/roocode</discordLink>",
Expand Down
4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/es/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/fr/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/hi/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/id/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/it/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ja/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ko/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/nl/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/pl/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/pt-BR/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/ru/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/tr/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion webview-ui/src/i18n/locales/vi/settings.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading