waygate-open 1.6.19 → 1.6.21

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.
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./LandingPage-DkcOcP6r.js","./vendor-befEYGHM.js","./accessUrl-DbL5DLDz.js","./LandingPage-Bx7xbIg8.css","./OverviewPage-CqDgOLe1.js","./Select-CrLEZJdb.js","./PageSkeleton-DG-Dj4_9.js","./sharedWindow-FDfq75PI.js","./useFx-xcrp_LHB.js","./ClientMetricTip-DUB2wyWX.js","./UsagePage-lHPe750E.js","./ClientsPage-CDRyiYxX.js","./Modal-B-rIrvXS.js","./useFocusTrap-Cj84bnpH.js","./Drawer-CleQGhRU.js","./Switch-0KA1AbiV.js","./ApiKeysPage-DTazS32S.js","./RequestsPage-DZNwUay0.js","./SettingsPage-Bzcu_JCB.js"])))=>i.map(i=>d[i]);
2
+ import{$ as e,D as t,F as n,O as r,P as i,S as a,T as o,U as s,Y as c,b as l,c as u,d,it as f,nt as p,r as m,rt as h,s as g,tt as _,v,x as y,y as b}from"./vendor-befEYGHM.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var x=f(),S=p();function C(e=window.location.pathname){let t=e.replace(/\/+$/,``)||`/`;return t===`/console`||t.startsWith(`/console/`)?`console`:`landing`}function w(e=!1){let{pathname:t,hash:n}=window.location;if(C(t)===`console`||!n.startsWith(`#/`))return;let r=`/console${n}`;e?window.location.replace(r):window.history.replaceState(null,``,r)}function T(){window.addEventListener(`hashchange`,()=>w(!0))}var E=`relay.theme`,D=`system`;function O(){try{return window.matchMedia?.(`(prefers-color-scheme: light)`).matches?`light`:`dark`}catch{return`dark`}}function k(e,t=window.location.pathname,n=window.location.hash){return e===`system`?O():e}function A(){try{let e=window.localStorage.getItem(E);return e===`light`||e===`dark`||e===`system`?e:D}catch{return D}}function ee(e){document.documentElement.dataset.theme=e}var j=null,M=new Set;function N(){if(j===null){let e=document.documentElement.dataset.theme,t=A();j={theme:e===`light`||e===`dark`?e:k(t),preference:t}}return j}function P(e){return M.add(e),()=>M.delete(e)}function te(e){try{window.localStorage.setItem(E,e)}catch{}F()}function F(){let e=A(),t=k(e);ee(t),j={theme:t,preference:e},M.forEach(e=>e())}typeof window<`u`&&(window.matchMedia?.(`(prefers-color-scheme: light)`).addEventListener?.(`change`,()=>{A()===`system`&&F()}),window.addEventListener(`storage`,e=>{(e.key===null||e.key===E)&&F()}));var I=[`overview`,`usage`,`clients`,`keys`,`requests`,`settings`];function L(e){let t=e.replace(/^#\/?/,``).split(`?`)[0];return I.includes(t)?t:`overview`}function ne(){let[e,t]=(0,x.useState)(()=>L(window.location.hash));return(0,x.useEffect)(()=>{let e=()=>t(L(window.location.hash));return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]),{route:e,navigate:e=>{window.location.hash=`#/${e}`}}}var R=class extends Error{code;status;retryAfterSeconds;constructor(e,t,n,r){super(e),this.name=`ApiError`,this.code=t,this.status=n,this.retryAfterSeconds=r}get isSessionExpired(){return this.code===40102}},z=new Set;function re(e){return z.add(e),()=>z.delete(e)}function ie(e){z.forEach(t=>t(e))}async function ae(e){let t=await e.text(),n=null;try{n=t?JSON.parse(t):null}catch{throw new R(`服务端返回了非 JSON 响应(HTTP ${e.status})`,0,e.status)}if(!n||typeof n.code!=`number`)throw new R(`响应缺少统一信封(HTTP ${e.status})`,0,e.status);if(n.code===0)return n.data;let r=n.data?.retryAfterSeconds;throw new R(n.message||`请求失败(code ${n.code})`,n.code,e.status,r)}var B=2e4;function oe(e,t){let n=new AbortController,r=!1,i=()=>n.abort(e?.reason);e&&(e.aborted?n.abort(e.reason):e.addEventListener(`abort`,i,{once:!0}));let a=t===null?void 0:setTimeout(()=>{r=!0,n.abort()},t);return{signal:n.signal,isTimedOut:()=>r,dispose:()=>{a!==void 0&&clearTimeout(a),e?.removeEventListener(`abort`,i)}}}function se(e){return e instanceof DOMException&&e.name===`AbortError`}async function V(e,t){let n=(t?.method??`GET`).toUpperCase(),r=oe(t?.signal,n===`GET`?B:null),i=new Headers(t?.headers);i.has(`accept`)||i.set(`Accept`,`application/json`),t?.body&&!i.has(`content-type`)&&i.set(`Content-Type`,`application/json`);let a;try{a=await fetch(e,{...t,signal:r.signal,credentials:`same-origin`,headers:i})}catch(e){throw r.dispose(),r.isTimedOut()?new R(`请求超时(${B/1e3}s 无响应),稍后重试。`,0,0):se(e)?e:new R(`连不上本机服务。确认后端已在 127.0.0.1:8787 启动。`,0,0)}try{let e=await ae(a);if(!a.ok)throw new R(`请求失败(HTTP ${a.status})`,0,a.status);return e}catch(e){throw r.isTimedOut()?new R(`请求超时(${B/1e3}s 无响应),稍后重试。`,0,0):e}finally{r.dispose()}}async function H(e,t){try{return await V(e,t)}catch(e){throw e instanceof R&&e.isSessionExpired&&ie(e),e}}function U(e){let t=new URLSearchParams;Object.entries(e).forEach(([e,n])=>{n!=null&&n!==``&&t.set(e,String(n))});let n=t.toString();return n?`?${n}`:``}var W=new Map,G=new Map;function ce(){W.clear(),G.clear()}function le(e,t){W.has(e)&&W.set(e,t(W.get(e)))}function ue(e,t,n){let r=G.get(e);if(r&&!n)return r;let i=t().then(t=>(G.get(e)===i&&W.set(e,t),t));return G.set(e,i),i.finally(()=>{G.get(e)===i&&G.delete(e)}).catch(()=>{}),i}function de(e,t,n={}){let r=n.enabled??!0,i=n.cacheKey,a=r&&i!==void 0&&W.has(i),[o,s]=(0,x.useState)(()=>a?W.get(i):null),[c,l]=(0,x.useState)(null),[u,d]=(0,x.useState)(r),[f,p]=(0,x.useState)(!a),m=(0,x.useRef)(0),h=(0,x.useRef)(e);h.current=e;let g=(0,x.useRef)(i);g.current=i;let _=(0,x.useCallback)(e=>{let t=++m.current,n=g.current;d(!0),(n===void 0?h.current():ue(n,()=>h.current(),e)).then(e=>{t===m.current&&(s(e),l(null),d(!1),p(!1))},e=>{t!==m.current||se(e)||(l(e instanceof R?e:new R(String(e),0,0)),d(!1),p(!1))})},[]);return(0,x.useEffect)(()=>{if(!r){m.current+=1,s(null),l(null),d(!1),p(!0);return}i!==void 0&&W.has(i)&&(s(W.get(i)),l(null),p(!1)),_(!1)},[r,i,...t]),{data:o,error:c,loading:u,initial:f,reload:(0,x.useCallback)(()=>_(!0),[_])}}var fe={today:`今日`,"1h":`最近 1 小时`,"24h":`最近 24 小时`,"7d":`最近 7 天`,"30d":`最近 30 天`},pe=Object.keys(fe).map(e=>({value:e,label:fe[e]}));function me(e,t){return t&&new Date(t).getTime()<Date.now()?`exp`:e?`live`:`off`}var he={live:`启用`,off:`已停用`,exp:`已过期`},ge=new Intl.NumberFormat(`zh-CN`),_e=new Intl.NumberFormat(`zh-CN`,{minimumFractionDigits:2,maximumFractionDigits:2});function ve(e){return e==null||Number.isNaN(e)?`--`:ge.format(Math.round(e))}function ye(e){return e==null||Number.isNaN(e)?`--`:_e.format(e)}function be(e,t=1){return e==null||Number.isNaN(e)?`--`:`${(e*100).toFixed(t)}%`}function xe(e,t=1){return`${((Number.isFinite(e)?Math.max(0,Math.min(1,e)):0)*100).toFixed(t)}%`}var Se=[{limit:0x38d7ea4c68000,div:0x38d7ea4c68000,digits:2,suffix:`Q`},{limit:0xe8d4a51000,div:0xe8d4a51000,digits:2,suffix:`T`},{limit:1e9,div:1e9,digits:2,suffix:`B`},{limit:1e6,div:1e6,digits:2,suffix:`M`},{limit:1e3,div:1e3,digits:1,suffix:`K`}];function Ce(e){if(e==null||Number.isNaN(e))return`--`;let t=Math.round(e),n=Se.find(e=>Math.abs(t)>=e.limit);return n?`${(t/n.div).toFixed(n.digits)}${n.suffix}`:String(t)}function we(e){return e==null||Number.isNaN(e)?`--`:e<1e3?`${Math.round(e)}ms`:e<6e4?`${(e/1e3).toFixed(1)}s`:`${Math.floor(e/6e4)}m${Math.round(e%6e4/1e3)}s`}function Te(e,t,n){let r=e??0;if(r<=0||t==null||t<=0)return null;let i=n==null?t:t-n;return i<=0?null:r/(i/1e3)}function Ee(e){return e==null||Number.isNaN(e)?`--`:`${e.toFixed(1)} t/s`}function De(e){if(!e)return`--`;let t=new Date(e);return Number.isNaN(t.getTime())?`--`:t.toLocaleTimeString(`zh-CN`,{hour12:!1})}function Oe(e){if(!e)return`--`;let t=new Date(e);return Number.isNaN(t.getTime())?`--`:`${t.toLocaleDateString(`zh-CN`)} ${t.toLocaleTimeString(`zh-CN`,{hour12:!1})}`}function ke(e){if(!e)return`--`;let t=new Date(e).getTime();if(Number.isNaN(t))return`--`;let n=Date.now()-t;if(n<0){let e=-n;return e<6e4?`马上`:e<36e5?`${Math.floor(e/6e4)} 分钟后`:e<864e5?`${Math.floor(e/36e5)} 小时后`:`${Math.floor(e/864e5)} 天后`}let r=Math.floor(n/6e4);if(r<1)return`刚刚`;if(r<60)return`${r} 分钟前`;let i=Math.floor(r/60);if(i<24)return`${i} 小时前`;let a=Math.floor(i/24);return a<30?`${a} 天前`:`${Math.floor(a/30)} 个月前`}function Ae(e){let t=e.match(/^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?/);if(!t)return e.slice(5,10);let n=`${Number(t[2])}/${Number(t[3])}`;return t[4]===void 0?n:`${n} ${Number(t[4])}时`}function je(e){switch(e.type){case`all`:return`全部模型`;case`family`:return`仅 ${e.value} 系`;case`tag`:return`仅 ${e.value}`;case`models`:return`指定 ${e.value.length} 个模型`;default:return`未知范围`}}var Me=`upstream_credential_invalid`;function Ne(e,t=Me){return e.split(`,`).includes(t)}function Pe(e,t=``){return Ne(t)||e===401?`fatal`:e>=400?`warn`:`live`}var Fe={[Me]:`上游访问密钥失效`,"upstream unreachable":`上游不可达`,"upstream empty body":`上游返回空响应`,upstream_error:`上游错误`,"bad request body":`请求体不合法`,"model not permitted":`模型未授权`,"model not found":`模型不存在`,"concurrency limit":`本机并发上限`,"rate limited":`命中上游限流`,rate_limited:`命中上游限流`,"upstream timeout":`上游超时`,model_not_available:`账号未开通此模型`,invalid_max_tokens:`max_tokens 不合法`,context_length_exceeded:`上下文超限`,upstream_11101:`上游要求强制流式`,upstream_11128:`上游渠道校验拒绝(提示指纹)`,retried:`已自动重试`,"cache hit":`命中缓存`,system_injected:`已补 system`,developer_role_normalized:`已规范 developer 角色`,stream_options_stripped:`已移除 stream_options`,sysprompt_degraded_retry:`命中渠道校验,已降级重试`,breaker_open:`渠道熔断中(未发上游)`,key_deleted_inflight:`密钥在途删除(归属已置空)`,stream_aborted:`流式中断`,client_detached:`客户端已断开`,usage_missing:`上游未返回用量`,"minimax tokens unavailable":`MiniMax token 不可用`,"token refresh failed":`上游 token 刷新失败`,"missing credential":`缺少上游访问凭证`,"wb oauth unavailable":`WorkBuddy 授权服务不可用`,"missing wb oauth credential":`WorkBuddy 未导入授权`,"wb token refresh failed":`WorkBuddy 授权刷新失败`,"qoder credential invalid":`Qoder 凭证无效`,"multiplier-unknown":`倍率未知(历史:积分按中性估算)`,cache_discounted:`缓存命中已按折扣计(历史)`,credits_from_upstream:`上游实扣积分`,credits_unknown:`上游未回报积分`,credits_recalibrated:`历史积分已重算`,estimate_voided:`历史估算已作废(上游未回报)`};function Ie(e){if(!e)return`-`;let t=e.split(`,`)[0];return Fe[t]??t}function Le(e){return e?e.split(`,`).map(e=>e.trim()).filter(Boolean).map(e=>Fe[e]??e):[]}function Re(e){return e.upstreamCode===11102?`11102:当前账号未开通该模型。该项已在模型表标为未验证,不会自动删除——订阅变动后可能再开。`:e.upstreamCode===11128?`11128:上游返回业务码 11128(上游原文「Illegal API invocation from an unapproved channel」):本次请求的 system 提示命中了上游对第三方客户端模板的指纹校验。本服务已在转发前改写模板行,并在被拒时自动降级为中性提示重试一次,均未通过;请检查「客户端与密钥 → 提供商 → system 提示改写」是否被关闭,或把该请求的特征反馈给维护者。`:e.upstreamCode===11101?`11101:上游拒绝了非流式请求。本服务已强制改写为流式,出现此码说明上游协议变更。`:e.upstreamCode===11133?`11133:max_tokens 过小。已提升到下限后重试一次。`:Ne(e.note)?`上游访问密钥失效是这套方案唯一会让服务停摆的状态:所有客户端共用同一把上游访问密钥,它一失效即整体不可用。去「客户端与密钥 → 提供商」的「修改」里换新。`:null}var ze=[{displayName:`Hy4 preview`,id:`hy4-preview`,tag:`限时免费`,multiplier:0},{displayName:`Hy3`,id:`hy3`,tag:`限时免费`,multiplier:0},{displayName:`Space-Bunny`,id:`space-bunny`,tag:`限时折扣`,multiplier:.03},{displayName:`Deepseek-V4.1-Flash`,id:`deepseek-v4.1-flash`,tag:null,multiplier:.11},{displayName:`Deepseek-V4-Pro`,id:`deepseek-v4-pro`,tag:null,multiplier:.51},{displayName:`GLM-5.3`,id:`glm-5.3`,tag:`订阅优先`,multiplier:.79},{displayName:`GLM-5.3-Flash`,id:`glm-5.3-flash`,tag:`订阅优先`,multiplier:.06},{displayName:`GLM-5.3-FlashX`,id:`glm-5.3-flashx`,tag:`订阅优先`,multiplier:.14},{displayName:`GLM-5.2`,id:`glm-5.2`,tag:null,multiplier:.79},{displayName:`GLM-5.1`,id:`glm-5.1`,tag:null,multiplier:.79},{displayName:`GLM-5v-Turbo`,id:`glm-5v-turbo`,tag:null,multiplier:.71},{displayName:`MiniMax-M3`,id:`minimax-m3`,tag:null,multiplier:.25},{displayName:`Kimi-K3`,id:`kimi-k3`,tag:`订阅优先`,multiplier:1.62},{displayName:`Kimi-K2.8-Preview`,id:`kimi-k2.8-preview`,tag:`订阅优先`,multiplier:.77},{displayName:`Kimi-K2.7-Code`,id:`kimi-k2.7`,tag:null,multiplier:.57},{displayName:`Kimi-K2.6`,id:`kimi-k2.6`,tag:null,multiplier:.52},{displayName:`Step-5-Preview`,id:`step-5-preview`,tag:`订阅优先`,multiplier:.43},{displayName:`Kimi-K3-1`,id:`kimi-k3-1`,tag:`订阅优先`,multiplier:null}],Be=new Set([`kimi-k3-1`]),Ve=new Set([`step-5-preview`]);function He(e){return Be.has(e)?`upstream`:Ve.has(e)?`manual`:`seed`}var Ue={source:`seed`,fetchedAt:new Date(Date.now()-72e5).toISOString(),upstreamReachable:!0,models:ze.map(e=>({...e,family:e.id.split(`-`)[0],source:He(e.id),provider:e.id.startsWith(`MiniMax-`)||e.id.startsWith(`minimax-`)?`MiniMax Code`:`WorkBuddy`,verified:e.id===`glm-5.1`||e.id===`hy3`?0:1,enabled:!0,lastVerifiedAt:new Date(Date.now()-72e5).toISOString()}))},We=[{id:`k_8f21`,name:`Claude Code`},{id:`k_1b83`,name:`Cherry Studio`},{id:`k_9d02`,name:`Cursor`},{id:`k_c3a5`,name:`Cron Job`},{id:`k_77c1`,name:`手机端(临时)`},{id:`unidentified`,name:`未识别客户端`}];function Ge(){let e=Date.now(),t={ipWhitelist:[],maxIps:null,tokenQuota:null,usedIps:0,usedTokens:0};return[{...t,id:`k_8f21`,name:`Claude Code · 本机`,hint:`sk-waygate-4f9c…7a2e`,scope:{type:`all`},client:`Claude Code`,clients:[`Claude Code`],enabled:!0,expiresAt:null,createdAt:new Date(e-11232e5).toISOString(),lastSeenAt:new Date(e-4e4).toISOString(),requests24h:760},{...t,maxIps:3,tokenQuota:2e6,usedIps:2,usedTokens:1234567,id:`k_1b83`,name:`Cherry Studio`,hint:`sk-waygate-1b83…c40f`,scope:{type:`all`},client:`Cherry Studio`,clients:[`Cherry Studio`],enabled:!0,expiresAt:null,createdAt:new Date(e-9504e5).toISOString(),lastSeenAt:new Date(e-9e4).toISOString(),requests24h:324},{...t,id:`k_9d02`,name:`Cursor · 笔记本`,hint:`sk-waygate-9d02…3ee1`,scope:{type:`family`,value:`kimi`},client:`Cursor`,clients:[`Cursor`,`Claude Code`],enabled:!0,expiresAt:null,createdAt:new Date(e-7776e5).toISOString(),lastSeenAt:new Date(e-108e5).toISOString(),requests24h:154},{...t,id:`k_c3a5`,name:`Cron Job · 定时任务`,hint:`sk-waygate-c3a5…91d7`,scope:{type:`family`,value:`deepseek`},client:`Cron Job`,clients:[`Cron Job`],enabled:!0,expiresAt:null,createdAt:new Date(e-6912e5).toISOString(),lastSeenAt:new Date(e-3e5).toISOString(),requests24h:78},{...t,ipWhitelist:[`192.168.1.0/24`],id:`k_77c1`,name:`手机端(临时)`,hint:`sk-waygate-77c1…b8f0`,scope:{type:`all`},client:`手机端(临时)`,clients:[`手机端(临时)`],enabled:!1,expiresAt:null,createdAt:new Date(e-2592e6).toISOString(),lastSeenAt:new Date(e-2592e5).toISOString(),requests24h:0},{...t,id:`k_2e6b`,name:`测试脚本 · 本地`,hint:`sk-waygate-2e6b…0a13`,scope:{type:`tag`,value:`夜间折扣`},client:null,clients:[],enabled:!0,expiresAt:new Date(e-1728e5).toISOString(),createdAt:new Date(e-3456e6).toISOString(),lastSeenAt:new Date(e-10368e5).toISOString(),requests24h:0},{...t,id:`k_5d7f`,name:`家人共享 · 只读`,hint:`sk-waygate-5d7f…22c8`,scope:{type:`models`,value:[`glm-5.3`,`kimi-k2.7`]},client:null,clients:[],enabled:!1,expiresAt:null,createdAt:new Date(e-1728e6).toISOString(),lastSeenAt:new Date(e-432e6).toISOString(),requests24h:0}]}We.filter(e=>e.id!==`unidentified`).map(e=>e.name),Ge(),new Date().toISOString(),Date.now()+1728e6,Date.now()+22464e5,new Date().toISOString().slice(0,10),new Date(Date.now()-18e5).toISOString(),new Date(Date.now()-216e5).toISOString(),new Date(Date.now()+19008e5).toISOString(),new Date(Date.now()-24e5).toISOString(),Ue.models.map(e=>({...e}));function K(e){return{method:`POST`,body:JSON.stringify(e)}}var q={session(){return V(`/api/auth/session`)},login(e){return V(`/api/auth/login`,K({password:e}))},logout(){return V(`/api/auth/logout`,{method:`POST`})},overview(e){return H(`/api/overview${U({window:e})}`)},clients(e){return H(`/api/clients${U({window:e})}`)},requests(e){return H(`/api/requests${U({...e})}`)},requestDetail(e){return H(`/api/requests/${e}`)},keys(){return H(`/api/keys`).then(e=>e.items)},createKey(e){return H(`/api/keys`,K(e))},patchKey(e,t){return H(`/api/keys/${e}`,{method:`PATCH`,body:JSON.stringify(t)})},deleteKey(e){return H(`/api/keys/${e}`,{method:`DELETE`})},settings(){return H(`/api/settings`)},putSettings(e){return H(`/api/settings`,{method:`PUT`,body:JSON.stringify({settings:e})}).then(t=>(le(`settings`,n=>({...n,version:t.version,groups:n.groups.map(t=>({...t,items:t.items.map(t=>{let n=e.find(e=>e.key===t.key);return n?{...t,value:n.value}:t})}))})),t))},danger(e,t){return H(`/api/settings/danger`,K({action:e,confirm:t}))},putCredential(e){return H(`/api/settings/credential`,{method:`PUT`,body:JSON.stringify({key:e})})},resetAdminPassword(){return H(`/api/auth/password/reset`,{method:`POST`})},setAdminPassword(e){return H(`/api/auth/password`,{method:`PUT`,body:JSON.stringify({password:e})})},catalog(e){return H(`/api/models/catalog${e?`?provider=${encodeURIComponent(e)}`:``}`)},refreshCatalog(){return H(`/api/models/catalog`,{method:`POST`})},testCredential(e){return H(`/api/settings/credential/test`,K({key:e}))},setModelEnabled(e,t,n){return H(`/api/models/catalog/${encodeURIComponent(e)}${n?`?provider=${encodeURIComponent(n)}`:``}`,{method:`PATCH`,body:JSON.stringify({enabled:t})})},providerSignin(e){return H(`/api/providers/${encodeURIComponent(e)}/signin`)},providerOauthImport(e,t){return H(`/api/providers/${encodeURIComponent(e)}/oauth-import`,{method:`POST`,body:JSON.stringify(t)})},providerImportLocal(e){return H(`/api/providers/${encodeURIComponent(e)}/import-local`,{method:`POST`,body:`{}`})},providerImportDeviceStart(e){return H(`/api/providers/${encodeURIComponent(e)}/import-device/start`,{method:`POST`,body:`{}`})},providerImportDevicePoll(e){return H(`/api/providers/${encodeURIComponent(e)}/import-device/poll`,{method:`POST`,body:`{}`})},providerImportDeviceCancel(e){return H(`/api/providers/${encodeURIComponent(e)}/import-device/cancel`,{method:`POST`,body:`{}`})},providerGrowthRun(e){return H(`/api/providers/${encodeURIComponent(e)}/growth/run`,{method:`POST`})},providerGrowthPanel(e){return H(`/api/providers/${encodeURIComponent(e)}/growth`)},providerSigninNow(e){return H(`/api/providers/${encodeURIComponent(e)}/signin`,{method:`POST`})},providers(){return H(`/api/providers`)},createProvider(e){return H(`/api/providers`,{method:`POST`,body:JSON.stringify(e)})},patchProvider(e,t){return H(`/api/providers/${encodeURIComponent(e)}`,{method:`PATCH`,body:JSON.stringify(t)})},deactivateProvider(e){return H(`/api/providers/${encodeURIComponent(e)}/deactivate`,{method:`PUT`})},activateProvider(e){return H(`/api/providers/${encodeURIComponent(e)}/activate`,{method:`PUT`})},testProvider(e,t){return H(`/api/providers/${encodeURIComponent(e)}/test`,{method:`POST`,body:JSON.stringify(t?{credential:t}:{})})},deleteProvider(e){return H(`/api/providers/${encodeURIComponent(e)}`,{method:`DELETE`})}};function Ke(){let[e,t]=(0,x.useState)(`loading`),[n,r]=(0,x.useState)(null);(0,x.useEffect)(()=>{let e=!0;return q.session().then(n=>{e&&(t(n.authenticated?`authed`:`anon`),r(n.expiresAt))}).catch(()=>{e&&t(`anon`)}),()=>{e=!1}},[]);let i=(0,x.useRef)(!1);return(0,x.useEffect)(()=>re(()=>{i.current||(ce(),t(`anon`))}),[]),{status:e,expiresAt:n,login:(0,x.useCallback)(async e=>{let n=await q.login(e);ce(),t(`authed`),r(n.expiresAt)},[]),logout:(0,x.useCallback)(async()=>{i.current=!0;try{await q.logout()}catch(e){if(!(e instanceof R))throw i.current=!1,e}t(`anon`),r(null),window.location.assign(`/`)},[])}}var J=_();function Y({size:e=26}){return(0,J.jsxs)(`svg`,{width:e,height:e,viewBox:`0 0 160 160`,fill:`none`,role:`img`,"aria-label":`Waygate`,children:[(0,J.jsx)(`polygon`,{points:`80,8 148,48 128,125 50,151 12,78`,fill:`var(--brand-500)`,opacity:`.12`}),(0,J.jsx)(`polygon`,{points:`80,8 80,94 12,78`,fill:`var(--brand-400)`}),(0,J.jsx)(`polygon`,{points:`80,8 148,48 80,94`,fill:`var(--brand-500)`}),(0,J.jsx)(`polygon`,{points:`148,48 128,125 80,94`,fill:`var(--accent-blue)`}),(0,J.jsx)(`polygon`,{points:`12,78 80,94 50,151`,fill:`var(--brand-450)`,opacity:`.85`}),(0,J.jsx)(`polygon`,{points:`80,94 128,125 50,151`,fill:`var(--brand-450)`})]})}function qe(){return{...(0,x.useSyncExternalStore)(P,N,()=>({theme:`dark`,preference:`system`})),setPreference:te}}var Je=h(),X=12,Z=8,Ye=300;function Xe(e,t){typeof e==`function`?e(t):e&&(e.current=t)}function Ze({content:e,children:t,placement:n=`auto`,className:r}){let i=(0,x.useId)(),a=(0,x.useRef)(null),o=(0,x.useRef)(null),[s,c]=(0,x.useState)(!1),[l,u]=(0,x.useState)(null),d=t.props,f=d.disabled===!0,p=d.ref,m=typeof d[`aria-describedby`]==`string`?d[`aria-describedby`]:void 0,h=[m,s?i:void 0].filter(Boolean).join(` `)||void 0,g=typeof d.tabIndex==`number`?d.tabIndex:f?void 0:0,_=(0,x.useCallback)(()=>{let e=a.current,t=o.current;if(!e||!t)return;let r=e.getBoundingClientRect(),i=window.innerWidth,s=window.innerHeight,c=Math.min(Ye,Math.max(0,i-24)),l=Math.min(c,t.offsetWidth||c),d=t.offsetHeight;if(r.bottom<X||r.top>s-X){u(null);return}let f=r.top-X,p=s-r.bottom-X,m=f>=d+Z,h=p>=d+Z,g=n===`above`?m||!h?`above`:`below`:n===`below`?h||!m?`below`:`above`:m||!h?`above`:`below`,_=r.left+r.width/2,v=Math.max(X,Math.min(_-l/2,i-l-X)),y=Math.max(12,Math.min(_-v,l-12)),b=g===`above`?Math.max(X,r.top-d-Z):Math.max(X,Math.min(s-d-X,r.bottom+Z));u({left:v,top:b,placement:g,maxWidth:c,arrowLeft:y})},[n]),v=(0,x.useCallback)(()=>c(!0),[]),y=(0,x.useCallback)(()=>c(!1),[]);(0,x.useLayoutEffect)(()=>{if(!s){u(null);return}_()},[e,_,s]),(0,x.useLayoutEffect)(()=>{if(!s)return;let e=()=>_(),t=e=>{e.key===`Escape`&&(e.preventDefault(),e.stopPropagation(),y())},n=e=>{let t=e.target;t&&(a.current?.contains(t)||o.current?.contains(t))||y()};return window.addEventListener(`scroll`,e,!0),window.addEventListener(`resize`,e),window.visualViewport?.addEventListener(`resize`,e),window.visualViewport?.addEventListener(`scroll`,e),document.addEventListener(`keydown`,t,!0),document.addEventListener(`pointerdown`,n,!0),()=>{window.removeEventListener(`scroll`,e,!0),window.removeEventListener(`resize`,e),window.visualViewport?.removeEventListener(`resize`,e),window.visualViewport?.removeEventListener(`scroll`,e),document.removeEventListener(`keydown`,t,!0),document.removeEventListener(`pointerdown`,n,!0)}},[y,_,s]);let b=(0,x.useCallback)(e=>{a.current=e,Xe(p,e)},[p]),S=(0,x.useCallback)(e=>{Xe(p,e)},[p]),C=(0,x.useCallback)(e=>{a.current=e},[]),w=d.onBlur,T=(e,t)=>{let n=e.relatedTarget;n instanceof Node&&e.currentTarget.contains(n)||(t&&w?.(e),y())},E=typeof d.className==`string`&&r?`${d.className} ${r}`:r??d.className,D=(0,x.cloneElement)(t,{...E?{className:E}:{},ref:f?S:b,"aria-describedby":f?m:h,"data-tooltip-trigger":f?void 0:`true`,tabIndex:g,onMouseEnter:e=>{d.onMouseEnter?.(e),v()},onMouseLeave:e=>{d.onMouseLeave?.(e),y()},onFocus:e=>{d.onFocus?.(e),v()},onBlur:e=>T(e,!f)}),O=s&&typeof document<`u`?(0,Je.createPortal)((0,J.jsx)(`div`,{ref:o,id:i,role:`tooltip`,className:`tooltip-surface tooltip-${l?.placement??`measuring`}`,style:l?{left:l.left,top:l.top,maxWidth:l.maxWidth,"--tooltip-arrow-left":`${l.arrowLeft}px`}:{visibility:`hidden`,maxWidth:Math.min(Ye,Math.max(0,window.innerWidth-24))},children:e}),document.body):null;if(!f)return(0,J.jsxs)(J.Fragment,{children:[D,O]});let k=[m,s?i:void 0].filter(Boolean).join(` `)||void 0;return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`span`,{ref:C,className:`tooltip-anchor${r?` ${r}`:``}`,"data-tooltip-trigger":`true`,tabIndex:0,"aria-describedby":k,"aria-disabled":`true`,onMouseEnter:v,onMouseLeave:y,onFocus:v,onBlur:e=>T(e,!1),children:D}),O]})}var Q=[{value:`system`,label:`跟随系统`,Icon:b},{value:`light`,label:`浅色`,Icon:g},{value:`dark`,label:`深色`,Icon:v}];function Qe(){let{preference:e,setPreference:t}=qe();return(0,J.jsx)(`div`,{className:`theme-seg`,role:`radiogroup`,"aria-label":`外观`,onKeyDown:n=>{if(n.key!==`ArrowLeft`&&n.key!==`ArrowRight`)return;n.preventDefault();let r=Q.findIndex(t=>t.value===e),i=n.key===`ArrowRight`?(r+1)%Q.length:(r-1+Q.length)%Q.length;t(Q[i].value)},children:Q.map(({value:n,label:r,Icon:i})=>{let a=e===n;return(0,J.jsx)(Ze,{content:r,children:(0,J.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":a,tabIndex:a?0:-1,className:`theme-seg-i${a?` on`:``}`,"aria-label":r,onClick:()=>t(n),children:(0,J.jsx)(i,{size:14})})},n)})})}var $e=`relay.console.route`;function et(e){try{window.sessionStorage.setItem($e,e)}catch{}}function tt(){try{let e=window.sessionStorage.getItem($e);if(e&&I.includes(e))return e}catch{}return`overview`}function nt(e){return`/console#/${e??tt()}`}var rt=[{route:`overview`,label:`概览`,icon:(0,J.jsx)(o,{size:18})},{route:`usage`,label:`积分与用量`,icon:(0,J.jsx)(c,{size:18})},{route:`clients`,label:`提供商管理`,icon:(0,J.jsx)(e,{size:18})},{route:`keys`,label:`API 密钥`,icon:(0,J.jsx)(t,{size:18})},{route:`requests`,label:`请求日志`,icon:(0,J.jsx)(d,{size:18})},{route:`settings`,label:`设置`,icon:(0,J.jsx)(u,{size:18})}];function it({route:e,navigate:t,expiresAt:n,onLogout:r,children:i}){(0,x.useEffect)(()=>{et(e)},[e]);let[a,o]=(0,x.useState)(null);(0,x.useEffect)(()=>{let e=!0;return(async()=>{try{let t=await fetch(`/healthz`,{headers:{Accept:`application/json`}});if(!t.ok)return;let n=await t.json();e&&typeof n.version==`string`&&n.version&&o(n.version)}catch{}})(),()=>{e=!1}},[]);let[s,c]=(0,x.useState)(!1),u=(0,x.useRef)(null),d=(0,x.useRef)(null),f=(0,x.useRef)(null);(0,x.useEffect)(()=>{if(s){f.current=document.activeElement instanceof HTMLElement?document.activeElement:null,(d.current?.querySelector(`a[href], button:not([disabled])`))?.focus({preventScroll:!0});return}f.current?.isConnected&&f.current.focus({preventScroll:!0}),f.current=null},[s]),(0,x.useEffect)(()=>{if(!s)return;let e=e=>{if(e.key===`Escape`){e.preventDefault(),c(!1);return}if(e.key!==`Tab`)return;let t=d.current?Array.from(d.current.querySelectorAll(`a[href], button:not([disabled])`)):[];if(t.length===0)return;let n=t[0],r=t[t.length-1];e.shiftKey&&document.activeElement===n?(e.preventDefault(),r.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n.focus())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[s]),(0,x.useEffect)(()=>{let e=()=>{window.innerWidth>720&&c(!1)};return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]);let p=e=>{c(!1),t(e)};return(0,J.jsxs)(`div`,{className:`app`,"data-view":e,"data-nav-open":s?`true`:`false`,children:[(0,J.jsxs)(`div`,{className:`scene`,"aria-hidden":`true`,children:[(0,J.jsxs)(`div`,{className:`lights`,children:[(0,J.jsx)(`div`,{className:`bloom l1`}),(0,J.jsx)(`div`,{className:`bloom l2`}),(0,J.jsx)(`div`,{className:`bloom l3`})]}),(0,J.jsx)(`div`,{className:`dimmer`}),(0,J.jsx)(`div`,{className:`noise`})]}),(0,J.jsx)(`button`,{ref:u,type:`button`,className:`nav-toggle`,"aria-label":`打开导航菜单`,"aria-controls":`console-sidebar`,"aria-expanded":s,onClick:()=>c(e=>!e),children:(0,J.jsx)(l,{size:20})}),(0,J.jsxs)(`aside`,{ref:d,className:`sidebar`,id:`console-sidebar`,"aria-label":`控制台导航`,children:[(0,J.jsxs)(`a`,{className:`sb-brand`,href:`/`,children:[(0,J.jsx)(Y,{size:26}),(0,J.jsx)(`span`,{children:`途关`}),(0,J.jsx)(`span`,{className:`brand-en`,children:`Waygate`}),(0,J.jsxs)(`span`,{className:`brand-ver`,children:[`v`,a??`1.6.21`]})]}),(0,J.jsx)(`div`,{className:`sb-group`,children:`工作台`}),rt.filter(e=>I.includes(e.route)).map(t=>(0,J.jsxs)(`button`,{type:`button`,className:`sb-item${e===t.route?` active`:``}`,onClick:()=>p(t.route),"aria-current":e===t.route?`page`:void 0,children:[t.icon,t.label]},t.route)),(0,J.jsx)(`div`,{className:`sb-spacer`}),(0,J.jsxs)(`div`,{className:`sb-tools`,children:[(0,J.jsx)(`span`,{className:`sb-tools-lb`,children:`外观`}),(0,J.jsx)(Qe,{})]}),(0,J.jsxs)(`div`,{className:`sb-account`,children:[(0,J.jsx)(`div`,{className:`avatar`,children:`管`}),(0,J.jsxs)(`div`,{className:`meta`,children:[(0,J.jsx)(`b`,{children:`管理员`}),(0,J.jsx)(`i`,{children:n?`会话有效 · ${ke(n)}到期`:`本机管理员`})]}),(0,J.jsx)(Ze,{content:`退出登录`,children:(0,J.jsx)(`button`,{type:`button`,className:`sb-logout`,onClick:r,"aria-label":`退出登录`,children:(0,J.jsx)(y,{size:16})})})]})]}),(0,J.jsx)(`div`,{className:`nav-backdrop`,"aria-hidden":`true`,onClick:()=>c(!1)}),(0,J.jsx)(`main`,{className:`main`,children:i})]})}var at={error:{icon:m},success:{icon:s},info:{icon:r},warn:{icon:m}};function ot({tone:e,children:t,actions:n}){let r=at[e].icon;return(0,J.jsxs)(`div`,{className:`banner banner-${e}`,role:e===`error`||e===`warn`?`alert`:`status`,children:[(0,J.jsx)(r,{className:`banner-ico`,size:15,"aria-hidden":`true`}),(0,J.jsx)(`div`,{className:`banner-body`,children:t}),n?(0,J.jsx)(`div`,{className:`banner-actions`,children:n}):null]})}function st(e){var t=e&&typeof e.querySelectorAll==`function`?e:document,n=document.documentElement,r={};function i(e,t){r[e]!==t&&(r[e]=t,n.style.setProperty(e,t))}var a=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches,o=!0,s=[`x`,`y`,`z`,`rx`,`ry`,`rz`,`fog`,`dim`],c={x:0,y:0,z:0,rx:0,ry:0,rz:0,fog:.18,dim:1},l={x:`px`,y:`px`,z:`px`,rx:`deg`,ry:`deg`,rz:`deg`},u={x:`--cam-x`,y:`--cam-y`,z:`--cam-z`,rx:`--cam-rx`,ry:`--cam-ry`,rz:`--cam-rz`,fog:`--fog`,dim:`--scene-dim`};function d(e){return function(){e|=0,e=e+1831565813|0;var t=Math.imul(e^e>>>15,1|e);return t=t+Math.imul(t^t>>>7,61|t)^t,((t^t>>>14)>>>0)/4294967296}}var f=[{sel:`.dust.d3`,count:14,min:.9,max:1.5,seed:20261004},{sel:`.dust.d2`,count:10,min:1.3,max:2,seed:77110203},{sel:`.dust.d1`,count:6,min:1.8,max:2.8,seed:31415926}];function p(){f.forEach(function(e){for(var n=t.querySelectorAll(e.sel),r=0;r<n.length;r+=1){n[r].innerHTML=``;for(var i=d(e.seed),a=document.createDocumentFragment(),o=0;o<e.count;o+=1){var s=document.createElement(`i`),c=e.min+i()*(e.max-e.min);s.style.left=(i()*100).toFixed(2)+`%`,s.style.top=(i()*100).toFixed(2)+`%`,s.style.width=c.toFixed(2)+`px`,s.style.height=c.toFixed(2)+`px`,s.style.animationDelay=(i()*3200).toFixed(0)+`ms`,a.appendChild(s)}n[r].appendChild(a)}})}var m=[];function h(e){var t=e.getBoundingClientRect();return t.top+window.pageYOffset+t.height/2}function g(){m=[].slice.call(t.querySelectorAll(`[data-cam]`)).map(function(e){var t={},n=e.getAttribute(`data-cam`);if(n)try{t=JSON.parse(n)}catch{console.warn(`[scene] data-cam 不是合法 JSON,已忽略:`,e,n),t={}}return{at:h(e),cam:t}}),m.sort(function(e,t){return e.at-t.at})}function _(e){return e<.5?2*e*e:1-(-2*e+2)**2/2}function v(e){if(!m.length)return Object.assign({},c);for(var t=0;t<m.length-1&&e>m[t+1].at;)t+=1;var n=m[t],r=m[t+1],i=r?e<=n.at?0:(e-n.at)/(r.at-n.at):1;i=Math.max(0,Math.min(1,i));for(var a=_(i),o={},l=0;l<s.length;l+=1){var u=s[l],d=n.cam[u]===void 0?c[u]:n.cam[u];o[u]=d+((r&&r.cam[u]!==void 0?r.cam[u]:d)-d)*a}return o}var y=.16,b=null,x=null,S=0,C=0;function w(e){for(var t=0;t<s.length;t+=1){var n=s[t],r=l[n]||``;i(u[n],e[n].toFixed(3)+r)}}function T(e){var t=S?Math.min((e-S)/1e3,.12):.016;S=e,b||=Object.assign({},x);for(var n=a?1:1-Math.exp(-t/y),r=!0,i=0;i<s.length;i+=1){var o=s[i],c=x[o]-b[o];b[o]+=c*n;var l=Math.max(.0015,Math.abs(x[o])*.0012);Math.abs(c)>l&&(r=!1)}if(w(b),r){b=Object.assign({},x),w(x),C=0,S=0;return}C=requestAnimationFrame(T)}function E(){C||=(S=0,requestAnimationFrame(T))}function D(){if(o){var e=document.documentElement,t=Math.max(1,e.scrollHeight-window.innerHeight);i(`--scroll-p`,(window.pageYOffset/t).toFixed(4)),x=v(window.pageYOffset+window.innerHeight/2),E()}}var O={tx:0,ty:0,x:0,y:0},k=0,A=0,ee=window.matchMedia(`(hover: hover) and (pointer: fine)`).matches;function j(){i(`--look-x`,O.x.toFixed(4)),i(`--look-y`,O.y.toFixed(4))}function M(e){var t=A?Math.min((e-A)/1e3,.12):.016;A=e;var n=1-Math.exp(-t/y);O.x+=(O.tx-O.x)*n,O.y+=(O.ty-O.y)*n,j(),Math.abs(O.tx-O.x)>8e-4||Math.abs(O.ty-O.y)>8e-4?k=requestAnimationFrame(M):(O.x=O.tx,O.y=O.ty,j(),k=0,A=0)}function N(e){document.hidden||(O.tx=(e.clientX/window.innerWidth-.5)*2,O.ty=(e.clientY/window.innerHeight-.5)*2,k||=(A=0,requestAnimationFrame(M)))}function P(){O.tx=0,O.ty=0,k||=(A=0,requestAnimationFrame(M))}function te(){!a&&ee&&(window.addEventListener(`pointermove`,N,{passive:!0}),document.addEventListener(`pointerleave`,P))}var F=null,I=null,L=null;function ne(){if(p(),g(),!m.length){n.setAttribute(`data-scene-ready`,`static`);return}D(),te();var e=!1;F=function(){e||(e=!0,requestAnimationFrame(function(){e=!1,D()}))},I=function(){o&&(g(),D())},L=function(){o&&(g(),D())},window.addEventListener(`scroll`,F,{passive:!0}),window.addEventListener(`resize`,I),window.addEventListener(`load`,L),document.fonts&&document.fonts.ready&&document.fonts.ready.then(function(){o&&(g(),D())}),n.setAttribute(`data-scene-ready`,`1`)}function R(){o=!1,F&&window.removeEventListener(`scroll`,F),I&&window.removeEventListener(`resize`,I),L&&window.removeEventListener(`load`,L),window.removeEventListener(`pointermove`,N),document.removeEventListener(`pointerleave`,P),C&&cancelAnimationFrame(C),k&&cancelAnimationFrame(k),C=0,k=0,[].slice.call(t.querySelectorAll(`.dust`)).forEach(function(e){e.innerHTML=``}),Object.keys(u).forEach(function(e){n.style.removeProperty(u[e])}),n.style.removeProperty(`--scroll-p`),n.style.removeProperty(`--look-x`),n.style.removeProperty(`--look-y`),r={},n.removeAttribute(`data-scene-ready`)}return ne(),R}var ct=e=>e,lt=[{tint:`var(--iris)`,a:`0deg`,r:`430px`,y:`-40px`,w:`300px`,h:`520px`,z:`-18deg`,x:`16deg`,o:`.95`,e:`.70`,hot:`.26`,dof:`0px`,dur:`15s`,delay:`0s`},{tint:`var(--accent-cyan)`,a:`72deg`,r:`448px`,y:`10px`,w:`255px`,h:`470px`,z:`12deg`,x:`-22deg`,o:`.82`,e:`.18`,hot:`.05`,dof:`0px`,dur:`19s`,delay:`3s`},{tint:`var(--brand-500)`,a:`144deg`,r:`424px`,y:`-60px`,w:`325px`,h:`560px`,z:`-24deg`,x:`19deg`,o:`.90`,e:`.52`,hot:`.18`,dof:`0px`,dur:`17s`,delay:`6.5s`},{tint:`var(--brand-400)`,a:`216deg`,r:`456px`,y:`20px`,w:`270px`,h:`490px`,z:`16deg`,x:`-14deg`,o:`.76`,e:`.14`,hot:`.04`,dof:`0px`,dur:`21s`,delay:`10s`},{tint:`var(--accent-blue)`,a:`288deg`,r:`436px`,y:`-30px`,w:`310px`,h:`535px`,z:`-14deg`,x:`24deg`,o:`.88`,e:`.30`,hot:`.12`,dof:`0px`,dur:`18s`,delay:`13.5s`},{tint:`var(--brand-500)`,a:`36deg`,r:`860px`,y:`40px`,w:`400px`,h:`560px`,z:`-22deg`,x:`26deg`,o:`.62`,e:`.20`,hot:`.06`,dof:`2.6px`,dur:`26s`,delay:`2s`,soft:!0},{tint:`var(--accent-cyan)`,a:`126deg`,r:`900px`,y:`-20px`,w:`360px`,h:`520px`,z:`18deg`,x:`-28deg`,o:`.52`,e:`.10`,hot:`.03`,dof:`2.6px`,dur:`30s`,delay:`9s`,soft:!0},{tint:`var(--iris)`,a:`216deg`,r:`840px`,y:`60px`,w:`440px`,h:`620px`,z:`-28deg`,x:`20deg`,o:`.58`,e:`.30`,hot:`.09`,dof:`2.6px`,dur:`24s`,delay:`15s`,soft:!0},{tint:`var(--brand-400)`,a:`306deg`,r:`890px`,y:`-10px`,w:`380px`,h:`540px`,z:`14deg`,x:`-24deg`,o:`.48`,e:`.08`,hot:`.03`,dof:`2.6px`,dur:`33s`,delay:`19s`,soft:!0}];function ut(){return(0,J.jsxs)(`div`,{className:`scene`,"aria-hidden":`true`,children:[(0,J.jsxs)(`div`,{className:`rig`,children:[(0,J.jsx)(`div`,{className:`tilt`,children:(0,J.jsx)(`div`,{className:`stage`,children:lt.map((e,t)=>(0,J.jsx)(`i`,{className:e.soft?`pl soft`:`pl`,style:ct({"--tint":e.tint,"--a":e.a,"--r":e.r,"--y":e.y,"--w":e.w,"--h":e.h,"--z":e.z,"--x":e.x,"--o":e.o,"--e":e.e,"--hot":e.hot,"--dof":e.dof,"--sheen-dur":e.dur,"--sheen-delay":e.delay})},t))})}),(0,J.jsx)(`div`,{className:`dust d3`}),(0,J.jsx)(`div`,{className:`dust d2`}),(0,J.jsx)(`div`,{className:`dust d1`})]}),(0,J.jsx)(`div`,{className:`core`}),(0,J.jsx)(`div`,{className:`nucleus`}),(0,J.jsx)(`div`,{className:`beam b1`}),(0,J.jsx)(`div`,{className:`beam b2`}),(0,J.jsx)(`div`,{className:`fog`}),(0,J.jsx)(`div`,{className:`dimmer`}),(0,J.jsx)(`div`,{className:`vignette`}),(0,J.jsx)(`div`,{className:`noise`})]})}function dt(){return(0,x.useEffect)(()=>st(document),[]),(0,J.jsx)(ut,{})}function ft({session:e,mockHint:r}){let[o,s]=(0,x.useState)(``),[c,l]=(0,x.useState)(!1),[u,d]=(0,x.useState)(!1),[f,p]=(0,x.useState)(null),m=(0,x.useRef)(null);return(0,x.useEffect)(()=>{let e=m.current;if(!e||!window.matchMedia(`(hover: hover) and (pointer: fine)`).matches)return;let t=t=>{let n=e.getBoundingClientRect();e.style.setProperty(`--mx`,`${t.clientX-n.left}px`),e.style.setProperty(`--my`,`${t.clientY-n.top}px`)};return e.addEventListener(`pointermove`,t),()=>e.removeEventListener(`pointermove`,t)},[]),(0,J.jsxs)(`div`,{className:`login-wrap landing`,children:[(0,J.jsx)(dt,{}),(0,J.jsxs)(`div`,{className:`login-card`,ref:m,children:[(0,J.jsx)(`span`,{className:`login-glow`,"aria-hidden":`true`}),(0,J.jsxs)(`div`,{className:`login-brand`,children:[(0,J.jsx)(Y,{size:30}),(0,J.jsx)(`span`,{className:`b-name`,children:`途关`}),(0,J.jsx)(`span`,{className:`b-en`,children:`Waygate`})]}),(0,J.jsx)(`h1`,{children:`登录控制台`}),(0,J.jsx)(`p`,{className:`sub`,children:`这是自用工具,只有一个管理口令。口令校验在服务端完成,前端不保存明文。`}),(0,J.jsxs)(`form`,{className:`login-form`,onSubmit:async t=>{if(t.preventDefault(),!u){d(!0),p(null);try{await e.login(o)}catch(e){p(e instanceof R?e:new R(String(e),0,0)),d(!1)}}},children:[(0,J.jsxs)(`div`,{className:`login-field`,children:[(0,J.jsx)(`label`,{htmlFor:`pw`,children:`管理口令`}),(0,J.jsxs)(`div`,{className:`login-input`,children:[(0,J.jsx)(t,{size:15,color:`var(--text-faint)`,"aria-hidden":!0}),(0,J.jsx)(`input`,{id:`pw`,type:c?`text`:`password`,value:o,autoFocus:!0,autoComplete:`current-password`,placeholder:`输入管理口令`,onChange:e=>s(e.target.value)}),(0,J.jsx)(`button`,{type:`button`,className:`login-eye`,"aria-label":c?`隐藏口令`:`显示口令`,onClick:()=>l(e=>!e),children:c?(0,J.jsx)(n,{size:15}):(0,J.jsx)(i,{size:15})})]})]}),f?(0,J.jsx)(ot,{tone:`error`,children:f.message}):null,(0,J.jsxs)(`button`,{type:`submit`,className:`btn btn-primary login-submit`,disabled:u||!o,children:[u?(0,J.jsx)(a,{size:16}):null,u?`正在验证…`:`进入控制台`]})]}),(0,J.jsx)(`p`,{className:`login-hint`,children:r?`当前为 Mock 模式(npm run dev:mock),口令固定为 ${r}。`:`口令首次启动时若未配置 RELAY_ADMIN_PASSWORD_HASH,会打印到服务端 stdout 一次。`})]})]})}function pt(){return(0,J.jsx)(`div`,{className:`login-wrap`,children:(0,J.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,alignItems:`center`,gap:16},children:[(0,J.jsx)(Y,{size:40}),(0,J.jsx)(`div`,{style:{fontSize:12.5,color:`var(--text-ghost)`},children:`正在确认会话…`})]})})}var mt=`modulepreload`,ht=function(e,t){return new URL(e,t).href},gt={},_t=function(e){return e.pathname.endsWith(`.css`)},$=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=o(t.map(t=>{t=ht(t,n);let r=s(t);if(r.href in gt)return;gt[r.href]=!0;let i=_t(r);if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((i?e.styles:e.all).has(r.href))return;let o=document.createElement(`link`);if(o.rel=i?`stylesheet`:mt,i||(o.as=`script`),o.crossOrigin=``,o.href=r.href,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),i)return new Promise((e,t)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>t(Error(`Unable to preload CSS for ${r}`)))})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},vt=(0,x.lazy)(()=>$(()=>import(`./LandingPage-DkcOcP6r.js`).then(e=>({default:e.LandingPage})),__vite__mapDeps([0,1,2,3]),import.meta.url)),yt=(0,x.lazy)(()=>$(()=>import(`./OverviewPage-CqDgOLe1.js`).then(e=>({default:e.OverviewPage})),__vite__mapDeps([4,1,5,6,7,8,9]),import.meta.url)),bt=(0,x.lazy)(()=>$(()=>import(`./UsagePage-lHPe750E.js`).then(e=>({default:e.UsagePage})),__vite__mapDeps([10,1,5,6,7,8,9]),import.meta.url)),xt=(0,x.lazy)(()=>$(()=>import(`./ClientsPage-CDRyiYxX.js`).then(e=>({default:e.ClientsPage})),__vite__mapDeps([11,1,5,12,13,6,7,14,15]),import.meta.url)),St=(0,x.lazy)(()=>$(()=>import(`./ApiKeysPage-DTazS32S.js`).then(e=>({default:e.ApiKeysPage})),__vite__mapDeps([16,1,5,12,13,6]),import.meta.url)),Ct=(0,x.lazy)(()=>$(()=>import(`./RequestsPage-DZNwUay0.js`).then(e=>({default:e.RequestsPage})),__vite__mapDeps([17,1,5,6,14,13,8]),import.meta.url)),wt=(0,x.lazy)(()=>$(()=>import(`./SettingsPage-Bzcu_JCB.js`).then(e=>({default:e.SettingsPage})),__vite__mapDeps([18,1,2,5,12,13,14,15]),import.meta.url));function Tt(){let[e,t]=(0,x.useState)(()=>window.location.pathname);return(0,x.useEffect)(()=>{let e=()=>t(window.location.pathname);return window.addEventListener(`popstate`,e),()=>window.removeEventListener(`popstate`,e)},[]),e}var Et=`Waygate — 控制台`;function Dt(){return(0,J.jsx)(`div`,{style:{display:`flex`,alignItems:`center`,justifyContent:`center`,minHeight:`50vh`,fontSize:12.5,color:`var(--text-ghost)`},children:`加载中…`})}function Ot(){let{route:e,navigate:t}=ne(),n=Ke();return(0,x.useEffect)(()=>{document.title=Et},[]),(0,x.useEffect)(()=>{window.location.hash||(window.location.hash=`#/overview`)},[]),n.status===`loading`?(0,J.jsx)(pt,{}):n.status===`anon`?(0,J.jsx)(ft,{session:n,mockHint:null}):(0,J.jsx)(it,{route:e,navigate:t,expiresAt:n.expiresAt,onLogout:()=>void n.logout(),children:(0,J.jsxs)(x.Suspense,{fallback:(0,J.jsx)(Dt,{}),children:[e===`overview`?(0,J.jsx)(yt,{navigate:t}):null,e===`usage`?(0,J.jsx)(bt,{}):null,e===`clients`?(0,J.jsx)(xt,{}):null,e===`keys`?(0,J.jsx)(St,{}):null,e===`requests`?(0,J.jsx)(Ct,{}):null,e===`settings`?(0,J.jsx)(wt,{}):null]})})}function kt(){let e=Tt(),t=C(e)===`console`;return(0,x.useEffect)(()=>{F()},[e]),t?(0,J.jsx)(Ot,{}):(0,J.jsx)(x.Suspense,{fallback:null,children:(0,J.jsx)(vt,{})})}var At=(0,x.createContext)(null),jt={error:{icon:m,defaultMs:8e3},warn:{icon:m,defaultMs:8e3},success:{icon:s,defaultMs:5e3},info:{icon:r,defaultMs:5e3}};function Mt({children:e}){let[t,n]=(0,x.useState)([]),r=(0,x.useRef)(1),i=(0,x.useCallback)(e=>{n(t=>t.filter(t=>t.id!==e))},[]),a=(0,x.useCallback)(e=>{let t=r.current++;return n(n=>[...n,{...e,id:t}].slice(-4)),t},[]),o=(0,x.useMemo)(()=>({push:a,dismiss:i}),[a,i]);return(0,J.jsxs)(At.Provider,{value:o,children:[e,typeof document<`u`?(0,Je.createPortal)((0,J.jsx)(`div`,{className:`toast-stack`,"aria-live":`polite`,"aria-atomic":`false`,children:t.map(e=>(0,J.jsx)(Nt,{item:e,onDismiss:i},e.id))}),document.body):null]})}function Nt({item:e,onDismiss:t}){let{icon:n,defaultMs:r}=jt[e.tone],i=e.durationMs??r,[a,o]=(0,x.useState)(!1),[s,c]=(0,x.useState)(i);return(0,x.useEffect)(()=>{if(a)return;let n=Date.now(),r=window.setInterval(()=>{let a=i-(Date.now()-n);a<=0?(window.clearInterval(r),t(e.id)):c(a)},100);return()=>window.clearInterval(r)},[a,i,e.id,t]),(0,J.jsxs)(`div`,{className:`toast toast-${e.tone}`,role:e.tone===`error`||e.tone===`warn`?`alert`:`status`,onMouseEnter:()=>o(!0),onMouseLeave:()=>o(!1),onFocus:()=>o(!0),onBlur:()=>o(!1),children:[(0,J.jsx)(n,{className:`toast-ico`,size:15,"aria-hidden":`true`}),(0,J.jsx)(`div`,{className:`toast-body`,children:e.message}),(0,J.jsx)(`button`,{type:`button`,className:`toast-close`,"aria-label":`关闭提示`,onClick:()=>t(e.id),children:`×`}),(0,J.jsx)(`span`,{className:`toast-progress${a?` paused`:``}`,style:{animationDuration:`${i}ms`},"aria-hidden":`true`})]})}function Pt(){return(0,x.useContext)(At)??{push:()=>0,dismiss:()=>{}}}w(),T(),F();for(let e of[`icon`,`apple-touch-icon`]){let t=document.createElement(`link`);t.rel=e,t.type=`image/svg+xml`,t.href=`/icon.svg?v=2`,document.head.appendChild(t)}var Ft=document.getElementById(`root`);if(!Ft)throw Error(`#root 未找到 —— index.html 被改坏了`);(0,S.createRoot)(Ft).render((0,J.jsx)(x.StrictMode,{children:(0,J.jsx)(Mt,{children:(0,J.jsx)(kt,{})})}));export{me as A,Le as C,he as D,Re as E,R as M,fe as O,Ie as S,Pe as T,be as _,Ze as a,Ee as b,q as c,xe as d,De as f,ve as g,we as h,nt as i,de as j,pe as k,Me as l,Oe as m,dt as n,Y as o,ye as p,ot as r,Ke as s,Pt as t,Ae as u,ke as v,Te as w,Ce as x,je as y};
@@ -56,9 +56,9 @@
56
56
  }
