import { useEffect, useState } from "react"; import { listModels, saveModel, setActive, deleteModel, testModel, type Kind, type Model, type ModelInput, } from "../api"; // 复用的模型控制面:列表(激活/脱敏key) + 登记表单 + 测试连接 + 激活/删除。 // 按 kind(chat/embedding) 区分,激活后经 NATS 热更新对应消费方。 export function ModelManager({ kind, title, baseUrlHint, modelHint, }: { kind: Kind; title: string; baseUrlHint: string; modelHint: string; }) { const empty: ModelInput = { kind, provider: "openai-compatible", base_url: "", api_key: "", model: "" }; const [models, setModels] = useState([]); const [form, setForm] = useState(empty); const [msg, setMsg] = useState(""); const [testing, setTesting] = useState(false); const refresh = () => listModels(kind).then(setModels).catch((e) => setMsg(`✗ ${e.message}`)); useEffect(() => { refresh(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [kind]); const set = (k: keyof ModelInput, v: string) => setForm((f) => ({ ...f, [k]: v })); const onSave = async () => { try { await saveModel({ ...form, kind }); setMsg("✓ 已保存"); setForm(empty); refresh(); } catch (e) { setMsg(`✗ ${(e as Error).message}`); } }; const onTest = async () => { setTesting(true); try { const r = await testModel({ ...form, kind }); setMsg(r.ok ? `✓ 连接成功(${r.message})` : `✗ 连接失败:${r.message}`); } catch (e) { setMsg(`✗ ${(e as Error).message}`); } finally { setTesting(false); } }; return (

{title}

{models.length === 0 && ( )} {models.map((m) => ( ))}
状态 Provider Base URL Model API Key 操作
暂无,使用下方表单登记。
{m.active ? ( 激活 ) : ( )} {m.provider} {m.base_url} {m.model} {m.api_key || "—"}
{!m.active && ( )}

登记(开发期:第三方在线 API,OpenAI 兼容)

{msg && {msg}}
); }