Skip to content

Commit db71853

Browse files
authored
Move less commonly used provider settings into an advanced dropdown (RooCodeInc#5762)
1 parent 93f88b4 commit db71853

22 files changed

+179
-75
lines changed

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 97 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { memo, useCallback, useEffect, useMemo, useState } from "react"
22
import { convertHeadersToObject } from "./utils/headers"
33
import { useDebounce } from "react-use"
44
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
5+
import { ExternalLinkIcon } from "@radix-ui/react-icons"
56

67
import {
78
type ProviderName,
@@ -31,8 +32,22 @@ import { useAppTranslation } from "@src/i18n/TranslationContext"
3132
import { useRouterModels } from "@src/components/ui/hooks/useRouterModels"
3233
import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel"
3334
import { useExtensionState } from "@src/context/ExtensionStateContext"
35+
import {
36+
useOpenRouterModelProviders,
37+
OPENROUTER_DEFAULT_PROVIDER_NAME,
38+
} from "@src/components/ui/hooks/useOpenRouterModelProviders"
3439
import { filterProviders, filterModels } from "./utils/organizationFilters"
35-
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SearchableSelect } from "@src/components/ui"
40+
import {
41+
Select,
42+
SelectTrigger,
43+
SelectValue,
44+
SelectContent,
45+
SelectItem,
46+
SearchableSelect,
47+
Collapsible,
48+
CollapsibleTrigger,
49+
CollapsibleContent,
50+
} from "@src/components/ui"
3651

3752
import {
3853
Anthropic,
@@ -121,6 +136,7 @@ const ApiOptions = ({
121136
)
122137

123138
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
139+
const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false)
124140

125141
const handleInputChange = useCallback(
126142
<K extends keyof ProviderSettings, E>(
@@ -141,6 +157,14 @@ const ApiOptions = ({
141157

142158
const { data: routerModels, refetch: refetchRouterModels } = useRouterModels()
143159

160+
const { data: openRouterModelProviders } = useOpenRouterModelProviders(apiConfiguration?.openRouterModelId, {
161+
enabled:
162+
!!apiConfiguration?.openRouterModelId &&
163+
routerModels?.openrouter &&
164+
Object.keys(routerModels.openrouter).length > 1 &&
165+
apiConfiguration.openRouterModelId in routerModels.openrouter,
166+
})
167+
144168
// Update `apiModelId` whenever `selectedModelId` changes.
145169
useEffect(() => {
146170
if (selectedModelId) {
@@ -534,30 +558,78 @@ const ApiOptions = ({
534558
/>
535559

536560
{!fromWelcomeView && (
537-
<>
538-
<DiffSettingsControl
539-
diffEnabled={apiConfiguration.diffEnabled}
540-
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
541-
onChange={(field, value) => setApiConfigurationField(field, value)}
542-
/>
543-
<TemperatureControl
544-
value={apiConfiguration.modelTemperature}
545-
onChange={handleInputChange("modelTemperature", noTransform)}
546-
maxValue={2}
547-
/>
548-
<RateLimitSecondsControl
549-
value={apiConfiguration.rateLimitSeconds || 0}
550-
onChange={(value) => setApiConfigurationField("rateLimitSeconds", value)}
551-
/>
552-
<ConsecutiveMistakeLimitControl
553-
value={
554-
apiConfiguration.consecutiveMistakeLimit !== undefined
555-
? apiConfiguration.consecutiveMistakeLimit
556-
: DEFAULT_CONSECUTIVE_MISTAKE_LIMIT
557-
}
558-
onChange={(value) => setApiConfigurationField("consecutiveMistakeLimit", value)}
559-
/>
560-
</>
561+
<Collapsible open={isAdvancedSettingsOpen} onOpenChange={setIsAdvancedSettingsOpen}>
562+
<CollapsibleTrigger className="flex items-center gap-1 w-full cursor-pointer hover:opacity-80 mb-2">
563+
<span className={`codicon codicon-chevron-${isAdvancedSettingsOpen ? "down" : "right"}`}></span>
564+
<span className="font-medium">{t("settings:advancedSettings.title")}</span>
565+
</CollapsibleTrigger>
566+
<CollapsibleContent className="space-y-3">
567+
<DiffSettingsControl
568+
diffEnabled={apiConfiguration.diffEnabled}
569+
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
570+
onChange={(field, value) => setApiConfigurationField(field, value)}
571+
/>
572+
<TemperatureControl
573+
value={apiConfiguration.modelTemperature}
574+
onChange={handleInputChange("modelTemperature", noTransform)}
575+
maxValue={2}
576+
/>
577+
<RateLimitSecondsControl
578+
value={apiConfiguration.rateLimitSeconds || 0}
579+
onChange={(value) => setApiConfigurationField("rateLimitSeconds", value)}
580+
/>
581+
<ConsecutiveMistakeLimitControl
582+
value={
583+
apiConfiguration.consecutiveMistakeLimit !== undefined
584+
? apiConfiguration.consecutiveMistakeLimit
585+
: DEFAULT_CONSECUTIVE_MISTAKE_LIMIT
586+
}
587+
onChange={(value) => setApiConfigurationField("consecutiveMistakeLimit", value)}
588+
/>
589+
{selectedProvider === "openrouter" &&
590+
openRouterModelProviders &&
591+
Object.keys(openRouterModelProviders).length > 0 && (
592+
<div>
593+
<div className="flex items-center gap-1">
594+
<label className="block font-medium mb-1">
595+
{t("settings:providers.openRouter.providerRouting.title")}
596+
</label>
597+
<a href={`https://openrouter.ai/${selectedModelId}/providers`}>
598+
<ExternalLinkIcon className="w-4 h-4" />
599+
</a>
600+
</div>
601+
<Select
602+
value={
603+
apiConfiguration?.openRouterSpecificProvider ||
604+
OPENROUTER_DEFAULT_PROVIDER_NAME
605+
}
606+
onValueChange={(value) =>
607+
setApiConfigurationField("openRouterSpecificProvider", value)
608+
}>
609+
<SelectTrigger className="w-full">
610+
<SelectValue placeholder={t("settings:common.select")} />
611+
</SelectTrigger>
612+
<SelectContent>
613+
<SelectItem value={OPENROUTER_DEFAULT_PROVIDER_NAME}>
614+
{OPENROUTER_DEFAULT_PROVIDER_NAME}
615+
</SelectItem>
616+
{Object.entries(openRouterModelProviders).map(([value, { label }]) => (
617+
<SelectItem key={value} value={value}>
618+
{label}
619+
</SelectItem>
620+
))}
621+
</SelectContent>
622+
</Select>
623+
<div className="text-sm text-vscode-descriptionForeground mt-1">
624+
{t("settings:providers.openRouter.providerRouting.description")}{" "}
625+
<a href="https://openrouter.ai/docs/features/provider-routing">
626+
{t("settings:providers.openRouter.providerRouting.learnMore")}.
627+
</a>
628+
</div>
629+
</div>
630+
)}
631+
</CollapsibleContent>
632+
</Collapsible>
561633
)}
562634
</div>
563635
)

webview-ui/src/components/settings/__tests__/ApiOptions.spec.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ vi.mock("@/components/ui", () => ({
100100
</select>
101101
</div>
102102
),
103+
// Add Collapsible components
104+
Collapsible: ({ children, open }: any) => (
105+
<div className="collapsible-mock" data-open={open}>
106+
{children}
107+
</div>
108+
),
109+
CollapsibleTrigger: ({ children, className, onClick }: any) => (
110+
<div className={`collapsible-trigger-mock ${className || ""}`} onClick={onClick}>
111+
{children}
112+
</div>
113+
),
114+
CollapsibleContent: ({ children, className }: any) => (
115+
<div className={`collapsible-content-mock ${className || ""}`}>{children}</div>
116+
),
103117
}))
104118

105119
vi.mock("../TemperatureControl", () => ({

webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,20 @@ vi.mock("@/components/ui", () => ({
179179
{children}
180180
</button>
181181
),
182+
// Add Collapsible components
183+
Collapsible: ({ children, open }: any) => (
184+
<div className="collapsible-mock" data-open={open}>
185+
{children}
186+
</div>
187+
),
188+
CollapsibleTrigger: ({ children, className, onClick }: any) => (
189+
<div className={`collapsible-trigger-mock ${className || ""}`} onClick={onClick}>
190+
{children}
191+
</div>
192+
),
193+
CollapsibleContent: ({ children, className }: any) => (
194+
<div className={`collapsible-content-mock ${className || ""}`}>{children}</div>
195+
),
182196
}))
183197

184198
// Mock window.postMessage to trigger state hydration

webview-ui/src/components/settings/providers/OpenRouter.tsx

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,14 @@ import { useCallback, useState } from "react"
22
import { Trans } from "react-i18next"
33
import { Checkbox } from "vscrui"
44
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
5-
import { ExternalLinkIcon } from "@radix-ui/react-icons"
65

76
import { type ProviderSettings, type OrganizationAllowList, openRouterDefaultModelId } from "@roo-code/types"
87

98
import type { RouterModels } from "@roo/api"
109

1110
import { useAppTranslation } from "@src/i18n/TranslationContext"
1211
import { getOpenRouterAuthUrl } from "@src/oauth/urls"
13-
import {
14-
useOpenRouterModelProviders,
15-
OPENROUTER_DEFAULT_PROVIDER_NAME,
16-
} from "@src/components/ui/hooks/useOpenRouterModelProviders"
1712
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
18-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@src/components/ui"
1913

2014
import { inputEventTransform, noTransform } from "../transforms"
2115

@@ -37,7 +31,6 @@ export const OpenRouter = ({
3731
apiConfiguration,
3832
setApiConfigurationField,
3933
routerModels,
40-
selectedModelId,
4134
uriScheme,
4235
fromWelcomeView,
4336
organizationAllowList,
@@ -58,14 +51,6 @@ export const OpenRouter = ({
5851
[setApiConfigurationField],
5952
)
6053

61-
const { data: openRouterModelProviders } = useOpenRouterModelProviders(apiConfiguration?.openRouterModelId, {
62-
enabled:
63-
!!apiConfiguration?.openRouterModelId &&
64-
routerModels?.openrouter &&
65-
Object.keys(routerModels.openrouter).length > 1 &&
66-
apiConfiguration.openRouterModelId in routerModels.openrouter,
67-
})
68-
6954
return (
7055
<>
7156
<VSCodeTextField
@@ -139,41 +124,6 @@ export const OpenRouter = ({
139124
organizationAllowList={organizationAllowList}
140125
errorMessage={modelValidationError}
141126
/>
142-
{openRouterModelProviders && Object.keys(openRouterModelProviders).length > 0 && (
143-
<div>
144-
<div className="flex items-center gap-1">
145-
<label className="block font-medium mb-1">
146-
{t("settings:providers.openRouter.providerRouting.title")}
147-
</label>
148-
<a href={`https://openrouter.ai/${selectedModelId}/providers`}>
149-
<ExternalLinkIcon className="w-4 h-4" />
150-
</a>
151-
</div>
152-
<Select
153-
value={apiConfiguration?.openRouterSpecificProvider || OPENROUTER_DEFAULT_PROVIDER_NAME}
154-
onValueChange={(value) => setApiConfigurationField("openRouterSpecificProvider", value)}>
155-
<SelectTrigger className="w-full">
156-
<SelectValue placeholder={t("settings:common.select")} />
157-
</SelectTrigger>
158-
<SelectContent>
159-
<SelectItem value={OPENROUTER_DEFAULT_PROVIDER_NAME}>
160-
{OPENROUTER_DEFAULT_PROVIDER_NAME}
161-
</SelectItem>
162-
{Object.entries(openRouterModelProviders).map(([value, { label }]) => (
163-
<SelectItem key={value} value={value}>
164-
{label}
165-
</SelectItem>
166-
))}
167-
</SelectContent>
168-
</Select>
169-
<div className="text-sm text-vscode-descriptionForeground mt-1">
170-
{t("settings:providers.openRouter.providerRouting.description")}{" "}
171-
<a href="https://openrouter.ai/docs/features/provider-routing">
172-
{t("settings:providers.openRouter.providerRouting.learnMore")}.
173-
</a>
174-
</div>
175-
</div>
176-
)}
177127
</>
178128
)
179129
}

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@
542542
"description": "Quan està habilitat, el terminal hereta les variables d'entorn del procés pare de VSCode, com ara la configuració d'integració del shell definida al perfil d'usuari. Això commuta directament la configuració global de VSCode `terminal.integrated.inheritEnv`. <0>Més informació</0>"
543543
}
544544
},
545+
"advancedSettings": {
546+
"title": "Configuració avançada"
547+
},
545548
"advanced": {
546549
"diff": {
547550
"label": "Habilitar edició mitjançant diffs",

webview-ui/src/i18n/locales/de/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@
542542
"description": "Wenn aktiviert, erbt das Terminal Umgebungsvariablen aus dem übergeordneten Prozess von VSCode, wie z.B. benutzerdefinierte Shell-Integrationseinstellungen. Dies schaltet direkt die globale VSCode-Einstellung `terminal.integrated.inheritEnv` um. <0>Mehr erfahren</0>"
543543
}
544544
},
545+
"advancedSettings": {
546+
"title": "Erweiterte Einstellungen"
547+
},
545548
"advanced": {
546549
"diff": {
547550
"label": "Bearbeitung durch Diffs aktivieren",

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@
542542
"description": "When enabled, the terminal will inherit environment variables from VSCode's parent process, such as user-profile-defined shell integration settings. This directly toggles VSCode global setting `terminal.integrated.inheritEnv`. <0>Learn more</0>"
543543
}
544544
},
545+
"advancedSettings": {
546+
"title": "Advanced settings"
547+
},
545548
"advanced": {
546549
"diff": {
547550
"label": "Enable editing through diffs",

webview-ui/src/i18n/locales/es/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@
542542
"description": "Cuando está habilitado, el terminal hereda las variables de entorno del proceso padre de VSCode, como la configuración de integración del shell definida en el perfil del usuario. Esto alterna directamente la configuración global de VSCode `terminal.integrated.inheritEnv`. <0>Más información</0>"
543543
}
544544
},
545+
"advancedSettings": {
546+
"title": "Configuración avanzada"
547+
},
545548
"advanced": {
546549
"diff": {
547550
"label": "Habilitar edición a través de diffs",

webview-ui/src/i18n/locales/fr/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@
542542
"description": "Lorsqu'activé, le terminal hérite des variables d'environnement du processus parent VSCode, comme les paramètres d'intégration du shell définis dans le profil utilisateur. Cela bascule directement le paramètre global VSCode `terminal.integrated.inheritEnv`. <0>En savoir plus</0>"
543543
}
544544
},
545+
"advancedSettings": {
546+
"title": "Paramètres avancés"
547+
},
545548
"advanced": {
546549
"diff": {
547550
"label": "Activer l'édition via des diffs",

webview-ui/src/i18n/locales/hi/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,9 @@
542542
"description": "सक्षम होने पर, टर्मिनल VSCode के मूल प्रक्रिया से पर्यावरण चर विरासत में लेता है, जैसे उपयोगकर्ता प्रोफ़ाइल में परिभाषित शेल एकीकरण सेटिंग्स। यह VSCode की वैश्विक सेटिंग `terminal.integrated.inheritEnv` को सीधे टॉगल करता है। <0>अधिक जानें</0>"
543543
}
544544
},
545+
"advancedSettings": {
546+
"title": "उन्नत सेटिंग्स"
547+
},
545548
"advanced": {
546549
"diff": {
547550
"label": "diffs के माध्यम से संपादन सक्षम करें",

0 commit comments

Comments
 (0)