57
57
  })();
58
58
  </script>
59
- <script type="module" crossorigin src="./assets/index-C-pZwUmz.js"></script>
59
+ <script type="module" crossorigin src="./assets/index-BMxTTq4E.js"></script>
60
60
  <link rel="modulepreload" crossorigin href="./assets/vendor-befEYGHM.js">
61
- <link rel="stylesheet" crossorigin href="./assets/index-BzSTojlK.css">
61
+ <link rel="stylesheet" crossorigin href="./assets/index-BIKHWTRG.css">
62
62
  </head>
63
63
  <body>
64
64
  <div id="root"></div>
@@ -1,5 +0,0 @@
1
- import{D as e,J as t,K as n,S as r,_ as i,a,g as o,h as s,it as c,n as l,t as u,tt as d,z as f}from"./vendor-befEYGHM.js";import{A as p,D as m,M as h,a as g,c as _,g as v,j as y,m as b,r as x,v as S,y as C}from"./index-C-pZwUmz.js";import{a as w,c as T,l as E,n as D,o as O,r as k,s as A,t as j}from"./Select-u39f55hZ.js";import{t as M}from"./Modal-B-rIrvXS.js";import{n as N}from"./PageSkeleton-DG-Dj4_9.js";var P=c(),F=d(),I={live:`live`,off:`off`,exp:`exp`};function L({rows:e,clientByKey:t,providerNameById:n,pendingId:r,onToggle:i,onEdit:c,onDelete:u}){return(0,F.jsx)(`div`,{className:`tbl-scroll`,children:(0,F.jsxs)(`table`,{className:`tbl`,children:[(0,F.jsxs)(`caption`,{className:`sr-only`,children:[`API Key 列表,共 `,e.length,` 把密钥`]}),(0,F.jsx)(`thead`,{children:(0,F.jsxs)(`tr`,{children:[(0,F.jsx)(`th`,{scope:`col`,children:`名称 / 密钥`}),(0,F.jsx)(`th`,{scope:`col`,children:`绑定提供商`}),(0,F.jsx)(`th`,{scope:`col`,children:`权限范围`}),(0,F.jsx)(`th`,{scope:`col`,className:`r`,children:`近24h请求`}),(0,F.jsx)(`th`,{scope:`col`,className:`r`,children:`最后使用`}),(0,F.jsx)(`th`,{scope:`col`,children:`状态 / 到期`}),(0,F.jsx)(`th`,{scope:`col`,className:`r`,style:{width:184},children:`操作`})]})}),(0,F.jsx)(`tbody`,{children:e.map(e=>{let d=p(e.enabled,e.expiresAt),f=r===e.id,h=t?.get(e.id),_=e.clients??[];return(0,F.jsxs)(`tr`,{children:[(0,F.jsxs)(`td`,{children:[(0,F.jsx)(`div`,{className:`td-strong`,children:e.name}),(0,F.jsx)(`div`,{className:`td-sub td-mono`,children:e.hint})]}),(0,F.jsx)(`td`,{children:_.length>0?(0,F.jsx)(g,{content:`绑定提供商(路由优先级从高到低):\n${_.map(e=>n?.get(e)??e).join(`
2
- `)}`,children:(0,F.jsx)(`span`,{className:`key-bindings`,children:(()=>{let e=_[0],t=n?.get(e)??e,r=h?.name===t?h:void 0;return(0,F.jsxs)(F.Fragment,{children:[r?(0,F.jsx)(`a`,{href:`#/clients?clientId=${encodeURIComponent(r.clientId)}`,children:t}):t,_.length>1?(0,F.jsx)(`i`,{className:`kb-rank`,children:`优先`}):null]})})()})}):h?(0,F.jsx)(`a`,{href:`#/clients?clientId=${encodeURIComponent(h.clientId)}`,children:h.name}):(0,F.jsx)(`span`,{className:`td-sub`,children:`未绑定`})}),(0,F.jsx)(`td`,{children:C(e.scope)}),(0,F.jsx)(`td`,{className:`r td-mono`,children:v(e.requests24h)}),(0,F.jsx)(`td`,{className:`r td-mono`,children:S(e.lastSeenAt)}),(0,F.jsxs)(`td`,{children:[(0,F.jsxs)(`span`,{style:{display:`inline-flex`,alignItems:`center`,gap:8,whiteSpace:`nowrap`},children:[(0,F.jsx)(E,{tone:I[d],children:m[d]}),(0,F.jsx)(`span`,{className:`td-sub td-mono`,children:e.expiresAt?`至 ${b(e.expiresAt)}`:`永不过期`})]}),e.maxIps!==null||e.tokenQuota!==null?(0,F.jsxs)(`div`,{className:`td-sub td-mono`,style:{marginTop:2},children:[e.maxIps===null?null:`IP ${e.usedIps??0}/${e.maxIps}`,e.maxIps!==null&&e.tokenQuota!==null?` · `:null,e.tokenQuota===null?null:`${v(e.usedTokens??0)}/${v(e.tokenQuota)} tok`,e.ipWhitelist&&e.ipWhitelist.length>0?` · 白名单 ${e.ipWhitelist.length} 条`:null]}):null]}),(0,F.jsx)(`td`,{className:`r`,children:(0,F.jsxs)(`span`,{style:{display:`inline-flex`,gap:8,justifyContent:`flex-start`},children:[(0,F.jsx)(g,{content:`改名 / 改绑定 / 访问控制(不动权限范围,密钥与哈希不受影响)`,children:f?(0,F.jsx)(`span`,{tabIndex:0,children:(0,F.jsxs)(`button`,{type:`button`,className:`mini-pill`,disabled:f,onClick:()=>c(e),children:[(0,F.jsx)(l,{size:12}),`修改`]})}):(0,F.jsxs)(`button`,{type:`button`,className:`mini-pill`,onClick:()=>c(e),children:[(0,F.jsx)(l,{size:12}),`修改`]})}),(0,F.jsx)(g,{content:d===`exp`?`已过期,需重新创建`:e.enabled?`停用后立即失效`:`重新启用`,children:f||d===`exp`?(0,F.jsx)(`span`,{tabIndex:0,children:(0,F.jsxs)(`button`,{type:`button`,className:`mini-pill`,disabled:!0,onClick:()=>i(e),children:[e.enabled?(0,F.jsx)(o,{size:12}):(0,F.jsx)(s,{size:12}),e.enabled?`停用`:`启用`]})}):(0,F.jsxs)(`button`,{type:`button`,className:`mini-pill`,onClick:()=>i(e),children:[e.enabled?(0,F.jsx)(o,{size:12}):(0,F.jsx)(s,{size:12}),e.enabled?`停用`:`启用`]})}),(0,F.jsxs)(`button`,{type:`button`,className:`mini-pill danger`,disabled:f,onClick:()=>u(e),children:[(0,F.jsx)(a,{size:12}),`删除`]})]})})]},e.id)})})]})})}var R={ipText:``,maxIps:``,tokenQuota:``};function z(e){return{ipText:e.ipWhitelist.join(`
3
- `),maxIps:e.maxIps===null?``:String(e.maxIps),tokenQuota:e.tokenQuota===null?``:String(e.tokenQuota)}}function B(e){return e.ipText.trim()!==``||e.maxIps.trim()!==``||e.tokenQuota.trim()!==``}function V(e){let t=e.trim();if(!t)return null;let n=t.indexOf(`/`);if(n>0){let e=t.slice(0,n),r=t.slice(n+1);return!/^\d{1,2}$/.test(r)||Number(r)>32?`「${t}」的掩码位数只能是 0-32`:H(e)?null:`「${t}」CIDR 只支持 IPv4 网段`}return H(t)||t.includes(`:`)&&/^[0-9a-fA-F:]+$/.test(t)?null:`「${t}」不是合法的 IP 地址(支持 IPv4、IPv6、IPv4 CIDR)`}function H(e){let t=e.split(`.`);return t.length===4&&t.every(e=>/^\d{1,3}$/.test(e)&&Number(e)<=255)}function U(e){let t=e.ipText.split(/[\n,]+/).map(e=>e.trim()).filter(e=>e!==``);for(let e of t){let t=V(e);if(t)return{error:`IP 白名单:${t}`}}let n=null;if(e.maxIps.trim()!==``&&(n=Number(e.maxIps),!Number.isInteger(n)||n<1))return{error:`最大 IP 数必须是正整数(留空 = 不限)。`};let r=null;return e.tokenQuota.trim()!==``&&(r=Number(e.tokenQuota),!Number.isInteger(r)||r<1)?{error:`Token 配额必须是正整数(留空 = 不限)。`}:{ipWhitelist:t,maxIps:n,tokenQuota:r}}function W(e){let t=[],n=e.ipText.split(/[\n,]+/).map(e=>e.trim()).filter(e=>e!==``).length;return n>0&&t.push(`白名单 ${n} 条`),e.maxIps.trim()!==``&&t.push(`最大 ${e.maxIps.trim()} IP`),e.tokenQuota.trim()!==``&&t.push(`配额 ${Number(e.tokenQuota).toLocaleString()} tok`),t.length>0?t.join(` · `):`未限制`}function G({draft:e,onChange:t,defaultOpen:r=!1}){let[i,a]=(0,P.useState)(r||B(e));return(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsxs)(`button`,{type:`button`,className:`policy-toggle`,"aria-expanded":i,onClick:()=>a(e=>!e),children:[(0,F.jsx)(n,{size:14,"aria-hidden":!0}),(0,F.jsxs)(`span`,{children:[`访问控制`,i?``:`(可选,留空 = 不限)`]}),i?null:(0,F.jsx)(`span`,{className:`policy-sum`,children:W(e)})]}),i?(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`textarea`,{className:`field-input text`,style:{width:`100%`,minHeight:48,resize:`vertical`,fontFamily:`var(--font-mono)`,marginTop:8},value:e.ipText,placeholder:`IP 白名单,每行一个:
4
- 203.0.113.7
5
- 10.0.0.0/8`,onChange:n=>t({...e,ipText:n.target.value})}),(0,F.jsxs)(`div`,{style:{display:`flex`,gap:12,marginTop:8},children:[(0,F.jsxs)(`label`,{style:{flex:1,display:`flex`,flexDirection:`column`,gap:4},children:[(0,F.jsx)(`span`,{className:`ov-hint`,children:`最大 IP 数(留空 = 不限)`}),(0,F.jsx)(`input`,{className:`field-input text`,style:{width:`100%`},type:`number`,min:1,value:e.maxIps,placeholder:`如 3`,onChange:n=>t({...e,maxIps:n.target.value})})]}),(0,F.jsxs)(`label`,{style:{flex:1,display:`flex`,flexDirection:`column`,gap:4},children:[(0,F.jsx)(`span`,{className:`ov-hint`,children:`Token 配额(留空 = 不限)`}),(0,F.jsx)(`input`,{className:`field-input text`,style:{width:`100%`},type:`number`,min:1,value:e.tokenQuota,placeholder:`如 1000000`,onChange:n=>t({...e,tokenQuota:n.target.value})})]})]}),(0,F.jsxs)(`div`,{className:`ov-hint`,style:{marginTop:6},children:[`白名单只放行名单内来源;最大 IP 数挡密钥转播后的`,(0,F.jsx)(`b`,{children:`新增`}),`来源;配额按累计 tokens 软校验(最后一笔可超出)。`]})]}):null]})}var K=[{value:`all`,label:`全部模型`},{value:`family`,label:`仅某系`},{value:`tag`,label:`仅某标签`},{value:`models`,label:`指定模型`}],q=[`kimi`,`deepseek`,`glm`,`minimax`,`hy4`,`hy3`,`space`,`step`],J=[`限时免费`,`限时折扣`,`夜间折扣`,`订阅优先`];function Y({onClose:e,onCreated:t}){let[n,i]=(0,P.useState)(``),[a,o]=(0,P.useState)(`all`),[s,c]=(0,P.useState)(q[0]),[l,u]=(0,P.useState)(J[0]),[d,f]=(0,P.useState)([]),p=y(()=>_.catalog(),[],{cacheKey:`catalog`}),m=y(()=>_.providers(),[],{cacheKey:`providers`}),[g,v]=(0,P.useState)([]),[b,S]=(0,P.useState)(R),[C,w]=(0,P.useState)(!1),[T,E]=(0,P.useState)(null),[D,O]=(0,P.useState)(null),A=(p.data?.models??[]).filter(e=>e.enabled),N=e=>f(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e]),I=a===`all`?{type:`all`}:a===`family`?{type:`family`,value:s}:a===`tag`?{type:`tag`,value:l}:{type:`models`,value:d},L=a===`models`&&d.length===0,z=(m.data?.items??[]).map(e=>({value:e.id,label:e.active?`${e.name}(已启用)`:e.name})).sort((e,t)=>e.label.localeCompare(t.label,`zh-Hans-CN`)),B=e=>v(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e]),V=(e,t)=>v(n=>{let r=[...n],i=e+t;return i<0||i>=r.length?n:([r[e],r[i]]=[r[i],r[e]],r)}),H=!!n.trim()&&!C&&!L;return D?(0,F.jsxs)(M,{title:`密钥已创建`,onClose:e,footer:(0,F.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:e,children:`我已保存,关闭`}),children:[(0,F.jsxs)(`div`,{className:`ov-lose`,children:[(0,F.jsx)(`b`,{children:`会失去什么:`}),D.warning]}),(0,F.jsx)(X,{value:D.key}),(0,F.jsxs)(`div`,{className:`ov-hint`,children:[`服务端只保存哈希。这串明文不会再出现,丢失只能删除重建。 下游可用 `,(0,F.jsx)(`span`,{className:`code-chip`,children:`GET /v1/usage`}),`(带这把密钥)自查配额余量与有效期 —— 纯只读,不产生调用。`]})]}):(0,F.jsxs)(M,{title:`新建密钥`,onClose:e,footer:(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:e,children:`取消`}),(0,F.jsxs)(`button`,{type:`submit`,form:`create-key-form`,className:`btn btn-primary btn-sm`,disabled:!H,children:[C?(0,F.jsx)(r,{size:14}):null,C?`创建中…`:`创建密钥`]})]}),children:[(0,F.jsx)(`p`,{className:`ov-sub`,children:`给一个提供商或用途起名。绑定提供商名后,识别规则第 2 条「密钥归属」就能直接命中。`}),(0,F.jsxs)(`form`,{id:`create-key-form`,onSubmit:async e=>{if(e.preventDefault(),!H)return;let r=U(b);if(`error`in r){E(new h(r.error,400,0));return}w(!0),E(null);try{let e=await _.createKey({name:n.trim(),scope:I,clients:g,client:g[0]??null,ipWhitelist:r.ipWhitelist,maxIps:r.maxIps,tokenQuota:r.tokenQuota});O(e),t()}catch(e){E(e instanceof h?e:new h(String(e),0,0))}finally{w(!1)}},style:{display:`flex`,flexDirection:`column`,gap:16},children:[(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsx)(`label`,{htmlFor:`ck-name`,children:`密钥名称`}),(0,F.jsx)(`input`,{id:`ck-name`,className:`field-input text`,style:{width:`100%`},value:n,autoFocus:!0,placeholder:`例如:Cursor · 笔记本`,onChange:e=>i(e.target.value)})]}),(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsx)(`label`,{children:`权限范围`}),(0,F.jsx)(j,{value:a,options:K,onChange:o,width:180}),a===`family`?(0,F.jsx)(j,{value:s,options:q.map(e=>({value:e,label:`${e} 系`})),onChange:c,width:180}):null,a===`tag`?(0,F.jsx)(j,{value:l,options:J.map(e=>({value:e,label:e})),onChange:u,width:180}):null,a===`models`?(0,F.jsx)(`div`,{className:`scope-models`,children:p.loading?(0,F.jsx)(`div`,{className:`ov-hint`,children:`正在读取模型清单…`}):A.length===0?(0,F.jsx)(`div`,{className:`ov-hint`,children:`模型清单为空。先去「提供商」面板执行一次「获取模型」。`}):(0,F.jsxs)(F.Fragment,{children:[(0,F.jsxs)(`div`,{className:`ov-hint`,children:[`已选 `,d.length,` 个`,L?` —— 至少选一个才能创建`:``]}),(0,F.jsx)(`div`,{className:`scope-models-list`,children:A.map(e=>(0,F.jsxs)(`label`,{className:`scope-model`,children:[(0,F.jsx)(`input`,{type:`checkbox`,checked:d.includes(e.id),onChange:()=>N(e.id)}),(0,F.jsx)(`span`,{className:`code-chip`,children:e.id}),(0,F.jsx)(`i`,{children:e.displayName})]},e.id))})]})}):null]}),(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsx)(`label`,{children:`绑定提供商(可多选,可排序)`}),m.loading?(0,F.jsx)(`div`,{className:`ov-hint`,children:`正在读取提供商…`}):z.length===0?(0,F.jsx)(`div`,{className:`ov-hint`,children:`还没有登记任何提供商 —— 先去「提供商管理」页登记。`}):(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`div`,{className:`pick-list`,children:z.map(e=>{let t=g.includes(e.value);return(0,F.jsxs)(`label`,{className:`pick-row${t?` on`:``}`,children:[(0,F.jsx)(`input`,{type:`checkbox`,checked:t,onChange:()=>B(e.value)}),(0,F.jsx)(`span`,{className:`pick-name`,children:e.label})]},e.value)})}),(0,F.jsxs)(`div`,{className:`picked-head`,children:[(0,F.jsxs)(`span`,{children:[`已选 `,g.length,` 个`]}),g.length>1?(0,F.jsx)(`span`,{className:`picked-tip`,children:`用 ↑↓ 调整优先级`}):null]}),g.length>0?(0,F.jsx)(`div`,{className:`picked-list`,children:g.map((e,t)=>(0,F.jsxs)(`div`,{className:`picked-item`,children:[(0,F.jsx)(`span`,{className:`picked-rank`,children:t+1}),(0,F.jsx)(`span`,{className:`picked-name`,children:e}),(0,F.jsxs)(`span`,{className:`picked-actions`,children:[(0,F.jsx)(`button`,{type:`button`,className:`pick-mv`,disabled:t===0,onClick:()=>V(t,-1),"aria-label":`上移`,children:`↑`}),(0,F.jsx)(`button`,{type:`button`,className:`pick-mv`,disabled:t===g.length-1,onClick:()=>V(t,1),"aria-label":`下移`,children:`↓`}),(0,F.jsx)(`button`,{type:`button`,className:`pick-rm`,onClick:()=>B(e),"aria-label":`移除`,children:`×`})]})]},e))}):null,(0,F.jsx)(`div`,{className:`ov-hint`,children:`勾选后这个 Key 的请求会归到对应提供商名下;第 1 位是首选(用量归因与后续路由都优先用它)。`})]})]}),(0,F.jsx)(G,{draft:b,onChange:S}),T?(0,F.jsx)(x,{tone:`error`,children:k(T)}):null]})]})}function X({value:e}){let[n,r]=(0,P.useState)(!1),i=async()=>{try{await navigator.clipboard.writeText(e),r(!0),setTimeout(()=>r(!1),2e3)}catch{r(!1)}};return(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsx)(`label`,{children:`完整密钥(只此一次)`}),(0,F.jsxs)(`div`,{className:`key-plain`,children:[(0,F.jsx)(`span`,{style:{flex:1},children:e}),(0,F.jsxs)(`button`,{type:`button`,className:`copy`,"aria-label":n?`已复制完整密钥`:`复制完整密钥`,onClick:()=>void i(),children:[n?(0,F.jsx)(t,{size:13}):(0,F.jsx)(f,{size:13}),n?`已复制`:`复制`]})]})]})}function Z({row:e,onClose:t,onSaved:n}){let[i,a]=(0,P.useState)(e.name),[o,s]=(0,P.useState)(e.clients??(e.client?[e.client]:[])),[c,l]=(0,P.useState)(()=>z({ipWhitelist:e.ipWhitelist??[],maxIps:e.maxIps??null,tokenQuota:e.tokenQuota??null})),[u,d]=(0,P.useState)(!1),[f,p]=(0,P.useState)(null),m=y(()=>_.providers(),[],{cacheKey:`providers`}),g=(()=>{let e=(m.data?.items??[]).map(e=>({value:e.id,label:e.active?`${e.name}(已启用)`:e.name})).sort((e,t)=>e.label.localeCompare(t.label,`zh-Hans-CN`));for(let t of o)e.some(e=>e.value===t)||e.push({value:t,label:`${t}(已删除,当前不在列表)`});return e})(),v=e=>s(t=>t.includes(e)?t.filter(t=>t!==e):[...t,e]),b=(e,t)=>s(n=>{let r=[...n],i=e+t;return i<0||i>=r.length?n:([r[e],r[i]]=[r[i],r[e]],r)}),S=i.trim(),C=S!==e.name,w=e.clients??(e.client?[e.client]:[]),T=JSON.stringify(o)!==JSON.stringify(w),E=U(c),D=!(`error`in E)&&(JSON.stringify(E.ipWhitelist)!==JSON.stringify(e.ipWhitelist??[])||E.maxIps!==(e.maxIps??null)||E.tokenQuota!==(e.tokenQuota??null)),O=!!S&&(C||T||D)&&!u;return(0,F.jsxs)(M,{title:`修改密钥`,onClose:t,footer:(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:t,children:`取消`}),(0,F.jsxs)(`button`,{type:`submit`,form:`edit-key-form`,className:`btn btn-primary btn-sm`,disabled:!O,children:[u?(0,F.jsx)(r,{size:14}):null,u?`保存中…`:`保存`]})]}),children:[(0,F.jsx)(`p`,{className:`ov-sub`,children:`改的是「叫什么」和「绑哪家」,不动作废 —— 这把密钥的明文和哈希都不受影响,已接入的客户端无需更换。`}),(0,F.jsxs)(`form`,{id:`edit-key-form`,onSubmit:async r=>{if(r.preventDefault(),O){if(`error`in E){p(new h(E.error,400,0));return}d(!0),p(null);try{let r={};C&&(r.name=S),T&&(r.clients=o),D&&(r.ipWhitelist=E.ipWhitelist,r.maxIps=E.maxIps,r.tokenQuota=E.tokenQuota),await _.patchKey(e.id,r),n(),t()}catch(e){p(e instanceof h?e:new h(String(e),0,0))}finally{d(!1)}}},style:{display:`flex`,flexDirection:`column`,gap:16},children:[(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsx)(`label`,{htmlFor:`ek-name`,children:`密钥名称`}),(0,F.jsx)(`input`,{id:`ek-name`,className:`field-input text`,style:{width:`100%`},value:i,autoFocus:!0,onChange:e=>a(e.target.value)}),(0,F.jsxs)(`div`,{className:`ov-hint`,children:[`当前:`,e.name,` · `,e.hint]})]}),(0,F.jsxs)(`div`,{className:`ov-field`,children:[(0,F.jsx)(`label`,{children:`绑定提供商(可多选,可排序)`}),m.loading?(0,F.jsx)(`div`,{className:`ov-hint`,children:`正在读取提供商…`}):g.length===0?(0,F.jsx)(`div`,{className:`ov-hint`,children:`还没有登记任何提供商 —— 先去「提供商管理」页登记。`}):(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`div`,{className:`pick-list`,children:g.map(e=>{let t=o.includes(e.value);return(0,F.jsxs)(`label`,{className:`pick-row${t?` on`:``}`,children:[(0,F.jsx)(`input`,{type:`checkbox`,checked:t,onChange:()=>v(e.value)}),(0,F.jsx)(`span`,{className:`pick-name`,children:e.label})]},e.value)})}),(0,F.jsxs)(`div`,{className:`picked-head`,children:[(0,F.jsxs)(`span`,{children:[`已选 `,o.length,` 个`]}),o.length>1?(0,F.jsx)(`span`,{className:`picked-tip`,children:`用 ↑↓ 调整优先级`}):null]}),o.length>0?(0,F.jsx)(`div`,{className:`picked-list`,children:o.map((e,t)=>(0,F.jsxs)(`div`,{className:`picked-item`,children:[(0,F.jsx)(`span`,{className:`picked-rank`,children:t+1}),(0,F.jsx)(`span`,{className:`picked-name`,children:e}),(0,F.jsxs)(`span`,{className:`picked-actions`,children:[(0,F.jsx)(`button`,{type:`button`,className:`pick-mv`,disabled:t===0,onClick:()=>b(t,-1),"aria-label":`上移`,children:`↑`}),(0,F.jsx)(`button`,{type:`button`,className:`pick-mv`,disabled:t===o.length-1,onClick:()=>b(t,1),"aria-label":`下移`,children:`↓`}),(0,F.jsx)(`button`,{type:`button`,className:`pick-rm`,onClick:()=>v(e),"aria-label":`移除`,children:`×`})]})]},e))}):null,(0,F.jsx)(`div`,{className:`ov-hint`,children:`全部取消即解绑。绑定只影响用量归因(第 1 位是首选),不改变权限范围。`})]})]}),(0,F.jsx)(G,{draft:c,onChange:l}),(e.maxIps!==null||e.tokenQuota!==null)&&(0,F.jsxs)(`div`,{className:`ov-hint`,children:[`当前累计:`,e.maxIps===null?``:`${e.usedIps??0} / ${e.maxIps} 个来源 IP`,e.maxIps!==null&&e.tokenQuota!==null?` · `:``,e.tokenQuota===null?``:`${(e.usedTokens??0).toLocaleString()} / ${e.tokenQuota.toLocaleString()} tokens`]}),(0,F.jsxs)(`div`,{className:`ov-hint`,children:[`权限范围(`,(0,F.jsx)(`b`,{children:`不可改`}),`):它是授权面,要换范围删除后重建 —— 明文只显示一次,本就该重新分发。`]}),f?(0,F.jsx)(x,{tone:`error`,children:k(f)}):null]})]})}function Q(){return new URLSearchParams(window.location.hash.split(`?`)[1]??``).get(`clientId`)||null}function $(){let t=y(()=>_.keys(),[],{cacheKey:`keys`}),n=y(()=>_.clients(`30d`),[],{cacheKey:`clients:30d`}),a=y(()=>_.providers(),[],{cacheKey:`providers`}),o=new Map((a.data?.items??[]).map(e=>[e.id,e.name])),[s,c]=(0,P.useState)(Q),[l,d]=(0,P.useState)(!1),[f,m]=(0,P.useState)(null),[g,b]=(0,P.useState)(null),[S,C]=(0,P.useState)(null),[E,j]=(0,P.useState)(null);(0,P.useEffect)(()=>{let e=()=>c(Q());return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]);let I=(0,P.useMemo)(()=>{let e=new Map;for(let t of n.data?.items??[]){let n={clientId:t.clientId,name:t.client};e.set(t.clientId,n);for(let r of t.boundKeyIds)e.set(r,n)}return e},[n.data]),R=n.data?.items.find(e=>e.clientId===s),z=t.data??[],B=s?z.filter(e=>e.id===s||R?.boundKeyIds.includes(e.id)):z,V=!!(s&&n.initial&&n.loading),H={total:B.length,live:0,off:0,exp:0};for(let e of B)H[p(e.enabled,e.expiresAt)]+=1;let U=e=>t.data&&!V?v(e):`--`,W=()=>{t.reload(),n.reload()},G=async e=>{if(!f){m(e.id),j(null);try{await _.patchKey(e.id,{enabled:!e.enabled}),t.reload()}catch(e){j(e instanceof h?e:new h(String(e),0,0))}finally{m(null)}}},K=async()=>{if(!S||f)return;let e=S;m(e.id),j(null);try{await _.deleteKey(e.id),C(null),W()}catch(e){j(e instanceof h?e:new h(String(e),0,0)),C(null)}finally{m(null)}},q=()=>{window.location.hash=`#/keys`,c(null)};return(0,F.jsxs)(`div`,{className:`view on`,children:[(0,F.jsx)(A,{title:`API Keys`,actions:(0,F.jsxs)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:()=>d(!0),children:[(0,F.jsx)(i,{size:14}),`新建API Key`]})}),(0,F.jsx)(`div`,{className:`view-body stack`,children:t.initial&&t.loading?(0,F.jsx)(N,{}):(0,F.jsxs)(F.Fragment,{children:[E?(0,F.jsx)(x,{tone:`error`,children:k(E)}):null,(0,F.jsx)(O,{items:[{label:`密钥总数`,value:U(H.total),detail:s?`客户端筛选下 ${U(H.total)} 把`:`全部密钥`},{label:`启用`,value:U(H.live),tone:`live`,detail:`未过期且启用`},{label:`停用`,value:U(H.off),detail:`已停用且未过期`},{label:`过期`,value:U(H.exp),tone:`amber`,detail:`expiresAt 已过`}]}),s?(0,F.jsxs)(`div`,{className:`note`,children:[(0,F.jsxs)(`span`,{children:[`关联客户端:`,R?(0,F.jsx)(`a`,{href:`#/clients?clientId=${encodeURIComponent(R.clientId)}`,children:R.client}):`未绑定`]}),(0,F.jsxs)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:q,children:[(0,F.jsx)(u,{size:14}),`清除筛选`]})]}):null,n.error?(0,F.jsx)(D,{kind:`error`,title:`客户端关联数据没取到`,detail:k(n.error),onRetry:n.reload}):null,(0,F.jsxs)(w,{title:`密钥列表`,aside:(0,F.jsxs)(T,{children:[U(B.length),` 个 · 明文仅在创建时显示一次`]}),children:[t.error?(0,F.jsx)(D,{kind:`error`,title:`密钥数据没取到`,detail:k(t.error),onRetry:t.reload}):V?(0,F.jsx)(D,{kind:`loading`,title:`正在读取客户端关联…`}):B.length===0?s?(0,F.jsx)(D,{kind:`empty`,title:`没有关联的密钥`,children:(0,F.jsxs)(`button`,{type:`button`,className:`btn btn-quiet btn-sm`,onClick:q,children:[(0,F.jsx)(u,{size:14}),`清除筛选`]})}):(0,F.jsx)(D,{kind:`empty`,title:`还没有任何密钥`,detail:`没有密钥时 /v1/* 会拒绝所有请求。`,children:(0,F.jsxs)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:()=>d(!0),children:[(0,F.jsx)(e,{size:14}),`创建第一把密钥`]})}):(0,F.jsx)(L,{rows:B,clientByKey:I,providerNameById:o,pendingId:f,onToggle:e=>void G(e),onEdit:b,onDelete:C}),(0,F.jsxs)(`div`,{className:`footer-note`,children:[`完整密钥只在创建时显示一次,服务端只保存哈希;停用后立即失效,可随时重新启用。改名与改绑定不会动作废 —— 已接入的客户端不受影响。`,(0,F.jsx)(`br`,{}),`上面三格互斥、可相加等于总数:`,(0,F.jsx)(`b`,{children:`过期优先于启停判断`}),`(expiresAt 已过即归过期,不再看启用状态),所以一把同时「启用」又「过期」的密钥只会计进「过期」。`]})]})]})}),l?(0,F.jsx)(Y,{onClose:()=>d(!1),onCreated:W}):null,g?(0,F.jsx)(Z,{row:g,onClose:()=>b(null),onSaved:W}):null,S?(0,F.jsx)(M,{title:`删除这把密钥?`,onClose:()=>{f||C(null)},footer:(0,F.jsxs)(F.Fragment,{children:[(0,F.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:!!f,onClick:()=>C(null),children:`取消(保留)`}),(0,F.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm`,disabled:!!f,onClick:()=>void K(),children:[f?(0,F.jsx)(r,{size:14,className:`spin`}):null,f?`删除中…`:`确认删除`]})]}),children:(0,F.jsxs)(`div`,{className:`ov-lose`,children:[(0,F.jsx)(`b`,{children:`会失去什么:`}),`密钥「`,S.name,`」(`,S.hint,`)立即失效,任何还在用它的客户端会立刻收到 401, 需要重新建密钥并逐个替换。此操作不可撤销。`]})}):null]})}export{$ as ApiKeysPage};