ellm-proxy 0.0.6 → 0.0.7
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.
- package/bin/commands/credentials.js +100 -0
- package/bin/ellm-proxy.js +4 -1
- package/dist/server.js +108 -2
- package/dist/web-ui/assets/DashboardView-BCwrFrE2.js +1 -0
- package/dist/web-ui/assets/{LayoutView-C9phf7in.js → LayoutView-BePJfgia.js} +1 -1
- package/dist/web-ui/assets/LoginView-Dp7NmXtf.js +1 -0
- package/dist/web-ui/assets/{LogsView-BlXITEJH.js → LogsView-Dyy_zkgg.js} +2 -2
- package/dist/web-ui/assets/{ProcessView-Bgf7-MLQ.js → ProcessView-CpPpMtFg.js} +1 -1
- package/dist/web-ui/assets/{ProvidersView-f8aZkMdw.js → ProvidersView-CYFs76wJ.js} +2 -2
- package/dist/web-ui/assets/SettingsView-mPcaVAD2.js +1 -0
- package/dist/web-ui/assets/SetupView-DX6S_KpK.js +1 -0
- package/dist/web-ui/assets/SetupView-kPJXJ7dX.css +1 -0
- package/dist/web-ui/assets/config-CRWaUFQc.js +1 -0
- package/dist/web-ui/assets/{index-GohB4JDa.js → index-X5PdkJlA.js} +28 -28
- package/dist/web-ui/assets/{providers-Djtdy2tv.js → providers-H_9x778D.js} +1 -1
- package/dist/web-ui/assets/{useToast-C0UMTbkx.js → useToast-MtbkGJiM.js} +1 -1
- package/dist/web-ui/index.html +1 -1
- package/ellm.config.example.json +2 -0
- package/manager/index.js +1 -1
- package/package.json +1 -1
- package/utils/updater.js +31 -8
- package/dist/web-ui/assets/DashboardView-C3Hw-HpG.js +0 -1
- package/dist/web-ui/assets/LoginView-es6pSPgt.js +0 -1
- package/dist/web-ui/assets/SettingsView-GvAA2vLp.js +0 -1
- package/dist/web-ui/assets/config-Cs3_z63C.js +0 -1
- package/dist/web-ui/assets/useApi-D_iJ2Mca.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{N as Kn,s as Mt,v as He,x as cr,y as Lt,z as jo,
|
|
1
|
+
import{N as Kn,s as Mt,v as He,x as cr,y as Lt,z as jo,B as Ts,C as ia,D as Os,G as aa,H as Is,I as Kt,J as sa,K as xi,L as Ns,M as Cs,O as As,P as xs,Q as Ps,R as Xr,S as Ds,T as Kr,U as Rs,V as Ms,W as Ls,X as ws,Y as gn,A as Yt,d as Jt,a as J,o as te,c as Me,w as M,f as K,t as Te,e as Be,F as Bo,q as ko,Z as fo,$ as Vs,k as q,h as ae,i as tt,g as P,a0 as Fs,l as Ht,r as Pe,_ as cn,a1 as Xo,a2 as Rt,p as la,a3 as $s,E as Ao,a4 as Us,a5 as js,a6 as Bs,a7 as ks}from"./index-X5PdkJlA.js";import{u as un}from"./useToast-MtbkGJiM.js";import{u as Ko}from"./providers-H_9x778D.js";import"./config-CRWaUFQc.js";var yr={exports:{}},po={exports:{}},ho={};/**
|
|
2
2
|
* @vue/compiler-core v3.5.42
|
|
3
3
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
4
4
|
* @license MIT
|
|
@@ -28,4 +28,4 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
28
28
|
`)&&(O="(?: "+O+")",j=" "+j,L++),S=new RegExp("^(?:"+O+")",w)),m&&(S=new RegExp("^"+O+"$(?!\\s)",w)),p&&(I=y.lastIndex),C=c.call(B?S:y,j),B?C?(C.input=C.input.slice(L),C[0]=C[0].slice(L),C.index=y.lastIndex,y.lastIndex+=C[0].length):y.lastIndex=0:p&&C&&(y.lastIndex=y.global?C.index+C[0].length:I),m&&C&&C.length>1&&f.call(C[0],S,function(){for(A=1;A<arguments.length-2;A++)arguments[A]===void 0&&(C[A]=void 0)}),C}),i.exports=u}),"94ca":(function(i,a,r){var s=r("d039"),l=/#|\.prototype\./,c=function(m,h){var v=u[f(m)];return v==d?!0:v==p?!1:typeof h=="function"?s(h):!!h},f=c.normalize=function(m){return String(m).replace(l,".").toLowerCase()},u=c.data={},p=c.NATIVE="N",d=c.POLYFILL="P";i.exports=c}),"99af":(function(i,a,r){var s=r("23e7"),l=r("d039"),c=r("e8b5"),f=r("861d"),u=r("7b0b"),p=r("50c4"),d=r("8418"),m=r("65f0"),h=r("1dde"),v=r("b622"),g=r("2d00"),y=v("isConcatSpreadable"),I=9007199254740991,S="Maximum allowed index exceeded",C=g>=51||!l(function(){var O=[];return O[y]=!1,O.concat()[0]!==O}),A=h("concat"),B=function(O){if(!f(O))return!1;var L=O[y];return L!==void 0?!!L:c(O)},w=!C||!A;s({target:"Array",proto:!0,forced:w},{concat:function(L){var j=u(this),R=m(j,0),E=0,N,V,F,U,z;for(N=-1,F=arguments.length;N<F;N++)if(z=N===-1?j:arguments[N],B(z)){if(U=p(z.length),E+U>I)throw TypeError(S);for(V=0;V<U;V++,E++)V in z&&d(R,E,z[V])}else{if(E>=I)throw TypeError(S);d(R,E++,z)}return R.length=E,R}})}),"9bdd":(function(i,a,r){var s=r("825a");i.exports=function(l,c,f,u){try{return u?c(s(f)[0],f[1]):c(f)}catch(d){var p=l.return;throw p!==void 0&&s(p.call(l)),d}}}),"9bf2":(function(i,a,r){var s=r("83ab"),l=r("0cfb"),c=r("825a"),f=r("c04e"),u=Object.defineProperty;a.f=s?u:function(d,m,h){if(c(d),m=f(m,!0),c(h),l)try{return u(d,m,h)}catch{}if("get"in h||"set"in h)throw TypeError("Accessors not supported");return"value"in h&&(d[m]=h.value),d}}),"9ed3":(function(i,a,r){var s=r("ae93").IteratorPrototype,l=r("7c73"),c=r("5c6c"),f=r("d44e"),u=r("3f8c"),p=function(){return this};i.exports=function(d,m,h){var v=m+" Iterator";return d.prototype=l(s,{next:c(1,h)}),f(d,v,!1,!0),u[v]=p,d}}),"9f7f":(function(i,a,r){var s=r("d039");function l(c,f){return RegExp(c,f)}a.UNSUPPORTED_Y=s(function(){var c=l("a","y");return c.lastIndex=2,c.exec("abcd")!=null}),a.BROKEN_CARET=s(function(){var c=l("^r","gy");return c.lastIndex=2,c.exec("str")!=null})}),a2bf:(function(i,a,r){var s=r("e8b5"),l=r("50c4"),c=r("0366"),f=function(u,p,d,m,h,v,g,y){for(var I=h,S=0,C=g?c(g,y,3):!1,A;S<m;){if(S in d){if(A=C?C(d[S],S,p):d[S],v>0&&s(A))I=f(u,p,A,l(A.length),I,v-1)-1;else{if(I>=9007199254740991)throw TypeError("Exceed the acceptable array length");u[I]=A}I++}S++}return I};i.exports=f}),a352:(function(i,a){i.exports=o}),a434:(function(i,a,r){var s=r("23e7"),l=r("23cb"),c=r("a691"),f=r("50c4"),u=r("7b0b"),p=r("65f0"),d=r("8418"),m=r("1dde"),h=r("ae40"),v=m("splice"),g=h("splice",{ACCESSORS:!0,0:0,1:2}),y=Math.max,I=Math.min,S=9007199254740991,C="Maximum allowed length exceeded";s({target:"Array",proto:!0,forced:!v||!g},{splice:function(B,w){var O=u(this),L=f(O.length),j=l(B,L),R=arguments.length,E,N,V,F,U,z;if(R===0?E=N=0:R===1?(E=0,N=L-j):(E=R-2,N=I(y(c(w),0),L-j)),L+E-N>S)throw TypeError(C);for(V=p(O,N),F=0;F<N;F++)U=j+F,U in O&&d(V,F,O[U]);if(V.length=N,E<N){for(F=j;F<L-N;F++)U=F+N,z=F+E,U in O?O[z]=O[U]:delete O[z];for(F=L;F>L-N+E;F--)delete O[F-1]}else if(E>N)for(F=L-N;F>j;F--)U=F+N-1,z=F+E-1,U in O?O[z]=O[U]:delete O[z];for(F=0;F<E;F++)O[F+j]=arguments[F+2];return O.length=L-N+E,V}})}),a4d3:(function(i,a,r){var s=r("23e7"),l=r("da84"),c=r("d066"),f=r("c430"),u=r("83ab"),p=r("4930"),d=r("fdbf"),m=r("d039"),h=r("5135"),v=r("e8b5"),g=r("861d"),y=r("825a"),I=r("7b0b"),S=r("fc6a"),C=r("c04e"),A=r("5c6c"),B=r("7c73"),w=r("df75"),O=r("241c"),L=r("057f"),j=r("7418"),R=r("06cf"),E=r("9bf2"),N=r("d1e7"),V=r("9112"),F=r("6eeb"),U=r("5692"),z=r("f772"),ce=r("d012"),Se=r("90e3"),ge=r("b622"),Ee=r("e538"),Ae=r("746f"),X=r("d44e"),D=r("69f3"),ue=r("b727").forEach,Y=z("hidden"),Oe="Symbol",be="prototype",Je=ge("toPrimitive"),Le=D.set,we=D.getterFor(Oe),Ie=Object[be],Fe=l.Symbol,vt=c("JSON","stringify"),ne=R.f,re=E.f,xt=L.f,co=N.f,St=U("symbols"),Ut=U("op-symbols"),fn=U("string-to-symbol-registry"),Pn=U("symbol-to-string-registry"),Dn=U("wks"),Rn=l.QObject,Mn=!Rn||!Rn[be]||!Rn[be].findChild,Ln=u&&m(function(){return B(re({},"a",{get:function(){return re(this,"a",{value:7}).a}})).a!=7})?function(ee,W,Q){var he=ne(Ie,W);he&&delete Ie[W],re(ee,W,Q),he&&ee!==Ie&&re(Ie,W,he)}:re,wn=function(ee,W){var Q=St[ee]=B(Fe[be]);return Le(Q,{type:Oe,tag:ee,description:W}),u||(Q.description=W),Q},T=d?function(ee){return typeof ee=="symbol"}:function(ee){return Object(ee)instanceof Fe},b=function(W,Q,he){W===Ie&&b(Ut,Q,he),y(W);var me=C(Q,!0);return y(he),h(St,me)?(he.enumerable?(h(W,Y)&&W[Y][me]&&(W[Y][me]=!1),he=B(he,{enumerable:A(0,!1)})):(h(W,Y)||re(W,Y,A(1,{})),W[Y][me]=!0),Ln(W,me,he)):re(W,me,he)},x=function(W,Q){y(W);var he=S(Q),me=w(he).concat(ye(he));return ue(me,function(st){(!u||G.call(he,st))&&b(W,st,he[st])}),W},$=function(W,Q){return Q===void 0?B(W):x(B(W),Q)},G=function(W){var Q=C(W,!0),he=co.call(this,Q);return this===Ie&&h(St,Q)&&!h(Ut,Q)?!1:he||!h(this,Q)||!h(St,Q)||h(this,Y)&&this[Y][Q]?he:!0},_=function(W,Q){var he=S(W),me=C(Q,!0);if(!(he===Ie&&h(St,me)&&!h(Ut,me))){var st=ne(he,me);return st&&h(St,me)&&!(h(he,Y)&&he[Y][me])&&(st.enumerable=!0),st}},le=function(W){var Q=xt(S(W)),he=[];return ue(Q,function(me){!h(St,me)&&!h(ce,me)&&he.push(me)}),he},ye=function(W){var Q=W===Ie,he=xt(Q?Ut:S(W)),me=[];return ue(he,function(st){h(St,st)&&(!Q||h(Ie,st))&&me.push(St[st])}),me};if(p||(Fe=function(){if(this instanceof Fe)throw TypeError("Symbol is not a constructor");var W=!arguments.length||arguments[0]===void 0?void 0:String(arguments[0]),Q=Se(W),he=function(me){this===Ie&&he.call(Ut,me),h(this,Y)&&h(this[Y],Q)&&(this[Y][Q]=!1),Ln(this,Q,A(1,me))};return u&&Mn&&Ln(Ie,Q,{configurable:!0,set:he}),wn(Q,W)},F(Fe[be],"toString",function(){return we(this).tag}),F(Fe,"withoutSetter",function(ee){return wn(Se(ee),ee)}),N.f=G,E.f=b,R.f=_,O.f=L.f=le,j.f=ye,Ee.f=function(ee){return wn(ge(ee),ee)},u&&(re(Fe[be],"description",{configurable:!0,get:function(){return we(this).description}}),f||F(Ie,"propertyIsEnumerable",G,{unsafe:!0}))),s({global:!0,wrap:!0,forced:!p,sham:!p},{Symbol:Fe}),ue(w(Dn),function(ee){Ae(ee)}),s({target:Oe,stat:!0,forced:!p},{for:function(ee){var W=String(ee);if(h(fn,W))return fn[W];var Q=Fe(W);return fn[W]=Q,Pn[Q]=W,Q},keyFor:function(W){if(!T(W))throw TypeError(W+" is not a symbol");if(h(Pn,W))return Pn[W]},useSetter:function(){Mn=!0},useSimple:function(){Mn=!1}}),s({target:"Object",stat:!0,forced:!p,sham:!u},{create:$,defineProperty:b,defineProperties:x,getOwnPropertyDescriptor:_}),s({target:"Object",stat:!0,forced:!p},{getOwnPropertyNames:le,getOwnPropertySymbols:ye}),s({target:"Object",stat:!0,forced:m(function(){j.f(1)})},{getOwnPropertySymbols:function(W){return j.f(I(W))}}),vt){var Xe=!p||m(function(){var ee=Fe();return vt([ee])!="[null]"||vt({a:ee})!="{}"||vt(Object(ee))!="{}"});s({target:"JSON",stat:!0,forced:Xe},{stringify:function(W,Q,he){for(var me=[W],st=1,uo;arguments.length>st;)me.push(arguments[st++]);if(uo=Q,!(!g(Q)&&W===void 0||T(W)))return v(Q)||(Q=function(bs,lr){if(typeof uo=="function"&&(lr=uo.call(this,bs,lr)),!T(lr))return lr}),me[1]=Q,vt.apply(null,me)}})}Fe[be][Je]||V(Fe[be],Je,Fe[be].valueOf),X(Fe,Oe),ce[Y]=!0}),a630:(function(i,a,r){var s=r("23e7"),l=r("4df4"),c=r("1c7e"),f=!c(function(u){Array.from(u)});s({target:"Array",stat:!0,forced:f},{from:l})}),a640:(function(i,a,r){var s=r("d039");i.exports=function(l,c){var f=[][l];return!!f&&s(function(){f.call(null,c||function(){throw 1},1)})}}),a691:(function(i,a){var r=Math.ceil,s=Math.floor;i.exports=function(l){return isNaN(l=+l)?0:(l>0?s:r)(l)}}),ab13:(function(i,a,r){var s=r("b622"),l=s("match");i.exports=function(c){var f=/./;try{"/./"[c](f)}catch{try{return f[l]=!1,"/./"[c](f)}catch{}}return!1}}),ac1f:(function(i,a,r){var s=r("23e7"),l=r("9263");s({target:"RegExp",proto:!0,forced:/./.exec!==l},{exec:l})}),ad6d:(function(i,a,r){var s=r("825a");i.exports=function(){var l=s(this),c="";return l.global&&(c+="g"),l.ignoreCase&&(c+="i"),l.multiline&&(c+="m"),l.dotAll&&(c+="s"),l.unicode&&(c+="u"),l.sticky&&(c+="y"),c}}),ae40:(function(i,a,r){var s=r("83ab"),l=r("d039"),c=r("5135"),f=Object.defineProperty,u={},p=function(d){throw d};i.exports=function(d,m){if(c(u,d))return u[d];m||(m={});var h=[][d],v=c(m,"ACCESSORS")?m.ACCESSORS:!1,g=c(m,0)?m[0]:p,y=c(m,1)?m[1]:void 0;return u[d]=!!h&&!l(function(){if(v&&!s)return!0;var I={length:-1};v?f(I,1,{enumerable:!0,get:p}):I[1]=1,h.call(I,g,y)})}}),ae93:(function(i,a,r){var s=r("e163"),l=r("9112"),c=r("5135"),f=r("b622"),u=r("c430"),p=f("iterator"),d=!1,m=function(){return this},h,v,g;[].keys&&(g=[].keys(),"next"in g?(v=s(s(g)),v!==Object.prototype&&(h=v)):d=!0),h==null&&(h={}),!u&&!c(h,p)&&l(h,p,m),i.exports={IteratorPrototype:h,BUGGY_SAFARI_ITERATORS:d}}),b041:(function(i,a,r){var s=r("00ee"),l=r("f5df");i.exports=s?{}.toString:function(){return"[object "+l(this)+"]"}}),b0c0:(function(i,a,r){var s=r("83ab"),l=r("9bf2").f,c=Function.prototype,f=c.toString,u=/^\s*function ([^ (]*)/,p="name";s&&!(p in c)&&l(c,p,{configurable:!0,get:function(){try{return f.call(this).match(u)[1]}catch{return""}}})}),b622:(function(i,a,r){var s=r("da84"),l=r("5692"),c=r("5135"),f=r("90e3"),u=r("4930"),p=r("fdbf"),d=l("wks"),m=s.Symbol,h=p?m:m&&m.withoutSetter||f;i.exports=function(v){return c(d,v)||(u&&c(m,v)?d[v]=m[v]:d[v]=h("Symbol."+v)),d[v]}}),b64b:(function(i,a,r){var s=r("23e7"),l=r("7b0b"),c=r("df75"),f=r("d039"),u=f(function(){c(1)});s({target:"Object",stat:!0,forced:u},{keys:function(d){return c(l(d))}})}),b727:(function(i,a,r){var s=r("0366"),l=r("44ad"),c=r("7b0b"),f=r("50c4"),u=r("65f0"),p=[].push,d=function(m){var h=m==1,v=m==2,g=m==3,y=m==4,I=m==6,S=m==5||I;return function(C,A,B,w){for(var O=c(C),L=l(O),j=s(A,B,3),R=f(L.length),E=0,N=w||u,V=h?N(C,R):v?N(C,0):void 0,F,U;R>E;E++)if((S||E in L)&&(F=L[E],U=j(F,E,O),m)){if(h)V[E]=U;else if(U)switch(m){case 3:return!0;case 5:return F;case 6:return E;case 2:p.call(V,F)}else if(y)return!1}return I?-1:g||y?y:V}};i.exports={forEach:d(0),map:d(1),filter:d(2),some:d(3),every:d(4),find:d(5),findIndex:d(6)}}),c04e:(function(i,a,r){var s=r("861d");i.exports=function(l,c){if(!s(l))return l;var f,u;if(c&&typeof(f=l.toString)=="function"&&!s(u=f.call(l))||typeof(f=l.valueOf)=="function"&&!s(u=f.call(l))||!c&&typeof(f=l.toString)=="function"&&!s(u=f.call(l)))return u;throw TypeError("Can't convert object to primitive value")}}),c430:(function(i,a){i.exports=!1}),c6b6:(function(i,a){var r={}.toString;i.exports=function(s){return r.call(s).slice(8,-1)}}),c6cd:(function(i,a,r){var s=r("da84"),l=r("ce4e"),c="__core-js_shared__",f=s[c]||l(c,{});i.exports=f}),c740:(function(i,a,r){var s=r("23e7"),l=r("b727").findIndex,c=r("44d2"),f=r("ae40"),u="findIndex",p=!0,d=f(u);u in[]&&Array(1)[u](function(){p=!1}),s({target:"Array",proto:!0,forced:p||!d},{findIndex:function(h){return l(this,h,arguments.length>1?arguments[1]:void 0)}}),c(u)}),c8ba:(function(i,a){var r;r=(function(){return this})();try{r=r||new Function("return this")()}catch{typeof window=="object"&&(r=window)}i.exports=r}),c975:(function(i,a,r){var s=r("23e7"),l=r("4d64").indexOf,c=r("a640"),f=r("ae40"),u=[].indexOf,p=!!u&&1/[1].indexOf(1,-0)<0,d=c("indexOf"),m=f("indexOf",{ACCESSORS:!0,1:0});s({target:"Array",proto:!0,forced:p||!d||!m},{indexOf:function(v){return p?u.apply(this,arguments)||0:l(this,v,arguments.length>1?arguments[1]:void 0)}})}),ca84:(function(i,a,r){var s=r("5135"),l=r("fc6a"),c=r("4d64").indexOf,f=r("d012");i.exports=function(u,p){var d=l(u),m=0,h=[],v;for(v in d)!s(f,v)&&s(d,v)&&h.push(v);for(;p.length>m;)s(d,v=p[m++])&&(~c(h,v)||h.push(v));return h}}),caad:(function(i,a,r){var s=r("23e7"),l=r("4d64").includes,c=r("44d2"),f=r("ae40"),u=f("indexOf",{ACCESSORS:!0,1:0});s({target:"Array",proto:!0,forced:!u},{includes:function(d){return l(this,d,arguments.length>1?arguments[1]:void 0)}}),c("includes")}),cc12:(function(i,a,r){var s=r("da84"),l=r("861d"),c=s.document,f=l(c)&&l(c.createElement);i.exports=function(u){return f?c.createElement(u):{}}}),ce4e:(function(i,a,r){var s=r("da84"),l=r("9112");i.exports=function(c,f){try{l(s,c,f)}catch{s[c]=f}return f}}),d012:(function(i,a){i.exports={}}),d039:(function(i,a){i.exports=function(r){try{return!!r()}catch{return!0}}}),d066:(function(i,a,r){var s=r("428f"),l=r("da84"),c=function(f){return typeof f=="function"?f:void 0};i.exports=function(f,u){return arguments.length<2?c(s[f])||c(l[f]):s[f]&&s[f][u]||l[f]&&l[f][u]}}),d1e7:(function(i,a,r){var s={}.propertyIsEnumerable,l=Object.getOwnPropertyDescriptor,c=l&&!s.call({1:2},1);a.f=c?function(u){var p=l(this,u);return!!p&&p.enumerable}:s}),d28b:(function(i,a,r){var s=r("746f");s("iterator")}),d2bb:(function(i,a,r){var s=r("825a"),l=r("3bbe");i.exports=Object.setPrototypeOf||("__proto__"in{}?(function(){var c=!1,f={},u;try{u=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set,u.call(f,[]),c=f instanceof Array}catch{}return function(d,m){return s(d),l(m),c?u.call(d,m):d.__proto__=m,d}})():void 0)}),d3b7:(function(i,a,r){var s=r("00ee"),l=r("6eeb"),c=r("b041");s||l(Object.prototype,"toString",c,{unsafe:!0})}),d44e:(function(i,a,r){var s=r("9bf2").f,l=r("5135"),c=r("b622"),f=c("toStringTag");i.exports=function(u,p,d){u&&!l(u=d?u:u.prototype,f)&&s(u,f,{configurable:!0,value:p})}}),d58f:(function(i,a,r){var s=r("1c0b"),l=r("7b0b"),c=r("44ad"),f=r("50c4"),u=function(p){return function(d,m,h,v){s(m);var g=l(d),y=c(g),I=f(g.length),S=p?I-1:0,C=p?-1:1;if(h<2)for(;;){if(S in y){v=y[S],S+=C;break}if(S+=C,p?S<0:I<=S)throw TypeError("Reduce of empty array with no initial value")}for(;p?S>=0:I>S;S+=C)S in y&&(v=m(v,y[S],S,g));return v}};i.exports={left:u(!1),right:u(!0)}}),d784:(function(i,a,r){r("ac1f");var s=r("6eeb"),l=r("d039"),c=r("b622"),f=r("9263"),u=r("9112"),p=c("species"),d=!l(function(){var y=/./;return y.exec=function(){var I=[];return I.groups={a:"7"},I},"".replace(y,"$<a>")!=="7"}),m=(function(){return"a".replace(/./,"$0")==="$0"})(),h=c("replace"),v=(function(){return/./[h]?/./[h]("a","$0")==="":!1})(),g=!l(function(){var y=/(?:)/,I=y.exec;y.exec=function(){return I.apply(this,arguments)};var S="ab".split(y);return S.length!==2||S[0]!=="a"||S[1]!=="b"});i.exports=function(y,I,S,C){var A=c(y),B=!l(function(){var E={};return E[A]=function(){return 7},""[y](E)!=7}),w=B&&!l(function(){var E=!1,N=/a/;return y==="split"&&(N={},N.constructor={},N.constructor[p]=function(){return N},N.flags="",N[A]=/./[A]),N.exec=function(){return E=!0,null},N[A](""),!E});if(!B||!w||y==="replace"&&!(d&&m&&!v)||y==="split"&&!g){var O=/./[A],L=S(A,""[y],function(E,N,V,F,U){return N.exec===f?B&&!U?{done:!0,value:O.call(N,V,F)}:{done:!0,value:E.call(V,N,F)}:{done:!1}},{REPLACE_KEEPS_$0:m,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:v}),j=L[0],R=L[1];s(String.prototype,y,j),s(RegExp.prototype,A,I==2?function(E,N){return R.call(E,this,N)}:function(E){return R.call(E,this)})}C&&u(RegExp.prototype[A],"sham",!0)}}),d81d:(function(i,a,r){var s=r("23e7"),l=r("b727").map,c=r("1dde"),f=r("ae40"),u=c("map"),p=f("map");s({target:"Array",proto:!0,forced:!u||!p},{map:function(m){return l(this,m,arguments.length>1?arguments[1]:void 0)}})}),da84:(function(i,a,r){(function(s){var l=function(c){return c&&c.Math==Math&&c};i.exports=l(typeof globalThis=="object"&&globalThis)||l(typeof window=="object"&&window)||l(typeof self=="object"&&self)||l(typeof s=="object"&&s)||Function("return this")()}).call(this,r("c8ba"))}),dbb4:(function(i,a,r){var s=r("23e7"),l=r("83ab"),c=r("56ef"),f=r("fc6a"),u=r("06cf"),p=r("8418");s({target:"Object",stat:!0,sham:!l},{getOwnPropertyDescriptors:function(m){for(var h=f(m),v=u.f,g=c(h),y={},I=0,S,C;g.length>I;)C=v(h,S=g[I++]),C!==void 0&&p(y,S,C);return y}})}),dbf1:(function(i,a,r){(function(s){r.d(a,"a",function(){return c});function l(){return typeof window<"u"?window.console:s.console}var c=l()}).call(this,r("c8ba"))}),ddb0:(function(i,a,r){var s=r("da84"),l=r("fdbc"),c=r("e260"),f=r("9112"),u=r("b622"),p=u("iterator"),d=u("toStringTag"),m=c.values;for(var h in l){var v=s[h],g=v&&v.prototype;if(g){if(g[p]!==m)try{f(g,p,m)}catch{g[p]=m}if(g[d]||f(g,d,h),l[h]){for(var y in c)if(g[y]!==c[y])try{f(g,y,c[y])}catch{g[y]=c[y]}}}}}),df75:(function(i,a,r){var s=r("ca84"),l=r("7839");i.exports=Object.keys||function(f){return s(f,l)}}),e01a:(function(i,a,r){var s=r("23e7"),l=r("83ab"),c=r("da84"),f=r("5135"),u=r("861d"),p=r("9bf2").f,d=r("e893"),m=c.Symbol;if(l&&typeof m=="function"&&(!("description"in m.prototype)||m().description!==void 0)){var h={},v=function(){var A=arguments.length<1||arguments[0]===void 0?void 0:String(arguments[0]),B=this instanceof v?new m(A):A===void 0?m():m(A);return A===""&&(h[B]=!0),B};d(v,m);var g=v.prototype=m.prototype;g.constructor=v;var y=g.toString,I=String(m("test"))=="Symbol(test)",S=/^Symbol\((.*)\)[^)]+$/;p(g,"description",{configurable:!0,get:function(){var A=u(this)?this.valueOf():this,B=y.call(A);if(f(h,A))return"";var w=I?B.slice(7,-1):B.replace(S,"$1");return w===""?void 0:w}}),s({global:!0,forced:!0},{Symbol:v})}}),e163:(function(i,a,r){var s=r("5135"),l=r("7b0b"),c=r("f772"),f=r("e177"),u=c("IE_PROTO"),p=Object.prototype;i.exports=f?Object.getPrototypeOf:function(d){return d=l(d),s(d,u)?d[u]:typeof d.constructor=="function"&&d instanceof d.constructor?d.constructor.prototype:d instanceof Object?p:null}}),e177:(function(i,a,r){var s=r("d039");i.exports=!s(function(){function l(){}return l.prototype.constructor=null,Object.getPrototypeOf(new l)!==l.prototype})}),e260:(function(i,a,r){var s=r("fc6a"),l=r("44d2"),c=r("3f8c"),f=r("69f3"),u=r("7dd0"),p="Array Iterator",d=f.set,m=f.getterFor(p);i.exports=u(Array,"Array",function(h,v){d(this,{type:p,target:s(h),index:0,kind:v})},function(){var h=m(this),v=h.target,g=h.kind,y=h.index++;return!v||y>=v.length?(h.target=void 0,{value:void 0,done:!0}):g=="keys"?{value:y,done:!1}:g=="values"?{value:v[y],done:!1}:{value:[y,v[y]],done:!1}},"values"),c.Arguments=c.Array,l("keys"),l("values"),l("entries")}),e439:(function(i,a,r){var s=r("23e7"),l=r("d039"),c=r("fc6a"),f=r("06cf").f,u=r("83ab"),p=l(function(){f(1)}),d=!u||p;s({target:"Object",stat:!0,forced:d,sham:!u},{getOwnPropertyDescriptor:function(h,v){return f(c(h),v)}})}),e538:(function(i,a,r){var s=r("b622");a.f=s}),e893:(function(i,a,r){var s=r("5135"),l=r("56ef"),c=r("06cf"),f=r("9bf2");i.exports=function(u,p){for(var d=l(p),m=f.f,h=c.f,v=0;v<d.length;v++){var g=d[v];s(u,g)||m(u,g,h(p,g))}}}),e8b5:(function(i,a,r){var s=r("c6b6");i.exports=Array.isArray||function(c){return s(c)=="Array"}}),e95a:(function(i,a,r){var s=r("b622"),l=r("3f8c"),c=s("iterator"),f=Array.prototype;i.exports=function(u){return u!==void 0&&(l.Array===u||f[c]===u)}}),f5df:(function(i,a,r){var s=r("00ee"),l=r("c6b6"),c=r("b622"),f=c("toStringTag"),u=l((function(){return arguments})())=="Arguments",p=function(d,m){try{return d[m]}catch{}};i.exports=s?l:function(d){var m,h,v;return d===void 0?"Undefined":d===null?"Null":typeof(h=p(m=Object(d),f))=="string"?h:u?l(m):(v=l(m))=="Object"&&typeof m.callee=="function"?"Arguments":v}}),f772:(function(i,a,r){var s=r("5692"),l=r("90e3"),c=s("keys");i.exports=function(f){return c[f]||(c[f]=l(f))}}),fb15:(function(i,a,r){if(r.r(a),typeof window<"u"){var s=window.document.currentScript;{var l=r("8875");s=l(),"currentScript"in document||Object.defineProperty(document,"currentScript",{get:l})}var c=s&&s.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);c&&(r.p=c[1])}r("99af"),r("4de4"),r("4160"),r("c975"),r("d81d"),r("a434"),r("159b"),r("a4d3"),r("e439"),r("dbb4"),r("b64b");function f(T,b,x){return b in T?Object.defineProperty(T,b,{value:x,enumerable:!0,configurable:!0,writable:!0}):T[b]=x,T}function u(T,b){var x=Object.keys(T);if(Object.getOwnPropertySymbols){var $=Object.getOwnPropertySymbols(T);b&&($=$.filter(function(G){return Object.getOwnPropertyDescriptor(T,G).enumerable})),x.push.apply(x,$)}return x}function p(T){for(var b=1;b<arguments.length;b++){var x=arguments[b]!=null?arguments[b]:{};b%2?u(Object(x),!0).forEach(function($){f(T,$,x[$])}):Object.getOwnPropertyDescriptors?Object.defineProperties(T,Object.getOwnPropertyDescriptors(x)):u(Object(x)).forEach(function($){Object.defineProperty(T,$,Object.getOwnPropertyDescriptor(x,$))})}return T}function d(T){if(Array.isArray(T))return T}r("e01a"),r("d28b"),r("e260"),r("d3b7"),r("3ca3"),r("ddb0");function m(T,b){if(!(typeof Symbol>"u"||!(Symbol.iterator in Object(T)))){var x=[],$=!0,G=!1,_=void 0;try{for(var le=T[Symbol.iterator](),ye;!($=(ye=le.next()).done)&&(x.push(ye.value),!(b&&x.length===b));$=!0);}catch(Xe){G=!0,_=Xe}finally{try{!$&&le.return!=null&&le.return()}finally{if(G)throw _}}return x}}r("a630"),r("fb6a"),r("b0c0"),r("25f0");function h(T,b){(b==null||b>T.length)&&(b=T.length);for(var x=0,$=new Array(b);x<b;x++)$[x]=T[x];return $}function v(T,b){if(T){if(typeof T=="string")return h(T,b);var x=Object.prototype.toString.call(T).slice(8,-1);if(x==="Object"&&T.constructor&&(x=T.constructor.name),x==="Map"||x==="Set")return Array.from(T);if(x==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(x))return h(T,b)}}function g(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
|
|
29
29
|
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function y(T,b){return d(T)||m(T,b)||v(T,b)||g()}function I(T){if(Array.isArray(T))return h(T)}function S(T){if(typeof Symbol<"u"&&Symbol.iterator in Object(T))return Array.from(T)}function C(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
|
|
30
30
|
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function A(T){return I(T)||S(T)||v(T)||C()}var B=r("a352"),w=r.n(B);function O(T){T.parentElement!==null&&T.parentElement.removeChild(T)}function L(T,b,x){var $=x===0?T.children[0]:T.children[x-1].nextSibling;T.insertBefore(b,$)}var j=r("dbf1");r("13d5"),r("4fad"),r("ac1f"),r("5319");function R(T){var b=Object.create(null);return function($){var G=b[$];return G||(b[$]=T($))}}var E=/-(\w)/g,N=R(function(T){return T.replace(E,function(b,x){return x.toUpperCase()})});r("5db7"),r("73d9");var V=["Start","Add","Remove","Update","End"],F=["Choose","Unchoose","Sort","Filter","Clone"],U=["Move"],z=[U,V,F].flatMap(function(T){return T}).map(function(T){return"on".concat(T)}),ce={manage:U,manageAndEmit:V,emit:F};function Se(T){return z.indexOf(T)!==-1}r("caad"),r("2ca0");var ge=["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","link","main","map","mark","math","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"];function Ee(T){return ge.includes(T)}function Ae(T){return["transition-group","TransitionGroup"].includes(T)}function X(T){return["id","class","role","style"].includes(T)||T.startsWith("data-")||T.startsWith("aria-")||T.startsWith("on")}function D(T){return T.reduce(function(b,x){var $=y(x,2),G=$[0],_=$[1];return b[G]=_,b},{})}function ue(T){var b=T.$attrs,x=T.componentData,$=x===void 0?{}:x,G=D(Object.entries(b).filter(function(_){var le=y(_,2),ye=le[0];return le[1],X(ye)}));return p(p({},G),$)}function Y(T){var b=T.$attrs,x=T.callBackBuilder,$=D(Oe(b));Object.entries(x).forEach(function(_){var le=y(_,2),ye=le[0],Xe=le[1];ce[ye].forEach(function(ee){$["on".concat(ee)]=Xe(ee)})});var G="[data-draggable]".concat($.draggable||"");return p(p({},$),{},{draggable:G})}function Oe(T){return Object.entries(T).filter(function(b){var x=y(b,2),$=x[0];return x[1],!X($)}).map(function(b){var x=y(b,2),$=x[0],G=x[1];return[N($),G]}).filter(function(b){var x=y(b,2),$=x[0];return x[1],!Se($)})}r("c740");function be(T,b){if(!(T instanceof b))throw new TypeError("Cannot call a class as a function")}function Je(T,b){for(var x=0;x<b.length;x++){var $=b[x];$.enumerable=$.enumerable||!1,$.configurable=!0,"value"in $&&($.writable=!0),Object.defineProperty(T,$.key,$)}}function Le(T,b,x){return b&&Je(T.prototype,b),T}var we=function(b){var x=b.el;return x},Ie=function(b,x){return b.__draggable_context=x},Fe=function(b){return b.__draggable_context},vt=(function(){function T(b){var x=b.nodes,$=x.header,G=x.default,_=x.footer,le=b.root,ye=b.realList;be(this,T),this.defaultNodes=G,this.children=[].concat(A($),A(G),A(_)),this.externalComponent=le.externalComponent,this.rootTransition=le.transition,this.tag=le.tag,this.realList=ye}return Le(T,[{key:"render",value:function(x,$){var G=this.tag,_=this.children,le=this._isRootComponent,ye=le?{default:function(){return _}}:_;return x(G,$,ye)}},{key:"updated",value:function(){var x=this.defaultNodes,$=this.realList;x.forEach(function(G,_){Ie(we(G),{element:$[_],index:_})})}},{key:"getUnderlyingVm",value:function(x){return Fe(x)}},{key:"getVmIndexFromDomIndex",value:function(x,$){var G=this.defaultNodes,_=G.length,le=$.children,ye=le.item(x);if(ye===null)return _;var Xe=Fe(ye);if(Xe)return Xe.index;if(_===0)return 0;var ee=we(G[0]),W=A(le).findIndex(function(Q){return Q===ee});return x<W?0:_}},{key:"_isRootComponent",get:function(){return this.externalComponent||this.rootTransition}}]),T})(),ne=r("8bbf");function re(T,b){var x=T[b];return x?x():[]}function xt(T){var b=T.$slots,x=T.realList,$=T.getKey,G=x||[],_=["header","footer"].map(function(Q){return re(b,Q)}),le=y(_,2),ye=le[0],Xe=le[1],ee=b.item;if(!ee)throw new Error("draggable element must have an item slot");var W=G.flatMap(function(Q,he){return ee({element:Q,index:he}).map(function(me){return me.key=$(Q),me.props=p(p({},me.props||{}),{},{"data-draggable":!0}),me})});if(W.length!==G.length)throw new Error("Item slot must have only one child");return{header:ye,footer:Xe,default:W}}function co(T){var b=Ae(T),x=!Ee(T)&&!b;return{transition:b,externalComponent:x,tag:x?Object(ne.resolveComponent)(T):b?ne.TransitionGroup:T}}function St(T){var b=T.$slots,x=T.tag,$=T.realList,G=T.getKey,_=xt({$slots:b,realList:$,getKey:G}),le=co(x);return new vt({nodes:_,root:le,realList:$})}function Ut(T,b){var x=this;Object(ne.nextTick)(function(){return x.$emit(T.toLowerCase(),b)})}function fn(T){var b=this;return function(x,$){if(b.realList!==null)return b["onDrag".concat(T)](x,$)}}function Pn(T){var b=this,x=fn.call(this,T);return function($,G){x.call(b,$,G),Ut.call(b,T,$)}}var Dn=null,Rn={list:{type:Array,required:!1,default:null},modelValue:{type:Array,required:!1,default:null},itemKey:{type:[String,Function],required:!0},clone:{type:Function,default:function(b){return b}},tag:{type:String,default:"div"},move:{type:Function,default:null},componentData:{type:Object,required:!1,default:null}},Mn=["update:modelValue","change"].concat(A([].concat(A(ce.manageAndEmit),A(ce.emit)).map(function(T){return T.toLowerCase()}))),Ln=Object(ne.defineComponent)({name:"draggable",inheritAttrs:!1,props:Rn,emits:Mn,data:function(){return{error:!1}},render:function(){try{this.error=!1;var b=this.$slots,x=this.$attrs,$=this.tag,G=this.componentData,_=this.realList,le=this.getKey,ye=St({$slots:b,tag:$,realList:_,getKey:le});this.componentStructure=ye;var Xe=ue({$attrs:x,componentData:G});return ye.render(ne.h,Xe)}catch(ee){return this.error=!0,Object(ne.h)("pre",{style:{color:"red"}},ee.stack)}},created:function(){this.list!==null&&this.modelValue!==null&&j.a.error("modelValue and list props are mutually exclusive! Please set one or another.")},mounted:function(){var b=this;if(!this.error){var x=this.$attrs,$=this.$el,G=this.componentStructure;G.updated();var _=Y({$attrs:x,callBackBuilder:{manageAndEmit:function(Xe){return Pn.call(b,Xe)},emit:function(Xe){return Ut.bind(b,Xe)},manage:function(Xe){return fn.call(b,Xe)}}}),le=$.nodeType===1?$:$.parentElement;this._sortable=new w.a(le,_),this.targetDomElement=le,le.__draggable_component__=this}},updated:function(){this.componentStructure.updated()},beforeUnmount:function(){this._sortable!==void 0&&this._sortable.destroy()},computed:{realList:function(){var b=this.list;return b||this.modelValue},getKey:function(){var b=this.itemKey;return typeof b=="function"?b:function(x){return x[b]}}},watch:{$attrs:{handler:function(b){var x=this._sortable;x&&Oe(b).forEach(function($){var G=y($,2),_=G[0],le=G[1];x.option(_,le)})},deep:!0}},methods:{getUnderlyingVm:function(b){return this.componentStructure.getUnderlyingVm(b)||null},getUnderlyingPotencialDraggableComponent:function(b){return b.__draggable_component__},emitChanges:function(b){var x=this;Object(ne.nextTick)(function(){return x.$emit("change",b)})},alterList:function(b){if(this.list){b(this.list);return}var x=A(this.modelValue);b(x),this.$emit("update:modelValue",x)},spliceList:function(){var b=arguments,x=function(G){return G.splice.apply(G,A(b))};this.alterList(x)},updatePosition:function(b,x){var $=function(_){return _.splice(x,0,_.splice(b,1)[0])};this.alterList($)},getRelatedContextFromMoveEvent:function(b){var x=b.to,$=b.related,G=this.getUnderlyingPotencialDraggableComponent(x);if(!G)return{component:G};var _=G.realList,le={list:_,component:G};if(x!==$&&_){var ye=G.getUnderlyingVm($)||{};return p(p({},ye),le)}return le},getVmIndexFromDomIndex:function(b){return this.componentStructure.getVmIndexFromDomIndex(b,this.targetDomElement)},onDragStart:function(b){this.context=this.getUnderlyingVm(b.item),b.item._underlying_vm_=this.clone(this.context.element),Dn=b.item},onDragAdd:function(b){var x=b.item._underlying_vm_;if(x!==void 0){O(b.item);var $=this.getVmIndexFromDomIndex(b.newIndex);this.spliceList($,0,x);var G={element:x,newIndex:$};this.emitChanges({added:G})}},onDragRemove:function(b){if(L(this.$el,b.item,b.oldIndex),b.pullMode==="clone"){O(b.clone);return}var x=this.context,$=x.index,G=x.element;this.spliceList($,1);var _={element:G,oldIndex:$};this.emitChanges({removed:_})},onDragUpdate:function(b){O(b.item),L(b.from,b.item,b.oldIndex);var x=this.context.index,$=this.getVmIndexFromDomIndex(b.newIndex);this.updatePosition(x,$);var G={element:this.context.element,oldIndex:x,newIndex:$};this.emitChanges({moved:G})},computeFutureIndex:function(b,x){if(!b.element)return 0;var $=A(x.to.children).filter(function(ye){return ye.style.display!=="none"}),G=$.indexOf(x.related),_=b.component.getVmIndexFromDomIndex(G),le=$.indexOf(Dn)!==-1;return le||!x.willInsertAfter?_:_+1},onDragMove:function(b,x){var $=this.move,G=this.realList;if(!$||!G)return!0;var _=this.getRelatedContextFromMoveEvent(b),le=this.computeFutureIndex(_,b),ye=p(p({},this.context),{},{futureIndex:le}),Xe=p(p({},b),{},{relatedContext:_,draggedContext:ye});return $(Xe,x)},onDragEnd:function(){Dn=null}}}),wn=Ln;a.default=wn}),fb6a:(function(i,a,r){var s=r("23e7"),l=r("861d"),c=r("e8b5"),f=r("23cb"),u=r("50c4"),p=r("fc6a"),d=r("8418"),m=r("b622"),h=r("1dde"),v=r("ae40"),g=h("slice"),y=v("slice",{ACCESSORS:!0,0:0,1:2}),I=m("species"),S=[].slice,C=Math.max;s({target:"Array",proto:!0,forced:!g||!y},{slice:function(B,w){var O=p(this),L=u(O.length),j=f(B,L),R=f(w===void 0?L:w,L),E,N,V;if(c(O)&&(E=O.constructor,typeof E=="function"&&(E===Array||c(E.prototype))?E=void 0:l(E)&&(E=E[I],E===null&&(E=void 0)),E===Array||E===void 0))return S.call(O,j,R);for(N=new(E===void 0?Array:E)(C(R-j,0)),V=0;j<R;j++,V++)j in O&&d(N,V,O[j]);return N.length=V,N}})}),fc6a:(function(i,a,r){var s=r("44ad"),l=r("1d80");i.exports=function(c){return s(l(c))}}),fdbc:(function(i,a){i.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}}),fdbf:(function(i,a,r){var s=r("4930");i.exports=s&&!Symbol.sham&&typeof Symbol.iterator=="symbol"})}).default})})(yr)),yr.exports}var Iu=Ou();const Nu=Ls(Iu),Ai=ws("testResults",()=>{const e=gn({}),t=gn({}),n=gn({}),o=gn({});function i(s){for(const[l,c]of Object.entries(s))e[l]=c.status,t[l]=c.message||"",n[l]=c.time?new Date(c.time).toLocaleString():"",o[l]=c.latency||0}async function a(){try{const s=await Yt.get("/api/test/results");i(s)}catch{}}async function r(s){e[s]="testing",t[s]="";try{const l=await Yt.post("/api/test/proxy",{model:s});e[s]=l.status,t[s]=l.message||"",n[s]=new Date().toLocaleString(),o[s]=l.latency||0}catch(l){e[s]="error",t[s]=l.message,n[s]=new Date().toLocaleString(),o[s]=0}}return{modelStatus:e,modelMessage:t,modelTime:n,modelLatency:o,loadResults:a,testProxy:r}}),Cu={class:"card-header"},Au={class:"card-title"},xu={class:"provider-name"},Pu={class:"card-meta"},Du={class:"meta-row"},Ru=["title"],Mu={class:"meta-row"},Lu={class:"meta-value"},wu={key:0,class:"model-tags"},Vu=["onClick"],Fu={key:0,class:"badge-mark"},$u={key:1,class:"badge-mark"},Uu={key:1,class:"text-empty"},ju={class:"card-footer"},Bu=Jt({__name:"ProviderCard",props:{provider:{}},emits:["clone","delete","edit","open-models","copy-model"],setup(e,{emit:t}){const n=e,o=t,{toast:i}=un(),a=Ai(),r=f=>f?f.length<=8?f:`${f.substring(0,6)}...${f.substring(f.length-4)}`:"-",s=Ht(()=>{const f=n.provider;return f.name||f.alias||r(f.apiKey||"")}),l=Pe(!1),c=async()=>{const f=n.provider.models;l.value=!0;try{await Promise.all(f.map(p=>a.testProxy(p.modelName)));const u=f.filter(p=>a.modelStatus[p.modelName]==="ok").length;i(`${s.value}: ${u}/${f.length} 个模型通过`,u===f.length?"success":"error")}catch{i("测试出错","error")}finally{l.value=!1}};return(f,u)=>{const p=J("el-tag"),d=J("el-icon"),m=J("el-button"),h=J("el-card");return te(),Me(h,{shadow:"never",class:"provider-card"},{header:M(()=>[K("div",Cu,[K("div",Au,[K("span",xu,Te(s.value),1),e.provider.alias&&e.provider.name!==e.provider.alias?(te(),Me(p,{key:0,type:"info",size:"small"},{default:M(()=>[ae(Te(e.provider.alias),1)]),_:1})):tt("",!0)]),P(d,{class:"drag-hint-icon"},{default:M(()=>[P(q(Fs))]),_:1})])]),default:M(()=>[K("div",Pu,[K("div",Du,[u[6]||(u[6]=K("span",{class:"meta-label"},"接口地址",-1)),K("span",{class:"meta-value",title:e.provider.apiBase},Te(e.provider.apiBase||"-"),9,Ru)]),K("div",Mu,[u[7]||(u[7]=K("span",{class:"meta-label"},"密钥",-1)),K("span",Lu,Te(r(e.provider.apiKey||"")),1)])]),e.provider.models.length?(te(),Be("div",wu,[(te(!0),Be(Bo,null,ko(e.provider.models,v=>(te(),Be("span",{key:v.modelName,class:Vs(["model-tag",{ok:q(a).modelStatus[v.modelName]==="ok",error:q(a).modelStatus[v.modelName]==="error"}]),onClick:fo(g=>o("copy-model",v.modelName),["stop"])},[ae(Te(v.modelName)+" ",1),q(a).modelStatus[v.modelName]==="ok"?(te(),Be("span",Fu,"✓")):tt("",!0),q(a).modelStatus[v.modelName]==="error"?(te(),Be("span",$u,"✗")):tt("",!0)],10,Vu))),128))])):(te(),Be("div",Uu,"暂无模型")),K("div",ju,[K("span",{class:"model-count",onClick:u[0]||(u[0]=fo(v=>o("open-models"),["stop"]))},Te(e.provider.models.length)+" 个模型",1),K("div",{class:"card-actions",onClick:u[5]||(u[5]=fo(()=>{},["stop"]))},[P(m,{size:"small",loading:l.value,disabled:l.value||!e.provider.models.length,onClick:c},{default:M(()=>[ae(Te(l.value?"测试中...":"一键测试"),1)]),_:1},8,["loading","disabled"]),P(m,{size:"small",onClick:u[1]||(u[1]=v=>o("clone"))},{default:M(()=>[...u[8]||(u[8]=[ae("复制",-1)])]),_:1}),P(m,{size:"small",onClick:u[2]||(u[2]=v=>o("delete"))},{default:M(()=>[...u[9]||(u[9]=[ae("删除",-1)])]),_:1}),P(m,{size:"small",onClick:u[3]||(u[3]=v=>o("open-models"))},{default:M(()=>[...u[10]||(u[10]=[ae("模型",-1)])]),_:1}),P(m,{size:"small",onClick:u[4]||(u[4]=v=>o("edit"))},{default:M(()=>[...u[11]||(u[11]=[ae("编辑",-1)])]),_:1})])])]),_:1})}}}),ku=cn(Bu,[["__scopeId","data-v-e96d8595"]]),Co=[{id:"deepseek",name:"DeepSeek(按量 API)",alias:"ds",website:"https://platform.deepseek.com",keyUrl:"https://platform.deepseek.com/api_keys",keyNote:"登录 DeepSeek 开放平台 →「API keys」→ 创建。官方原生支持 Anthropic 协议:本模板已指向 Anthropic 兼容地址(api.deepseek.com/anthropic),配合 Claude Code 等客户端可原生保留缓存控制。同一把 Key 也可改用 OpenAI 协议地址 https://api.deepseek.com。",apiBase:"https://api.deepseek.com/anthropic",autoV1:!1,protocol:"anthropic",presetModels:["deepseek-v4-pro","deepseek-v4-flash"]},{id:"kimi",name:"月之暗面 Kimi(按量 API)",alias:"kimi",website:"https://platform.kimi.com",keyUrl:"https://platform.kimi.com/console/api-keys",keyNote:"登录 Kimi 开放平台 →「API Key 管理」→ 新建。本模板指向 Anthropic 兼容地址(api.moonshot.cn/anthropic),配合 Claude Code 使用;1M 上下文模型名需加 [1m] 后缀(如 kimi-k3[1m])。同一把 Key 也可改用 OpenAI 协议地址 https://api.moonshot.cn/v1。",apiBase:"https://api.moonshot.cn/anthropic",autoV1:!1,protocol:"anthropic",presetModels:["kimi-k3","kimi-k2.7-code"]},{id:"zhipu",name:"智谱 GLM(按量 API)",alias:"zhipu",website:"https://open.bigmodel.cn",keyUrl:"https://bigmodel.cn/usercenter/proj-mgmt/apikeys",keyNote:"登录智谱开放平台 →「API Keys」→ 创建。按量付费用此 Key + 本模板地址(OpenAI 兼容 /api/paas/v4)。若购买的是 Coding Plan 套餐,请改用下方「智谱 GLM(Coding Plan)」模板——套餐 Key 与按量 Key 不通用。",apiBase:"https://open.bigmodel.cn/api/paas/v4",autoV1:!1,protocol:"openai",presetModels:["glm-5.3","glm-5.3-flash"]},{id:"zhipu-coding",name:"智谱 GLM(Coding Plan)",alias:"zhipu-code",website:"https://bigmodel.cn/coding-plan/personal/overview",keyUrl:"https://bigmodel.cn/coding-plan/personal/overview",keyNote:"Coding Plan 套餐专用:Key 在套餐页面单独获取,与按量付费 Key 不通用。本模板指向套餐 Anthropic 端点(/api/anthropic),供 Claude Code 等客户端使用;注意地址填错会把套餐额度按按量计费扣费。",apiBase:"https://open.bigmodel.cn/api/anthropic",autoV1:!1,protocol:"anthropic",presetModels:["glm-5.3","glm-5.3-flash"]},{id:"ark",name:"火山方舟(按量 API)",alias:"ark",website:"https://console.volcengine.com/ark",keyUrl:"https://console.volcengine.com/ark/region:cn-beijing/apikey",keyNote:"火山方舟控制台 →「API Key 管理」→ 创建。API Key 鉴权可直接填模型名(如 doubao-seed-2.1-turbo);若使用 Access Key 鉴权则需填推理接入点 ID(ep-xxx)。购买 Coding Plan 套餐请改用下方「火山方舟(Coding Plan)」模板。",apiBase:"https://ark.cn-beijing.volces.com/api/v3",autoV1:!1,protocol:"openai"},{id:"ark-coding",name:"火山方舟(Coding Plan)",alias:"ark-code",website:"https://console.volcengine.com/ark",keyUrl:"https://console.volcengine.com/ark/region:cn-beijing/apikey",keyNote:"Coding Plan 套餐专用端点(/api/coding/v3),模型直接填模型名(如 ark-code-latest 自动切换、doubao-seed-evolving、glm-5.3、deepseek-v4-flash 等),无需接入点。注意:误用按量地址(/api/v3)会把套餐额度按按量计费扣费。",apiBase:"https://ark.cn-beijing.volces.com/api/coding/v3",autoV1:!1,protocol:"openai",presetModels:["ark-code-latest","doubao-seed-evolving"]},{id:"dashscope",name:"阿里云百炼(按量 API)",alias:"ali",website:"https://bailian.console.aliyun.com",keyUrl:"https://bailian.console.aliyun.com/?apiKey=1",keyNote:"登录阿里云百炼控制台 →右上角「API-KEY」→ 创建。本模板为 OpenAI 兼容地址(旧域名,仍可用);开通 Token Plan / Coding Plan 套餐的用户请到对应套餐控制台获取专属 Key 和地址。",apiBase:"https://dashscope.aliyuncs.com/compatible-mode/v1",autoV1:!1,protocol:"openai",presetModels:["qwen3.8-max","qwen3.7-plus"]},{id:"openai",name:"OpenAI(按量 API)",alias:"openai",website:"https://platform.openai.com",keyUrl:"https://platform.openai.com/api-keys",keyNote:"登录 OpenAI 平台 →「API keys」→ 创建新密钥。官方支持 /v1/chat/completions 与 /v1/responses 两种协议(不支持 Anthropic 协议)。",apiBase:"https://api.openai.com/v1",autoV1:!1,protocol:"openai",presetModels:["gpt-5.6-sol","gpt-5.5"]},{id:"custom",name:"自定义 / OpenAI 兼容中转",alias:"",keyNote:"不使用模板预填,按中转站文档填写即可;协议拿不准先用「测试」验证。",apiBase:"",autoV1:!0,protocol:"openai"}];function Xu(e){const{toast:t}=un(),n=Pe(!1),o=Pe(null),i=gn({}),a=()=>{for(const f of Object.keys(i))delete i[f]},r=()=>{o.value=null},s=async()=>{const f=e.api_key.trim(),u=e.api_base.trim();if(!(!f||!u)){o.value={loading:!0};try{const p=await Yt.post("/api/test",{api_base:u,api_key:f,protocol:e.protocol,autoV1:e.autoV1});p.status==="ok"?(o.value={loading:!1,status:"ok",msg:`连接成功 (${p.models??0} 个模型)`},t("连接成功","success")):(o.value={loading:!1,status:"fail",msg:p.message},t(`连接失败: ${p.message}`,"error"))}catch(p){o.value={loading:!1,status:"fail",msg:p.message},t(p.message,"error")}}},l=async f=>{i[f.full_name]={loading:!0};try{const u=await Yt.post("/api/test/model",{model:f.upstream,api_base:e.api_base.trim(),api_key:e.api_key.trim(),protocol:f.protocol||e.protocol,autoV1:e.autoV1});i[f.full_name]={loading:!1,status:u.status==="ok"?"ok":"fail",msg:u.status==="ok"&&u.latency!=null?`${u.message} · ${u.latency}ms`:u.message,request:u.request,response:u.response},t(u.status==="ok"?"模型可用":`模型不可用: ${u.message}`,u.status==="ok"?"success":"error")}catch(u){i[f.full_name]={loading:!1,status:"fail",msg:u.message},t(u.message,"error")}};return{testingAll:n,keyStatus:o,modelTest:i,testKey:s,testModel:l,testAll:async()=>{const f=[...e.models];if(f.length){n.value=!0;try{await Promise.all(f.map(u=>l(u)))}finally{n.value=!1}}},clearModelTest:a,resetKeyStatus:r}}const Ku={key:0,class:"detail-body"},Gu={class:"detail-head"},Hu={class:"detail-name"},Wu={class:"muted-sm"},Yu={class:"detail-pre"},zu={class:"detail-pre"},Ju=Jt({__name:"TestDetailDialog",props:{modelValue:{type:Boolean},detail:{}},emits:["update:modelValue"],setup(e,{emit:t}){const n=e,o=t,i=Pe("request");Xo(()=>n.modelValue,r=>{r&&(i.value="request")});const a=r=>{if(r==null)return"(无)";try{const s=new WeakSet;return JSON.stringify(r,(l,c)=>{if(c&&typeof c=="object"){if(s.has(c))return"[circular]";s.add(c)}return c},2)}catch{return String(r)}};return(r,s)=>{const l=J("el-tag"),c=J("el-tab-pane"),f=J("el-tabs"),u=J("el-button"),p=J("el-dialog");return te(),Me(p,{"model-value":e.modelValue,title:"测试详情",width:"900px",top:"5vh","align-center":"","append-to-body":"","onUpdate:modelValue":s[2]||(s[2]=d=>o("update:modelValue",d))},{footer:M(()=>[P(u,{type:"primary",onClick:s[1]||(s[1]=d=>o("update:modelValue",!1))},{default:M(()=>[...s[3]||(s[3]=[ae("关闭",-1)])]),_:1})]),default:M(()=>[e.detail?(te(),Be("div",Ku,[K("div",Gu,[K("span",Hu,Te(e.detail.name),1),P(l,{type:e.detail.status==="ok"?"success":"danger",size:"small"},{default:M(()=>[ae(Te(e.detail.status==="ok"?"成功":"失败"),1)]),_:1},8,["type"]),K("span",Wu,Te(e.detail.msg),1)]),P(f,{modelValue:i.value,"onUpdate:modelValue":s[0]||(s[0]=d=>i.value=d)},{default:M(()=>[P(c,{label:"请求参数 (Request)",name:"request"},{default:M(()=>[K("pre",Yu,Te(a(e.detail.request)),1)]),_:1}),P(c,{label:"响应数据 (Response)",name:"response"},{default:M(()=>[K("pre",zu,Te(a(e.detail.response)),1)]),_:1})]),_:1},8,["modelValue"])])):tt("",!0)]),_:1},8,["model-value"])}}}),Qu=cn(Ju,[["__scopeId","data-v-08dfa117"]]),Zu={class:"protocol-help"},_u={class:"help-item"},qu={class:"help-title"},ef={class:"help-item"},tf={class:"help-title"},nf={class:"help-item"},rf={class:"help-title"},of={class:"help-item"},af=Jt({__name:"ProtocolHelpDialog",props:{modelValue:{type:Boolean}},emits:["update:modelValue"],setup(e,{emit:t}){const n=t,o=[{client:"Claude Code",endpoint:"/v1/messages",note:"Anthropic 协议入口;上游优先选 Anthropic Messages(官方支持时),缓存/思维链原生保留"},{client:"Codex CLI",endpoint:"/v1/chat/completions",note:"OpenAI Chat 协议入口;上游协议随意,网关自动转换"},{client:"其他 OpenAI SDK / 工具",endpoint:"/v1/chat/completions",note:"OpenAI Chat 协议入口(chat/completions 是事实标准)"}];return(i,a)=>{const r=J("el-tag"),s=J("el-divider"),l=J("el-table-column"),c=J("el-table"),f=J("el-button"),u=J("el-dialog");return te(),Me(u,{"model-value":e.modelValue,title:"上游协议怎么选?",width:"760px","align-center":"","append-to-body":"","onUpdate:modelValue":a[1]||(a[1]=p=>n("update:modelValue",p))},{footer:M(()=>[P(f,{type:"primary",onClick:a[0]||(a[0]=p=>n("update:modelValue",!1))},{default:M(()=>[...a[15]||(a[15]=[ae("我知道了",-1)])]),_:1})]),default:M(()=>[K("div",Zu,[a[13]||(a[13]=K("p",{class:"help-intro"}," 协议就是上游 API「说话的格式」——同样的模型,接口路径、请求和响应的字段都不一样。选错格式,请求会直接失败。 ",-1)),K("div",_u,[K("div",qu,[a[3]||(a[3]=ae("OpenAI Chat Completions ",-1)),P(r,{size:"small",type:"primary"},{default:M(()=>[...a[2]||(a[2]=[ae("最常用",-1)])]),_:1})]),a[4]||(a[4]=K("p",null,"业界事实标准。DeepSeek、通义、Kimi、智谱、火山方舟等绝大多数国内外厂商,以及各类 OpenAI 兼容中转站,都用这套格式。",-1))]),K("div",ef,[K("div",tf,[a[6]||(a[6]=ae("Anthropic Messages ",-1)),P(r,{size:"small",type:"success"},{default:M(()=>[...a[5]||(a[5]=[ae("推荐优先",-1)])]),_:1})]),a[7]||(a[7]=K("p",null,[ae(" Claude 官方格式,以 /v1/messages 为标志。DeepSeek 官方 API 等少数厂商原生支持。 "),K("strong",null,"如果上游官方支持,优先选它"),ae("——尤其在 Claude Code 这类客户端场景下,能原生保留缓存控制(省 token 费用)、思维链等能力,避免协议来回转换造成损耗。 ")],-1))]),K("div",nf,[K("div",rf,[a[9]||(a[9]=ae("OpenAI Responses ",-1)),P(r,{size:"small",type:"info"},{default:M(()=>[...a[8]||(a[8]=[ae("小众",-1)])]),_:1})]),a[10]||(a[10]=K("p",null,"OpenAI 官方推出的新一代接口(/v1/responses),目前基本只有 OpenAI 自家在用。",-1))]),P(s),K("div",of,[a[11]||(a[11]=K("div",{class:"help-title"},"常用客户端对照表",-1)),a[12]||(a[12]=K("p",{class:"help-table-note"},"客户端接入本网关后用哪个入口,是客户端自己的属性,与上游协议选择无关;网关负责两边互转。",-1)),P(c,{data:o,size:"small",border:"",class:"help-table"},{default:M(()=>[P(l,{prop:"client",label:"客户端",width:"150"}),P(l,{prop:"endpoint",label:"网关入口",width:"190"}),P(l,{prop:"note",label:"说明","min-width":"220"})]),_:1})]),a[14]||(a[14]=K("div",{class:"help-item"},[K("div",{class:"help-title"},"还是拿不准?"),K("p",null,"先选 OpenAI Chat Completions,添加模型后用「测试」按钮验证:成功即选对;报 404 / format 类错误时,换 Anthropic Messages 再试。")],-1))])]),_:1},8,["model-value"])}}}),sf=cn(af,[["__scopeId","data-v-2248b61a"]]),lf={class:"full-width mb-8"},cf={class:"flex-gap-8 mb-8"},uf={class:"model-select-wrap"},ff={class:"muted-13"},df={key:0,class:"muted-12"},pf=Jt({__name:"ProviderModelEditor",props:{form:{},modelTest:{},testingAll:{type:Boolean},editingName:{}},emits:["test-model","test-all","show-test-detail"],setup(e,{expose:t,emit:n}){const o=e,i=n,{toast:a}=un(),r=Pe([]),s=Pe([]),l=Ht(()=>r.value.filter(v=>!o.form.models.some(g=>g.full_name===(o.form.alias.trim()?`${o.form.alias.trim()}/${v}`:v)))),c=()=>{const v=o.form.alias.trim();for(const g of s.value){const y=g.trim();if(!y)continue;r.value.includes(y)||r.value.push(y);let I=v?`${v}/${y}`:y,S=2;for(;o.form.models.some(C=>C.full_name===I);)I=`${v?`${v}/`:""}${y}-${S}`,S+=1;o.form.models.push({full_name:I,upstream:y,protocol:o.form.protocol})}s.value=[]},f=v=>{o.form.models.splice(v,1)};t({loadCachedModels:async v=>{const g=await Yt.get(`/api/test/models-cache/${encodeURIComponent(v)}`).catch(()=>({models:[]}));r.value=g.models||[]},addPresetModels:v=>{r.value=[...v],s.value=[...v],c()},resetState:()=>{r.value=[],s.value=[]}});const m=Pe(!1),h=async()=>{var v;m.value=!0;try{const g=o.editingName!=null?o.editingName:`new::${o.form.api_base.trim()}`,y=await Yt.post("/api/test/fetch-models",{api_base:o.form.api_base.trim(),api_key:o.form.api_key.trim(),keyId:g,protocol:o.form.protocol,autoV1:o.form.autoV1});y.status==="ok"&&((v=y.models)==null?void 0:v.length)>0?(r.value=[...new Set([...r.value,...y.models])],a(`已获取 ${y.models.length} 个模型`,"success")):/404/.test(y.message||"")?a("该上游不支持获取模型列表(404),请手动输入模型名,或到官网文档查看支持的模型","error"):a(y.message||"未获取到模型","error")}catch(g){a(g.message,"error")}finally{m.value=!1}};return(v,g)=>{const y=J("el-icon"),I=J("el-tooltip"),S=J("el-alert"),C=J("el-option"),A=J("el-select"),B=J("el-button"),w=J("el-table-column"),O=J("el-input"),L=J("el-link"),j=J("el-table"),R=J("el-form-item");return te(),Me(R,{prop:"models"},{label:M(()=>[g[2]||(g[2]=K("span",null,"模型列表",-1)),P(I,{placement:"top",content:"这家供应商下你要用哪些模型。至少添加一个才能保存;客户端请求时填「模型全名」即可路由到这里。"},{default:M(()=>[P(y,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1})]),default:M(()=>[K("div",lf,[P(S,{type:"info",closable:!1,"show-icon":"",title:"此处测试为直连上游(不经过网关),仅验证连通性;保存后可在列表卡片中测试完整代理链路。"})]),K("div",cf,[K("div",uf,[P(A,{modelValue:s.value,"onUpdate:modelValue":g[0]||(g[0]=E=>s.value=E),multiple:"","collapse-tags":"",filterable:"","allow-create":"","default-first-option":"",placeholder:"搜索或输入模型名"},{default:M(()=>[(te(!0),Be(Bo,null,ko(l.value,E=>(te(),Me(C,{key:E,label:E,value:E},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),P(B,{onClick:c,disabled:!s.value.length},{default:M(()=>[...g[3]||(g[3]=[ae("添加",-1)])]),_:1},8,["disabled"]),P(B,{loading:m.value,disabled:!e.form.api_base||!e.form.api_key,onClick:h},{default:M(()=>[ae(Te(m.value?"":"获取模型列表"),1)]),_:1},8,["loading","disabled"]),P(B,{loading:e.testingAll,disabled:!e.form.models.length||!e.form.api_base||!e.form.api_key,onClick:g[1]||(g[1]=E=>i("test-all"))},{default:M(()=>[ae(Te(e.testingAll?"":"测试全部"),1)]),_:1},8,["loading","disabled"])]),P(j,{border:"",data:e.form.models,class:"full-width","empty-text":"暂无模型"},{default:M(()=>[P(w,{type:"index",label:"#",width:"50",align:"center"}),P(w,{"min-width":"260"},{header:M(()=>[g[4]||(g[4]=K("span",{class:"col-help"},"模型全名(可编辑)",-1)),P(I,{placement:"top",content:"发请求时实际使用的模型名称(客户端填的 model 参数),默认 = 别名/上游模型名,可自由修改;全局唯一,点击可复制。"},{default:M(()=>[P(y,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1})]),default:M(({row:E})=>[P(O,{modelValue:E.full_name,"onUpdate:modelValue":N=>E.full_name=N},null,8,["modelValue","onUpdate:modelValue"])]),_:1}),P(w,{prop:"upstream","min-width":"180"},{header:M(()=>[g[5]||(g[5]=K("span",{class:"col-help"},"上游模型",-1)),P(I,{placement:"top",content:"供应商 API 真实的模型标识(如 deepseek-chat、gpt-4o),请求会被转发给这个模型;同一上游模型可添加多次(如配不同协议),但模型全名不能重复。"},{default:M(()=>[P(y,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1})]),default:M(({row:E})=>[K("span",ff,Te(E.upstream),1)]),_:1}),P(w,{width:"230"},{header:M(()=>[g[6]||(g[6]=K("span",{class:"col-help"},"上游协议",-1)),P(I,{placement:"top",content:"请求该模型时使用的 API 格式,默认继承上方供应商协议;个别模型可单独改(如同一供应商既有 OpenAI 风格又有 Anthropic 风格的模型)。"},{default:M(()=>[P(y,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1})]),default:M(({row:E})=>[P(A,{modelValue:E.protocol,"onUpdate:modelValue":N=>E.protocol=N,class:"full-width",size:"small"},{default:M(()=>[P(C,{label:"Anthropic Messages",value:"anthropic"}),P(C,{label:"OpenAI Chat Completions",value:"openai"}),P(C,{label:"OpenAI Responses",value:"openai-responses"})]),_:1},8,["modelValue","onUpdate:modelValue"])]),_:1}),P(w,{label:"测试结果(直连)",width:"200",align:"center"},{default:M(({row:E})=>{var N,V;return[(N=e.modelTest[E.full_name])!=null&&N.loading?(te(),Be("span",df,"测试中...")):(V=e.modelTest[E.full_name])!=null&&V.status?(te(),Me(L,{key:1,type:e.modelTest[E.full_name].status==="ok"?"success":"danger",class:"test-result-link",onClick:F=>i("show-test-detail",E.full_name)},{default:M(()=>[ae(Te(e.modelTest[E.full_name].msg),1)]),_:2},1032,["type","onClick"])):tt("",!0)]}),_:1}),P(w,{width:"140",align:"center",label:"操作"},{default:M(({row:E})=>{var N;return[P(B,{link:"",loading:(N=e.modelTest[E.full_name])==null?void 0:N.loading,disabled:!e.form.api_base||!e.form.api_key,onClick:V=>i("test-model",E)},{default:M(()=>[...g[7]||(g[7]=[ae("测试",-1)])]),_:1},8,["loading","disabled","onClick"]),P(B,{link:"",type:"danger",onClick:V=>f(e.form.models.indexOf(E))},{default:M(()=>[...g[8]||(g[8]=[ae("删除",-1)])]),_:1},8,["onClick"])]}),_:1})]),_:1},8,["data"])]),_:1})}}}),hf=cn(pf,[["__scopeId","data-v-e64a6809"]]),mf={class:"dialog-body"},vf={class:"flex-gap-8 full-width"},gf={class:"full-url-toggle label-inline-toggle"},yf={key:0,class:"muted-sm"},Ef={key:0,class:"mt-4"},Sf={key:0,class:"test-ok-text"},bf={key:1,class:"test-fail-text"},Tf={key:1,class:"muted-sm"},Of={class:"flex-gap-8 flex-center"},If=Jt({__name:"ProviderModal",props:{editName:{},provider:{},cloneOf:{}},emits:["close","saved"],setup(e,{emit:t}){const n=e,o=t,{toast:i}=un(),a=Ko(),r=Pe(n.editName),s=Ht(()=>n.editName!=null),l=Pe(""),c=Ht(()=>Co.find(X=>X.id===l.value)),f=X=>{var ue;const D=Co.find(Y=>Y.id===X);D&&(d.name=D.name,d.alias=D.alias,d.website=D.website||"",d.api_base=D.apiBase,d.autoV1=D.autoV1,d.protocol=D.protocol,(ue=D.presetModels)!=null&&ue.length&&!d.models.length&&w(D.presetModels))},u=()=>{var D;const X=(D=c.value)==null?void 0:D.keyUrl;X&&window.open(X,"_blank","noopener")},p=()=>{const X=d.website.trim();X&&R(X)&&window.open(X,"_blank","noopener")},d=gn({name:"",alias:"",website:"",api_base:"",protocol:"anthropic",api_key:"",autoV1:!0,models:[]}),{testingAll:m,keyStatus:h,modelTest:v,testKey:g,testModel:y,testAll:I,clearModelTest:S,resetKeyStatus:C}=Xu(d),A=Pe(null),B=X=>{var D;return(D=A.value)==null?void 0:D.loadCachedModels(X)},w=X=>{var D;return(D=A.value)==null?void 0:D.addPresetModels(X)},O=()=>{var X;return(X=A.value)==null?void 0:X.resetState()},L=Pe(),j=Pe(!1),R=X=>{try{const D=new URL(X);return D.protocol==="http:"||D.protocol==="https:"}catch{return!1}},E=(X,D,ue)=>{!D||R(D)?ue():ue(new Error("请输入有效的 URL(以 http:// 或 https:// 开头)"))},N={name:[{required:!0,message:"请输入供应商名称",trigger:"blur"}],alias:[{required:!0,message:"请输入供应商英文名称(别名)",trigger:"blur"}],website:[{validator:E,trigger:"blur"}],api_base:[{required:!0,message:"请输入请求地址 (API Base)",trigger:"blur"},{validator:E,trigger:"blur"}],api_key:[{required:!0,message:"请输入 API Key",trigger:"blur"}]},V={anthropic:"/messages",openai:"/chat/completions","openai-responses":"/responses"},F=Ht(()=>{const X=d.api_base.trim().replace(/\/+$/,"");if(!X)return"";const D=V[d.protocol]||"";return d.autoV1&&!/\/v\d+$/i.test(X)?`${X}/v1${D}`:`${X}${D}`}),U=()=>{var X;Object.assign(d,{name:"",alias:"",website:"",api_base:"",protocol:"anthropic",api_key:"",autoV1:!0,models:[]}),(X=L.value)==null||X.clearValidate(),l.value="",O(),C(),S(),ce.value=!1,ge.value=null},z=async()=>{var D,ue;U();const X=n.provider;if(n.editName!=null&&X)await B(X.name),Object.assign(d,{name:X.name||"",alias:X.alias||"",website:X.website||"",api_base:X.apiBase||"",protocol:X.customLlmProvider||"anthropic",api_key:X.apiKey||"",autoV1:X.autoV1!==!1,models:X.models.map(Y=>({full_name:Y.modelName,upstream:Y.model,protocol:Y.customLlmProvider||X.customLlmProvider||"anthropic"}))});else if(n.cloneOf){const Y=n.cloneOf;Y.name&&await B(Y.name);const Oe=(D=Y.alias)==null?void 0:D.trim(),be=Oe?`${Oe}-copy`:"copy",Je=`${((ue=Y.name)==null?void 0:ue.trim())||Oe||"供应商"}副本`;Object.assign(d,{name:Je,alias:be,website:Y.website||"",api_base:Y.apiBase||"",protocol:Y.customLlmProvider||"anthropic",api_key:Y.apiKey||"",autoV1:Y.autoV1!==!1,models:(Y.models||[]).map(Le=>{let we=Le.modelName;return Oe&&we.startsWith(`${Oe}/`)&&(we=`${be}/${we.slice(Oe.length+1)}`),{full_name:we,upstream:Le.model,protocol:Le.customLlmProvider||Y.customLlmProvider||"anthropic"}})})}};la(()=>{r.value=n.editName,z()}),Xo(()=>n.editName,async X=>{r.value=X,await z()});const ce=Pe(!1),Se=Pe(!1),ge=Pe(null),Ee=X=>{const D=v[X];!D||D.loading||(ge.value={name:X,status:D.status||"",msg:D.msg||"",request:D.request,response:D.response},ce.value=!0)},Ae=async()=>{var vt;if(!await((vt=L.value)==null?void 0:vt.validate().catch(()=>!1))||!d.models.length)return;const D=d.models.map(ne=>({full_name:ne.full_name.trim(),upstream:ne.upstream.trim(),protocol:ne.protocol||d.protocol})).filter(ne=>ne.full_name);if(!D.length){i("请至少填写一个有效的模型名称","error");return}const ue=d.name.trim(),Y=d.alias.trim(),Oe=d.website.trim(),be=d.api_base.trim(),Je=d.api_key.trim(),Le=a.suppliers.filter(ne=>ne.name!==r.value);if(Le.some(ne=>ne.name===ue)){i(`供应商名称已存在: ${ue}`,"error");return}if(Y&&Le.some(ne=>(ne.alias??"").trim()===Y)){i(`供应商别名已存在: ${Y}`,"error");return}const we={name:ue,...Y?{alias:Y}:{},...Oe?{website:Oe}:{},customLlmProvider:d.protocol,apiKey:Je,apiBase:be,...d.autoV1?{}:{autoV1:!1},models:D.map(ne=>({modelName:ne.full_name,model:ne.upstream,...ne.protocol&&ne.protocol!==d.protocol?{customLlmProvider:ne.protocol}:{}}))};if(we.models.some(ne=>ne.model.includes("/"))){i("上游模型名不得包含 /","error");return}const Ie=[...Le.flatMap(ne=>ne.models.map(re=>re.modelName)),...D.map(ne=>ne.full_name)],Fe=new Set;for(const ne of Ie){if(Fe.has(ne)){i(`模型名称重复: ${ne}`,"error");return}Fe.add(ne)}j.value=!0;try{const ne=r.value==null,re=await a.saveProviders(ne?[we,...Le]:[...Le,we]);ne&&a.moveProviderToTop(ue),i(re.message||"供应商已保存","success"),o("saved")}catch(ne){i(ne.message,"error")}finally{j.value=!1}};return(X,D)=>{const ue=J("el-alert"),Y=J("el-option"),Oe=J("el-select"),be=J("el-form-item"),Je=J("el-icon"),Le=J("el-tooltip"),we=J("el-input"),Ie=J("el-button"),Fe=J("el-switch"),vt=J("el-form"),ne=J("el-dialog");return te(),Me(ne,{"model-value":!0,title:r.value?"编辑供应商":"添加供应商",width:"1200px",top:"3vh","align-center":"","close-on-click-modal":!1,onClose:D[12]||(D[12]=re=>o("close"))},{footer:M(()=>[K("div",Of,[P(Ie,{onClick:D[11]||(D[11]=re=>o("close")),disabled:j.value},{default:M(()=>[...D[27]||(D[27]=[ae(" 取消 ",-1)])]),_:1},8,["disabled"]),P(Ie,{type:"primary",loading:j.value,onClick:Ae,disabled:!d.models.length||!d.api_base||!d.api_key||j.value},{default:M(()=>[ae(Te(j.value?"保存中...":r.value?"保存":"添加供应商"),1)]),_:1},8,["loading","disabled"])])]),default:M(()=>[K("div",mf,[!s.value&&!n.cloneOf?(te(),Me(ue,{key:0,class:"mb-16",type:"info",closable:!1,"show-icon":"",title:"添加流程:选模板 → 去平台创建 API Key → 粘贴 Key → 测试 → 保存。全新手建议从「供应商模板」开始。"})):tt("",!0),P(vt,{ref_key:"formRef",ref:L,model:d,rules:N,"label-position":"top"},{default:M(()=>[!s.value&&!n.cloneOf?(te(),Me(be,{key:0,label:"供应商模板"},{default:M(()=>[K("div",vf,[P(Oe,{modelValue:l.value,"onUpdate:modelValue":D[0]||(D[0]=re=>l.value=re),class:"full-width",placeholder:"选择模板快速填充,或选「自定义」手动填写",onChange:f},{default:M(()=>[(te(!0),Be(Bo,null,ko(q(Co),re=>(te(),Me(Y,{key:re.id,label:re.name,value:re.id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),D[13]||(D[13]=K("div",{class:"muted-sm"},"内置常用厂商的地址和配置,选中后自动填充下方所有字段,仍可自由修改",-1))]),_:1})):tt("",!0),P(be,{prop:"name"},{label:M(()=>[D[14]||(D[14]=K("span",null,"供应商名称",-1)),P(Le,{placement:"top",content:"给你接入的 AI 服务起个名字,只在管理界面显示,随便起(如:DeepSeek、公司中转、朋友的号)。"},{default:M(()=>[P(Je,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1})]),default:M(()=>[P(we,{modelValue:d.name,"onUpdate:modelValue":D[1]||(D[1]=re=>d.name=re),modelModifiers:{trim:!0},placeholder:"如:DeepSeek(仅用于界面展示)"},null,8,["modelValue"])]),_:1}),P(be,{prop:"alias"},{label:M(()=>[D[15]||(D[15]=K("span",null,"供应商英文名称(别名)",-1)),P(Le,{placement:"top",content:"模型名的统一前缀。添加模型后名字会变成 前缀/模型名(如 ds/deepseek-chat),客户端选择模型时一眼能看出属于哪家。仅限英文小写。"},{default:M(()=>[P(Je,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1})]),default:M(()=>[P(we,{modelValue:d.alias,"onUpdate:modelValue":D[2]||(D[2]=re=>d.alias=re),modelModifiers:{trim:!0},placeholder:"如:ds"},null,8,["modelValue"]),D[16]||(D[16]=K("div",{class:"muted-sm"},"添加模型时的默认名称前缀,如 ds/deepseek-chat",-1))]),_:1}),P(be,{prop:"website"},{label:M(()=>[D[18]||(D[18]=K("span",null,"官网链接",-1)),P(Le,{placement:"top",content:"选填。方便以后回来查文档、看模型列表;填了之后这里会出现「打开链接」按钮。"},{default:M(()=>[P(Je,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1}),d.website?(te(),Me(Ie,{key:0,class:"label-action-btn",link:"",type:"primary",onClick:p},{default:M(()=>[...D[17]||(D[17]=[ae("打开链接",-1)])]),_:1})):tt("",!0)]),default:M(()=>[P(we,{modelValue:d.website,"onUpdate:modelValue":D[3]||(D[3]=re=>d.website=re),modelModifiers:{trim:!0},placeholder:"https://platform.deepseek.com(可选)"},null,8,["modelValue"])]),_:1}),P(be,{prop:"api_base"},{label:M(()=>[D[20]||(D[20]=K("span",null,"请求地址 (API Base)",-1)),P(Le,{placement:"top",content:"网关往哪发请求。官方厂商在「API 文档」里找,通常长得像 https://api.xxx.com;中转站会直接给你这个地址。模板会自动填好。"},{default:M(()=>[P(Je,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1}),K("div",gf,[D[19]||(D[19]=K("span",{class:"muted-13"},"自动补全 /v1",-1)),P(Fe,{modelValue:d.autoV1,"onUpdate:modelValue":D[4]||(D[4]=re=>d.autoV1=re)},null,8,["modelValue"])])]),default:M(()=>[P(we,{modelValue:d.api_base,"onUpdate:modelValue":D[5]||(D[5]=re=>d.api_base=re),modelModifiers:{trim:!0},placeholder:"https://api.deepseek.com"},null,8,["modelValue"]),F.value?(te(),Be("div",yf," 实际请求地址:"+Te(F.value)+"(开启自动补全时,地址末尾无 /v1~v9 版本段会插入 /v1;上游无版本前缀请关闭) ",1)):tt("",!0)]),_:1}),P(be,null,{label:M(()=>[D[22]||(D[22]=K("span",null,"上游协议 (Protocol)",-1)),P(Ie,{class:"label-action-btn",link:"",type:"primary",onClick:D[6]||(D[6]=re=>Se.value=!0)},{default:M(()=>[...D[21]||(D[21]=[ae(" 如何选择 ",-1)])]),_:1})]),default:M(()=>[P(Oe,{modelValue:d.protocol,"onUpdate:modelValue":D[7]||(D[7]=re=>d.protocol=re)},{default:M(()=>[P(Y,{label:"Anthropic Messages",value:"anthropic"}),P(Y,{label:"OpenAI Chat Completions",value:"openai"}),P(Y,{label:"OpenAI Responses",value:"openai-responses"})]),_:1},8,["modelValue"]),D[23]||(D[23]=K("div",{class:"muted-sm protocol-hint"},"上游接口的 API 风格,选错会请求失败;拿不准时先用下方「测试」逐个验证。",-1))]),_:1}),P(be,{prop:"api_key"},{label:M(()=>{var re,xt;return[D[26]||(D[26]=K("span",null,"API Key",-1)),P(Le,{placement:"top",content:"你在上游平台的「钥匙」,证明请求是你发的、从你账户扣费。在平台控制台创建,形如 sk- 开头的一串字符,粘贴到这里即可。"},{default:M(()=>[P(Je,{class:"col-help-icon"},{default:M(()=>[P(q(Rt))]),_:1})]),_:1}),(re=c.value)!=null&&re.keyUrl?(te(),Me(Ie,{key:0,class:"label-action-btn",link:"",type:"primary",onClick:u},{default:M(()=>[...D[24]||(D[24]=[ae("获取 Key",-1)])]),_:1})):tt("",!0),P(Ie,{class:"label-action-btn",link:"",type:"primary",loading:(xt=q(h))==null?void 0:xt.loading,disabled:!d.api_base||!d.api_key,onClick:q(g)},{default:M(()=>[...D[25]||(D[25]=[ae("测试",-1)])]),_:1},8,["loading","disabled","onClick"])]}),default:M(()=>{var re;return[P(we,{modelValue:d.api_key,"onUpdate:modelValue":D[8]||(D[8]=xt=>d.api_key=xt),modelModifiers:{trim:!0},placeholder:"如:sk-xxxxxxxx(DeepSeek 开放平台密钥)",onKeyup:$s(q(g),["enter"])},null,8,["modelValue","onKeyup"]),q(h)&&!q(h).loading?(te(),Be("div",Ef,[q(h).status==="ok"?(te(),Be("span",Sf,Te(q(h).msg),1)):q(h).status==="fail"?(te(),Be("span",bf,Te(q(h).msg),1)):tt("",!0)])):tt("",!0),(re=c.value)!=null&&re.keyNote?(te(),Be("div",Tf,Te(c.value.keyNote),1)):tt("",!0)]}),_:1}),P(hf,{ref_key:"modelEditorRef",ref:A,form:d,"model-test":q(v),"testing-all":q(m),"editing-name":r.value,onTestModel:q(y),onTestAll:q(I),onShowTestDetail:Ee},null,8,["form","model-test","testing-all","editing-name","onTestModel","onTestAll"])]),_:1},8,["model"])]),P(Qu,{modelValue:ce.value,"onUpdate:modelValue":D[9]||(D[9]=re=>ce.value=re),detail:ge.value},null,8,["modelValue","detail"]),P(sf,{modelValue:Se.value,"onUpdate:modelValue":D[10]||(D[10]=re=>Se.value=re)},null,8,["modelValue"])]),_:1},8,["title"])}}}),Nf=cn(If,[["__scopeId","data-v-097689eb"]]),Cf={class:"models-dialog-body"},Af=["onClick"],xf={class:"muted-13"},Pf={key:3,class:"muted-disabled"},Df={key:0,class:"muted-12"},Rf={key:1,class:"muted-disabled"},Mf={key:0,class:"muted-12"},Lf={key:1,class:"muted-disabled"},wf=Jt({__name:"ProviderModelsDialog",props:{modelValue:{type:Boolean},providerName:{}},emits:["update:modelValue","copy-model","changed"],setup(e,{emit:t}){const n=e,o=t,{toast:i}=un(),a=Ko(),r=Ai(),s=Ht(()=>n.providerName!=null?a.suppliers.find(f=>f.name===n.providerName):void 0),l=Ht(()=>{const f=s.value;return f?f.alias&&f.alias!==f.name?`${f.name}(${f.alias})`:f.name:""}),c=async f=>{try{await Ao.confirm(`确定删除模型 "${f}"?`,"确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await a.deleteModel(f),o("changed"),i("模型已删除","success")}catch(u){u!=="cancel"&&i(u.message,"error")}};return(f,u)=>{const p=J("el-alert"),d=J("el-table-column"),m=J("el-tag"),h=J("el-tooltip"),v=J("el-button"),g=J("el-table"),y=J("el-empty"),I=J("el-dialog");return te(),Me(I,{"model-value":e.modelValue,title:l.value,width:"1200px",top:"3vh","destroy-on-close":"","onUpdate:modelValue":u[0]||(u[0]=S=>o("update:modelValue",S))},{default:M(()=>[K("div",Cf,[s.value?(te(),Me(p,{key:0,class:"mb-8",type:"info",closable:!1,"show-icon":"",title:"测试走网关代理:请求经本网关转发至上游(含协议转换、计费记录),验证完整链路;编辑弹窗内测试为直连上游,仅验证连通性。"})):tt("",!0),s.value&&s.value.models.length?(te(),Me(g,{key:1,border:"",data:s.value.models,stripe:"",class:"models-table full-width"},{default:M(()=>[P(d,{prop:"modelName",label:"模型名称","min-width":"220"},{default:M(({row:S})=>[K("span",{class:"link-blue",onClick:C=>o("copy-model",S.modelName),title:"点击复制"},Te(S.modelName),9,Af)]),_:1}),P(d,{prop:"model",label:"上游模型","min-width":"180"},{default:M(({row:S})=>[K("span",xf,Te(S.model),1)]),_:1}),P(d,{prop:"customLlmProvider",label:"上游协议",width:"100",align:"center"},{default:M(({row:S})=>[P(m,{type:"info"},{default:M(()=>[ae(Te(S.customLlmProvider||s.value.customLlmProvider),1)]),_:2},1024)]),_:1}),P(d,{label:"状态",width:"150",align:"center"},{default:M(({row:S})=>[q(r).modelStatus[S.modelName]==="ok"?(te(),Me(m,{key:0,type:"success"},{default:M(()=>[...u[1]||(u[1]=[ae("通过",-1)])]),_:1})):q(r).modelStatus[S.modelName]==="error"?(te(),Me(h,{key:1,content:q(r).modelMessage[S.modelName],placement:"top","show-after":300},{default:M(()=>[P(m,{type:"danger",class:"error-tag"},{default:M(()=>[ae(Te(q(r).modelMessage[S.modelName]),1)]),_:2},1024)]),_:2},1032,["content"])):q(r).modelStatus[S.modelName]==="testing"?(te(),Me(m,{key:2,type:"warning"},{default:M(()=>[...u[2]||(u[2]=[ae("测试中",-1)])]),_:1})):(te(),Be("span",Pf,"-"))]),_:1}),P(d,{label:"耗时",width:"80",align:"center"},{default:M(({row:S})=>[q(r).modelLatency[S.modelName]?(te(),Be("span",Df,Te((q(r).modelLatency[S.modelName]/1e3).toFixed(1))+"s ",1)):(te(),Be("span",Rf,"-"))]),_:1}),P(d,{label:"上次测试","min-width":"160"},{default:M(({row:S})=>[q(r).modelTime[S.modelName]?(te(),Be("span",Mf,Te(q(r).modelTime[S.modelName]),1)):(te(),Be("span",Lf,"未测试"))]),_:1}),P(d,{label:"操作",width:"140",align:"center"},{default:M(({row:S})=>[P(v,{link:"",loading:q(r).modelStatus[S.modelName]==="testing",onClick:C=>q(r).testProxy(S.modelName)},{default:M(()=>[...u[3]||(u[3]=[ae(" 测试 ",-1)])]),_:1},8,["loading","onClick"]),P(v,{link:"",type:"danger",onClick:C=>c(S.modelName)},{default:M(()=>[...u[4]||(u[4]=[ae(" 删除 ",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"])):s.value?(te(),Me(y,{key:2,description:"暂无模型","image-size":64})):tt("",!0)])]),_:1},8,["model-value","title"])}}}),Vf=cn(wf,[["__scopeId","data-v-a79f8c7b"]]),Ff={class:"muted-sm mb-8"},$f={class:"flex-between"},Uf={class:"flex-gap-8"},jf=Jt({__name:"ConfigFileDialog",props:{modelValue:{type:Boolean}},emits:["update:modelValue","saved"],setup(e,{emit:t}){const n=e,o=t,{toast:i}=un(),a=Pe(""),r=Pe(""),s=Pe(!1);Xo(()=>n.modelValue,async f=>{if(f){a.value="";try{const u=await Yt.get("/api/config");a.value=JSON.stringify(u,null,2)+`
|
|
31
|
-
`,r.value="ellm.config.json"}catch(u){i(u.message,"error")}}});const l=async()=>{try{await navigator.clipboard.writeText(a.value),i("已复制","success")}catch{i("复制失败","error")}},c=async()=>{s.value=!0;try{const f=JSON.parse(a.value),u=await Yt.put("/api/config",f);o("update:modelValue",!1),i(u.message||"配置已保存","success"),o("saved")}catch(f){f instanceof SyntaxError?i(`JSON 解析失败: ${f.message}`,"error"):i(f.message,"error")}finally{s.value=!1}};return(f,u)=>{const p=J("el-input"),d=J("el-button"),m=J("el-dialog");return te(),Me(m,{"model-value":e.modelValue,title:"配置文件",width:"800px",top:"5vh","destroy-on-close":"","onUpdate:modelValue":u[2]||(u[2]=h=>o("update:modelValue",h))},{footer:M(()=>[K("div",$f,[P(d,{onClick:l},{default:M(()=>[...u[3]||(u[3]=[ae("复制",-1)])]),_:1}),K("div",Uf,[P(d,{onClick:u[1]||(u[1]=h=>o("update:modelValue",!1))},{default:M(()=>[...u[4]||(u[4]=[ae("取消",-1)])]),_:1}),P(d,{type:"primary",loading:s.value,onClick:c},{default:M(()=>[...u[5]||(u[5]=[ae("保存并生效",-1)])]),_:1},8,["loading"])])])]),default:M(()=>[K("div",Ff," 配置文件:"+Te(r.value)+"(原样保存,校验通过后热更新生效) ",1),P(p,{type:"textarea",rows:24,modelValue:a.value,"onUpdate:modelValue":u[0]||(u[0]=h=>a.value=h),placeholder:"loading...",spellcheck:"false",class:"full-width"},null,8,["modelValue"])]),_:1},8,["model-value"])}}}),Bf={class:"flex-end mb-16"},kf={key:0,class:"loading-block"},Xf=Jt({__name:"ProvidersView",setup(e){const{toast:t}=un(),n=Ko(),o=Ai(),i=Pe(!1),a=Pe(null),r=Pe(null),s=Pe(!1),l=Pe(null),c=Pe(!1),f=Pe(null),u=Ht({get:()=>n.orderedProviders,set:R=>n.reorderProviders(R)});function p(){}const d=async()=>{await Promise.all([n.loadProviders(),o.loadResults()])},m=()=>{const R={version:2,exported_at:new Date().toISOString(),providers:n.suppliers},E=new Blob([JSON.stringify(R,null,2)],{type:"application/json"}),N=URL.createObjectURL(E),V=document.createElement("a");V.href=N,V.download=`ellm-providers-${new Date().toISOString().slice(0,10)}.json`,document.body.appendChild(V),V.click(),document.body.removeChild(V),URL.revokeObjectURL(N),t("已导出供应商配置","success")},h=()=>{var R;(R=f.value)==null||R.click()},v=R=>{var E,N;return R.customLlmProvider!==void 0||((N=(E=R.models)==null?void 0:E[0])==null?void 0:N.modelName)!==void 0?R:{name:String(R.name??""),...R.alias?{alias:String(R.alias)}:{},customLlmProvider:String(R.protocol??"openai"),...R.api_key?{apiKey:String(R.api_key)}:{},...R.api_base?{apiBase:String(R.api_base)}:{},models:(R.models??[]).map(V=>({modelName:String(V.full_name??""),model:String(V.upstream_model??V.full_name??""),...V.protocol&&V.protocol!==R.protocol?{customLlmProvider:String(V.protocol)}:{},...V.info!==void 0?{info:V.info}:{}}))}},g=async R=>{var V;const E=R.target,N=(V=E.files)==null?void 0:V[0];if(E.value="",!!N)try{const F=await N.text(),U=JSON.parse(F),z=Array.isArray(U)?U:Array.isArray(U.providers)?U.providers:Array.isArray(U.suppliers)?U.suppliers:null;if(!z){t("文件格式错误:未找到 providers","error");return}const ce=z.map(ge=>v(ge));await Ao.confirm(`确定导入 ${ce.length} 个供应商?将覆盖当前配置。`,"导入确认",{confirmButtonText:"导入",cancelButtonText:"取消",type:"warning"});const Se=await n.saveProviders(ce);await d(),t(Se.message||"导入成功","success")}catch(F){F!=="cancel"&&t(F.message||"导入失败","error")}},y=()=>{a.value=null,r.value=null,i.value=!0},I=R=>{a.value=R,r.value=null,i.value=!0},S=R=>{const E=n.suppliers.find(N=>N.name===R);E&&(a.value=null,r.value=E,i.value=!0)},C=()=>{i.value=!1,r.value=null},A=async()=>{i.value=!1,r.value=null,await d()},B=R=>R?R.length<=8?R:`${R.substring(0,6)}...${R.substring(R.length-4)}`:"-",w=R=>R.name||R.alias||B(R.apiKey||""),O=async R=>{try{const E=n.suppliers.find(N=>N.name===R);if(!E)return;await Ao.confirm(`确定删除该供应商(${w(E)})及其所有模型?`,"确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await n.deleteProvider(E),await d(),t("供应商已删除","success")}catch(E){E!=="cancel"&&t(E.message,"error")}},L=R=>{l.value=R,s.value=!0},j=async R=>{try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(R);else{const E=document.createElement("textarea");E.value=R,E.style.position="fixed",E.style.left="-9999px",document.body.appendChild(E),E.select(),document.execCommand("copy"),document.body.removeChild(E)}t(`已复制: ${R}`,"success")}catch{t("复制失败","error")}};return la(d),(R,E)=>{const N=J("el-icon"),V=J("el-button"),F=J("el-empty");return te(),Be("div",null,[K("div",Bf,[P(V,{onClick:m},{default:M(()=>[P(N,null,{default:M(()=>[P(q(Us))]),_:1}),E[4]||(E[4]=ae(" 导出 ",-1))]),_:1}),P(V,{onClick:h},{default:M(()=>[P(N,null,{default:M(()=>[P(q(js))]),_:1}),E[5]||(E[5]=ae(" 导入 ",-1))]),_:1}),P(V,{onClick:E[0]||(E[0]=U=>c.value=!0)},{default:M(()=>[P(N,null,{default:M(()=>[P(q(Bs))]),_:1}),E[6]||(E[6]=ae(" 配置文件 ",-1))]),_:1}),P(V,{type:"primary",onClick:y},{default:M(()=>[P(N,null,{default:M(()=>[P(q(ks))]),_:1}),E[7]||(E[7]=ae(" 添加供应商 ",-1))]),_:1})]),q(n).loading?(te(),Be("div",kf,"加载中...")):q(n).orderedProviders.length===0?(te(),Me(F,{key:1,description:"暂无供应商,点击上方按钮添加"})):(te(),Me(q(Nu),{key:2,modelValue:u.value,"onUpdate:modelValue":E[1]||(E[1]=U=>u.value=U),"item-key":"name",filter:".card-actions","prevent-on-filter":!1,"ghost-class":"ghost","drag-class":"dragging",class:"provider-grid",onChange:p},{item:M(({element:U})=>[P(ku,{provider:U,onClone:z=>S(U.name),onDelete:z=>O(U.name),onEdit:z=>I(U.name),onOpenModels:z=>L(U.name),onCopyModel:j},null,8,["provider","onClone","onDelete","onEdit","onOpenModels"])]),_:1},8,["modelValue"])),i.value?(te(),Me(Nf,{key:3,"edit-name":a.value,provider:a.value!=null?q(n).suppliers.find(U=>U.name===a.value):void 0,"clone-of":r.value,onClose:C,onSaved:A},null,8,["edit-name","provider","clone-of"])):tt("",!0),P(Vf,{modelValue:s.value,"onUpdate:modelValue":E[2]||(E[2]=U=>s.value=U),"provider-name":l.value,onCopyModel:j,onChanged:d},null,8,["modelValue","provider-name"]),P(jf,{modelValue:c.value,"onUpdate:modelValue":E[3]||(E[3]=U=>c.value=U),onSaved:d},null,8,["modelValue"]),K("input",{ref_key:"fileInput",ref:f,type:"file",accept:".json,application/json",style:{display:"none"},onChange:g},null,544)])}}}),
|
|
31
|
+
`,r.value="ellm.config.json"}catch(u){i(u.message,"error")}}});const l=async()=>{try{await navigator.clipboard.writeText(a.value),i("已复制","success")}catch{i("复制失败","error")}},c=async()=>{s.value=!0;try{const f=JSON.parse(a.value),u=await Yt.put("/api/config",f);o("update:modelValue",!1),i(u.message||"配置已保存","success"),o("saved")}catch(f){f instanceof SyntaxError?i(`JSON 解析失败: ${f.message}`,"error"):i(f.message,"error")}finally{s.value=!1}};return(f,u)=>{const p=J("el-input"),d=J("el-button"),m=J("el-dialog");return te(),Me(m,{"model-value":e.modelValue,title:"配置文件",width:"800px",top:"5vh","destroy-on-close":"","onUpdate:modelValue":u[2]||(u[2]=h=>o("update:modelValue",h))},{footer:M(()=>[K("div",$f,[P(d,{onClick:l},{default:M(()=>[...u[3]||(u[3]=[ae("复制",-1)])]),_:1}),K("div",Uf,[P(d,{onClick:u[1]||(u[1]=h=>o("update:modelValue",!1))},{default:M(()=>[...u[4]||(u[4]=[ae("取消",-1)])]),_:1}),P(d,{type:"primary",loading:s.value,onClick:c},{default:M(()=>[...u[5]||(u[5]=[ae("保存并生效",-1)])]),_:1},8,["loading"])])])]),default:M(()=>[K("div",Ff," 配置文件:"+Te(r.value)+"(原样保存,校验通过后热更新生效) ",1),P(p,{type:"textarea",rows:24,modelValue:a.value,"onUpdate:modelValue":u[0]||(u[0]=h=>a.value=h),placeholder:"loading...",spellcheck:"false",class:"full-width"},null,8,["modelValue"])]),_:1},8,["model-value"])}}}),Bf={class:"flex-end mb-16"},kf={key:0,class:"loading-block"},Xf=Jt({__name:"ProvidersView",setup(e){const{toast:t}=un(),n=Ko(),o=Ai(),i=Pe(!1),a=Pe(null),r=Pe(null),s=Pe(!1),l=Pe(null),c=Pe(!1),f=Pe(null),u=Ht({get:()=>n.orderedProviders,set:R=>n.reorderProviders(R)});function p(){}const d=async()=>{await Promise.all([n.loadProviders(),o.loadResults()])},m=()=>{const R={version:2,exported_at:new Date().toISOString(),providers:n.suppliers},E=new Blob([JSON.stringify(R,null,2)],{type:"application/json"}),N=URL.createObjectURL(E),V=document.createElement("a");V.href=N,V.download=`ellm-providers-${new Date().toISOString().slice(0,10)}.json`,document.body.appendChild(V),V.click(),document.body.removeChild(V),URL.revokeObjectURL(N),t("已导出供应商配置","success")},h=()=>{var R;(R=f.value)==null||R.click()},v=R=>{var E,N;return R.customLlmProvider!==void 0||((N=(E=R.models)==null?void 0:E[0])==null?void 0:N.modelName)!==void 0?R:{name:String(R.name??""),...R.alias?{alias:String(R.alias)}:{},customLlmProvider:String(R.protocol??"openai"),...R.api_key?{apiKey:String(R.api_key)}:{},...R.api_base?{apiBase:String(R.api_base)}:{},models:(R.models??[]).map(V=>({modelName:String(V.full_name??""),model:String(V.upstream_model??V.full_name??""),...V.protocol&&V.protocol!==R.protocol?{customLlmProvider:String(V.protocol)}:{},...V.info!==void 0?{info:V.info}:{}}))}},g=async R=>{var V;const E=R.target,N=(V=E.files)==null?void 0:V[0];if(E.value="",!!N)try{const F=await N.text(),U=JSON.parse(F),z=Array.isArray(U)?U:Array.isArray(U.providers)?U.providers:Array.isArray(U.suppliers)?U.suppliers:null;if(!z){t("文件格式错误:未找到 providers","error");return}const ce=z.map(ge=>v(ge));await Ao.confirm(`确定导入 ${ce.length} 个供应商?将覆盖当前配置。`,"导入确认",{confirmButtonText:"导入",cancelButtonText:"取消",type:"warning"});const Se=await n.saveProviders(ce);await d(),t(Se.message||"导入成功","success")}catch(F){F!=="cancel"&&t(F.message||"导入失败","error")}},y=()=>{a.value=null,r.value=null,i.value=!0},I=R=>{a.value=R,r.value=null,i.value=!0},S=R=>{const E=n.suppliers.find(N=>N.name===R);E&&(a.value=null,r.value=E,i.value=!0)},C=()=>{i.value=!1,r.value=null},A=async()=>{i.value=!1,r.value=null,await d()},B=R=>R?R.length<=8?R:`${R.substring(0,6)}...${R.substring(R.length-4)}`:"-",w=R=>R.name||R.alias||B(R.apiKey||""),O=async R=>{try{const E=n.suppliers.find(N=>N.name===R);if(!E)return;await Ao.confirm(`确定删除该供应商(${w(E)})及其所有模型?`,"确认删除",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await n.deleteProvider(E),await d(),t("供应商已删除","success")}catch(E){E!=="cancel"&&t(E.message,"error")}},L=R=>{l.value=R,s.value=!0},j=async R=>{try{if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(R);else{const E=document.createElement("textarea");E.value=R,E.style.position="fixed",E.style.left="-9999px",document.body.appendChild(E),E.select(),document.execCommand("copy"),document.body.removeChild(E)}t(`已复制: ${R}`,"success")}catch{t("复制失败","error")}};return la(d),(R,E)=>{const N=J("el-icon"),V=J("el-button"),F=J("el-empty");return te(),Be("div",null,[K("div",Bf,[P(V,{onClick:m},{default:M(()=>[P(N,null,{default:M(()=>[P(q(Us))]),_:1}),E[4]||(E[4]=ae(" 导出 ",-1))]),_:1}),P(V,{onClick:h},{default:M(()=>[P(N,null,{default:M(()=>[P(q(js))]),_:1}),E[5]||(E[5]=ae(" 导入 ",-1))]),_:1}),P(V,{onClick:E[0]||(E[0]=U=>c.value=!0)},{default:M(()=>[P(N,null,{default:M(()=>[P(q(Bs))]),_:1}),E[6]||(E[6]=ae(" 配置文件 ",-1))]),_:1}),P(V,{type:"primary",onClick:y},{default:M(()=>[P(N,null,{default:M(()=>[P(q(ks))]),_:1}),E[7]||(E[7]=ae(" 添加供应商 ",-1))]),_:1})]),q(n).loading?(te(),Be("div",kf,"加载中...")):q(n).orderedProviders.length===0?(te(),Me(F,{key:1,description:"暂无供应商,点击上方按钮添加"})):(te(),Me(q(Nu),{key:2,modelValue:u.value,"onUpdate:modelValue":E[1]||(E[1]=U=>u.value=U),"item-key":"name",filter:".card-actions","prevent-on-filter":!1,"ghost-class":"ghost","drag-class":"dragging",class:"provider-grid",onChange:p},{item:M(({element:U})=>[P(ku,{provider:U,onClone:z=>S(U.name),onDelete:z=>O(U.name),onEdit:z=>I(U.name),onOpenModels:z=>L(U.name),onCopyModel:j},null,8,["provider","onClone","onDelete","onEdit","onOpenModels"])]),_:1},8,["modelValue"])),i.value?(te(),Me(Nf,{key:3,"edit-name":a.value,provider:a.value!=null?q(n).suppliers.find(U=>U.name===a.value):void 0,"clone-of":r.value,onClose:C,onSaved:A},null,8,["edit-name","provider","clone-of"])):tt("",!0),P(Vf,{modelValue:s.value,"onUpdate:modelValue":E[2]||(E[2]=U=>s.value=U),"provider-name":l.value,onCopyModel:j,onChanged:d},null,8,["modelValue","provider-name"]),P(jf,{modelValue:c.value,"onUpdate:modelValue":E[3]||(E[3]=U=>c.value=U),onSaved:d},null,8,["modelValue"]),K("input",{ref_key:"fileInput",ref:f,type:"file",accept:".json,application/json",style:{display:"none"},onChange:g},null,544)])}}}),Yf=cn(Xf,[["__scopeId","data-v-e250879b"]]);export{Yf as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{u as Y}from"./useToast-MtbkGJiM.js";import{d as F,p as X,b as q,o as m,c as B,w as n,e as $,f as s,t as h,i as D,h as u,g as a,F as H,r as d,E as W,a as c,j as G,_ as Q,l as j,A as ee}from"./index-X5PdkJlA.js";import{u as le}from"./config-CRWaUFQc.js";import{m as K}from"./useManagerApi-C1_COxKg.js";const te={class:"flex-between"},se={class:"muted-sm mb-8"},ae={class:"switch-row"},oe={class:"switch-info"},ne={class:"switch-title"},ue={class:"switch-row"},ie={class:"switch-info"},de={class:"switch-title"},re={class:"switch-row"},ce={class:"switch-info"},ve={class:"switch-title"},pe=F({__name:"HarnessSwitches",setup(J){const{toast:g}=Y(),b=d(!0),E=d(!1),v=d(null),V=d(null),i=d(null),x=d(null),_=d("success"),C=async f=>{f||(v.value?E.value=!0:b.value=!0);try{v.value=await K.harness(),V.value=null}catch(o){f||(V.value=o.message)}finally{f||(b.value=!1,E.value=!1)}};X(()=>C(!1));const S={claudeCode:{label:"Claude Code",file:"~/.claude/settings.json",toggle:K.setClaudeCode},codex:{label:"Codex CLI",file:"~/.codex/config.toml",toggle:K.setCodex},dsh:{label:"DeepSeek Harness",file:"~/.dsh/settings.yaml",toggle:K.setDsh}},k=async(f,o)=>{if(!v.value||i.value)return;const y=S[f],p=o?`确定开启 ${y.label} 代理?将改写 ${y.file}(开启前自动备份,关闭时从备份还原)。`:`确定关闭 ${y.label} 代理?将从备份还原 ${y.file}(无备份时移除代理相关配置)。`;try{await W.confirm(p,o?"开启确认":"关闭确认",{confirmButtonText:o?"开启":"关闭",cancelButtonText:"取消",type:"warning"})}catch{return}i.value=f;try{const l=await y.toggle(o);x.value=l.note??null,_.value=o?"success":"info",g(o?"已开启代理":"已关闭代理","success")}catch(l){g(l.message||"操作失败","error")}finally{i.value=null,await C(!0)}};return(f,o)=>{const y=c("el-button"),p=c("el-alert"),l=c("el-tag"),I=c("el-switch"),z=c("el-divider"),P=c("el-empty"),R=c("el-card"),N=G("loading");return q((m(),B(R,{shadow:"never"},{header:n(()=>[s("div",te,[o[7]||(o[7]=s("span",{class:"fw-600"},"代理开关",-1)),a(y,{loading:E.value,onClick:o[0]||(o[0]=T=>C(!1))},{default:n(()=>[...o[6]||(o[6]=[u("刷新",-1)])]),_:1},8,["loading"])])]),default:n(()=>[v.value?(m(),$(H,{key:0},[s("div",se," 将本机 CLI 工具的流量一键指向 ellm-proxy 网关("+h(v.value.gatewayBase)+")。 开启前自动备份原配置为 *.ellm-bak(保留最早的原始备份),关闭时从备份还原。 ",1),x.value?(m(),B(p,{key:0,title:x.value,type:_.value,"show-icon":"",class:"mb-8",onClose:o[1]||(o[1]=T=>x.value=null)},null,8,["title","type"])):D("",!0),s("div",ae,[s("div",oe,[s("div",ne,[o[8]||(o[8]=u(" Claude Code ",-1)),a(l,{type:v.value.claudeCode?"success":"info",size:"small","disable-transitions":""},{default:n(()=>[u(h(v.value.claudeCode?"已开启":"未开启"),1)]),_:1},8,["type"])]),o[9]||(o[9]=s("div",{class:"switch-desc"},[u(" 写入 "),s("code",null,"~/.claude/settings.json"),u(" 的 env.ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN, 鉴权取网关配置的 masterKey(未设置将开启失败);其余字段原样保留,重启 Claude Code 会话后生效。 ")],-1))]),a(I,{"model-value":v.value.claudeCode,loading:i.value==="claudeCode",onChange:o[2]||(o[2]=T=>k("claudeCode",!!T))},null,8,["model-value","loading"])]),a(z,{class:"switch-divider"}),s("div",ue,[s("div",ie,[s("div",de,[o[10]||(o[10]=u(" Codex CLI ",-1)),a(l,{type:v.value.codex?"success":"info",size:"small","disable-transitions":""},{default:n(()=>[u(h(v.value.codex?"已开启":"未开启"),1)]),_:1},8,["type"])]),o[11]||(o[11]=s("div",{class:"switch-desc"},[u(" 写入 "),s("code",null,"~/.codex/config.toml"),u(" 的 model_provider 与 [model_providers.ellm-proxy] 段 (保留用户注释与排版);开启后需按提示设置环境变量 ELLM_PROXY_API_KEY 供 Codex 鉴权。 ")],-1))]),a(I,{"model-value":v.value.codex,loading:i.value==="codex",onChange:o[3]||(o[3]=T=>k("codex",!!T))},null,8,["model-value","loading"])]),a(z,{class:"switch-divider"}),s("div",re,[s("div",ce,[s("div",ve,[o[12]||(o[12]=u(" DeepSeek Harness ",-1)),a(l,{type:v.value.dsh?"success":"info",size:"small","disable-transitions":""},{default:n(()=>[u(h(v.value.dsh?"已开启":"未开启"),1)]),_:1},8,["type"])]),o[13]||(o[13]=s("div",{class:"switch-desc"},[u(" 写入 "),s("code",null,"~/.dsh/settings.yaml"),u(" 的 llm-deepseek.baseURL 与 "),s("code",null,"~/.dsh/.credentials.yaml"),u(" 的 DEEPSEEK_API_KEY(取网关 masterKey,未设置则写占位值);模型请在 dsh 内选择与网关部署名一致的模型。 dsh 为 developer preview,配置格式可能随版本变化。 ")],-1))]),a(I,{"model-value":v.value.dsh,loading:i.value==="dsh",onChange:o[4]||(o[4]=T=>k("dsh",!!T))},null,8,["model-value","loading"])])],64)):(m(),B(P,{key:1,description:V.value||"暂无开关状态"},{default:n(()=>[a(y,{type:"primary",onClick:o[5]||(o[5]=T=>C(!1))},{default:n(()=>[...o[14]||(o[14]=[u("重试",-1)])]),_:1})]),_:1},8,["description"]))]),_:1})),[[N,b.value]])}}}),me=Q(pe,[["__scopeId","data-v-65e65156"]]),fe={class:"service-settings"},_e={class:"flex-between"},ge={key:0,class:"switch-row"},ye={class:"switch-info"},we={class:"switch-title"},be={key:0,class:"switch-row"},Ce={class:"switch-info"},ke={class:"switch-title"},he={class:"switch-desc"},xe={key:0,class:"version-block"},$e={class:"version-row"},Ve={class:"muted-sm"},Te={key:0,class:"muted-sm"},Ae={class:"version-actions"},Ee=F({__name:"ServiceUpdateSettings",setup(J){const{toast:g}=Y(),b=d(!0),E=d(!1),v=d(null),V=d(null),i=d(null),x=d(null),_=d(null),C=d(!1),S=d(!1),k=d(null),f=async t=>{var e,r;if(!t){if(E.value)return;E.value=!0}try{const[A,U]=await Promise.allSettled([K.autostart(),K.update()]);v.value=A.status==="fulfilled"?A.value:null,V.value=A.status==="rejected"?(e=A.reason)==null?void 0:e.message:null,i.value=U.status==="fulfilled"?U.value:null,x.value=U.status==="rejected"?(r=U.reason)==null?void 0:r.message:null}finally{b.value=!1,E.value=!1}};X(()=>f(!1));const o=j(()=>{var t,e;return((e=(t=i.value)==null?void 0:t.lastCheck)==null?void 0:e.currentVersion)??null}),y=j(()=>{var t,e;return((e=(t=i.value)==null?void 0:t.lastCheck)==null?void 0:e.latestVersion)??null}),p=j(()=>{var t,e;return((e=(t=i.value)==null?void 0:t.lastCheck)==null?void 0:e.hasUpdate)===!0}),l=j(()=>{var e,r;const t=(r=(e=i.value)==null?void 0:e.lastCheck)==null?void 0:r.checkedAt;return t?new Date(t).toLocaleString():null}),I=j(()=>{var r;const t=(r=i.value)==null?void 0:r.lastApply;if(!t)return null;const e=t.appliedAt?new Date(t.appliedAt).toLocaleString():"";return`${t.fromVersion} → ${t.toVersion}${e?`(${e})`:""}`}),z=t=>t?new Date(t).toLocaleString():"",P=async t=>{if(!v.value||_.value)return;const e=t?"确定开启开机自启?将注册登录触发的自启项(登录时自动恢复服务)。":"确定关闭开机自启?将移除自启项,且此后首次启动不再自动注册。";try{await W.confirm(e,t?"开启确认":"关闭确认",{confirmButtonText:t?"开启":"关闭",cancelButtonText:"取消",type:"warning"})}catch{return}_.value="autostart";try{const r=await K.setAutostart(t);r.note?g(r.note,"success"):g(t?"开机自启已开启":"开机自启已关闭","success")}catch(r){g(r.message||"操作失败","error")}finally{_.value=null,await f(!0)}},R=async t=>{if(!i.value||_.value)return;const e=t?"确定开启自动更新?将每小时检查私有源,发现新版本自动安装并重启服务。":"确定关闭自动更新?不再自动检查(手动检查更新不受影响)。";try{await W.confirm(e,t?"开启确认":"关闭确认",{confirmButtonText:t?"开启":"关闭",cancelButtonText:"取消",type:"warning"})}catch{return}_.value="updateEnabled";try{const r=await K.setUpdateEnabled(t);r.note&&g(r.note,"success")}catch(r){g(r.message||"操作失败","error")}finally{_.value=null,await f(!0)}},N=async()=>{C.value=!0;try{const t=await K.checkUpdate();k.value=t.hasUpdate?`发现新版本 ${t.latestVersion}(当前 ${t.currentVersion}),可点击「立即更新」安装`:`已是最新版本 ${t.currentVersion}(检查于 ${z(t.checkedAt)})`,await f(!0)}catch(t){g(t.message||"检查更新失败","error")}finally{C.value=!1}},T=async()=>{try{await W.confirm(`确定更新到 ${y.value}?更新期间主服务将短暂中断(停服安装后自动重启),管理服务随后自重启。`,"更新确认",{confirmButtonText:"立即更新",cancelButtonText:"取消",type:"warning"})}catch{return}S.value=!0;try{const t=await K.applyUpdate();k.value=t.note??`已更新 ${t.fromVersion} → ${t.toVersion}`,g("更新完成","success"),await f(!0)}catch(t){g(t.message||"更新失败","error"),await f(!0)}finally{S.value=!1}};return(t,e)=>{const r=c("el-button"),A=c("el-tag"),U=c("el-switch"),M=c("el-empty"),O=c("el-card"),w=c("el-alert"),Z=G("loading");return q((m(),$("div",fe,[a(O,{shadow:"never",class:"mb-16"},{header:n(()=>[s("div",_e,[e[7]||(e[7]=s("span",{class:"fw-600"},"开机自启",-1)),a(r,{loading:E.value,onClick:e[0]||(e[0]=L=>f(!1))},{default:n(()=>[...e[6]||(e[6]=[u("刷新",-1)])]),_:1},8,["loading"])])]),default:n(()=>[v.value?(m(),$("div",ge,[s("div",ye,[s("div",we,[e[8]||(e[8]=u(" 登录时自动启动服务 ",-1)),a(A,{type:v.value.enabled?"success":"info",size:"small","disable-transitions":""},{default:n(()=>[u(h(v.value.enabled?"已开启":"未开启"),1)]),_:1},8,["type"])]),e[9]||(e[9]=s("div",{class:"switch-desc"},[u(" 登录操作系统时自动执行 "),s("code",null,"pm2 resurrect"),u(" 恢复服务(无需管理员权限)。 关闭后首次启动 "),s("code",null,"ellm-proxy"),u(" 也不会再自动注册,重新开启即可解除。 ")],-1))]),a(U,{"model-value":v.value.enabled,loading:_.value==="autostart",onChange:e[1]||(e[1]=L=>P(!!L))},null,8,["model-value","loading"])])):(m(),B(M,{key:1,description:V.value||"暂无自启状态"},{default:n(()=>[a(r,{type:"primary",onClick:e[2]||(e[2]=L=>f(!1))},{default:n(()=>[...e[10]||(e[10]=[u("重试",-1)])]),_:1})]),_:1},8,["description"]))]),_:1}),a(O,{shadow:"never",class:"mb-16"},{header:n(()=>[...e[11]||(e[11]=[s("div",{class:"flex-between"},[s("span",{class:"fw-600"},"自动更新")],-1)])]),default:n(()=>[i.value?(m(),$("div",be,[s("div",Ce,[s("div",ke,[e[12]||(e[12]=u(" 自动检查并安装新版本 ",-1)),a(A,{type:i.value.enabled?"success":"info",size:"small","disable-transitions":""},{default:n(()=>[u(h(i.value.enabled?"已开启":"未开启"),1)]),_:1},8,["type"])]),s("div",he,[i.value.supported?(m(),$(H,{key:1},[u(" 每小时检查私有 npm 源,发现新版本自动安装并重启服务(更新期间服务短暂中断); 关闭后仍可在下方手动检查与更新。 ")],64)):(m(),$(H,{key:0},[u(" 当前为源码运行模式,更新功能不可用(仅 npm 全局安装的包支持自动更新)。 ")],64))])]),i.value.supported?(m(),B(U,{key:0,"model-value":i.value.enabled,loading:_.value==="updateEnabled",onChange:e[3]||(e[3]=L=>R(!!L))},null,8,["model-value","loading"])):D("",!0)])):(m(),B(M,{key:1,description:x.value||"暂无更新状态"},{default:n(()=>[a(r,{type:"primary",onClick:e[4]||(e[4]=L=>f(!1))},{default:n(()=>[...e[13]||(e[13]=[u("重试",-1)])]),_:1})]),_:1},8,["description"]))]),_:1}),a(O,{shadow:"never"},{header:n(()=>[...e[14]||(e[14]=[s("div",{class:"flex-between"},[s("span",{class:"fw-600"},"版本信息")],-1)])]),default:n(()=>[i.value?(m(),$("div",xe,[s("div",$e,[e[17]||(e[17]=s("span",{class:"version-label"},"当前版本",-1)),a(A,{size:"small"},{default:n(()=>[u(h(o.value||"未知"),1)]),_:1}),y.value?(m(),$(H,{key:0},[e[16]||(e[16]=s("span",{class:"version-label"},"最新版本",-1)),a(A,{type:p.value?"warning":"success",size:"small","disable-transitions":""},{default:n(()=>[u(h(y.value),1)]),_:1},8,["type"]),p.value?(m(),B(A,{key:0,type:"warning",size:"small","disable-transitions":""},{default:n(()=>[...e[15]||(e[15]=[u("发现新版本",-1)])]),_:1})):D("",!0)],64)):D("",!0)]),s("div",Ve,[u(" 上次检查:"+h(l.value||"尚未检查")+" ",1),i.value.updating?(m(),$(H,{key:0},[u(" · 更新执行中...")],64)):D("",!0)]),I.value?(m(),$("div",Te,"上次更新:"+h(I.value),1)):D("",!0),s("div",Ae,[a(r,{loading:C.value,disabled:i.value.updating,onClick:N},{default:n(()=>[u(h(C.value?"检查中...":"检查更新"),1)]),_:1},8,["loading","disabled"]),p.value?(m(),B(r,{key:0,type:"primary",loading:S.value,disabled:i.value.updating,onClick:T},{default:n(()=>[u(h(S.value?"更新中...":`立即更新到 ${y.value}`),1)]),_:1},8,["loading","disabled"])):D("",!0)]),k.value?(m(),B(w,{key:1,title:k.value,type:"info","show-icon":"",class:"mt-8",onClose:e[5]||(e[5]=L=>k.value=null)},null,8,["title"])):D("",!0)])):(m(),B(M,{key:1,description:"更新状态不可用"}))]),_:1})])),[[Z,b.value]])}}}),Se=Q(Ee,[["__scopeId","data-v-03f482d3"]]),Ue={class:"flex-col-gap"},Be={class:"flex-between"},Ie={class:"muted-sm"},Pe={key:0},De={class:"flex-end"},He=F({__name:"SettingsView",setup(J){const{toast:g}=Y(),b=le(),E=d("basic"),v=d(!0),V=d(!1),i=d(""),x=d(29770),_=d(null),C=d("passthrough"),S=d(!1),k=d(""),f=d(""),o=async()=>{var p;try{await b.load(),i.value=b.config.masterKey||"",x.value=b.config.port??29770,C.value=b.config.compression==="plain"?"plain":"passthrough",S.value=b.config.logContent===!0;const l=(p=b.config["web-ui"])==null?void 0:p["login-account"];k.value=(l==null?void 0:l.username)||"",f.value=(l==null?void 0:l.password)||"";try{_.value=await ee.get("/api/status").then(I=>I.listenPort)}catch{_.value=null}}catch(l){g(l.message,"error")}finally{v.value=!1}},y=async()=>{V.value=!0;try{await b.update(p=>{var l;p.masterKey=i.value.trim(),p.port=x.value,p.compression=C.value,p.logContent=S.value,p["web-ui"]??(p["web-ui"]={}),(l=p["web-ui"])["login-account"]??(l["login-account"]={}),p["web-ui"]["login-account"].username=k.value.trim(),p["web-ui"]["login-account"].password=f.value}),g("设置已保存并生效","success")}catch(p){g(p.message,"error")}finally{V.value=!1}};return X(o),(p,l)=>{const I=c("el-tag"),z=c("el-input"),P=c("el-form-item"),R=c("el-input-number"),N=c("el-option"),T=c("el-select"),t=c("el-switch"),e=c("el-form"),r=c("el-card"),A=c("el-button"),U=c("el-tab-pane"),M=c("el-tabs"),O=G("loading");return m(),B(M,{modelValue:E.value,"onUpdate:modelValue":l[6]||(l[6]=w=>E.value=w),class:"settings-tabs"},{default:n(()=>[a(U,{label:"基本设置",name:"basic"},{default:n(()=>[q((m(),$("div",Ue,[a(r,{shadow:"never"},{header:n(()=>[s("div",Be,[l[8]||(l[8]=s("span",{class:"fw-600"},"基本设置",-1)),a(I,{type:"success"},{default:n(()=>[...l[7]||(l[7]=[u("运行中",-1)])]),_:1})])]),default:n(()=>[a(e,{"label-position":"top"},{default:n(()=>[a(P,{label:"Master Key"},{default:n(()=>[a(z,{modelValue:i.value,"onUpdate:modelValue":l[0]||(l[0]=w=>i.value=w),type:"password",placeholder:"sk-1234","show-password":""},null,8,["modelValue"]),l[9]||(l[9]=s("div",{class:"muted-sm"}," 网关 API 认证密钥(/v1/* 请求需携带 Bearer <masterKey>;留空 = 本地放行) ",-1))]),_:1}),a(P,{label:"监听端口 (port)"},{default:n(()=>[a(R,{modelValue:x.value,"onUpdate:modelValue":l[1]||(l[1]=w=>x.value=w),min:1,max:65535,step:1,class:"full-width"},null,8,["modelValue"]),s("div",Ie,[l[11]||(l[11]=u(" 网关与管理台 API 的监听端口,保存后下次重启生效 ",-1)),_.value!==null?(m(),$(H,{key:0},[l[10]||(l[10]=u(" ;当前实际监听 ",-1)),s("b",null,h(_.value),1),_.value!==x.value?(m(),$("span",Pe,"(由 PORT 环境变量覆盖,此配置值不生效)")):D("",!0)],64)):D("",!0)])]),_:1}),a(P,{label:"压缩语义 (compression)"},{default:n(()=>[a(T,{modelValue:C.value,"onUpdate:modelValue":l[2]||(l[2]=w=>C.value=w),class:"full-width"},{default:n(()=>[a(N,{label:"透传 (passthrough)",value:"passthrough"}),a(N,{label:"明文 (plain)",value:"plain"})]),_:1},8,["modelValue"]),l[12]||(l[12]=s("div",{class:"muted-sm"},"上游响应压缩处理方式,保存后热更新生效",-1))]),_:1}),a(P,{label:"日志内容捕获 (logContent)"},{default:n(()=>[a(t,{modelValue:S.value,"onUpdate:modelValue":l[3]||(l[3]=w=>S.value=w)},null,8,["modelValue"]),l[13]||(l[13]=s("div",{class:"muted-sm"}," 记录完整请求/响应(含上游原始与转换后内容)进日志详情,用于排查定位问题;开启后有少量内存与存储开销,保存后热更新生效 ",-1))]),_:1}),a(P,{label:"管理台用户名 (web-ui.login-account.username)"},{default:n(()=>[a(z,{modelValue:k.value,"onUpdate:modelValue":l[4]||(l[4]=w=>k.value=w),placeholder:"admin"},null,8,["modelValue"]),l[14]||(l[14]=s("div",{class:"muted-sm"}," 管理台登录用户名,留空回退 WEBUI_USERNAME 环境变量或默认 admin ",-1))]),_:1}),a(P,{label:"管理台密码 (web-ui.login-account.password)"},{default:n(()=>[a(z,{modelValue:f.value,"onUpdate:modelValue":l[5]||(l[5]=w=>f.value=w),type:"password",placeholder:"admin","show-password":""},null,8,["modelValue"]),l[15]||(l[15]=s("div",{class:"muted-sm"}," 管理台登录密码,留空回退 WEBUI_PASSWORD 环境变量或默认 admin;修改保存后立即生效,需用新账号重新登录 ",-1))]),_:1})]),_:1})]),_:1}),s("div",De,[a(A,{type:"primary",loading:V.value,disabled:V.value,onClick:y},{default:n(()=>[u(h(V.value?"保存中...":"保存设置"),1)]),_:1},8,["loading","disabled"])])])),[[O,v.value]])]),_:1}),a(U,{label:"代理开关",name:"harness",lazy:""},{default:n(()=>[a(me)]),_:1}),a(U,{label:"服务与更新",name:"service",lazy:""},{default:n(()=>[a(Se)]),_:1})]),_:1},8,["modelValue"])}}});export{He as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{d as J,p as O,aa as Q,e as S,g as a,w as l,r as i,a as r,o as s,f as k,F as x,h as o,c as p,i as K,t as I,Z as W,l as z,A,a9 as v,ab as X,m as Y,_ as h}from"./index-X5PdkJlA.js";const ee={class:"setup-wrap"},ae={class:"wizard-actions"},le={class:"key-row"},te={class:"wizard-actions"},se={class:"wizard-actions"},oe=J({__name:"SetupView",setup(ne){const P=Y(),m=i(0),n=i(""),d=i("generate"),b=i(""),M=i(""),_=i(""),c=i(""),U=i(""),B=i(!1),E=i(!1),w=i(!1);O(async()=>{const u=await Q();w.value=u.masterKeySet,w.value&&(d.value="skip")});const T=z(()=>n.value==="local"||w.value),R=z(()=>w.value?"(保留现有主密钥)":"(/v1 保持免鉴权)"),D=z(()=>d.value==="skip"?T.value:d.value==="custom"?M.value.trim().length>=8:b.value!=="");async function H(){try{const u=await A.post("/api/setup/master-key",{mode:"generate"});b.value=u.masterKey}catch(u){v.error(u.message||"生成失败")}}async function Z(){try{await navigator.clipboard.writeText(b.value),v.success("已复制到剪贴板")}catch{v.error("复制失败,请手动选择复制")}}async function j(){if(d.value==="skip"){m.value=2;return}B.value=!0;try{d.value==="custom"&&await A.post("/api/setup/master-key",{mode:"custom",masterKey:M.value.trim()}),w.value=!0,m.value=2}catch(u){v.error(u.message||"保存失败")}finally{B.value=!1}}async function $(){const u=_.value!==""||c.value!=="";if(u||n.value==="server"){if(!_.value.trim()){v.warning("请输入用户名");return}if(c.value.length<6){v.warning("密码至少 6 位");return}if(c.value!==U.value){v.warning("两次输入的密码不一致");return}}E.value=!0;try{await A.post("/api/setup/finish",{deployment:n.value,...u?{username:_.value.trim(),password:c.value}:{}}),X(n.value),v.success("初始化完成,请使用新账号登录"),await P.push("/login")}catch(e){v.error(e.message||"保存失败")}finally{E.value=!1}}return(u,e)=>{const L=r("el-step"),q=r("el-steps"),g=r("el-radio"),F=r("el-radio-group"),f=r("el-form-item"),N=r("el-form"),V=r("el-alert"),y=r("el-button"),C=r("el-input"),G=r("el-card");return s(),S("div",ee,[a(G,{shadow:"hover",class:"setup-card"},{default:l(()=>[e[20]||(e[20]=k("h2",{class:"setup-title"},"ELLM 初始化向导",-1)),a(q,{active:m.value,"align-center":"","finish-status":"success",class:"mb-24"},{default:l(()=>[a(L,{title:"部署环境"}),a(L,{title:"主密钥"}),a(L,{title:"登录账号"})]),_:1},8,["active"]),m.value===0?(s(),S(x,{key:0},[a(N,{"label-position":"top"},{default:l(()=>[a(f,{label:"这台机器上的 ELLM 会被哪些设备访问?"},{default:l(()=>[a(F,{modelValue:n.value,"onUpdate:modelValue":e[0]||(e[0]=t=>n.value=t)},{default:l(()=>[a(g,{value:"local"},{default:l(()=>[...e[9]||(e[9]=[o("仅本机使用(本地个人部署)",-1)])]),_:1}),a(g,{value:"server"},{default:l(()=>[...e[10]||(e[10]=[o("局域网 / 公网可访问(服务器部署)",-1)])]),_:1})]),_:1},8,["modelValue"])]),_:1})]),_:1}),n.value==="server"?(s(),p(V,{key:0,type:"warning","show-icon":"",closable:!1,title:"服务器部署存在安全风险",description:"服务将暴露给网络中的其他设备:不设置主密钥,任何人都能消耗你的模型额度;不修改默认账号密码(admin/admin),陌生人可直接登录管理台查看供应商密钥与调用日志。后两步将强制要求设置。",class:"mb-16"})):n.value==="local"?(s(),p(V,{key:1,type:"info","show-icon":"",closable:!1,title:"本地模式",description:"仅本机可访问时,主密钥与登录账号均可在后续步骤跳过(保持 /v1 免鉴权与默认账号 admin/admin)。若日后开放给其他设备,请再回来补全。",class:"mb-16"})):K("",!0),k("div",ae,[e[12]||(e[12]=k("span",null,null,-1)),a(y,{type:"primary",disabled:!n.value,onClick:e[1]||(e[1]=t=>m.value=1)},{default:l(()=>[...e[11]||(e[11]=[o("下一步",-1)])]),_:1},8,["disabled"])])],64)):m.value===1?(s(),S(x,{key:1},[w.value?(s(),p(V,{key:0,type:"success","show-icon":"",closable:!1,title:"已检测到主密钥",description:"当前部署已设置主密钥(可在「设置」页查看修改),本步可直接跳过;如需更换可在下方重新生成或输入。",class:"mb-16"})):K("",!0),a(N,{"label-position":"top"},{default:l(()=>[a(f,{label:"主密钥(调用 /v1/* 接口的 Bearer Token)"},{default:l(()=>[a(F,{modelValue:d.value,"onUpdate:modelValue":e[2]||(e[2]=t=>d.value=t)},{default:l(()=>[a(g,{value:"generate"},{default:l(()=>[...e[13]||(e[13]=[o("随机生成(推荐)",-1)])]),_:1}),a(g,{value:"custom"},{default:l(()=>[...e[14]||(e[14]=[o("自定义输入",-1)])]),_:1}),T.value?(s(),p(g,{key:0,value:"skip"},{default:l(()=>[o("跳过"+I(R.value),1)]),_:1})):K("",!0)]),_:1},8,["modelValue"])]),_:1}),d.value==="generate"?(s(),S(x,{key:0},[b.value?(s(),p(f,{key:1,label:"请复制保存你的主密钥(设置页也可随时查看):"},{default:l(()=>[k("div",le,[a(C,{"model-value":b.value,readonly:""},{append:l(()=>[a(y,{onClick:Z},{default:l(()=>[...e[16]||(e[16]=[o("复制",-1)])]),_:1})]),_:1},8,["model-value"])])]),_:1})):(s(),p(f,{key:0},{default:l(()=>[a(y,{type:"primary",plain:"",onClick:H},{default:l(()=>[...e[15]||(e[15]=[o("生成随机密钥",-1)])]),_:1})]),_:1}))],64)):K("",!0),d.value==="custom"?(s(),p(f,{key:1,label:"自定义主密钥(至少 8 位)"},{default:l(()=>[a(C,{modelValue:M.value,"onUpdate:modelValue":e[3]||(e[3]=t=>M.value=t),placeholder:"例如 my-secret-key-2026","show-password":"",clearable:""},null,8,["modelValue"])]),_:1})):K("",!0)]),_:1}),k("div",te,[a(y,{onClick:e[4]||(e[4]=t=>m.value=0)},{default:l(()=>[...e[17]||(e[17]=[o("上一步",-1)])]),_:1}),a(y,{type:"primary",loading:B.value,disabled:!D.value,onClick:j},{default:l(()=>[...e[18]||(e[18]=[o(" 下一步 ",-1)])]),_:1},8,["loading","disabled"])])],64)):(s(),S(x,{key:2},[n.value==="server"?(s(),p(V,{key:0,type:"warning","show-icon":"",closable:!1,title:"必须设置登录账号密码",description:"服务器部署的管理台会暴露在局域网/公网中,默认账号 admin/admin 等于向所有人开放管理权限,请务必设置强密码。",class:"mb-16"})):(s(),p(V,{key:1,type:"info","show-icon":"",closable:!1,title:"可选步骤",description:"本地模式可跳过,保持默认账号 admin/admin。建议设置专属账号密码,避免日后开放访问时遗忘修改。",class:"mb-16"})),a(N,{"label-position":"top",onSubmit:W($,["prevent"])},{default:l(()=>[a(f,{label:"用户名"},{default:l(()=>[a(C,{modelValue:_.value,"onUpdate:modelValue":e[5]||(e[5]=t=>_.value=t),placeholder:"请输入用户名",clearable:""},null,8,["modelValue"])]),_:1}),a(f,{label:"密码(至少 6 位)"},{default:l(()=>[a(C,{modelValue:c.value,"onUpdate:modelValue":e[6]||(e[6]=t=>c.value=t),type:"password","show-password":"",placeholder:"请输入密码"},null,8,["modelValue"])]),_:1}),a(f,{label:"确认密码"},{default:l(()=>[a(C,{modelValue:U.value,"onUpdate:modelValue":e[7]||(e[7]=t=>U.value=t),type:"password","show-password":"",placeholder:"请再次输入密码"},null,8,["modelValue"])]),_:1})]),_:1}),k("div",se,[a(y,{onClick:e[8]||(e[8]=t=>m.value=1)},{default:l(()=>[...e[19]||(e[19]=[o("上一步",-1)])]),_:1}),a(y,{type:"primary",loading:E.value,onClick:$},{default:l(()=>[o(I(n.value==="server"||_.value||c.value?"完成":"跳过并完成"),1)]),_:1},8,["loading"])])],64))]),_:1})])}}}),ie=h(oe,[["__scopeId","data-v-89c00f65"]]);export{ie as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.setup-wrap[data-v-89c00f65]{min-height:100vh;display:flex;align-items:center;justify-content:center;background:#f5f7fa}.setup-card[data-v-89c00f65]{width:560px;max-width:92vw}.setup-title[data-v-89c00f65]{text-align:center;margin-bottom:24px;color:#3b82f6}.key-row[data-v-89c00f65]{width:100%}.wizard-actions[data-v-89c00f65]{display:flex;justify-content:space-between;margin-top:8px}.mb-24[data-v-89c00f65]{margin-bottom:24px}.mb-16[data-v-89c00f65]{margin-bottom:16px}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{X as p,r as u,l as n,A as i}from"./index-X5PdkJlA.js";const y=p("config",()=>{const e=u({}),o=u(!1),t=n(()=>Array.isArray(e.value.providers)?e.value.providers:[]),l=n(()=>t.value.length),c=n(()=>t.value.reduce((a,d)=>{var s;return a+(((s=d.models)==null?void 0:s.length)??0)},0));async function f(){o.value=!0;try{e.value=await i.get("/api/config")}finally{o.value=!1}}async function r(){return await i.put("/api/config",e.value)}async function v(a){return a(e.value),await r()}return{config:e,loading:o,providers:t,providerCount:l,totalModelCount:c,load:f,save:r,update:v}});export{y as u};
|