2 lines
31 KiB
JavaScript
2 lines
31 KiB
JavaScript
import{r as o,j as e}from"./router-zNjPR4CY.js";import{g as S,a7 as re,a8 as oe,a9 as ce,aa as de,E as me,D as pe,i as ue,j as he,k as xe,l as ge,a5 as je,L as A,B as p,S as fe,I as F,a3 as be}from"./index-CuOHsLf7.js";import{_ as h}from"./misc-BwRzHX8c.js";import{S as V,Y as ye,an as ve,b as Ne,$ as _e,a0 as Ce,c as ke,L as E,_ as q,u as $,v as H,e as M,W as Q,f as Z,ap as we,G as Ie,y as Ae,aq as Se}from"./icons-DTcdLw9j.js";import{P as Be,a as Fe,b as Te}from"./popover-DSuRLFDH.js";import{S as J,a as Y,b as X,c as ee,d as P}from"./select-DGqIoF9r.js";import{B as N}from"./badge-CDs67obV.js";import{C as K}from"./checkbox-DWiVrbnx.js";import{T as Oe,a as Pe,b as U,c as I,d as Le,e as k}from"./table-DFeDhBY_.js";const Qe="model-assignment-tour",De=[{target:"body",content:"本引导会帮你在同一个页面完成模型厂商、模型列表和功能分配配置。",placement:"center",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="providers-tab-trigger"]',content:'第一步,进入"模型厂商设置"。这里用于配置要连接的模型服务厂商或模型平台。',placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="add-provider-button"]',content:'点击"添加提供商"按钮,开始配置模型厂商的连接信息。',placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="provider-dialog"]',content:"在这里可以选择厂商模板,填写 API Key、URL 和连接参数,保存后即可供模型引用。",placement:"left",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="provider-name-input"]',content:"这里的名称用于在后续模型配置中识别这个厂商。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="provider-apikey-input"]',content:"这里填写从模型厂商获取的 API Key,用于验证并调用模型服务。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="provider-url-input"]',content:"这里填写模型厂商的 API 访问地址。不同厂商或平台的地址可能不同。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="provider-template-select"]',content:"如果不确定如何填写,可以从预设模板中选择常用厂商,相关信息会自动填充。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="provider-save-button"]',content:"填写完成后点击保存,模型厂商就配置好了。",placement:"top",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="provider-cancel-button"]',content:"这次只是演示流程,点击取消关闭厂商配置窗口。",placement:"top",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="models-tab-trigger"]',content:'厂商配置完成后,切换到"添加模型",把具体要使用的模型加入列表。',placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="add-model-button"]',content:'点击"添加模型"按钮,开始添加一个可分配给功能的模型。',placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="model-dialog"]',content:"在这里选择刚才配置好的厂商,并填写模型名称、标识符、价格和能力参数。",placement:"left",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="model-name-input"]',content:"模型名称用于在任务分配时识别这个模型。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="model-provider-select"]',content:"这里选择模型所属的厂商,系统会根据厂商配置获取或调用对应模型。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="model-identifier-input"]',content:"这里填写模型标识符。不同厂商的模型标识符格式可能不同,请参考对应厂商文档。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="model-save-button"]',content:"填写完成后点击保存,模型就会加入可用模型列表。",placement:"top",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1},{target:'[data-tour="model-cancel-button"]',content:"这次只是演示流程,点击取消关闭模型配置窗口。",placement:"top",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="tasks-tab-trigger"]',content:'最后切换到"为模型分配功能",为麦麦的各个组件选择合适的模型。',placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!0,hideFooter:!0},{target:'[data-tour="task-model-select"]',content:"在这里可以为每个组件选择一个或多个模型,选择完成后配置会自动保存。",placement:"bottom",disableBeacon:!0,disableOverlayClose:!0,hideCloseButton:!1,spotlightClicks:!1}],Ze=Object.fromEntries(De.map((a,l)=>[l,"/config/model"])),se=o.forwardRef(({className:a,...l},i)=>e.jsx(h,{ref:i,className:S("flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",a),...l}));se.displayName=h.displayName;const ae=o.forwardRef(({className:a,...l},i)=>e.jsxs("div",{className:"flex items-center border-b px-3","cmdk-input-wrapper":"",children:[e.jsx(V,{className:"mr-2 h-4 w-4 shrink-0 opacity-50"}),e.jsx(h.Input,{ref:i,className:S("flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",a),...l})]}));ae.displayName=h.Input.displayName;const te=o.forwardRef(({className:a,...l},i)=>e.jsx(h.List,{ref:i,className:S("max-h-[300px] overflow-y-auto overflow-x-hidden",a),...l}));te.displayName=h.List.displayName;const le=o.forwardRef((a,l)=>e.jsx(h.Empty,{ref:l,className:"py-6 text-center text-sm",...a}));le.displayName=h.Empty.displayName;const ie=o.forwardRef(({className:a,...l},i)=>e.jsx(h.Group,{ref:i,className:S("overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",a),...l}));ie.displayName=h.Group.displayName;const Re=o.forwardRef(({className:a,...l},i)=>e.jsx(h.Separator,{ref:i,className:S("-mx-1 h-px bg-border",a),...l}));Re.displayName=h.Separator.displayName;const ne=o.forwardRef(({className:a,...l},i)=>e.jsx(h.Item,{ref:i,className:S("relative flex cursor-pointer gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",a),...l}));ne.displayName=h.Item.displayName;function T({content:a,className:l,iconClassName:i,side:c="top",align:w="center",maxWidth:_="300px"}){return e.jsx(re,{delayDuration:200,children:e.jsxs(oe,{children:[e.jsx(ce,{asChild:!0,children:e.jsxs("button",{type:"button",className:S("inline-flex items-center justify-center rounded-full","text-muted-foreground hover:text-foreground","transition-colors cursor-help","focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",l),onClick:C=>C.preventDefault(),children:[e.jsx(ye,{className:S("h-4 w-4",i)}),e.jsx("span",{className:"sr-only",children:"帮助信息"})]})}),e.jsx(de,{side:c,align:w,className:S("max-w-[var(--max-width)] text-sm leading-relaxed","bg-background text-foreground","border-2 border-primary shadow-lg","p-4"),style:{"--max-width":_},children:a})]})})}const D=[{id:"siliconflow",name:"SiliconFlow",base_url:"https://api.siliconflow.cn/v1",client_type:"openai",display_name:"硅基流动 (SiliconFlow)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"deepseek",name:"DeepSeek",base_url:"https://api.deepseek.com",client_type:"openai",display_name:"DeepSeek",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"rinkoai",name:"RinkoAI",base_url:"https://rinkoai.com/v1",client_type:"openai",display_name:"RinkoAI",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"zhipu",name:"ZhipuAI",base_url:"https://open.bigmodel.cn/api/paas/v4",client_type:"openai",display_name:"智谱 AI (ZhipuAI / GLM)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"moonshot",name:"Moonshot",base_url:"https://api.moonshot.cn/v1",client_type:"openai",display_name:"月之暗面 (Moonshot / Kimi)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"doubao",name:"Doubao",base_url:"https://ark.cn-beijing.volces.com/api/v3",client_type:"openai",display_name:"字节豆包 (Doubao)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"alibaba",name:"Alibaba",base_url:"https://dashscope.aliyuncs.com/compatible-mode/v1",client_type:"openai",display_name:"阿里云百炼 (Alibaba Qwen)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"baichuan",name:"Baichuan",base_url:"https://api.baichuan-ai.com/v1",client_type:"openai",display_name:"百川智能 (Baichuan)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"minimax",name:"MiniMax",base_url:"https://api.minimax.chat/v1",client_type:"openai",display_name:"MiniMax (海螺 AI)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"stepfun",name:"StepFun",base_url:"https://api.stepfun.com/v1",client_type:"openai",display_name:"阶跃星辰 (StepFun)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"lingyi",name:"Lingyi",base_url:"https://api.lingyiwanwu.com/v1",client_type:"openai",display_name:"零一万物 (Lingyi / Yi)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"openai",name:"OpenAI",base_url:"https://api.openai.com/v1",client_type:"openai",display_name:"OpenAI",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"xai",name:"xAI",base_url:"https://api.x.ai/v1",client_type:"openai",display_name:"xAI (Grok)",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"anthropic",name:"Anthropic",base_url:"https://api.anthropic.com/v1",client_type:"openai",display_name:"Anthropic (Claude)"},{id:"gemini",name:"Gemini",base_url:"https://generativelanguage.googleapis.com/v1beta",client_type:"gemini",display_name:"Google Gemini",modelFetcher:{endpoint:"/models",parser:"gemini"}},{id:"cohere",name:"Cohere",base_url:"https://api.cohere.ai/v1",client_type:"openai",display_name:"Cohere"},{id:"groq",name:"Groq",base_url:"https://api.groq.com/openai/v1",client_type:"openai",display_name:"Groq",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"together",name:"Together AI",base_url:"https://api.together.xyz/v1",client_type:"openai",display_name:"Together AI",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"fireworks",name:"Fireworks",base_url:"https://api.fireworks.ai/inference/v1",client_type:"openai",display_name:"Fireworks AI",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"mistral",name:"Mistral",base_url:"https://api.mistral.ai/v1",client_type:"openai",display_name:"Mistral AI",modelFetcher:{endpoint:"/models",parser:"openai"}},{id:"perplexity",name:"Perplexity",base_url:"https://api.perplexity.ai",client_type:"openai",display_name:"Perplexity AI"},{id:"custom",name:"",base_url:"",client_type:"openai",display_name:"自定义"}];function W(a){return a?a.replace(/\/+$/,"").toLowerCase():""}function Je(a){if(!a)return null;const l=W(a);return D.find(i=>i.id!=="custom"&&W(i.base_url)===l)||null}const Ye=a=>({...a,max_retry:a.max_retry??2,timeout:a.timeout??30,retry_interval:a.retry_interval??10}),ze=(a,l=[],i=null)=>{const c={};return a?(a.name?.trim()?l.some((_,C)=>i!==null&&C===i?!1:_.name.trim().toLowerCase()===a.name.trim().toLowerCase())&&(c.name="提供商名称已存在,请使用其他名称"):c.name="请输入提供商名称",a.base_url?.trim()||(c.base_url="请输入基础 URL"),a.api_key?.trim()||(c.api_key="请输入 API Key"),{isValid:Object.keys(c).length===0,errors:c}):{isValid:!1,errors:{name:"提供商数据为空"}}};function Xe({open:a,onOpenChange:l,editingProvider:i,editingIndex:c,providers:w,onSave:_,tourState:C}){const[n,f]=o.useState({}),[g,j]=o.useState("custom"),[R,x]=o.useState(!1),[b,y]=o.useState(!1),[u,m]=o.useState(i),{toast:O}=me();o.useEffect(()=>{if(!a){m(null),f({}),y(!1),j("custom");return}if(m(i),f({}),y(!1),i){const t=D.find(s=>s.base_url===i.base_url&&s.client_type===i.client_type);j(t?.id||"custom")}else j("custom")},[a,i,c]);const d=o.useMemo(()=>g!=="custom",[g]),B=o.useCallback(t=>{j(t),x(!1);const s=D.find(r=>r.id===t);s&&s.id!=="custom"?m(r=>({...r,name:s.name,base_url:s.base_url,client_type:s.client_type})):s?.id==="custom"&&m(r=>({...r,name:"",base_url:"",client_type:"openai"}))},[]),L=o.useCallback(async()=>{if(u?.api_key)try{await navigator.clipboard.writeText(u.api_key),O({title:"复制成功",description:"API Key 已复制到剪贴板"})}catch{O({title:"复制失败",description:"无法访问剪贴板",variant:"destructive"})}},[u?.api_key,O]),z=()=>{if(!u)return;const{isValid:t,errors:s}=ze(u,w,c);if(!t){f(s);return}f({}),_(u,c)};return e.jsx(pe,{open:a,onOpenChange:l,children:e.jsxs(ue,{className:"max-w-[95vw] sm:max-w-2xl","data-tour":"provider-dialog",preventOutsideClose:C.isRunning,confirmOnEnter:!0,children:[e.jsxs(he,{children:[e.jsx(xe,{children:c!==null?"编辑提供商":"添加提供商"}),e.jsx(ge,{children:"配置 API 提供商的连接信息和参数"})]}),e.jsxs("form",{onSubmit:t=>{t.preventDefault(),z()},autoComplete:"off",className:"contents",children:[e.jsx(je,{children:e.jsxs("div",{className:"grid gap-4 py-4",children:[e.jsxs("div",{className:"grid gap-2","data-tour":"provider-template-select",children:[e.jsx(A,{htmlFor:"template",children:"提供商模板"}),e.jsxs(Be,{open:R,onOpenChange:x,children:[e.jsx(Fe,{asChild:!0,children:e.jsxs(p,{variant:"outline",role:"combobox","aria-expanded":R,className:"w-full justify-between",children:[g?D.find(t=>t.id===g)?.display_name:"选择提供商模板...",e.jsx(ve,{className:"ml-2 h-4 w-4 shrink-0 opacity-50"})]})}),e.jsx(Te,{className:"p-0",align:"start",style:{width:"var(--radix-popover-trigger-width)"},children:e.jsxs(se,{children:[e.jsx(ae,{placeholder:"搜索提供商模板..."}),e.jsx(fe,{className:"h-[300px]",children:e.jsxs(te,{className:"max-h-none overflow-visible",children:[e.jsx(le,{children:"未找到匹配的模板"}),e.jsx(ie,{children:D.map(t=>e.jsxs(ne,{value:t.display_name,onSelect:()=>B(t.id),children:[e.jsx(Ne,{className:`mr-2 h-4 w-4 ${g===t.id?"opacity-100":"opacity-0"}`}),t.display_name]},t.id))})]})})]})})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"选择预设模板可自动填充 URL 和客户端类型,支持搜索"})]}),e.jsxs("div",{className:"grid gap-2","data-tour":"provider-name-input",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"name",className:n.name?"text-destructive":"",children:"名称 *"}),e.jsx(T,{content:e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"font-medium",children:"提供商名称"}),e.jsx("p",{children:"为这个 API 提供商设置一个便于识别的名称,用于在模型配置中引用。"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[e.jsx("li",{children:"推荐使用厂商官方名称,如 DeepSeek、OpenAI"}),e.jsx("li",{children:"名称需要唯一,不能与现有提供商重复"})]})]}),side:"right",maxWidth:"350px"})]}),e.jsx(F,{id:"name",value:u?.name||"",onChange:t=>{m(s=>s?{...s,name:t.target.value}:null),n.name&&f(s=>({...s,name:void 0}))},placeholder:"例如: DeepSeek, SiliconFlow","aria-invalid":n.name?!0:void 0,"aria-describedby":n.name?"name-error":void 0,className:n.name?"border-destructive focus-visible:ring-destructive":""}),n.name&&e.jsx("p",{id:"name-error",role:"alert",className:"text-xs text-destructive",children:n.name})]}),e.jsxs("div",{className:"grid gap-2","data-tour":"provider-url-input",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"base_url",className:n.base_url?"text-destructive":"",children:"基础 URL *"}),e.jsx(T,{content:e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"font-medium",children:"API 基础地址"}),e.jsx("p",{children:"提供商的 API 端点基础 URL,通常以 /v1 结尾。"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"OpenAI 格式:"}),"https://api.openai.com/v1"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"DeepSeek:"}),"https://api.deepseek.com"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"硅基流动:"}),"https://api.siliconflow.cn/v1"]}),e.jsx("li",{children:"选择模板会自动填充正确的 URL"})]})]}),side:"right",maxWidth:"400px"})]}),e.jsx(F,{id:"base_url",value:u?.base_url||"",onChange:t=>{m(s=>s?{...s,base_url:t.target.value}:null),n.base_url&&f(s=>({...s,base_url:void 0}))},placeholder:"https://api.example.com/v1",disabled:d,"aria-invalid":n.base_url?!0:void 0,"aria-describedby":n.base_url?"base-url-error":void 0,className:`${d?"bg-muted cursor-not-allowed":""} ${n.base_url?"border-destructive focus-visible:ring-destructive":""}`}),n.base_url&&e.jsx("p",{id:"base-url-error",role:"alert",className:"text-xs text-destructive",children:n.base_url}),d&&!n.base_url&&e.jsx("p",{className:"text-xs text-muted-foreground",children:'使用模板时 URL 不可编辑,切换到"自定义"以手动配置'})]}),e.jsxs("div",{className:"grid gap-2","data-tour":"provider-apikey-input",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"api_key",className:n.api_key?"text-destructive":"",children:"API Key *"}),e.jsx(T,{content:e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"font-medium",children:"API 密钥"}),e.jsx("p",{children:"从提供商平台获取的身份验证密钥。"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[e.jsxs("li",{children:["通常以 ",e.jsx("code",{children:"sk-"})," 开头"]}),e.jsx("li",{children:"请妥善保管,不要泄露给他人"}),e.jsx("li",{children:"可以点击眼睛图标切换显示/隐藏"}),e.jsx("li",{children:"点击复制图标可快速复制密钥"})]})]}),side:"right",maxWidth:"350px"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(F,{id:"api_key",type:b?"text":"password",value:u?.api_key||"",onChange:t=>{m(s=>s?{...s,api_key:t.target.value}:null),n.api_key&&f(s=>({...s,api_key:void 0}))},placeholder:"sk-...","aria-invalid":n.api_key?!0:void 0,"aria-describedby":n.api_key?"api-key-error":void 0,className:`flex-1 ${n.api_key?"border-destructive focus-visible:ring-destructive":""}`}),e.jsx(p,{type:"button",variant:"outline",size:"icon",onClick:()=>y(!b),title:b?"隐藏密钥":"显示密钥",children:b?e.jsx(_e,{className:"h-4 w-4"}):e.jsx(Ce,{className:"h-4 w-4"})}),e.jsx(p,{type:"button",variant:"outline",size:"icon",onClick:L,title:"复制密钥",children:e.jsx(ke,{className:"h-4 w-4"})})]}),n.api_key&&e.jsx("p",{id:"api-key-error",role:"alert",className:"text-xs text-destructive",children:n.api_key})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"client_type",children:"客户端类型"}),e.jsx(T,{content:e.jsxs("div",{className:"space-y-2",children:[e.jsx("p",{className:"font-medium",children:"API 客户端类型"}),e.jsx("p",{children:"指定与提供商通信时使用的 API 协议格式。"}),e.jsxs("ul",{className:"list-disc list-inside space-y-1 text-xs",children:[e.jsxs("li",{children:[e.jsx("strong",{children:"OpenAI:"}),"兼容 OpenAI API 格式的提供商"]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Gemini:"}),"Google Gemini 专用格式"]}),e.jsx("li",{children:"大部分第三方提供商都兼容 OpenAI 格式"})]})]}),side:"right",maxWidth:"350px"})]}),e.jsxs(J,{value:u?.client_type||"openai",onValueChange:t=>m(s=>s?{...s,client_type:t}:null),disabled:d,children:[e.jsx(Y,{id:"client_type",className:d?"bg-muted cursor-not-allowed":"",children:e.jsx(X,{placeholder:"选择客户端类型"})}),e.jsxs(ee,{children:[e.jsx(P,{value:"openai",children:"OpenAI"}),e.jsx(P,{value:"gemini",children:"Gemini"})]})]}),d&&e.jsx("p",{className:"text-xs text-muted-foreground",children:'使用模板时客户端类型不可编辑,切换到"自定义"以手动配置'})]}),e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"max_retry",children:"最大重试"}),e.jsx(T,{content:"API 请求失败时的最大重试次数。设置为 0 表示不重试。默认值:2",side:"top",maxWidth:"250px"})]}),e.jsx(F,{id:"max_retry",type:"number",min:"0",value:u?.max_retry??"",onChange:t=>{const s=t.target.value===""?null:parseInt(t.target.value);m(r=>r?{...r,max_retry:s}:null)},placeholder:"默认: 2"})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"timeout",children:"超时(秒)"}),e.jsx(T,{content:"单次 API 请求的超时时间(秒)。超时后会触发重试或报错。默认值:30 秒",side:"top",maxWidth:"250px"})]}),e.jsx(F,{id:"timeout",type:"number",min:"1",value:u?.timeout??"",onChange:t=>{const s=t.target.value===""?null:parseInt(t.target.value);m(r=>r?{...r,timeout:s}:null)},placeholder:"默认: 30"})]}),e.jsxs("div",{className:"grid gap-2",children:[e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx(A,{htmlFor:"retry_interval",children:"重试间隔(秒)"}),e.jsx(T,{content:"两次重试之间的等待时间(秒)。适当的间隔可以避免触发 API 限流。默认值:10 秒",side:"top",maxWidth:"250px"})]}),e.jsx(F,{id:"retry_interval",type:"number",min:"1",value:u?.retry_interval??"",onChange:t=>{const s=t.target.value===""?null:parseInt(t.target.value);m(r=>r?{...r,retry_interval:s}:null)},placeholder:"默认: 10"})]})]})]})}),e.jsxs(be,{children:[e.jsx(p,{type:"button",variant:"outline",onClick:()=>l(!1),"data-tour":"provider-cancel-button",children:"取消"}),e.jsx(p,{type:"submit","data-dialog-action":"confirm","data-tour":"provider-save-button",children:"保存"})]})]})]})})}function Ee({provider:a,actualIndex:l,testingProviders:i,testResults:c,onEdit:w,onDelete:_,onTest:C}){const n=()=>{const f=i.has(a.name),g=c.get(a.name);return f?e.jsxs(N,{variant:"secondary",className:"gap-1",children:[e.jsx(E,{className:"h-3 w-3 animate-spin"}),"测试中"]}):g?g.network_ok?g.api_key_valid===!0?e.jsxs(N,{className:"gap-1 bg-green-600 hover:bg-green-700",children:[e.jsx(M,{className:"h-3 w-3"}),"正常"]}):g.api_key_valid===!1?e.jsxs(N,{variant:"destructive",className:"gap-1",children:[e.jsx(Q,{className:"h-3 w-3"}),"Key无效"]}):e.jsxs(N,{className:"gap-1 bg-blue-600 hover:bg-blue-700",children:[e.jsx(M,{className:"h-3 w-3"}),"可访问"]}):e.jsxs(N,{variant:"destructive",className:"gap-1",children:[e.jsx(Z,{className:"h-3 w-3"}),"离线"]}):null};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 flex-wrap",children:[e.jsx("h3",{className:"font-semibold text-base truncate",children:a.name}),n()]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1 break-all",children:a.base_url})]}),e.jsxs("div",{className:"flex gap-1 flex-shrink-0",children:[e.jsx(p,{variant:"outline",size:"sm",onClick:()=>C(a.name),disabled:i.has(a.name),title:"测试连接",children:i.has(a.name)?e.jsx(E,{className:"h-4 w-4 animate-spin"}):e.jsx(q,{className:"h-4 w-4"})}),e.jsx(p,{variant:"default",size:"sm",onClick:()=>w(a,l),children:e.jsx($,{className:"h-4 w-4",strokeWidth:2,fill:"none"})}),e.jsx(p,{size:"sm",onClick:()=>_(l),className:"bg-red-600 hover:bg-red-700 text-white",children:e.jsx(H,{className:"h-4 w-4",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:a.client_type})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"最大重试"}),e.jsx("p",{className:"font-medium",children:a.max_retry})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"超时(秒)"}),e.jsx("p",{className:"font-medium",children:a.timeout})]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground text-xs",children:"重试间隔(秒)"}),e.jsx("p",{className:"font-medium",children:a.retry_interval})]})]})]})}function es({providers:a,testingProviders:l,testResults:i,selectedProviders:c,toolbarActions:w,onEdit:_,onDelete:C,onTest:n,onToggleSelect:f,onToggleSelectAll:g}){const[j,R]=o.useState(""),[x,b]=o.useState(1),[y,u]=o.useState(20),[m,O]=o.useState(""),d=o.useMemo(()=>{if(!j)return a;const s=j.toLowerCase();return a.filter(r=>r.name.toLowerCase().includes(s)||r.base_url.toLowerCase().includes(s)||r.client_type.toLowerCase().includes(s))},[a,j]),{totalPages:B,paginatedProviders:L}=o.useMemo(()=>{const s=Math.ceil(d.length/y),r=d.slice((x-1)*y,x*y);return{totalPages:s,paginatedProviders:r}},[d,x,y]),z=o.useCallback(()=>{const s=parseInt(m);s>=1&&s<=B&&(b(s),O(""))},[m,B]),t=s=>{const r=l.has(s),v=i.get(s);return r?e.jsxs(N,{variant:"secondary",className:"gap-1",children:[e.jsx(E,{className:"h-3 w-3 animate-spin"}),"测试中"]}):v?v.network_ok?v.api_key_valid===!0?e.jsxs(N,{className:"gap-1 bg-green-600 hover:bg-green-700",children:[e.jsx(M,{className:"h-3 w-3"}),"正常"]}):v.api_key_valid===!1?e.jsxs(N,{variant:"destructive",className:"gap-1",children:[e.jsx(Q,{className:"h-3 w-3"}),"Key无效"]}):e.jsxs(N,{className:"gap-1 bg-blue-600 hover:bg-blue-700",children:[e.jsx(M,{className:"h-3 w-3"}),"可访问"]}):e.jsxs(N,{variant:"destructive",className:"gap-1",children:[e.jsx(Z,{className:"h-3 w-3"}),"离线"]}):e.jsx(N,{variant:"outline",className:"text-muted-foreground",children:"未测试"})};return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"mb-4 flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{className:"flex w-full flex-col gap-2 sm:flex-row sm:items-center",children:[e.jsxs("div",{className:"relative w-full sm:flex-1 sm:max-w-sm",children:[e.jsx(V,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(F,{placeholder:"搜索提供商名称、URL 或类型...",value:j,onChange:s=>R(s.target.value),className:"pl-9"})]}),j&&e.jsxs("p",{className:"text-sm text-muted-foreground whitespace-nowrap",children:["找到 ",d.length," 个结果"]})]}),w&&e.jsx("div",{className:"flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-center sm:justify-end",children:w})]}),e.jsx("div",{className:"md:hidden space-y-3",children:d.length===0?e.jsx("div",{className:"text-center text-muted-foreground py-8 rounded-lg border bg-card",children:j?"未找到匹配的提供商":'暂无提供商配置,点击"添加提供商"开始配置'}):L.map((s,r)=>{const v=a.findIndex(G=>G===s);return e.jsx(Ee,{provider:s,actualIndex:v,testingProviders:l,testResults:i,onEdit:_,onDelete:C,onTest:n},r)})}),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(Oe,{"aria-label":"AI 模型提供商列表",children:[e.jsx(Pe,{children:e.jsxs(U,{children:[e.jsx(I,{className:"w-12",children:e.jsx(K,{checked:c.size===d.length&&d.length>0,onCheckedChange:g})}),e.jsx(I,{children:"状态"}),e.jsx(I,{children:"名称"}),e.jsx(I,{children:"基础URL"}),e.jsx(I,{children:"客户端类型"}),e.jsx(I,{className:"text-right",children:"最大重试"}),e.jsx(I,{className:"text-right",children:"超时(秒)"}),e.jsx(I,{className:"text-right",children:"重试间隔(秒)"}),e.jsx(I,{className:"text-right",children:"操作"})]})}),e.jsx(Le,{children:L.length===0?e.jsx(U,{children:e.jsx(k,{colSpan:9,className:"text-center text-muted-foreground py-8",children:j?"未找到匹配的提供商":'暂无提供商配置,点击"添加提供商"开始配置'})}):L.map((s,r)=>{const v=a.findIndex(G=>G===s);return e.jsxs(U,{children:[e.jsx(k,{children:e.jsx(K,{checked:c.has(v),onCheckedChange:()=>f(v)})}),e.jsx(k,{children:t(s.name)}),e.jsx(k,{className:"font-medium",children:s.name}),e.jsx(k,{className:"max-w-xs truncate",title:s.base_url,children:s.base_url}),e.jsx(k,{children:s.client_type}),e.jsx(k,{className:"text-right",children:s.max_retry}),e.jsx(k,{className:"text-right",children:s.timeout}),e.jsx(k,{className:"text-right",children:s.retry_interval}),e.jsx(k,{className:"text-right",children:e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx(p,{variant:"outline",size:"sm",onClick:()=>n(s.name),disabled:l.has(s.name),title:"测试连接",children:l.has(s.name)?e.jsx(E,{className:"h-4 w-4 animate-spin"}):e.jsx(q,{className:"h-4 w-4"})}),e.jsxs(p,{variant:"default",size:"sm",onClick:()=>_(s,v),children:[e.jsx($,{className:"h-4 w-4 mr-1",strokeWidth:2,fill:"none"}),"编辑"]}),e.jsxs(p,{size:"sm",onClick:()=>C(v),className:"bg-red-600 hover:bg-red-700 text-white",children:[e.jsx(H,{className:"h-4 w-4 mr-1",strokeWidth:2,fill:"none"}),"删除"]})]})})]},r)})})]})})}),d.length>0&&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(A,{htmlFor:"page-size-provider",className:"text-sm whitespace-nowrap",children:"每页显示"}),e.jsxs(J,{value:y.toString(),onValueChange:s=>{u(parseInt(s)),b(1)},children:[e.jsx(Y,{id:"page-size-provider",className:"w-20",children:e.jsx(X,{})}),e.jsxs(ee,{children:[e.jsx(P,{value:"10",children:"10"}),e.jsx(P,{value:"20",children:"20"}),e.jsx(P,{value:"50",children:"50"}),e.jsx(P,{value:"100",children:"100"})]})]}),e.jsxs("span",{className:"text-sm text-muted-foreground",children:["显示 ",(x-1)*y+1," 到"," ",Math.min(x*y,d.length)," 条,共 ",d.length," 条"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(p,{variant:"outline",size:"sm",onClick:()=>b(1),disabled:x===1,className:"hidden sm:flex",children:e.jsx(we,{className:"h-4 w-4"})}),e.jsxs(p,{variant:"outline",size:"sm",onClick:()=>b(s=>Math.max(1,s-1)),disabled:x===1,children:[e.jsx(Ie,{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(F,{type:"number",value:m,onChange:s=>O(s.target.value),onKeyDown:s=>s.key==="Enter"&&z(),placeholder:x.toString(),className:"w-16 h-8 text-center",min:1,max:B}),e.jsx(p,{variant:"outline",size:"sm",onClick:z,disabled:!m,className:"h-8",children:"跳转"})]}),e.jsxs(p,{variant:"outline",size:"sm",onClick:()=>b(s=>s+1),disabled:x>=B,children:[e.jsx("span",{className:"hidden sm:inline",children:"下一页"}),e.jsx(Ae,{className:"h-4 w-4 sm:ml-1"})]}),e.jsx(p,{variant:"outline",size:"sm",onClick:()=>b(B),disabled:x>=B,className:"hidden sm:flex",children:e.jsx(Se,{className:"h-4 w-4"})})]})]})]})}export{se as C,T as H,Qe as M,es as P,Ze as S,Xe as a,ae as b,Ye as c,te as d,le as e,ie as f,ne as g,Je as h,De as m};
|