2 lines
72 KiB
JavaScript
2 lines
72 KiB
JavaScript
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};
|