feat: switch provider cleans other custom providers and sets default model
This commit is contained in:
+34
-11
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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: "导入当前配置",
|
||||||
|
|||||||
Reference in New Issue
Block a user