import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Save } from "lucide-react"; import { toast } from "sonner"; import { useHermesModelConfig, useSaveHermesModelConfig, } from "@/hooks/useHermes"; import { extractErrorMessage } from "@/utils/errorUtils"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import type { HermesModelConfig } from "@/types"; const ModelPanel: React.FC = () => { const { t } = useTranslation(); const { data: modelData, isLoading } = useHermesModelConfig(true); const saveModelMutation = useSaveHermesModelConfig(); const [defaultModel, setDefaultModel] = useState(""); const [provider, setProvider] = useState(""); const [baseUrl, setBaseUrl] = useState(""); const [contextLength, setContextLength] = useState(""); const [maxTokens, setMaxTokens] = useState(""); // Preserve unknown fields from the original config const [extra, setExtra] = useState>({}); useEffect(() => { if (modelData === undefined) return; if (modelData) { setDefaultModel(modelData.default ?? ""); setProvider(modelData.provider ?? ""); setBaseUrl(modelData.base_url ?? ""); setContextLength( modelData.context_length != null ? String(modelData.context_length) : "", ); setMaxTokens( modelData.max_tokens != null ? String(modelData.max_tokens) : "", ); // Collect unknown fields const { default: _d, provider: _p, base_url: _b, context_length: _c, max_tokens: _m, ...rest } = modelData; setExtra(rest); } else { setDefaultModel(""); setProvider(""); setBaseUrl(""); setContextLength(""); setMaxTokens(""); setExtra({}); } }, [modelData]); const handleSave = async () => { try { const config: HermesModelConfig = { ...extra, }; if (defaultModel.trim()) config.default = defaultModel.trim(); if (provider.trim()) config.provider = provider.trim(); if (baseUrl.trim()) config.base_url = baseUrl.trim(); const cl = parseInt(contextLength); if (!isNaN(cl) && cl > 0) config.context_length = cl; const mt = parseInt(maxTokens); if (!isNaN(mt) && mt > 0) config.max_tokens = mt; await saveModelMutation.mutateAsync(config); toast.success(t("hermes.model.saveSuccess")); } catch (error) { toast.error(t("hermes.model.saveFailed"), { description: extractErrorMessage(error), }); } }; if (isLoading) { return (
{t("common.loading")}
); } return (

{t("hermes.model.description")}

setDefaultModel(e.target.value)} placeholder="anthropic/claude-opus-4-6" />

{t("hermes.model.defaultHint", { defaultValue: "The default model to use, e.g. anthropic/claude-opus-4-6", })}

setProvider(e.target.value)} placeholder="openrouter" />

{t("hermes.model.providerHint", { defaultValue: "Provider name for model routing (e.g. openrouter, anthropic)", })}

setBaseUrl(e.target.value)} placeholder="https://api.example.com/v1" />

{t("hermes.model.baseUrlHint", { defaultValue: "Override the API endpoint URL for this model", })}

setContextLength(e.target.value)} placeholder="200000" />
setMaxTokens(e.target.value)} placeholder="16384" />
); }; export default ModelPanel;