ezllm 0.0.45 → 0.0.47

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.
Files changed (64) hide show
  1. package/README.md +5 -5
  2. package/dist/cli.js +24 -23
  3. package/dist/daemon.js +14 -6
  4. package/dist/plugin-host.js +3 -3
  5. package/dist/server.js +75 -75
  6. package/dist/web-ui/assets/DashboardView-CNsnnzad.css +1 -0
  7. package/dist/web-ui/assets/DashboardView-CqupMCmm.js +2 -0
  8. package/dist/web-ui/assets/LayoutView-CyOrx1rA.js +1 -0
  9. package/dist/web-ui/assets/LayoutView-cQeiOjLU.css +1 -0
  10. package/dist/web-ui/assets/LoginView-YolyK2Q0.js +1 -0
  11. package/dist/web-ui/assets/{LogsView-CXFJ_22b.css → LogsView-DPmB8dy8.css} +1 -1
  12. package/dist/web-ui/assets/LogsView-E64a6PIt.js +5 -0
  13. package/dist/web-ui/assets/ManagedServicesView-DVCADa1y.css +1 -0
  14. package/dist/web-ui/assets/ManagedServicesView-mk_mSWzE.js +6 -0
  15. package/dist/web-ui/assets/PluginsView-DTJeufic.js +2 -0
  16. package/dist/web-ui/assets/PluginsView-DzHAW2gO.css +1 -0
  17. package/dist/web-ui/assets/ProvidersView-BrirhwQN.js +14 -0
  18. package/dist/web-ui/assets/ProvidersView-BwX8Y3kP.css +1 -0
  19. package/dist/web-ui/assets/SettingsView-BGMZbskz.css +1 -0
  20. package/dist/web-ui/assets/SettingsView-p3uvWhGh.js +1 -0
  21. package/dist/web-ui/assets/SetupView-6BYv_B5n.css +1 -0
  22. package/dist/web-ui/assets/SetupView-CGQibXHs.js +1 -0
  23. package/dist/web-ui/assets/config-Dzo6AFZx.js +1 -0
  24. package/dist/web-ui/assets/{format-CPPf8IfM.js → format-Deb1hfjO.js} +1 -1
  25. package/dist/web-ui/assets/{index-s_h6GEbv.css → index-DodsqGDu.css} +1 -1
  26. package/dist/web-ui/assets/index-wQG3qUgW.js +49 -0
  27. package/dist/web-ui/assets/message-C8pR37GK.js +2 -0
  28. package/dist/web-ui/assets/navVisibility-CPbwxq3d.js +1 -0
  29. package/dist/web-ui/assets/pluginProviders-DeHPKGnd.js +1 -0
  30. package/dist/web-ui/assets/providers-Dbg0NkwB.js +1 -0
  31. package/dist/web-ui/assets/router-JpU_7F6L.js +6 -0
  32. package/dist/web-ui/assets/{useCopyToast-BeWZ6lSF.js → useCopyToast-GaJ4QVNE.js} +1 -1
  33. package/dist/web-ui/assets/useManagerApi-DEPhOKWy.js +1 -0
  34. package/dist/web-ui/assets/{useQuickRangeFilter-DQQ8QAr5.js → useQuickRangeFilter-DeKORPZt.js} +1 -1
  35. package/dist/web-ui/assets/useToast-DVCDN-da.js +1 -0
  36. package/dist/web-ui/index.html +4 -4
  37. package/ezllm.config.example.json +0 -1
  38. package/package.json +2 -1
  39. package/dist/web-ui/assets/DashboardView-CkTFY0Da.js +0 -1
  40. package/dist/web-ui/assets/LayoutView-CcXUd-b0.js +0 -1
  41. package/dist/web-ui/assets/LayoutView-D84C9Iqp.css +0 -1
  42. package/dist/web-ui/assets/LoginView-Dq7gaxB9.js +0 -1
  43. package/dist/web-ui/assets/LogsView-CO6GNtfl.js +0 -5
  44. package/dist/web-ui/assets/ManagedServicesView-CNLHAVAL.js +0 -6
  45. package/dist/web-ui/assets/ManagedServicesView-D29NyvP6.css +0 -1
  46. package/dist/web-ui/assets/PluginsView-B2H4xfag.css +0 -1
  47. package/dist/web-ui/assets/PluginsView-Dljy9HZq.js +0 -2
  48. package/dist/web-ui/assets/ProvidersView-CD3QYu3i.js +0 -14
  49. package/dist/web-ui/assets/ProvidersView-Cwe2Q81Y.css +0 -1
  50. package/dist/web-ui/assets/ServiceStatusView-BgHmV09I.js +0 -2
  51. package/dist/web-ui/assets/ServiceStatusView-DmUKbS8w.css +0 -1
  52. package/dist/web-ui/assets/SettingsView-BLQl0mEB.js +0 -1
  53. package/dist/web-ui/assets/SettingsView-NXkxZUgr.css +0 -1
  54. package/dist/web-ui/assets/SetupView-BzZqIZpo.js +0 -1
  55. package/dist/web-ui/assets/SetupView-CSBKlfcJ.css +0 -1
  56. package/dist/web-ui/assets/config-CLbcTOt9.js +0 -1
  57. package/dist/web-ui/assets/index-yak1S-7W.js +0 -49
  58. package/dist/web-ui/assets/message-K5WVknE-.js +0 -2
  59. package/dist/web-ui/assets/pluginProviders-CB38zjhC.js +0 -1
  60. package/dist/web-ui/assets/providers-BuzQNH1W.js +0 -1
  61. package/dist/web-ui/assets/router-tvNif7bs.js +0 -6
  62. package/dist/web-ui/assets/updateNote-CttDt8SZ.js +0 -1
  63. package/dist/web-ui/assets/useManagerApi-Wm9Nz3_p.js +0 -1
  64. package/dist/web-ui/assets/useToast-D_jja27E.js +0 -1
