Files
mai-bot/dashboard/dist/assets/ProviderList-4mOft0xL.js

2 lines
31 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{r as 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};