Files
mai-bot/dashboard/dist/assets/bot-zehsWfTg.js

5 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{r as t,j as s}from"./router-zNjPR4CY.js";import{p as es}from"./parse-BBzU4wsN.js";import{U as ss,E as ts,V as rs,M as Ae,W as as,S as Pe,T as He,O as $e,P as ce,B as P,A as ns,m as os,n as is,o as cs,q as ls,r as us,s as ds,t as ms,v as ps,X as Le,Y as De,Z as Oe,_ as fs,g as gs,R as hs}from"./index-CuOHsLf7.js";import{C as xs}from"./CodeEditor-4JcGD1og.js";import{B as vs,A as bs,H as Ie,M as Cs,C as ys,a as ws,E as js,b as Ss,K as _s,R as ks,c as Ts,d as Ns,f as le,D as Rs}from"./BotInfoSection-D3nfOJyA.js";import"./textarea-8PIujbf-.js";import"./switch-Kc2EZ0Ga.js";import"./select-DGqIoF9r.js";import"./slider-mDhSC-zv.js";import{R as Es,u as Ms,a as As}from"./restart-overlay-B44c6hlE.js";import{af as Ps,ag as Ls,R as Ds,ah as Os,a6 as Is,ai as Ve,G as Vs,y as Bs}from"./icons-DTcdLw9j.js";import"./misc-BwRzHX8c.js";import"./radix-C-ZuImoP.js";import"./utils-DjBw3JGv.js";import"./badge-CDs67obV.js";import"./separator-B_DSOSdz.js";import"./key-value-editor-D1uUqXIn.js";import"./popover-DSuRLFDH.js";import"./progress-C6-hh8fF.js";import"./system-api-DeeJapvB.js";function Hs(h,x,d,l={}){const{debounceMs:m=2e3,onSaveSuccess:r,onSaveError:n}=l,a=t.useRef(null),v=t.useCallback(async(y,C)=>{try{x(!0);const w=await ss(y,C);if(!w.success)throw new Error(w.error);d(!1),r?.()}catch(w){console.error(`自动保存 ${y} 失败:`,w),d(!0),n?.(w instanceof Error?w:new Error(String(w)))}finally{x(!1)}},[x,d,r,n]),k=t.useCallback((y,C)=>{h||(d(!0),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>{v(y,C)},m))},[h,d,v,m]),T=t.useCallback(async(y,C)=>{a.current&&(clearTimeout(a.current),a.current=null),await v(y,C)},[v]),E=t.useCallback(()=>{a.current&&(clearTimeout(a.current),a.current=null)},[]);return t.useEffect(()=>()=>{a.current&&clearTimeout(a.current)},[]),{triggerAutoSave:k,saveNow:T,cancelPendingAutoSave:E}}function g(h,x,d,l){const m=t.useRef(null);t.useEffect(()=>{if(!h)return;const r=JSON.stringify(h);if(d||m.current===null){m.current=r;return}r!==m.current&&(m.current=r,l(x,h))},[h,d])}const $s=500,Be=["bot","chat","expression","a_memorix","visual","message_receive","emoji","voice","response_post_process","webui","plugin_runtime","log"],A=new Set(["bot","chat","expression","a_memorix"]);function Fs(h){const x=h.nested||{},d=Object.entries(x),l=new Map,m=(r,n=new Set)=>{if(n.has(r))return null;const a=x[r];return a?a.uiParent?(n.add(r),m(a.uiParent,n)):a.uiLabel&&a.uiIcon?r:null:null};for(const[r,n]of d)n.uiLabel&&n.uiIcon&&!n.uiParent&&l.set(r,{id:r,label:n.uiLabel,icon:n.uiIcon||"",sections:[r]});for(const[r]of d){const n=m(r);if(!n||n===r)continue;const a=l.get(n);a&&!a.sections.includes(r)&&a.sections.push(r)}return Array.from(l.values()).sort((r,n)=>{const a=Be.indexOf(r.id),v=Be.indexOf(n.id);return(a===-1?1/0:a)-(v===-1?1/0:v)})}function dt(){return s.jsx(Es,{children:s.jsx(zs,{})})}function zs(){const[h,x]=t.useState(!0),[d,l]=t.useState(!1),[m,r]=t.useState(!1),[n,a]=t.useState(!1),[v,k]=t.useState("visual"),[T,E]=t.useState(""),[y,C]=t.useState(!1),[w,N]=t.useState(""),[ae,i]=t.useState(()=>localStorage.getItem("bot-config-restart-notice-dismissed")!=="true"),{toast:c}=ts(),{triggerRestart:L,isRestarting:M}=Ms(),[b,D]=t.useState(null),[j,O]=t.useState(null),[R,se]=t.useState(null),[I,ue]=t.useState(null),[V,de]=t.useState(null),[B,me]=t.useState(null),[H,pe]=t.useState(null),[$,fe]=t.useState(null),[F,ge]=t.useState(null),[z,he]=t.useState(null),[q,xe]=t.useState(null),[G,ve]=t.useState(null),[U,be]=t.useState(null),[W,Ce]=t.useState(null),[K,ye]=t.useState(null),[Y,we]=t.useState(null),[X,je]=t.useState(null),[J,Se]=t.useState(null),[Z,_e]=t.useState(null),[Q,ke]=t.useState(null),[ee,Te]=t.useState(null),[te,ze]=t.useState(null),u=t.useRef(!0),Ne=t.useRef({}),qe=e=>{const o=e.split(`
`);let f=o[0];f=f.replace(/^Error:\s*/,"");const S=[[/Invalid TOML document: unrecognized escape sequence/,"TOML 文档错误:无法识别的转义序列(提示:在双引号字符串中使用 \\\\ 转义反斜杠,或使用单引号字符串)"],[/Invalid TOML document: only letter, numbers, dashes and underscores are allowed in keys/,"TOML 文档错误:键名只能包含字母、数字、短横线和下划线"],[/Invalid TOML document: (.+)/,"TOML 文档错误:$1"],[/Unexpected character.*at line (\d+), column (\d+)/,"第 $1 行第 $2 列:意外的字符"],[/Expected.*at line (\d+), column (\d+)/,"第 $1 行第 $2 列:缺少必要的字符"],[/Invalid.*at line (\d+), column (\d+)/,"第 $1 行第 $2 列:无效的语法"],[/Unterminated string at line (\d+)/,"第 $1 行:字符串未正常结束(缺少引号)"],[/Duplicate key.*at line (\d+)/,"第 $1 行:重复的键名"],[/Invalid escape sequence at line (\d+)/,"第 $1 行:无效的转义序列(提示:在双引号字符串中使用 \\\\ 转义反斜杠)"],[/Expected.*but got.*at line (\d+)/,"第 $1 行:类型不匹配"],[/line (\d+), column (\d+)/,"第 $1 行第 $2 列"],[/Unexpected end of input/,"意外的文件结束(可能缺少闭合符号)"],[/Unexpected token/,"意外的标记"],[/Invalid number/,"无效的数字"],[/Invalid date/,"无效的日期格式"],[/Invalid boolean/,"无效的布尔值(应为 true 或 false"],[/Unexpected character/,"意外的字符"],[/unrecognized escape sequence/,"无法识别的转义序列"]];for(const[_,Me]of S)if(_.test(f)){f=f.replace(_,Me);break}return o.length>1?(o[0]=f,o.join(`
`)):f},ne=t.useCallback(e=>{const{memory:o,...f}=e;Ne.current=f,D(e.bot??{}),O(e.personality??{}),se(e.chat??{}),ue(e.expression??{}),de(e.emoji??{}),me(e.visual??{}),pe(e.voice??{}),fe(e.message_receive??{}),ge(e.keyword_reaction??{}),he(e.response_post_process??{}),xe(e.chinese_typo??{}),ve(e.response_splitter??{}),be(e.log??{}),Ce(e.debug??{}),ye(e.maim_message??{}),we(e.telemetry??{}),je(e.webui??{}),Se(e.database??{}),_e(e.mcp??{}),ke(e.plugin_runtime??{}),Te(e.a_memorix??{})},[]),Re=t.useCallback(()=>({...Ne.current,bot:b,personality:j,chat:R,expression:I,emoji:V,visual:B,voice:H,message_receive:$,keyword_reaction:F,response_post_process:z,chinese_typo:q,response_splitter:G,log:U,debug:W,maim_message:K,telemetry:Y,webui:X,database:J,mcp:Z,plugin_runtime:Q,a_memorix:ee}),[b,j,R,I,V,B,H,$,F,z,q,G,U,W,K,Y,X,J,Z,Q,ee]),oe=t.useCallback(async()=>{try{const e=await rs();if(!e.success){c({variant:"destructive",title:"加载失败",description:e.error});return}const f=e.data.content.replace(/"([^"]*)"/g,(S,_)=>`"${_.replace(/\\n/g,`
`).replace(/\\t/g," ").replace(/\\r/g,"\r").replace(/\\"/g,'"').replace(/\\\\/g,"\\")}"`);E(f),C(!1)}catch(e){c({variant:"destructive",title:"加载失败",description:e instanceof Error?e.message:"加载源代码失败"})}},[c]),re=t.useCallback(async()=>{try{x(!0);const[e,o]=await Promise.all([Ae(),as()]);if(!e.success){c({title:"加载失败",description:e.error,variant:"destructive"}),x(!1);return}ne(e.data.config),o.success&&o.data&&ze(o.data.schema),a(!1),u.current=!1,await oe()}catch(e){console.error("加载配置失败:",e),c({title:"加载失败",description:"无法加载配置文件",variant:"destructive"})}finally{x(!1)}},[c,oe,ne]);t.useEffect(()=>{re()},[re]),t.useEffect(()=>{const e=[["bot.platform",vs,"replace"],["bot.alias_names",bs],["bot.qq_account",Ie,"hidden"],["bot.platforms",Ie,"hidden"],["personality.multiple_reply_style",Cs],["chat.chat_prompts",ys],["chat.talk_value_rules",ws],["expression.expression_groups",js],["expression.learning_list",Ss],["keyword_reaction.keyword_rules",_s],["keyword_reaction.regex_rules",ks],["mcp.client.roots.items",Ts],["mcp.servers",Ns]];for(const[o,f,S="replace"]of e)le.register(o,f,S);return()=>{for(const[o]of e)le.unregister(o)}},[]);const{triggerAutoSave:p,cancelPendingAutoSave:ie}=Hs(u.current,r,a);g(b,"bot",u.current,p),g(j,"personality",u.current,p),g(R,"chat",u.current,p),g(I,"expression",u.current,p),g(V,"emoji",u.current,p),g(B,"visual",u.current,p),g(H,"voice",u.current,p),g($,"message_receive",u.current,p),g(F,"keyword_reaction",u.current,p),g(z,"response_post_process",u.current,p),g(q,"chinese_typo",u.current,p),g(G,"response_splitter",u.current,p),g(U,"log",u.current,p),g(W,"debug",u.current,p),g(K,"maim_message",u.current,p),g(Y,"telemetry",u.current,p),g(X,"webui",u.current,p),g(J,"database",u.current,p),g(Z,"mcp",u.current,p),g(Q,"plugin_runtime",u.current,p),g(ee,"a_memorix",u.current,p);const Ge=async()=>{try{l(!0);const e=T.replace(/"([^"]*)"/g,(f,S)=>`"${S.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r")}"`);try{es(e)}catch(f){const S=f instanceof Error?f.message:"TOML 格式错误",_=qe(S);C(!0),N(_),c({variant:"destructive",title:"TOML 格式错误",description:_}),l(!1);return}const o=await fs(e);if(!o.success){C(!0);const f=o.error;N(f),c({variant:"destructive",title:"保存失败",description:f});return}a(!1),C(!1),N(""),c({title:"保存成功",description:"配置已保存"}),await re()}catch(e){C(!0);const o=e instanceof Error?e.message:"保存配置失败";N(o),c({variant:"destructive",title:"保存失败",description:o})}finally{l(!1)}},Ue=async e=>{if(n){c({variant:"destructive",title:"切换失败",description:"请先保存当前更改"});return}if(k(e),e==="source")await oe();else try{const o=await Ae();if(!o.success){c({title:"加载失败",description:o.error,variant:"destructive"});return}ne(o.data.config),a(!1)}catch(o){console.error("加载配置失败:",o),c({title:"加载失败",description:"无法加载配置文件",variant:"destructive"})}},We=async()=>{try{l(!0),ie();const e=await Oe(Re());if(!e.success){c({title:"保存失败",description:e.error,variant:"destructive"}),l(!1);return}a(!1),c({title:"保存成功",description:"麦麦设置已保存"})}catch(e){console.error("保存配置失败:",e),c({title:"保存失败",description:e.message,variant:"destructive"})}finally{l(!1)}},Ee=async()=>{await L()},Ke=()=>{localStorage.setItem("bot-config-restart-notice-dismissed","true"),i(!1)},Ye=async()=>{ie(),await re(),a(!1),c({title:"已刷新",description:"已从 bot_config.toml 重新读取配置"})},Xe=async()=>{try{l(!0),ie();const e=await Oe(Re());if(!e.success){c({title:"保存失败",description:e.error,variant:"destructive"}),l(!1);return}a(!1),c({title:"保存成功",description:"配置已保存,即将重启麦麦..."}),await new Promise(o=>setTimeout(o,$s)),await Ee()}catch(e){console.error("保存失败:",e),c({title:"保存失败",description:e.message,variant:"destructive"})}finally{l(!1)}},Je=t.useMemo(()=>te?Fs(te):[],[te]),Ze=t.useMemo(()=>({bot:b,personality:j,chat:R,expression:I,emoji:V,visual:B,voice:H,message_receive:$,keyword_reaction:F,response_post_process:z,chinese_typo:q,response_splitter:G,log:U,debug:W,maim_message:K,telemetry:Y,webui:X,database:J,mcp:Z,plugin_runtime:Q,a_memorix:ee}),[b,j,R,I,V,B,H,$,F,z,q,G,U,W,K,Y,X,J,Z,Q,ee]),Qe=t.useCallback((e,o)=>{({bot:D,personality:O,chat:se,expression:ue,emoji:de,visual:me,voice:pe,message_receive:fe,keyword_reaction:ge,response_post_process:he,chinese_typo:xe,response_splitter:ve,log:be,debug:Ce,maim_message:ye,telemetry:we,webui:je,database:Se,mcp:_e,plugin_runtime:ke,a_memorix:Te})[e]?.(o)},[]);return h?s.jsx(Pe,{className:"h-full",children:s.jsx("div",{className:"space-y-4 sm:space-y-6 p-4 sm:p-6",children:s.jsx("div",{className:"flex items-center justify-center h-64",children:s.jsx("p",{className:"text-muted-foreground",children:"加载中..."})})})}):s.jsx(Pe,{className:"h-full min-w-0",scrollbars:"vertical",children:s.jsxs("div",{className:"max-w-full space-y-4 overflow-x-hidden p-4 sm:space-y-6 sm:p-6",children:[s.jsx("div",{className:"flex flex-col gap-3 sm:gap-4",children:s.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3",children:[s.jsxs("div",{className:"min-w-0",children:[s.jsx("h1",{className:"text-xl sm:text-2xl md:text-3xl font-bold",children:"麦麦设置"}),s.jsx("p",{className:"text-muted-foreground mt-1 text-xs sm:text-sm",children:"管理麦麦的核心功能和行为设置"})]}),s.jsxs("div",{className:"flex w-full min-w-0 flex-wrap gap-2 sm:w-auto sm:flex-shrink-0 sm:justify-end",children:[s.jsx(He,{value:v,onValueChange:e=>Ue(e),className:"w-full min-w-0 sm:w-[14rem]",children:s.jsxs($e,{className:"grid h-8 w-full grid-cols-2 sm:h-9",children:[s.jsxs(ce,{value:"visual",className:"px-2 text-xs",children:[s.jsx(Ps,{className:"mr-1 h-3 w-3 sm:h-4 sm:w-4"}),"可视化"]}),s.jsxs(ce,{value:"source",className:"px-2 text-xs",children:[s.jsx(Ls,{className:"mr-1 h-3 w-3 sm:h-4 sm:w-4"}),"源代码"]})]})}),s.jsxs(P,{onClick:Ye,disabled:d||m||M,size:"sm",variant:"outline",className:"min-w-0 flex-1 sm:w-24 sm:flex-none",children:[s.jsx(Ds,{className:"h-3 w-3 sm:h-4 sm:w-4 mr-1"}),"刷新"]}),s.jsxs(P,{onClick:v==="visual"?We:Ge,disabled:d||m||!n||M,size:"sm",variant:"outline",className:"min-w-0 flex-1 sm:w-24 sm:flex-none",children:[s.jsx(Os,{className:"h-4 w-4 flex-shrink-0",strokeWidth:2,fill:"none"}),s.jsx("span",{className:"ml-1 truncate text-xs sm:text-sm",children:d?"保存中":m?"自动":n?"保存":"已保存"})]}),s.jsxs(ns,{children:[s.jsx(os,{asChild:!0,children:s.jsxs(P,{disabled:d||m||M,size:"sm",className:"min-w-0 flex-1 sm:w-28 sm:flex-none",children:[s.jsx(Is,{className:"h-4 w-4 flex-shrink-0"}),s.jsx("span",{className:"ml-1 truncate text-xs sm:text-sm",children:M?"重启中":n?"保存重启":"重启"})]})}),s.jsxs(is,{children:[s.jsxs(cs,{children:[s.jsx(ls,{children:"确认重启麦麦?"}),s.jsx(us,{asChild:!0,children:s.jsx("div",{children:s.jsx("p",{children:n?"当前有未保存的配置更改。点击确认将先保存配置,然后重启麦麦使新配置生效。重启过程中麦麦将暂时离线。":"即将重启麦麦主程序。重启过程中麦麦将暂时离线,配置将在重启后生效。"})})})]}),s.jsxs(ds,{children:[s.jsx(ms,{children:"取消"}),s.jsx(ps,{onClick:n?Xe:Ee,children:n?"保存并重启":"确认重启"})]})]})]})]})]})}),ae&&s.jsxs(Le,{children:[s.jsx(Ve,{className:"h-4 w-4"}),s.jsxs(De,{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[s.jsxs("span",{children:["配置更新后需要",s.jsx("strong",{children:"重启麦麦"}),'才能生效。你可以点击右上角的"保存并重启"按钮一键完成保存和重启。']}),s.jsx(P,{type:"button",variant:"outline",size:"sm",onClick:Ke,children:"我知道了"})]})]}),v==="source"&&s.jsxs("div",{className:"space-y-4",children:[s.jsxs(Le,{children:[s.jsx(Ve,{className:"h-4 w-4"}),s.jsxs(De,{children:[s.jsx("strong",{children:"源代码模式(高级功能):"}),"直接编辑 TOML 配置文件。此功能仅适用于熟悉 TOML 语法的高级用户。保存时会在前端验证格式,只有格式完全正确才能保存。",y&&w&&s.jsxs("div",{className:"text-destructive font-semibold mt-3 p-3 bg-destructive/10 rounded-md",children:[s.jsx("div",{className:"font-bold mb-2",children:"⚠️ TOML 格式错误:"}),s.jsx("pre",{className:"text-sm font-mono whitespace-pre-wrap break-words",children:w})]})]})]}),s.jsx(xs,{value:T,onChange:e=>{E(e),a(!0),y&&(C(!1),N(""))},language:"toml",height:"calc(100vh - 280px)",minHeight:"500px",placeholder:"TOML 配置内容"})]}),v==="visual"&&s.jsx(qs,{configSchema:te,tabGroups:Je,sectionValues:Ze,setSectionValue:Qe,setHasUnsavedChanges:a}),s.jsx(As,{})]})})}function Fe(h,x,d){const l=h&&typeof h=="object"&&!Array.isArray(h)?h:{},[m,...r]=x;return m?r.length===0?{...l,[m]:d}:{...l,[m]:Fe(l[m],r,d)}:l}function qs(h){const{configSchema:x,sectionValues:d,setHasUnsavedChanges:l,setSectionValue:m,tabGroups:r}=h,[n,a]=t.useState(!1),[v,k]=t.useState(r[0]?.id??""),[T,E]=t.useState(!1);if(t.useEffect(()=>{r.some(i=>i.id===v)||k(r[0]?.id??"")},[v,r]),r.length===0||!x?.nested)return null;const y=n?r:r.filter(i=>A.has(i.id)),C=r.some(i=>!A.has(i.id)),w=y.find(i=>!A.has(i.id))?.id,N=()=>{a(i=>{if(i&&!A.has(v)){const c=r.find(L=>A.has(L.id));k(c?.id??r[0]?.id??"")}return!i})},ae=i=>{const c=i.sections.map(b=>[b,x.nested?.[b]]).filter(b=>!!b[1]);if(c.length===0)return null;const L=Object.fromEntries(c.map(([b])=>[b,d[b]??{}])),M={className:i.id,classDoc:i.label,fields:[],nested:Object.fromEntries(c)};return s.jsx(Rs,{schema:M,values:L,onChange:(b,D)=>{const[j,...O]=b.split(".");if(!j)return;const R=d[j]??{},se=O.length===0?D:Fe(R,O,D);m(j,se),l(!0)},hooks:le,advancedVisible:T,sectionColumns:2})};return s.jsxs(He,{value:v,onValueChange:k,className:"w-full",children:[s.jsxs($e,{className:"flex h-auto max-w-full justify-start gap-1 overflow-x-auto p-1 transition-all duration-300 ease-out sm:flex-wrap sm:overflow-x-visible",children:[y.map(i=>{const c=!A.has(i.id);return s.jsxs(t.Fragment,{children:[i.id===w&&s.jsx("span",{className:"mx-1 hidden h-6 w-px bg-border/80 transition-opacity duration-200 sm:block"}),s.jsx(ce,{value:i.id,className:gs("shrink-0 px-2 py-1.5 text-sm transition-all duration-200 ease-out sm:px-3 sm:py-2 data-[state=active]:shadow-sm",c&&"border border-dashed border-border/70 bg-background/45 text-muted-foreground/80 motion-safe:animate-[config-tab-enter_180ms_ease-out_both] hover:bg-background/70 data-[state=active]:border-primary/45 data-[state=active]:bg-primary/10 data-[state=active]:text-primary data-[state=active]:shadow-none"),children:i.label})]},i.id)}),C&&s.jsxs(P,{type:"button",variant:"ghost",size:"sm",className:"group h-8 shrink-0 px-2 text-xs transition-all duration-200 ease-out sm:h-9 sm:px-3",onClick:N,children:[n?s.jsx(Vs,{className:"mr-1 h-3.5 w-3.5 transition-transform duration-200 group-hover:-translate-x-0.5"}):s.jsx(Bs,{className:"mr-1 h-3.5 w-3.5 transition-transform duration-200 group-hover:translate-x-0.5"}),n?"收起":"更多"]}),s.jsx(P,{type:"button",variant:T?"default":"outline",size:"sm",className:"h-8 shrink-0 px-2 text-xs transition-all duration-200 ease-out sm:ml-auto sm:h-9 sm:px-3",onClick:()=>E(i=>!i),children:"高级设置"})]}),r.map(i=>s.jsx(hs,{value:i.id,className:"space-y-4 motion-safe:animate-[config-tab-content-enter_180ms_ease-out_both]",children:ae(i)},i.id))]})}export{dt as BotConfigPage};