aicodeswitch 2.1.4 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -84,7 +84,7 @@ Error generating stack: `+a.message+`
|
|
|
84
84
|
`),(v=t.onStdout)==null||v.call(t,`子进程已创建 (PID: ${S.data.pid})
|
|
85
85
|
`),(y=t.onStdout)==null||y.call(t,`等待 npm 输出...
|
|
86
86
|
|
|
87
|
-
`);break;case"stdout":(x=t.onStdout)==null||x.call(t,S.data);break;case"stderr":(g=t.onStderr)==null||g.call(t,S.data);break;case"close":console.log("[API Client] 安装完成:",S.data),(b=t.onClose)==null||b.call(t,S.data.code,S.data.success),setTimeout(()=>{a==null||a.close()},1e3);break;case"error":console.error("[API Client] 安装错误:",S.data),(w=t.onError)==null||w.call(t,S.data);break}}catch(S){console.error("[API Client] 解析消息失败:",S,d.data)}},a.onclose=d=>{var f;console.log("[API Client] WebSocket 连接关闭:",d.code,d.reason),d.wasClean||(f=t.onError)==null||f.call(t,"连接意外关闭")},a.onerror=d=>{var f;console.error("[API Client] WebSocket 错误:",d),(f=t.onError)==null||f.call(t,"WebSocket 连接错误")};const o=()=>{console.log("[API Client] 清理 WebSocket 连接"),a&&(a.close(),a=null)},l=d=>{a&&a.readyState===WebSocket.OPEN?(a.send(JSON.stringify({type:"input",data:d})),console.log("[API Client] 发送输入:",d.slice(0,10))):console.warn("[API Client] WebSocket 未连接,无法发送输入")},s=o;return s.sendInput=l,s}};var Jn=(e=>(e.AUTH_TOKEN="authorization",e.API_KEY="x-api-key",e.AUTO="auto",e))(Jn||{});const In={
|
|
87
|
+
`);break;case"stdout":(x=t.onStdout)==null||x.call(t,S.data);break;case"stderr":(g=t.onStderr)==null||g.call(t,S.data);break;case"close":console.log("[API Client] 安装完成:",S.data),(b=t.onClose)==null||b.call(t,S.data.code,S.data.success),setTimeout(()=>{a==null||a.close()},1e3);break;case"error":console.error("[API Client] 安装错误:",S.data),(w=t.onError)==null||w.call(t,S.data);break}}catch(S){console.error("[API Client] 解析消息失败:",S,d.data)}},a.onclose=d=>{var f;console.log("[API Client] WebSocket 连接关闭:",d.code,d.reason),d.wasClean||(f=t.onError)==null||f.call(t,"连接意外关闭")},a.onerror=d=>{var f;console.error("[API Client] WebSocket 错误:",d),(f=t.onError)==null||f.call(t,"WebSocket 连接错误")};const o=()=>{console.log("[API Client] 清理 WebSocket 连接"),a&&(a.close(),a=null)},l=d=>{a&&a.readyState===WebSocket.OPEN?(a.send(JSON.stringify({type:"input",data:d})),console.log("[API Client] 发送输入:",d.slice(0,10))):console.warn("[API Client] WebSocket 未连接,无法发送输入")},s=o;return s.sendInput=l,s}};var Jn=(e=>(e.AUTH_TOKEN="authorization",e.API_KEY="x-api-key",e.AUTO="auto",e))(Jn||{});const In={minimax:{name:"Minimax",description:"国内优秀的大模型 https://platform.minimaxi.com/subscribe/coding-plan?code=G6xKj7L4YN&source=link",services:[{name:"Coding Plan Claude Code",sourceType:"claude-code",apiUrl:"https://api.minimaxi.com/anthropic",models:"MiniMax-M2.1"},{name:"Coding Plan Codex",sourceType:"openai-chat",apiUrl:"https://api.minimaxi.com/v1",models:"codex-MiniMax-M2.1"}]},glm:{name:"GLM",description:"国内优秀的大模型 https://www.bigmodel.cn/glm-coding?ic=5AH7ATEZSC",services:[{name:"Coding Plan Claude Code",sourceType:"claude-code",apiUrl:"https://open.bigmodel.cn/api/anthropic",models:"glm-4.7, glm-4.5-air",modelLimits:{"glm-4.7":131072,"glm-4.5-air":98304}}]},kimi:{name:"Kimi",description:"国内优秀大模型 https://www.kimi.ai/",services:[{name:"Coding Plan Claude Code",sourceType:"claude-code",apiUrl:"https://api.kimi.com/coding"}]},doubao:{name:"火山方舟(豆包)",description:"字节旗下大模型平台。Coding Plan一次性支持GLM、Kimi-K2、Deepseek多个国产模型 https://volcengine.com/L/RcHlm6yxj0w/ 邀请码:Y58X463P",services:[{name:"Coding Plan Claude Code",sourceType:"claude-code",apiUrl:"https://ark.cn-beijing.volces.com/api/coding",models:"ark-code-latest"},{name:"Coding Plan Codex",sourceType:"openai-responses",apiUrl:"https://ark.cn-beijing.volces.com/api/coding/v3",models:"ark-code-latest"},{name:"付费API兼容Claude Code",sourceType:"claude-code",apiUrl:"https://ark.cn-beijing.volces.com/api/compatible",models:"doubao-seed-code-preview-251028"},{name:"付费API兼容Codex",sourceType:"openai-responses",apiUrl:"https://ark.cn-beijing.volces.com/api/v3",models:"doubao-seed-code-preview-251028"}]},aicodewith:{name:"AICodeWith",description:"稳定的第三方中转 https://aicodewith.com/login?tab=register&invitation=QCA74W",services:[{name:"claudecode",sourceType:"claude-code",apiUrl:"https://api.aicodewith.com"},{name:"codex",sourceType:"openai-responses",apiUrl:"https://api.aicodewith.com/chatgpt"}]},openai:{name:"OpenAI",description:"OpenAI 官方 API https://platform.openai.com",services:[{name:"GPT",sourceType:"openai-responses",apiUrl:"https://api.openai.com"}],is_oversea:!0},anthropic:{name:"Anthropic",description:"Anthropic 官方 API https://www.anthropic.com",services:[{name:"Claude",sourceType:"claude-code",apiUrl:"https://api.anthropic.com"}],is_oversea:!0},openrouter:{name:"OpenRouter",description:"一站式 AI 模型路由平台 https://openrouter.ai",services:[{name:"Claude Code专属接口",sourceType:"claude-code",apiUrl:"https://openrouter.ai/api",models:"anthropic/claude-opus-4.6, anthropic/claude-opus-4.5, anthropic/claude-sonnet-4.5, anthropic/claude-haiku-4.5",authType:Jn.AUTH_TOKEN},{name:"通用接口",sourceType:"openai-chat",apiUrl:"https://openrouter.ai/api/v1/chat/completions",models:"anthropic/claude-opus-4.5, anthropic/claude-sonnet-4.5, anthropic/claude-haiku-4.5, openai/gpt-5.2-codex, openai/gpt-5.2-chat, openai/gpt-5.2-pro, openai/gpt-5.2, openai/gpt-5.1-codex-max"}],is_oversea:!0}},Wu={"claude-code":"Claude Code",codex:"Codex"},Hu={"claude-code":"Claude Code","claude-chat":"Claude Chat","openai-responses":"OpenAI Responses","openai-chat":"OpenAI Chat","deepseek-reasoning-chat":"DeepSeek Reasoning Chat"},m3={"openai-chat":"填写完整的接口地址,如:https://api.openai.com/v1/chat/completions","openai-responses":"只填写 base 地址(含/v1),如:https://api.openai.com/v1","claude-chat":"填写完整的接口地址,如:https://api.anthropic.com/v1/messages","claude-code":"只填写 base 地址,如:https://api.anthropic.com","deepseek-reasoning-chat":"推理类模型,填写完整的接口地址,如:https://api.deepseek.com/v1/chat/completions"},G1={[Jn.AUTO]:"自动",[Jn.AUTH_TOKEN]:"AUTH_TOKEN",[Jn.API_KEY]:"API_KEY"},v3={[Jn.AUTO]:"根据数据源类型自动判断:Claude 相关类型使用 x-api-key header,OpenAI 相关类型使用 Authorization: Bearer header",[Jn.AUTH_TOKEN]:"使用 Authorization: Bearer <token> 进行认证(对应 Claude Code 的 ANTHROPIC_AUTH_TOKEN,以及OpenAI的所有请求)",[Jn.API_KEY]:"使用 x-api-key: <token> 进行认证(对应 Claude Code 的 ANTHROPIC_API_KEY)"},g3=`#### 🚀 智谱 GLM Coding Plan
|
|
88
88
|
|
|
89
89
|
> 价格便宜,国内速度快,支持多工具(Claude Code等 20+ 大编程工具),而且其中的GLM-4.7是目前国内最强编程模型。适合对模型有一定要求,同时又无法获取国外模型的朋友入手。
|
|
90
90
|
>
|
|
@@ -348,13 +348,13 @@ PORT=4567
|
|
|
348
348
|
opacity: 1;
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
|
-
`}),c.jsx("div",{style:{position:"fixed",top:"20px",right:"20px",zIndex:9999},children:e.map(i=>c.jsxs("div",{style:n(i.type),children:[c.jsx("span",{style:{fontSize:"18px",fontWeight:"bold"},children:r(i.type)}),c.jsx("span",{style:{flex:1},children:i.message}),c.jsx("button",{onClick:()=>aE(i.id),style:{background:"none",border:"none",color:"inherit",cursor:"pointer",fontSize:"18px",padding:"0",marginLeft:"10px",opacity:.6},onMouseEnter:a=>a.currentTarget.style.opacity="1",onMouseLeave:a=>a.currentTarget.style.opacity="0.6",children:"×"})]},i.id))})]})}function X1(e){const t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0");return`${t}-${n}-${r}T${i}:${a}`}function j3({value:e=[],onChange:t,placeholder:n,inputValue:r,onInputChange:i}){const a=l=>{if(l.key==="Enter"||l.key===","){l.preventDefault();const s=r.trim();s&&!e.includes(s)&&(t([...e,s]),i(""))}else l.key==="Backspace"&&!r&&e.length>0&&t(e.slice(0,-1))},o=l=>{t(e.filter((s,u)=>u!==l))};return c.jsx("div",{style:{border:"1px solid var(--border-primary)",borderRadius:"4px",padding:"8px",minHeight:"40px",background:"var(--bg-secondary)"},children:c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"4px",alignItems:"center"},children:[e.map((l,s)=>c.jsxs("span",{style:{backgroundColor:"var(--accent-light)",color:"var(--text-primary)",padding:"4px 8px",borderRadius:"4px",fontSize:"12px",display:"flex",alignItems:"center",gap:"4px"},children:[l,c.jsx("button",{type:"button",onClick:()=>o(s),style:{background:"none",border:"none",color:"var(--text-primary)",cursor:"pointer",fontSize:"16px",lineHeight:"1",padding:"0",marginLeft:"4px"},onMouseOver:u=>u.currentTarget.style.color="var(--accent-danger)",onMouseOut:u=>u.currentTarget.style.color="var(--text-primary)",children:"×"})]},s)),c.jsx("input",{type:"text",value:r,onChange:l=>i(l.target.value),onKeyDown:a,placeholder:n,style:{border:"none",outline:"none",flex:"1",minWidth:"120px",fontSize:"14px"}})]})})}function P3(){var Pe,St;const{confirm:e}=Cy(),[t,n]=m.useState([]),[r,i]=m.useState([]),[a,o]=m.useState(null),[l,s]=m.useState(!1),[u,d]=m.useState(!1),[f,p]=m.useState(!1),[h,v]=m.useState(!1),[y,x]=m.useState(null),[g,b]=m.useState(null),[w,S]=m.useState([]),[j,k]=m.useState(""),[C,O]=m.useState({}),[N,A]=m.useState(!1),[T,I]=m.useState(void 0),[q,z]=m.useState(void 0),[D,$]=m.useState(void 0),[K,M]=m.useState(!1),[R,P]=m.useState(void 0),[G,ee]=m.useState(void 0),[E,ae]=m.useState(void 0),[xe,H]=m.useState("openai-chat"),[Y,ue]=m.useState(Jn.AUTO),[F,J]=m.useState(""),[re,B]=m.useState([]),[ve,de]=m.useState(""),_e=x3(),Ne=m.useMemo(()=>{const W=Object.keys(In).filter(fe=>In[fe].is_oversea).map(fe=>({...In[fe],key:fe}));return[...Object.keys(In).filter(fe=>!In[fe].is_oversea).map(fe=>({...In[fe],key:fe})),null,...W]},[]);m.useEffect(()=>{Ae()},[]),m.useEffect(()=>{a&&tt(a.id)},[a]),m.useEffect(()=>{const W=new Set(w),oe={};Object.entries(C).forEach(([je,Oe])=>{W.has(je)&&(oe[je]=Oe)}),Object.keys(oe).length!==Object.keys(C).length&&O(oe)},[w]);const Ae=async()=>{const W=await te.getVendors();n(W),W.length>0&&!a&&o(W[0])},tt=async W=>{const oe=await te.getAPIServices(W);i(oe)},bt=()=>{x(null),s(!0)},wt=()=>{p(!0)},yn=W=>{x(W),s(!0)},sr=async W=>{await e({message:"确定要删除此供应商吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteVendor(W),Ae(),a&&a.id===W&&(o(null),i([])),me.success("供应商已删除"))},Yr=async W=>{W.preventDefault();const oe=new FormData(W.currentTarget),fe={name:oe.get("name"),description:oe.get("description"),sortOrder:parseInt(oe.get("sortOrder"))||0};y?await te.updateVendor(y.id,fe):await te.createVendor(fe),s(!1),Ae()},Pi=()=>{b(null),S([]),k(""),O({}),A(!1),I(void 0),z(void 0),$(void 0),M(!1),P(void 0),ee(void 0),ae(void 0),H("openai-chat"),d(!0)},Tn=W=>{b(W),S(W.supportedModels||[]),k(""),O(W.modelLimits||{}),A(W.enableTokenLimit||!1),I(W.tokenLimit),z(W.tokenResetInterval),$(W.tokenResetBaseTime?new Date(W.tokenResetBaseTime):void 0),M(W.enableRequestLimit||!1),P(W.requestCountLimit),ee(W.requestResetInterval),ae(W.requestResetBaseTime?new Date(W.requestResetBaseTime):void 0),H(W.sourceType||"openai-chat"),ue(W.authType||Jn.AUTO),d(!0)},V=async W=>{await e({message:"确定要删除此API服务吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteAPIService(W),a&&tt(a.id),me.success("API服务已删除"))},Z=async W=>{W.preventDefault();let oe=[...w];if(j.trim()){const ot=j.split(",").map(lt=>lt.trim()).filter(lt=>lt&&!oe.includes(lt));oe=[...oe,...ot]}const fe=new FormData(W.currentTarget),je={};Object.entries(C).forEach(([ot,lt])=>{ot&<&<>0&&(je[ot]=lt)});const Oe={vendorId:a.id,name:fe.get("name"),apiUrl:fe.get("apiUrl"),apiKey:fe.get("apiKey"),sourceType:fe.get("sourceType"),authType:fe.get("authType")||void 0,supportedModels:oe.length>0?oe:void 0,modelLimits:Object.keys(je).length>0?je:void 0,enableProxy:fe.get("enableProxy")==="on",enableTokenLimit:N,tokenLimit:T,tokenResetInterval:q,tokenResetBaseTime:D?D.getTime():void 0,enableRequestLimit:K,requestCountLimit:R,requestResetInterval:G,requestResetBaseTime:E?E.getTime():void 0};g?await te.updateAPIService(g.id,Oe):await te.createAPIService(Oe),d(!1),S([]),k(""),O({}),A(!1),I(void 0),z(void 0),$(void 0),M(!1),P(void 0),ee(void 0),ae(void 0),a&&tt(a.id)},ye=W=>{if(W){J(W);const oe=In[W];oe&&oe.services.length>0&&B(oe.services.map((fe,je)=>je))}else J(""),B([]);de(""),v(!0)},Se=async W=>{W.preventDefault();const oe=new FormData(W.currentTarget),fe=oe.get("vendorKey"),je=oe.get("apiKey");if(!fe||!je){me.warning("请填写完整信息");return}if(re.length===0){me.warning("请至少选择一个源类型");return}const Oe=In[fe];if(!Oe){me.error("未找到对应的供应商配置");return}try{const ot=await te.createVendor({name:Oe.name,description:Oe.description}),vl=Oe.services.filter((Xt,Ci)=>re.includes(Ci)).map(async Xt=>te.createAPIService({vendorId:ot.id,name:Xt.name,apiUrl:Xt.apiUrl,apiKey:je,sourceType:Xt.sourceType,authType:Xt.authType,supportedModels:Xt.models?Xt.models.split(",").map(Ci=>Ci.trim()):void 0,modelLimits:Xt.modelLimits||{}}));await Promise.all(vl),await Ae(),v(!1),me.success(`配置成功! 已创建 ${re.length} 个API服务`)}catch(ot){console.error("一键配置失败:",ot),me.error("配置失败,请检查输入信息")}};return c.jsxs("div",{className:"vendors-page",children:[c.jsxs("div",{className:"page-header",children:[c.jsx("h1",{children:"供应商管理"}),c.jsx("p",{children:"管理API供应商和服务配置"})]}),c.jsxs("div",{style:{display:"flex",gap:"20px"},children:[c.jsxs("div",{className:"card",style:{flex:"0 0 25%",minWidth:400},children:[c.jsxs("div",{className:"toolbar",children:[c.jsx("h3",{children:"供应商列表"}),c.jsxs("div",{style:{display:"flex",gap:"10px"},children:[c.jsx("button",{className:"btn btn-secondary",style:{background:"#2563EB",color:"#FFFFFF",border:"none",cursor:"pointer"},onClick:wt,children:"推荐"}),c.jsx("button",{className:"btn btn-primary",onClick:()=>ye(),children:"一键配置"}),c.jsx("button",{className:"btn btn-primary",onClick:bt,children:"新增"})]})]}),t.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无供应商"})}):c.jsx("div",{style:{marginTop:"10px"},children:t.map(W=>c.jsx("div",{onClick:()=>o(W),style:{padding:"12px",marginBottom:"8px",backgroundColor:a&&a.id===W.id?"var(--accent-light)":"var(--bg-secondary)",borderRadius:"4px",cursor:"pointer",border:"1px solid var(--border-secondary)",color:"var(--text-primary)"},children:c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"8px"},children:[c.jsxs("div",{style:{flex:1,minWidth:0,overflow:"hidden"},children:[c.jsx("div",{style:{fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:W.name}),W.description&&c.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"4px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:W.description})]}),c.jsxs("div",{className:"action-buttons",style:{flexShrink:0},children:[c.jsx("button",{className:"btn btn-secondary",style:{padding:"4px 8px",fontSize:"12px"},onClick:oe=>{oe.stopPropagation(),yn(W)},children:"编辑"}),c.jsx("button",{className:"btn btn-danger",style:{padding:"4px 8px",fontSize:"12px"},onClick:oe=>{oe.stopPropagation(),sr(W.id)},children:"删除"})]})]})},W.id))})]}),c.jsxs("div",{className:"card",style:{flex:1},children:[c.jsxs("div",{className:"toolbar",children:[c.jsxs("h3",{children:["供应商API服务",a&&` - ${a.name}`]}),a&&c.jsx("button",{className:"btn btn-primary",onClick:Pi,children:"新增服务"})]}),a?r.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无API服务"})}):c.jsxs("table",{style:{fontSize:"smaller"},children:[c.jsx("thead",{children:c.jsxs("tr",{children:[c.jsx("th",{style:{whiteSpace:"nowrap"},children:"服务名称"}),c.jsx("th",{children:"源类型"}),c.jsx("th",{children:"API地址"}),c.jsx("th",{children:"模型列表"}),c.jsx("th",{children:"操作"})]})}),c.jsx("tbody",{children:r.map(W=>{var oe;return c.jsxs("tr",{children:[c.jsx("td",{children:W.name}),c.jsx("td",{children:W.sourceType?Hu[W.sourceType]:"-"}),c.jsx("td",{style:{maxWidth:"200px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:W.apiUrl,children:W.apiUrl}),c.jsx("td",{children:((oe=W.supportedModels)==null?void 0:oe.join(", "))||"*"}),c.jsx("td",{children:c.jsxs("div",{className:"action-buttons",children:[c.jsx("button",{className:"btn btn-sm btn-secondary",onClick:()=>Tn(W),children:"编辑"}),c.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>V(W.id),children:"删除"})]})})]},W.id)})})]}):c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"请先选择一个供应商"})})]})]}),l&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>s(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:y?"编辑供应商":"新增供应商"})}),c.jsxs("form",{onSubmit:Yr,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商名称"}),c.jsx("input",{type:"text",name:"name",defaultValue:y?y.name:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"描述"}),c.jsx("textarea",{name:"description",rows:3,defaultValue:y?y.description:""})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["排序 ",c.jsx("small",{children:"数值越大越靠前"})]}),c.jsx("input",{type:"number",name:"sortOrder",defaultValue:y&&y.sortOrder||0,min:"0"})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>s(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),u&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>d(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",style:{width:800},children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:g?"编辑供应商API服务":"新增供应商API服务"})}),c.jsxs("form",{onSubmit:Z,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"服务名称"}),c.jsx("input",{type:"text",name:"name",defaultValue:g?g.name:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["数据源类型 ",c.jsx("small",{children:"供应商接口返回的数据格式标准类型"})]}),c.jsxs("select",{name:"sourceType",defaultValue:g&&g.sourceType||"",onChange:W=>H(W.target.value),required:!0,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择源类型"}),Object.keys(Hu).map(W=>c.jsx("option",{value:W,children:Hu[W]},W))]}),c.jsx("small",{style:{display:"block",marginTop:"4px",color:"var(--text-muted)"},children:m3[xe]||""})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商API地址"}),c.jsx("input",{type:"url",name:"apiUrl",defaultValue:g?g.apiUrl:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商API密钥"}),c.jsx("input",{type:"password",name:"apiKey",defaultValue:g?g.apiKey:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["API认证方式 ",c.jsx("small",{children:"API 请求使用的认证方式"})]}),c.jsx("select",{name:"authType",defaultValue:g&&g.authType||Jn.AUTO,onChange:W=>ue(W.target.value),children:Object.keys(G1).map(W=>c.jsx("option",{value:W,children:G1[W]},W))}),c.jsx("small",{style:{display:"block",marginTop:"4px",color:"var(--text-muted)"},children:v3[Y]||""})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"支持的模型列表"}),c.jsx(j3,{value:w,onChange:S,inputValue:j,onInputChange:k,placeholder:"输入模型名,按Enter或逗号添加"},(g==null?void 0:g.id)||"new"),c.jsx("div",{style:{display:"block",width:"100%"},children:c.jsx("small",{style:{fontSize:"10px"},children:"留空表示支持所有模型,路由配置中,可直接将模型透传给该供应商服务接口。"})})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["模型输出限制 ",c.jsx("small",{children:"为支持的模型配置最大输出tokens"})]}),c.jsxs("div",{style:{border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"16px",background:"var(--bg-secondary)",maxHeight:"300px",overflowY:"auto"},children:[Object.keys(C).length===0&&w.length===0?c.jsx("div",{style:{color:"var(--text-muted)",textAlign:"center",padding:"20px",fontSize:"14px"},children:"暂无模型限制配置,可点击下方按钮添加"}):c.jsxs("div",{children:[w.length>0&&c.jsxs("div",{style:{marginBottom:"12px"},children:[c.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px",fontWeight:500},children:'来自"支持的模型列表"(自动同步)'}),w.map(W=>c.jsxs("div",{style:{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center",padding:"8px",background:"var(--bg-primary)",borderRadius:"4px",border:"1px solid var(--accent-light)"},children:[c.jsxs("div",{style:{flex:2,fontSize:"14px",color:"var(--text-primary)",fontWeight:500,display:"flex",alignItems:"center",gap:"6px"},children:[W,c.jsx("span",{style:{fontSize:"10px",padding:"2px 6px",borderRadius:"3px",background:"var(--accent-light)",color:"var(--accent-primary)"},children:"已同步"})]}),c.jsxs("div",{style:{flex:1,display:"flex",alignItems:"center",gap:"8px"},children:[c.jsx("input",{type:"number",value:C[W]||"",onChange:oe=>{const fe=oe.target.value;if(fe===""){const je={...C};delete je[W],O(je)}else O({...C,[W]:parseInt(fe)||0})},placeholder:"留空不限",min:"1",style:{width:"100%",padding:"6px 8px",border:"1px solid var(--border-primary)",borderRadius:"4px",fontSize:"14px"}}),c.jsx("span",{style:{fontSize:"12px",color:"var(--text-muted)",whiteSpace:"nowrap"},children:"tokens"})]}),c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>{const oe={...C};delete oe[W],O(oe)},style:{padding:"4px 8px",fontSize:"12px"},title:"移除此限制(模型仍在支持列表中)",children:"移除限制"})]},`sync-${W}`))]}),Object.keys(C).length>0&&c.jsx("div",{children:Object.entries(C).filter(([W])=>!w.includes(W)).map(([W,oe])=>c.jsxs("div",{style:{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center",padding:"8px",background:"var(--bg-primary)",borderRadius:"4px",border:"1px solid var(--border-secondary)"},children:[c.jsx("input",{type:"text",value:W,onChange:fe=>{const je={...C},Oe=fe.target.value;delete je[W],je[Oe]=oe,O(je)},placeholder:"模型名 (如: gpt-4)",style:{flex:2,padding:"6px 8px",border:"1px solid var(--border-primary)",borderRadius:"4px",fontSize:"14px"}}),c.jsx("input",{type:"number",value:oe,onChange:fe=>{O({...C,[W]:parseInt(fe.target.value)||0})},placeholder:"最大tokens",min:"1",style:{flex:1,padding:"6px 8px",border:"1px solid var(--border-primary)",borderRadius:"4px",fontSize:"14px"}}),c.jsx("button",{type:"button",className:"btn btn-sm btn-danger",onClick:()=>{const fe={...C};delete fe[W],O(fe)},style:{padding:"4px 8px",fontSize:"12px"},children:"删除"})]},`custom-${W}`))})]}),c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>{const W=`model-${Date.now()}`;O({...C,[W]:4096})},style:{marginTop:"8px",width:"100%"},children:"+ 添加模型限制"})]}),c.jsx("div",{style:{display:"block",width:"100%",marginTop:"8px"},children:c.jsxs("small",{style:{fontSize:"10px"},children:[c.jsx("strong",{children:"自动同步:"}),"上方添加的模型会自动在此创建限制配置(默认4096),删除模型会同步移除限制。",c.jsx("strong",{children:"手动添加:"}),"可点击下方按钮为特定模型(如 gpt-4)或前缀(如 gpt-4-*)添加限制。 留空则透传前端工具发送的值。支持精确匹配和前缀匹配。 对于o1等新模型,将自动映射到max_completion_tokens字段。"]})})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[c.jsx("input",{type:"checkbox",name:"enableProxy",defaultChecked:(g==null?void 0:g.enableProxy)||!1,style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用代理"})]}),c.jsx("small",{style:{display:"block",marginTop:"6px",color:"#666",fontSize:"12px",marginLeft:"24px"},children:'勾选后,此 API 服务的请求将通过设置的代理转发。请在"设置"页面配置代理。'})]}),c.jsx("div",{className:"form-group",children:c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[c.jsx("input",{type:"checkbox",checked:N,onChange:W=>A(W.target.checked),style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用Token超量限制"})]})}),N&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Token超量值(单位:k)"}),c.jsx("input",{type:"number",value:T||"",onChange:W=>I(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:1000表示1000k tokens"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:q||"",onChange:W=>z(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:720表示30天,168表示7天"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:D?X1(D):"",onChange:W=>{W.target.value?$(new Date(W.target.value)):$(void 0)},className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置下一次重置的精确时间点"})]})]}),c.jsx("div",{className:"form-group",children:c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[c.jsx("input",{type:"checkbox",checked:K,onChange:W=>M(W.target.checked),style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用请求次数超量限制"})]})}),K&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"请求次数超量值"}),c.jsx("input",{type:"number",value:R||"",onChange:W=>P(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:100"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:G||"",onChange:W=>ee(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:720表示30天,168表示7天"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:E?X1(E):"",onChange:W=>{W.target.value?ae(new Date(W.target.value)):ae(void 0)},className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置下一次重置的精确时间点"})]})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>d(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),f&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>p(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",style:{maxWidth:"800px"},children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:"供应商推荐"})}),c.jsx("div",{className:"modal-body",children:c.jsx("div",{className:"markdown-content",children:c.jsx(Py,{components:{a:({href:W,children:oe,title:fe})=>fe&&In[fe]?c.jsx("a",{href:"#",style:{color:"#2563EB",borderBottom:"solid 1px #2563EB",cursor:"pointer"},onClick:je=>{je.preventDefault(),p(!1),ye(fe)},children:oe}):c.jsx("a",{href:W,style:{color:"#2563EB",borderBottom:"solid 1px #2563EB"},target:"_blank",rel:"noopener noreferrer",children:oe})},children:_e})})}),c.jsx("div",{className:"modal-footer",children:c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>p(!1),children:"关闭"})})]})})]}),h&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>v(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:"一键配置供应商"})}),c.jsxs("form",{onSubmit:Se,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商"}),c.jsxs("select",{name:"vendorKey",value:F,onChange:W=>{const oe=W.target.value;if(J(oe),oe){const fe=In[oe];fe&&fe.services.length>0&&B(fe.services.map((je,Oe)=>Oe))}else B([])},required:!0,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择供应商"}),Ne.map(W=>W?c.jsx("option",{value:W.key,children:W.name},W.key):c.jsx("option",{value:"",disabled:!0,children:"--"}))]})]}),(Pe=In[F])!=null&&Pe.description?c.jsx("div",{style:{fontSize:".8em",marginBottom:16,marginTop:-16},children:In[F].description}):null,c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["源类型 ",c.jsx("small",{style:{color:"var(--text-muted)",fontWeight:"normal"},children:"可选择多个"})]}),c.jsx("div",{style:{border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"16px",background:"var(--bg-secondary)",minHeight:"100px",display:"flex",flexDirection:"column",gap:"8px"},children:F?(St=In[F])==null?void 0:St.services.map((W,oe)=>{const fe=re.includes(oe);return c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer",padding:"10px 14px",borderRadius:"6px",background:fe?"var(--accent-light)":"transparent",border:`2px solid ${fe?"var(--accent-primary)":"transparent"}`,transition:"all 0.2s ease",position:"relative",overflow:"hidden"},onMouseEnter:je=>{fe||(je.currentTarget.style.background="var(--bg-hover)",je.currentTarget.style.borderColor="var(--border-secondary)")},onMouseLeave:je=>{fe||(je.currentTarget.style.background="transparent",je.currentTarget.style.borderColor="transparent")},children:[c.jsx("input",{type:"checkbox",checked:fe,onChange:je=>{je.target.checked?B([...re,oe]):B(re.filter(Oe=>Oe!==oe))},style:{width:"18px",height:"18px",marginRight:"12px",cursor:"pointer",accentColor:"var(--accent-primary)"}}),c.jsxs("span",{style:{fontSize:"14px",fontWeight:fe?"600":"400",color:fe?"var(--accent-primary)":"var(--text-primary)",transition:"all 0.2s ease"},children:[W.name," - ",Hu[W.sourceType]]}),fe&&c.jsx("span",{style:{marginLeft:"auto",fontSize:"16px",color:"var(--accent-primary)"},children:"✓"})]},oe)}):c.jsx("div",{style:{color:"var(--text-muted)",textAlign:"center",padding:"30px 20px",fontSize:"14px"},children:"请先选择供应商"})})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"API Key"}),c.jsx("input",{type:"password",name:"apiKey",value:ve,onChange:W=>de(W.target.value),placeholder:"请输入API密钥",required:!0})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>v(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"确认配置"})]})]})]})})]})]})}function C3(){const e=m.useRef(new Map),t=m.useRef(!1),n=m.useCallback((a,o)=>{var u;const l=o.getBoundingClientRect(),s=(u=o.parentElement)==null?void 0:u.getBoundingClientRect();s&&e.current.set(a,{top:l.top-s.top,left:l.left-s.left,height:l.height,width:l.width})},[]),r=m.useCallback((a,o,l=250)=>{var v;if(t.current)return;const s=e.current.get(a);if(!s)return;const u=o.getBoundingClientRect(),d=(v=o.parentElement)==null?void 0:v.getBoundingClientRect();if(!d)return;const f={top:u.top-d.top,left:u.left-d.left,height:u.height,width:u.width},p=s.top-f.top,h=s.left-f.left;if(Math.abs(p)<1&&Math.abs(h)<1){e.current.delete(a);return}o.style.transform=`translate(${h}px, ${p}px)`,o.style.transition="none",o.style.willChange="transform",t.current=!0,requestAnimationFrame(()=>{o.style.transition=`transform ${l}ms cubic-bezier(0.4, 0, 0.2, 1)`,o.style.transform="",setTimeout(()=>{e.current.delete(a),t.current=!1,o.style.willChange=""},l)})},[]),i=m.useCallback(()=>{e.current.clear()},[]);return{recordPositions:n,applyAnimation:r,clearPositions:i}}function O3(){const[e,t]=m.useState("disconnected"),[n,r]=m.useState({}),i=m.useRef(null),a=m.useRef(null),o=m.useRef(null),l=()=>{var y;if(((y=i.current)==null?void 0:y.readyState)===WebSocket.OPEN)return;t("connecting");const p=window.location.protocol==="https:"?"wss:":"ws:",h=window.location.host,v=`${p}//${h}/api/rules/status`;try{const x=new WebSocket(v);i.current=x,x.onopen=()=>{console.log("[RulesStatus] WebSocket 连接已建立"),t("connected"),a.current&&(clearTimeout(a.current),a.current=null),d()},x.onmessage=g=>{try{const b=JSON.parse(g.data);if(b.type==="rule_status"){const{ruleId:w,status:S,totalTokensUsed:j,totalRequestsUsed:k,timestamp:C}=b.data;r(O=>({...O,[w]:{status:S,totalTokensUsed:j,totalRequestsUsed:k,lastUpdate:C}}))}}catch(b){console.error("[RulesStatus] 解析消息失败:",b)}},x.onclose=g=>{console.log("[RulesStatus] WebSocket 连接关闭:",g.code,g.reason),t("disconnected"),f(),g.code!==1e3&&u()},x.onerror=g=>{console.error("[RulesStatus] WebSocket 错误:",g)}}catch(x){console.error("[RulesStatus] 创建 WebSocket 失败:",x),t("disconnected"),u()}},s=()=>{a.current&&(clearTimeout(a.current),a.current=null),f(),i.current&&(i.current.close(1e3,"主动关闭"),i.current=null),t("disconnected")},u=()=>{a.current||(console.log("[RulesStatus] 5秒后尝试重连..."),a.current=setTimeout(()=>{a.current=null,l()},5e3))},d=()=>{o.current=setInterval(()=>{var p;((p=i.current)==null?void 0:p.readyState)===WebSocket.OPEN?i.current.send(JSON.stringify({type:"ping"})):f()},3e4)},f=()=>{o.current&&(clearInterval(o.current),o.current=null)};return m.useEffect(()=>(l(),()=>{s()}),[]),m.useEffect(()=>{const p=setInterval(()=>{const h=Date.now();r(v=>{const y={...v};let x=!1;return Object.keys(y).forEach(g=>{h-y[g].lastUpdate>6e4&&y[g].status==="in_use"&&(y[g]={...y[g],status:"idle"},x=!0)}),x?y:v})},1e4);return()=>{clearInterval(p)}},[]),{connectionStatus:e,ruleStatuses:n,getRuleStatus:p=>n[p],isConnected:e==="connected"}}const Q1=[{value:"default",label:"默认"},{value:"background",label:"后台"},{value:"thinking",label:"思考"},{value:"long-context",label:"长上下文"},{value:"image-understanding",label:"图像理解"},{value:"model-mapping",label:"模型顶替"}],Th=[{value:"claude-code",label:"Claude Code"},{value:"codex",label:"Codex"}];function Z1(e){const t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0");return`${t}-${n}-${r}T${i}:${a}`}const Ih=e=>e==="claude-code"?{write:te.writeClaudeConfig,restore:te.restoreClaudeConfig,checkBackup:te.checkClaudeBackup,toolName:"Claude Code"}:{write:te.writeCodexConfig,restore:te.restoreCodexConfig,checkBackup:te.checkCodexBackup,toolName:"Codex"};function J1(){var z0,$0;const{confirm:e}=Cy(),{ruleStatuses:t}=O3(),[n,r]=m.useState([]),[i,a]=m.useState([]),[o,l]=m.useState([]),[s,u]=m.useState([]),[d,f]=m.useState([]),[p,h]=m.useState(null),[v,y]=m.useState(!1),[x,g]=m.useState(!1),[b,w]=m.useState(null),[S,j]=m.useState(null),[k,C]=m.useState(""),[O,N]=m.useState(""),[A,T]=m.useState(""),[I,q]=m.useState(""),[z,D]=m.useState(0),[$,K]=m.useState((S==null?void 0:S.contentType)||""),[M,R]=m.useState(void 0),[P,G]=m.useState(void 0),[ee,E]=m.useState(void 0),[ae,xe]=m.useState(void 0),[H,Y]=m.useState(void 0),[ue,F]=m.useState(void 0),[J,re]=m.useState(void 0),[B,ve]=m.useState(null),[de,_e]=m.useState(!1),[Ne,Ae]=m.useState(!1),[tt,bt]=m.useState(void 0),[wt,yn]=m.useState(void 0),[sr,Yr]=m.useState({}),[Pi,Tn]=m.useState(!1),[V,Z]=m.useState(!1),[ye,Se]=m.useState({"claude-code":!1,codex:!1}),[Pe,St]=m.useState(null),{recordPositions:W,applyAnimation:oe}=C3(),fe=m.useRef(new Map),je=m.useRef(null);m.useEffect(()=>{Oe(),lt(),vl(),Xt()},[]),m.useEffect(()=>{const _=ne=>{Pe&&(ne.preventDefault(),ne.returnValue="正在配置路由,刷新页面可能导致配置不完整。")};return window.addEventListener("beforeunload",_),()=>window.removeEventListener("beforeunload",_)},[Pe]),m.useEffect(()=>{p&&ot(p.id)},[p]),m.useEffect(()=>{f(k?s.filter(_=>_.vendorId===k):[]),N(""),T("")},[k,s]);const Oe=async()=>{const ne=(await te.getRoutes()).sort((ge,be)=>ge.isActive&&!be.isActive?-1:!ge.isActive&&be.isActive?1:0);r(ne),ne.length>0&&!p&&h(ne[0])},ot=async _=>{const ne=await te.getRules(_);if(a(ne),_)try{const be=(await te.getRulesBlacklistStatus(_)).reduce((Ve,Qt)=>(Ve[Qt.ruleId]=Qt,Ve),{});Yr(be)}catch(ge){console.error("Failed to load blacklist status:",ge)}},lt=async()=>{const _=await te.getVendors();l(_)},vl=async()=>{const _=await te.getAPIServices();u(_)},Xt=async()=>{try{const[_,ne]=await Promise.all([te.checkClaudeBackup(),te.checkCodexBackup()]);Se({"claude-code":_.exists,codex:ne.exists})}catch(_){console.error("检查备份状态失败:",_),Se({"claude-code":!1,codex:!1})}},Ci=async _=>{const ne=n.find(Ve=>Ve.id===_);if(!ne)return;await Xt();const ge=!ye[ne.targetType];St(_);let be=!1;try{if(ge)try{await Ih(ne.targetType).write(),be=!0}catch(Ve){throw new Error(`配置文件覆盖失败: ${Ve.message||"未知错误"}`)}try{const Ve=fe.current.get(_);Ve&&W(_,Ve),je.current=_,await te.activateRoute(_),await Oe(),await Xt(),Ve&&setTimeout(()=>{const Qt=fe.current.get(_);Qt&&oe(_,Qt,250),je.current=null},0)}catch(Ve){if(be)try{throw await Ih(ne.targetType).restore(),new Error(`路由激活失败,配置文件已回滚: ${Ve.message||"未知错误"}`)}catch(Qt){throw new Error(`路由激活失败且配置回滚失败!请手动检查配置文件。
|
|
351
|
+
`}),c.jsx("div",{style:{position:"fixed",top:"20px",right:"20px",zIndex:9999},children:e.map(i=>c.jsxs("div",{style:n(i.type),children:[c.jsx("span",{style:{fontSize:"18px",fontWeight:"bold"},children:r(i.type)}),c.jsx("span",{style:{flex:1},children:i.message}),c.jsx("button",{onClick:()=>aE(i.id),style:{background:"none",border:"none",color:"inherit",cursor:"pointer",fontSize:"18px",padding:"0",marginLeft:"10px",opacity:.6},onMouseEnter:a=>a.currentTarget.style.opacity="1",onMouseLeave:a=>a.currentTarget.style.opacity="0.6",children:"×"})]},i.id))})]})}function X1(e){const t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0");return`${t}-${n}-${r}T${i}:${a}`}function j3({value:e=[],onChange:t,placeholder:n,inputValue:r,onInputChange:i}){const a=l=>{if(l.key==="Enter"||l.key===","){l.preventDefault();const s=r.trim();s&&!e.includes(s)&&(t([...e,s]),i(""))}else l.key==="Backspace"&&!r&&e.length>0&&t(e.slice(0,-1))},o=l=>{t(e.filter((s,u)=>u!==l))};return c.jsx("div",{style:{border:"1px solid var(--border-primary)",borderRadius:"4px",padding:"8px",minHeight:"40px",background:"var(--bg-secondary)"},children:c.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:"4px",alignItems:"center"},children:[e.map((l,s)=>c.jsxs("span",{style:{backgroundColor:"var(--accent-light)",color:"var(--text-primary)",padding:"4px 8px",borderRadius:"4px",fontSize:"12px",display:"flex",alignItems:"center",gap:"4px"},children:[l,c.jsx("button",{type:"button",onClick:()=>o(s),style:{background:"none",border:"none",color:"var(--text-primary)",cursor:"pointer",fontSize:"16px",lineHeight:"1",padding:"0",marginLeft:"4px"},onMouseOver:u=>u.currentTarget.style.color="var(--accent-danger)",onMouseOut:u=>u.currentTarget.style.color="var(--text-primary)",children:"×"})]},s)),c.jsx("input",{type:"text",value:r,onChange:l=>i(l.target.value),onKeyDown:a,placeholder:n,style:{border:"none",outline:"none",flex:"1",minWidth:"120px",fontSize:"14px"}})]})})}function P3(){var Pe,St;const{confirm:e}=Cy(),[t,n]=m.useState([]),[r,i]=m.useState([]),[a,o]=m.useState(null),[l,s]=m.useState(!1),[u,d]=m.useState(!1),[f,p]=m.useState(!1),[h,v]=m.useState(!1),[y,x]=m.useState(null),[g,b]=m.useState(null),[w,S]=m.useState([]),[j,k]=m.useState(""),[C,O]=m.useState({}),[N,A]=m.useState(!1),[T,I]=m.useState(void 0),[q,z]=m.useState(void 0),[D,$]=m.useState(void 0),[K,M]=m.useState(!1),[R,P]=m.useState(void 0),[G,ee]=m.useState(void 0),[E,ae]=m.useState(void 0),[xe,H]=m.useState("openai-chat"),[Y,ue]=m.useState(Jn.AUTO),[F,J]=m.useState(""),[re,B]=m.useState([]),[ve,de]=m.useState(""),_e=x3(),Ne=m.useMemo(()=>{const W=Object.keys(In).filter(fe=>In[fe].is_oversea).map(fe=>({...In[fe],key:fe}));return[...Object.keys(In).filter(fe=>!In[fe].is_oversea).map(fe=>({...In[fe],key:fe})),null,...W]},[]);m.useEffect(()=>{Ae()},[]),m.useEffect(()=>{a&&tt(a.id)},[a]),m.useEffect(()=>{const W=new Set(w),oe={};Object.entries(C).forEach(([je,Oe])=>{W.has(je)&&(oe[je]=Oe)}),Object.keys(oe).length!==Object.keys(C).length&&O(oe)},[w]);const Ae=async()=>{const W=await te.getVendors();n(W),W.length>0&&!a&&o(W[0])},tt=async W=>{const oe=await te.getAPIServices(W);i(oe)},bt=()=>{x(null),s(!0)},wt=()=>{p(!0)},yn=W=>{x(W),s(!0)},sr=async W=>{await e({message:"确定要删除此供应商吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteVendor(W),Ae(),a&&a.id===W&&(o(null),i([])),me.success("供应商已删除"))},Yr=async W=>{W.preventDefault();const oe=new FormData(W.currentTarget),fe={name:oe.get("name"),description:oe.get("description"),sortOrder:parseInt(oe.get("sortOrder"))||0};y?await te.updateVendor(y.id,fe):await te.createVendor(fe),s(!1),Ae()},Pi=()=>{b(null),S([]),k(""),O({}),A(!1),I(void 0),z(void 0),$(void 0),M(!1),P(void 0),ee(void 0),ae(void 0),H("openai-chat"),d(!0)},Tn=W=>{b(W),S(W.supportedModels||[]),k(""),O(W.modelLimits||{}),A(W.enableTokenLimit||!1),I(W.tokenLimit),z(W.tokenResetInterval),$(W.tokenResetBaseTime?new Date(W.tokenResetBaseTime):void 0),M(W.enableRequestLimit||!1),P(W.requestCountLimit),ee(W.requestResetInterval),ae(W.requestResetBaseTime?new Date(W.requestResetBaseTime):void 0),H(W.sourceType||"openai-chat"),ue(W.authType||Jn.AUTO),d(!0)},V=async W=>{await e({message:"确定要删除此API服务吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteAPIService(W),a&&tt(a.id),me.success("API服务已删除"))},Z=async W=>{W.preventDefault();let oe=[...w];if(j.trim()){const ot=j.split(",").map(lt=>lt.trim()).filter(lt=>lt&&!oe.includes(lt));oe=[...oe,...ot]}const fe=new FormData(W.currentTarget),je={};Object.entries(C).forEach(([ot,lt])=>{ot&<&<>0&&(je[ot]=lt)});const Oe={vendorId:a.id,name:fe.get("name"),apiUrl:fe.get("apiUrl"),apiKey:fe.get("apiKey"),sourceType:fe.get("sourceType"),authType:fe.get("authType")||void 0,supportedModels:oe.length>0?oe:void 0,modelLimits:Object.keys(je).length>0?je:void 0,enableProxy:fe.get("enableProxy")==="on",enableTokenLimit:N,tokenLimit:T,tokenResetInterval:q,tokenResetBaseTime:D?D.getTime():void 0,enableRequestLimit:K,requestCountLimit:R,requestResetInterval:G,requestResetBaseTime:E?E.getTime():void 0};g?await te.updateAPIService(g.id,Oe):await te.createAPIService(Oe),d(!1),S([]),k(""),O({}),A(!1),I(void 0),z(void 0),$(void 0),M(!1),P(void 0),ee(void 0),ae(void 0),a&&tt(a.id)},ye=W=>{if(W){J(W);const oe=In[W];oe&&oe.services.length>0&&B(oe.services.map((fe,je)=>je))}else J(""),B([]);de(""),v(!0)},Se=async W=>{W.preventDefault();const oe=new FormData(W.currentTarget),fe=oe.get("vendorKey"),je=oe.get("apiKey");if(!fe||!je){me.warning("请填写完整信息");return}if(re.length===0){me.warning("请至少选择一个源类型");return}const Oe=In[fe];if(!Oe){me.error("未找到对应的供应商配置");return}try{const ot=await te.createVendor({name:Oe.name,description:Oe.description}),vl=Oe.services.filter((Xt,Ci)=>re.includes(Ci)).map(async Xt=>te.createAPIService({vendorId:ot.id,name:Xt.name,apiUrl:Xt.apiUrl,apiKey:je,sourceType:Xt.sourceType,authType:Xt.authType,supportedModels:Xt.models?Xt.models.split(",").map(Ci=>Ci.trim()):void 0,modelLimits:Xt.modelLimits||{}}));await Promise.all(vl),await Ae(),v(!1),me.success(`配置成功! 已创建 ${re.length} 个API服务`)}catch(ot){console.error("一键配置失败:",ot),me.error("配置失败,请检查输入信息")}};return c.jsxs("div",{className:"vendors-page",children:[c.jsxs("div",{className:"page-header",children:[c.jsx("h1",{children:"供应商管理"}),c.jsx("p",{children:"管理API供应商和服务配置"})]}),c.jsxs("div",{style:{display:"flex",gap:"20px"},children:[c.jsxs("div",{className:"card",style:{flex:"0 0 25%",minWidth:400},children:[c.jsxs("div",{className:"toolbar",children:[c.jsx("h3",{children:"供应商列表"}),c.jsxs("div",{style:{display:"flex",gap:"10px"},children:[c.jsx("button",{className:"btn btn-secondary",style:{background:"#2563EB",color:"#FFFFFF",border:"none",cursor:"pointer"},onClick:wt,children:"推荐"}),c.jsx("button",{className:"btn btn-primary",onClick:()=>ye(),children:"一键配置"}),c.jsx("button",{className:"btn btn-primary",onClick:bt,children:"新增"})]})]}),t.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无供应商"})}):c.jsx("div",{style:{marginTop:"10px"},children:t.map(W=>c.jsx("div",{onClick:()=>o(W),style:{padding:"12px",marginBottom:"8px",backgroundColor:a&&a.id===W.id?"var(--accent-light)":"var(--bg-secondary)",borderRadius:"4px",cursor:"pointer",border:"1px solid var(--border-secondary)",color:"var(--text-primary)"},children:c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",gap:"8px"},children:[c.jsxs("div",{style:{flex:1,minWidth:0,overflow:"hidden"},children:[c.jsx("div",{style:{fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:W.name}),W.description&&c.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginTop:"4px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:W.description})]}),c.jsxs("div",{className:"action-buttons",style:{flexShrink:0},children:[c.jsx("button",{className:"btn btn-secondary",style:{padding:"4px 8px",fontSize:"12px"},onClick:oe=>{oe.stopPropagation(),yn(W)},children:"编辑"}),c.jsx("button",{className:"btn btn-danger",style:{padding:"4px 8px",fontSize:"12px"},onClick:oe=>{oe.stopPropagation(),sr(W.id)},children:"删除"})]})]})},W.id))})]}),c.jsxs("div",{className:"card",style:{flex:1},children:[c.jsxs("div",{className:"toolbar",children:[c.jsxs("h3",{children:["供应商",a?`(${a.name})`:null,"API服务"]}),a&&c.jsx("button",{className:"btn btn-primary",onClick:Pi,children:"新增服务"})]}),a?r.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无API服务"})}):c.jsxs("table",{style:{fontSize:"smaller"},children:[c.jsx("thead",{children:c.jsxs("tr",{children:[c.jsx("th",{style:{whiteSpace:"nowrap"},children:"服务名称"}),c.jsx("th",{children:"源类型"}),c.jsx("th",{children:"API地址"}),c.jsx("th",{children:"模型"}),c.jsx("th",{children:"操作"})]})}),c.jsx("tbody",{children:r.map(W=>{var oe;return c.jsxs("tr",{children:[c.jsx("td",{children:W.name}),c.jsx("td",{children:W.sourceType?Hu[W.sourceType]:"-"}),c.jsx("td",{style:{maxWidth:"200px",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:W.apiUrl,children:W.apiUrl}),c.jsxs("td",{children:[((oe=W.supportedModels)==null?void 0:oe.length)??"*"," 个"]}),c.jsx("td",{children:c.jsxs("div",{className:"action-buttons",children:[c.jsx("button",{className:"btn btn-sm btn-secondary",onClick:()=>Tn(W),children:"编辑"}),c.jsx("button",{className:"btn btn-sm btn-danger",onClick:()=>V(W.id),children:"删除"})]})})]},W.id)})})]}):c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"请先选择一个供应商"})})]})]}),l&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>s(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:y?"编辑供应商":"新增供应商"})}),c.jsxs("form",{onSubmit:Yr,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商名称"}),c.jsx("input",{type:"text",name:"name",defaultValue:y?y.name:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"描述"}),c.jsx("textarea",{name:"description",rows:3,defaultValue:y?y.description:""})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["排序 ",c.jsx("small",{children:"数值越大越靠前"})]}),c.jsx("input",{type:"number",name:"sortOrder",defaultValue:y&&y.sortOrder||0,min:"0"})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>s(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),u&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>d(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",style:{width:800},children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:g?"编辑供应商API服务":"新增供应商API服务"})}),c.jsxs("form",{onSubmit:Z,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"服务名称"}),c.jsx("input",{type:"text",name:"name",defaultValue:g?g.name:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["数据源类型 ",c.jsx("small",{children:"供应商接口返回的数据格式标准类型"})]}),c.jsxs("select",{name:"sourceType",defaultValue:g&&g.sourceType||"",onChange:W=>H(W.target.value),required:!0,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择源类型"}),Object.keys(Hu).map(W=>c.jsx("option",{value:W,children:Hu[W]},W))]}),c.jsx("small",{style:{display:"block",marginTop:"4px",color:"var(--text-muted)"},children:m3[xe]||""})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商API地址"}),c.jsx("input",{type:"url",name:"apiUrl",defaultValue:g?g.apiUrl:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商API密钥"}),c.jsx("input",{type:"password",name:"apiKey",defaultValue:g?g.apiKey:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["API认证方式 ",c.jsx("small",{children:"API 请求使用的认证方式"})]}),c.jsx("select",{name:"authType",defaultValue:g&&g.authType||Jn.AUTO,onChange:W=>ue(W.target.value),children:Object.keys(G1).map(W=>c.jsx("option",{value:W,children:G1[W]},W))}),c.jsx("small",{style:{display:"block",marginTop:"4px",color:"var(--text-muted)"},children:v3[Y]||""})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"支持的模型列表"}),c.jsx(j3,{value:w,onChange:S,inputValue:j,onInputChange:k,placeholder:"输入模型名,按Enter或逗号添加"},(g==null?void 0:g.id)||"new"),c.jsx("div",{style:{display:"block",width:"100%"},children:c.jsx("small",{style:{fontSize:"10px"},children:"留空表示支持所有模型,路由配置中,可直接将模型透传给该供应商服务接口。"})})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["模型输出限制 ",c.jsx("small",{children:"为支持的模型配置最大输出tokens"})]}),c.jsxs("div",{style:{border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"16px",background:"var(--bg-secondary)",maxHeight:"300px",overflowY:"auto"},children:[Object.keys(C).length===0&&w.length===0?c.jsx("div",{style:{color:"var(--text-muted)",textAlign:"center",padding:"20px",fontSize:"14px"},children:"暂无模型限制配置,可点击下方按钮添加"}):c.jsxs("div",{children:[w.length>0&&c.jsxs("div",{style:{marginBottom:"12px"},children:[c.jsx("div",{style:{fontSize:"12px",color:"var(--text-muted)",marginBottom:"8px",fontWeight:500},children:'来自"支持的模型列表"(自动同步)'}),w.map(W=>c.jsxs("div",{style:{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center",padding:"8px",background:"var(--bg-primary)",borderRadius:"4px",border:"1px solid var(--accent-light)"},children:[c.jsxs("div",{style:{flex:2,fontSize:"14px",color:"var(--text-primary)",fontWeight:500,display:"flex",alignItems:"center",gap:"6px"},children:[W,c.jsx("span",{style:{fontSize:"10px",padding:"2px 6px",borderRadius:"3px",background:"var(--accent-light)",color:"var(--accent-primary)"},children:"已同步"})]}),c.jsxs("div",{style:{flex:1,display:"flex",alignItems:"center",gap:"8px"},children:[c.jsx("input",{type:"number",value:C[W]||"",onChange:oe=>{const fe=oe.target.value;if(fe===""){const je={...C};delete je[W],O(je)}else O({...C,[W]:parseInt(fe)||0})},placeholder:"留空不限",min:"1",style:{width:"100%",padding:"6px 8px",border:"1px solid var(--border-primary)",borderRadius:"4px",fontSize:"14px"}}),c.jsx("span",{style:{fontSize:"12px",color:"var(--text-muted)",whiteSpace:"nowrap"},children:"tokens"})]}),c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>{const oe={...C};delete oe[W],O(oe)},style:{padding:"4px 8px",fontSize:"12px"},title:"移除此限制(模型仍在支持列表中)",children:"移除限制"})]},`sync-${W}`))]}),Object.keys(C).length>0&&c.jsx("div",{children:Object.entries(C).filter(([W])=>!w.includes(W)).map(([W,oe])=>c.jsxs("div",{style:{display:"flex",gap:"8px",marginBottom:"8px",alignItems:"center",padding:"8px",background:"var(--bg-primary)",borderRadius:"4px",border:"1px solid var(--border-secondary)"},children:[c.jsx("input",{type:"text",value:W,onChange:fe=>{const je={...C},Oe=fe.target.value;delete je[W],je[Oe]=oe,O(je)},placeholder:"模型名 (如: gpt-4)",style:{flex:2,padding:"6px 8px",border:"1px solid var(--border-primary)",borderRadius:"4px",fontSize:"14px"}}),c.jsx("input",{type:"number",value:oe,onChange:fe=>{O({...C,[W]:parseInt(fe.target.value)||0})},placeholder:"最大tokens",min:"1",style:{flex:1,padding:"6px 8px",border:"1px solid var(--border-primary)",borderRadius:"4px",fontSize:"14px"}}),c.jsx("button",{type:"button",className:"btn btn-sm btn-danger",onClick:()=>{const fe={...C};delete fe[W],O(fe)},style:{padding:"4px 8px",fontSize:"12px"},children:"删除"})]},`custom-${W}`))})]}),c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>{const W=`model-${Date.now()}`;O({...C,[W]:4096})},style:{marginTop:"8px",width:"100%"},children:"+ 添加模型限制"})]}),c.jsx("div",{style:{display:"block",width:"100%",marginTop:"8px"},children:c.jsxs("small",{style:{fontSize:"10px"},children:[c.jsx("strong",{children:"自动同步:"}),"上方添加的模型会自动在此创建限制配置(默认4096),删除模型会同步移除限制。",c.jsx("strong",{children:"手动添加:"}),"可点击下方按钮为特定模型(如 gpt-4)或前缀(如 gpt-4-*)添加限制。 留空则透传前端工具发送的值。支持精确匹配和前缀匹配。 对于o1等新模型,将自动映射到max_completion_tokens字段。"]})})]}),c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[c.jsx("input",{type:"checkbox",name:"enableProxy",defaultChecked:(g==null?void 0:g.enableProxy)||!1,style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用代理"})]}),c.jsx("small",{style:{display:"block",marginTop:"6px",color:"#666",fontSize:"12px",marginLeft:"24px"},children:'勾选后,此 API 服务的请求将通过设置的代理转发。请在"设置"页面配置代理。'})]}),c.jsx("div",{className:"form-group",children:c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[c.jsx("input",{type:"checkbox",checked:N,onChange:W=>A(W.target.checked),style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用Token超量限制"})]})}),N&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Token超量值(单位:k)"}),c.jsx("input",{type:"number",value:T||"",onChange:W=>I(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:1000表示1000k tokens"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:q||"",onChange:W=>z(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:720表示30天,168表示7天"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:D?X1(D):"",onChange:W=>{W.target.value?$(new Date(W.target.value)):$(void 0)},className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置下一次重置的精确时间点"})]})]}),c.jsx("div",{className:"form-group",children:c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer"},children:[c.jsx("input",{type:"checkbox",checked:K,onChange:W=>M(W.target.checked),style:{marginRight:"8px",cursor:"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用请求次数超量限制"})]})}),K&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"请求次数超量值"}),c.jsx("input",{type:"number",value:R||"",onChange:W=>P(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:100"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:G||"",onChange:W=>ee(W.target.value?parseInt(W.target.value):void 0),min:"1",placeholder:"例如:720表示30天,168表示7天"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:E?X1(E):"",onChange:W=>{W.target.value?ae(new Date(W.target.value)):ae(void 0)},className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置下一次重置的精确时间点"})]})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>d(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),f&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>p(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",style:{maxWidth:"800px"},children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:"供应商推荐"})}),c.jsx("div",{className:"modal-body",children:c.jsx("div",{className:"markdown-content",children:c.jsx(Py,{components:{a:({href:W,children:oe,title:fe})=>fe&&In[fe]?c.jsx("a",{href:"#",style:{color:"#2563EB",borderBottom:"solid 1px #2563EB",cursor:"pointer"},onClick:je=>{je.preventDefault(),p(!1),ye(fe)},children:oe}):c.jsx("a",{href:W,style:{color:"#2563EB",borderBottom:"solid 1px #2563EB"},target:"_blank",rel:"noopener noreferrer",children:oe})},children:_e})})}),c.jsx("div",{className:"modal-footer",children:c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>p(!1),children:"关闭"})})]})})]}),h&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>v(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:"一键配置供应商"})}),c.jsxs("form",{onSubmit:Se,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商"}),c.jsxs("select",{name:"vendorKey",value:F,onChange:W=>{const oe=W.target.value;if(J(oe),oe){const fe=In[oe];fe&&fe.services.length>0&&B(fe.services.map((je,Oe)=>Oe))}else B([])},required:!0,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择供应商"}),Ne.map(W=>W?c.jsx("option",{value:W.key,children:W.name},W.key):c.jsx("option",{value:"",disabled:!0,children:"--"}))]})]}),(Pe=In[F])!=null&&Pe.description?c.jsx("div",{style:{fontSize:".8em",marginBottom:16,marginTop:-16},children:In[F].description}):null,c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["源类型 ",c.jsx("small",{style:{color:"var(--text-muted)",fontWeight:"normal"},children:"可选择多个"})]}),c.jsx("div",{style:{border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"16px",background:"var(--bg-secondary)",minHeight:"100px",display:"flex",flexDirection:"column",gap:"8px"},children:F?(St=In[F])==null?void 0:St.services.map((W,oe)=>{const fe=re.includes(oe);return c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:"pointer",padding:"10px 14px",borderRadius:"6px",background:fe?"var(--accent-light)":"transparent",border:`2px solid ${fe?"var(--accent-primary)":"transparent"}`,transition:"all 0.2s ease",position:"relative",overflow:"hidden"},onMouseEnter:je=>{fe||(je.currentTarget.style.background="var(--bg-hover)",je.currentTarget.style.borderColor="var(--border-secondary)")},onMouseLeave:je=>{fe||(je.currentTarget.style.background="transparent",je.currentTarget.style.borderColor="transparent")},children:[c.jsx("input",{type:"checkbox",checked:fe,onChange:je=>{je.target.checked?B([...re,oe]):B(re.filter(Oe=>Oe!==oe))},style:{width:"18px",height:"18px",marginRight:"12px",cursor:"pointer",accentColor:"var(--accent-primary)"}}),c.jsxs("span",{style:{fontSize:"14px",fontWeight:fe?"600":"400",color:fe?"var(--accent-primary)":"var(--text-primary)",transition:"all 0.2s ease"},children:[W.name," - ",Hu[W.sourceType]]}),fe&&c.jsx("span",{style:{marginLeft:"auto",fontSize:"16px",color:"var(--accent-primary)"},children:"✓"})]},oe)}):c.jsx("div",{style:{color:"var(--text-muted)",textAlign:"center",padding:"30px 20px",fontSize:"14px"},children:"请先选择供应商"})})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"API Key"}),c.jsx("input",{type:"password",name:"apiKey",value:ve,onChange:W=>de(W.target.value),placeholder:"请输入API密钥",required:!0})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>v(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"确认配置"})]})]})]})})]})]})}function C3(){const e=m.useRef(new Map),t=m.useRef(!1),n=m.useCallback((a,o)=>{var u;const l=o.getBoundingClientRect(),s=(u=o.parentElement)==null?void 0:u.getBoundingClientRect();s&&e.current.set(a,{top:l.top-s.top,left:l.left-s.left,height:l.height,width:l.width})},[]),r=m.useCallback((a,o,l=250)=>{var v;if(t.current)return;const s=e.current.get(a);if(!s)return;const u=o.getBoundingClientRect(),d=(v=o.parentElement)==null?void 0:v.getBoundingClientRect();if(!d)return;const f={top:u.top-d.top,left:u.left-d.left,height:u.height,width:u.width},p=s.top-f.top,h=s.left-f.left;if(Math.abs(p)<1&&Math.abs(h)<1){e.current.delete(a);return}o.style.transform=`translate(${h}px, ${p}px)`,o.style.transition="none",o.style.willChange="transform",t.current=!0,requestAnimationFrame(()=>{o.style.transition=`transform ${l}ms cubic-bezier(0.4, 0, 0.2, 1)`,o.style.transform="",setTimeout(()=>{e.current.delete(a),t.current=!1,o.style.willChange=""},l)})},[]),i=m.useCallback(()=>{e.current.clear()},[]);return{recordPositions:n,applyAnimation:r,clearPositions:i}}function O3(){const[e,t]=m.useState("disconnected"),[n,r]=m.useState({}),i=m.useRef(null),a=m.useRef(null),o=m.useRef(null),l=()=>{var y;if(((y=i.current)==null?void 0:y.readyState)===WebSocket.OPEN)return;t("connecting");const p=window.location.protocol==="https:"?"wss:":"ws:",h=window.location.host,v=`${p}//${h}/api/rules/status`;try{const x=new WebSocket(v);i.current=x,x.onopen=()=>{console.log("[RulesStatus] WebSocket 连接已建立"),t("connected"),a.current&&(clearTimeout(a.current),a.current=null),d()},x.onmessage=g=>{try{const b=JSON.parse(g.data);if(b.type==="rule_status"){const{ruleId:w,status:S,totalTokensUsed:j,totalRequestsUsed:k,timestamp:C}=b.data;r(O=>({...O,[w]:{status:S,totalTokensUsed:j,totalRequestsUsed:k,lastUpdate:C}}))}}catch(b){console.error("[RulesStatus] 解析消息失败:",b)}},x.onclose=g=>{console.log("[RulesStatus] WebSocket 连接关闭:",g.code,g.reason),t("disconnected"),f(),g.code!==1e3&&u()},x.onerror=g=>{console.error("[RulesStatus] WebSocket 错误:",g)}}catch(x){console.error("[RulesStatus] 创建 WebSocket 失败:",x),t("disconnected"),u()}},s=()=>{a.current&&(clearTimeout(a.current),a.current=null),f(),i.current&&(i.current.close(1e3,"主动关闭"),i.current=null),t("disconnected")},u=()=>{a.current||(console.log("[RulesStatus] 5秒后尝试重连..."),a.current=setTimeout(()=>{a.current=null,l()},5e3))},d=()=>{o.current=setInterval(()=>{var p;((p=i.current)==null?void 0:p.readyState)===WebSocket.OPEN?i.current.send(JSON.stringify({type:"ping"})):f()},3e4)},f=()=>{o.current&&(clearInterval(o.current),o.current=null)};return m.useEffect(()=>(l(),()=>{s()}),[]),m.useEffect(()=>{const p=setInterval(()=>{const h=Date.now();r(v=>{const y={...v};let x=!1;return Object.keys(y).forEach(g=>{h-y[g].lastUpdate>6e4&&y[g].status==="in_use"&&(y[g]={...y[g],status:"idle"},x=!0)}),x?y:v})},1e4);return()=>{clearInterval(p)}},[]),{connectionStatus:e,ruleStatuses:n,getRuleStatus:p=>n[p],isConnected:e==="connected"}}const Q1=[{value:"default",label:"默认"},{value:"background",label:"后台"},{value:"thinking",label:"思考"},{value:"long-context",label:"长上下文"},{value:"image-understanding",label:"图像理解"},{value:"model-mapping",label:"模型顶替"}],Th=[{value:"claude-code",label:"Claude Code"},{value:"codex",label:"Codex"}];function Z1(e){const t=e.getFullYear(),n=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0"),i=String(e.getHours()).padStart(2,"0"),a=String(e.getMinutes()).padStart(2,"0");return`${t}-${n}-${r}T${i}:${a}`}const Ih=e=>e==="claude-code"?{write:te.writeClaudeConfig,restore:te.restoreClaudeConfig,checkBackup:te.checkClaudeBackup,toolName:"Claude Code"}:{write:te.writeCodexConfig,restore:te.restoreCodexConfig,checkBackup:te.checkCodexBackup,toolName:"Codex"};function J1(){var z0,$0;const{confirm:e}=Cy(),{ruleStatuses:t}=O3(),[n,r]=m.useState([]),[i,a]=m.useState([]),[o,l]=m.useState([]),[s,u]=m.useState([]),[d,f]=m.useState([]),[p,h]=m.useState(null),[v,y]=m.useState(!1),[x,g]=m.useState(!1),[b,w]=m.useState(null),[S,j]=m.useState(null),[k,C]=m.useState(""),[O,N]=m.useState(""),[A,T]=m.useState(""),[I,q]=m.useState(""),[z,D]=m.useState(0),[$,K]=m.useState((S==null?void 0:S.contentType)||""),[M,R]=m.useState(void 0),[P,G]=m.useState(void 0),[ee,E]=m.useState(void 0),[ae,xe]=m.useState(void 0),[H,Y]=m.useState(void 0),[ue,F]=m.useState(void 0),[J,re]=m.useState(void 0),[B,ve]=m.useState(null),[de,_e]=m.useState(!1),[Ne,Ae]=m.useState(!1),[tt,bt]=m.useState(void 0),[wt,yn]=m.useState(void 0),[sr,Yr]=m.useState({}),[Pi,Tn]=m.useState(!1),[V,Z]=m.useState(!1),[ye,Se]=m.useState({"claude-code":!1,codex:!1}),[Pe,St]=m.useState(null),{recordPositions:W,applyAnimation:oe}=C3(),fe=m.useRef(new Map),je=m.useRef(null);m.useEffect(()=>{Oe(),lt(),vl(),Xt()},[]),m.useEffect(()=>{const _=ne=>{Pe&&(ne.preventDefault(),ne.returnValue="正在配置路由,刷新页面可能导致配置不完整。")};return window.addEventListener("beforeunload",_),()=>window.removeEventListener("beforeunload",_)},[Pe]),m.useEffect(()=>{p&&ot(p.id)},[p]),m.useEffect(()=>{f(k?s.filter(_=>_.vendorId===k):[]),N(""),T("")},[k,s]);const Oe=async()=>{const ne=(await te.getRoutes()).sort((ge,be)=>ge.isActive&&!be.isActive?-1:!ge.isActive&&be.isActive?1:0);r(ne),ne.length>0&&!p&&h(ne[0])},ot=async _=>{const ne=await te.getRules(_);if(a(ne),_)try{const be=(await te.getRulesBlacklistStatus(_)).reduce((Ve,Qt)=>(Ve[Qt.ruleId]=Qt,Ve),{});Yr(be)}catch(ge){console.error("Failed to load blacklist status:",ge)}},lt=async()=>{const _=await te.getVendors();l(_)},vl=async()=>{const _=await te.getAPIServices();u(_)},Xt=async()=>{try{const[_,ne]=await Promise.all([te.checkClaudeBackup(),te.checkCodexBackup()]);Se({"claude-code":_.exists,codex:ne.exists})}catch(_){console.error("检查备份状态失败:",_),Se({"claude-code":!1,codex:!1})}},Ci=async _=>{const ne=n.find(Ve=>Ve.id===_);if(!ne)return;await Xt();const ge=!ye[ne.targetType];St(_);let be=!1;try{if(ge)try{await Ih(ne.targetType).write(),be=!0}catch(Ve){throw new Error(`配置文件覆盖失败: ${Ve.message||"未知错误"}`)}try{const Ve=fe.current.get(_);Ve&&W(_,Ve),je.current=_,await te.activateRoute(_),await Oe(),await Xt(),Ve&&setTimeout(()=>{const Qt=fe.current.get(_);Qt&&oe(_,Qt,250),je.current=null},0)}catch(Ve){if(be)try{throw await Ih(ne.targetType).restore(),new Error(`路由激活失败,配置文件已回滚: ${Ve.message||"未知错误"}`)}catch(Qt){throw new Error(`路由激活失败且配置回滚失败!请手动检查配置文件。
|
|
352
352
|
激活错误: ${Ve.message}
|
|
353
353
|
回滚错误: ${Qt.message}`)}throw new Error(`路由激活失败: ${Ve.message||"未知错误"}`)}}catch(Ve){console.error("激活路由失败:",Ve),me.error(Ve.message)}finally{St(null)}},Fp=async _=>{const ne=n.find(be=>be.id===_);if(!ne)return;const ge=Ih(ne.targetType);St(_);try{try{await ge.restore()}catch(be){throw new Error(`配置文件恢复失败: ${be.message||"未知错误"}
|
|
354
354
|
|
|
355
355
|
路由未停用,请检查配置文件权限。`)}try{await te.deactivateRoute(_),await Oe(),await Xt()}catch(be){throw new Error(`配置文件已恢复,但路由停用失败: ${be.message||"未知错误"}
|
|
356
356
|
|
|
357
|
-
请刷新页面后重试。`)}}catch(be){console.error("停用路由失败:",be),me.error(be.message)}finally{St(null)}},Up=async _=>{_.preventDefault();const ne=new FormData(_.currentTarget),ge={name:ne.get("name"),description:ne.get("description"),targetType:ne.get("targetType"),isActive:!1};b?await te.updateRoute(b.id,ge):await te.createRoute(ge),y(!1),Oe()},Wp=async _=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteRoute(_),Oe(),p&&p.id===_&&(h(null),a([])),me.success("路由已删除"))},Hp=async _=>{if(_.preventDefault(),M!==void 0&&tt!==void 0&&M>tt){me.warning(`Token超量值 (${M}k) 不能超过API服务的限制 (${tt}k)`);return}if(H!==void 0&&wt!==void 0&&H>wt){me.warning(`请求次数超量值 (${H}) 不能超过API服务的限制 (${wt})`);return}const ne=new FormData(_.currentTarget),ge={routeId:p.id,contentType:ne.get("contentType"),targetServiceId:O,targetModel:A||void 0,replacedModel:I||void 0,sortOrder:z,timeout:ae?ae*1e3:void 0,tokenLimit:M||void 0,resetInterval:P,tokenResetBaseTime:ee?ee.getTime():void 0,requestCountLimit:H,requestResetInterval:ue,requestResetBaseTime:J?J.getTime():void 0};S?await te.updateRule(S.id,ge):await te.createRule(ge),g(!1),p&&ot(p.id)},U=async _=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteRule(_),p&&ot(p.id),me.success("规则已删除"))},Te=async _=>{try{await te.clearRuleBlacklist(_),p&&ot(p.id),me.success("已恢复")}catch(ne){me.error("恢复失败: "+ne.message)}},Pt=async _=>{try{const ne=await te.toggleRuleDisable(_);p&&ot(p.id),me.success(ne.isDisabled?"规则已屏蔽":"规则已启用")}catch(ne){me.error("操作失败: "+ne.message)}},R0=()=>Q1,qN=_=>{j(_),K(_.contentType);const ne=s.find(ge=>ge.id===_.targetServiceId);ne&&(C(ne.vendorId),f(s.filter(ge=>ge.vendorId===ne.vendorId)),setTimeout(()=>{if(N(ne.id),T(_.targetModel||""),q(_.replacedModel||""),D(_.sortOrder||0),xe(_.timeout?_.timeout/1e3:void 0),R(_.tokenLimit||void 0),G(_.resetInterval),E(_.tokenResetBaseTime?new Date(_.tokenResetBaseTime):void 0),Y(_.requestCountLimit),F(_.requestResetInterval),re(_.requestResetBaseTime?new Date(_.requestResetBaseTime):void 0),ne.enableTokenLimit&&ne.tokenLimit){bt(ne.tokenLimit);const ge=_.tokenLimit===ne.tokenLimit&&_.resetInterval===(ne.tokenResetInterval||void 0)&&_.tokenLimit!==null&&_.resetInterval!==null;_e(ge)}else bt(void 0),_e(!1);if(ne.enableRequestLimit&&ne.requestCountLimit){yn(ne.requestCountLimit);const ge=_.requestCountLimit===ne.requestCountLimit&&_.requestResetInterval===(ne.requestResetInterval||void 0)&&_.requestCountLimit!==null&&_.requestResetInterval!==null;Ae(ge)}else yn(void 0),Ae(!1);Tn(!!_.tokenLimit),Z(!!_.requestCountLimit)},0)),g(!0)},YN=_=>{var Me;const ne=sr[_.id],ge=[],be=t[_.id];if((be==null?void 0:be.status)==="in_use")return{status:"in_use",label:"使用中",reason:"正在处理请求"};if(ne!=null&&ne.isBlacklisted){const Fe=ne.blacklistEntry;(Fe==null?void 0:Fe.errorType)==="timeout"?ge.push("请求超时"):Fe!=null&&Fe.lastStatusCode&&ge.push(`HTTP ${Fe.lastStatusCode}错误`)}const Ve=(be==null?void 0:be.totalTokensUsed)!==void 0?be.totalTokensUsed:_.totalTokensUsed;_.tokenLimit&&Ve!==void 0&&Ve>=_.tokenLimit*1e3&&ge.push("Token超限");const Qt=(be==null?void 0:be.totalRequestsUsed)!==void 0?be.totalRequestsUsed:_.totalRequestsUsed;if(_.requestCountLimit&&Qt!==void 0&&Qt>=_.requestCountLimit&&ge.push("次数超限"),ge.length>0)return{status:"error",label:ne!=null&&ne.isBlacklisted?((Me=ne.blacklistEntry)==null?void 0:Me.errorType)==="timeout"?"超时":"服务错误":ge[0],reason:ge.join(", ")};const pa=[];if(_.tokenLimit&&Ve!==void 0){const Fe=Ve/(_.tokenLimit*1e3)*100;Fe>=80&&pa.push(`Token ${Fe.toFixed(0)}%`)}if(_.requestCountLimit&&Qt!==void 0){const Fe=Qt/_.requestCountLimit*100;Fe>=80&&pa.push(`次数 ${Fe.toFixed(0)}%`)}return pa.length>0?{status:"warning",label:"接近限制",reason:pa.join(", ")}:{status:"success",label:"正常",reason:""}},GN=()=>{j(null),K("default"),C(""),N(""),T(""),q(""),D(0),xe(void 0),R(void 0),G(void 0),E(void 0),Y(void 0),F(void 0),re(void 0),_e(!1),Ae(!1),bt(void 0),yn(void 0),Tn(!1),Z(!1),g(!0)};return c.jsxs("div",{className:"routes-page",children:[c.jsxs("div",{className:"page-header",children:[c.jsx("h1",{children:"路由管理"}),c.jsx("p",{children:"管理API路由和路由配置"})]}),c.jsxs("div",{style:{display:"flex",gap:"20px"},children:[c.jsxs("div",{className:"card",style:{flex:"0 0 25%",minWidth:300},children:[c.jsxs("div",{className:"toolbar",children:[c.jsx("h3",{children:"路由"}),c.jsx("button",{className:"btn btn-primary",onClick:()=>y(!0),children:"新建"})]}),n.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无路由"})}):c.jsx("div",{style:{marginTop:"10px"},children:n.map(_=>{var ne,ge;return c.jsx("div",{ref:be=>{be?fe.current.set(_.id,be):fe.current.delete(_.id)},onClick:()=>h(_),style:{padding:"12px",marginBottom:"8px",backgroundColor:p&&p.id===_.id?"var(--bg-route-item-selected)":"var(--bg-route-item)",borderRadius:"8px",cursor:"pointer",border:"1px solid var(--border-primary)",position:"relative"},children:c.jsxs("div",{children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[c.jsx("div",{style:{fontWeight:500},children:_.name}),_.isActive&&c.jsxs("span",{className:`badge ${_.targetType==="claude-code"?"badge-claude-code":"badge-codex"}`,style:{position:"absolute",top:-16,right:-8},children:[(ne=Th.find(be=>be.value===_.targetType))==null?void 0:ne.label," 已激活"]})]}),c.jsxs("div",{style:{fontSize:"12px",color:"var(--text-route-muted)",marginTop:"2px"},children:["客户端工具: ",(ge=Th.find(be=>be.value===_.targetType))==null?void 0:ge.label]}),c.jsxs("div",{className:"action-buttons",style:{marginTop:"8px"},children:[_.isActive?c.jsx("button",{className:"btn btn-warning",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),Fp(_.id)},disabled:Pe!==null,children:Pe===_.id?"处理中...":"停用"}):c.jsx("button",{className:"btn btn-success",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),Ci(_.id)},disabled:Pe!==null,children:Pe===_.id?"处理中...":"激活"}),c.jsx("button",{className:"btn btn-secondary",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),w(_),y(!0)},children:"编辑"}),c.jsx("button",{className:"btn btn-danger",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),Wp(_.id)},disabled:_.isActive,children:"删除"})]})]})},_.id)})})]}),c.jsxs("div",{className:"card",style:{flex:1},children:[c.jsxs("div",{className:"toolbar",children:[c.jsx("h3",{children:"规则列表"}),p&&c.jsx("button",{className:"btn btn-primary",onClick:GN,children:"新建规则"})]}),p?i.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无路由"})}):c.jsxs("table",{children:[c.jsx("thead",{children:c.jsxs("tr",{children:[c.jsx("th",{children:"优先级"}),c.jsx("th",{children:"类型"}),c.jsx("th",{children:"API服务"}),c.jsx("th",{children:"状态"}),c.jsx("th",{children:"用量情况"}),c.jsx("th",{children:"操作"})]})}),c.jsx("tbody",{children:i.map(_=>{var Ve,Qt,pa;const ne=s.find(Me=>Me.id===_.targetServiceId),ge=o.find(Me=>Me.id===(ne==null?void 0:ne.vendorId)),be=(Ve=Q1.find(Me=>Me.value===_.contentType))==null?void 0:Ve.label;return c.jsxs("tr",{children:[c.jsx("td",{children:_.sortOrder||0}),c.jsx("td",{children:c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[c.jsx("span",{children:be}),_.contentType==="model-mapping"&&_.replacedModel&&c.jsxs("div",{style:{position:"relative",display:"inline-block"},onMouseEnter:()=>ve(_.id),onMouseLeave:()=>ve(null),children:[c.jsx("span",{style:{cursor:"help",fontSize:"14px",color:"var(--text-info)",fontWeight:"bold"},children:"ⓘ"}),B===_.id&&c.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:["被顶替的模型是: ",_.replacedModel,c.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]})}),c.jsx("td",{children:c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"4px",fontSize:"0.6em",flexWrap:"wrap"},children:[c.jsxs("span",{children:[ge?ge.name:"Unknown",":"]}),c.jsxs("span",{children:[ne?ne.name:"Unknown",":"]}),c.jsx("span",{children:_.targetModel||"透传模型"})]})}),c.jsx("td",{style:{whiteSpace:"nowrap"},children:(()=>{var B0,F0;const Me=YN(_),Fe=sr[_.id],XN=(Fe==null?void 0:Fe.isBlacklisted)&&!((B0=Me.reason)!=null&&B0.includes("Token超限"))&&!((F0=Me.reason)!=null&&F0.includes("次数超限"));return _.isDisabled?c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[c.jsx("span",{style:{color:"#6c757d",fontWeight:"bold",fontSize:"14px"},children:"⊘"}),c.jsx("span",{style:{fontSize:"13px",color:"#6c757d",fontWeight:"bold"},children:"已屏蔽"})]}):c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px",flexWrap:"wrap"},children:[c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[Me.status==="success"&&c.jsx("span",{style:{color:"#28a745",fontWeight:"bold",fontSize:"14px"},children:"✓"}),Me.status==="warning"&&c.jsx("span",{style:{color:"#ffc107",fontWeight:"bold",fontSize:"14px"},children:"⚠"}),Me.status==="error"&&c.jsx("span",{style:{color:"#dc3545",fontWeight:"bold",fontSize:"14px"},children:"✗"}),Me.status==="in_use"&&c.jsx(c.Fragment,{children:c.jsx("span",{style:{color:"#007bff",fontWeight:"bold",fontSize:"14px",animation:"pulse 1.5s ease-in-out infinite"},children:"●"})}),c.jsx("span",{style:{fontSize:"13px",color:Me.status==="success"?"#28a745":Me.status==="warning"?"#ffc107":Me.status==="in_use"?"#007bff":"#dc3545",fontWeight:Me.status!=="success"?"bold":"normal"},children:Me.label}),Me.reason&&c.jsxs("div",{style:{position:"relative",display:"inline-block",cursor:"help"},onMouseEnter:()=>ve(_.id+"-status"),onMouseLeave:()=>ve(null),children:[c.jsx("span",{style:{fontSize:"12px",color:"#999",marginLeft:"4px"},children:" ⓘ"}),B===_.id+"-status"&&c.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:[Me.reason,c.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]}),XN&&c.jsx("button",{className:"btn btn-info",style:{padding:"2px 8px",fontSize:"11px"},onClick:()=>Te(_.id),children:"恢复"})]})})()}),c.jsx("td",{children:c.jsxs("div",{style:{fontSize:"13px"},children:[c.jsxs("div",{style:{whiteSpace:"nowrap"},children:[c.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"Tokens:"}),_.tokenLimit?c.jsxs(c.Fragment,{children:[c.jsxs("span",{style:{color:(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalTokensUsed)??_.totalTokensUsed;return Me&&_.tokenLimit&&Me>=_.tokenLimit*1e3?"red":"inherit"})()},children:[(((((Qt=t[_.id])==null?void 0:Qt.totalTokensUsed)??_.totalTokensUsed)||0)/1e3).toFixed(1),"K/",_.tokenLimit.toFixed(0),"K"]}),(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalTokensUsed)??_.totalTokensUsed;return Me&&_.tokenLimit&&Me>=_.tokenLimit*1e3?c.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]}):c.jsx("span",{style:{color:"#999"},children:"不限制"})]}),c.jsxs("div",{style:{marginTop:"6px"},children:[c.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"次数:"}),_.requestCountLimit?c.jsxs(c.Fragment,{children:[c.jsxs("span",{style:{color:(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalRequestsUsed)??_.totalRequestsUsed;return Me&&_.requestCountLimit&&Me>=_.requestCountLimit?"red":"inherit"})()},children:[(((pa=t[_.id])==null?void 0:pa.totalRequestsUsed)??_.totalRequestsUsed)||0,"/",_.requestCountLimit]}),(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalRequestsUsed)??_.totalRequestsUsed;return Me&&_.requestCountLimit&&Me>=_.requestCountLimit?c.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]}):c.jsx("span",{style:{color:"#999"},children:"不限制"})]})]})}),c.jsx("td",{children:c.jsxs("div",{className:"action-buttons",style:{justifyContent:"flex-end"},children:[c.jsx("button",{className:`btn ${_.isDisabled?"btn-success":"btn-warning"}`,onClick:()=>Pt(_.id),title:_.isDisabled?"启用规则":"临时屏蔽规则",children:_.isDisabled?"启用":"屏蔽"}),c.jsx("button",{className:"btn btn-secondary",onClick:()=>qN(_),children:"编辑"}),c.jsx("button",{className:"btn btn-danger",onClick:()=>U(_.id),children:"删除"})]})})]},_.id)})})]}):c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"请先选择一个路由"})}),p&&i.length>0&&c.jsxs("div",{style:{fontSize:"12px",color:"var(--text-info-box)",marginTop:"16px",padding:"12px",backgroundColor:"var(--bg-info-box)",borderRadius:"6px",border:"1px solid var(--border-info-box)",lineHeight:"1.6"},children:[c.jsx("strong",{children:"💡 智能故障切换机制"}),c.jsxs("div",{style:{marginTop:"6px"},children:["• 当同一请求类型配置多个规则时,系统会按排序优先使用第一个",c.jsx("br",{}),"• 如果某个服务报错(4xx/5xx)或请求超时,将自动切换到下一个可用服务",c.jsx("br",{}),"• 报错或超时的服务会被标记为不可用,有效期10分钟",c.jsx("br",{}),"• 10分钟后自动解除标记,如果再次报错或超时则重新标记",c.jsx("br",{}),"• 确保您的请求始终路由到稳定可用的服务",c.jsx("br",{}),"• 规则状态列会实时显示每个规则的可用性状态",c.jsx("br",{}),"• 如不需要此功能,可在",c.jsx("strong",{children:"设置"}),'页面关闭"启用智能故障切换"选项']})]})]})]}),c.jsxs("div",{className:"card",style:{marginTop:"20px"},children:[c.jsx("div",{className:"toolbar",children:c.jsx("h3",{children:"📝 配置文件自动管理"})}),c.jsxs("div",{style:{padding:"20px",lineHeight:"1.8"},children:[c.jsxs("div",{style:{background:"var(--bg-info-blue)",padding:"15px",borderRadius:"8px",marginBottom:"15px",borderLeft:"4px solid var(--border-info-blue)"},children:[c.jsx("strong",{children:"💡 工作原理"}),c.jsx("p",{style:{marginTop:"8px",marginBottom:"0"},children:"激活路由时,系统会自动修改编程工具的配置文件,使其通过本代理服务器访问AI服务。 停用路由时,系统会自动恢复原始配置。"})]}),c.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"15px"},children:[c.jsxs("div",{style:{background:"var(--bg-info-green)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-green)"},children:[c.jsx("strong",{children:"✓ 激活路由"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[c.jsx("li",{children:"首次激活:自动备份并覆盖配置文件"}),c.jsx("li",{children:"再次激活:仅切换路由,不重复覆盖"})]})]}),c.jsxs("div",{style:{background:"var(--bg-info-orange)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-orange)"},children:[c.jsx("strong",{children:"○ 停用路由"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[c.jsx("li",{children:"自动恢复原始配置文件"}),c.jsx("li",{children:"删除备份文件"})]})]})]}),c.jsxs("div",{style:{marginTop:"15px",padding:"12px 15px",background:"var(--bg-info-yellow)",borderRadius:"8px",borderLeft:"4px solid var(--border-info-yellow)"},children:[c.jsx("strong",{children:"⚠️ 重要提示"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[c.jsxs("li",{children:["激活(首次)/停用路由后,",c.jsx("strong",{children:"必须重启对应的编程工具"}),"才能使配置生效"]}),c.jsx("li",{children:"操作前建议关闭编程工具,避免配置冲突"})]})]}),c.jsxs("details",{style:{marginTop:"15px",cursor:"pointer"},children:[c.jsx("summary",{style:{fontWeight:"bold",color:"#666"},children:"📂 配置文件位置(点击展开)"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",color:"#666"},children:[c.jsxs("li",{children:[c.jsx("strong",{children:"Claude Code:"})," ~/.claude/settings.json, ~/.claude.json"]}),c.jsxs("li",{children:[c.jsx("strong",{children:"Codex:"})," ~/.codex/config.toml, ~/.codex/auth.json"]})]})]})]})]}),v&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>y(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:b?"编辑路由":"新建路由"})}),c.jsxs("form",{onSubmit:Up,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"路由名称"}),c.jsx("input",{type:"text",name:"name",defaultValue:b?b.name:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"描述"}),c.jsx("textarea",{name:"description",rows:3,defaultValue:b?b.description:""})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"客户端工具"}),c.jsx("select",{name:"targetType",defaultValue:b?b.targetType:"claude-code",required:!0,children:Th.map(_=>c.jsx("option",{value:_.value,children:_.label},_.value))})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>y(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),x&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>g(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:S?"编辑规则":"新建规则"})}),c.jsxs("form",{onSubmit:Hp,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"对象请求类型"}),c.jsx("select",{name:"contentType",value:$,required:!0,onChange:_=>{K(_.target.value)},children:R0().map(_=>c.jsx("option",{value:_.value,children:_.label},_.value))})]}),$==="model-mapping"&&c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["被顶替模型 ",c.jsx("small",{children:"(可在日志中找出想要顶替的模型名)"})]}),c.jsx("input",{type:"text",value:I,onChange:_=>q(_.target.value),placeholder:"例如:gpt-4"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商"}),c.jsxs("select",{value:k,onChange:_=>C(_.target.value),required:!0,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择供应商"}),o.map(_=>c.jsx("option",{value:_.id,children:_.name},_.id))]})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商API服务"}),c.jsxs("select",{value:O,onChange:_=>{const ne=_.target.value;N(ne),T("");const ge=s.find(be=>be.id===ne);ge&&(ge.enableTokenLimit&&ge.tokenLimit?(R(ge.tokenLimit),G(ge.tokenResetInterval),E(ge.tokenResetBaseTime?new Date(ge.tokenResetBaseTime):void 0),bt(ge.tokenLimit),_e(!0),Tn(!0)):(bt(void 0),_e(!1),Tn(!1)),ge.enableRequestLimit&&ge.requestCountLimit?(Y(ge.requestCountLimit),F(ge.requestResetInterval),re(ge.requestResetBaseTime?new Date(ge.requestResetBaseTime):void 0),yn(ge.requestCountLimit),Ae(!0),Z(!0)):(yn(void 0),Ae(!1),Z(!1)))},required:!0,disabled:!k,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择API服务"}),d.map(_=>c.jsx("option",{value:_.id,children:_.name},_.id))]})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商模型"}),c.jsxs("select",{value:A,onChange:_=>T(_.target.value),disabled:!O,children:[c.jsx("option",{value:"",children:"透传模型名"}),($0=(z0=s.find(_=>_.id===O))==null?void 0:z0.supportedModels)==null?void 0:$0.map(_=>c.jsx("option",{value:_,children:_},_))]})]}),c.jsx("div",{className:"form-group",children:c.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:de?"not-allowed":"pointer"},children:[c.jsx("input",{type:"checkbox",checked:Pi,onChange:_=>Tn(_.target.checked),disabled:de,style:{marginRight:"8px",cursor:de?"not-allowed":"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用Tokens超量限制"}),de&&c.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),de&&c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>_e(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),Pi&&!de&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Tokens超量(单位:k)"}),c.jsx("input",{type:"number",value:M||"",onChange:_=>{const ne=_.target.value?parseInt(_.target.value):void 0;if(ne!==void 0&&tt!==void 0&&ne>tt){me.warning(`Token超量值不能超过API服务的限制 (${tt}k)`);return}R(ne),de&&ne!==tt&&_e(!1)},min:"0",max:tt,placeholder:tt?`最大 ${tt}k`:"不限制",disabled:de}),tt&&c.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",tt,"k,当前值不能超过此限制"]}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当编程工具的请求tokens达到这个量时,在配置了其他规则的情况下,本条规则将失效,从而保护你的余额。例如:输入100表示100k即100,000个tokens"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Tokens超量自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:P||"",onChange:_=>{G(_.target.value?parseInt(_.target.value):void 0),de&&_e(!1)},min:"1",placeholder:"不自动重置",disabled:de}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置token计数。例如设置5小时,则每5小时重置一次"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Token下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:ee?Z1(ee):"",onChange:_=>{_.target.value?E(new Date(_.target.value)):E(void 0),de&&_e(!1)},disabled:!P||de,className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"Tokens超量自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]}),c.jsx("div",{className:"form-group",children:c.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:Ne?"not-allowed":"pointer"},children:[c.jsx("input",{type:"checkbox",checked:V,onChange:_=>Z(_.target.checked),disabled:Ne,style:{marginRight:"8px",cursor:Ne?"not-allowed":"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用请求次数超量限制"}),Ne&&c.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),Ne&&c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>Ae(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),V&&!Ne&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"请求次数超量"}),c.jsx("input",{type:"number",value:H||"",onChange:_=>{const ne=_.target.value?parseInt(_.target.value):void 0;if(ne!==void 0&&wt!==void 0&&ne>wt){me.warning(`请求次数超量值不能超过API服务的限制 (${wt})`);return}Y(ne),Ne&&ne!==wt&&Ae(!1)},min:"0",max:wt,placeholder:wt?`最大 ${wt}`:"不限制",disabled:Ne}),wt&&c.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",wt,",当前值不能超过此限制"]}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当请求次数达到这个量时,在配置了其他规则的情况下,本条规则将失效"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"请求次数自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:ue||"",onChange:_=>{F(_.target.value?parseInt(_.target.value):void 0),Ne&&Ae(!1)},min:"1",placeholder:"不自动重置",disabled:Ne}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置请求次数计数。例如设置24小时,则每24小时重置一次"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:J?Z1(J):"",onChange:_=>{_.target.value?re(new Date(_.target.value)):re(void 0),Ne&&Ae(!1)},disabled:!ue||Ne,className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"请求次数自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"超时时间(秒)"}),c.jsx("input",{type:"number",value:ae||"",onChange:_=>xe(_.target.value?parseInt(_.target.value):void 0),min:"1",placeholder:"默认300秒"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置此规则的API请求超时时间。不设置则使用默认值300秒(5分钟)"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"排序(值越大优先级越高)"}),c.jsx("input",{type:"number",value:z,onChange:_=>D(parseInt(_.target.value)||0),min:"0",max:"1000"})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>g(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]})]})}var oE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(zo,function(){var n=1e3,r=6e4,i=36e5,a="millisecond",o="second",l="minute",s="hour",u="day",d="week",f="month",p="quarter",h="year",v="date",y="Invalid Date",x=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,g=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,b={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(z){var D=["th","st","nd","rd"],$=z%100;return"["+z+(D[($-20)%10]||D[$]||D[0])+"]"}},w=function(z,D,$){var K=String(z);return!K||K.length>=D?z:""+Array(D+1-K.length).join($)+z},S={s:w,z:function(z){var D=-z.utcOffset(),$=Math.abs(D),K=Math.floor($/60),M=$%60;return(D<=0?"+":"-")+w(K,2,"0")+":"+w(M,2,"0")},m:function z(D,$){if(D.date()<$.date())return-z($,D);var K=12*($.year()-D.year())+($.month()-D.month()),M=D.clone().add(K,f),R=$-M<0,P=D.clone().add(K+(R?-1:1),f);return+(-(K+($-M)/(R?M-P:P-M))||0)},a:function(z){return z<0?Math.ceil(z)||0:Math.floor(z)},p:function(z){return{M:f,y:h,w:d,d:u,D:v,h:s,m:l,s:o,ms:a,Q:p}[z]||String(z||"").toLowerCase().replace(/s$/,"")},u:function(z){return z===void 0}},j="en",k={};k[j]=b;var C="$isDayjsObject",O=function(z){return z instanceof I||!(!z||!z[C])},N=function z(D,$,K){var M;if(!D)return j;if(typeof D=="string"){var R=D.toLowerCase();k[R]&&(M=R),$&&(k[R]=$,M=R);var P=D.split("-");if(!M&&P.length>1)return z(P[0])}else{var G=D.name;k[G]=D,M=G}return!K&&M&&(j=M),M||!K&&j},A=function(z,D){if(O(z))return z.clone();var $=typeof D=="object"?D:{};return $.date=z,$.args=arguments,new I($)},T=S;T.l=N,T.i=O,T.w=function(z,D){return A(z,{locale:D.$L,utc:D.$u,x:D.$x,$offset:D.$offset})};var I=function(){function z($){this.$L=N($.locale,null,!0),this.parse($),this.$x=this.$x||$.x||{},this[C]=!0}var D=z.prototype;return D.parse=function($){this.$d=function(K){var M=K.date,R=K.utc;if(M===null)return new Date(NaN);if(T.u(M))return new Date;if(M instanceof Date)return new Date(M);if(typeof M=="string"&&!/Z$/i.test(M)){var P=M.match(x);if(P){var G=P[2]-1||0,ee=(P[7]||"0").substring(0,3);return R?new Date(Date.UTC(P[1],G,P[3]||1,P[4]||0,P[5]||0,P[6]||0,ee)):new Date(P[1],G,P[3]||1,P[4]||0,P[5]||0,P[6]||0,ee)}}return new Date(M)}($),this.init()},D.init=function(){var $=this.$d;this.$y=$.getFullYear(),this.$M=$.getMonth(),this.$D=$.getDate(),this.$W=$.getDay(),this.$H=$.getHours(),this.$m=$.getMinutes(),this.$s=$.getSeconds(),this.$ms=$.getMilliseconds()},D.$utils=function(){return T},D.isValid=function(){return this.$d.toString()!==y},D.isSame=function($,K){var M=A($);return this.startOf(K)<=M&&M<=this.endOf(K)},D.isAfter=function($,K){return A($)<this.startOf(K)},D.isBefore=function($,K){return this.endOf(K)<A($)},D.$g=function($,K,M){return T.u($)?this[K]:this.set(M,$)},D.unix=function(){return Math.floor(this.valueOf()/1e3)},D.valueOf=function(){return this.$d.getTime()},D.startOf=function($,K){var M=this,R=!!T.u(K)||K,P=T.p($),G=function(F,J){var re=T.w(M.$u?Date.UTC(M.$y,J,F):new Date(M.$y,J,F),M);return R?re:re.endOf(u)},ee=function(F,J){return T.w(M.toDate()[F].apply(M.toDate("s"),(R?[0,0,0,0]:[23,59,59,999]).slice(J)),M)},E=this.$W,ae=this.$M,xe=this.$D,H="set"+(this.$u?"UTC":"");switch(P){case h:return R?G(1,0):G(31,11);case f:return R?G(1,ae):G(0,ae+1);case d:var Y=this.$locale().weekStart||0,ue=(E<Y?E+7:E)-Y;return G(R?xe-ue:xe+(6-ue),ae);case u:case v:return ee(H+"Hours",0);case s:return ee(H+"Minutes",1);case l:return ee(H+"Seconds",2);case o:return ee(H+"Milliseconds",3);default:return this.clone()}},D.endOf=function($){return this.startOf($,!1)},D.$set=function($,K){var M,R=T.p($),P="set"+(this.$u?"UTC":""),G=(M={},M[u]=P+"Date",M[v]=P+"Date",M[f]=P+"Month",M[h]=P+"FullYear",M[s]=P+"Hours",M[l]=P+"Minutes",M[o]=P+"Seconds",M[a]=P+"Milliseconds",M)[R],ee=R===u?this.$D+(K-this.$W):K;if(R===f||R===h){var E=this.clone().set(v,1);E.$d[G](ee),E.init(),this.$d=E.set(v,Math.min(this.$D,E.daysInMonth())).$d}else G&&this.$d[G](ee);return this.init(),this},D.set=function($,K){return this.clone().$set($,K)},D.get=function($){return this[T.p($)]()},D.add=function($,K){var M,R=this;$=Number($);var P=T.p(K),G=function(ae){var xe=A(R);return T.w(xe.date(xe.date()+Math.round(ae*$)),R)};if(P===f)return this.set(f,this.$M+$);if(P===h)return this.set(h,this.$y+$);if(P===u)return G(1);if(P===d)return G(7);var ee=(M={},M[l]=r,M[s]=i,M[o]=n,M)[P]||1,E=this.$d.getTime()+$*ee;return T.w(E,this)},D.subtract=function($,K){return this.add(-1*$,K)},D.format=function($){var K=this,M=this.$locale();if(!this.isValid())return M.invalidDate||y;var R=$||"YYYY-MM-DDTHH:mm:ssZ",P=T.z(this),G=this.$H,ee=this.$m,E=this.$M,ae=M.weekdays,xe=M.months,H=M.meridiem,Y=function(J,re,B,ve){return J&&(J[re]||J(K,R))||B[re].slice(0,ve)},ue=function(J){return T.s(G%12||12,J,"0")},F=H||function(J,re,B){var ve=J<12?"AM":"PM";return B?ve.toLowerCase():ve};return R.replace(g,function(J,re){return re||function(B){switch(B){case"YY":return String(K.$y).slice(-2);case"YYYY":return T.s(K.$y,4,"0");case"M":return E+1;case"MM":return T.s(E+1,2,"0");case"MMM":return Y(M.monthsShort,E,xe,3);case"MMMM":return Y(xe,E);case"D":return K.$D;case"DD":return T.s(K.$D,2,"0");case"d":return String(K.$W);case"dd":return Y(M.weekdaysMin,K.$W,ae,2);case"ddd":return Y(M.weekdaysShort,K.$W,ae,3);case"dddd":return ae[K.$W];case"H":return String(G);case"HH":return T.s(G,2,"0");case"h":return ue(1);case"hh":return ue(2);case"a":return F(G,ee,!0);case"A":return F(G,ee,!1);case"m":return String(ee);case"mm":return T.s(ee,2,"0");case"s":return String(K.$s);case"ss":return T.s(K.$s,2,"0");case"SSS":return T.s(K.$ms,3,"0");case"Z":return P}return null}(J)||P.replace(":","")})},D.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},D.diff=function($,K,M){var R,P=this,G=T.p(K),ee=A($),E=(ee.utcOffset()-this.utcOffset())*r,ae=this-ee,xe=function(){return T.m(P,ee)};switch(G){case h:R=xe()/12;break;case f:R=xe();break;case p:R=xe()/3;break;case d:R=(ae-E)/6048e5;break;case u:R=(ae-E)/864e5;break;case s:R=ae/i;break;case l:R=ae/r;break;case o:R=ae/n;break;default:R=ae}return M?R:T.a(R)},D.daysInMonth=function(){return this.endOf(f).$D},D.$locale=function(){return k[this.$L]},D.locale=function($,K){if(!$)return this.$L;var M=this.clone(),R=N($,K,!0);return R&&(M.$L=R),M},D.clone=function(){return T.w(this.$d,this)},D.toDate=function(){return new Date(this.valueOf())},D.toJSON=function(){return this.isValid()?this.toISOString():null},D.toISOString=function(){return this.$d.toISOString()},D.toString=function(){return this.$d.toUTCString()},z}(),q=I.prototype;return A.prototype=q,[["$ms",a],["$s",o],["$m",l],["$H",s],["$W",u],["$M",f],["$y",h],["$D",v]].forEach(function(z){q[z[1]]=function(D){return this.$g(D,z[0],z[1])}}),A.extend=function(z,D){return z.$i||(z(D,I,A),z.$i=!0),A},A.locale=N,A.isDayjs=O,A.unix=function(z){return A(1e3*z)},A.en=k[j],A.Ls=k,A.p={},A})})(oE);var E3=oE.exports;const tn=Un(E3);var lE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(zo,function(){return function(n,r,i){n=n||{};var a=r.prototype,o={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function l(u,d,f,p){return a.fromToBase(u,d,f,p)}i.en.relativeTime=o,a.fromToBase=function(u,d,f,p,h){for(var v,y,x,g=f.$locale().relativeTime||o,b=n.thresholds||[{l:"s",r:44,d:"second"},{l:"m",r:89},{l:"mm",r:44,d:"minute"},{l:"h",r:89},{l:"hh",r:21,d:"hour"},{l:"d",r:35},{l:"dd",r:25,d:"day"},{l:"M",r:45},{l:"MM",r:10,d:"month"},{l:"y",r:17},{l:"yy",d:"year"}],w=b.length,S=0;S<w;S+=1){var j=b[S];j.d&&(v=p?i(u).diff(f,j.d,!0):f.diff(u,j.d,!0));var k=(n.rounding||Math.round)(Math.abs(v));if(x=v>0,k<=j.r||!j.r){k<=1&&S>0&&(j=b[S-1]);var C=g[j.l];h&&(k=h(""+k)),y=typeof C=="string"?C.replace("%d",k):C(k,d,j.l,x);break}}if(d)return y;var O=x?g.future:g.past;return typeof O=="function"?O(y):O.replace("%s",y)},a.to=function(u,d){return l(u,d,this,!0)},a.from=function(u,d){return l(u,d,this)};var s=function(u){return u.$u?i.utc():i()};a.toNow=function(u){return this.to(s(this),u)},a.fromNow=function(u){return this.from(s(this),u)}}})})(lE);var A3=lE.exports;const T3=Un(A3),I3=["authorization","x-api-key","api-key","apikey","x-auth-token","auth-token","secret","password","api_secret","jwt","csrf_token","xsrf_token","auth_token","session_token","private_key","client_secret"],_3=e=>{const t=e.toLowerCase();return!!(I3.some(n=>t===n)||t.startsWith("api_")&&(t.endsWith("_key")||t.endsWith("_secret"))||(t.endsWith("_token")||t.endsWith("_key")||t.endsWith("_secret"))&&!["max_tokens","input_tokens","output_tokens","completion_tokens","prompt_tokens","cachereadinputtokens","totaltokens"].some(r=>t.replace(/_/g,"").includes(r.replace(/_/g,""))))},N3=e=>!e||e.length<=8?"***":`${e.slice(0,4)}${"*".repeat(Math.min(e.length-8,20))}${e.slice(-4)}`,pv=e=>{if(e==null)return e;if(Array.isArray(e))return e.map(t=>pv(t));if(typeof e=="object"){const t={};for(const[n,r]of Object.entries(e))_3(n)?t[n]=typeof r=="string"?N3(r):"***":typeof r=="object"?t[n]=pv(r):t[n]=r;return t}return e},cr=({data:e,title:t,collapsed:n=!1})=>{const[r,i]=m.useState(!n),[a,o]=m.useState(!1),l=d=>{try{let f;typeof d=="string"?f=JSON.parse(d):f=d;const p=pv(f);return JSON.stringify(p,null,2)}catch{return typeof d=="string"?d:String(d)}},s=()=>{const d=l(e);navigator.clipboard.writeText(d).then(()=>{o(!0),setTimeout(()=>o(!1),2e3)}).catch(f=>{console.error("Failed to copy JSON:",f)})},u=l(e);return c.jsxs("div",{className:"json-viewer",children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"8px"},children:[t&&c.jsx("h4",{style:{margin:0,fontSize:"14px",color:"var(--text-primary)"},children:t}),c.jsxs("div",{style:{display:"flex",gap:"8px"},children:[c.jsx("button",{onClick:()=>i(!r),className:"btn btn-sm btn-secondary",style:{fontSize:"12px",padding:"2px 8px"},children:r?"折叠":"展开"}),c.jsx("button",{onClick:s,className:"btn btn-sm btn-primary",style:{fontSize:"12px",padding:"2px 8px"},children:a?"已复制":"复制"})]})]}),r&&c.jsx("pre",{style:{background:"var(--bg-code)",border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"12px",overflowX:"auto",fontSize:"12px",lineHeight:"1.4",color:"var(--text-primary)",maxHeight:"400px",overflowY:"auto",margin:0},children:c.jsx("code",{children:u})})]})},_h=({currentPage:e,totalItems:t,pageSize:n,onPageChange:r,onPageSizeChange:i,pageSizeOptions:a=[10,20,50,100]})=>{const o=Math.max(1,Math.ceil(t/n)),l=e===1,s=e>=o,u=()=>{l||r(1)},d=()=>{l||r(e-1)},f=()=>{s||r(e+1)},p=()=>{s||r(o)},h=v=>{const y=parseInt(v.target.value,10);i(y)};return c.jsxs("div",{className:"pagination",children:[c.jsxs("div",{className:"pagination-info",children:["共 ",t," 条"]}),c.jsxs("div",{className:"pagination-controls",children:[c.jsx("button",{className:"pagination-btn",onClick:u,disabled:l,children:"首页"}),c.jsx("button",{className:"pagination-btn",onClick:d,disabled:l,children:"上一页"}),c.jsxs("span",{className:"pagination-info",children:["第 ",e," / ",o," 页"]}),c.jsx("button",{className:"pagination-btn",onClick:f,disabled:s,children:"下一页"}),c.jsx("button",{className:"pagination-btn",onClick:p,disabled:s,children:"尾页"})]}),c.jsx("div",{className:"pagination-size",children:c.jsxs("label",{children:["每页显示",c.jsx("select",{className:"pagination-select",value:n,onChange:h,children:a.map(v=>c.jsx("option",{value:v,children:v},v))}),"条"]})})]})};tn.extend(T3);function M3(e){const t=[];let n={dataLines:[],rawLines:[]};for(const r of e){const i=r.split(`
|
|
357
|
+
请刷新页面后重试。`)}}catch(be){console.error("停用路由失败:",be),me.error(be.message)}finally{St(null)}},Up=async _=>{_.preventDefault();const ne=new FormData(_.currentTarget),ge={name:ne.get("name"),description:ne.get("description"),targetType:ne.get("targetType"),isActive:!1};b?await te.updateRoute(b.id,ge):await te.createRoute(ge),y(!1),Oe()},Wp=async _=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteRoute(_),Oe(),p&&p.id===_&&(h(null),a([])),me.success("路由已删除"))},Hp=async _=>{if(_.preventDefault(),M!==void 0&&tt!==void 0&&M>tt){me.warning(`Token超量值 (${M}k) 不能超过API服务的限制 (${tt}k)`);return}if(H!==void 0&&wt!==void 0&&H>wt){me.warning(`请求次数超量值 (${H}) 不能超过API服务的限制 (${wt})`);return}const ne=new FormData(_.currentTarget),ge={routeId:p.id,contentType:ne.get("contentType"),targetServiceId:O,targetModel:A||void 0,replacedModel:I||void 0,sortOrder:z,timeout:ae?ae*1e3:void 0,tokenLimit:M||void 0,resetInterval:P,tokenResetBaseTime:ee?ee.getTime():void 0,requestCountLimit:H,requestResetInterval:ue,requestResetBaseTime:J?J.getTime():void 0};S?await te.updateRule(S.id,ge):await te.createRule(ge),g(!1),p&&ot(p.id)},U=async _=>{await e({message:"确定要删除此路由吗?",title:"确认删除",type:"danger",confirmText:"删除",cancelText:"取消"})&&(await te.deleteRule(_),p&&ot(p.id),me.success("规则已删除"))},Te=async _=>{try{await te.clearRuleBlacklist(_),p&&ot(p.id),me.success("已恢复")}catch(ne){me.error("恢复失败: "+ne.message)}},Pt=async _=>{try{const ne=await te.toggleRuleDisable(_);p&&ot(p.id),me.success(ne.isDisabled?"规则已屏蔽":"规则已启用")}catch(ne){me.error("操作失败: "+ne.message)}},R0=()=>Q1,qN=_=>{j(_),K(_.contentType);const ne=s.find(ge=>ge.id===_.targetServiceId);ne&&(C(ne.vendorId),f(s.filter(ge=>ge.vendorId===ne.vendorId)),setTimeout(()=>{if(N(ne.id),T(_.targetModel||""),q(_.replacedModel||""),D(_.sortOrder||0),xe(_.timeout?_.timeout/1e3:void 0),R(_.tokenLimit||void 0),G(_.resetInterval),E(_.tokenResetBaseTime?new Date(_.tokenResetBaseTime):void 0),Y(_.requestCountLimit),F(_.requestResetInterval),re(_.requestResetBaseTime?new Date(_.requestResetBaseTime):void 0),ne.enableTokenLimit&&ne.tokenLimit){bt(ne.tokenLimit);const ge=_.tokenLimit===ne.tokenLimit&&_.resetInterval===(ne.tokenResetInterval||void 0)&&_.tokenLimit!==null&&_.resetInterval!==null;_e(ge)}else bt(void 0),_e(!1);if(ne.enableRequestLimit&&ne.requestCountLimit){yn(ne.requestCountLimit);const ge=_.requestCountLimit===ne.requestCountLimit&&_.requestResetInterval===(ne.requestResetInterval||void 0)&&_.requestCountLimit!==null&&_.requestResetInterval!==null;Ae(ge)}else yn(void 0),Ae(!1);Tn(!!_.tokenLimit),Z(!!_.requestCountLimit)},0)),g(!0)},YN=_=>{var Me;const ne=sr[_.id],ge=[],be=t[_.id];if((be==null?void 0:be.status)==="in_use")return{status:"in_use",label:"使用中",reason:"正在处理请求"};if(ne!=null&&ne.isBlacklisted){const Fe=ne.blacklistEntry;(Fe==null?void 0:Fe.errorType)==="timeout"?ge.push("请求超时"):Fe!=null&&Fe.lastStatusCode&&ge.push(`HTTP ${Fe.lastStatusCode}错误`)}const Ve=(be==null?void 0:be.totalTokensUsed)!==void 0?be.totalTokensUsed:_.totalTokensUsed;_.tokenLimit&&Ve!==void 0&&Ve>=_.tokenLimit*1e3&&ge.push("Token超限");const Qt=(be==null?void 0:be.totalRequestsUsed)!==void 0?be.totalRequestsUsed:_.totalRequestsUsed;if(_.requestCountLimit&&Qt!==void 0&&Qt>=_.requestCountLimit&&ge.push("次数超限"),ge.length>0)return{status:"error",label:ne!=null&&ne.isBlacklisted?((Me=ne.blacklistEntry)==null?void 0:Me.errorType)==="timeout"?"超时":"服务错误":ge[0],reason:ge.join(", ")};const pa=[];if(_.tokenLimit&&Ve!==void 0){const Fe=Ve/(_.tokenLimit*1e3)*100;Fe>=80&&pa.push(`Token ${Fe.toFixed(0)}%`)}if(_.requestCountLimit&&Qt!==void 0){const Fe=Qt/_.requestCountLimit*100;Fe>=80&&pa.push(`次数 ${Fe.toFixed(0)}%`)}return pa.length>0?{status:"warning",label:"接近限制",reason:pa.join(", ")}:{status:"success",label:"正常",reason:""}},GN=()=>{j(null),K("default"),C(""),N(""),T(""),q(""),D(0),xe(void 0),R(void 0),G(void 0),E(void 0),Y(void 0),F(void 0),re(void 0),_e(!1),Ae(!1),bt(void 0),yn(void 0),Tn(!1),Z(!1),g(!0)};return c.jsxs("div",{className:"routes-page",children:[c.jsxs("div",{className:"page-header",children:[c.jsx("h1",{children:"路由管理"}),c.jsx("p",{children:"管理API路由和路由配置"})]}),c.jsxs("div",{style:{display:"flex",gap:"20px"},children:[c.jsxs("div",{className:"card",style:{flex:"0 0 25%",minWidth:300},children:[c.jsxs("div",{className:"toolbar",children:[c.jsx("h3",{children:"路由"}),c.jsx("button",{className:"btn btn-primary",onClick:()=>y(!0),children:"新建"})]}),n.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无路由"})}):c.jsx("div",{style:{marginTop:"10px"},children:n.map(_=>{var ne,ge;return c.jsx("div",{ref:be=>{be?fe.current.set(_.id,be):fe.current.delete(_.id)},onClick:()=>h(_),style:{padding:"12px",marginBottom:"8px",backgroundColor:p&&p.id===_.id?"var(--bg-route-item-selected)":"var(--bg-route-item)",borderRadius:"8px",cursor:"pointer",border:"1px solid var(--border-primary)",position:"relative"},children:c.jsxs("div",{children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[c.jsx("div",{style:{fontWeight:500},children:_.name}),_.isActive&&c.jsxs("span",{className:`badge ${_.targetType==="claude-code"?"badge-claude-code":"badge-codex"}`,style:{position:"absolute",top:-16,right:-8},children:[(ne=Th.find(be=>be.value===_.targetType))==null?void 0:ne.label," 已激活"]})]}),c.jsxs("div",{style:{fontSize:"12px",color:"var(--text-route-muted)",marginTop:"2px"},children:["客户端工具: ",(ge=Th.find(be=>be.value===_.targetType))==null?void 0:ge.label]}),c.jsxs("div",{className:"action-buttons",style:{marginTop:"8px"},children:[_.isActive?c.jsx("button",{className:"btn btn-warning",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),Fp(_.id)},disabled:Pe!==null,children:Pe===_.id?"处理中...":"停用"}):c.jsx("button",{className:"btn btn-success",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),Ci(_.id)},disabled:Pe!==null,children:Pe===_.id?"处理中...":"激活"}),c.jsx("button",{className:"btn btn-secondary",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),w(_),y(!0)},children:"编辑"}),c.jsx("button",{className:"btn btn-danger",style:{padding:"4px 8px",fontSize:"12px"},onClick:be=>{be.stopPropagation(),Wp(_.id)},disabled:_.isActive,children:"删除"})]})]})},_.id)})})]}),c.jsxs("div",{className:"card",style:{flex:1},children:[c.jsxs("div",{className:"toolbar",children:[c.jsx("h3",{children:"规则列表"}),p&&c.jsx("button",{className:"btn btn-primary",onClick:GN,children:"新建规则"})]}),p?i.length===0?c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"暂无路由"})}):c.jsxs("table",{children:[c.jsx("thead",{children:c.jsxs("tr",{children:[c.jsx("th",{children:"优先级"}),c.jsx("th",{children:"类型"}),c.jsx("th",{children:"API服务"}),c.jsx("th",{children:"状态"}),c.jsx("th",{children:"用量情况"}),c.jsx("th",{children:"操作"})]})}),c.jsx("tbody",{children:i.map(_=>{var Ve,Qt,pa;const ne=s.find(Me=>Me.id===_.targetServiceId),ge=o.find(Me=>Me.id===(ne==null?void 0:ne.vendorId)),be=(Ve=Q1.find(Me=>Me.value===_.contentType))==null?void 0:Ve.label;return c.jsxs("tr",{children:[c.jsx("td",{children:_.sortOrder||0}),c.jsx("td",{children:c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[c.jsx("span",{children:be}),_.contentType==="model-mapping"&&_.replacedModel&&c.jsxs("div",{style:{position:"relative",display:"inline-block"},onMouseEnter:()=>ve(_.id),onMouseLeave:()=>ve(null),children:[c.jsx("span",{style:{cursor:"help",fontSize:"14px",color:"var(--text-info)",fontWeight:"bold"},children:"ⓘ"}),B===_.id&&c.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:["被顶替的模型是: ",_.replacedModel,c.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]})}),c.jsx("td",{children:c.jsxs("div",{style:{fontSize:"0.6em"},children:[c.jsxs("div",{children:["供应商:",ge?ge.name:"Unknown"]}),c.jsxs("div",{children:["服务:",ne?ne.name:"Unknown"]}),c.jsxs("div",{children:["模型:",_.targetModel||"透传模型"]})]})}),c.jsx("td",{style:{whiteSpace:"nowrap"},children:(()=>{var B0,F0;const Me=YN(_),Fe=sr[_.id],XN=(Fe==null?void 0:Fe.isBlacklisted)&&!((B0=Me.reason)!=null&&B0.includes("Token超限"))&&!((F0=Me.reason)!=null&&F0.includes("次数超限"));return _.isDisabled?c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[c.jsx("span",{style:{color:"#6c757d",fontWeight:"bold",fontSize:"14px"},children:"⊘"}),c.jsx("span",{style:{fontSize:"13px",color:"#6c757d",fontWeight:"bold"},children:"已屏蔽"})]}):c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px",flexWrap:"wrap"},children:[c.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"6px"},children:[Me.status==="success"&&c.jsx("span",{style:{color:"#28a745",fontWeight:"bold",fontSize:"14px"},children:"✓"}),Me.status==="warning"&&c.jsx("span",{style:{color:"#ffc107",fontWeight:"bold",fontSize:"14px"},children:"⚠"}),Me.status==="error"&&c.jsx("span",{style:{color:"#dc3545",fontWeight:"bold",fontSize:"14px"},children:"✗"}),Me.status==="in_use"&&c.jsx(c.Fragment,{children:c.jsx("span",{style:{color:"#007bff",fontWeight:"bold",fontSize:"14px",animation:"pulse 1.5s ease-in-out infinite"},children:"●"})}),c.jsx("span",{style:{fontSize:"13px",color:Me.status==="success"?"#28a745":Me.status==="warning"?"#ffc107":Me.status==="in_use"?"#007bff":"#dc3545",fontWeight:Me.status!=="success"?"bold":"normal"},children:Me.label}),Me.reason&&c.jsxs("div",{style:{position:"relative",display:"inline-block",cursor:"help"},onMouseEnter:()=>ve(_.id+"-status"),onMouseLeave:()=>ve(null),children:[c.jsx("span",{style:{fontSize:"12px",color:"#999",marginLeft:"4px"},children:" ⓘ"}),B===_.id+"-status"&&c.jsxs("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"calc(100% + 8px)",backgroundColor:"var(--bg-popover, #333)",color:"var(--text-popover, #fff)",padding:"6px 10px",borderRadius:"4px",fontSize:"12px",whiteSpace:"nowrap",zIndex:1e3,boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:[Me.reason,c.jsx("div",{style:{position:"absolute",left:"50%",transform:"translateX(-50%)",bottom:"-4px",width:"0",height:"0",borderLeft:"4px solid transparent",borderRight:"4px solid transparent",borderTop:"4px solid var(--bg-popover, #333)"}})]})]})]}),XN&&c.jsx("button",{className:"btn btn-info",style:{padding:"2px 8px",fontSize:"11px"},onClick:()=>Te(_.id),children:"恢复"})]})})()}),c.jsx("td",{children:c.jsxs("div",{style:{fontSize:"13px"},children:[c.jsxs("div",{style:{whiteSpace:"nowrap"},children:[c.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"Tokens:"}),_.tokenLimit?c.jsxs(c.Fragment,{children:[c.jsxs("span",{style:{color:(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalTokensUsed)??_.totalTokensUsed;return Me&&_.tokenLimit&&Me>=_.tokenLimit*1e3?"red":"inherit"})()},children:[(((((Qt=t[_.id])==null?void 0:Qt.totalTokensUsed)??_.totalTokensUsed)||0)/1e3).toFixed(1),"K/",_.tokenLimit.toFixed(0),"K"]}),(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalTokensUsed)??_.totalTokensUsed;return Me&&_.tokenLimit&&Me>=_.tokenLimit*1e3?c.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]}):c.jsx("span",{style:{color:"#999"},children:"不限制"})]}),c.jsxs("div",{style:{marginTop:"6px"},children:[c.jsx("span",{style:{fontWeight:"bold",fontSize:"12px"},children:"次数:"}),_.requestCountLimit?c.jsxs(c.Fragment,{children:[c.jsxs("span",{style:{color:(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalRequestsUsed)??_.totalRequestsUsed;return Me&&_.requestCountLimit&&Me>=_.requestCountLimit?"red":"inherit"})()},children:[(((pa=t[_.id])==null?void 0:pa.totalRequestsUsed)??_.totalRequestsUsed)||0,"/",_.requestCountLimit]}),(()=>{var Fe;const Me=((Fe=t[_.id])==null?void 0:Fe.totalRequestsUsed)??_.totalRequestsUsed;return Me&&_.requestCountLimit&&Me>=_.requestCountLimit?c.jsx("span",{style:{color:"red",marginLeft:"4px",fontWeight:"bold",fontSize:"11px"},children:"超限"}):null})()]}):c.jsx("span",{style:{color:"#999"},children:"不限制"})]})]})}),c.jsx("td",{children:c.jsxs("div",{className:"action-buttons",style:{justifyContent:"flex-end"},children:[c.jsx("button",{className:`btn ${_.isDisabled?"btn-success":"btn-warning"}`,onClick:()=>Pt(_.id),title:_.isDisabled?"启用规则":"临时屏蔽规则",children:_.isDisabled?"启用":"屏蔽"}),c.jsx("button",{className:"btn btn-secondary",onClick:()=>qN(_),children:"编辑"}),c.jsx("button",{className:"btn btn-danger",onClick:()=>U(_.id),children:"删除"})]})})]},_.id)})})]}):c.jsx("div",{className:"empty-state",children:c.jsx("p",{children:"请先选择一个路由"})}),p&&i.length>0&&c.jsxs("div",{style:{fontSize:"12px",color:"var(--text-info-box)",marginTop:"16px",padding:"12px",backgroundColor:"var(--bg-info-box)",borderRadius:"6px",border:"1px solid var(--border-info-box)",lineHeight:"1.6"},children:[c.jsx("strong",{children:"💡 智能故障切换机制"}),c.jsxs("div",{style:{marginTop:"6px"},children:["• 当同一请求类型配置多个规则时,系统会按排序优先使用第一个",c.jsx("br",{}),"• 如果某个服务报错(4xx/5xx)或请求超时,将自动切换到下一个可用服务",c.jsx("br",{}),"• 报错或超时的服务会被标记为不可用,有效期10分钟",c.jsx("br",{}),"• 10分钟后自动解除标记,如果再次报错或超时则重新标记",c.jsx("br",{}),"• 确保您的请求始终路由到稳定可用的服务",c.jsx("br",{}),"• 规则状态列会实时显示每个规则的可用性状态",c.jsx("br",{}),"• 如不需要此功能,可在",c.jsx("strong",{children:"设置"}),'页面关闭"启用智能故障切换"选项']})]})]})]}),c.jsxs("div",{className:"card",style:{marginTop:"20px"},children:[c.jsx("div",{className:"toolbar",children:c.jsx("h3",{children:"📝 配置文件自动管理"})}),c.jsxs("div",{style:{padding:"20px",lineHeight:"1.8"},children:[c.jsxs("div",{style:{background:"var(--bg-info-blue)",padding:"15px",borderRadius:"8px",marginBottom:"15px",borderLeft:"4px solid var(--border-info-blue)"},children:[c.jsx("strong",{children:"💡 工作原理"}),c.jsx("p",{style:{marginTop:"8px",marginBottom:"0"},children:"激活路由时,系统会自动修改编程工具的配置文件,使其通过本代理服务器访问AI服务。 停用路由时,系统会自动恢复原始配置。"})]}),c.jsxs("div",{style:{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"15px"},children:[c.jsxs("div",{style:{background:"var(--bg-info-green)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-green)"},children:[c.jsx("strong",{children:"✓ 激活路由"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[c.jsx("li",{children:"首次激活:自动备份并覆盖配置文件"}),c.jsx("li",{children:"再次激活:仅切换路由,不重复覆盖"})]})]}),c.jsxs("div",{style:{background:"var(--bg-info-orange)",padding:"15px",borderRadius:"8px",borderLeft:"4px solid var(--border-info-orange)"},children:[c.jsx("strong",{children:"○ 停用路由"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[c.jsx("li",{children:"自动恢复原始配置文件"}),c.jsx("li",{children:"删除备份文件"})]})]})]}),c.jsxs("div",{style:{marginTop:"15px",padding:"12px 15px",background:"var(--bg-info-yellow)",borderRadius:"8px",borderLeft:"4px solid var(--border-info-yellow)"},children:[c.jsx("strong",{children:"⚠️ 重要提示"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",marginBottom:"0"},children:[c.jsxs("li",{children:["激活(首次)/停用路由后,",c.jsx("strong",{children:"必须重启对应的编程工具"}),"才能使配置生效"]}),c.jsx("li",{children:"操作前建议关闭编程工具,避免配置冲突"})]})]}),c.jsxs("details",{style:{marginTop:"15px",cursor:"pointer"},children:[c.jsx("summary",{style:{fontWeight:"bold",color:"#666"},children:"📂 配置文件位置(点击展开)"}),c.jsxs("ul",{style:{marginTop:"8px",paddingLeft:"20px",color:"#666"},children:[c.jsxs("li",{children:[c.jsx("strong",{children:"Claude Code:"})," ~/.claude/settings.json, ~/.claude.json"]}),c.jsxs("li",{children:[c.jsx("strong",{children:"Codex:"})," ~/.codex/config.toml, ~/.codex/auth.json"]})]})]})]})]}),v&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>y(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:b?"编辑路由":"新建路由"})}),c.jsxs("form",{onSubmit:Up,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"路由名称"}),c.jsx("input",{type:"text",name:"name",defaultValue:b?b.name:"",required:!0})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"描述"}),c.jsx("textarea",{name:"description",rows:3,defaultValue:b?b.description:""})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"客户端工具"}),c.jsx("select",{name:"targetType",defaultValue:b?b.targetType:"claude-code",required:!0,children:Th.map(_=>c.jsx("option",{value:_.value,children:_.label},_.value))})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>y(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]}),x&&c.jsxs("div",{className:"modal-overlay",children:[c.jsx("button",{type:"button",className:"modal-close-btn",onClick:()=>g(!1),"aria-label":"关闭",children:"×"}),c.jsx("div",{className:"modal",children:c.jsxs("div",{className:"modal-container",children:[c.jsx("div",{className:"modal-header",children:c.jsx("h2",{children:S?"编辑规则":"新建规则"})}),c.jsxs("form",{onSubmit:Hp,children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"对象请求类型"}),c.jsx("select",{name:"contentType",value:$,required:!0,onChange:_=>{K(_.target.value)},children:R0().map(_=>c.jsx("option",{value:_.value,children:_.label},_.value))})]}),$==="model-mapping"&&c.jsxs("div",{className:"form-group",children:[c.jsxs("label",{children:["被顶替模型 ",c.jsx("small",{children:"(可在日志中找出想要顶替的模型名)"})]}),c.jsx("input",{type:"text",value:I,onChange:_=>q(_.target.value),placeholder:"例如:gpt-4"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商"}),c.jsxs("select",{value:k,onChange:_=>C(_.target.value),required:!0,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择供应商"}),o.map(_=>c.jsx("option",{value:_.id,children:_.name},_.id))]})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商API服务"}),c.jsxs("select",{value:O,onChange:_=>{const ne=_.target.value;N(ne),T("");const ge=s.find(be=>be.id===ne);ge&&(ge.enableTokenLimit&&ge.tokenLimit?(R(ge.tokenLimit),G(ge.tokenResetInterval),E(ge.tokenResetBaseTime?new Date(ge.tokenResetBaseTime):void 0),bt(ge.tokenLimit),_e(!0),Tn(!0)):(bt(void 0),_e(!1),Tn(!1)),ge.enableRequestLimit&&ge.requestCountLimit?(Y(ge.requestCountLimit),F(ge.requestResetInterval),re(ge.requestResetBaseTime?new Date(ge.requestResetBaseTime):void 0),yn(ge.requestCountLimit),Ae(!0),Z(!0)):(yn(void 0),Ae(!1),Z(!1)))},required:!0,disabled:!k,children:[c.jsx("option",{value:"",disabled:!0,children:"请选择API服务"}),d.map(_=>c.jsx("option",{value:_.id,children:_.name},_.id))]})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"供应商模型"}),c.jsxs("select",{value:A,onChange:_=>T(_.target.value),disabled:!O,children:[c.jsx("option",{value:"",children:"透传模型名"}),($0=(z0=s.find(_=>_.id===O))==null?void 0:z0.supportedModels)==null?void 0:$0.map(_=>c.jsx("option",{value:_,children:_},_))]})]}),c.jsx("div",{className:"form-group",children:c.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:de?"not-allowed":"pointer"},children:[c.jsx("input",{type:"checkbox",checked:Pi,onChange:_=>Tn(_.target.checked),disabled:de,style:{marginRight:"8px",cursor:de?"not-allowed":"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用Tokens超量限制"}),de&&c.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),de&&c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>_e(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),Pi&&!de&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Tokens超量(单位:k)"}),c.jsx("input",{type:"number",value:M||"",onChange:_=>{const ne=_.target.value?parseInt(_.target.value):void 0;if(ne!==void 0&&tt!==void 0&&ne>tt){me.warning(`Token超量值不能超过API服务的限制 (${tt}k)`);return}R(ne),de&&ne!==tt&&_e(!1)},min:"0",max:tt,placeholder:tt?`最大 ${tt}k`:"不限制",disabled:de}),tt&&c.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",tt,"k,当前值不能超过此限制"]}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当编程工具的请求tokens达到这个量时,在配置了其他规则的情况下,本条规则将失效,从而保护你的余额。例如:输入100表示100k即100,000个tokens"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Tokens超量自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:P||"",onChange:_=>{G(_.target.value?parseInt(_.target.value):void 0),de&&_e(!1)},min:"1",placeholder:"不自动重置",disabled:de}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置token计数。例如设置5小时,则每5小时重置一次"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"Token下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:ee?Z1(ee):"",onChange:_=>{_.target.value?E(new Date(_.target.value)):E(void 0),de&&_e(!1)},disabled:!P||de,className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"Tokens超量自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]}),c.jsx("div",{className:"form-group",children:c.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[c.jsxs("label",{style:{display:"flex",alignItems:"center",cursor:Ne?"not-allowed":"pointer"},children:[c.jsx("input",{type:"checkbox",checked:V,onChange:_=>Z(_.target.checked),disabled:Ne,style:{marginRight:"8px",cursor:Ne?"not-allowed":"pointer",width:"16px",height:"16px"}}),c.jsx("span",{children:"启用请求次数超量限制"}),Ne&&c.jsx("small",{style:{color:"#999",fontSize:"12px",marginLeft:"8px"},children:"(从API服务继承)"})]}),Ne&&c.jsx("button",{type:"button",className:"btn btn-sm btn-secondary",onClick:()=>Ae(!1),style:{padding:"4px 12px",fontSize:"12px"},children:"自定义限制"})]})}),V&&!Ne&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"请求次数超量"}),c.jsx("input",{type:"number",value:H||"",onChange:_=>{const ne=_.target.value?parseInt(_.target.value):void 0;if(ne!==void 0&&wt!==void 0&&ne>wt){me.warning(`请求次数超量值不能超过API服务的限制 (${wt})`);return}Y(ne),Ne&&ne!==wt&&Ae(!1)},min:"0",max:wt,placeholder:wt?`最大 ${wt}`:"不限制",disabled:Ne}),wt&&c.jsxs("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:["⚠️ API服务限制:最大 ",wt,",当前值不能超过此限制"]}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"当请求次数达到这个量时,在配置了其他规则的情况下,本条规则将失效"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"请求次数自动重置间隔(小时)"}),c.jsx("input",{type:"number",value:ue||"",onChange:_=>{F(_.target.value?parseInt(_.target.value):void 0),Ne&&Ae(!1)},min:"1",placeholder:"不自动重置",disabled:Ne}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置后,系统将每隔指定小时数自动重置请求次数计数。例如设置24小时,则每24小时重置一次"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"下一次重置时间基点"}),c.jsx("input",{type:"datetime-local",value:J?Z1(J):"",onChange:_=>{_.target.value?re(new Date(_.target.value)):re(void 0),Ne&&Ae(!1)},disabled:!ue||Ne,className:"datetime-picker-input"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:'配合"请求次数自动重置间隔"使用,设置下一次重置的精确时间点。例如,每月1日0点重置(间隔720小时),或每周一0点重置(间隔168小时)。设置后,系统会基于此时间点自动计算后续重置周期'})]})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"超时时间(秒)"}),c.jsx("input",{type:"number",value:ae||"",onChange:_=>xe(_.target.value?parseInt(_.target.value):void 0),min:"1",placeholder:"默认300秒"}),c.jsx("small",{style:{color:"#666",fontSize:"12px",marginTop:"4px",display:"block"},children:"设置此规则的API请求超时时间。不设置则使用默认值300秒(5分钟)"})]}),c.jsxs("div",{className:"form-group",children:[c.jsx("label",{children:"排序(值越大优先级越高)"}),c.jsx("input",{type:"number",value:z,onChange:_=>D(parseInt(_.target.value)||0),min:"0",max:"1000"})]}),c.jsxs("div",{className:"modal-footer",children:[c.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>g(!1),children:"取消"}),c.jsx("button",{type:"submit",className:"btn btn-primary",children:"保存"})]})]})]})})]})]})}var oE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(zo,function(){var n=1e3,r=6e4,i=36e5,a="millisecond",o="second",l="minute",s="hour",u="day",d="week",f="month",p="quarter",h="year",v="date",y="Invalid Date",x=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,g=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,b={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(z){var D=["th","st","nd","rd"],$=z%100;return"["+z+(D[($-20)%10]||D[$]||D[0])+"]"}},w=function(z,D,$){var K=String(z);return!K||K.length>=D?z:""+Array(D+1-K.length).join($)+z},S={s:w,z:function(z){var D=-z.utcOffset(),$=Math.abs(D),K=Math.floor($/60),M=$%60;return(D<=0?"+":"-")+w(K,2,"0")+":"+w(M,2,"0")},m:function z(D,$){if(D.date()<$.date())return-z($,D);var K=12*($.year()-D.year())+($.month()-D.month()),M=D.clone().add(K,f),R=$-M<0,P=D.clone().add(K+(R?-1:1),f);return+(-(K+($-M)/(R?M-P:P-M))||0)},a:function(z){return z<0?Math.ceil(z)||0:Math.floor(z)},p:function(z){return{M:f,y:h,w:d,d:u,D:v,h:s,m:l,s:o,ms:a,Q:p}[z]||String(z||"").toLowerCase().replace(/s$/,"")},u:function(z){return z===void 0}},j="en",k={};k[j]=b;var C="$isDayjsObject",O=function(z){return z instanceof I||!(!z||!z[C])},N=function z(D,$,K){var M;if(!D)return j;if(typeof D=="string"){var R=D.toLowerCase();k[R]&&(M=R),$&&(k[R]=$,M=R);var P=D.split("-");if(!M&&P.length>1)return z(P[0])}else{var G=D.name;k[G]=D,M=G}return!K&&M&&(j=M),M||!K&&j},A=function(z,D){if(O(z))return z.clone();var $=typeof D=="object"?D:{};return $.date=z,$.args=arguments,new I($)},T=S;T.l=N,T.i=O,T.w=function(z,D){return A(z,{locale:D.$L,utc:D.$u,x:D.$x,$offset:D.$offset})};var I=function(){function z($){this.$L=N($.locale,null,!0),this.parse($),this.$x=this.$x||$.x||{},this[C]=!0}var D=z.prototype;return D.parse=function($){this.$d=function(K){var M=K.date,R=K.utc;if(M===null)return new Date(NaN);if(T.u(M))return new Date;if(M instanceof Date)return new Date(M);if(typeof M=="string"&&!/Z$/i.test(M)){var P=M.match(x);if(P){var G=P[2]-1||0,ee=(P[7]||"0").substring(0,3);return R?new Date(Date.UTC(P[1],G,P[3]||1,P[4]||0,P[5]||0,P[6]||0,ee)):new Date(P[1],G,P[3]||1,P[4]||0,P[5]||0,P[6]||0,ee)}}return new Date(M)}($),this.init()},D.init=function(){var $=this.$d;this.$y=$.getFullYear(),this.$M=$.getMonth(),this.$D=$.getDate(),this.$W=$.getDay(),this.$H=$.getHours(),this.$m=$.getMinutes(),this.$s=$.getSeconds(),this.$ms=$.getMilliseconds()},D.$utils=function(){return T},D.isValid=function(){return this.$d.toString()!==y},D.isSame=function($,K){var M=A($);return this.startOf(K)<=M&&M<=this.endOf(K)},D.isAfter=function($,K){return A($)<this.startOf(K)},D.isBefore=function($,K){return this.endOf(K)<A($)},D.$g=function($,K,M){return T.u($)?this[K]:this.set(M,$)},D.unix=function(){return Math.floor(this.valueOf()/1e3)},D.valueOf=function(){return this.$d.getTime()},D.startOf=function($,K){var M=this,R=!!T.u(K)||K,P=T.p($),G=function(F,J){var re=T.w(M.$u?Date.UTC(M.$y,J,F):new Date(M.$y,J,F),M);return R?re:re.endOf(u)},ee=function(F,J){return T.w(M.toDate()[F].apply(M.toDate("s"),(R?[0,0,0,0]:[23,59,59,999]).slice(J)),M)},E=this.$W,ae=this.$M,xe=this.$D,H="set"+(this.$u?"UTC":"");switch(P){case h:return R?G(1,0):G(31,11);case f:return R?G(1,ae):G(0,ae+1);case d:var Y=this.$locale().weekStart||0,ue=(E<Y?E+7:E)-Y;return G(R?xe-ue:xe+(6-ue),ae);case u:case v:return ee(H+"Hours",0);case s:return ee(H+"Minutes",1);case l:return ee(H+"Seconds",2);case o:return ee(H+"Milliseconds",3);default:return this.clone()}},D.endOf=function($){return this.startOf($,!1)},D.$set=function($,K){var M,R=T.p($),P="set"+(this.$u?"UTC":""),G=(M={},M[u]=P+"Date",M[v]=P+"Date",M[f]=P+"Month",M[h]=P+"FullYear",M[s]=P+"Hours",M[l]=P+"Minutes",M[o]=P+"Seconds",M[a]=P+"Milliseconds",M)[R],ee=R===u?this.$D+(K-this.$W):K;if(R===f||R===h){var E=this.clone().set(v,1);E.$d[G](ee),E.init(),this.$d=E.set(v,Math.min(this.$D,E.daysInMonth())).$d}else G&&this.$d[G](ee);return this.init(),this},D.set=function($,K){return this.clone().$set($,K)},D.get=function($){return this[T.p($)]()},D.add=function($,K){var M,R=this;$=Number($);var P=T.p(K),G=function(ae){var xe=A(R);return T.w(xe.date(xe.date()+Math.round(ae*$)),R)};if(P===f)return this.set(f,this.$M+$);if(P===h)return this.set(h,this.$y+$);if(P===u)return G(1);if(P===d)return G(7);var ee=(M={},M[l]=r,M[s]=i,M[o]=n,M)[P]||1,E=this.$d.getTime()+$*ee;return T.w(E,this)},D.subtract=function($,K){return this.add(-1*$,K)},D.format=function($){var K=this,M=this.$locale();if(!this.isValid())return M.invalidDate||y;var R=$||"YYYY-MM-DDTHH:mm:ssZ",P=T.z(this),G=this.$H,ee=this.$m,E=this.$M,ae=M.weekdays,xe=M.months,H=M.meridiem,Y=function(J,re,B,ve){return J&&(J[re]||J(K,R))||B[re].slice(0,ve)},ue=function(J){return T.s(G%12||12,J,"0")},F=H||function(J,re,B){var ve=J<12?"AM":"PM";return B?ve.toLowerCase():ve};return R.replace(g,function(J,re){return re||function(B){switch(B){case"YY":return String(K.$y).slice(-2);case"YYYY":return T.s(K.$y,4,"0");case"M":return E+1;case"MM":return T.s(E+1,2,"0");case"MMM":return Y(M.monthsShort,E,xe,3);case"MMMM":return Y(xe,E);case"D":return K.$D;case"DD":return T.s(K.$D,2,"0");case"d":return String(K.$W);case"dd":return Y(M.weekdaysMin,K.$W,ae,2);case"ddd":return Y(M.weekdaysShort,K.$W,ae,3);case"dddd":return ae[K.$W];case"H":return String(G);case"HH":return T.s(G,2,"0");case"h":return ue(1);case"hh":return ue(2);case"a":return F(G,ee,!0);case"A":return F(G,ee,!1);case"m":return String(ee);case"mm":return T.s(ee,2,"0");case"s":return String(K.$s);case"ss":return T.s(K.$s,2,"0");case"SSS":return T.s(K.$ms,3,"0");case"Z":return P}return null}(J)||P.replace(":","")})},D.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},D.diff=function($,K,M){var R,P=this,G=T.p(K),ee=A($),E=(ee.utcOffset()-this.utcOffset())*r,ae=this-ee,xe=function(){return T.m(P,ee)};switch(G){case h:R=xe()/12;break;case f:R=xe();break;case p:R=xe()/3;break;case d:R=(ae-E)/6048e5;break;case u:R=(ae-E)/864e5;break;case s:R=ae/i;break;case l:R=ae/r;break;case o:R=ae/n;break;default:R=ae}return M?R:T.a(R)},D.daysInMonth=function(){return this.endOf(f).$D},D.$locale=function(){return k[this.$L]},D.locale=function($,K){if(!$)return this.$L;var M=this.clone(),R=N($,K,!0);return R&&(M.$L=R),M},D.clone=function(){return T.w(this.$d,this)},D.toDate=function(){return new Date(this.valueOf())},D.toJSON=function(){return this.isValid()?this.toISOString():null},D.toISOString=function(){return this.$d.toISOString()},D.toString=function(){return this.$d.toUTCString()},z}(),q=I.prototype;return A.prototype=q,[["$ms",a],["$s",o],["$m",l],["$H",s],["$W",u],["$M",f],["$y",h],["$D",v]].forEach(function(z){q[z[1]]=function(D){return this.$g(D,z[0],z[1])}}),A.extend=function(z,D){return z.$i||(z(D,I,A),z.$i=!0),A},A.locale=N,A.isDayjs=O,A.unix=function(z){return A(1e3*z)},A.en=k[j],A.Ls=k,A.p={},A})})(oE);var E3=oE.exports;const tn=Un(E3);var lE={exports:{}};(function(e,t){(function(n,r){e.exports=r()})(zo,function(){return function(n,r,i){n=n||{};var a=r.prototype,o={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function l(u,d,f,p){return a.fromToBase(u,d,f,p)}i.en.relativeTime=o,a.fromToBase=function(u,d,f,p,h){for(var v,y,x,g=f.$locale().relativeTime||o,b=n.thresholds||[{l:"s",r:44,d:"second"},{l:"m",r:89},{l:"mm",r:44,d:"minute"},{l:"h",r:89},{l:"hh",r:21,d:"hour"},{l:"d",r:35},{l:"dd",r:25,d:"day"},{l:"M",r:45},{l:"MM",r:10,d:"month"},{l:"y",r:17},{l:"yy",d:"year"}],w=b.length,S=0;S<w;S+=1){var j=b[S];j.d&&(v=p?i(u).diff(f,j.d,!0):f.diff(u,j.d,!0));var k=(n.rounding||Math.round)(Math.abs(v));if(x=v>0,k<=j.r||!j.r){k<=1&&S>0&&(j=b[S-1]);var C=g[j.l];h&&(k=h(""+k)),y=typeof C=="string"?C.replace("%d",k):C(k,d,j.l,x);break}}if(d)return y;var O=x?g.future:g.past;return typeof O=="function"?O(y):O.replace("%s",y)},a.to=function(u,d){return l(u,d,this,!0)},a.from=function(u,d){return l(u,d,this)};var s=function(u){return u.$u?i.utc():i()};a.toNow=function(u){return this.to(s(this),u)},a.fromNow=function(u){return this.from(s(this),u)}}})})(lE);var A3=lE.exports;const T3=Un(A3),I3=["authorization","x-api-key","api-key","apikey","x-auth-token","auth-token","secret","password","api_secret","jwt","csrf_token","xsrf_token","auth_token","session_token","private_key","client_secret"],_3=e=>{const t=e.toLowerCase();return!!(I3.some(n=>t===n)||t.startsWith("api_")&&(t.endsWith("_key")||t.endsWith("_secret"))||(t.endsWith("_token")||t.endsWith("_key")||t.endsWith("_secret"))&&!["max_tokens","input_tokens","output_tokens","completion_tokens","prompt_tokens","cachereadinputtokens","totaltokens"].some(r=>t.replace(/_/g,"").includes(r.replace(/_/g,""))))},N3=e=>!e||e.length<=8?"***":`${e.slice(0,4)}${"*".repeat(Math.min(e.length-8,20))}${e.slice(-4)}`,pv=e=>{if(e==null)return e;if(Array.isArray(e))return e.map(t=>pv(t));if(typeof e=="object"){const t={};for(const[n,r]of Object.entries(e))_3(n)?t[n]=typeof r=="string"?N3(r):"***":typeof r=="object"?t[n]=pv(r):t[n]=r;return t}return e},cr=({data:e,title:t,collapsed:n=!1})=>{const[r,i]=m.useState(!n),[a,o]=m.useState(!1),l=d=>{try{let f;typeof d=="string"?f=JSON.parse(d):f=d;const p=pv(f);return JSON.stringify(p,null,2)}catch{return typeof d=="string"?d:String(d)}},s=()=>{const d=l(e);navigator.clipboard.writeText(d).then(()=>{o(!0),setTimeout(()=>o(!1),2e3)}).catch(f=>{console.error("Failed to copy JSON:",f)})},u=l(e);return c.jsxs("div",{className:"json-viewer",children:[c.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"8px"},children:[t&&c.jsx("h4",{style:{margin:0,fontSize:"14px",color:"var(--text-primary)"},children:t}),c.jsxs("div",{style:{display:"flex",gap:"8px"},children:[c.jsx("button",{onClick:()=>i(!r),className:"btn btn-sm btn-secondary",style:{fontSize:"12px",padding:"2px 8px"},children:r?"折叠":"展开"}),c.jsx("button",{onClick:s,className:"btn btn-sm btn-primary",style:{fontSize:"12px",padding:"2px 8px"},children:a?"已复制":"复制"})]})]}),r&&c.jsx("pre",{style:{background:"var(--bg-code)",border:"1px solid var(--border-primary)",borderRadius:"8px",padding:"12px",overflowX:"auto",fontSize:"12px",lineHeight:"1.4",color:"var(--text-primary)",maxHeight:"400px",overflowY:"auto",margin:0},children:c.jsx("code",{children:u})})]})},_h=({currentPage:e,totalItems:t,pageSize:n,onPageChange:r,onPageSizeChange:i,pageSizeOptions:a=[10,20,50,100]})=>{const o=Math.max(1,Math.ceil(t/n)),l=e===1,s=e>=o,u=()=>{l||r(1)},d=()=>{l||r(e-1)},f=()=>{s||r(e+1)},p=()=>{s||r(o)},h=v=>{const y=parseInt(v.target.value,10);i(y)};return c.jsxs("div",{className:"pagination",children:[c.jsxs("div",{className:"pagination-info",children:["共 ",t," 条"]}),c.jsxs("div",{className:"pagination-controls",children:[c.jsx("button",{className:"pagination-btn",onClick:u,disabled:l,children:"首页"}),c.jsx("button",{className:"pagination-btn",onClick:d,disabled:l,children:"上一页"}),c.jsxs("span",{className:"pagination-info",children:["第 ",e," / ",o," 页"]}),c.jsx("button",{className:"pagination-btn",onClick:f,disabled:s,children:"下一页"}),c.jsx("button",{className:"pagination-btn",onClick:p,disabled:s,children:"尾页"})]}),c.jsx("div",{className:"pagination-size",children:c.jsxs("label",{children:["每页显示",c.jsx("select",{className:"pagination-select",value:n,onChange:h,children:a.map(v=>c.jsx("option",{value:v,children:v},v))}),"条"]})})]})};tn.extend(T3);function M3(e){const t=[];let n={dataLines:[],rawLines:[]};for(const r of e){const i=r.split(`
|
|
358
358
|
`);for(const a of i){if(n.rawLines.push(a),!a.trim()){if(n.event||n.dataLines.length>0){const o=n.dataLines.length>0?n.dataLines.join(`
|
|
359
359
|
`):void 0,l={event:n.event,raw:n.rawLines.join(`
|
|
360
360
|
`)};if(o)try{l.data=JSON.parse(o)}catch{l.data=o}t.push(l)}n={dataLines:[],rawLines:[]};continue}a.startsWith("event:")?n.event=a.slice(6).trim():a.startsWith("data:")&&n.dataLines.push(a.slice(5).trim())}}if(n.event||n.dataLines.length>0){const r=n.dataLines.length>0?n.dataLines.join(`
|
package/dist/ui/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>AI Code Switch</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-4IziQEi6.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="./assets/index-BVblbmz5.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicodeswitch",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"description": "A tool to help you manage AI programming tools to access large language models locally. It allows your Claude Code, Codex and other tools to no longer be limited to official models.",
|
|
5
5
|
"author": "tangshuang",
|
|
6
6
|
"license": "GPL-3.0",
|