Move less commonly used provider settings into an advanced dropdown (#5762)

This commit is contained in:
Matt Rubens 2025-07-15 19:00:14 -04:00 • committed by GitHub
parent 93f88b45b6
commit db718533c6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 179 additions and 75 deletions

View file

@ -2,6 +2,7 @@ import React, { memo, useCallback, useEffect, useMemo, useState } from "react"
import { convertHeadersToObject } from "./utils/headers"
import { useDebounce } from "react-use"
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
import { ExternalLinkIcon } from "@radix-ui/react-icons"
import {
type ProviderName,
@ -31,8 +32,22 @@ import { useAppTranslation } from "@src/i18n/TranslationContext"
import { useRouterModels } from "@src/components/ui/hooks/useRouterModels"
import { useSelectedModel } from "@src/components/ui/hooks/useSelectedModel"
import { useExtensionState } from "@src/context/ExtensionStateContext"
import {
useOpenRouterModelProviders,
OPENROUTER_DEFAULT_PROVIDER_NAME,
} from "@src/components/ui/hooks/useOpenRouterModelProviders"
import { filterProviders, filterModels } from "./utils/organizationFilters"
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SearchableSelect } from "@src/components/ui"
import {
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
SearchableSelect,
Collapsible,
CollapsibleTrigger,
CollapsibleContent,
} from "@src/components/ui"
import {
Anthropic,
@ -121,6 +136,7 @@ const ApiOptions = ({
)
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
const [isAdvancedSettingsOpen, setIsAdvancedSettingsOpen] = useState(false)
const handleInputChange = useCallback(
<K extends keyof ProviderSettings, E>(
@ -141,6 +157,14 @@ const ApiOptions = ({
const { data: routerModels, refetch: refetchRouterModels } = useRouterModels()
const { data: openRouterModelProviders } = useOpenRouterModelProviders(apiConfiguration?.openRouterModelId, {
enabled:
!!apiConfiguration?.openRouterModelId &&
routerModels?.openrouter &&
Object.keys(routerModels.openrouter).length > 1 &&
apiConfiguration.openRouterModelId in routerModels.openrouter,
})
// Update `apiModelId` whenever `selectedModelId` changes.
useEffect(() => {
if (selectedModelId) {
@ -534,30 +558,78 @@ const ApiOptions = ({
/>
{!fromWelcomeView && (
<>
<DiffSettingsControl
diffEnabled={apiConfiguration.diffEnabled}
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
onChange={(field, value) => setApiConfigurationField(field, value)}
/>
<TemperatureControl
value={apiConfiguration.modelTemperature}
onChange={handleInputChange("modelTemperature", noTransform)}
maxValue={2}
/>
<RateLimitSecondsControl
value={apiConfiguration.rateLimitSeconds || 0}
onChange={(value) => setApiConfigurationField("rateLimitSeconds", value)}
/>
<ConsecutiveMistakeLimitControl
value={
apiConfiguration.consecutiveMistakeLimit !== undefined
? apiConfiguration.consecutiveMistakeLimit
: DEFAULT_CONSECUTIVE_MISTAKE_LIMIT
}
onChange={(value) => setApiConfigurationField("consecutiveMistakeLimit", value)}
/>
</>
<Collapsible open={isAdvancedSettingsOpen} onOpenChange={setIsAdvancedSettingsOpen}>
<CollapsibleTrigger className="flex items-center gap-1 w-full cursor-pointer hover:opacity-80 mb-2">
<span className={`codicon codicon-chevron-${isAdvancedSettingsOpen ? "down" : "right"}`}></span>
<span className="font-medium">{t("settings:advancedSettings.title")}</span>
</CollapsibleTrigger>
<CollapsibleContent className="space-y-3">
<DiffSettingsControl
diffEnabled={apiConfiguration.diffEnabled}
fuzzyMatchThreshold={apiConfiguration.fuzzyMatchThreshold}
onChange={(field, value) => setApiConfigurationField(field, value)}
/>
<TemperatureControl
value={apiConfiguration.modelTemperature}
onChange={handleInputChange("modelTemperature", noTransform)}
maxValue={2}
/>
<RateLimitSecondsControl
value={apiConfiguration.rateLimitSeconds || 0}
onChange={(value) => setApiConfigurationField("rateLimitSeconds", value)}
/>
<ConsecutiveMistakeLimitControl
value={
apiConfiguration.consecutiveMistakeLimit !== undefined
? apiConfiguration.consecutiveMistakeLimit
: DEFAULT_CONSECUTIVE_MISTAKE_LIMIT
}
onChange={(value) => setApiConfigurationField("consecutiveMistakeLimit", value)}
/>
{selectedProvider === "openrouter" &&
openRouterModelProviders &&
Object.keys(openRouterModelProviders).length > 0 && (
<div>
<div className="flex items-center gap-1">
<label className="block font-medium mb-1">
{t("settings:providers.openRouter.providerRouting.title")}
</label>
<a href={`https://openrouter.ai/${selectedModelId}/providers`}>
<ExternalLinkIcon className="w-4 h-4" />
</a>
</div>
<Select
value={
apiConfiguration?.openRouterSpecificProvider ||
OPENROUTER_DEFAULT_PROVIDER_NAME
}
onValueChange={(value) =>
setApiConfigurationField("openRouterSpecificProvider", value)
}>
<SelectTrigger className="w-full">
<SelectValue placeholder={t("settings:common.select")} />
</SelectTrigger>
<SelectContent>
<SelectItem value={OPENROUTER_DEFAULT_PROVIDER_NAME}>
{OPENROUTER_DEFAULT_PROVIDER_NAME}
</SelectItem>
{Object.entries(openRouterModelProviders).map(([value, { label }]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
<div className="text-sm text-vscode-descriptionForeground mt-1">
{t("settings:providers.openRouter.providerRouting.description")}{" "}
<a href="https://openrouter.ai/docs/features/provider-routing">
{t("settings:providers.openRouter.providerRouting.learnMore")}.
</a>
</div>
</div>
)}
</CollapsibleContent>
</Collapsible>
)}
</div>
)

View file

@ -100,6 +100,20 @@ vi.mock("@/components/ui", () => ({
</select>
</div>
),
// Add Collapsible components
Collapsible: ({ children, open }: any) => (
<div className="collapsible-mock" data-open={open}>
{children}
</div>
),
CollapsibleTrigger: ({ children, className, onClick }: any) => (
<div className={`collapsible-trigger-mock ${className || ""}`} onClick={onClick}>
{children}
</div>
),
CollapsibleContent: ({ children, className }: any) => (
<div className={`collapsible-content-mock ${className || ""}`}>{children}</div>
),
}))
vi.mock("../TemperatureControl", () => ({

View file

@ -179,6 +179,20 @@ vi.mock("@/components/ui", () => ({
{children}
</button>
),
// Add Collapsible components
Collapsible: ({ children, open }: any) => (
<div className="collapsible-mock" data-open={open}>
{children}
</div>
),
CollapsibleTrigger: ({ children, className, onClick }: any) => (
<div className={`collapsible-trigger-mock ${className || ""}`} onClick={onClick}>
{children}
</div>
),
CollapsibleContent: ({ children, className }: any) => (
<div className={`collapsible-content-mock ${className || ""}`}>{children}</div>
),
}))
// Mock window.postMessage to trigger state hydration

View file

@ -2,7 +2,6 @@ import { useCallback, useState } from "react"
import { Trans } from "react-i18next"
import { Checkbox } from "vscrui"
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import { ExternalLinkIcon } from "@radix-ui/react-icons"
import { type ProviderSettings, type OrganizationAllowList, openRouterDefaultModelId } from "@roo-code/types"
@ -10,12 +9,7 @@ import type { RouterModels } from "@roo/api"
import { useAppTranslation } from "@src/i18n/TranslationContext"
import { getOpenRouterAuthUrl } from "@src/oauth/urls"
import {
useOpenRouterModelProviders,
OPENROUTER_DEFAULT_PROVIDER_NAME,
} from "@src/components/ui/hooks/useOpenRouterModelProviders"
import { VSCodeButtonLink } from "@src/components/common/VSCodeButtonLink"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@src/components/ui"
import { inputEventTransform, noTransform } from "../transforms"
@ -37,7 +31,6 @@ export const OpenRouter = ({
apiConfiguration,
setApiConfigurationField,
routerModels,
selectedModelId,
uriScheme,
fromWelcomeView,
organizationAllowList,
@ -58,14 +51,6 @@ export const OpenRouter = ({
[setApiConfigurationField],
)
const { data: openRouterModelProviders } = useOpenRouterModelProviders(apiConfiguration?.openRouterModelId, {
enabled:
!!apiConfiguration?.openRouterModelId &&
routerModels?.openrouter &&
Object.keys(routerModels.openrouter).length > 1 &&
apiConfiguration.openRouterModelId in routerModels.openrouter,
})
return (
<>
<VSCodeTextField
@ -139,41 +124,6 @@ export const OpenRouter = ({
organizationAllowList={organizationAllowList}
errorMessage={modelValidationError}
/>
{openRouterModelProviders && Object.keys(openRouterModelProviders).length > 0 && (
<div>
<div className="flex items-center gap-1">
<label className="block font-medium mb-1">
{t("settings:providers.openRouter.providerRouting.title")}
</label>
<a href={`https://openrouter.ai/${selectedModelId}/providers`}>
<ExternalLinkIcon className="w-4 h-4" />
</a>
</div>
<Select
value={apiConfiguration?.openRouterSpecificProvider || OPENROUTER_DEFAULT_PROVIDER_NAME}
onValueChange={(value) => setApiConfigurationField("openRouterSpecificProvider", value)}>
<SelectTrigger className="w-full">
<SelectValue placeholder={t("settings:common.select")} />
</SelectTrigger>
<SelectContent>
<SelectItem value={OPENROUTER_DEFAULT_PROVIDER_NAME}>
{OPENROUTER_DEFAULT_PROVIDER_NAME}
</SelectItem>
{Object.entries(openRouterModelProviders).map(([value, { label }]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
<div className="text-sm text-vscode-descriptionForeground mt-1">
{t("settings:providers.openRouter.providerRouting.description")}{" "}
<a href="https://openrouter.ai/docs/features/provider-routing">
{t("settings:providers.openRouter.providerRouting.learnMore")}.
</a>
</div>
</div>
)}
</>
)
}

View file

@ -542,6 +542,9 @@
"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>"
}
},
"advancedSettings": {
"title": "Configuració avançada"
},
"advanced": {
"diff": {
"label": "Habilitar edició mitjançant diffs",

View file

@ -542,6 +542,9 @@
"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>"
}
},
"advancedSettings": {
"title": "Erweiterte Einstellungen"
},
"advanced": {
"diff": {
"label": "Bearbeitung durch Diffs aktivieren",

View file

@ -542,6 +542,9 @@
"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>"
}
},
"advancedSettings": {
"title": "Advanced settings"
},
"advanced": {
"diff": {
"label": "Enable editing through diffs",

View file

@ -542,6 +542,9 @@
"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>"
}
},
"advancedSettings": {
"title": "Configuración avanzada"
},
"advanced": {
"diff": {
"label": "Habilitar edición a través de diffs",

View file

@ -542,6 +542,9 @@
"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>"
}
},
"advancedSettings": {
"title": "Paramètres avancés"
},
"advanced": {
"diff": {
"label": "Activer l'édition via des diffs",

View file

@ -542,6 +542,9 @@
"description": "सक्षम होने पर, टर्मिनल VSCode के मूल प्रक्रिया से पर्यावरण चर विरासत में लेता है, जैसे उपयोगकर्ता प्रोफ़ाइल में परिभाषित शेल एकीकरण सेटिंग्स। यह VSCode की वैश्विक सेटिंग `terminal.integrated.inheritEnv` को सीधे टॉगल करता है। <0>अधिक जानें</0>"
}
},
"advancedSettings": {
"title": "उन्नत सेटिंग्स"
},
"advanced": {
"diff": {
"label": "diffs के माध्यम से संपादन सक्षम करें",

View file

@ -546,6 +546,9 @@
"description": "Ketika diaktifkan, terminal akan mewarisi variabel environment dari proses parent VSCode, seperti pengaturan integrasi shell yang didefinisikan user-profile. Ini secara langsung mengalihkan pengaturan global VSCode `terminal.integrated.inheritEnv`. <0>Pelajari lebih lanjut</0>"
}
},
"advancedSettings": {
"title": "Pengaturan lanjutan"
},
"advanced": {
"diff": {
"label": "Aktifkan editing melalui diff",

View file

@ -542,6 +542,9 @@
"description": "Quando abilitato, il terminale eredita le variabili d'ambiente dal processo padre di VSCode, come le impostazioni di integrazione della shell definite nel profilo utente. Questo attiva direttamente l'impostazione globale di VSCode `terminal.integrated.inheritEnv`. <0>Scopri di più</0>"
}
},
"advancedSettings": {
"title": "Impostazioni avanzate"
},
"advanced": {
"diff": {
"label": "Abilita modifica tramite diff",

View file

@ -542,6 +542,9 @@
"description": "有効にすると、ターミナルは VSCode の親プロセスから環境変数を継承します。ユーザープロファイルで定義されたシェル統合設定などが含まれます。これは VSCode のグローバル設定 `terminal.integrated.inheritEnv` を直接切り替えます。 <0>詳細情報</0>"
}
},
"advancedSettings": {
"title": "詳細設定"
},
"advanced": {
"diff": {
"label": "diff経由の編集を有効化",

View file

@ -542,6 +542,9 @@
"description": "활성화하면 터미널이 VSCode 부모 프로세스로부터 환경 변수를 상속받습니다. 사용자 프로필에 정의된 셸 통합 설정 등이 포함됩니다. 이는 VSCode 전역 설정 `terminal.integrated.inheritEnv`를 직접 전환합니다. <0>더 알아보기</0>"
}
},
"advancedSettings": {
"title": "고급 설정"
},
"advanced": {
"diff": {
"label": "diff를 통한 편집 활성화",

View file

@ -542,6 +542,9 @@
"description": "Indien ingeschakeld, neemt de terminal omgevingsvariabelen over van het bovenliggende VSCode-proces, zoals shell-integratie-instellingen uit het gebruikersprofiel. Dit schakelt direct de VSCode-instelling `terminal.integrated.inheritEnv` om. <0>Meer informatie</0>"
}
},
"advancedSettings": {
"title": "Geavanceerde instellingen"
},
"advanced": {
"diff": {
"label": "Bewerken via diffs inschakelen",

View file

@ -542,6 +542,9 @@
"description": "Po włączeniu terminal dziedziczy zmienne środowiskowe z procesu nadrzędnego VSCode, takie jak ustawienia integracji powłoki zdefiniowane w profilu użytkownika. Przełącza to bezpośrednio globalne ustawienie VSCode `terminal.integrated.inheritEnv`. <0>Dowiedz się więcej</0>"
}
},
"advancedSettings": {
"title": "Ustawienia zaawansowane"
},
"advanced": {
"diff": {
"label": "Włącz edycję przez różnice",

View file

@ -542,6 +542,9 @@
"description": "Quando ativado, o terminal herda variáveis de ambiente do processo pai do VSCode, como configurações de integração do shell definidas no perfil do usuário. Isso alterna diretamente a configuração global do VSCode `terminal.integrated.inheritEnv`. <0>Saiba mais</0>"
}
},
"advancedSettings": {
"title": "Configurações avançadas"
},
"advanced": {
"diff": {
"label": "Ativar edição através de diffs",

View file

@ -542,6 +542,9 @@
"description": "Если включено, терминал будет наследовать переменные среды от родительского процесса VSCode, такие как настройки интеграции оболочки, определённые в профиле пользователя. Напрямую переключает глобальную настройку VSCode `terminal.integrated.inheritEnv`. <0>Подробнее</0>"
}
},
"advancedSettings": {
"title": "Дополнительные настройки"
},
"advanced": {
"diff": {
"label": "Включить редактирование через диффы",

View file

@ -542,6 +542,9 @@
"description": "Etkinleştirildiğinde, terminal VSCode üst işleminden ortam değişkenlerini devralır, örneğin kullanıcı profilinde tanımlanan kabuk entegrasyon ayarları gibi. Bu, VSCode'un global ayarı olan `terminal.integrated.inheritEnv` değerini doğrudan değiştirir. <0>Daha fazla bilgi</0>"
}
},
"advancedSettings": {
"title": "Gelişmiş ayarlar"
},
"advanced": {
"diff": {
"label": "Diff'ler aracılığıyla düzenlemeyi etkinleştir",

View file

@ -542,6 +542,9 @@
"description": "Khi được bật, terminal sẽ kế thừa các biến môi trường từ tiến trình cha của VSCode, như các cài đặt tích hợp shell được định nghĩa trong hồ sơ người dùng. Điều này trực tiếp chuyển đổi cài đặt toàn cục của VSCode `terminal.integrated.inheritEnv`. <0>Tìm hiểu thêm</0>"
}
},
"advancedSettings": {
"title": "Cài đặt nâng cao"
},
"advanced": {
"diff": {
"label": "Bật chỉnh sửa qua diff",

View file

@ -542,6 +542,9 @@
"description": "启用后,终端将从 VSCode 父进程继承环境变量,如用户配置文件中定义的 shell 集成设置。这直接切换 VSCode 全局设置 `terminal.integrated.inheritEnv`。 <0>了解更多</0>"
}
},
"advancedSettings": {
"title": "高级设置"
},
"advanced": {
"diff": {
"label": "启用diff更新",

View file

@ -542,6 +542,9 @@
"description": "啟用後,終端機將從 VSCode 父程序繼承環境變數,如使用者設定檔中定義的 shell 整合設定。這直接切換 VSCode 全域設定 `terminal.integrated.inheritEnv`。 <0>瞭解更多</0>"
}
},
"advancedSettings": {
"title": "進階設定"
},
"advanced": {
"diff": {
"label": "透過差異比對編輯",