@@ -1,6 +0,0 @@
1
- import{A as e,F as t,I as n,M as r,O as i,P as a,Pt as o,Q as s,Tt as c,V as l,Wt as u,Z as d,at as f,et as p,fn as m,ht as h,it as g,j as _,k as v,mt as y,vt as b,w as x}from"./router-tvNif7bs.js";import{W as S}from"./message-K5WVknE-.js";import{n as C,t as w}from"./index-yak1S-7W.js";import{t as T}from"./useManagerApi-Wm9Nz3_p.js";import{n as E,t as D}from"./useCopyToast-BeWZ6lSF.js";import{t as O}from"./useToast-D_jja27E.js";import{m as k}from"./format-CPPf8IfM.js";l(),u(),b();var A={class:`form-hint`},j={key:1,class:`form-hint form-hint--block`},M=w(n({__name:`ManagedServiceModal`,props:{editingName:{},service:{}},emits:[`close`,`saved`],setup(n,{emit:o}){let s=n,l=o,{toast:u}=O(),d=c(),f=c(!1),h=c(!0),b=i(()=>s.service?.pid!=null),S=c({name:s.service?.name??``,exec:s.service?.exec??``,cwd:s.service?.cwd??``,autostart:s.service?.autostart??!0}),C=c((s.service?.args??[]).join(`
2
- `)),w={name:[{required:!0,message:`请填写服务名`,trigger:`blur`},{pattern:/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/,message:`只能用字母、数字、点、下划线、短横线(字母或数字开头,不超过 64 个字符)`,trigger:`blur`}],cwd:[{required:!0,message:`请填写工作目录`,trigger:`blur`}]},E=async()=>{let e=e=>e.split(`
3
- `).map(e=>e.trim()).filter(e=>e!==``);if(!await d.value?.validate().catch(()=>!1)){u(`请补全标红的必填项`,`error`);return}let t={name:S.value.name.trim(),exec:S.value.exec.trim(),args:e(C.value),cwd:S.value.cwd.trim(),autostart:S.value.autostart};b.value||(t.start=h.value),f.value=!0;try{s.editingName===null?(await T.createManagedService(t),u(t.start?`服务已添加并启动`:`服务已添加`,`success`)):(await T.updateManagedService(s.editingName,t),u(b.value?`已保存,服务正按新配置重启`:`已保存`,`success`)),l(`saved`)}catch(e){u(e.message||`保存失败`,`error`)}finally{f.value=!1}};return(i,o)=>{let s=g(`el-input`),c=g(`el-form-item`),u=g(`el-switch`),T=g(`el-form`),D=g(`el-button`),O=g(`el-dialog`);return p(),e(O,{"model-value":!0,title:n.editingName?`编辑托管服务`:`添加托管服务`,width:`720px`,top:`6vh`,"align-center":``,"close-on-click-modal":!1,onClose:o[7]||=e=>l(`close`)},{footer:y(()=>[t(D,{disabled:f.value,onClick:o[6]||=e=>l(`close`)},{default:y(()=>[...o[13]||=[a(`取消`,-1)]]),_:1},8,[`disabled`]),t(D,{type:`primary`,loading:f.value,onClick:E},{default:y(()=>[a(m(f.value?`保存中...`:n.editingName?`保存`:`添加服务`),1)]),_:1},8,[`loading`])]),default:y(()=>[t(T,{ref_key:`formRef`,ref:d,model:S.value,rules:w,"label-position":`top`},{default:y(()=>[t(c,{label:`服务名`,prop:`name`},{default:y(()=>[t(s,{modelValue:S.value.name,"onUpdate:modelValue":o[0]||=e=>S.value.name=e,disabled:n.editingName!==null,placeholder:`如 codebuddy-cpa(字母数字开头,可用 . _ -)`},null,8,[`modelValue`,`disabled`]),v(`div`,A,[o[8]||=a(` 名称用于日志文件名(logs/out-<名称>.log)与进程标识;`,-1),n.editingName===null?_(``,!0):(p(),r(x,{key:0},[a(`编辑时不可修改(改名请删除后重新添加)。`)],64))])]),_:1}),t(c,{label:`工作目录`,prop:`cwd`},{default:y(()=>[t(s,{modelValue:S.value.cwd,"onUpdate:modelValue":o[1]||=e=>S.value.cwd=e,placeholder:`如 E:\\gitee\\codebuddy-cpa(服务的运行目录)`},null,8,[`modelValue`]),o[9]||=v(`div`,{class:`form-hint`},`服务在此目录下启动;保存时会校验目录是否存在。`,-1)]),_:1}),t(c,{label:`可执行文件`},{default:y(()=>[t(s,{modelValue:S.value.exec,"onUpdate:modelValue":o[2]||=e=>S.value.exec=e,placeholder:`留空 = 使用 ezllm 主进程的 Node;也可填 npm.cmd 或绝对路径`},null,8,[`modelValue`]),o[10]||=v(`div`,{class:`form-hint`},` 留空时用主进程的 Node 直接运行下方参数(第一个参数通常是脚本相对工作目录的路径)。 Windows 上 .cmd / .bat / 无扩展名的命令(如 npm)会自动经 cmd.exe 执行;其他平台直接执行。 `,-1)]),_:1}),t(c,{label:`参数`},{default:y(()=>[t(s,{modelValue:C.value,"onUpdate:modelValue":o[3]||=e=>C.value=e,type:`textarea`,rows:3,placeholder:`每行一个参数,如:
4
- src/proxy.js
5
- --log
6
- proxy.log`},null,8,[`modelValue`]),o[11]||=v(`div`,{class:`form-hint`},`逐行填写,每行作为一个完整参数传递(含空格也不拆分),不需要加引号。`,-1)]),_:1}),t(c,{label:`开机自启`},{default:y(()=>[t(u,{modelValue:S.value.autostart,"onUpdate:modelValue":o[4]||=e=>S.value.autostart=e},null,8,[`modelValue`]),o[12]||=v(`span`,{class:`form-hint form-hint--inline`},` 开启后随 ezllm 主进程启动自动拉起(系统登录后、以及 ezllm 更新重启后) `,-1)]),_:1}),b.value?(p(),r(`div`,j,` 该服务当前正在运行:保存后将按新配置自动重启,使改动立即生效。 `)):(p(),e(c,{key:0,label:`保存后立即启动`},{default:y(()=>[t(u,{modelValue:h.value,"onUpdate:modelValue":o[5]||=e=>h.value=e},null,8,[`modelValue`])]),_:1}))]),_:1},8,[`model`])]),_:1},8,[`title`])}}}),[[`__scopeId`,`data-v-55b26af7`]]);l(),b(),u();var N={class:`page-head`},P={class:`page-head-actions`},F={class:`flex-between`},I={class:`muted-sm`},L={class:`name-cell`},R={class:`fw-600`},z={class:`cmd-cell`},B={class:`mono`},V=[`title`],H={class:`mono`},U={class:`muted-sm`},W={key:1,class:`muted-sm`},G=w(n({__name:`ManagedServicesView`,setup(n){let{toast:i}=O(),{copyWithToast:l}=D(),{loadError:u,run:b}=E(`托管服务加载失败,请重试`),w=c([]),A=c(null),j=c(!0),G=c(!0),K=c(null),q=c(!1),J=c(null),Y=e=>[e.exec===``?`主进程 Node`:e.exec,...e.args].join(` `),X=()=>b(async()=>{try{let e=await T.managedServices();w.value=e.services??[],A.value=e.configError??null,G.value=!0}catch(e){if(typeof e?.message==`string`&&e.message.includes(`未由 ezllm 主进程托管`)){G.value=!1,w.value=[],A.value=null,u.value=null;return}throw e}finally{j.value=!1}}),Z=()=>{J.value=null,q.value=!0},ee=e=>{J.value=e.name,q.value=!0},te=async()=>{q.value=!1,await X()},Q=async(e,t,n)=>{if(!K.value){K.value=e;try{await t(),i(n,`success`),await X()}catch(e){i(e.message||`操作失败`,`error`)}finally{K.value=null}}},$=async(e,t)=>{let n={start:`启动`,stop:`停止`,restart:`重启`}[t];if(t===`stop`||t===`restart`)try{await C.confirm(`确定${n}服务 ${e.name}?`,`${n}确认`,{confirmButtonText:n,cancelButtonText:`取消`,type:`warning`})}catch{return}let r={start:()=>T.startManagedService(e.name),stop:()=>T.stopManagedService(e.name),restart:()=>T.restartManagedService(e.name)}[t];await Q(`${t}:${e.name}`,async()=>void await r(),`${n}指令已执行:${e.name}`)},ne=async(e,t)=>{let n=t?`开启「${e.name}」开机自启?此后随 ezllm 主进程启动自动拉起(不改变当前运行状态)。`:`关闭「${e.name}」开机自启?此后不再随 ezllm 启动自动拉起(不改变当前运行状态)。`;try{await C.confirm(n,t?`开启确认`:`关闭确认`,{confirmButtonText:t?`开启`:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{return}await Q(`autostart:${e.name}`,async()=>{await T.updateManagedService(e.name,{name:e.name,exec:e.exec,args:e.args,cwd:e.cwd,autostart:t})},t?`已开启开机自启`:`已关闭开机自启`)},re=async e=>{try{await C.confirm(`确定删除托管服务 ${e.name}?${e.pid?`该服务正在运行,会先被停止;`:``}此后不再随 ezllm 启动,其配置将被移除。`,`确认删除`,{confirmButtonText:`确定`,cancelButtonText:`取消`,type:`warning`})}catch{return}await Q(`remove:${e.name}`,async()=>{await T.removeManagedService(e.name)},`已删除:${e.name}`)},ie=async e=>{await l(e.logFiles.out,`已复制日志路径:${e.logFiles.out}`)},ae=window.setInterval(()=>{q.value||K.value||X()},5e3);return s(()=>window.clearInterval(ae)),d(X),(n,i)=>{let s=g(`el-button`),c=g(`el-icon`),l=g(`el-alert`),d=g(`el-tag`),b=g(`el-table-column`),C=g(`el-switch`),T=g(`el-table`),E=g(`el-card`),D=f(`loading`);return p(),r(`div`,null,[v(`div`,N,[i[3]||=v(`div`,null,[v(`div`,{class:`page-head-title`},`托管服务`),v(`div`,{class:`page-head-sub`},` 由 ezllm 主进程守护的外部服务:可随开机自启、崩溃自动重启,与网关服务同等纳管 `)],-1),v(`div`,P,[t(s,{loading:j.value,onClick:X},{default:y(()=>[...i[1]||=[a(`刷新`,-1)]]),_:1},8,[`loading`]),t(s,{type:`primary`,disabled:!G.value,onClick:Z},{default:y(()=>[t(c,null,{default:y(()=>[t(o(S))]),_:1}),i[2]||=a(` 添加服务 `,-1)]),_:1},8,[`disabled`])])]),o(u)?(p(),e(l,{key:0,title:o(u),type:`error`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[t(s,{size:`small`,onClick:X},{default:y(()=>[...i[4]||=[a(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):_(``,!0),A.value?(p(),e(l,{key:1,title:`托管服务清单不可用:${A.value}`,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`},{default:y(()=>[...i[5]||=[v(`div`,{class:`muted-sm`},` 修复该文件后重启 ezllm(或重新添加服务)即可恢复;期间已有服务不会自动加载。 `,-1)]]),_:1},8,[`title`])):_(``,!0),t(E,{shadow:`never`},{header:y(()=>[v(`div`,F,[i[6]||=v(`span`,{class:`fw-600`},`服务列表`,-1),v(`span`,I,m(w.value.length)+` 个服务`,1)])]),default:y(()=>[h((p(),e(T,{data:w.value,"empty-text":`暂无托管服务,点击右上角「添加服务」创建`},{default:y(()=>[t(b,{label:`服务名`,"min-width":`150`},{default:y(({row:t})=>[v(`div`,L,[v(`span`,R,m(t.name),1),t.pid?(p(),e(d,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:y(()=>[...i[7]||=[a(`运行中`,-1)]]),_:1})):(p(),e(d,{key:1,type:`info`,size:`small`,"disable-transitions":``},{default:y(()=>[...i[8]||=[a(`已停止`,-1)]]),_:1}))])]),_:1}),t(b,{label:`启动命令`,"min-width":`240`},{default:y(({row:e})=>[v(`div`,z,[v(`span`,B,m(Y(e)),1),v(`span`,{class:`muted-sm cwd-text`,title:e.cwd},m(e.cwd),9,V)])]),_:1}),t(b,{label:`进程`,width:`110`},{default:y(({row:e})=>[e.pid?(p(),r(x,{key:0},[v(`div`,H,`pid `+m(e.pid),1),v(`div`,U,m(e.startedAt?o(k)(e.startedAt):``),1)],64)):(p(),r(`span`,W,`-`))]),_:1}),t(b,{label:`开机自启`,width:`100`,align:`center`},{default:y(({row:e})=>[t(C,{"model-value":e.autostart,loading:K.value===`autostart:${e.name}`,onChange:t=>ne(e,!!t)},null,8,[`model-value`,`loading`,`onChange`])]),_:1}),t(b,{label:`日志`,width:`100`,align:`center`},{default:y(({row:e})=>[t(s,{link:``,type:`primary`,onClick:t=>ie(e)},{default:y(()=>[...i[9]||=[a(`复制路径`,-1)]]),_:1},8,[`onClick`])]),_:1}),t(b,{label:`操作`,width:`230`,align:`center`},{default:y(({row:n})=>[n.pid?(p(),r(x,{key:1},[t(s,{link:``,type:`warning`,loading:K.value===`restart:${n.name}`,onClick:e=>$(n,`restart`)},{default:y(()=>[...i[11]||=[a(`重启`,-1)]]),_:1},8,[`loading`,`onClick`]),t(s,{link:``,type:`danger`,loading:K.value===`stop:${n.name}`,onClick:e=>$(n,`stop`)},{default:y(()=>[...i[12]||=[a(`停止`,-1)]]),_:1},8,[`loading`,`onClick`])],64)):(p(),e(s,{key:0,link:``,type:`primary`,loading:K.value===`start:${n.name}`,onClick:e=>$(n,`start`)},{default:y(()=>[...i[10]||=[a(`启动`,-1)]]),_:1},8,[`loading`,`onClick`])),t(s,{link:``,onClick:e=>ee(n)},{default:y(()=>[...i[13]||=[a(`编辑`,-1)]]),_:1},8,[`onClick`]),t(s,{link:``,type:`danger`,loading:K.value===`remove:${n.name}`,onClick:e=>re(n)},{default:y(()=>[...i[14]||=[a(`删除`,-1)]]),_:1},8,[`loading`,`onClick`])]),_:1})]),_:1},8,[`data`])),[[D,j.value]])]),_:1}),q.value?(p(),e(M,{key:2,"editing-name":J.value,service:J.value==null?void 0:w.value.find(e=>e.name===J.value),onClose:i[0]||=e=>q.value=!1,onSaved:te},null,8,[`editing-name`,`service`])):_(``,!0)])}}}),[[`__scopeId`,`data-v-f4d654e1`]]);export{G as default};
@@ -1 +0,0 @@
1
- .form-hint[data-v-55b26af7]{color:var(--el-text-color-secondary);margin-top:4px;font-size:12px;line-height:1.6}.form-hint--inline[data-v-55b26af7]{margin-top:0;margin-left:8px}.form-hint--block[data-v-55b26af7]{margin-bottom:8px}.name-cell[data-v-f4d654e1]{align-items:center;gap:8px;display:flex}.cmd-cell[data-v-f4d654e1]{flex-direction:column;gap:2px;min-width:0;display:flex}.mono[data-v-f4d654e1]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px}.cwd-text[data-v-f4d654e1]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}
@@ -1 +0,0 @@
1
- .plugin-grid[data-v-60925e93]{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px;display:grid}.plugin-card[data-v-60925e93]{border:1px solid var(--el-border-color-light);border-radius:8px;flex-direction:column;gap:10px;padding:16px;transition:border-color .15s;display:flex}.plugin-card[data-v-60925e93]:hover{border-color:var(--el-color-primary-light-5)}.card-top[data-v-60925e93]{align-items:flex-start;gap:12px;display:flex}.plugin-icon[data-v-60925e93]{background:var(--el-fill-color-light);border-radius:8px;flex-shrink:0;justify-content:center;align-items:center;width:40px;height:40px;font-size:18px;font-weight:600;display:flex;overflow:hidden}.plugin-icon img[data-v-60925e93]{object-fit:contain;width:100%;height:100%}.plugin-titles[data-v-60925e93]{flex:1;min-width:0}.plugin-name[data-v-60925e93]{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;overflow:hidden}.plugin-tags[data-v-60925e93]{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.plugin-action[data-v-60925e93]{flex-shrink:0}.plugin-summary[data-v-60925e93]{color:var(--el-text-color-regular);-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;min-height:39px;font-size:13px;line-height:1.5;display:-webkit-box;overflow:hidden}.plugin-meta[data-v-60925e93]{color:var(--el-text-color-secondary);border-top:1px solid var(--el-border-color-lighter);flex-wrap:wrap;gap:12px;padding-top:10px;font-size:12px;display:flex}.mono[data-v-60925e93]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.installed-error[data-v-60925e93]{margin-bottom:12px}.installed-list[data-v-60925e93]{scrollbar-width:thin;scrollbar-color:var(--el-border-color) transparent;flex-direction:column;gap:12px;max-height:70vh;padding-right:4px;display:flex;overflow:hidden auto}.installed-list[data-v-60925e93]::-webkit-scrollbar:horizontal{height:0;display:none}.installed-summary[data-v-60925e93]{color:var(--el-text-color-secondary);margin-bottom:12px;font-size:12px}.installed-summary-ok[data-v-60925e93]{color:var(--el-color-success)}.installed-card[data-v-60925e93]{border:1px solid var(--el-border-color-light);background:var(--el-bg-color);border-radius:12px;flex-shrink:0;transition:border-color .15s,box-shadow .15s;overflow:hidden;box-shadow:0 1px 2px #00000008}.installed-card[data-v-60925e93]:hover{border-color:var(--el-color-primary-light-7);box-shadow:0 2px 8px #0000000f}.installed-head[data-v-60925e93]{background:var(--el-fill-color-lighter);border-bottom:1px solid var(--el-border-color-lighter);align-items:flex-start;gap:12px;padding:12px 14px;display:flex}.installed-avatar[data-v-60925e93]{background:var(--el-color-primary-light-9);width:32px;height:32px;color:var(--el-color-primary);border-radius:9px;flex-shrink:0;justify-content:center;align-items:center;font-size:14px;font-weight:600;display:flex}.installed-identity[data-v-60925e93]{flex:1;min-width:0}.installed-title[data-v-60925e93]{align-items:center;gap:8px;min-width:0;display:flex}.installed-name[data-v-60925e93]{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--el-text-color-primary);font-size:14px;font-weight:600;overflow:hidden}.installed-version[data-v-60925e93]{border:1px solid var(--el-border-color-light);background:var(--el-bg-color);color:var(--el-text-color-regular);border-radius:999px;flex-shrink:0;padding:0 6px;font-size:11px;line-height:16px}.installed-desc[data-v-60925e93]{color:var(--el-text-color-regular);-webkit-line-clamp:2;line-clamp:2;-webkit-box-orient:vertical;margin-top:4px;font-size:12px;line-height:1.5;display:-webkit-box;overflow:hidden}.installed-pkgname[data-v-60925e93]{color:var(--el-text-color-placeholder);text-overflow:ellipsis;white-space:nowrap;margin-top:3px;font-size:11px;overflow:hidden}.installed-ops[data-v-60925e93]{flex-shrink:0;align-items:center;gap:4px;padding-top:2px;display:flex}.installed-ops .el-button[data-v-60925e93]{height:auto;padding:0}.installed-ops .card-more[data-v-60925e93]{width:28px;height:28px;color:var(--el-text-color-secondary);border-radius:6px;padding:0}.installed-ops .card-more[data-v-60925e93]:hover{color:var(--el-color-primary);background:var(--el-fill-color-darker)}.danger-text[data-v-60925e93]{color:var(--el-color-danger)}.installed-noprovider[data-v-60925e93]{color:var(--el-text-color-secondary);padding:10px 14px 12px;font-size:12px}.installed-providers[data-v-60925e93]{padding:2px 14px}.installed-provider[data-v-60925e93]{justify-content:space-between;align-items:center;gap:12px;padding:10px 0;display:flex}.installed-provider[data-v-60925e93]:not(:last-child){border-bottom:1px solid var(--el-border-color-lighter)}.installed-provider-info[data-v-60925e93]{align-items:baseline;gap:8px;min-width:0;display:flex}.installed-provider-id[data-v-60925e93]{text-overflow:ellipsis;white-space:nowrap;min-width:0;color:var(--el-text-color-primary);font-size:13px;overflow:hidden}.installed-provider-models[data-v-60925e93]{color:var(--el-text-color-secondary);flex-shrink:0;font-size:12px}.installed-provider-actions[data-v-60925e93]{flex-shrink:0;align-items:center;gap:8px;display:flex}.installed-provider-actions .el-button[data-v-60925e93]{height:auto;padding:0}.installed-state[data-v-60925e93]{color:var(--el-text-color-secondary);white-space:nowrap;align-items:center;gap:4px;font-size:12px;display:inline-flex}.installed-state .status-dot[data-v-60925e93]{background:var(--el-text-color-placeholder);margin-right:0}.installed-state.is-on[data-v-60925e93]{color:var(--el-color-success)}.installed-state.is-on .status-dot[data-v-60925e93]{background:var(--el-color-success)}.method-list[data-v-60925e93]{flex-direction:column;gap:8px;margin-top:12px;display:flex}.method-btn[data-v-60925e93]{justify-content:flex-start;margin-left:0}.field-row[data-v-60925e93]:not(:first-child){margin-top:12px}
@@ -1,2 +0,0 @@
1
- import{A as e,F as t,I as n,J as r,M as i,O as a,P as o,Pt as s,Tt as c,V as l,Wt as u,Z as ee,et as d,fn as f,it as p,j as m,k as h,m as g,mt as _,nt as v,sn as te,vt as ne,w as y,x as re}from"./router-tvNif7bs.js";import{H as ie,W as ae}from"./message-K5WVknE-.js";import{n as oe,t as b}from"./index-yak1S-7W.js";import{t as x}from"./useManagerApi-Wm9Nz3_p.js";import{n as S,t as se}from"./providers-BuzQNH1W.js";import{t as ce}from"./useToast-D_jja27E.js";import{a as C,c as le,i as ue,l as w,n as de,o as fe,r as pe,s as T,t as me,u as he}from"./pluginProviders-CB38zjhC.js";ne();var E=`https://raw.githubusercontent.com/magpie-community/plugins/main/registry.json`,D=[`https://gh-proxy.com/${E}`,`https://ghfast.top/${E}`,E],O=1e4,k=`plugin_market_cache`,A=1,ge=216e5,_e=36e5,ve=[`provider`];function ye(){try{let e=localStorage.getItem(k);if(e===null)return null;let t=JSON.parse(e);if(t.version!==A||!Array.isArray(t.entries))return null;let n=t.fetchedAt;return n===void 0||typeof n.at!=`number`?null:{version:A,entries:t.entries.filter(Se),fetchedAt:n}}catch{return null}}function be(e,t){try{let n={version:A,entries:e,fetchedAt:t};localStorage.setItem(k,JSON.stringify(n))}catch{}}function j(e){return typeof e==`string`&&e.trim()!==``?e.trim():null}function xe(e){if(typeof e!=`object`||!e||Array.isArray(e))return null;let t=e;return j(t.zh)??j(t.en)}function M(e){switch(e){case`provider`:case`middleware`:case`agent`:case`tools`:case`page`:return e;default:return`provider`}}function N(e){return ve.includes(e)}function Se(e){if(typeof e!=`object`||!e)return!1;let t=e.kind;return typeof t==`string`&&N(t)}function Ce(e){let t=j(e.package);if(t===null)return null;let n=Array.isArray(e.providers)?e.providers.filter(e=>typeof e==`string`):[];return{package:t,name:j(e.name)??t,icon:j(e.icon),providers:n,community:j(e.community),summary:xe(e.summary),kind:M(e.kind),replaces:j(e.replaces),version:null,license:null,description:null,homepage:null,weeklyDownloads:null}}var we=new Map,P=new Map;async function F(e){let t=we.get(e);if(t!==void 0&&Date.now()-t.at<_e)return t.meta;try{let t=await w(`https://registry.npmjs.org/${encodeURIComponent(e)}`),n={version:j(t[`dist-tags`]?.latest),license:j(t.license),description:j(t.description),homepage:j(t.homepage)};return we.set(e,{at:Date.now(),meta:n}),n}catch{return{version:null,license:null,description:null,homepage:null}}}async function I(e){let t=P.get(e);if(t!==void 0&&Date.now()-t.at<_e)return t.downloads;try{let t=await w(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(e)}`),n=typeof t.downloads==`number`?t.downloads:null;return P.set(e,{at:Date.now(),downloads:n}),n}catch{return null}}async function Te(){let e=[];for(let t of D)try{let e=await w(t,{timeoutMs:O});return t!==D[0]&&S(`[plugin-market] 清单改由备用源取到:${t}`),{registry:e,source:t}}catch(n){let r=n instanceof Error?n.message:String(n);e.push(`${t} → ${r}`)}throw Error(`插件清单取不到(已试 ${String(D.length)} 个源):\n${e.join(`
2
- `)}`)}async function Ee(e){let{registry:t,source:n}=await Te(),r=t.plugins;if(!Array.isArray(r))throw Error(`清单格式不是预期形状(缺 plugins 数组):${E}`);let i=r.map(e=>typeof e==`object`&&e?Ce(e):null).filter(Se).sort((e,t)=>e.package.localeCompare(t.package)),a=0;return await Promise.all(i.map(async t=>{let[n,r]=await Promise.all([F(t.package),I(t.package)]);Object.assign(t,n,{weeklyDownloads:r}),a+=1,e?.(a,i.length)})),{entries:i,source:n}}var L=c([]),R=c(!1),z=c(null),B=c({loaded:0,total:0}),V=c(null),H=c(!1),De=null;function Oe(e,t){JSON.stringify(e)!==JSON.stringify(L.value)&&(L.value=e),V.value=t,be(e,t)}async function ke(e={}){let t=e.force===!0,n=L.value.length===0?ye():null;n!==null&&(L.value=n.entries,V.value=n.fetchedAt);let r=L.value.length>0,i=V.value,a=i!==null&&Date.now()-i.at<ge;if(!(!t&&r&&a)){if(De!==null){if(t)await De;else return}if(t||!r){R.value=!0,H.value=!1,B.value={loaded:0,total:0};try{let e=await Ee((e,t)=>{B.value={loaded:e,total:t}});Oe(e.entries,{source:e.source,at:Date.now()}),z.value=null}catch(e){z.value=`插件市场清单加载失败:${e instanceof Error?e.message:String(e)}`}finally{R.value=!1}return}H.value=!0,De=(async()=>{try{let e=await Ee();Oe(e.entries,{source:e.source,at:Date.now()}),z.value=null,H.value=!1}catch(e){S(`[plugin-market] 后台刷新失败,继续用缓存:${e instanceof Error?e.message:String(e)}`)}finally{De=null}})()}}function Ae(){return{entries:L,loading:R,marketError:z,progress:B,fetchedAt:V,stale:H,loadMarket:ke}}l(),ne(),u(),g();var je={class:`page-head`},Me={class:`page-head-actions`},Ne={class:`flex-between`},Pe={class:`muted-sm`},Fe={key:0,class:`loading-block`},Ie={key:1,class:`loading-block`},Le={key:2,class:`plugin-grid`},Re={class:`card-top`},ze={class:`plugin-icon`},Be=[`src`,`alt`,`onError`],Ve={key:1},He={class:`plugin-titles`},Ue=[`title`],We={class:`plugin-tags`},Ge={class:`plugin-action`},Ke=[`title`],qe={class:`plugin-meta`},Je={key:0},Ye={key:1,class:`mono`},Xe={key:2,class:`muted-disabled`},Ze={key:2,class:`installed-summary`},Qe={class:`installed-summary-ok`},$e={key:3,class:`installed-list`},et={class:`installed-head`},tt={class:`installed-avatar`},nt={class:`installed-identity`},rt={class:`installed-title`},it=[`title`],at={class:`installed-version`},ot=[`title`],st=[`title`],ct={class:`installed-ops`},lt={key:0,class:`installed-noprovider`},ut={key:1,class:`installed-providers`},dt={class:`installed-provider-info`},ft=[`title`],pt={class:`installed-provider-models`},mt={class:`installed-provider-actions`},ht={class:`method-list`},gt={class:`muted-sm`},_t={key:0,class:`muted-sm`},vt={class:`muted-sm`},yt={class:`muted-sm`},bt={key:0,class:`mt-8`},xt=[`href`],St={key:2,class:`muted-sm mt-8`},Ct=5e3,wt=b(n({__name:`PluginsView`,setup(n){let{toast:l}=ce(),u=se(),g=c(!0),ne=c(`服务未由 ezllm 主进程托管(源码运行模式);请用 ezllm 启动服务`),b=c(!1),S=c(!1),E=c(null),D=c(!1),O=c(!0),k=c(!1),{entries:A,loading:ge,marketError:_e,progress:ve,fetchedAt:ye,stale:be,loadMarket:j}=Ae(),xe=c(new Set),M=c([]),N=c(null),Se=a(()=>{let e=M.value.flatMap(e=>e.providers);return{total:e.length,signedIn:e.filter(e=>e.signedIn).length}}),Ce=e=>A.value.find(t=>t.package===e)?.name??e.replace(/^@[^/]+\//,``),we=e=>{let t=Ce(e).trim();return t===``?`?`:t.charAt(0).toUpperCase()},P=c(null),F=c(!1),I=c(``),Te=c(!1),Ee=c(!1),L=c({}),R=c(!1),z=c(!0),B=a(()=>S.value&&E.value!==null),V=e=>M.value.some(t=>t.package===e.package),H=e=>e.icon===null||xe.value.has(e.package)?null:/^https?:\/\//i.test(e.icon)?e.icon:null,De=e=>e.icon!==null&&!/^https?:\/\//i.test(e.icon)?e.icon:(e.name.charAt(0)||`?`).toUpperCase(),Oe=e=>{xe.value=new Set(xe.value).add(e.package)},ke=e=>e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e),wt=async()=>{try{let e=await x.plugins();g.value=!0,b.value=e.enabled,O.value=e.autoUpdate,S.value=e.running,E.value=e.port}catch(e){if(typeof e?.message==`string`&&e.message.includes(`未由 ezllm 主进程托管`)){g.value=!1,ne.value=e.message,b.value=!1,O.value=!1,S.value=!1,E.value=null;return}throw e}},U=async()=>{if(!B.value){M.value=[],N.value=null;return}let e=E.value;if(e!==null)try{let t=await w(T(e,`/packages`));M.value=Array.isArray(t.packages)?t.packages:[],N.value=null}catch(e){M.value=[],N.value=`无法读取已装插件(插件服务可能正在重启):${e?.message??`请求失败`}`}},Tt=e=>{let t=Math.floor((Date.now()-e)/6e4);if(t<1)return`刚刚`;if(t<60)return`${String(t)} 分钟前`;let n=Math.floor(t/60);return n<24?`${String(n)} 小时前`:new Date(e).toLocaleDateString()},Et=a(()=>{if(ge.value)return`正在加载 ${String(ve.value.loaded)}/${String(ve.value.total)}…`;let e=ye.value===null?``:Tt(ye.value.at),t=e===``?``:` · ${e}更新`,n=be.value?` · 更新中…`:``;return`${String(A.value.length)} 个插件 · 已装 ${String(M.value.length)} 个${t}${n}`}),Dt=async(e=!1)=>{await j({force:e})},Ot=async()=>{try{await wt()}catch(e){_e.value=e?.message??`插件服务状态加载失败`;return}await U(),await Dt(),W()},kt=c(!1),At=async e=>{let t=await w(T(e,`/plugins`));return Array.isArray(t.providers)?t.providers:[]},jt=async(e,t)=>{try{let n=await w(`${ue(t,e)}/v1/models`,{timeoutMs:Ct}),r=(n.data??[]).map(e=>typeof e.id==`string`?e.id.trim():``).filter(e=>e!==``);return{fromHook:n.fromHook===!0,ids:r}}catch{return null}},Mt=async()=>{let e=E.value;if(B.value&&e!==null){kt.value=!0;try{await u.loadProviders();let t=await At(e),n=pe(u.suppliers,t,e),r=t.filter(e=>e.protocol!==null&&n.providers.filter(t=>C(t.apiBase)===e.id).some(t=>me(t,e))),i=new Map;await Promise.all(r.map(async t=>{let n=await jt(t.id,e);n!==null&&i.set(t.id,n)}));let a=de(n.providers,t,i);if(n.added.length===0&&n.updated.length===0&&a.refreshed.length===0)return;await u.saveProviders(a.providers);let o=[];n.added.length>0&&o.push(`新增 ${String(n.added.length)} 个供应商`),n.updated.length>0&&o.push(`修正 ${String(n.updated.length)} 个供应商`),a.refreshed.length>0&&o.push(`刷新 ${String(a.refreshed.length)} 个供应商的模型清单`),l(`已接入网关:${o.join(`、`)}`,`success`)}catch(e){l(e?.message??`供应商配置同步失败`,`error`)}finally{kt.value=!1}}},Nt=null,W=()=>(Nt===null&&(Nt=Mt().finally(()=>{Nt=null})),Nt),Pt=async e=>{D.value=!0;try{let t=await x.setPluginEnabled(e);b.value=t.enabled,S.value=t.running,E.value=t.port,l(e?`插件服务已开启`:`插件服务已关闭`,`success`),await U()}catch(e){await wt().catch(()=>void 0),l(e?.message??`操作失败`,`error`)}finally{D.value=!1}},Ft=async e=>{if(e){await Pt(!0);return}try{await oe.confirm(`关闭插件服务?已装插件保留,但插件模型的请求将不可用。`,`关闭确认`,{confirmButtonText:`关闭`,cancelButtonText:`取消`,type:`warning`})}catch{await wt().catch(()=>void 0);return}await Pt(!1)},It=async e=>{let t=!!e;k.value=!0;try{let e=await x.setPluginAutoUpdate(t);O.value=e.autoUpdate,l(t?`已开启插件自动更新`:`已关闭插件自动更新`,`success`)}catch(e){await wt().catch(()=>void 0),l(e?.message??`操作失败`,`error`)}finally{k.value=!1}},Lt=async e=>{await zt(e.package)},Rt=async()=>{let e=I.value.trim();if(e!==``){Ee.value=!0;try{await zt(e),F.value=!1,I.value=``}finally{Ee.value=!1}}},zt=async e=>{let t=E.value;if(t===null){l(`插件服务未开启`,`error`);return}P.value=e;try{(await he(T(t,`/packages`),{package:e})).loaded===!1?l(`${e} 已安装但未加载成功(重启插件服务或查看日志)`,`warning`):l(`已安装 ${e}`,`success`),await U(),await W()}catch(e){l(e?.message??`安装失败`,`error`)}finally{P.value=null}},Bt=async e=>{let t=E.value;if(t===null)return;let n=[];try{await u.loadProviders(),n=fe(u.suppliers,e.providers.map(e=>e.id))}catch{}let r=n.length===0?``:`网关里对应的供应商(${n.join(`、`)})也会一并移除。`;try{await oe.confirm(`确定卸载 ${e.package}?该插件提供的模型将不可用。${r}`,`确认卸载`,{confirmButtonText:`卸载`,cancelButtonText:`取消`,type:`warning`})}catch{return}P.value=e.package;try{await le(T(t,`/packages/${encodeURIComponent(e.package)}`)),n.length>0&&await u.saveProviders(u.suppliers.filter(e=>!n.includes(e.name))),l(`已卸载 ${e.package}`,`success`),await U()}catch(e){l(e?.message??`卸载失败`,`error`)}finally{P.value=null}},Vt=(e,t)=>{e===`uninstall`&&Bt(t)},Ht=()=>{I.value=``,F.value=!0},Ut=async()=>{await U(),Te.value=!0},Wt=a(()=>B.value?z.value?`检查已装插件是否有新版本`:`宿主当前无法检查更新`:`插件服务未开启`),Gt=e=>{let t=L.value[e];return t&&t.updateAvailable&&t.latest?t.latest:null},Kt=async(e=!1)=>{let t=E.value;if(t===null){e||l(`插件服务未开启`,`error`);return}R.value=!0;try{let n=await w(T(t,`/packages/updates`)),r=Array.isArray(n.packages)?n.packages:[];z.value=n.canCheck;let i={};for(let e of r)i[e.package]=e;if(L.value=i,e)return;if(!n.canCheck){l(`宿主当前无法检查更新`,`warning`);return}let a=r.filter(e=>e.updateAvailable).length;l(a>0?`发现 ${String(a)} 个插件有新版本`:`全部插件已是最新`,`success`)}catch(t){e||l(t?.message??`检查更新失败`,`error`)}finally{R.value=!1}},qt=async e=>{let t=E.value,n=L.value[e]?.latest;if(t===null){l(`插件服务未开启`,`error`);return}if(n!=null){P.value=e;try{await he(T(t,`/packages`),{package:e,version:n});let r=await x.restartPlugins();S.value=r.running,E.value=r.port,l(`已更新到 ${n} 并重启插件服务`,`success`),delete L.value[e],await U(),await W(),await Kt(!0)}catch(e){l(e?.message??`更新失败`,`error`)}finally{P.value=null}}},Jt=c(null),Yt=c(!1),Xt=c(``),Zt=c([]),G=c(!1),Qt=c(``),K=c(``),$t=c(``),q=c(null),J=c(!1),en=c(``),tn=c(``),nn=c(``),Y=c(``),rn=c(void 0),an=c({}),X=c(null),on=c(!1),Z=c(!1),sn=c(``),cn=c([]),Q=c({}),ln=c(void 0),un=c(null),dn=c(!1),$=new Map,fn=!1,pn=e=>{$.set(e,($.get(e)??0)+1)};r(()=>{fn=!0,$.clear()});let mn=(e,t)=>{K.value!==``&&K.value!==e&&pn(K.value),K.value=e,Qt.value=t.url??``,$t.value=t.instructions??``,q.value=null,G.value=!0},hn=async e=>{let t=E.value;if(t===null)return;let n=($.get(e)??0)+1;$.set(e,n);let r=()=>!fn&&$.get(e)===n,i=Date.now()+18e4;for(;;){if(await new Promise(e=>setTimeout(e,2e3)),!r())return;let n;try{n=await w(T(t,`/login/${encodeURIComponent(e)}`))}catch(t){r()&&K.value===e&&(q.value=t?.message??`查询登录状态失败`);return}if(!r())return;if(n.state===`success`){K.value===e&&(G.value=!1),l(`已登录${n.accountId?`(${n.accountId})`:``}`,`success`),await U(),await W();return}if(n.state===`failed`){K.value===e&&(q.value=n.error??`登录失败`);return}if(Date.now()>i){K.value===e&&(q.value=`等待超时,可关闭后重新点击「登录」`);return}}},gn=async(e,t,n,r)=>{let i=E.value;if(i===null){l(`插件服务未开启`,`error`);return}pn(e);let a={};t!==void 0&&(a.method=t),Object.keys(n).length>0&&(a.inputs=n),r!==void 0&&r!==``&&(a.key=r);let o=await he(T(i,`/login/${encodeURIComponent(e)}`),a);if(o.needMethod===!0){Xt.value=e,Zt.value=o.methods,Yt.value=!0;return}if(o.needInputs!==void 0&&o.needInputs.length>0){J.value=!1,sn.value=e,ln.value=t,cn.value=o.needInputs;let r={...o.inputs??n};for(let e of o.needInputs)r[e.key]=r[e.key]??``;Q.value=r,un.value=null,Z.value=!0;return}if(o.needKey===!0){Z.value=!1,en.value=e,rn.value=t,tn.value=o.label??``,nn.value=o.placeholder??``,an.value={...o.inputs??n},Y.value=``,X.value=null,J.value=!0;return}if(o.state===`success`){Z.value=!1,J.value=!1,l(`已登录${o.accountId?`(${o.accountId})`:``}`,`success`),await U(),await W();return}if(o.state===`failed`){let e=o.error??`登录失败`;if(J.value){X.value=e;return}if(Z.value){un.value=e;return}l(e,`error`);return}Z.value=!1,J.value=!1,mn(e,o),hn(e)},_n=async(e,t)=>{Jt.value=e;try{await gn(e,t,{})}catch(e){l(e?.message??`发起登录失败`,`error`)}finally{Jt.value=null}},vn=c(null),yn=async e=>{let t=E.value;if(t===null){l(`插件服务未开启`,`error`);return}try{await oe.confirm(`确定退出 ${e.id} 的登录?本机保存的凭据会被删除,该供应商的模型将立即不可用(插件与网关配置保留)。`,`确认退出登录`,{confirmButtonText:`退出登录`,cancelButtonText:`取消`,type:`warning`})}catch{return}pn(e.id),K.value===e.id&&(G.value=!1),vn.value=e.id;try{await le(T(t,`/login/${encodeURIComponent(e.id)}`)),l(`已退出 ${e.id} 的登录`,`success`),await U()}catch(e){let t=String(e?.message??``);l(t.includes(`405`)?`当前插件服务版本不支持退出登录,请先升级 ezllm`:e?.message??`退出登录失败`,`error`)}finally{vn.value=null}},bn=async e=>{Yt.value=!1,await _n(Xt.value,e)},xn=async()=>{dn.value=!0;try{await gn(sn.value,ln.value,{...Q.value})}catch(e){un.value=e?.message??`提交失败`}finally{dn.value=!1}},Sn=async()=>{if(Y.value.trim()===``){X.value=`请填写密钥`;return}on.value=!0,X.value=null;try{await gn(en.value,rn.value,{...an.value},Y.value)}catch(e){X.value=e?.message??`提交失败`}finally{on.value=!1}};return ee(Ot),(n,r)=>{let a=p(`el-switch`),c=p(`el-button`),l=p(`el-icon`),u=p(`el-alert`),ee=p(`el-tag`),oe=p(`el-card`),x=p(`el-input`),se=p(`el-form-item`),ce=p(`el-form`),C=p(`el-dialog`),le=p(`el-empty`),ue=p(`el-dropdown-item`),w=p(`el-dropdown-menu`),de=p(`el-dropdown`),fe=p(`el-option`),pe=p(`el-select`);return d(),i(`div`,null,[h(`div`,je,[r[23]||=h(`div`,null,[h(`div`,{class:`page-head-title`},`插件`),h(`div`,{class:`page-head-sub`},` 订阅社区 OpenCode 插件——把订阅账号(CodeBuddy、智谱 Coding Plan 等)当作供应商接入网关 `)],-1),h(`div`,Me,[t(a,{modelValue:b.value,"onUpdate:modelValue":r[0]||=e=>b.value=e,loading:D.value,disabled:!g.value||D.value,"active-text":`插件服务`,"inline-prompt":``,onChange:Ft},null,8,[`modelValue`,`loading`,`disabled`]),t(a,{modelValue:O.value,"onUpdate:modelValue":r[1]||=e=>O.value=e,loading:k.value,disabled:!g.value||k.value,"active-text":`自动更新`,"inline-prompt":``,title:`插件会在后台每小时检查并更新`,onChange:It},null,8,[`modelValue`,`loading`,`disabled`]),t(c,{disabled:!S.value,onClick:Ut},{default:_(()=>[...r[20]||=[o(`已装插件`,-1)]]),_:1},8,[`disabled`]),t(c,{disabled:!S.value,onClick:Ht},{default:_(()=>[t(l,null,{default:_(()=>[t(s(ae))]),_:1}),r[21]||=o(` 手动安装 `,-1)]),_:1},8,[`disabled`]),t(c,{loading:s(ge),onClick:r[2]||=e=>Dt(!0)},{default:_(()=>[...r[22]||=[o(`刷新`,-1)]]),_:1},8,[`loading`])])]),g.value?S.value?m(``,!0):(d(),e(u,{key:1,type:`info`,"show-icon":``,closable:!1,class:`mb-16`,title:`插件服务未开启`},{default:_(()=>[r[25]||=h(`div`,{class:`muted-sm`},`开启后即可安装并加载插件;下方清单仍可浏览。`,-1),t(c,{size:`small`,type:`primary`,class:`mt-8`,loading:D.value,onClick:r[3]||=e=>Pt(!0)},{default:_(()=>[...r[24]||=[o(` 开启插件服务 `,-1)]]),_:1},8,[`loading`])]),_:1})):(d(),e(u,{key:0,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`,title:`插件服务不可用`},{default:_(()=>[o(f(ne.value),1)]),_:1})),s(_e)?(d(),e(u,{key:2,type:`error`,"show-icon":``,closable:!1,class:`mb-16`,title:s(_e)},{default:_(()=>[t(c,{size:`small`,onClick:Dt},{default:_(()=>[...r[26]||=[o(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):m(``,!0),t(oe,{shadow:`never`},{header:_(()=>[h(`div`,Ne,[r[27]||=h(`span`,{class:`fw-600`},`社区插件`,-1),h(`span`,Pe,f(Et.value),1)])]),default:_(()=>[s(ge)&&s(A).length===0?(d(),i(`div`,Fe,`正在从社区清单加载…`)):s(A).length===0?(d(),i(`div`,Ie,` 清单里没有本宿主支持的插件(只收 provider 类),可点右上角「刷新」重试,或用「手动安装」直接按包名安装。 `)):(d(),i(`div`,Le,[(d(!0),i(y,null,v(s(A),t=>(d(),i(`div`,{key:t.package,class:`plugin-card`},[h(`div`,Re,[h(`div`,ze,[H(t)?(d(),i(`img`,{key:0,src:H(t),alt:t.name,onError:e=>Oe(t)},null,40,Be)):(d(),i(`span`,Ve,f(De(t)),1))]),h(`div`,He,[h(`div`,{class:`plugin-name`,title:t.name},f(t.name),9,Ue),h(`div`,We,[t.community?(d(),e(ee,{key:0,size:`small`,type:`info`,"disable-transitions":``},{default:_(()=>[o(f(t.community),1)]),_:2},1024)):m(``,!0)])]),h(`div`,Ge,[V(t)?(d(),e(ee,{key:0,type:`success`,size:`small`,"disable-transitions":``},{default:_(()=>[...r[28]||=[o(`已装`,-1)]]),_:1})):(d(),e(c,{key:1,type:`primary`,size:`small`,disabled:!B.value||P.value===t.package,loading:P.value===t.package,onClick:e=>Lt(t)},{default:_(()=>[...r[29]||=[o(` 安装 `,-1)]]),_:1},8,[`disabled`,`loading`,`onClick`]))])]),h(`div`,{class:`plugin-summary`,title:t.summary??``},f(t.summary??`(清单未提供简介)`),9,Ke),h(`div`,qe,[h(`span`,null,`供应商 `+f(t.providers.length),1),t.weeklyDownloads===null?m(``,!0):(d(),i(`span`,Je,f(ke(t.weeklyDownloads))+`/周`,1)),t.version?(d(),i(`span`,Ye,`v`+f(t.version),1)):(d(),i(`span`,Xe,`版本未知`))])]))),128))]))]),_:1}),t(C,{modelValue:F.value,"onUpdate:modelValue":r[6]||=e=>F.value=e,title:`手动安装插件`,width:`520px`},{footer:_(()=>[t(c,{onClick:r[5]||=e=>F.value=!1},{default:_(()=>[...r[31]||=[o(`取消`,-1)]]),_:1}),t(c,{type:`primary`,loading:Ee.value,disabled:I.value.trim()===``,onClick:Rt},{default:_(()=>[...r[32]||=[o(` 安装 `,-1)]]),_:1},8,[`loading`,`disabled`])]),default:_(()=>[t(ce,{"label-position":`top`},{default:_(()=>[t(se,{label:`npm 包名`},{default:_(()=>[t(x,{modelValue:I.value,"onUpdate:modelValue":r[4]||=e=>I.value=e,placeholder:`例:@magpie-community/opencode-workbuddy-auth`,clearable:``},null,8,[`modelValue`]),r[30]||=h(`div`,{class:`muted-sm`},[o(`可带版本(`),h(`span`,{class:`mono`},`name@1.2.3`),o(`);清单加载不出来时用这个。`)],-1)]),_:1})]),_:1})]),_:1},8,[`modelValue`]),t(C,{modelValue:Te.value,"onUpdate:modelValue":r[9]||=e=>Te.value=e,title:`已装插件`,width:`800px`,top:`6vh`},{footer:_(()=>[t(c,{disabled:!B.value||kt.value,loading:kt.value,title:`把宿主已加载的插件供应商补进网关配置:缺的整条新增,已在的只修地址/协议(模型清单保持你的选择)`,onClick:W},{default:_(()=>[...r[37]||=[o(`接入网关`,-1)]]),_:1},8,[`disabled`,`loading`]),t(c,{disabled:!B.value||!z.value||P.value!==null,loading:R.value,title:Wt.value,onClick:r[7]||=e=>Kt()},{default:_(()=>[...r[38]||=[o(`检查更新`,-1)]]),_:1},8,[`disabled`,`loading`,`title`]),t(c,{onClick:r[8]||=e=>Te.value=!1},{default:_(()=>[...r[39]||=[o(`关闭`,-1)]]),_:1})]),default:_(()=>[N.value?(d(),e(u,{key:0,type:`warning`,"show-icon":``,closable:!1,class:`installed-error`,title:N.value},null,8,[`title`])):m(``,!0),M.value.length===0&&!N.value?(d(),e(le,{key:1,description:`尚未安装任何插件`,"image-size":80})):m(``,!0),M.value.length>0?(d(),i(`div`,Ze,[o(f(M.value.length)+` 个插件 · `+f(Se.value.total)+` 个供应商 · `,1),h(`span`,Qe,f(Se.value.signedIn)+` 个已登录`,1)])):m(``,!0),M.value.length>0?(d(),i(`div`,$e,[(d(!0),i(y,null,v(M.value,n=>(d(),i(`div`,{key:n.package,class:`installed-card`},[h(`div`,et,[h(`div`,tt,f(we(n.package)),1),h(`div`,nt,[h(`div`,rt,[h(`span`,{class:`installed-name`,title:n.package},f(Ce(n.package)),9,it),h(`span`,at,`v`+f(n.version||`-`),1),n.loaded?m(``,!0):(d(),e(ee,{key:0,type:`danger`,size:`small`,"disable-transitions":``},{default:_(()=>[...r[33]||=[o(`加载失败`,-1)]]),_:1}))]),n.description?(d(),i(`div`,{key:0,class:`installed-desc`,title:n.description},f(n.description),9,ot)):m(``,!0),Ce(n.package)===n.package?m(``,!0):(d(),i(`div`,{key:1,class:`mono installed-pkgname`,title:n.package},f(n.package),9,st))]),h(`div`,ct,[Gt(n.package)?(d(),e(c,{key:0,link:``,type:`primary`,size:`small`,disabled:P.value!==null||R.value,loading:P.value===n.package,onClick:e=>qt(n.package)},{default:_(()=>[o(`更新到 `+f(Gt(n.package)),1)]),_:2},1032,[`disabled`,`loading`,`onClick`])):m(``,!0),t(de,{trigger:`click`,placement:`bottom-end`,onCommand:e=>Vt(e,n)},{dropdown:_(()=>[t(w,null,{default:_(()=>[t(ue,{command:`uninstall`,disabled:P.value!==null},{default:_(()=>[...r[34]||=[h(`span`,{class:`danger-text`},`卸载插件`,-1)]]),_:1},8,[`disabled`])]),_:1})]),default:_(()=>[t(c,{link:``,size:`small`,class:`card-more`,title:`更多操作`},{default:_(()=>[t(l,null,{default:_(()=>[t(s(ie))]),_:1})]),_:1})]),_:1},8,[`onCommand`])])]),n.providers.length?(d(),i(`div`,ut,[(d(!0),i(y,null,v(n.providers,t=>(d(),i(`div`,{key:t.id,class:`installed-provider`},[h(`div`,dt,[h(`span`,{class:`mono installed-provider-id`,title:t.id},f(t.id),9,ft),h(`span`,pt,f(t.models)+` 个模型`,1)]),h(`div`,mt,[h(`span`,{class:te([`installed-state`,{"is-on":t.signedIn}])},[h(`span`,{class:te([`status-dot`,{running:t.signedIn}])},null,2),h(`span`,null,f(t.signedIn?`已登录`:t.needsLogin===!1?`无需登录`:`未登录`),1)],2),t.signedIn?(d(),e(c,{key:0,link:``,size:`small`,loading:vn.value===t.id,onClick:e=>yn(t)},{default:_(()=>[...r[35]||=[o(`退出登录`,-1)]]),_:1},8,[`loading`,`onClick`])):t.needsLogin===!1?m(``,!0):(d(),e(c,{key:1,link:``,type:`primary`,size:`small`,loading:Jt.value===t.id,onClick:e=>_n(t.id)},{default:_(()=>[...r[36]||=[o(`登录`,-1)]]),_:1},8,[`loading`,`onClick`]))])]))),128))])):(d(),i(`div`,lt,`未声明可用的供应商`))]))),128))])):m(``,!0)]),_:1},8,[`modelValue`]),t(C,{modelValue:Yt.value,"onUpdate:modelValue":r[11]||=e=>Yt.value=e,title:`选择登录方式`,width:`460px`},{footer:_(()=>[t(c,{onClick:r[10]||=e=>Yt.value=!1},{default:_(()=>[...r[40]||=[o(`取消`,-1)]]),_:1})]),default:_(()=>[r[41]||=h(`div`,{class:`muted-sm`},`该插件提供多种登录方式,选一种:`,-1),h(`div`,ht,[(d(!0),i(y,null,v(Zt.value,t=>(d(),e(c,{key:t.label,class:`method-btn`,onClick:e=>bn(t.label)},{default:_(()=>[o(f(t.label||t.type),1)]),_:2},1032,[`onClick`]))),128))])]),_:1},8,[`modelValue`]),t(C,{modelValue:Z.value,"onUpdate:modelValue":r[13]||=e=>Z.value=e,title:`登录 ${sn.value}`,width:`480px`},{footer:_(()=>[t(c,{onClick:r[12]||=e=>Z.value=!1},{default:_(()=>[...r[42]||=[o(`取消`,-1)]]),_:1}),t(c,{type:`primary`,loading:dn.value,onClick:xn},{default:_(()=>[...r[43]||=[o(`确定`,-1)]]),_:1},8,[`loading`])]),default:_(()=>[(d(!0),i(y,null,v(cn.value,t=>(d(),i(`div`,{key:t.key,class:`field-row`},[h(`div`,gt,f(t.message||t.key),1),t.type===`select`?(d(),e(pe,{key:0,modelValue:Q.value[t.key],"onUpdate:modelValue":e=>Q.value[t.key]=e,class:`mt-8`,placeholder:`请选择`,style:{width:`100%`}},{default:_(()=>[(d(!0),i(y,null,v(t.options,t=>(d(),e(fe,{key:t.value,label:t.label??t.value,value:t.value??``},{default:_(()=>[h(`span`,null,f(t.label??t.value),1),t.hint?(d(),i(`span`,_t,`(`+f(t.hint)+`)`,1)):m(``,!0)]),_:2},1032,[`label`,`value`]))),128))]),_:2},1032,[`modelValue`,`onUpdate:modelValue`])):(d(),e(x,{key:1,modelValue:Q.value[t.key],"onUpdate:modelValue":e=>Q.value[t.key]=e,class:`mt-8`,placeholder:t.placeholder||``,onKeyup:re(xn,[`enter`])},null,8,[`modelValue`,`onUpdate:modelValue`,`placeholder`]))]))),128)),un.value?(d(),e(u,{key:0,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:un.value},null,8,[`title`])):m(``,!0)]),_:1},8,[`modelValue`,`title`]),t(C,{modelValue:J.value,"onUpdate:modelValue":r[16]||=e=>J.value=e,title:`登录 ${en.value}`,width:`480px`},{footer:_(()=>[t(c,{onClick:r[15]||=e=>J.value=!1},{default:_(()=>[...r[44]||=[o(`取消`,-1)]]),_:1}),t(c,{type:`primary`,loading:on.value,onClick:Sn},{default:_(()=>[...r[45]||=[o(`确定`,-1)]]),_:1},8,[`loading`])]),default:_(()=>[h(`div`,vt,f(tn.value||`该登录方式需要一枚密钥`),1),t(x,{modelValue:Y.value,"onUpdate:modelValue":r[14]||=e=>Y.value=e,class:`mt-8`,placeholder:nn.value||`粘贴密钥`,"show-password":``,onKeyup:re(Sn,[`enter`])},null,8,[`modelValue`,`placeholder`]),X.value?(d(),e(u,{key:0,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:X.value},null,8,[`title`])):m(``,!0)]),_:1},8,[`modelValue`,`title`]),t(C,{modelValue:G.value,"onUpdate:modelValue":r[18]||=e=>G.value=e,title:`登录 ${K.value}`,width:`480px`,onClose:r[19]||=e=>pn(K.value)},{footer:_(()=>[t(c,{onClick:r[17]||=e=>G.value=!1},{default:_(()=>[...r[47]||=[o(`关闭`,-1)]]),_:1})]),default:_(()=>[h(`div`,yt,f($t.value||`正在读取本机已登录的凭据…`),1),Qt.value?(d(),i(`div`,bt,[h(`a`,{class:`el-button el-button--primary`,href:Qt.value,target:`_blank`,rel:`noopener`},` 打开登录页 `,8,xt),r[46]||=h(`div`,{class:`muted-sm mt-8`},`在打开的页面完成登录即可,本页会自动检测(最长等待几分钟)。`,-1)])):m(``,!0),q.value?(d(),e(u,{key:1,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:q.value},null,8,[`title`])):(d(),i(`div`,St,`等待登录完成…`))]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-60925e93`]]);export{wt as default};