feat: switch provider cleans other custom providers and sets default model

This commit is contained in:
KimiSwitch Dev
2026-07-08 14:02:09 +08:00
parent 4fecf191da
commit 8c515f42dc
4 changed files with 56 additions and 25 deletions
+34 -11
View File
@@ -191,17 +191,40 @@ export default function App() {
updateConfig((cfg) => ({ ...cfg, default_model: alias })); updateConfig((cfg) => ({ ...cfg, default_model: alias }));
}; };
const handleToggleProviderEnabled = (name: string) => { const handleSwitchProvider = (name: string) => {
updateConfig((cfg) => { updateConfig((cfg) => {
const provider = cfg.providers[name]; const target = cfg.providers[name];
if (!provider) return cfg; if (!target) return cfg;
return {
...cfg, const isKimiNative = (p: Provider) => p.managed === true;
providers: {
...cfg.providers, // Keep Kimi native (managed) providers and the selected provider only.
[name]: { ...provider, enabled: !provider.enabled }, const providers: Record<string, Provider> = {};
}, for (const [key, p] of Object.entries(cfg.providers)) {
}; if (isKimiNative(p)) {
providers[key] = p;
}
}
providers[name] = { ...target, enabled: true };
// Drop models whose provider was removed.
const models: Record<string, Model> = {};
for (const [key, m] of Object.entries(cfg.models)) {
if (providers[m.provider]) {
models[key] = m;
}
}
// Set default model to the first model of the selected provider.
let default_model: string | null = null;
for (const [key, m] of Object.entries(models)) {
if (m.provider === name) {
default_model = key;
break;
}
}
return { ...cfg, providers, models, default_model };
}); });
}; };
@@ -320,7 +343,7 @@ export default function App() {
}} }}
onDelete={handleDeleteProvider} onDelete={handleDeleteProvider}
onAdd={handleAddProvider} onAdd={handleAddProvider}
onToggleEnabled={handleToggleProviderEnabled} onSwitchProvider={handleSwitchProvider}
/> />
) : currentProvider ? ( ) : currentProvider ? (
<ProviderEdit <ProviderEdit
+18 -14
View File
@@ -8,7 +8,7 @@ interface ProviderListProps {
onEdit: (name: string) => void; onEdit: (name: string) => void;
onDelete: (name: string) => void; onDelete: (name: string) => void;
onAdd: () => void; onAdd: () => void;
onToggleEnabled: (name: string) => void; onSwitchProvider: (name: string) => void;
} }
const PROVIDER_ICONS: Record<string, string> = { const PROVIDER_ICONS: Record<string, string> = {
@@ -53,7 +53,7 @@ export function ProviderList({
onEdit, onEdit,
onDelete, onDelete,
onAdd, onAdd,
onToggleEnabled, onSwitchProvider,
}: ProviderListProps) { }: ProviderListProps) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
@@ -92,15 +92,19 @@ export function ProviderList({
const defaultModelName = defaultModel const defaultModelName = defaultModel
? models[defaultModel]?.display_name || defaultModel ? models[defaultModel]?.display_name || defaultModel
: null; : null;
const enabled = provider.enabled !== false; const isKimiNative = provider.managed === true;
const isActive =
!isKimiNative &&
defaultModel !== null &&
models[defaultModel]?.provider === provider.name;
return ( return (
<div <div
key={provider.name} key={provider.name}
className={`group relative flex items-center gap-4 p-4 rounded-xl border transition-colors cursor-pointer w-full ${ className={`group relative flex items-center gap-4 p-4 rounded-xl border transition-colors cursor-pointer w-full ${
enabled isActive
? "bg-[#16161a] border-[#2a2a2e] hover:border-[#3a3a42] hover:bg-[#1c1c20]" ? "bg-green-900/10 border-green-500/30 hover:border-green-500/50 hover:bg-green-900/20"
: "bg-[#16161a]/50 border-[#2a2a2e]/50 opacity-60" : "bg-[#16161a] border-[#2a2a2e] hover:border-[#3a3a42] hover:bg-[#1c1c20]"
}`} }`}
onClick={() => onEdit(provider.name)} onClick={() => onEdit(provider.name)}
> >
@@ -117,9 +121,9 @@ export function ProviderList({
<h3 className="font-semibold text-[#e5e5e7] truncate"> <h3 className="font-semibold text-[#e5e5e7] truncate">
{provider.name} {provider.name}
</h3> </h3>
{!enabled && ( {isActive && (
<span className="text-xs px-2 py-0.5 rounded-full bg-gray-800 text-gray-400 border border-gray-700"> <span className="text-xs px-2 py-0.5 rounded-full bg-green-900/30 text-green-400 border border-green-500/30">
{t("disabled")} {t("inUse")}
</span> </span>
)} )}
{provider.note && ( {provider.note && (
@@ -152,15 +156,15 @@ export function ProviderList({
type="button" type="button"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
onToggleEnabled(provider.name); onSwitchProvider(provider.name);
}} }}
className={`px-3 py-1.5 text-sm rounded focus:ring-2 focus:outline-none ${ className={`px-3 py-1.5 text-sm rounded focus:ring-2 focus:outline-none ${
enabled isActive
? "bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-500" ? "bg-green-600 hover:bg-green-700 text-white focus:ring-green-500"
: "border border-[#2a2a2e] hover:bg-[#252529] text-gray-400 focus:ring-blue-500" : "bg-blue-600 hover:bg-blue-700 text-white focus:ring-blue-500"
}`} }`}
> >
{enabled ? `${t("activated")}` : t("activate")} {isActive ? t("inUse") : t("switchTo")}
</button> </button>
<button <button
type="button" type="button"
+2
View File
@@ -85,6 +85,8 @@ export const enTranslations: Record<TranslationKey, string> = {
activate: "Activate", activate: "Activate",
activated: "Activated", activated: "Activated",
disabled: "Disabled", disabled: "Disabled",
switchTo: "Switch to",
inUse: "In use",
unsavedChanges: "Unsaved changes", unsavedChanges: "Unsaved changes",
qwenActivateNotImplemented: "Qwen Code activation will be implemented in a follow-up.", qwenActivateNotImplemented: "Qwen Code activation will be implemented in a follow-up.",
importConfig: "Import current config", importConfig: "Import current config",
+2
View File
@@ -83,6 +83,8 @@ export const zhTranslations = {
activate: "启用", activate: "启用",
activated: "已启用", activated: "已启用",
disabled: "已停用", disabled: "已停用",
switchTo: "切换使用",
inUse: "使用中",
unsavedChanges: "未保存修改", unsavedChanges: "未保存修改",
qwenActivateNotImplemented: "Qwen Code 启用功能将在后续实现。", qwenActivateNotImplemented: "Qwen Code 启用功能将在后续实现。",
importConfig: "导入当前配置", importConfig: "导入当前配置",