Files
mai-bot/dashboard/dist/assets/model-Bpgh3xA9.js

2 lines
72 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 a,j as e,R as ns,i as va}from"./router-zNjPR4CY.js";import{D as ks,i as ys,j as Cs,k as Ss,l as Ts,a3 as Ps,B as N,a4 as ie,h as Na,a5 as ht,X as oe,a6 as lt,Y as de,T as ft,O as pt,P as Pe,R as Me,L as O,I as W,g as ts,a7 as ba,a8 as _a,a9 as wa,aa as ka,a0 as ws,$ as ya,ab as Ca,u as Sa,E as Ta,N as Ze,ac as Pa,a1 as Ns,S as bs,A as fe,m as Ma,n as pe,o as ge,q as je,r as ve,s as Ne,t as be,v as _e,ad as Da,a2 as Oa}from"./index-CuOHsLf7.js";import{S as Ms,a as Ds,b as Os,c as Es,d as zs}from"./select-DGqIoF9r.js";import{C as gt,b as jt,d as vt,e as Nt,f as bt,g as _t,M as Se,m as Ea,S as za,h as Ia,c as ce,P as Ra,a as Aa,H as it}from"./ProviderList-4mOft0xL.js";import{P as wt,a as kt,b as yt}from"./popover-DSuRLFDH.js";import{S as Ae}from"./switch-Kc2EZ0Ga.js";import{S as Ct}from"./slider-mDhSC-zv.js";import{B as ee}from"./badge-CDs67obV.js";import{R as Fa,u as La,a as $a}from"./restart-overlay-B44c6hlE.js";import{K as Ba}from"./key-value-editor-D1uUqXIn.js";import{T as Ka}from"./textarea-8PIujbf-.js";import{C as Le}from"./checkbox-DWiVrbnx.js";import{S as Va}from"./separator-B_DSOSdz.js";import{e as Wa,c as Ua}from"./pack-api-NsQx-ed4.js";import{aj as St,P as Ga,L as as,ai as rs,t as ct,ak as ot,al as dt,b as Is,am as Ja,an as Tt,ao as qa,X as Ha,u as Pt,v as Te,ap as Qa,G as Xa,y as Ya,aq as Za,ah as er,a6 as sr,T as Fe,ar as tr,_ as mt,w as es,S as ar,R as rr,s as nr}from"./icons-DTcdLw9j.js";import{u as lr,a as ut,D as ir,c as cr,S as or,h as dr,b as mr,s as ur,K as xr,P as hr,d as fr,C as pr}from"./dnd-BoJ1-vkD.js";import{T as gr,a as jr,b as _s,c as Q,d as vr,e as H}from"./table-DFeDhBY_.js";import"./misc-BwRzHX8c.js";import"./radix-C-ZuImoP.js";import"./utils-DjBw3JGv.js";import"./progress-C6-hh8fF.js";import"./system-api-DeeJapvB.js";function Nr({open:T,onOpenChange:c,value:g,onChange:x}){const[w,h]=a.useState(g);a.useEffect(()=>{T&&h(g)},[T,g]);const k=_=>{_&&h(g),c(_)},o=()=>{x(w),c(!1)},P=()=>{h(g),c(!1)};return e.jsx(ks,{open:T,onOpenChange:k,children:e.jsxs(ys,{className:"max-w-3xl h-[70vh] flex flex-col",children:[e.jsxs(Cs,{children:[e.jsx(Ss,{children:"编辑额外参数"}),e.jsx(Ts,{children:"配置模型调用时的额外参数,支持嵌套对象和数组"})]}),e.jsx("div",{className:"flex-1 overflow-hidden min-h-0",children:e.jsx(Ba,{value:w,onChange:h,placeholder:"添加额外参数(如 thinking、top_p 等)..."})}),e.jsxs(Ps,{children:[e.jsx(N,{variant:"outline",onClick:P,children:"取消"}),e.jsx(N,{onClick:o,children:"保存"})]})]})})}const br={utils:"通用工具",utils_small:"轻量工具",tool_use:"工具调用",replyer:"回复生成",planner:"规划推理",vlm:"视觉模型",voice:"语音处理",embedding:"向量嵌入",lpmm_entity_extract:"实体提取",lpmm_rdf_build:"RDF构建",lpmm_qa:"问答模型"},_r=["官方推荐","性价比","高性能","免费模型","国内可用","海外模型","OpenAI","Claude","Gemini","国产模型","多模态","轻量级"];function wr({trigger:T}){const[c,g]=a.useState(!1),[x,w]=a.useState(1),[h,k]=a.useState(!1),[o,P]=a.useState(!1),[_,y]=a.useState([]),[n,i]=a.useState([]),[u,C]=a.useState({}),[R,j]=a.useState(new Set),[v,m]=a.useState(new Set),[f,A]=a.useState(new Set),[se,te]=a.useState(""),[d,E]=a.useState(""),[q,De]=a.useState(""),[X,we]=a.useState([]);a.useEffect(()=>{c&&x===1&&ls()},[c,x]);const ls=async()=>{k(!0);try{const l=await Wa({name:"",description:"",author:""});y(l.providers),i(l.models),C(l.task_config),j(new Set(l.providers.map(S=>S.name))),m(new Set(l.models.map(S=>S.name))),A(new Set(Object.keys(l.task_config)))}catch(l){console.error("加载配置失败:",l),ie({title:"加载当前配置失败",variant:"destructive"})}finally{k(!1)}},Oe=l=>{const S=new Set(R),$=new Set(v),L=new Set(f);S.has(l)?(S.delete(l),n.filter(z=>z.api_provider===l).forEach(z=>$.delete(z.name)),Object.entries(u).forEach(([z,G])=>{G.model_list&&(G.model_list.some(Y=>$.has(Y))||L.delete(z))})):(S.add(l),n.filter(z=>z.api_provider===l).forEach(z=>$.add(z.name)),Object.entries(u).forEach(([z,G])=>{G.model_list&&G.model_list.some(Y=>{const Ve=n.find(ze=>ze.name===Y);return Ve&&Ve.api_provider===l})&&L.add(z)})),j(S),m($),A(L)},me=l=>{const S=new Set(v),$=new Set(f);S.has(l)?(S.delete(l),Object.entries(u).forEach(([L,U])=>{U.model_list&&(U.model_list.some(G=>S.has(G))||$.delete(L))})):(S.add(l),Object.entries(u).forEach(([L,U])=>{U.model_list&&U.model_list.includes(l)&&$.add(L)})),m(S),A($)},$e=l=>{const S=new Set(f);S.has(l)?S.delete(l):S.add(l),A(S)},is=l=>{X.includes(l)?we(X.filter(S=>S!==l)):X.length<5?we([...X,l]):ie({title:"最多选择 5 个标签",variant:"destructive"})},ke=()=>{R.size===_.length?j(new Set):j(new Set(_.map(l=>l.name)))},cs=()=>{v.size===n.length?m(new Set):m(new Set(n.map(l=>l.name)))},Be=()=>{const l=Object.keys(u);f.size===l.length?A(new Set):A(new Set(l))},os=async()=>{if(!se.trim()){ie({title:"请输入模板名称",variant:"destructive"});return}if(!d.trim()){ie({title:"请输入模板描述",variant:"destructive"});return}if(!q.trim()){ie({title:"请输入作者名称",variant:"destructive"});return}if(R.size===0&&v.size===0&&f.size===0){ie({title:"请至少选择一项配置",variant:"destructive"});return}P(!0);try{const l=_.filter(L=>R.has(L.name)),S=n.filter(L=>v.has(L.name)),$={};for(const[L,U]of Object.entries(u))f.has(L)&&($[L]=U);await Ua({name:se.trim(),description:d.trim(),author:q.trim(),tags:X,providers:l,models:S,task_config:$}),ie({title:"模板已提交审核,审核通过后将显示在市场中"}),g(!1),Ee()}catch(l){console.error("提交失败:",l),ie({title:l instanceof Error?l.message:"提交失败",variant:"destructive"})}finally{P(!1)}},Ee=()=>{w(1),te(""),E(""),De(""),we([]),j(new Set),m(new Set),A(new Set)},Ke=2;return e.jsxs(ks,{open:c,onOpenChange:g,children:[e.jsx(Na,{asChild:!0,children:T||e.jsxs(N,{variant:"outline",children:[e.jsx(St,{className:"w-4 h-4 mr-2"}),"分享配置"]})}),e.jsxs(ys,{className:"max-w-2xl flex flex-col",confirmOnEnter:!0,children:[e.jsxs(Cs,{children:[e.jsxs(Ss,{className:"flex items-center gap-2",children:[e.jsx(Ga,{className:"w-5 h-5"}),"分享配置模板"]}),e.jsxs(Ts,{children:["步骤 ",x," / ",Ke,"",x===1&&"选择要分享的配置",x===2&&"填写模板信息"]})]}),e.jsx(ht,{children:h?e.jsxs("div",{className:"py-8 text-center",children:[e.jsx(as,{className:"w-8 h-8 mx-auto animate-spin text-primary"}),e.jsx("p",{className:"mt-4 text-muted-foreground",children:"正在加载当前配置..."})]}):e.jsxs(e.Fragment,{children:[x===1&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs(oe,{children:[e.jsx(rs,{className:"h-4 w-4"}),e.jsx(lt,{children:"安全提示"}),e.jsxs(de,{children:["分享的配置将",e.jsx("strong",{children:"不包含"})," API Key其他用户需要自行配置。"]})]}),e.jsxs(ft,{defaultValue:"providers",className:"w-full",children:[e.jsxs(pt,{className:"grid w-full grid-cols-3",children:[e.jsxs(Pe,{value:"providers",children:[e.jsx(ct,{className:"w-4 h-4 mr-2"}),"API 提供商",e.jsxs(ee,{variant:"secondary",className:"ml-2",children:[R.size,"/",_.length]})]}),e.jsxs(Pe,{value:"models",children:[e.jsx(ot,{className:"w-4 h-4 mr-2"}),"模型配置",e.jsxs(ee,{variant:"secondary",className:"ml-2",children:[v.size,"/",n.length]})]}),e.jsxs(Pe,{value:"tasks",children:[e.jsx(dt,{className:"w-4 h-4 mr-2"}),"任务配置",e.jsxs(ee,{variant:"secondary",className:"ml-2",children:[f.size,"/",Object.keys(u).length]})]})]}),e.jsx(Me,{value:"providers",className:"space-y-2 mt-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex justify-end",children:e.jsx(N,{variant:"ghost",size:"sm",onClick:ke,children:R.size===_.length?"取消全选":"全选"})}),_.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-2",children:"暂无提供商配置"}):_.map(l=>e.jsxs("div",{className:"flex items-center space-x-2 p-2 rounded hover:bg-muted",children:[e.jsx(Le,{id:`provider-${l.name}`,checked:R.has(l.name),onCheckedChange:()=>Oe(l.name)}),e.jsxs(O,{htmlFor:`provider-${l.name}`,className:"flex-1 cursor-pointer",children:[e.jsx("span",{className:"font-medium",children:l.name}),e.jsx("span",{className:"text-xs text-muted-foreground ml-2",children:l.base_url})]}),e.jsx(ee,{variant:"outline",className:"text-xs",children:l.client_type})]},l.name))]})}),e.jsx(Me,{value:"models",className:"space-y-2 mt-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex justify-end",children:e.jsx(N,{variant:"ghost",size:"sm",onClick:cs,children:v.size===n.length?"取消全选":"全选"})}),n.length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-2",children:"暂无模型配置"}):n.map(l=>e.jsxs("div",{className:"flex items-center space-x-2 p-2 rounded hover:bg-muted",children:[e.jsx(Le,{id:`model-${l.name}`,checked:v.has(l.name),onCheckedChange:()=>me(l.name)}),e.jsxs(O,{htmlFor:`model-${l.name}`,className:"flex-1 cursor-pointer",children:[e.jsx("span",{className:"font-medium",children:l.name}),e.jsx("span",{className:"text-xs text-muted-foreground ml-2",children:l.model_identifier})]}),e.jsx("span",{className:"text-xs text-muted-foreground",children:l.api_provider})]},l.name))]})}),e.jsx(Me,{value:"tasks",className:"space-y-2 mt-4",children:e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"flex justify-end",children:e.jsx(N,{variant:"ghost",size:"sm",onClick:Be,children:f.size===Object.keys(u).length?"取消全选":"全选"})}),Object.keys(u).length===0?e.jsx("p",{className:"text-sm text-muted-foreground text-center py-2",children:"暂无任务配置"}):Object.entries(u).map(([l,S])=>e.jsxs("div",{className:"space-y-2 p-2 rounded hover:bg-muted",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Le,{id:`task-${l}`,checked:f.has(l),onCheckedChange:()=>$e(l)}),e.jsx(O,{htmlFor:`task-${l}`,className:"flex-1 cursor-pointer",children:e.jsx("span",{className:"font-medium",children:br[l]||l})}),e.jsxs(ee,{variant:"outline",className:"text-xs",children:[S.model_list.length," 个模型"]})]}),S.model_list&&S.model_list.length>0&&e.jsx("div",{className:"ml-6 flex flex-wrap gap-1",children:S.model_list.map($=>{const L=n.find(z=>z.name===$),U=v.has($);return e.jsxs(ee,{variant:U?"default":"outline",className:"text-xs cursor-pointer hover:opacity-80 transition-opacity",onClick:()=>me($),children:[$,L&&e.jsxs("span",{className:"ml-1 opacity-70",children:["(",L.api_provider,")"]})]},$)})})]},l))]})})]})]}),x===2&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex gap-4 text-sm p-3 bg-muted rounded-lg",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(ct,{className:"w-4 h-4"}),R.size," 个提供商"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(ot,{className:"w-4 h-4"}),v.size," 个模型"]}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(dt,{className:"w-4 h-4"}),f.size," 个任务"]})]}),e.jsx(Va,{}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"pack-name",children:"模板名称 *"}),e.jsx(W,{id:"pack-name",placeholder:"例如:高性价比国产模型配置",value:se,onChange:l=>te(l.target.value),maxLength:50}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[se.length,"/50"]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"pack-description",children:"模板描述 *"}),e.jsx(Ka,{id:"pack-description",placeholder:"详细描述这个配置模板的特点、适用场景等...",value:d,onChange:l=>E(l.target.value),rows:4,maxLength:500}),e.jsxs("p",{className:"text-xs text-muted-foreground",children:[d.length,"/500"]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{htmlFor:"pack-author",children:"作者名称 *"}),e.jsx(W,{id:"pack-author",placeholder:"你的昵称或 ID",value:q,onChange:l=>De(l.target.value),maxLength:30})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{children:"标签(可选,最多 5 个)"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:_r.map(l=>e.jsxs(ee,{variant:X.includes(l)?"default":"outline",className:"cursor-pointer transition-colors",onClick:()=>is(l),children:[X.includes(l)&&e.jsx(Is,{className:"w-3 h-3 mr-1"}),e.jsx(Ja,{className:"w-3 h-3 mr-1"}),l]},l))})]})]}),e.jsxs(oe,{children:[e.jsx(rs,{className:"h-4 w-4"}),e.jsx(lt,{children:"审核说明"}),e.jsx(de,{children:"提交后需要经过审核才能在市场中展示。审核通常在 1-3 个工作日内完成。"})]})]})]})}),e.jsxs(Ps,{className:"flex justify-between pt-4 border-t",children:[e.jsx("div",{children:x>1&&e.jsx(N,{variant:"outline",onClick:()=>w(x-1),disabled:o,children:"上一步"})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(N,{variant:"outline",onClick:()=>{g(!1),Ee()},disabled:o,children:"取消"}),x<Ke?e.jsx(N,{"data-dialog-action":"confirm",onClick:()=>w(x+1),disabled:h||R.size===0&&v.size===0&&f.size===0,children:"下一步"}):e.jsxs(N,{"data-dialog-action":"confirm",onClick:os,disabled:o,children:[o&&e.jsx(as,{className:"w-4 h-4 mr-2 animate-spin"}),"提交审核"]})]})]})]})]})}function kr({value:T,label:c,onRemove:g}){const{attributes:x,listeners:w,setNodeRef:h,transform:k,transition:o,isDragging:P}=fr({id:T}),_={transform:pr.Transform.toString(k),transition:o,opacity:P?.5:1},y=i=>{i.preventDefault(),i.stopPropagation(),g(T)},n=i=>{i.stopPropagation()};return e.jsx("div",{ref:h,style:_,className:ts("inline-flex items-center gap-1",P&&"shadow-lg"),children:e.jsxs(ee,{variant:"secondary",className:"cursor-move hover:bg-secondary/80 flex items-center gap-1",children:[e.jsx("div",{...x,...w,className:"cursor-grab active:cursor-grabbing flex items-center",children:e.jsx(qa,{className:"h-3 w-3 text-muted-foreground"})}),e.jsx("span",{children:c}),e.jsx("span",{role:"button",tabIndex:0,className:"ml-1 rounded-sm hover:bg-destructive/20 focus:outline-none focus:ring-1 focus:ring-destructive cursor-pointer",onClick:y,onPointerDown:n,onMouseDown:i=>i.stopPropagation(),onKeyDown:i=>{(i.key==="Enter"||i.key===" ")&&(i.preventDefault(),y(i))},children:e.jsx(Ha,{className:"h-3 w-3 hover:text-destructive",strokeWidth:2,fill:"none"})})]})})}function yr({options:T,selected:c,onChange:g,placeholder:x="选择选项...",emptyText:w="未找到选项",className:h}){const[k,o]=a.useState(!1),P=lr(ut(hr,{activationConstraint:{distance:8}}),ut(xr,{coordinateGetter:ur})),_=i=>{c.includes(i)?g(c.filter(u=>u!==i)):g([...c,i])},y=i=>{g(c.filter(u=>u!==i))},n=i=>{const{active:u,over:C}=i;if(C&&u.id!==C.id){const R=c.indexOf(u.id),j=c.indexOf(C.id);g(mr(c,R,j))}};return e.jsxs(wt,{open:k,onOpenChange:o,children:[e.jsx(kt,{asChild:!0,children:e.jsxs(N,{variant:"outline",role:"combobox","aria-expanded":k,className:ts("w-full justify-between min-h-10 h-auto",h),children:[e.jsx(ir,{sensors:P,collisionDetection:cr,onDragEnd:n,children:e.jsx(or,{items:c,strategy:dr,children:e.jsx("div",{className:"flex gap-1 flex-wrap flex-1",children:c.length===0?e.jsx("span",{className:"text-muted-foreground",children:x}):c.map(i=>{const u=T.find(C=>C.value===i);return e.jsx(kr,{value:i,label:u?.label||i,onRemove:y},i)})})})}),e.jsx(Tt,{className:"ml-2 h-4 w-4 shrink-0 opacity-50",strokeWidth:2,fill:"none"})]})}),e.jsx(yt,{className:"w-full p-0",align:"start",children:e.jsxs(gt,{children:[e.jsx(jt,{placeholder:"搜索...",className:"h-9"}),e.jsxs(vt,{children:[e.jsx(Nt,{children:w}),e.jsx(bt,{children:T.map(i=>{const u=c.includes(i.value);return e.jsxs(_t,{value:i.value,onSelect:()=>_(i.value),children:[e.jsx("div",{className:ts("mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",u?"bg-primary text-primary-foreground":"opacity-50 [&_svg]:invisible"),children:e.jsx(Is,{className:"h-3 w-3",strokeWidth:2,fill:"none"})}),e.jsx("span",{children:i.label})]},i.value)})})]})]})})]})}const Cr=[{value:"balance",label:"负载均衡balance",description:"优先选择当前使用次数较少的模型,适合多个同类模型共同承担请求。"},{value:"random",label:"随机选择random",description:"每次请求从模型列表中随机选择一个模型,适合简单分散请求。"},{value:"sequential",label:"按顺序优先sequential",description:"优先使用模型列表中靠前的模型,前面的模型不可用时再尝试后面的模型。"}],Sr=ns.memo(function({title:c,description:g,taskConfig:x,modelNames:w,onChange:h,hideTemperature:k=!1,hideMaxTokens:o=!1,advanced:P=!1,showAdvancedSettings:_=!1,dataTour:y}){const n=i=>{h("model_list",i)};return e.jsxs("div",{className:ts("rounded-lg border bg-card p-4 sm:p-6 space-y-4",P&&"border-amber-300 bg-amber-50/40 dark:border-amber-500/50 dark:bg-amber-500/10"),children:[e.jsxs("div",{children:[e.jsx("h4",{className:"font-semibold text-base sm:text-lg",children:c}),e.jsx("p",{className:"text-xs sm:text-sm text-muted-foreground mt-1",children:g})]}),e.jsxs("div",{className:"grid gap-4",children:[e.jsxs("div",{className:"grid gap-2","data-tour":y,children:[e.jsx(O,{children:"模型列表"}),e.jsx(yr,{options:w.map(i=>({label:i,value:i})),selected:x.model_list||[],onChange:n,placeholder:"选择模型...",emptyText:"暂无可用模型"})]}),e.jsxs("div",{className:"grid grid-cols-1 gap-4 lg:grid-cols-3",children:[!k&&e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(O,{children:"温度"}),e.jsx(W,{type:"number",step:"0.1",min:"0",max:"2",value:x.temperature??.7,onChange:i=>{const u=parseFloat(i.target.value);!isNaN(u)&&u>=0&&u<=2&&h("temperature",u)},className:"w-20 h-8 text-sm"})]}),e.jsx(Ct,{value:[x.temperature??.7],onValueChange:i=>h("temperature",i[0]),min:0,max:2,step:.1,className:"w-full"})]}),!o&&e.jsxs("div",{className:"grid gap-2",children:[e.jsx(O,{children:"最大 Token"}),e.jsx(W,{type:"number",step:"1",min:"1",value:x.max_tokens??1024,onChange:i=>h("max_tokens",parseInt(i.target.value))})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsx(O,{children:"模型选择策略"}),e.jsxs(Ms,{value:x.selection_strategy??"balance",onValueChange:i=>h("selection_strategy",i),children:[e.jsx(Ds,{children:e.jsx(Os,{placeholder:"选择模型选择策略"})}),e.jsx(Es,{children:e.jsx(ba,{delayDuration:150,children:Cr.map(i=>e.jsxs(_a,{children:[e.jsx(wa,{asChild:!0,children:e.jsx(zs,{value:i.value,title:i.description,children:i.label})}),e.jsx(ka,{side:"right",align:"center",className:"max-w-72 bg-background text-foreground border shadow-lg",children:i.description})]},i.value))})})]})]})]}),_&&e.jsxs("div",{className:"grid gap-2 rounded-md border border-amber-200 bg-amber-50/50 p-3 dark:border-amber-500/40 dark:bg-amber-500/10",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(O,{children:"慢请求阈值 (秒)"}),e.jsx("span",{className:"text-xs text-muted-foreground",children:"高级配置"})]}),e.jsx(W,{type:"number",step:"1",min:"1",value:x.slow_threshold??15,onChange:i=>{const u=parseInt(i.target.value);!isNaN(u)&&u>=1&&h("slow_threshold",u)},placeholder:"15"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"模型响应时间超过此阈值将输出警告日志"})]})]})]})}),Tr=ns.memo(function({paginatedModels:c,allModels:g,onEdit:x,onDelete:w,isModelUsed:h,searchQuery:k}){return c.length===0?e.jsx("div",{className:"md:hidden text-center text-muted-foreground py-8 rounded-lg border bg-card",children:k?"未找到匹配的模型":"暂无模型配置"}):e.jsx("div",{className:"md:hidden space-y-3",children:c.map((o,P)=>{const _=g.findIndex(n=>n===o),y=h(o.name);return e.jsxs("div",{className:"rounded-lg border bg-card p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[e.jsx("h3",{className:"font-semibold text-base",children:o.name}),e.jsx("span",{className:`block h-3 w-3 shrink-0 rounded-full border ${y?"border-green-500 bg-green-500 shadow-[0_0_0_3px_rgba(34,197,94,0.18)]":"border-green-700/40 bg-green-950/20"}`,title:y?"已使用":"未使用","aria-label":y?"已使用":"未使用"})]}),e.jsx("p",{className:"text-xs text-muted-foreground break-all",title:o.model_identifier,children:o.model_identifier})]}),e.jsxs("div",{className:"flex gap-1 flex-shrink-0",children:[e.jsxs(N,{variant:"default",size:"sm",onClick:()=>x(o,_),children:[e.jsx(Pt,{className:"h-4 w-4 mr-1",strokeWidth:2,fill:"none"}),"编辑"]}),e.jsxs(N,{size:"sm",onClick:()=>w(_),className:"bg-red-600 hover:bg-red-700 text-white",children:[e.jsx(Te,{className:"h-4 w-4 mr-1",strokeWidth:2,fill:"none"}),"删除"]})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2 text-sm",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"提供商"}),e.jsx("p",{className:"font-medium",children:o.api_provider})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"视觉"}),e.jsx("p",{className:"flex h-5 items-center",children:e.jsx("span",{className:`block h-3 w-3 rounded-full border ${o.visual?"border-green-500 bg-green-500 shadow-[0_0_0_3px_rgba(34,197,94,0.18)]":"border-green-700/40 bg-green-950/20"}`,title:o.visual?"已启用视觉":"未启用视觉","aria-label":o.visual?"已启用视觉":"未启用视觉"})})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"输入价格"}),e.jsxs("p",{className:"font-medium",children:["¥",o.price_in,"/M"]})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"输出价格"}),e.jsxs("p",{className:"font-medium",children:["¥",o.price_out,"/M"]})]})]})]},P)})})}),Pr=ns.memo(function({paginatedModels:c,allModels:g,filteredModels:x,selectedModels:w,onEdit:h,onDelete:k,onToggleSelection:o,onToggleSelectAll:P,isModelUsed:_,searchQuery:y}){return e.jsx("div",{className:"hidden md:block rounded-lg border bg-card overflow-hidden",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs(gr,{"aria-label":"模型列表",children:[e.jsx(jr,{children:e.jsxs(_s,{children:[e.jsx(Q,{className:"w-12",children:e.jsx(Le,{checked:w.size===x.length&&x.length>0,onCheckedChange:P})}),e.jsx(Q,{className:"w-14 text-center",children:"使用"}),e.jsx(Q,{children:"模型名称"}),e.jsx(Q,{children:"模型标识符"}),e.jsx(Q,{children:"提供商"}),e.jsx(Q,{className:"w-14 text-center",children:"视觉"}),e.jsx(Q,{className:"text-center",children:"温度"}),e.jsx(Q,{className:"text-right",children:"输入价格"}),e.jsx(Q,{className:"text-right",children:"输出价格"}),e.jsx(Q,{className:"text-right",children:"操作"})]})}),e.jsx(vr,{children:c.length===0?e.jsx(_s,{children:e.jsx(H,{colSpan:10,className:"text-center text-muted-foreground py-8",children:y?"未找到匹配的模型":"暂无模型配置"})}):c.map((n,i)=>{const u=g.findIndex(R=>R===n),C=_(n.name);return e.jsxs(_s,{children:[e.jsx(H,{children:e.jsx(Le,{checked:w.has(u),onCheckedChange:()=>o(u)})}),e.jsx(H,{className:"text-center",children:e.jsx("span",{className:`mx-auto block h-3 w-3 rounded-full border ${C?"border-green-500 bg-green-500 shadow-[0_0_0_3px_rgba(34,197,94,0.18)]":"border-green-700/40 bg-green-950/20"}`,title:C?"已使用":"未使用","aria-label":C?"已使用":"未使用"})}),e.jsx(H,{className:"font-medium",children:n.name}),e.jsx(H,{className:"max-w-xs truncate",title:n.model_identifier,children:n.model_identifier}),e.jsx(H,{children:n.api_provider}),e.jsx(H,{className:"text-center",children:e.jsx("span",{className:`mx-auto block h-3 w-3 rounded-full border ${n.visual?"border-green-500 bg-green-500 shadow-[0_0_0_3px_rgba(34,197,94,0.18)]":"border-green-700/40 bg-green-950/20"}`,title:n.visual?"已启用视觉":"未启用视觉","aria-label":n.visual?"已启用视觉":"未启用视觉"})}),e.jsx(H,{className:"text-center",children:n.temperature!=null?n.temperature:e.jsx("span",{className:"text-muted-foreground",children:"-"})}),e.jsxs(H,{className:"text-right",children:["¥",n.price_in,"/M"]}),e.jsxs(H,{className:"text-right",children:["¥",n.price_out,"/M"]}),e.jsx(H,{className:"text-right",children:e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsxs(N,{variant:"default",size:"sm",onClick:()=>h(n,u),children:[e.jsx(Pt,{className:"h-4 w-4 mr-1",strokeWidth:2,fill:"none"}),"编辑"]}),e.jsxs(N,{size:"sm",onClick:()=>k(u),className:"bg-red-600 hover:bg-red-700 text-white",children:[e.jsx(Te,{className:"h-4 w-4 mr-1",strokeWidth:2,fill:"none"}),"删除"]})]})})]},i)})})]})})})}),Mr=300*1e3,xt=new Map,Dr=[10,20,50,100],Or=ns.memo(function({page:c,pageSize:g,totalItems:x,jumpToPage:w,onPageChange:h,onPageSizeChange:k,onJumpToPageChange:o,onJumpToPage:P,onSelectionClear:_}){const y=Math.ceil(x/g),n=u=>{k(parseInt(u)),h(1),_?.()},i=u=>{u.key==="Enter"&&P()};return x===0?null:e.jsxs("div",{className:"flex flex-col sm:flex-row items-center justify-between gap-4 mt-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(O,{htmlFor:"page-size-model",className:"text-sm whitespace-nowrap",children:"每页显示"}),e.jsxs(Ms,{value:g.toString(),onValueChange:n,children:[e.jsx(Ds,{id:"page-size-model",className:"w-20",children:e.jsx(Os,{})}),e.jsx(Es,{children:Dr.map(u=>e.jsx(zs,{value:u.toString(),children:u},u))})]}),e.jsxs("span",{className:"text-sm text-muted-foreground",children:["显示 ",(c-1)*g+1," 到"," ",Math.min(c*g,x)," 条,共 ",x," 条"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(N,{variant:"outline",size:"sm",onClick:()=>h(1),disabled:c===1,className:"hidden sm:flex",children:e.jsx(Qa,{className:"h-4 w-4"})}),e.jsxs(N,{variant:"outline",size:"sm",onClick:()=>h(Math.max(1,c-1)),disabled:c===1,children:[e.jsx(Xa,{className:"h-4 w-4 sm:mr-1"}),e.jsx("span",{className:"hidden sm:inline",children:"上一页"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(W,{type:"number",value:w,onChange:u=>o(u.target.value),onKeyDown:i,placeholder:c.toString(),className:"w-16 h-8 text-center",min:1,max:y}),e.jsx(N,{variant:"outline",size:"sm",onClick:P,disabled:!w,className:"h-8",children:"跳转"})]}),e.jsxs(N,{variant:"outline",size:"sm",onClick:()=>h(c+1),disabled:c>=y,children:[e.jsx("span",{className:"hidden sm:inline",children:"下一页"}),e.jsx(Ya,{className:"h-4 w-4 sm:ml-1"})]}),e.jsx(N,{variant:"outline",size:"sm",onClick:()=>h(y),disabled:c>=y,className:"hidden sm:flex",children:e.jsx(Za,{className:"h-4 w-4"})})]})]})});function Er(T){const{models:c,taskConfig:g,debounceMs:x=2e3,onSavingChange:w,onUnsavedChange:h}=T,k=a.useRef(null),o=a.useRef(null),P=a.useRef(!0),_=a.useRef(null),y=a.useRef(null),n=a.useCallback(()=>{k.current&&(clearTimeout(k.current),k.current=null),o.current&&(clearTimeout(o.current),o.current=null)},[]),i=a.useCallback(m=>{const f={model_identifier:m.model_identifier,name:m.name,api_provider:m.api_provider,price_in:m.price_in??0,price_out:m.price_out??0,cache:m.cache??!1,cache_price_in:m.cache_price_in??0,visual:m.visual??!1,force_stream_mode:m.force_stream_mode??!1,extra_params:m.extra_params??{}};return m.temperature!=null&&(f.temperature=m.temperature),m.max_tokens!=null&&(f.max_tokens=m.max_tokens),f},[]),u=a.useCallback(m=>JSON.stringify(m.map(i)),[i]),C=a.useCallback(m=>m?JSON.stringify(m):null,[]),R=a.useCallback((m,f)=>{_.current=u(m),y.current=C(f)},[u,C]),j=a.useCallback(async m=>{try{w?.(!0);const f=m.map(i),A=await ws("models",f);if(!A.success)throw new Error(A.error);_.current=JSON.stringify(f),h?.(!1)}catch(f){console.error("自动保存模型列表失败:",f),h?.(!0)}finally{w?.(!1)}},[w,h,i]),v=a.useCallback(async m=>{try{w?.(!0);const f=await ws("model_task_config",m);if(!f.success)throw new Error(f.error);y.current=JSON.stringify(m),h?.(!1)}catch(f){console.error("自动保存任务配置失败:",f),h?.(!0)}finally{w?.(!1)}},[w,h]);return a.useEffect(()=>{if(P.current)return;const m=u(c);if(_.current===null){_.current=m;return}if(m!==_.current)return h?.(!0),k.current&&clearTimeout(k.current),k.current=setTimeout(()=>{j(c)},x),()=>{k.current&&clearTimeout(k.current)}},[c,j,x,h,u]),a.useEffect(()=>{if(P.current||!g)return;const m=C(g);if(y.current===null){y.current=m;return}if(m!==y.current)return h?.(!0),o.current&&clearTimeout(o.current),o.current=setTimeout(()=>{v(g)},x),()=>{o.current&&clearTimeout(o.current)}},[g,v,x,h,C]),a.useEffect(()=>()=>{n()},[n]),{clearTimers:n,initialLoadRef:P,resetSnapshots:R}}function zr(T={}){const{onOpenEditDialog:c,onCloseEditDialog:g,onOpenProviderDialog:x,onCloseProviderDialog:w,onOpenProvidersTab:h,onOpenModelsTab:k,onOpenTasksTab:o}=T,P=va(),{registerTour:_,startTour:y,state:n,goToStep:i}=ya(),u=a.useRef(n.stepIndex),C=a.useCallback((j,v)=>{if((j.target instanceof Element?j.target:null)?.closest(v))return!0;const f=document.querySelector(v);if(!f)return!1;const A=f.getBoundingClientRect();return j.clientX>=A.left&&j.clientX<=A.right&&j.clientY>=A.top&&j.clientY<=A.bottom},[]);return a.useEffect(()=>{_(Se,Ea)},[_]),a.useEffect(()=>{if(n.activeTourId!==Se||!n.isRunning)return;const j=za[n.stepIndex];j&&window.location.pathname!==j&&P({to:j})},[n.stepIndex,n.activeTourId,n.isRunning,P]),a.useEffect(()=>{if(n.activeTourId!==Se||!n.isRunning)return;const j=u.current,v=n.stepIndex;v<=2&&h?.(),j>=3&&j<=9&&v<3&&w?.(),j<=2&&v>=3&&v<=9&&x?.(),(v===10||v===11)&&(w?.(),k?.()),j>=12&&j<=17&&v<12&&g?.(),j<=11&&v>=12&&v<=17&&c?.(),v===19&&o?.(),u.current=v},[n.stepIndex,n.activeTourId,n.isRunning,c,g,x,w,h,k,o]),a.useEffect(()=>{if(n.activeTourId!==Se||!n.isRunning)return;const j=v=>{const m=n.stepIndex;m===1&&C(v,'[data-tour="providers-tab-trigger"]')?(h?.(),setTimeout(()=>i(2),300)):m===2&&C(v,'[data-tour="add-provider-button"]')?(x?.(),setTimeout(()=>i(3),300)):m===9&&C(v,'[data-tour="provider-cancel-button"]')?(w?.(),setTimeout(()=>i(10),300)):m===10&&C(v,'[data-tour="models-tab-trigger"]')?(k?.(),setTimeout(()=>i(11),300)):m===11&&C(v,'[data-tour="add-model-button"]')?(c?.(),setTimeout(()=>i(12),300)):m===17&&C(v,'[data-tour="model-cancel-button"]')?(g?.(),setTimeout(()=>i(18),300)):m===18&&C(v,'[data-tour="tasks-tab-trigger"]')&&(o?.(),setTimeout(()=>i(19),300))};return document.addEventListener("click",j,!0),()=>document.removeEventListener("click",j,!0)},[n,i,c,g,x,w,h,k,o,C]),{startTour:a.useCallback(()=>{h?.(),y(Se)},[y,h]),isRunning:n.isRunning&&n.activeTourId===Se,stepIndex:n.stepIndex}}function Ir(T){const{getProviderConfig:c}=T,[g,x]=a.useState([]),[w,h]=a.useState(!1),[k,o]=a.useState(null),[P,_]=a.useState(null),y=a.useCallback(()=>{x([]),o(null),_(null)},[]),n=a.useCallback(async(i,u=!1)=>{const C=c(i);if(!C?.base_url){x([]),_(null),o('提供商配置不完整,请先在"模型厂商设置"中配置');return}if(!C.api_key){x([]),_(null),o('该提供商未配置 API Key请先在"模型厂商设置"中填写');return}const R=Ia(C.base_url);if(_(R),!R?.modelFetcher){x([]),o(null);return}const j=`${i}:${C.base_url}`,v=xt.get(j);if(!u&&v&&Date.now()-v.timestamp<Mr){x(v.models),o(null);return}h(!0),o(null);try{const m=await Ca(i,R.modelFetcher.parser,R.modelFetcher.endpoint);if(!m.success)throw new Error(m.error);const f=m.data;x(f),xt.set(j,{models:f,timestamp:Date.now()})}catch(m){console.error("获取模型列表失败:",m);const f=m.message||"获取模型列表失败";f.includes("无效")||f.includes("过期")||f.includes("API Key")?o('API Key 无效或已过期,请检查"模型厂商设置"中的密钥'):f.includes("权限")?o("没有权限获取模型列表,请检查 API Key 权限"):f.includes("timeout")||f.includes("超时")?o("请求超时,请检查网络连接后重试"):f.includes("不支持")?o("该提供商不支持自动获取模型列表,请手动输入"):o(f),x([])}finally{h(!1)}},[c]);return{availableModels:g,fetchingModels:w,modelFetchError:k,matchedTemplate:P,fetchModelsForProvider:n,clearModels:y}}function ss(T){return T&&typeof T=="object"&&"config"in T?T.config:T}function Rr(T){return new Set((T?.fields??[]).filter(c=>c.type==="object"&&!c.advanced).map(c=>c.name))}function ln(){return e.jsx(Fa,{children:e.jsx(Ar,{})})}function Ar(){const{i18n:T}=Sa(),[c,g]=a.useState([]),[x,w]=a.useState([]),[h,k]=a.useState([]),[o,P]=a.useState([]),[_,y]=a.useState([]),[n,i]=a.useState(null),[u,C]=a.useState(!0),[R,j]=a.useState(!1),[v,m]=a.useState(!1),[f,A]=a.useState(!1),[se,te]=a.useState(!1),[d,E]=a.useState(null),[q,De]=a.useState(null),[X,we]=a.useState(!1),[ls,Oe]=a.useState(!1),[me,$e]=a.useState(null),[is,ke]=a.useState(!1),[cs,Be]=a.useState(null),[os,Ee]=a.useState(null),[Ke,l]=a.useState(!1),[S,$]=a.useState(null),[L,U]=a.useState(""),[z,G]=a.useState(new Set),[J,Y]=a.useState(new Set),[Ve,ze]=a.useState(!1),[Mt,ds]=a.useState(!1),[ue,Rs]=a.useState(new Set),[Dt,Ot]=a.useState(new Map),[V,ms]=a.useState({isOpen:!1,providersToDelete:[],affectedModels:[],pendingProviders:[],context:"auto",oldProviders:[]}),[us,Et]=a.useState(null),As=a.useRef(null),[xs,Fs]=a.useState(1),[We,zt]=a.useState(20),[Ls,$s]=a.useState(""),[It,Ue]=a.useState("providers"),[Bs,Ks]=a.useState(!1),[hs,Rt]=a.useState(!1),[At,Ft]=a.useState(()=>localStorage.getItem("model-config-restart-notice-dismissed")!=="true"),[Lt,$t]=a.useState(()=>localStorage.getItem("model-assignment-tour-entry-dismissed")!=="true"),[Vs,Ws]=a.useState(!1),Z=a.useRef(null),xe=a.useRef(null),[Bt,Ge]=a.useState(!1),Je=a.useRef([]),Ie=a.useRef(null),[Us,Gs]=a.useState([]),[Js,Kt]=a.useState([]),[K,ye]=a.useState({}),{toast:D}=Ta(),{triggerRestart:Vt,isRestarting:fs}=La(),{clearTimers:qs,initialLoadRef:Ce,resetSnapshots:qe}=Er({models:c,taskConfig:n,onSavingChange:m,onUnsavedChange:A}),ae=a.useCallback((s,t,r)=>{if(!s)return;const p=new Set(t.map(F=>F.name)),M=Rr(r??As.current),I=[],b=[];for(const[F,B]of Object.entries(s)){if(!B)continue;if(!B.model_list||B.model_list.length===0){M.has(F)&&b.push(F);continue}const nt=B.model_list.filter(ja=>!p.has(ja));nt.length>0&&I.push({taskName:F,invalidModels:nt})}Gs(I),Kt(b)},[]),ps=a.useCallback(async()=>{try{C(!0);const[s,t]=await Promise.all([Ze(),Pa()]);if(!s.success){D({title:"加载失败",description:s.error,variant:"destructive"}),C(!1);return}const r=ss(s.data),p=r.models||[];g(p),y(p.map(B=>B.name));const M=r.api_providers||[];w(M.map(B=>B.name)),k(M),P(M.map(B=>ce(B))),xe.current=JSON.stringify(M.map(B=>ce(B)));const I=r.model_task_config||null;i(I),qe(p,I);let b=null;t.success&&t.data&&(b=t.data.schema.nested?.model_task_config??null,As.current=b,Et(b)),ae(I,p,b);const F=I?.embedding?.model_list||[];Je.current=[...F],A(!1),Ce.current=!1}catch(s){console.error("加载配置失败:",s)}finally{C(!1)}},[Ce,ae,qe]);a.useEffect(()=>{ps()},[ps]);const Wt=a.useCallback(s=>h.find(t=>t.name===s),[h]),{availableModels:Ut,fetchingModels:He,modelFetchError:re,matchedTemplate:ne,fetchModelsForProvider:Qe,clearModels:Gt}=Ir({getProviderConfig:Wt});a.useEffect(()=>{se&&d?.api_provider&&Qe(d.api_provider)},[se,d?.api_provider,Qe]);const gs=async()=>{await Vt()},Jt=()=>{localStorage.setItem("model-config-restart-notice-dismissed","true"),Ft(!1)},qt=s=>{s.stopPropagation(),localStorage.setItem("model-assignment-tour-entry-dismissed","true"),$t(!1)},he=a.useCallback(s=>{const t=s.map(ce);P(t),w(t.map(r=>r.name)),k(t.map(r=>({name:r.name,base_url:r.base_url,api_key:r.api_key,client_type:r.client_type,max_retry:r.max_retry??2,timeout:r.timeout??30,retry_interval:r.retry_interval??10})))},[]),Hs=a.useCallback((s,t,r)=>{const p=new Set(r.map(b=>typeof b=="object"&&b!==null&&"name"in b?String(b.name):"").filter(Boolean));if(p.size===0)return{models:s,taskConfig:t};const M=s.filter(b=>!p.has(b.name));if(!t)return{models:M,taskConfig:t};const I={};for(const[b,F]of Object.entries(t))I[b]={...F,model_list:(F?.model_list||[]).filter(B=>!p.has(B))};return{models:M,taskConfig:I}},[]),Xe=a.useCallback(async(s,t="auto")=>{const r=new Set(o.map(b=>b.name)),p=new Set(s.map(b=>b.name)),M=Array.from(r).filter(b=>!p.has(b));if(M.length===0)return{shouldProceed:!0};const I=c.filter(b=>M.includes(b.api_provider));return I.length===0?{shouldProceed:!0}:(ms({isOpen:!0,providersToDelete:M,affectedModels:I,pendingProviders:s,context:t,oldProviders:[...o]}),{shouldProceed:!1})},[o,c]),js=a.useCallback(async(s,t="auto",r=[])=>{const p=s.map(ce),{models:M,taskConfig:I}=Hs(c,n,r);if(t==="auto"&&r.length===0){const b=await ws("api_providers",p);if(!b.success)throw new Error(b.error||"保存提供商失败")}else{const b=await Ze();if(!b.success)throw new Error(b.error||"加载模型配置失败");const F=ss(b.data);F.api_providers=p,F.models=M.map(vs),F.model_task_config=I;const B=await Ns(F);if(!B.success)throw new Error(B.error||"保存模型配置失败")}he(p),g(M),y(M.map(b=>b.name)),i(I),ae(I,M),xe.current=JSON.stringify(p),A(!1),t==="restart"&&await gs()},[ae,c,Hs,he,n]),Qs=a.useCallback(async s=>{if(Ce.current)return;const{shouldProceed:t}=await Xe(s,"auto");if(!t){A(!0);return}try{m(!0),await js(s,"auto")}catch(r){console.error("自动保存提供商失败:",r),D({title:"自动保存失败",description:r.message,variant:"destructive"}),A(!0)}finally{m(!1)}},[Xe,Ce,js,D]);a.useEffect(()=>{if(Ce.current)return;const s=JSON.stringify(o.map(ce));if(xe.current===null){xe.current=s;return}if(s!==xe.current)return A(!0),Z.current&&clearTimeout(Z.current),Z.current=setTimeout(()=>{Qs(o)},2e3),()=>{Z.current&&clearTimeout(Z.current)}},[o,Qs,Ce]);const Ht=a.useCallback(()=>{if(!n)return;const s=new Set(c.map(r=>r.name)),t={};for(const[r,p]of Object.entries(n))p&&p.model_list?t[r]={...p,model_list:p.model_list.filter(M=>s.has(M))}:t[r]=p;i(t),Gs([]),D({title:"清理完成",description:"已删除所有无效的模型引用"})},[n,c,D]),vs=s=>{const t={model_identifier:s.model_identifier,name:s.name,api_provider:s.api_provider,price_in:s.price_in??0,price_out:s.price_out??0,cache:s.cache??!1,cache_price_in:s.cache_price_in??0,visual:s.visual??!1,force_stream_mode:s.force_stream_mode??!1,extra_params:s.extra_params??{}};return s.temperature!=null&&(t.temperature=s.temperature),s.max_tokens!=null&&(t.max_tokens=s.max_tokens),t},Qt=async()=>{try{j(!0),qs(),Z.current&&clearTimeout(Z.current);const s=await Ze();if(!s.success){D({title:"保存失败",description:s.error,variant:"destructive"}),j(!1);return}const t=ss(s.data);t.api_providers=o.map(ce),t.models=c.map(vs),t.model_task_config=n;const r=await Ns(t);if(!r.success){D({title:"保存失败",description:r.error,variant:"destructive"}),j(!1);return}qe(t.models,n),xe.current=JSON.stringify(t.api_providers),A(!1),D({title:"保存成功",description:"正在重启麦麦..."}),await gs()}catch(s){console.error("保存配置失败:",s),D({title:"保存失败",description:s.message,variant:"destructive"}),j(!1)}},Xt=async()=>{try{j(!0),qs(),Z.current&&clearTimeout(Z.current);const s=await Ze();if(!s.success){D({title:"保存失败",description:s.error,variant:"destructive"}),j(!1);return}const t=ss(s.data);t.api_providers=o.map(ce),t.models=c.map(vs),t.model_task_config=n;const r=await Ns(t);if(!r.success){D({title:"保存失败",description:r.error,variant:"destructive"}),j(!1);return}qe(t.models,n),xe.current=JSON.stringify(t.api_providers),A(!1),D({title:"保存成功",description:"模型配置已保存"}),await ps()}catch(s){console.error("保存配置失败:",s),D({title:"保存失败",description:s.message,variant:"destructive"})}finally{j(!1)}},Re=(s,t)=>{ye({}),E(s||{model_identifier:"",name:"",api_provider:x[0]||"",price_in:0,price_out:0,cache:!1,cache_price_in:0,temperature:null,max_tokens:null,visual:!1,force_stream_mode:!1,extra_params:{}}),Ks(!1),De(t),te(!0)},Ye=(s,t)=>{Be(s||{name:"",base_url:"",api_key:"",client_type:"openai",max_retry:2,timeout:30,retry_interval:10}),Ee(t),ke(!0)},{startTour:Yt,isRunning:Xs}=zr({onOpenEditDialog:()=>Re(null,null),onCloseEditDialog:()=>te(!1),onOpenProviderDialog:()=>Ye(null,null),onCloseProviderDialog:()=>ke(!1),onOpenProvidersTab:()=>Ue("providers"),onOpenModelsTab:()=>Ue("models"),onOpenTasksTab:()=>Ue("tasks")}),Zt=(s,t)=>{const r=ce(s);if(t!==null){const p=[...o];p[t]=r,he(p)}else he([...o,r]);ke(!1),Be(null),Ee(null),D({title:t!==null?"提供商已更新":"提供商已添加",description:'配置将在 2 秒后自动保存,或点击右上角"保存配置"按钮立即保存'})},ea=()=>{if(!d)return;const s={};if(d.name?.trim()?c.some((I,b)=>q!==null&&b===q?!1:I.name.trim().toLowerCase()===d.name.trim().toLowerCase())&&(s.name="模型名称已存在,请使用其他名称"):s.name="请输入模型名称",d.api_provider?.trim()||(s.api_provider="请选择 API 提供商"),d.model_identifier?.trim()||(s.model_identifier="请输入模型标识符"),Object.keys(s).length>0){ye(s);return}ye({});const t={model_identifier:d.model_identifier,name:d.name,api_provider:d.api_provider,price_in:d.price_in??0,price_out:d.price_out??0,cache:d.cache??!1,cache_price_in:d.cache_price_in??0,visual:d.visual??!1,force_stream_mode:d.force_stream_mode??!1,extra_params:d.extra_params??{}};d.temperature!=null&&(t.temperature=d.temperature),d.max_tokens!=null&&(t.max_tokens=d.max_tokens);let r,p=null;if(q!==null?(p=c[q].name,r=[...c],r[q]=t):r=[...c,t],g(r),y(r.map(M=>M.name)),p&&p!==t.name&&n){const M=b=>b.map(F=>F===p?t.name:F),I={};for(const[b,F]of Object.entries(n))I[b]={...F,model_list:M(F?.model_list||[])};i(I)}te(!1),E(null),De(null),D({title:q!==null?"模型已更新":"模型已添加",description:'配置将在 2 秒后自动保存,或点击右上角"保存配置"按钮立即保存'})},sa=s=>{if(!s&&d){const t={...d,price_in:d.price_in??0,price_out:d.price_out??0};E(t)}te(s)},Ys=s=>{$e(s),Oe(!0)},ta=()=>{if(me!==null){const s=c.filter((t,r)=>r!==me);g(s),y(s.map(t=>t.name)),ae(n,s),D({title:"删除成功",description:'配置将在 2 秒后自动保存,或点击右上角"保存配置"按钮立即保存'})}Oe(!1),$e(null)},aa=s=>{$(s),l(!0)},ra=async()=>{if(S!==null){const s=o.filter((r,p)=>p!==S),{shouldProceed:t}=await Xe(s,"manual");t&&(he(s),D({title:"删除成功",description:"提供商已从列表中移除"}))}l(!1),$(null)},na=s=>{const t=new Set(J);t.has(s)?t.delete(s):t.add(s),Y(t)},la=()=>{J.size===o.length?Y(new Set):Y(new Set(o.map((s,t)=>t)))},Zs=()=>{if(J.size===0){D({title:"提示",description:"请先选择要删除的提供商",variant:"default"});return}ds(!0)},ia=async()=>{const s=o.filter((r,p)=>!J.has(p)),{shouldProceed:t}=await Xe(s,"manual");if(t){const r=J.size;he(s),Y(new Set),D({title:"批量删除成功",description:`已删除 ${r} 个提供商`})}ds(!1)},ca=async()=>{try{(V.context==="auto"?m:j)(!0),await js(V.pendingProviders,V.context,V.affectedModels),D({title:"删除成功",description:`已删除 ${V.providersToDelete.length} 个提供商和 ${V.affectedModels.length} 个关联模型`}),ms({isOpen:!1,providersToDelete:[],affectedModels:[],pendingProviders:[],context:"auto",oldProviders:[]}),Y(new Set)}catch(s){D({title:"删除失败",description:s.message,variant:"destructive"})}finally{j(!1),m(!1)}},oa=()=>{V.oldProviders.length>0&&he(V.oldProviders),ms({isOpen:!1,providersToDelete:[],affectedModels:[],pendingProviders:[],context:"auto",oldProviders:[]}),A(!1)},et=async s=>{Rs(t=>new Set(t).add(s));try{const t=await Oa(s);if(!t.success){D({title:"测试失败",description:t.error,variant:"destructive"});return}const r=t.data;Ot(p=>new Map(p).set(s,r)),r.network_ok&&r.api_key_valid!==!1?D({title:r.api_key_valid===!0?"连接正常":"网络连接正常",description:`${s} 可以访问 (${r.latency_ms}ms)`}):D({title:r.network_ok?"连接正常但 Key 无效":"连接失败",description:r.error||`${s} API Key 无效或无法连接`,variant:"destructive"})}catch(t){D({title:"测试失败",description:t.message,variant:"destructive"})}finally{Rs(t=>{const r=new Set(t);return r.delete(s),r})}},st=async()=>{for(const s of o)await et(s.name)},da=s=>{const t=new Set(z);t.has(s)?t.delete(s):t.add(s),G(t)},ma=()=>{if(z.size===le.length)G(new Set);else{const s=le.map((t,r)=>c.findIndex(p=>p===le[r]));G(new Set(s))}},tt=()=>{if(z.size===0){D({title:"提示",description:"请先选择要删除的模型",variant:"default"});return}ze(!0)},ua=()=>{const s=z.size,t=c.filter((r,p)=>!z.has(p));g(t),y(t.map(r=>r.name)),ae(n,t),G(new Set),ze(!1),D({title:"批量删除成功",description:`已删除 ${s} 个模型,配置将在 2 秒后自动保存`})},xa=(s,t,r)=>{if(!n)return;if(s==="embedding"&&t==="model_list"&&Array.isArray(r)){const M=Je.current,I=r;if((M.length!==I.length||M.some(F=>!I.includes(F))||I.some(F=>!M.includes(F)))&&M.length>0){Ie.current={field:t,value:r},Ge(!0);return}}const p={...n,[s]:{...n[s],[t]:r}};i(p),ae(p,c),s==="embedding"&&t==="model_list"&&Array.isArray(r)&&(Je.current=[...r])},ha=()=>{if(!n||!Ie.current)return;const{field:s,value:t}=Ie.current,r={...n,embedding:{...n.embedding,[s]:t}};i(r),ae(r,c),s==="model_list"&&Array.isArray(t)&&(Je.current=[...t]),Ie.current=null,Ge(!1),D({title:"嵌入模型已更新",description:"建议重新生成知识库向量以确保最佳匹配精度"})},fa=()=>{Ie.current=null,Ge(!1)},le=c.filter(s=>{if(!L)return!0;const t=L.toLowerCase();return s.name.toLowerCase().includes(t)||s.model_identifier.toLowerCase().includes(t)||s.api_provider.toLowerCase().includes(t)}),pa=Math.ceil(le.length/We),at=le.slice((xs-1)*We,xs*We),ga=()=>{const s=parseInt(Ls);s>=1&&s<=pa&&(Fs(s),$s(""))},rt=s=>n?Object.values(n).some(t=>t?.model_list?.includes(s)):!1;return u?e.jsx(bs,{className:"h-full",children:e.jsx("div",{className:"space-y-4 sm:space-y-6 p-4 sm:p-6",children:e.jsx("div",{className:"flex items-center justify-center h-64",children:e.jsx("p",{className:"text-muted-foreground",children:"加载中..."})})})}):e.jsx(bs,{className:"h-full",children:e.jsxs("div",{className:"space-y-4 sm:space-y-6 p-4 sm:p-6",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl sm:text-3xl font-bold",children:"模型管理与分配"}),e.jsx("p",{className:"text-muted-foreground mt-1 sm:mt-2 text-sm sm:text-base",children:"添加模型并为模型分配功能"})]}),e.jsxs("div",{className:"flex gap-2 w-full sm:w-auto",children:[e.jsx(wr,{trigger:e.jsxs(N,{variant:"outline",size:"sm",className:"flex-1 sm:flex-none",children:[e.jsx(St,{className:"mr-2 h-4 w-4"}),"分享配置"]})}),e.jsxs(N,{onClick:Xt,disabled:R||v||!f||fs,size:"sm",variant:"outline",className:"flex-1 sm:flex-none sm:min-w-[120px]",children:[e.jsx(er,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),R?"保存中...":v?"自动保存中...":f?"保存配置":"已保存"]}),e.jsxs(fe,{children:[e.jsx(Ma,{asChild:!0,children:e.jsxs(N,{disabled:R||v||fs,size:"sm",className:"flex-1 sm:flex-none sm:min-w-[120px]",children:[e.jsx(sr,{className:"mr-2 h-4 w-4"}),fs?"重启中...":f?"保存并重启":"重启麦麦"]})}),e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsx(je,{children:"确认重启麦麦?"}),e.jsx(ve,{asChild:!0,children:e.jsx("div",{children:e.jsx("p",{children:f?"当前有未保存的配置更改。点击确认将先保存配置,然后重启麦麦使新配置生效。重启过程中麦麦将暂时离线。":"即将重启麦麦主程序。重启过程中麦麦将暂时离线,配置将在重启后生效。"})})})]}),e.jsxs(Ne,{children:[e.jsx(be,{children:"取消"}),e.jsx(_e,{onClick:f?Qt:gs,children:f?"保存并重启":"确认重启"})]})]})]})]})]}),At&&e.jsxs(oe,{children:[e.jsx(rs,{className:"h-4 w-4"}),e.jsxs(de,{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("span",{children:["配置更新后需要",e.jsx("strong",{children:"重启麦麦"}),'才能生效。你可以点击右上角的"保存并重启"按钮一键完成保存和重启。']}),e.jsx(N,{type:"button",variant:"outline",size:"sm",onClick:Jt,children:"我知道了"})]})]}),Us.length>0&&e.jsxs(oe,{variant:"destructive",children:[e.jsx(Fe,{className:"h-4 w-4"}),e.jsxs(de,{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"flex-1",children:[e.jsx("strong",{children:"检测到无效的模型引用"}),e.jsx("div",{className:"mt-2 space-y-1",children:Us.map(({taskName:s,invalidModels:t})=>e.jsxs("div",{className:"text-sm",children:[e.jsx("strong",{children:s})," 引用了不存在的模型: ",t.join(", ")]},s))})]}),e.jsx(N,{variant:"outline",size:"sm",className:"shrink-0 bg-background hover:bg-accent",onClick:Ht,children:"一键清理"})]})]}),Js.length>0&&e.jsxs(oe,{variant:"default",className:"border-yellow-500/50 bg-yellow-500/10",children:[e.jsx(Fe,{className:"h-4 w-4 text-yellow-600"}),e.jsxs(de,{children:[e.jsx("strong",{className:"text-yellow-600",children:"以下任务未配置模型"}),e.jsxs("div",{className:"mt-2 text-sm",children:[Js.join("、")," 还未分配模型,这些功能将无法正常工作。"]})]})]}),Lt&&e.jsxs(oe,{className:"hidden lg:flex border-primary/30 bg-primary/5 cursor-pointer hover:bg-primary/10 transition-colors",onClick:Yt,children:[e.jsx(tr,{className:"h-4 w-4 text-primary"}),e.jsxs(de,{className:"flex items-center justify-between",children:[e.jsxs("span",{children:[e.jsx("strong",{className:"text-primary",children:"新手引导:"}),"不知道如何配置模型?点击这里开始学习如何为麦麦的组件分配模型。"]}),e.jsxs("div",{className:"ml-4 flex shrink-0 items-center gap-2",children:[e.jsx(N,{variant:"outline",size:"sm",children:"开始引导"}),e.jsx(N,{type:"button",variant:"ghost",size:"sm",onClick:qt,children:"关闭"})]})]})]}),e.jsxs(ft,{value:It,onValueChange:Ue,className:"w-full",children:[e.jsxs(pt,{className:"grid w-full grid-cols-3",children:[e.jsx(Pe,{value:"providers",className:"w-full","data-tour":"providers-tab-trigger",children:"模型厂商设置"}),e.jsx(Pe,{value:"models",className:"w-full","data-tour":"models-tab-trigger",children:"添加模型"}),e.jsx(Pe,{value:"tasks",className:"w-full","data-tour":"tasks-tab-trigger",children:"为模型分配功能"})]}),e.jsxs(Me,{value:"providers",className:"space-y-4 mt-0",children:[e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"管理 AI 模型厂商的 API 配置"}),e.jsxs("div",{className:"hidden",children:[J.size>0&&e.jsxs(N,{onClick:Zs,size:"sm",variant:"destructive",className:"w-full sm:w-auto",children:[e.jsx(Te,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),"批量删除 (",J.size,")"]}),e.jsxs(N,{onClick:st,size:"sm",variant:"outline",className:"w-full sm:w-auto",disabled:o.length===0||ue.size>0,children:[e.jsx(mt,{className:"mr-2 h-4 w-4"}),ue.size>0?`测试中 (${ue.size})`:"测试全部"]}),e.jsxs(N,{onClick:()=>Ye(null,null),size:"sm",variant:"outline",className:"w-full sm:w-auto","data-tour":"add-provider-button",children:[e.jsx(es,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),"添加提供商"]})]})]}),e.jsx(Ra,{providers:o,testingProviders:ue,testResults:Dt,selectedProviders:J,toolbarActions:e.jsxs(e.Fragment,{children:[J.size>0&&e.jsxs(N,{onClick:Zs,size:"sm",variant:"destructive",className:"w-full sm:w-auto",children:[e.jsx(Te,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),e.jsxs("span",{className:"text-sm",children:["批量删除 (",J.size,")"]})]}),e.jsxs(N,{onClick:st,size:"sm",variant:"outline",className:"w-full sm:w-auto",disabled:o.length===0||ue.size>0,children:[e.jsx(mt,{className:"mr-2 h-4 w-4"}),e.jsx("span",{className:"text-sm",children:ue.size>0?`测试中 (${ue.size})`:"测试全部连接"})]}),e.jsxs(N,{onClick:()=>Ye(null,null),size:"sm",variant:"outline",className:"w-full sm:w-auto","data-tour":"add-provider-button",children:[e.jsx(es,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),e.jsx("span",{className:"text-sm",children:"添加厂商"})]})]}),onEdit:Ye,onDelete:aa,onTest:et,onToggleSelect:na,onToggleSelectAll:la})]}),e.jsxs(Me,{value:"models",className:"space-y-4 mt-0",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row justify-between items-start sm:items-center gap-2",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"配置可用的模型列表"}),e.jsxs("div",{className:"hidden",children:[z.size>0&&e.jsxs(N,{onClick:tt,size:"sm",variant:"destructive",className:"w-full sm:w-auto",children:[e.jsx(Te,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),"批量删除 (",z.size,")"]}),e.jsxs(N,{onClick:()=>Re(null,null),size:"sm",variant:"outline",className:"w-full sm:w-auto","data-tour":"add-model-button",children:[e.jsx(es,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),"添加模型"]})]})]}),e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{className:"relative w-full sm:flex-1 sm:max-w-sm",children:[e.jsx(ar,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(W,{placeholder:"搜索模型名称、标识符或提供商...",value:L,onChange:s=>U(s.target.value),className:"pl-9"})]}),L&&e.jsxs("p",{className:"text-sm text-muted-foreground whitespace-nowrap",children:["找到 ",le.length," 个结果"]}),e.jsxs("div",{className:"flex w-full flex-col gap-2 sm:ml-auto sm:w-auto sm:flex-row sm:items-center sm:justify-end",children:[z.size>0&&e.jsxs(N,{onClick:tt,size:"sm",variant:"destructive",className:"w-full sm:w-auto",children:[e.jsx(Te,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),e.jsxs("span",{className:"text-sm",children:["批量删除 (",z.size,")"]})]}),e.jsxs(N,{onClick:()=>Re(null,null),size:"sm",variant:"outline",className:"w-full sm:w-auto","data-tour":"add-model-button",children:[e.jsx(es,{className:"mr-2 h-4 w-4",strokeWidth:2,fill:"none"}),e.jsx("span",{className:"text-sm",children:"添加模型"})]})]})]}),e.jsx(Tr,{paginatedModels:at,allModels:c,onEdit:Re,onDelete:Ys,isModelUsed:rt,searchQuery:L}),e.jsx(Pr,{paginatedModels:at,allModels:c,filteredModels:le,selectedModels:z,onEdit:Re,onDelete:Ys,onToggleSelection:da,onToggleSelectAll:ma,isModelUsed:rt,searchQuery:L}),e.jsx(Or,{page:xs,pageSize:We,totalItems:le.length,jumpToPage:Ls,onPageChange:Fs,onPageSizeChange:zt,onJumpToPageChange:$s,onJumpToPage:ga,onSelectionClear:()=>G(new Set)})]}),e.jsxs(Me,{value:"tasks",className:"space-y-6 mt-0",children:[e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"为不同的任务配置使用的模型和参数"}),us?.fields.some(s=>s.advanced)&&e.jsx(N,{type:"button",variant:hs?"default":"outline",size:"sm",onClick:()=>Rt(s=>!s),children:"高级设置"})]}),n&&us&&e.jsx("div",{className:"grid gap-4 sm:gap-6",children:us.fields.filter(s=>s.type==="object"&&(hs||!s.advanced)).map((s,t)=>e.jsx(Sr,{title:Da(s,T.language),description:s.description,taskConfig:n[s.name]??{model_list:[]},modelNames:_,onChange:(r,p)=>xa(s.name,r,p),advanced:s.advanced,showAdvancedSettings:hs,...t===0?{dataTour:"task-model-select"}:{}},s.name))})]})]}),e.jsx(Aa,{open:is,onOpenChange:ke,editingProvider:cs,editingIndex:os,providers:o,onSave:Zt,tourState:{isRunning:Xs}}),e.jsx(fe,{open:Ke,onOpenChange:l,children:e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsx(je,{children:"确认删除提供商"}),e.jsxs(ve,{children:['确定要删除提供商"',S!==null?o[S]?.name:"",'"吗? 如果该提供商下存在模型,确认时会提示一并处理关联模型。']})]}),e.jsxs(Ne,{children:[e.jsx(be,{children:"取消"}),e.jsx(_e,{onClick:ra,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"删除"})]})]})}),e.jsx(fe,{open:Mt,onOpenChange:ds,children:e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsx(je,{children:"确认批量删除提供商"}),e.jsxs(ve,{children:["确定要删除选中的 ",J.size," 个提供商吗? 如果这些提供商下存在模型,确认时会提示一并处理关联模型。"]})]}),e.jsxs(Ne,{children:[e.jsx(be,{children:"取消"}),e.jsx(_e,{onClick:ia,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"批量删除"})]})]})}),e.jsx(fe,{open:V.isOpen,children:e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsxs(je,{className:"flex items-center gap-2",children:[e.jsx(Fe,{className:"h-5 w-5 text-amber-500"}),"删除提供商会同时移除关联模型"]}),e.jsx(ve,{asChild:!0,children:e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsxs("p",{children:["将删除 ",V.providersToDelete.length," 个提供商,并移除"," ",V.affectedModels.length," 个使用这些提供商的模型。"]}),V.affectedModels.length>0&&e.jsxs("div",{className:"rounded-md bg-muted p-3 text-muted-foreground",children:[V.affectedModels.slice(0,8).map(s=>e.jsxs("div",{children:[s.name," (",s.api_provider,")"]},s.name)),V.affectedModels.length>8&&e.jsxs("div",{children:["还有 ",V.affectedModels.length-8," 个模型..."]})]}),e.jsx("p",{className:"font-medium text-foreground",children:"关联模型会从模型列表和任务分配中移除,此操作无法撤销。"})]})})]}),e.jsxs(Ne,{children:[e.jsx(be,{onClick:oa,children:"取消"}),e.jsx(_e,{onClick:ca,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"确认删除"})]})]})}),e.jsx(ks,{open:se,onOpenChange:sa,children:e.jsxs(ys,{className:"max-w-[95vw] sm:max-w-2xl","data-tour":"model-dialog",preventOutsideClose:Xs,confirmOnEnter:!0,children:[e.jsxs(Cs,{children:[e.jsx(Ss,{children:q!==null?"编辑模型":"添加模型"}),e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsx(Ts,{children:"配置模型的基本信息和参数"}),e.jsx(N,{type:"button",variant:Bs?"default":"outline",size:"sm",onClick:()=>Ks(s=>!s),className:"self-start sm:self-auto",children:"高级设置"})]})]}),e.jsx(ht,{children:e.jsxs("div",{className:"grid gap-4 py-4",children:[e.jsxs("div",{className:"grid gap-2","data-tour":"model-name-input",children:[e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center",children:[e.jsx(O,{htmlFor:"model_name",className:`sm:w-28 sm:flex-shrink-0 ${K.name?"text-destructive":""}`,children:"模型名称 *"}),e.jsx(W,{id:"model_name",value:d?.name||"",onChange:s=>{E(t=>t?{...t,name:s.target.value}:null),K.name&&ye(t=>({...t,name:void 0}))},placeholder:"例如: qwen3-30b",className:`sm:flex-1 ${K.name?"border-destructive focus-visible:ring-destructive":""}`})]}),K.name?e.jsx("p",{className:"text-xs text-destructive sm:pl-28",children:K.name}):null]}),e.jsxs("div",{className:"grid gap-2","data-tour":"model-provider-select",children:[e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center",children:[e.jsx(O,{htmlFor:"api_provider",className:`sm:w-28 sm:flex-shrink-0 ${K.api_provider?"text-destructive":""}`,children:"API 提供商 *"}),e.jsxs(Ms,{value:d?.api_provider||"",onValueChange:s=>{E(t=>t?{...t,api_provider:s}:null),Gt(),K.api_provider&&ye(t=>({...t,api_provider:void 0}))},children:[e.jsx(Ds,{id:"api_provider",className:`sm:flex-1 ${K.api_provider?"border-destructive focus-visible:ring-destructive":""}`,children:e.jsx(Os,{placeholder:"选择提供商"})}),e.jsx(Es,{children:x.map(s=>e.jsx(zs,{value:s,children:s},s))})]})]}),K.api_provider&&e.jsx("p",{className:"text-xs text-destructive sm:pl-28",children:K.api_provider})]}),e.jsxs("div",{className:"grid gap-2","data-tour":"model-identifier-input",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(O,{htmlFor:"model_identifier",className:K.model_identifier?"text-destructive":"",children:"模型标识符 *"}),ne?.modelFetcher&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(ee,{variant:"secondary",className:"text-xs",children:ne.display_name}),e.jsx(N,{variant:"ghost",size:"sm",className:"h-6 px-2",onClick:()=>d?.api_provider&&Qe(d.api_provider,!0),disabled:He,children:He?e.jsx(as,{className:"h-3 w-3 animate-spin"}):e.jsx(rr,{className:"h-3 w-3"})})]})]}),e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row",children:[ne?.modelFetcher&&e.jsxs(wt,{open:Vs,onOpenChange:Ws,children:[e.jsx(kt,{asChild:!0,children:e.jsxs(N,{variant:"outline",role:"combobox","aria-expanded":Vs,className:"w-full justify-between font-normal sm:w-[46%]",disabled:He||!!re,children:[He?e.jsxs("span",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(as,{className:"h-4 w-4 animate-spin"}),"正在获取模型列表..."]}):re?e.jsx("span",{className:"text-muted-foreground text-sm",children:"手动填写"}):d?.model_identifier?e.jsx("span",{className:"truncate",children:d.model_identifier}):e.jsx("span",{className:"text-muted-foreground",children:"搜索或选择模型..."}),e.jsx(Tt,{className:"ml-2 h-4 w-4 shrink-0 opacity-50"})]})}),e.jsx(yt,{className:"p-0",align:"start",style:{width:"var(--radix-popover-trigger-width)"},children:e.jsxs(gt,{children:[e.jsx(jt,{placeholder:"搜索模型..."}),e.jsx(bs,{className:"h-[300px]",children:e.jsxs(vt,{className:"max-h-none overflow-visible",children:[e.jsx(Nt,{children:re?e.jsxs("div",{className:"py-4 px-2 text-center space-y-2",children:[e.jsx("p",{className:"text-sm text-destructive",children:re}),!re.includes("API Key")&&e.jsx(N,{variant:"link",size:"sm",onClick:()=>d?.api_provider&&Qe(d.api_provider,!0),children:"重试"})]}):"未找到匹配的模型"}),e.jsx(bt,{heading:"可用模型",children:Ut.map(s=>e.jsxs(_t,{value:s.id,onSelect:()=>{E(t=>t?{...t,model_identifier:s.id}:null),Ws(!1)},children:[e.jsx(Is,{className:`mr-2 h-4 w-4 ${d?.model_identifier===s.id?"opacity-100":"opacity-0"}`}),e.jsxs("div",{className:"flex flex-col",children:[e.jsx("span",{children:s.id}),s.name!==s.id&&e.jsx("span",{className:"text-xs text-muted-foreground",children:s.name})]})]},s.id))})]})})]})})]}),e.jsx(W,{id:"model_identifier",value:d?.model_identifier||"",onChange:s=>{E(t=>t?{...t,model_identifier:s.target.value}:null),K.model_identifier&&ye(t=>({...t,model_identifier:void 0}))},placeholder:ne?.modelFetcher?"手动输入模型标识符":"Qwen/Qwen3-30B-A3B-Instruct-2507",className:`${ne?.modelFetcher?"sm:flex-1":"w-full"} ${K.model_identifier?"border-destructive focus-visible:ring-destructive":""}`})]}),K.model_identifier&&e.jsx("p",{className:"text-xs text-destructive",children:K.model_identifier}),re&&ne?.modelFetcher&&!K.model_identifier&&e.jsxs(oe,{variant:"destructive",className:"mt-2 py-2",children:[e.jsx(rs,{className:"h-4 w-4"}),e.jsx(de,{className:"text-xs",children:re})]}),!K.model_identifier&&e.jsx("p",{className:"text-xs text-muted-foreground",children:re?'请手动输入模型标识符,或前往"模型厂商设置"检查 API Key':ne?.modelFetcher?`已识别为 ${ne.display_name},支持自动获取模型列表`:"API 提供商提供的模型 ID"})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Ae,{id:"model_visual",checked:d?.visual||!1,onCheckedChange:s=>E(t=>t?{...t,visual:s}:null)}),e.jsx(O,{htmlFor:"model_visual",className:"cursor-pointer",children:"启用视觉"})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(O,{htmlFor:"price_in",className:"w-36 shrink-0",children:"输入价格 (¥/M token)"}),e.jsx(W,{id:"price_in",type:"number",step:"0.1",min:"0",value:d?.price_in??"",onChange:s=>{const t=s.target.value===""?null:parseFloat(s.target.value);E(r=>r?{...r,price_in:t}:null)},placeholder:"默认: 0",className:"flex-1"})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(O,{htmlFor:"price_out",className:"w-36 shrink-0",children:"输出价格 (¥/M token)"}),e.jsx(W,{id:"price_out",type:"number",step:"0.1",min:"0",value:d?.price_out??"",onChange:s=>{const t=s.target.value===""?null:parseFloat(s.target.value);E(r=>r?{...r,price_out:t}:null)},placeholder:"默认: 0",className:"flex-1"})]})]}),Bs&&e.jsxs("div",{className:"rounded-lg border border-amber-200 bg-amber-50/50 p-4 space-y-4 dark:border-amber-500/40 dark:bg-amber-500/10",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(O,{htmlFor:"model_cache",className:"cursor-pointer",children:"支持缓存计费"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"开启后,命中缓存的输入 token 会按缓存输入价格统计"})]}),e.jsx(Ae,{id:"model_cache",checked:d?.cache||!1,onCheckedChange:s=>E(t=>t?{...t,cache:s}:null)})]}),d?.cache&&e.jsxs("div",{className:"flex items-center gap-3 border-t pt-4",children:[e.jsx(O,{htmlFor:"cache_price_in",className:"w-40 shrink-0",children:"缓存输入价格 (¥/M token)"}),e.jsx(W,{id:"cache_price_in",type:"number",step:"0.1",min:"0",value:d?.cache_price_in??"",onChange:s=>{const t=s.target.value===""?null:parseFloat(s.target.value);E(r=>r?{...r,cache_price_in:t}:null)},placeholder:"默认: 0",className:"flex-1"})]}),e.jsxs("div",{className:"flex items-center justify-between gap-4 border-t pt-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(O,{htmlFor:"force_stream_mode",className:"cursor-pointer",children:"强制流式输出模式"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"用于必须通过流式响应返回内容的模型"})]}),e.jsx(Ae,{id:"force_stream_mode",checked:d?.force_stream_mode||!1,onCheckedChange:s=>E(t=>t?{...t,force_stream_mode:s}:null)})]})]}),e.jsxs("div",{className:"rounded-lg border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"space-y-0.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(O,{htmlFor:"enable_model_temperature",className:"cursor-pointer",children:"自定义模型温度"}),e.jsx(it,{content:e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"font-medium",children:"什么是温度Temperature"}),e.jsx("p",{children:"温度控制模型输出的随机性和创造性:"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"低温度0.1-0.3"}),":更确定、更保守的输出,适合事实性任务"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"中温度0.5-0.7"}),":平衡创造性与可控性"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"高温度0.8-1.0"}),":更有创意、更多样化的输出"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"极高温度1.0-2.0"}),":极度随机,可能产生不可预测的结果"]})]})]}),side:"right",maxWidth:"400px"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"启用后将覆盖「为模型分配功能」中的任务温度配置"})]}),e.jsx(Ae,{id:"enable_model_temperature",checked:d?.temperature!=null,onCheckedChange:s=>{E(s?t=>t?{...t,temperature:.7}:null:t=>t?{...t,temperature:null}:null)}})]}),d?.temperature!=null&&e.jsxs("div",{className:"space-y-3 pt-2 border-t",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx(O,{className:"text-sm",children:"温度值"}),e.jsx(W,{type:"number",value:d.temperature,onChange:s=>{const t=parseFloat(s.target.value);!isNaN(t)&&t>=0&&t<=2&&E(r=>r?{...r,temperature:t}:null)},onBlur:s=>{const t=parseFloat(s.target.value);isNaN(t)||t<0?E(r=>r?{...r,temperature:0}:null):t>2&&E(r=>r?{...r,temperature:2}:null)},step:.01,min:0,max:2,className:"w-20 h-8 text-sm text-right tabular-nums"})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-xs text-muted-foreground tabular-nums",children:"0"}),e.jsx(Ct,{value:[d.temperature],onValueChange:s=>E(t=>t?{...t,temperature:s[0]}:null),min:0,max:2,step:.05,className:"flex-1"}),e.jsx("span",{className:"text-xs text-muted-foreground tabular-nums",children:"2"})]}),d.temperature>1&&e.jsxs(oe,{className:"bg-amber-500/10 border-amber-500/20 [&>svg+div]:translate-y-0",children:[e.jsx(Fe,{className:"h-4 w-4 text-amber-500"}),e.jsx(de,{className:"text-xs text-amber-600 dark:text-amber-400",children:"温度 > 1 会产生更随机、更不可预测的输出,请谨慎使用"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"较低0.1-0.5产生确定输出中等0.5-1.0平衡创造性较高1.0-2.0)产生极度随机输出"})]})]}),e.jsxs("div",{className:"rounded-lg border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"space-y-0.5",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(O,{htmlFor:"enable_model_max_tokens",className:"cursor-pointer",children:"自定义最大 Token"}),e.jsx(it,{content:e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"font-medium",children:"什么是最大 Token"}),e.jsx("p",{children:"控制模型单次回复的最大长度。1 token ≈ 0.75 个英文单词或 0.5 个中文字符。"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"较小值512-1024"}),":简短回复,节省成本"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"中等值2048-4096"}),":正常对话长度"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"较大值8192+"}),":长文本生成,成本较高"]})]})]}),side:"right",maxWidth:"400px"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"启用后将覆盖「为模型分配功能」中的任务最大 Token 配置"})]}),e.jsx(Ae,{id:"enable_model_max_tokens",checked:d?.max_tokens!=null,onCheckedChange:s=>{E(s?t=>t?{...t,max_tokens:2048}:null:t=>t?{...t,max_tokens:null}:null)}})]}),d?.max_tokens!=null&&e.jsxs("div",{className:"space-y-2 pt-2 border-t",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(O,{className:"text-sm",children:"最大 Token 数"}),e.jsx(W,{type:"number",min:"1",max:"128000",value:d.max_tokens,onChange:s=>{const t=parseInt(s.target.value);!isNaN(t)&&t>=1&&E(r=>r?{...r,max_tokens:t}:null)},className:"w-28 h-8 text-sm"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"限制模型单次输出的最大 token 数量,不同模型支持的上限不同"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(O,{className:"text-sm font-medium",children:"额外参数"}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsxs(N,{type:"button",variant:"outline",size:"sm",className:"flex-1 justify-start h-9",onClick:()=>we(!0),children:[e.jsx(nr,{className:"h-4 w-4 mr-2"}),Object.keys(d?.extra_params||{}).length>0?e.jsxs("span",{children:["已配置 ",Object.keys(d?.extra_params||{}).length," 个参数"]}):e.jsx("span",{className:"text-muted-foreground",children:"未配置额外参数"})]})}),Object.keys(d?.extra_params||{}).length>0&&e.jsxs("div",{className:"text-xs text-muted-foreground px-1",children:[Object.keys(d?.extra_params||{}).slice(0,3).map(s=>e.jsx("span",{className:"inline-block mr-2",children:e.jsx("code",{className:"px-1.5 py-0.5 bg-muted rounded",children:s})},s)),Object.keys(d?.extra_params||{}).length>3&&e.jsx("span",{children:"..."})]})]})]})}),e.jsxs(Ps,{children:[e.jsx(N,{variant:"outline",onClick:()=>te(!1),"data-tour":"model-cancel-button",children:"取消"}),e.jsx(N,{"data-dialog-action":"confirm",onClick:ea,"data-tour":"model-save-button",children:"保存"})]})]})}),e.jsx(fe,{open:ls,onOpenChange:Oe,children:e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsx(je,{children:"确认删除"}),e.jsxs(ve,{children:['确定要删除模型 "',me!==null?c[me]?.name:"",'" 吗? 此操作无法撤销。']})]}),e.jsxs(Ne,{children:[e.jsx(be,{children:"取消"}),e.jsx(_e,{onClick:ta,children:"删除"})]})]})}),e.jsx(fe,{open:Ve,onOpenChange:ze,children:e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsx(je,{children:"确认批量删除"}),e.jsxs(ve,{children:["确定要删除选中的 ",z.size," 个模型吗? 此操作无法撤销。"]})]}),e.jsxs(Ne,{children:[e.jsx(be,{children:"取消"}),e.jsx(_e,{onClick:ua,className:"bg-destructive text-destructive-foreground hover:bg-destructive/90",children:"批量删除"})]})]})}),e.jsx(fe,{open:Bt,onOpenChange:Ge,children:e.jsxs(pe,{children:[e.jsxs(ge,{children:[e.jsxs(je,{className:"flex items-center gap-2",children:[e.jsx(Fe,{className:"h-5 w-5 text-amber-500"}),"更换嵌入模型警告"]}),e.jsx(ve,{asChild:!0,children:e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsxs("p",{children:[e.jsx("strong",{className:"text-foreground",children:"注意:"}),"更换嵌入模型可能会影响知识库的匹配精度!"]}),e.jsxs("ul",{className:"space-y-2 ml-4 list-disc text-muted-foreground",children:[e.jsx("li",{children:"不同的嵌入模型会产生不同的向量表示"}),e.jsx("li",{children:"这可能导致现有知识库的检索结果不准确"}),e.jsx("li",{children:"建议更换嵌入模型后重新生成所有知识库的向量"})]}),e.jsx("p",{className:"text-foreground font-medium",children:"确定要更换嵌入模型吗?"})]})})]}),e.jsxs(Ne,{children:[e.jsx(be,{onClick:fa,children:"取消"}),e.jsx(_e,{onClick:ha,className:"bg-amber-600 hover:bg-amber-700",children:"确认更换"})]})]})}),e.jsx(Nr,{open:X,onOpenChange:we,value:d?.extra_params||{},onChange:s=>E(t=>t?{...t,extra_params:s}:null)}),e.jsx($a,{})]})})}export{ln as ModelConfigPage};