mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-05-21 21:11:24 +08:00
feat(hermes): memory enable switch + clearer migration warning copy
Replaces the greyed-out "Memory is disabled" banner with a real Switch at the top of each memory tab. Users can now toggle Hermes' memory/user blobs without leaving CC Switch; the underlying write goes through the merge-aware `set_memory_enabled`, so budgets and external-provider settings survive toggle operations. The new `useToggleHermesMemoryEnabled` mutation invalidates the limits query so the Switch state and the amber disabled-hint update in lockstep. Reworks the `schema_migrated_v12` health banner copy to match the simplified "CC Switch only manages custom_providers" posture — it now tells users to reconcile migrated dict entries via Hermes Web UI, instead of the earlier (and now inaccurate) "CC Switch reads both".
This commit is contained in:
@@ -30,6 +30,41 @@ function getWarningText(
|
||||
return t("hermes.health.envParseFailed", {
|
||||
defaultValue: "The .env file could not be parsed.",
|
||||
});
|
||||
case "model_no_default":
|
||||
return t("hermes.health.modelNoDefault", {
|
||||
defaultValue:
|
||||
"No default model or provider is configured in the 'model' section.",
|
||||
});
|
||||
case "custom_providers_not_list":
|
||||
return t("hermes.health.customProvidersNotList", {
|
||||
defaultValue:
|
||||
"custom_providers should be a YAML list (items prefixed with '-'), not a mapping.",
|
||||
});
|
||||
case "model_provider_unknown":
|
||||
return t("hermes.health.modelProviderUnknown", {
|
||||
defaultValue:
|
||||
"model.provider references a provider that is not configured.",
|
||||
});
|
||||
case "model_default_not_in_provider":
|
||||
return t("hermes.health.modelDefaultNotInProvider", {
|
||||
defaultValue:
|
||||
"model.default is not in the selected provider's models list.",
|
||||
});
|
||||
case "duplicate_provider_name":
|
||||
return t("hermes.health.duplicateProviderName", {
|
||||
defaultValue:
|
||||
"custom_providers contains duplicate provider names — only one entry will be used.",
|
||||
});
|
||||
case "duplicate_provider_base_url":
|
||||
return t("hermes.health.duplicateProviderBaseUrl", {
|
||||
defaultValue:
|
||||
"custom_providers contains duplicate base_urls — possible accidental copy.",
|
||||
});
|
||||
case "schema_migrated_v12":
|
||||
return t("hermes.health.schemaMigratedV12", {
|
||||
defaultValue:
|
||||
"Hermes moved some providers into the 'providers:' dict. CC Switch only manages 'custom_providers:' — edit or remove those entries via Hermes Web UI.",
|
||||
});
|
||||
default:
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import { ExternalLink } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import MarkdownEditor from "@/components/MarkdownEditor";
|
||||
import {
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
useHermesMemoryLimits,
|
||||
useOpenHermesWebUI,
|
||||
useSaveHermesMemory,
|
||||
useToggleHermesMemoryEnabled,
|
||||
} from "@/hooks/useHermes";
|
||||
import { useDarkMode } from "@/hooks/useDarkMode";
|
||||
import type { HermesMemoryKind } from "@/types";
|
||||
@@ -30,6 +32,7 @@ const MemoryTabPane: React.FC<MemoryTabPaneProps> = ({
|
||||
const darkMode = useDarkMode();
|
||||
const { data, isLoading } = useHermesMemory(kind, true);
|
||||
const saveMutation = useSaveHermesMemory();
|
||||
const toggleMutation = useToggleHermesMemoryEnabled();
|
||||
const [content, setContent] = useState("");
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
@@ -57,11 +60,34 @@ const MemoryTabPane: React.FC<MemoryTabPaneProps> = ({
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
{!enabled && (
|
||||
<div className="text-sm text-amber-700 dark:text-amber-400 px-3 py-2 rounded-md bg-amber-500/10 border border-amber-500/30">
|
||||
{t("hermes.memory.disabled")}
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center justify-between px-3 py-2 rounded-md border",
|
||||
enabled
|
||||
? "bg-muted/30"
|
||||
: "bg-amber-500/10 border-amber-500/30",
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<Switch
|
||||
checked={enabled}
|
||||
disabled={toggleMutation.isPending}
|
||||
onCheckedChange={(next) =>
|
||||
toggleMutation.mutate({ kind, enabled: next })
|
||||
}
|
||||
/>
|
||||
<span className="text-sm">
|
||||
{enabled
|
||||
? t("hermes.memory.enableOn")
|
||||
: t("hermes.memory.enableOff")}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{!enabled && (
|
||||
<span className="text-xs text-amber-700 dark:text-amber-400">
|
||||
{t("hermes.memory.disabledHint")}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isLoading && !loaded ? (
|
||||
<div className="flex items-center justify-center h-64 text-muted-foreground">
|
||||
|
||||
@@ -125,6 +125,34 @@ export function useSaveHermesMemory() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle one memory blob's on/off flag in Hermes' `config.yaml`. Invalidates
|
||||
* the limits query so the switch UI and disabled banner update immediately.
|
||||
*/
|
||||
export function useToggleHermesMemoryEnabled() {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
kind,
|
||||
enabled,
|
||||
}: {
|
||||
kind: HermesMemoryKind;
|
||||
enabled: boolean;
|
||||
}) => hermesApi.setMemoryEnabled(kind, enabled),
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries({
|
||||
queryKey: hermesKeys.memoryLimits,
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
toast.error(t("hermes.memory.toggleFailed"), {
|
||||
description: extractErrorMessage(error) || undefined,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a handler that probes the local Hermes Web UI, opens it in the
|
||||
* system browser, and surfaces a localized toast on failure. Callers only
|
||||
|
||||
@@ -53,4 +53,15 @@ export const hermesApi = {
|
||||
async getMemoryLimits(): Promise<HermesMemoryLimits> {
|
||||
return await invoke("get_hermes_memory_limits");
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the on/off flag for one memory blob. Other fields in the `memory:`
|
||||
* section (budgets, external provider config) are preserved.
|
||||
*/
|
||||
async setMemoryEnabled(
|
||||
kind: HermesMemoryKind,
|
||||
enabled: boolean,
|
||||
): Promise<void> {
|
||||
await invoke("set_hermes_memory_enabled", { kind, enabled });
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user