ezllm 0.0.48 → 0.0.49
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/dist/server.js +62 -61
- package/dist/web-ui/assets/{DashboardView-CJOcLFY-.js → DashboardView--YRv0pdB.js} +1 -1
- package/dist/web-ui/assets/{LayoutView-DH55aSBP.js → LayoutView-3OpEgcEH.js} +1 -1
- package/dist/web-ui/assets/{LoginView-Cp-a8Nds.js → LoginView-DyiYIltJ.js} +1 -1
- package/dist/web-ui/assets/{LogsView-C1ImQHJ6.js → LogsView-BlO9eUXV.js} +2 -2
- package/dist/web-ui/assets/{ManagedServicesView-DIMY-j18.js → ManagedServicesView-DalOm5fB.js} +1 -1
- package/dist/web-ui/assets/{PluginsView-CqmYhJ6G.js → PluginsView-CMjFrpCT.js} +1 -1
- package/dist/web-ui/assets/{ProvidersView-BwX8Y3kP.css → ProvidersView-DZs-NofB.css} +1 -1
- package/dist/web-ui/assets/ProvidersView-PlwErhJU.js +14 -0
- package/dist/web-ui/assets/{SettingsView-BbmPwJ-1.js → SettingsView-Dl-dHm8U.js} +1 -1
- package/dist/web-ui/assets/{SetupView-WCA8Jeug.js → SetupView-BblW5D0m.js} +1 -1
- package/dist/web-ui/assets/{config-BKCqJSgG.js → config-DRb_7Qvh.js} +1 -1
- package/dist/web-ui/assets/index-BviWrBv1.js +49 -0
- package/dist/web-ui/assets/{message-Bqg-4z7y.js → message-BgUNwRuF.js} +2 -2
- package/dist/web-ui/assets/pluginProviders-CMNUPYaO.js +1 -0
- package/dist/web-ui/assets/{providers-DRvT1zLg.js → providers-fXKPM_nK.js} +1 -1
- package/dist/web-ui/assets/{router-CpkAp9dB.js → router-Cpy-sU_q.js} +2 -2
- package/dist/web-ui/assets/{useCopyToast-DwJ3VhPN.js → useCopyToast-DreqvPDI.js} +1 -1
- package/dist/web-ui/assets/{useManagerApi-Cf88mNiu.js → useManagerApi-DBsdJZgc.js} +1 -1
- package/dist/web-ui/assets/{useQuickRangeFilter-BsOHHbog.js → useQuickRangeFilter-D2Epk9Kj.js} +1 -1
- package/dist/web-ui/assets/useToast-BpZaUS2s.js +1 -0
- package/dist/web-ui/index.html +3 -3
- package/package.json +1 -1
- package/dist/web-ui/assets/ProvidersView-uCjHMlHd.js +0 -14
- package/dist/web-ui/assets/index-DNgY-btf.js +0 -49
- package/dist/web-ui/assets/pluginProviders-BGmYcLwJ.js +0 -1
- package/dist/web-ui/assets/useToast-IlI6ESuD.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,Et as t,F as n,Ft as r,Gt as i,H as a,I as o,L as s,M as c,N as l,Q as u,T as d,a as f,at as p,d as m,gt as h,ht as g,j as _,k as v,n as y,ot as b,pn as x,rt as S,tt as C,yt as w}from"./router-CpkAp9dB.js";import{t as T}from"./index-DNgY-btf.js";import{t as E}from"./useManagerApi-Cf88mNiu.js";import{t as D}from"./config-BKCqJSgG.js";import{n as O,t as k}from"./useCopyToast-DwJ3VhPN.js";import{t as A}from"./useToast-IlI6ESuD.js";import{t as j}from"./navVisibility-CPbwxq3d.js";function M(e){let t=N(e)?e:{},n=t[`login-enabled`];if(n===!1)return!1;if(n!==void 0)return!0;let r=N(t[`login-account`])?t[`login-account`]:{},i=typeof r.username==`string`?r.username.trim():``,a=typeof r.password==`string`?r.password:``;return i!==``&&a!==``}function N(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}a(),i(),w();var P={class:`flex-between`},F={class:`muted-sm mb-8`},I={class:`switch-row`},L={class:`switch-info`},R={class:`switch-title`},z={class:`switch-row`},B={class:`switch-info`},V={class:`switch-title`},H={class:`switch-row`},U={class:`switch-info`},W={class:`switch-title`},G=m(s({__name:`HarnessSwitches`,setup(r){let{toast:i}=A(),a=t(!0),s=t(!1),f=t(null),m=t(null),v=t(null),y=t(null),S=t(`success`),w=async e=>{e||(f.value?s.value=!0:a.value=!0);try{f.value=await E.harness(),m.value=null}catch(t){e||(m.value=t.message)}finally{e||(a.value=!1,s.value=!1)}};u(()=>w(!1));let D={claudeCode:{label:`Claude Code`,file:`~/.claude/settings.json`,toggle:E.setClaudeCode},codex:{label:`Codex CLI`,file:`~/.codex/config.toml`,toggle:E.setCodex},dsh:{label:`DeepSeek Harness`,file:`~/.dsh/settings.yaml`,toggle:E.setDsh}},O=async(e,t)=>{if(!f.value||v.value)return;let n=D[e],r=t?`确定开启 ${n.label} 代理?将改写 ${n.file}(开启前自动备份,关闭时从备份还原)。`:`确定关闭 ${n.label} 代理?将从备份还原 ${n.file}(无备份时移除代理相关配置)。`;try{await T.confirm(r,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}v.value=e;try{let e=await n.toggle(t);y.value=e.note??null,S.value=t?`success`:`info`,i(t?`已开启代理`:`已关闭代理`,`success`)}catch(e){i(e.message||`操作失败`,`error`)}finally{v.value=null,await w(!0)}};return(t,r)=>{let i=p(`el-button`),u=p(`el-alert`),T=p(`el-tag`),E=p(`el-switch`),D=p(`el-divider`),k=p(`el-empty`),A=p(`el-card`),j=b(`loading`);return h((C(),_(A,{shadow:`never`},{header:g(()=>[e(`div`,P,[r[7]||=e(`span`,{class:`fw-600`},`代理开关`,-1),o(i,{loading:s.value,onClick:r[0]||=e=>w(!1)},{default:g(()=>[...r[6]||=[n(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:g(()=>[f.value?(C(),l(d,{key:0},[e(`div`,F,` 将本机 CLI 工具的流量一键指向本机网关(`+x(f.value.gatewayBase)+`)。 开启前自动备份原配置为 *.ellm-bak(保留最早的原始备份),关闭时从备份还原。 `,1),y.value?(C(),_(u,{key:0,title:y.value,type:S.value,"show-icon":``,class:`mb-8`,onClose:r[1]||=e=>y.value=null},null,8,[`title`,`type`])):c(``,!0),e(`div`,I,[e(`div`,L,[e(`div`,R,[r[8]||=n(` Claude Code `,-1),o(T,{type:f.value.claudeCode?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(f.value.claudeCode?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),r[9]||=e(`div`,{class:`switch-desc`},[n(` 写入 `),e(`code`,null,`~/.claude/settings.json`),n(` 的 env.ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN, 鉴权取网关配置的 masterKey(未设置将开启失败);其余字段原样保留,重启 Claude Code 会话后生效。 `)],-1)]),o(E,{"model-value":f.value.claudeCode,loading:v.value===`claudeCode`,onChange:r[2]||=e=>O(`claudeCode`,!!e)},null,8,[`model-value`,`loading`])]),o(D,{class:`switch-divider`}),e(`div`,z,[e(`div`,B,[e(`div`,V,[r[10]||=n(` Codex CLI `,-1),o(T,{type:f.value.codex?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(f.value.codex?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),r[11]||=e(`div`,{class:`switch-desc`},[n(` 写入 `),e(`code`,null,`~/.codex/config.toml`),n(` 的 model_provider 与 [model_providers.ellm-proxy] 段 (保留用户注释与排版);开启后需按提示设置环境变量 ELLM_PROXY_API_KEY 供 Codex 鉴权。 `)],-1)]),o(E,{"model-value":f.value.codex,loading:v.value===`codex`,onChange:r[3]||=e=>O(`codex`,!!e)},null,8,[`model-value`,`loading`])]),o(D,{class:`switch-divider`}),e(`div`,H,[e(`div`,U,[e(`div`,W,[r[12]||=n(` DeepSeek Harness `,-1),o(T,{type:f.value.dsh?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(f.value.dsh?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),r[13]||=e(`div`,{class:`switch-desc`},[n(` 写入 `),e(`code`,null,`~/.dsh/settings.yaml`),n(` 的 llm-deepseek.baseURL 与 `),e(`code`,null,`~/.dsh/.credentials.yaml`),n(` 的 DEEPSEEK_API_KEY(取网关 masterKey,未设置则写占位值);模型请在 dsh 内选择与网关部署名一致的模型。 dsh 为 developer preview,配置格式可能随版本变化。 `)],-1)]),o(E,{"model-value":f.value.dsh,loading:v.value===`dsh`,onChange:r[4]||=e=>O(`dsh`,!!e)},null,8,[`model-value`,`loading`])])],64)):(C(),_(k,{key:1,description:m.value||`暂无开关状态`},{default:g(()=>[o(i,{type:`primary`,onClick:r[5]||=e=>w(!1)},{default:g(()=>[...r[14]||=[n(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1})),[[j,a.value]])}}}),[[`__scopeId`,`data-v-00711dc3`]]);a(),w(),i();var K={class:`flex-col-gap`},q={class:`flex-between`},J={class:`muted-sm`},ee={class:`login-row`},te={class:`muted-sm`},ne={class:`flex-between`},re={class:`monitor-row`},ie={class:`monitor-row`},ae={class:`monitor-row`},oe={class:`save-bar`},Y=m(s({__name:`SettingsView`,setup(i){let{toast:a}=A(),{copyWithToast:s}=k(),m=D(),w=t(`basic`),T=t(!0),E=t(!1),N=t(``),P=async()=>{N.value&&await s(N.value)},F=t(29770),I=t(null),L=t(!0),R=t(``),z=t(``),B=t(!1),V=v(()=>N.value.trim()!==``||B.value&&R.value.trim()!==``&&z.value!==``),H=t(!1),U=t(60),W=[{label:`10分钟`,value:10},{label:`30分钟`,value:30},{label:`1小时`,value:60},{label:`2小时`,value:120},{label:`5小时`,value:300},{label:`8小时`,value:480},{label:`12小时`,value:720},{label:`24小时`,value:1440}],Y=t(!1),X=t(!0),{loadError:Z,run:Q}=O(`设置加载失败,请重试`),$=()=>Q(async()=>{try{await m.load(),N.value=m.config.masterKey||``,F.value=m.config.port??29770;let e=m.config[`web-ui`]?.[`login-account`];R.value=e?.username||``,z.value=e?.password||``,B.value=M(m.config[`web-ui`]),L.value=m.config.allowLan!==!1;let t=m.config.latencyTest;H.value=t?.enabled===!0,U.value=t?.intervalMinutes??60;let n=j(m.config[`web-ui`]);Y.value=n.managedServices,X.value=n.plugins;try{let e=await f.get(`/api/status`);I.value=e.listenPort}catch{I.value=null}}finally{T.value=!1}}),se=async()=>{if(B.value&&(R.value.trim()===``||z.value===``)){a(`启用管理台登录时请填写用户名和密码(长度与字符不限)`,`error`);return}E.value=!0;let e=H.value&&m.config.latencyTest?.enabled!==!0;try{let t=await m.update(e=>{e.masterKey=N.value.trim(),e.port=F.value,e.allowLan=L.value,e.latencyTest={enabled:H.value,intervalMinutes:U.value},e[`web-ui`]??={},e[`web-ui`][`login-enabled`]=B.value,B.value&&(e[`web-ui`][`login-account`]??={},e[`web-ui`][`login-account`].username=R.value.trim(),e[`web-ui`][`login-account`].password=z.value),e[`web-ui`].nav??={},e[`web-ui`].nav[`managed-services`]=Y.value,e[`web-ui`].nav.plugins=X.value});await y(!0),a(`设置已保存并生效`,`success`),e&&a(`已开启自动测试:服务将定期直连所有上游发送探测请求,有少量 token 消耗`,`warning`),t.restartHint&&a(t.restartHint,`warning`)}catch(e){a(e.message,`error`)}finally{E.value=!1}};return u($),(t,i)=>{let a=p(`el-button`),s=p(`el-alert`),u=p(`el-tag`),f=p(`el-input`),m=p(`el-form-item`),v=p(`el-input-number`),y=p(`el-form`),D=p(`el-card`),O=p(`el-switch`),k=p(`el-divider`),A=p(`el-option`),j=p(`el-select`),M=p(`el-tab-pane`),Q=p(`el-tabs`),ce=b(`loading`);return C(),_(Q,{modelValue:w.value,"onUpdate:modelValue":i[10]||=e=>w.value=e,class:`settings-tabs`},{default:g(()=>[o(M,{label:`基本设置`,name:`basic`},{default:g(()=>[h((C(),l(`div`,K,[r(Z)?(C(),_(s,{key:0,title:r(Z),type:`error`,"show-icon":``,closable:!1},{default:g(()=>[o(a,{size:`small`,onClick:$},{default:g(()=>[...i[11]||=[n(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):c(``,!0),o(D,{shadow:`never`},{header:g(()=>[e(`div`,q,[i[13]||=e(`span`,{class:`fw-600`},`网关访问`,-1),o(u,{type:`success`},{default:g(()=>[...i[12]||=[n(`运行中`,-1)]]),_:1})])]),default:g(()=>[o(y,{"label-position":`top`},{default:g(()=>[o(m,{label:`API 密钥 (masterKey)`},{default:g(()=>[o(f,{modelValue:N.value,"onUpdate:modelValue":i[0]||=e=>N.value=e,placeholder:`sk-1234`,clearable:``},{append:g(()=>[o(a,{onClick:P},{default:g(()=>[...i[14]||=[n(`复制`,-1)]]),_:1})]),_:1},8,[`modelValue`]),i[15]||=e(`div`,{class:`muted-sm`},`客户端请求 /v1/* 时的认证密钥(Bearer <masterKey>;留空 = 本地放行)`,-1)]),_:1}),o(m,{label:`监听端口 (port)`},{default:g(()=>[o(v,{modelValue:F.value,"onUpdate:modelValue":i[1]||=e=>F.value=e,min:1,max:65535,step:1,style:{width:`220px`}},null,8,[`modelValue`]),e(`div`,J,[i[17]||=n(` 网关与管理台 API 的监听端口,保存后重启生效 `,-1),I.value===null?c(``,!0):(C(),l(d,{key:0},[i[16]||=n(` ;服务上报的端口 `,-1),e(`b`,null,x(I.value),1)],64))])]),_:1})]),_:1})]),_:1}),o(D,{shadow:`never`},{header:g(()=>[...i[18]||=[e(`span`,{class:`fw-600`},`安全与登录`,-1)]]),default:g(()=>[o(y,{"label-position":`top`},{default:g(()=>[o(m,{label:`启用管理台登录`},{default:g(()=>[o(O,{modelValue:B.value,"onUpdate:modelValue":i[2]||=e=>B.value=e},null,8,[`modelValue`]),i[19]||=e(`div`,{class:`muted-sm`},` 开启后访问管理台需要下方用户名密码;关闭 = 免登录直接访问(仅本机使用时推荐) `,-1)]),_:1}),B.value?(C(),_(m,{key:0,label:`管理台登录账号`},{default:g(()=>[e(`div`,ee,[o(f,{modelValue:R.value,"onUpdate:modelValue":i[3]||=e=>R.value=e,placeholder:`用户名`,style:{width:`200px`}},null,8,[`modelValue`]),o(f,{modelValue:z.value,"onUpdate:modelValue":i[4]||=e=>z.value=e,type:`password`,placeholder:`密码(长度与字符不限)`,"show-password":``,style:{width:`200px`}},null,8,[`modelValue`])]),i[20]||=e(`div`,{class:`muted-sm`},`修改后立即生效,需用新账号重新登录;用户名和密码不校验长度,任意字符均可`,-1)]),_:1})):c(``,!0),!B.value&&L.value?(C(),_(s,{key:1,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`,title:`已允许局域网访问但未启用管理台登录:局域网内设备可直接打开管理台。建议启用登录或关闭局域网访问。`})):c(``,!0),o(m,{label:`允许局域网访问 (allowLan)`},{default:g(()=>[o(O,{modelValue:L.value,"onUpdate:modelValue":i[5]||=e=>L.value=e},null,8,[`modelValue`]),e(`div`,te,[i[21]||=n(` 开启 = 绑定全部网卡,局域网内设备可访问;关闭 = 仅本机 127.0.0.1。保存后需重启生效 `,-1),V.value?c(``,!0):(C(),l(d,{key:0},[n(` ;未设置任何有效凭据(主密钥为空且登录未启用)时始终仅绑本机 `)],64))])]),_:1})]),_:1})]),_:1}),o(D,{shadow:`never`},{header:g(()=>[e(`div`,ne,[i[22]||=e(`span`,{class:`fw-600`},`模型服务监控`,-1),o(u,{type:H.value?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(H.value?`已开启`:`未开启`),1)]),_:1},8,[`type`])])]),default:g(()=>[e(`div`,re,[i[23]||=e(`div`,{class:`monitor-info`},[e(`div`,{class:`monitor-title`},`自动测试模型服务状态`),e(`div`,{class:`muted-sm`},` 按设定间隔自动直连所有上游模型发送极小探测请求(max_tokens: 1,有少量 token 消耗); 测试结果展示在首页「服务状态」tab `)],-1),o(O,{modelValue:H.value,"onUpdate:modelValue":i[6]||=e=>H.value=e},null,8,[`modelValue`])]),H.value?(C(),l(d,{key:0},[o(k,{style:{margin:`12px 0`}}),o(y,{"label-position":`top`},{default:g(()=>[o(m,{label:`测试间隔`,style:{"margin-bottom":`0`}},{default:g(()=>[o(j,{modelValue:U.value,"onUpdate:modelValue":i[7]||=e=>U.value=e,style:{width:`220px`}},{default:g(()=>[(C(),l(d,null,S(W,e=>o(A,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`]),i[24]||=e(`div`,{class:`muted-sm`},`自动测试的执行间隔,保存后即时生效(无需重启)`,-1)]),_:1})]),_:1})],64)):c(``,!0)]),_:1}),o(D,{shadow:`never`},{header:g(()=>[...i[25]||=[e(`span`,{class:`fw-600`},`界面与入口`,-1)]]),default:g(()=>[e(`div`,ie,[i[26]||=e(`div`,{class:`monitor-info`},[e(`div`,{class:`monitor-title`},`显示「托管服务」入口`),e(`div`,{class:`muted-sm`},`开启后顶部导航显示「托管服务」tab;默认关闭,不用的功能不占导航`)],-1),o(O,{modelValue:Y.value,"onUpdate:modelValue":i[8]||=e=>Y.value=e},null,8,[`modelValue`])]),o(k,{style:{margin:`12px 0`}}),e(`div`,ae,[i[27]||=e(`div`,{class:`monitor-info`},[e(`div`,{class:`monitor-title`},`显示「插件」入口`),e(`div`,{class:`muted-sm`},` 开启后顶部导航显示「插件」tab,并同时启用插件服务(关闭会隐藏入口并停止插件服务);默认开启 `)],-1),o(O,{modelValue:X.value,"onUpdate:modelValue":i[9]||=e=>X.value=e},null,8,[`modelValue`])])]),_:1}),e(`div`,oe,[o(a,{type:`primary`,size:`large`,loading:E.value,disabled:E.value||r(Z)!==null,onClick:se},{default:g(()=>[n(x(E.value?`保存中...`:`保存设置`),1)]),_:1},8,[`loading`,`disabled`])])])),[[ce,T.value]])]),_:1}),o(M,{label:`代理开关`,name:`harness`,lazy:``},{default:g(()=>[o(G)]),_:1})]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-e3f72f2d`]]);export{Y as default};
|
|
1
|
+
import{A as e,Et as t,F as n,Ft as r,Gt as i,H as a,I as o,L as s,M as c,N as l,Q as u,T as d,a as f,at as p,d as m,gt as h,ht as g,j as _,k as v,n as y,ot as b,pn as x,rt as S,tt as C,yt as w}from"./router-Cpy-sU_q.js";import{t as T}from"./index-BviWrBv1.js";import{t as E}from"./useManagerApi-DBsdJZgc.js";import{t as D}from"./config-DRb_7Qvh.js";import{n as O,t as k}from"./useCopyToast-DreqvPDI.js";import{t as A}from"./useToast-BpZaUS2s.js";import{t as j}from"./navVisibility-CPbwxq3d.js";function M(e){let t=N(e)?e:{},n=t[`login-enabled`];if(n===!1)return!1;if(n!==void 0)return!0;let r=N(t[`login-account`])?t[`login-account`]:{},i=typeof r.username==`string`?r.username.trim():``,a=typeof r.password==`string`?r.password:``;return i!==``&&a!==``}function N(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}a(),i(),w();var P={class:`flex-between`},F={class:`muted-sm mb-8`},I={class:`switch-row`},L={class:`switch-info`},R={class:`switch-title`},z={class:`switch-row`},B={class:`switch-info`},V={class:`switch-title`},H={class:`switch-row`},U={class:`switch-info`},W={class:`switch-title`},G=m(s({__name:`HarnessSwitches`,setup(r){let{toast:i}=A(),a=t(!0),s=t(!1),f=t(null),m=t(null),v=t(null),y=t(null),S=t(`success`),w=async e=>{e||(f.value?s.value=!0:a.value=!0);try{f.value=await E.harness(),m.value=null}catch(t){e||(m.value=t.message)}finally{e||(a.value=!1,s.value=!1)}};u(()=>w(!1));let D={claudeCode:{label:`Claude Code`,file:`~/.claude/settings.json`,toggle:E.setClaudeCode},codex:{label:`Codex CLI`,file:`~/.codex/config.toml`,toggle:E.setCodex},dsh:{label:`DeepSeek Harness`,file:`~/.dsh/settings.yaml`,toggle:E.setDsh}},O=async(e,t)=>{if(!f.value||v.value)return;let n=D[e],r=t?`确定开启 ${n.label} 代理?将改写 ${n.file}(开启前自动备份,关闭时从备份还原)。`:`确定关闭 ${n.label} 代理?将从备份还原 ${n.file}(无备份时移除代理相关配置)。`;try{await T.confirm(r,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}v.value=e;try{let e=await n.toggle(t);y.value=e.note??null,S.value=t?`success`:`info`,i(t?`已开启代理`:`已关闭代理`,`success`)}catch(e){i(e.message||`操作失败`,`error`)}finally{v.value=null,await w(!0)}};return(t,r)=>{let i=p(`el-button`),u=p(`el-alert`),T=p(`el-tag`),E=p(`el-switch`),D=p(`el-divider`),k=p(`el-empty`),A=p(`el-card`),j=b(`loading`);return h((C(),_(A,{shadow:`never`},{header:g(()=>[e(`div`,P,[r[7]||=e(`span`,{class:`fw-600`},`代理开关`,-1),o(i,{loading:s.value,onClick:r[0]||=e=>w(!1)},{default:g(()=>[...r[6]||=[n(`刷新`,-1)]]),_:1},8,[`loading`])])]),default:g(()=>[f.value?(C(),l(d,{key:0},[e(`div`,F,` 将本机 CLI 工具的流量一键指向本机网关(`+x(f.value.gatewayBase)+`)。 开启前自动备份原配置为 *.ellm-bak(保留最早的原始备份),关闭时从备份还原。 `,1),y.value?(C(),_(u,{key:0,title:y.value,type:S.value,"show-icon":``,class:`mb-8`,onClose:r[1]||=e=>y.value=null},null,8,[`title`,`type`])):c(``,!0),e(`div`,I,[e(`div`,L,[e(`div`,R,[r[8]||=n(` Claude Code `,-1),o(T,{type:f.value.claudeCode?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(f.value.claudeCode?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),r[9]||=e(`div`,{class:`switch-desc`},[n(` 写入 `),e(`code`,null,`~/.claude/settings.json`),n(` 的 env.ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN, 鉴权取网关配置的 masterKey(未设置将开启失败);其余字段原样保留,重启 Claude Code 会话后生效。 `)],-1)]),o(E,{"model-value":f.value.claudeCode,loading:v.value===`claudeCode`,onChange:r[2]||=e=>O(`claudeCode`,!!e)},null,8,[`model-value`,`loading`])]),o(D,{class:`switch-divider`}),e(`div`,z,[e(`div`,B,[e(`div`,V,[r[10]||=n(` Codex CLI `,-1),o(T,{type:f.value.codex?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(f.value.codex?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),r[11]||=e(`div`,{class:`switch-desc`},[n(` 写入 `),e(`code`,null,`~/.codex/config.toml`),n(` 的 model_provider 与 [model_providers.ellm-proxy] 段 (保留用户注释与排版);开启后需按提示设置环境变量 ELLM_PROXY_API_KEY 供 Codex 鉴权。 `)],-1)]),o(E,{"model-value":f.value.codex,loading:v.value===`codex`,onChange:r[3]||=e=>O(`codex`,!!e)},null,8,[`model-value`,`loading`])]),o(D,{class:`switch-divider`}),e(`div`,H,[e(`div`,U,[e(`div`,W,[r[12]||=n(` DeepSeek Harness `,-1),o(T,{type:f.value.dsh?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(f.value.dsh?`已开启`:`未开启`),1)]),_:1},8,[`type`])]),r[13]||=e(`div`,{class:`switch-desc`},[n(` 写入 `),e(`code`,null,`~/.dsh/settings.yaml`),n(` 的 llm-deepseek.baseURL 与 `),e(`code`,null,`~/.dsh/.credentials.yaml`),n(` 的 DEEPSEEK_API_KEY(取网关 masterKey,未设置则写占位值);模型请在 dsh 内选择与网关部署名一致的模型。 dsh 为 developer preview,配置格式可能随版本变化。 `)],-1)]),o(E,{"model-value":f.value.dsh,loading:v.value===`dsh`,onChange:r[4]||=e=>O(`dsh`,!!e)},null,8,[`model-value`,`loading`])])],64)):(C(),_(k,{key:1,description:m.value||`暂无开关状态`},{default:g(()=>[o(i,{type:`primary`,onClick:r[5]||=e=>w(!1)},{default:g(()=>[...r[14]||=[n(`重试`,-1)]]),_:1})]),_:1},8,[`description`]))]),_:1})),[[j,a.value]])}}}),[[`__scopeId`,`data-v-00711dc3`]]);a(),w(),i();var K={class:`flex-col-gap`},q={class:`flex-between`},J={class:`muted-sm`},ee={class:`login-row`},te={class:`muted-sm`},ne={class:`flex-between`},re={class:`monitor-row`},ie={class:`monitor-row`},ae={class:`monitor-row`},oe={class:`save-bar`},Y=m(s({__name:`SettingsView`,setup(i){let{toast:a}=A(),{copyWithToast:s}=k(),m=D(),w=t(`basic`),T=t(!0),E=t(!1),N=t(``),P=async()=>{N.value&&await s(N.value)},F=t(29770),I=t(null),L=t(!0),R=t(``),z=t(``),B=t(!1),V=v(()=>N.value.trim()!==``||B.value&&R.value.trim()!==``&&z.value!==``),H=t(!1),U=t(60),W=[{label:`10分钟`,value:10},{label:`30分钟`,value:30},{label:`1小时`,value:60},{label:`2小时`,value:120},{label:`5小时`,value:300},{label:`8小时`,value:480},{label:`12小时`,value:720},{label:`24小时`,value:1440}],Y=t(!1),X=t(!0),{loadError:Z,run:Q}=O(`设置加载失败,请重试`),$=()=>Q(async()=>{try{await m.load(),N.value=m.config.masterKey||``,F.value=m.config.port??29770;let e=m.config[`web-ui`]?.[`login-account`];R.value=e?.username||``,z.value=e?.password||``,B.value=M(m.config[`web-ui`]),L.value=m.config.allowLan!==!1;let t=m.config.latencyTest;H.value=t?.enabled===!0,U.value=t?.intervalMinutes??60;let n=j(m.config[`web-ui`]);Y.value=n.managedServices,X.value=n.plugins;try{let e=await f.get(`/api/status`);I.value=e.listenPort}catch{I.value=null}}finally{T.value=!1}}),se=async()=>{if(B.value&&(R.value.trim()===``||z.value===``)){a(`启用管理台登录时请填写用户名和密码(长度与字符不限)`,`error`);return}E.value=!0;let e=H.value&&m.config.latencyTest?.enabled!==!0;try{let t=await m.update(e=>{e.masterKey=N.value.trim(),e.port=F.value,e.allowLan=L.value,e.latencyTest={enabled:H.value,intervalMinutes:U.value},e[`web-ui`]??={},e[`web-ui`][`login-enabled`]=B.value,B.value&&(e[`web-ui`][`login-account`]??={},e[`web-ui`][`login-account`].username=R.value.trim(),e[`web-ui`][`login-account`].password=z.value),e[`web-ui`].nav??={},e[`web-ui`].nav[`managed-services`]=Y.value,e[`web-ui`].nav.plugins=X.value});await y(!0),a(`设置已保存并生效`,`success`),e&&a(`已开启自动测试:服务将定期直连所有上游发送探测请求,有少量 token 消耗`,`warning`),t.restartHint&&a(t.restartHint,`warning`)}catch(e){a(e.message,`error`)}finally{E.value=!1}};return u($),(t,i)=>{let a=p(`el-button`),s=p(`el-alert`),u=p(`el-tag`),f=p(`el-input`),m=p(`el-form-item`),v=p(`el-input-number`),y=p(`el-form`),D=p(`el-card`),O=p(`el-switch`),k=p(`el-divider`),A=p(`el-option`),j=p(`el-select`),M=p(`el-tab-pane`),Q=p(`el-tabs`),ce=b(`loading`);return C(),_(Q,{modelValue:w.value,"onUpdate:modelValue":i[10]||=e=>w.value=e,class:`settings-tabs`},{default:g(()=>[o(M,{label:`基本设置`,name:`basic`},{default:g(()=>[h((C(),l(`div`,K,[r(Z)?(C(),_(s,{key:0,title:r(Z),type:`error`,"show-icon":``,closable:!1},{default:g(()=>[o(a,{size:`small`,onClick:$},{default:g(()=>[...i[11]||=[n(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):c(``,!0),o(D,{shadow:`never`},{header:g(()=>[e(`div`,q,[i[13]||=e(`span`,{class:`fw-600`},`网关访问`,-1),o(u,{type:`success`},{default:g(()=>[...i[12]||=[n(`运行中`,-1)]]),_:1})])]),default:g(()=>[o(y,{"label-position":`top`},{default:g(()=>[o(m,{label:`API 密钥 (masterKey)`},{default:g(()=>[o(f,{modelValue:N.value,"onUpdate:modelValue":i[0]||=e=>N.value=e,placeholder:`sk-1234`,clearable:``},{append:g(()=>[o(a,{onClick:P},{default:g(()=>[...i[14]||=[n(`复制`,-1)]]),_:1})]),_:1},8,[`modelValue`]),i[15]||=e(`div`,{class:`muted-sm`},`客户端请求 /v1/* 时的认证密钥(Bearer <masterKey>;留空 = 本地放行)`,-1)]),_:1}),o(m,{label:`监听端口 (port)`},{default:g(()=>[o(v,{modelValue:F.value,"onUpdate:modelValue":i[1]||=e=>F.value=e,min:1,max:65535,step:1,style:{width:`220px`}},null,8,[`modelValue`]),e(`div`,J,[i[17]||=n(` 网关与管理台 API 的监听端口,保存后重启生效 `,-1),I.value===null?c(``,!0):(C(),l(d,{key:0},[i[16]||=n(` ;服务上报的端口 `,-1),e(`b`,null,x(I.value),1)],64))])]),_:1})]),_:1})]),_:1}),o(D,{shadow:`never`},{header:g(()=>[...i[18]||=[e(`span`,{class:`fw-600`},`安全与登录`,-1)]]),default:g(()=>[o(y,{"label-position":`top`},{default:g(()=>[o(m,{label:`启用管理台登录`},{default:g(()=>[o(O,{modelValue:B.value,"onUpdate:modelValue":i[2]||=e=>B.value=e},null,8,[`modelValue`]),i[19]||=e(`div`,{class:`muted-sm`},` 开启后访问管理台需要下方用户名密码;关闭 = 免登录直接访问(仅本机使用时推荐) `,-1)]),_:1}),B.value?(C(),_(m,{key:0,label:`管理台登录账号`},{default:g(()=>[e(`div`,ee,[o(f,{modelValue:R.value,"onUpdate:modelValue":i[3]||=e=>R.value=e,placeholder:`用户名`,style:{width:`200px`}},null,8,[`modelValue`]),o(f,{modelValue:z.value,"onUpdate:modelValue":i[4]||=e=>z.value=e,type:`password`,placeholder:`密码(长度与字符不限)`,"show-password":``,style:{width:`200px`}},null,8,[`modelValue`])]),i[20]||=e(`div`,{class:`muted-sm`},`修改后立即生效,需用新账号重新登录;用户名和密码不校验长度,任意字符均可`,-1)]),_:1})):c(``,!0),!B.value&&L.value?(C(),_(s,{key:1,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`,title:`已允许局域网访问但未启用管理台登录:局域网内设备可直接打开管理台。建议启用登录或关闭局域网访问。`})):c(``,!0),o(m,{label:`允许局域网访问 (allowLan)`},{default:g(()=>[o(O,{modelValue:L.value,"onUpdate:modelValue":i[5]||=e=>L.value=e},null,8,[`modelValue`]),e(`div`,te,[i[21]||=n(` 开启 = 绑定全部网卡,局域网内设备可访问;关闭 = 仅本机 127.0.0.1。保存后需重启生效 `,-1),V.value?c(``,!0):(C(),l(d,{key:0},[n(` ;未设置任何有效凭据(主密钥为空且登录未启用)时始终仅绑本机 `)],64))])]),_:1})]),_:1})]),_:1}),o(D,{shadow:`never`},{header:g(()=>[e(`div`,ne,[i[22]||=e(`span`,{class:`fw-600`},`模型服务监控`,-1),o(u,{type:H.value?`success`:`info`,size:`small`,"disable-transitions":``},{default:g(()=>[n(x(H.value?`已开启`:`未开启`),1)]),_:1},8,[`type`])])]),default:g(()=>[e(`div`,re,[i[23]||=e(`div`,{class:`monitor-info`},[e(`div`,{class:`monitor-title`},`自动测试模型服务状态`),e(`div`,{class:`muted-sm`},` 按设定间隔自动直连所有上游模型发送极小探测请求(max_tokens: 1,有少量 token 消耗); 测试结果展示在首页「服务状态」tab `)],-1),o(O,{modelValue:H.value,"onUpdate:modelValue":i[6]||=e=>H.value=e},null,8,[`modelValue`])]),H.value?(C(),l(d,{key:0},[o(k,{style:{margin:`12px 0`}}),o(y,{"label-position":`top`},{default:g(()=>[o(m,{label:`测试间隔`,style:{"margin-bottom":`0`}},{default:g(()=>[o(j,{modelValue:U.value,"onUpdate:modelValue":i[7]||=e=>U.value=e,style:{width:`220px`}},{default:g(()=>[(C(),l(d,null,S(W,e=>o(A,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`])),64))]),_:1},8,[`modelValue`]),i[24]||=e(`div`,{class:`muted-sm`},`自动测试的执行间隔,保存后即时生效(无需重启)`,-1)]),_:1})]),_:1})],64)):c(``,!0)]),_:1}),o(D,{shadow:`never`},{header:g(()=>[...i[25]||=[e(`span`,{class:`fw-600`},`界面与入口`,-1)]]),default:g(()=>[e(`div`,ie,[i[26]||=e(`div`,{class:`monitor-info`},[e(`div`,{class:`monitor-title`},`显示「托管服务」入口`),e(`div`,{class:`muted-sm`},`开启后顶部导航显示「托管服务」tab;默认关闭,不用的功能不占导航`)],-1),o(O,{modelValue:Y.value,"onUpdate:modelValue":i[8]||=e=>Y.value=e},null,8,[`modelValue`])]),o(k,{style:{margin:`12px 0`}}),e(`div`,ae,[i[27]||=e(`div`,{class:`monitor-info`},[e(`div`,{class:`monitor-title`},`显示「插件」入口`),e(`div`,{class:`muted-sm`},` 开启后顶部导航显示「插件」tab,并同时启用插件服务(关闭会隐藏入口并停止插件服务);默认开启 `)],-1),o(O,{modelValue:X.value,"onUpdate:modelValue":i[9]||=e=>X.value=e},null,8,[`modelValue`])])]),_:1}),e(`div`,oe,[o(a,{type:`primary`,size:`large`,loading:E.value,disabled:E.value||r(Z)!==null,onClick:se},{default:g(()=>[n(x(E.value?`保存中...`:`保存设置`),1)]),_:1},8,[`loading`,`disabled`])])])),[[ce,T.value]])]),_:1}),o(M,{label:`代理开关`,name:`harness`,lazy:``},{default:g(()=>[o(G)]),_:1})]),_:1},8,[`modelValue`])}}}),[[`__scopeId`,`data-v-e3f72f2d`]]);export{Y as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,C as t,Et as n,F as r,H as i,I as a,L as o,M as s,N as c,Q as l,a as u,at as d,d as f,h as p,ht as m,j as h,n as g,pt as _,r as v,tt as y,u as b,yt as x}from"./router-
|
|
1
|
+
import{A as e,C as t,Et as n,F as r,H as i,I as a,L as o,M as s,N as c,Q as l,a as u,at as d,d as f,h as p,ht as m,j as h,n as g,pt as _,r as v,tt as y,u as b,yt as x}from"./router-Cpy-sU_q.js";import{t as S}from"./message-BgUNwRuF.js";import{t as C}from"./clipboard-JYWVdyjq.js";i(),p(),x();var w={class:`setup-wrap`},T={class:`account-row`},E=f(o({__name:`SetupView`,setup(i){let o=b(),f=n(!1),p=n(``),x=n(!1),E=!1,D=n(``),O=n(``),k=n(!1),A=n(!1),j=n(``);l(async()=>{let e=await g();x.value=e.masterKeySet,k.value=e.authRequired===!0});function M(){p.value=(()=>{let e=new Uint8Array(32);crypto.getRandomValues(e);let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)})(),E=!0}_(f,e=>{j.value=``,e?(k.value=!0,p.value.trim()===``&&M()):E&&=(p.value=``,!1)});async function N(){await C(p.value)?S.success(`已复制到剪贴板`):S.error(`复制失败,请手动选择复制`)}async function P(){j.value=``;let e=f.value?`server`:`local`,t=p.value.trim();if(f.value&&t===``){j.value=`服务器部署必须设置主密钥,防止 /v1 网关被他人盗用`;return}if(f.value&&!k.value){j.value=`服务器部署必须启用管理台登录并设置账号密码,防止管理台被陌生人登录`;return}if(k.value&&(D.value.trim()===``||O.value===``)){j.value=`启用管理台登录时请填写用户名和密码(长度与字符不限)`;return}A.value=!0;try{let n=await u.post(`/api/setup/finish`,{deployment:e,...t===``?{}:{masterKey:t},loginEnabled:k.value,...k.value?{username:D.value.trim(),password:O.value}:{}});v(e,k.value),S.success(k.value?`初始化完成,请使用新账号登录`:`初始化完成,免登录进入管理台`),n.restartHint&&S({message:n.restartHint,type:`warning`,duration:8e3}),await o.push(k.value?`/login`:`/`)}catch(e){j.value=e.message||`保存失败`}finally{A.value=!1}}return(n,i)=>{let o=d(`el-checkbox`),l=d(`el-alert`),u=d(`el-button`),g=d(`el-input`),_=d(`el-form-item`),v=d(`el-switch`),b=d(`el-form`),S=d(`el-card`);return y(),c(`div`,w,[a(S,{shadow:`never`,class:`setup-card`},{default:m(()=>[i[12]||=e(`div`,{class:`setup-brand`},[e(`span`,{class:`brand-mark`},`EZ`),e(`span`,{class:`setup-title`},`初始化 EZLLM`)],-1),i[13]||=e(`p`,{class:`setup-sub`},`首次使用前完成部署形态与访问凭据的配置`,-1),a(o,{modelValue:f.value,"onUpdate:modelValue":i[0]||=e=>f.value=e,class:`mb-16`},{default:m(()=>[...i[5]||=[r(` 允许其他设备访问本服务(局域网 / 公网部署) `,-1)]]),_:1},8,[`modelValue`]),f.value?(y(),h(l,{key:0,type:`warning`,"show-icon":``,closable:!1,title:`服务将对网络中的其他设备可见,请务必设置主密钥并启用管理台登录`,class:`mb-16`})):s(``,!0),a(b,{"label-position":`top`,onSubmit:t(P,[`prevent`])},{default:m(()=>[a(_,null,{label:m(()=>[...i[6]||=[r(` API 主密钥(本地部署可留空) `,-1),e(`span`,{class:`label-hint`},`调用 /v1/* 时的 Bearer Token;留空 = 不启用鉴权,且未启用管理台登录时服务仅本机可访问`,-1)]]),default:m(()=>[a(g,{modelValue:p.value,"onUpdate:modelValue":i[1]||=e=>p.value=e,placeholder:x.value?`已设置主密钥,留空保持不变`:`未设置主密钥`,clearable:``},{append:m(()=>[a(u,{onClick:M},{default:m(()=>[...i[7]||=[r(`生成`,-1)]]),_:1}),a(u,{disabled:!p.value,onClick:N},{default:m(()=>[...i[8]||=[r(`复制`,-1)]]),_:1},8,[`disabled`])]),_:1},8,[`modelValue`,`placeholder`])]),_:1}),a(_,null,{label:m(()=>[...i[9]||=[r(` 管理台登录 `,-1),e(`span`,{class:`label-hint`},`开启后访问管理台需要用户名密码;本地单人使用可关闭,对外访问必须开启`,-1)]]),default:m(()=>[a(v,{modelValue:k.value,"onUpdate:modelValue":i[2]||=e=>k.value=e,"inline-prompt":``,"active-text":`启用`,"inactive-text":`关闭`},null,8,[`modelValue`])]),_:1}),k.value?(y(),h(_,{key:0},{label:m(()=>[...i[10]||=[r(` 登录账号密码 `,-1),e(`span`,{class:`label-hint`},`长度与字符不限,任意非空内容均可`,-1)]]),default:m(()=>[e(`div`,T,[a(g,{modelValue:D.value,"onUpdate:modelValue":i[3]||=e=>D.value=e,placeholder:`用户名`,clearable:``},null,8,[`modelValue`]),a(g,{modelValue:O.value,"onUpdate:modelValue":i[4]||=e=>O.value=e,type:`password`,"show-password":``,placeholder:`密码`},null,8,[`modelValue`])])]),_:1})):s(``,!0),j.value?(y(),h(l,{key:1,title:j.value,type:`error`,"show-icon":``,closable:!1,class:`mb-16`},null,8,[`title`])):s(``,!0),a(u,{type:`primary`,class:`full-width`,loading:A.value,onClick:P},{default:m(()=>[...i[11]||=[r(` 完成初始化 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})])}}}),[[`__scopeId`,`data-v-789fc546`]]);export{E as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Et as e,H as t,a as n,k as r,yt as i}from"./router-
|
|
1
|
+
import{Et as e,H as t,a as n,k as r,yt as i}from"./router-Cpy-sU_q.js";import{n as a}from"./index-BviWrBv1.js";i(),t();var o=a(`config`,()=>{let t=e({}),i=e(!1),a=r(()=>Array.isArray(t.value.providers)?t.value.providers:[]),o=r(()=>a.value.length),s=r(()=>a.value.reduce((e,t)=>e+(t.models?.length??0),0));async function c(){i.value=!0;try{t.value=await n.get(`/api/config`)}finally{i.value=!1}}let l=Promise.resolve();function u(e){let r=e??JSON.parse(JSON.stringify(t.value)),i=()=>n.put(`/api/config`,r),a=l.then(i,i);return l=a.then(()=>void 0,()=>void 0),a}async function d(e){return e(t.value),await u()}return{config:t,loading:i,providers:a,providerCount:o,totalModelCount:s,load:c,save:u,update:d}});export{o as t};
|