mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-06-17 22:37:50 +08:00
feat(hermes): render providers: dict overlays as read-only cards
ProviderCard now detects Hermes provider entries sourced from the v12+ `providers:` dict via the `_cc_source` marker that the backend injects, and renders a "Hermes Managed" badge beside the title. ProviderActions receives an `isReadOnly` prop that disables the Edit and Delete buttons (with a tooltip pointing the user at Hermes Web UI) while keeping Switch and Duplicate enabled — switching only touches `model.*`, and duplicate lets users fork the overlay into their own `custom_providers:` list. Three-locale i18n keys `provider.managedByHermes` / `provider.managedByHermesHint` added.
This commit is contained in:
@@ -38,6 +38,8 @@ interface ProviderActionsProps {
|
||||
isInFailoverQueue?: boolean;
|
||||
onToggleFailover?: (enabled: boolean) => void;
|
||||
isOfficialBlockedByProxy?: boolean;
|
||||
// Hermes v12+ providers: dict overlay — edit/delete must go through Web UI
|
||||
isReadOnly?: boolean;
|
||||
// OpenClaw: default model
|
||||
isDefaultModel?: boolean;
|
||||
onSetAsDefault?: () => void;
|
||||
@@ -63,6 +65,7 @@ export function ProviderActions({
|
||||
isInFailoverQueue = false,
|
||||
onToggleFailover,
|
||||
isOfficialBlockedByProxy = false,
|
||||
isReadOnly = false,
|
||||
// OpenClaw: default model
|
||||
isDefaultModel = false,
|
||||
onSetAsDefault,
|
||||
@@ -205,7 +208,11 @@ export function ProviderActions({
|
||||
|
||||
const buttonState = getMainButtonState();
|
||||
|
||||
const canDelete = isOmo || isAdditiveMode ? true : !isCurrent;
|
||||
const canDelete =
|
||||
!isReadOnly && (isOmo || isAdditiveMode ? true : !isCurrent);
|
||||
const readOnlyHint = t("provider.managedByHermesHint", {
|
||||
defaultValue: "由 Hermes 管理,请在 Hermes Web UI 中编辑",
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1.5">
|
||||
@@ -255,9 +262,13 @@ export function ProviderActions({
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
onClick={onEdit}
|
||||
title={t("common.edit")}
|
||||
className={iconButtonClass}
|
||||
onClick={isReadOnly ? undefined : onEdit}
|
||||
disabled={isReadOnly}
|
||||
title={isReadOnly ? readOnlyHint : t("common.edit")}
|
||||
className={cn(
|
||||
iconButtonClass,
|
||||
isReadOnly && "opacity-40 cursor-not-allowed text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
@@ -323,7 +334,7 @@ export function ProviderActions({
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
onClick={canDelete ? onDelete : undefined}
|
||||
title={t("common.delete")}
|
||||
title={isReadOnly ? readOnlyHint : t("common.delete")}
|
||||
className={cn(
|
||||
iconButtonClass,
|
||||
canDelete && "hover:text-red-500 dark:hover:text-red-400",
|
||||
|
||||
@@ -180,6 +180,12 @@ export function ProviderCard({
|
||||
const isCopilot =
|
||||
provider.meta?.providerType === PROVIDER_TYPES.GITHUB_COPILOT ||
|
||||
provider.meta?.usage_script?.templateType === "github_copilot";
|
||||
// Hermes v12+ overlay entries live under the `providers:` dict and are
|
||||
// read-only here — writes have to go through Hermes Web UI.
|
||||
const isHermesReadOnly =
|
||||
appId === "hermes" &&
|
||||
(provider.settingsConfig as Record<string, unknown>)?._cc_source ===
|
||||
"providers_dict";
|
||||
const isCodexOauth =
|
||||
provider.meta?.providerType === PROVIDER_TYPES.CODEX_OAUTH;
|
||||
|
||||
@@ -336,6 +342,19 @@ export function ProviderCard({
|
||||
⭐
|
||||
</span>
|
||||
)}
|
||||
|
||||
{isHermesReadOnly && (
|
||||
<span
|
||||
className="inline-flex items-center rounded-md bg-slate-200 px-1.5 py-0.5 text-[10px] font-semibold text-slate-700 dark:bg-slate-700/60 dark:text-slate-200"
|
||||
title={t("provider.managedByHermesHint", {
|
||||
defaultValue: "由 Hermes 管理,请在 Hermes Web UI 中编辑",
|
||||
})}
|
||||
>
|
||||
{t("provider.managedByHermes", {
|
||||
defaultValue: "Hermes Managed",
|
||||
})}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{displayUrl && (
|
||||
@@ -429,6 +448,7 @@ export function ProviderCard({
|
||||
isTesting={isTesting}
|
||||
isProxyTakeover={isProxyTakeover}
|
||||
isOfficialBlockedByProxy={isOfficialBlockedByProxy}
|
||||
isReadOnly={isHermesReadOnly}
|
||||
isOmo={isAnyOmo}
|
||||
onSwitch={() => onSwitch(provider)}
|
||||
onEdit={() => onEdit(provider)}
|
||||
|
||||
@@ -141,6 +141,8 @@
|
||||
"sortUpdateFailed": "Failed to update sort order",
|
||||
"configureUsage": "Configure usage query",
|
||||
"officialPartner": "Official Partner",
|
||||
"managedByHermes": "Hermes Managed",
|
||||
"managedByHermesHint": "Defined in Hermes' providers: dict. Edit or remove it via Hermes Web UI.",
|
||||
"openTerminal": "Open Terminal",
|
||||
"terminalOpened": "Terminal opened",
|
||||
"terminalOpenFailed": "Failed to open terminal",
|
||||
|
||||
@@ -141,6 +141,8 @@
|
||||
"sortUpdateFailed": "並び順の更新に失敗しました",
|
||||
"configureUsage": "利用状況を設定",
|
||||
"officialPartner": "公式パートナー",
|
||||
"managedByHermes": "Hermes 管理",
|
||||
"managedByHermesHint": "Hermes の providers: dict で定義されています。Hermes Web UI で編集または削除してください。",
|
||||
"openTerminal": "ターミナルを開く",
|
||||
"terminalOpened": "ターミナルを開きました",
|
||||
"terminalOpenFailed": "ターミナルを開けませんでした",
|
||||
|
||||
@@ -141,6 +141,8 @@
|
||||
"sortUpdateFailed": "排序更新失败",
|
||||
"configureUsage": "配置用量查询",
|
||||
"officialPartner": "官方合作伙伴",
|
||||
"managedByHermes": "Hermes 托管",
|
||||
"managedByHermesHint": "该条目定义在 Hermes 的 providers: dict,请在 Hermes Web UI 中编辑或删除。",
|
||||
"openTerminal": "打开终端",
|
||||
"terminalOpened": "终端已打开",
|
||||
"terminalOpenFailed": "打开终端失败",
|
||||
|
||||
Reference in New Issue
Block a user