ezllm 0.0.47 → 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.
Files changed (33) hide show
  1. package/dist/cli.js +24 -24
  2. package/dist/daemon.js +15 -14
  3. package/dist/plugin-host.js +3 -3
  4. package/dist/server.js +64 -63
  5. package/dist/web-ui/assets/{DashboardView-CqupMCmm.js → DashboardView--YRv0pdB.js} +1 -1
  6. package/dist/web-ui/assets/{LayoutView-CyOrx1rA.js → LayoutView-3OpEgcEH.js} +1 -1
  7. package/dist/web-ui/assets/{LoginView-YolyK2Q0.js → LoginView-DyiYIltJ.js} +1 -1
  8. package/dist/web-ui/assets/{LogsView-E64a6PIt.js → LogsView-BlO9eUXV.js} +2 -2
  9. package/dist/web-ui/assets/{ManagedServicesView-mk_mSWzE.js → ManagedServicesView-DalOm5fB.js} +1 -1
  10. package/dist/web-ui/assets/PluginsView-Bnwsd3-R.css +1 -0
  11. package/dist/web-ui/assets/PluginsView-CMjFrpCT.js +2 -0
  12. package/dist/web-ui/assets/{ProvidersView-BwX8Y3kP.css → ProvidersView-DZs-NofB.css} +1 -1
  13. package/dist/web-ui/assets/ProvidersView-PlwErhJU.js +14 -0
  14. package/dist/web-ui/assets/{SettingsView-p3uvWhGh.js → SettingsView-Dl-dHm8U.js} +1 -1
  15. package/dist/web-ui/assets/{SetupView-CGQibXHs.js → SetupView-BblW5D0m.js} +1 -1
  16. package/dist/web-ui/assets/{config-Dzo6AFZx.js → config-DRb_7Qvh.js} +1 -1
  17. package/dist/web-ui/assets/index-BviWrBv1.js +49 -0
  18. package/dist/web-ui/assets/{message-C8pR37GK.js → message-BgUNwRuF.js} +2 -2
  19. package/dist/web-ui/assets/pluginProviders-CMNUPYaO.js +1 -0
  20. package/dist/web-ui/assets/{providers-Dbg0NkwB.js → providers-fXKPM_nK.js} +1 -1
  21. package/dist/web-ui/assets/{router-JpU_7F6L.js → router-Cpy-sU_q.js} +2 -2
  22. package/dist/web-ui/assets/{useCopyToast-GaJ4QVNE.js → useCopyToast-DreqvPDI.js} +1 -1
  23. package/dist/web-ui/assets/{useManagerApi-DEPhOKWy.js → useManagerApi-DBsdJZgc.js} +1 -1
  24. package/dist/web-ui/assets/{useQuickRangeFilter-DeKORPZt.js → useQuickRangeFilter-D2Epk9Kj.js} +1 -1
  25. package/dist/web-ui/assets/useToast-BpZaUS2s.js +1 -0
  26. package/dist/web-ui/index.html +3 -3
  27. package/package.json +1 -1
  28. package/dist/web-ui/assets/PluginsView-DTJeufic.js +0 -2
  29. package/dist/web-ui/assets/PluginsView-DzHAW2gO.css +0 -1
  30. package/dist/web-ui/assets/ProvidersView-BrirhwQN.js +0 -14
  31. package/dist/web-ui/assets/index-wQG3qUgW.js +0 -49
  32. package/dist/web-ui/assets/pluginProviders-DeHPKGnd.js +0 -1
  33. package/dist/web-ui/assets/useToast-DVCDN-da.js +0 -1
@@ -1,2 +0,0 @@
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,S as ee,T as d,Y as te,at as f,cn as ne,d as re,h as ie,ht as p,j as m,k as h,pn as g,rt as _,tt as v,yt as y}from"./router-JpU_7F6L.js";import{G as ae,U as oe}from"./message-C8pR37GK.js";import{t as se}from"./index-wQG3qUgW.js";import{t as b}from"./useManagerApi-DEPhOKWy.js";import{n as x,t as ce}from"./providers-Dbg0NkwB.js";import{t as le}from"./useToast-DVCDN-da.js";import{a as S,c as ue,d as C,f as w,i as de,l as T,n as fe,o as pe,p as E,s as me,u as he}from"./pluginProviders-DeHPKGnd.js";y();var D=`https://raw.githubusercontent.com/magpie-community/plugins/main/registry.json`,O=[`https://gh-proxy.com/${D}`,`https://ghfast.top/${D}`,D],ge=1e4,_e=`plugin_market_cache`,ve=2,ye=216e5,be=36e5,k=[`provider`];function A(){try{let e=localStorage.getItem(_e);if(e===null)return null;let t=JSON.parse(e);if(t.version!==ve||!Array.isArray(t.entries))return null;let n=t.fetchedAt;return n===void 0||typeof n.at!=`number`?null:{version:ve,entries:t.entries.filter(P),fetchedAt:n}}catch{return null}}function j(e,t){try{let n={version:ve,entries:e,fetchedAt:t};localStorage.setItem(_e,JSON.stringify(n))}catch{}}function M(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 M(t.zh)??M(t.en)}function Se(e){switch(e){case`provider`:case`middleware`:case`agent`:case`tools`:case`page`:return e;default:return`provider`}}function N(e){return k.includes(e)}function P(e){if(typeof e!=`object`||!e)return!1;let t=e.kind;return typeof t==`string`&&N(t)}function F(e){let t=M(e.package);if(t===null)return null;let n=Array.isArray(e.providers)?e.providers.filter(e=>typeof e==`string`):[];return{package:t,name:M(e.name)??t,icon:M(e.icon),providers:n,community:M(e.community),summary:xe(e.summary),kind:Se(e.kind),replaces:M(e.replaces),version:null,license:null,description:null,homepage:null,weeklyDownloads:null,published:null}}var I=new Map,Ce=new Map;async function L(e){let t=I.get(e);if(t!==void 0&&Date.now()-t.at<be)return t.meta;try{let t=await C(`https://registry.npmjs.org/${encodeURIComponent(e)}`),n={version:M(t[`dist-tags`]?.latest),license:M(t.license),description:M(t.description),homepage:M(t.homepage),published:!0};return I.set(e,{at:Date.now(),meta:n}),n}catch(t){let n={version:null,license:null,description:null,homepage:null,published:E(t)!==404&&null};return n.published===!1&&I.set(e,{at:Date.now(),meta:n}),n}}async function R(e){let t=Ce.get(e);if(t!==void 0&&Date.now()-t.at<be)return t.downloads;try{let t=await C(`https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(e)}`),n=typeof t.downloads==`number`?t.downloads:null;return Ce.set(e,{at:Date.now(),downloads:n}),n}catch{return null}}async function we(){let e=[];for(let t of O)try{let e=await C(t,{timeoutMs:ge});return t!==O[0]&&x(`[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(O.length)} 个源):\n${e.join(`
2
- `)}`)}async function z(e){let{registry:t,source:n}=await we(),r=t.plugins;if(!Array.isArray(r))throw Error(`清单格式不是预期形状(缺 plugins 数组):${D}`);let i=r.map(e=>typeof e==`object`&&e?F(e):null).filter(P).sort((e,t)=>e.package.localeCompare(t.package)),a=0;return await Promise.all(i.map(async t=>{let[n,r]=await Promise.all([L(t.package),R(t.package)]);Object.assign(t,n,{weeklyDownloads:r}),a+=1,e?.(a,i.length)})),{entries:i,source:n}}var B=t([]),V=t(!1),H=t(null),Te=t({loaded:0,total:0}),Ee=t(null),De=t(!1),U=null;function W(e,t){JSON.stringify(e)!==JSON.stringify(B.value)&&(B.value=e),Ee.value=t,j(e,t)}async function Oe(e={}){let t=e.force===!0,n=B.value.length===0?A():null;n!==null&&(B.value=n.entries,Ee.value=n.fetchedAt);let r=B.value.length>0,i=Ee.value,a=i!==null&&Date.now()-i.at<ye;if(!(!t&&r&&a)){if(U!==null){if(t)await U;else return}if(t||!r){V.value=!0,De.value=!1,Te.value={loaded:0,total:0};try{let e=await z((e,t)=>{Te.value={loaded:e,total:t}});W(e.entries,{source:e.source,at:Date.now()}),H.value=null}catch(e){H.value=`插件市场清单加载失败:${e instanceof Error?e.message:String(e)}`}finally{V.value=!1}return}De.value=!0,U=(async()=>{try{let e=await z();W(e.entries,{source:e.source,at:Date.now()}),H.value=null,De.value=!1}catch(e){x(`[plugin-market] 后台刷新失败,继续用缓存:${e instanceof Error?e.message:String(e)}`)}finally{U=null}})()}}function ke(){return{entries:B,loading:V,marketError:H,progress:Te,fetchedAt:Ee,stale:De,loadMarket:Oe}}async function Ae(e){let t=e.timeoutMs??2e4,n=e.intervalMs??400,r=e.now??Date.now,i=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),a=r()+t;for(;;)try{return await e.probe(),!0}catch{if(r()>=a)return!1;await i(n)}}a(),y(),i(),ie();var je={class:`page-head`},Me={class:`page-head-actions`},Ne={key:0,class:`tab-count`},Pe={key:1,class:`loading-block`},Fe={key:3},Ie={class:`tab-toolbar`},Le={class:`installed-summary`},Re={class:`installed-summary-ok`},ze={class:`tab-actions`},Be={class:`installed-list`},Ve={class:`installed-head`},He={class:`installed-avatar`},Ue={class:`installed-identity`},We={class:`installed-title`},Ge=[`title`],Ke={class:`installed-version`},qe=[`title`],Je=[`title`],Ye={class:`installed-ops`},Xe={key:0,class:`installed-noprovider`},Ze={key:1,class:`installed-providers`},Qe={class:`installed-provider-info`},$e=[`title`],et={class:`installed-provider-models`},tt={class:`installed-provider-actions`},nt={key:0,class:`tab-count`},rt={class:`tab-toolbar`},it={class:`muted-sm`},at={key:0,class:`loading-block`},ot={key:2,class:`plugin-grid`},st={class:`card-top`},ct={class:`plugin-icon`},lt=[`src`,`alt`,`onError`],ut={key:1},dt={class:`plugin-titles`},ft=[`title`],pt={class:`plugin-tags`},mt={class:`plugin-action`},ht=[`title`],gt={class:`plugin-meta`},_t={key:0},vt={key:1,class:`mono`},yt={key:2,class:`muted-disabled`},bt={key:3,class:`muted-disabled`},xt={class:`method-list`},St={class:`muted-sm`},Ct={key:0,class:`muted-sm`},wt={class:`muted-sm`},Tt={class:`muted-sm`},Et={key:0,class:`mt-8`},Dt=[`href`],Ot={key:2,class:`muted-sm mt-8`},kt=5e3,At=5e3,jt=re(s({__name:`PluginsView`,setup(i){let{toast:a}=le(),s=ce(),re=t(!0),ie=t(`服务未由 ezllm 主进程托管(源码运行模式);请用 ezllm 启动服务`),y=t(!1),x=t(null),{entries:E,loading:D,marketError:O,progress:ge,fetchedAt:_e,stale:ve,loadMarket:ye}=ke(),be=t(new Set),k=t([]),A=t(null),j=t(!1),M=h(()=>{let e=k.value.flatMap(e=>e.providers);return{total:e.length,signedIn:e.filter(e=>e.signedIn).length}}),xe=e=>E.value.find(t=>t.package===e)?.name??e.replace(/^@[^/]+\//,``),Se=e=>{let t=xe(e).trim();return t===``?`?`:t.charAt(0).toUpperCase()},N=t(null),P=t(!1),F=t(``),I=t(`installed`),Ce=t(!1),L=t({}),R=t(!1),we=t(!0),z=h(()=>y.value&&x.value!==null),B=e=>k.value.some(t=>t.package===e.package),V=h(()=>E.value.filter(e=>!B(e))),H=e=>e.icon===null||be.value.has(e.package)?null:/^https?:\/\//i.test(e.icon)?e.icon:null,Te=e=>e.icon!==null&&!/^https?:\/\//i.test(e.icon)?e.icon:(e.name.charAt(0)||`?`).toUpperCase(),Ee=e=>{be.value=new Set(be.value).add(e.package)},De=e=>e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e),U=async()=>{try{let e=await b.plugins();re.value=!0,y.value=e.running,x.value=e.port}catch(e){if(typeof e?.message==`string`&&e.message.includes(`未由 ezllm 主进程托管`)){re.value=!1,ie.value=e.message,y.value=!1,x.value=null;return}throw e}},W=async()=>{if(!z.value){k.value=[],A.value=null,j.value=!1;return}let e=x.value;if(e!==null){j.value=!0;try{let t=await C(T(e,`/packages`));k.value=Array.isArray(t.packages)?t.packages:[],A.value=null}catch(e){k.value=[],A.value=`无法读取已装插件(插件服务可能正在重启):${e?.message??`请求失败`}`}finally{j.value=!1}}},Oe=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()},jt=h(()=>{if(D.value)return`正在加载 ${String(ge.value.loaded)}/${String(ge.value.total)}…`;let e=_e.value===null?``:Oe(_e.value.at),t=e===``?``:` · ${e}更新`,n=ve.value?` · 更新中…`:``;return`清单 ${String(E.value.length)} 个 · 已装 ${String(k.value.length)} 个${t}${n}`}),Mt=async(e=!1)=>{await ye({force:e})},Nt=async()=>{try{await U()}catch{}await Promise.all([W(),Mt(!0)])},Pt=async()=>{try{await U()}catch(e){O.value=e?.message??`插件服务状态加载失败`;return}await W(),await Mt(),G()},Ft=t(!1),It=async e=>{let t=await C(T(e,`/plugins`));return Array.isArray(t.providers)?t.providers:[]},Lt=async(e,t)=>{try{let n=await C(`${pe(t,e)}/v1/models`,{timeoutMs:kt}),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}},Rt=async()=>{let e=x.value;if(z.value&&e!==null){Ft.value=!0;try{await s.loadProviders();let t=await It(e),n=S(s.suppliers,t,e),r=t.filter(e=>e.protocol!==null&&n.providers.filter(t=>me(t.apiBase)===e.id).some(t=>fe(t,e))),i=new Map;await Promise.all(r.map(async t=>{let n=await Lt(t.id,e);n!==null&&i.set(t.id,n)}));let o=de(n.providers,t,i);if(n.added.length===0&&n.updated.length===0&&o.refreshed.length===0)return;await s.mutateProviders(n=>{let r=S(n,t,e);return de(r.providers,t,i).providers});let c=[];n.added.length>0&&c.push(`新增 ${String(n.added.length)} 个供应商`),n.updated.length>0&&c.push(`修正 ${String(n.updated.length)} 个供应商`),o.refreshed.length>0&&c.push(`刷新 ${String(o.refreshed.length)} 个供应商的模型清单`),a(`已接入网关:${c.join(`、`)}`,`success`)}catch(e){a(e?.message??`供应商配置同步失败`,`error`)}finally{Ft.value=!1}}},zt=null,G=()=>(zt===null&&(zt=Rt().finally(()=>{zt=null})),zt),Bt=e=>Ae({probe:()=>C(T(e,`/health`),{timeoutMs:2e3})}),Vt=async()=>{try{let e=await b.plugins();return{pid:e.pid,startedAt:e.startedAt}}catch{return null}},Ht=(e,t)=>!(e.pid!==null&&t.pid!==null&&e.pid!==t.pid||e.startedAt!==null&&t.startedAt!==null&&e.startedAt!==t.startedAt),Ut=(e,t,n)=>Ae({timeoutMs:n,probe:async()=>{let n=await b.plugins();if(!n.running||n.port!==e||Ht(t,{pid:n.pid,startedAt:n.startedAt}))throw Error(`宿主尚未完成重启`)}}),Wt=async(e,t)=>(t!==null&&await Ut(e,t,At),await Bt(e)),Gt=async(e,t)=>await Wt(e,t)?(await W(),!0):(A.value=`插件服务未确认完成重启,请稍后点「刷新」或重新打开本页`,!1),Kt=async(e,t)=>{try{let n=e;try{let e=await b.plugins();if(t!==null&&e.running&&!Ht(t,{pid:e.pid,startedAt:e.startedAt}))y.value=e.running,x.value=e.port,n=e.port;else{let e=await b.restartPlugins();y.value=e.running,x.value=e.port,n=e.port}}catch{let e=await b.restartPlugins();y.value=e.running,x.value=e.port,n=e.port}return await Gt(n,t)}catch(e){return A.value=`插件服务重启失败:${e?.message??`请求失败`}`,!1}},qt=async e=>{await Yt(e.package)},Jt=async()=>{let e=F.value.trim();if(e!==``){Ce.value=!0;try{await Yt(e),P.value=!1,F.value=``}finally{Ce.value=!1}}},Yt=async e=>{let t=x.value;if(t===null){a(`插件服务未开启`,`error`);return}N.value=e;try{let n=await Vt(),r=await w(T(t,`/packages`),{package:e}),i=r.restartRequested!==!0||await Kt(t,n);r.restartRequested!==!0&&await W(),r.loaded===!1?a(`${e} 已安装但未加载成功(重启插件服务或查看日志)`,`warning`):i?a(`已安装 ${e}`,`success`):a(`${e} 已安装,但未能确认插件服务已完成重启;稍后刷新即可`,`warning`),i&&await G()}catch(e){a(e?.message??`安装失败`,`error`)}finally{N.value=null}},Xt=async e=>{let t=x.value;if(t===null)return;let n=[];try{await s.loadProviders(),n=ue(s.suppliers,e.providers.map(e=>e.id))}catch{}let r=n.length===0?``:`网关里对应的供应商(${n.join(`、`)})也会一并移除。`;try{await se.confirm(`确定卸载 ${e.package}?该插件提供的模型将不可用。${r}`,`确认卸载`,{confirmButtonText:`卸载`,cancelButtonText:`取消`,type:`warning`})}catch{return}N.value=e.package;try{let r=await Vt(),i=await he(T(t,`/packages/${encodeURIComponent(e.package)}`));n.length>0&&await s.mutateProviders(e=>e.filter(e=>!n.includes(e.name))),a(`已卸载 ${e.package}`,`success`),i.restartRequested===!0?await Kt(t,r)||a(`插件服务未确认完成重启;稍后刷新即可`,`warning`):await W()}catch(e){a(e?.message??`卸载失败`,`error`)}finally{N.value=null}},Zt=(e,t)=>{e===`uninstall`&&Xt(t)},Qt=()=>{F.value=``,P.value=!0},$t=h(()=>z.value?we.value?`检查已装插件是否有新版本`:`宿主当前无法检查更新`:`插件服务未开启`),en=e=>{let t=L.value[e];return t&&t.updateAvailable&&t.latest?t.latest:null},tn=async(e=!1)=>{let t=x.value;if(t===null){e||a(`插件服务未开启`,`error`);return}R.value=!0;try{let n=await C(T(t,`/packages/updates`)),r=Array.isArray(n.packages)?n.packages:[];we.value=n.canCheck;let i={};for(let e of r)i[e.package]=e;if(L.value=i,e)return;if(!n.canCheck){a(`宿主当前无法检查更新`,`warning`);return}let o=r.filter(e=>e.updateAvailable).length;a(o>0?`发现 ${String(o)} 个插件有新版本`:`全部插件已是最新`,`success`)}catch(t){e||a(t?.message??`检查更新失败`,`error`)}finally{R.value=!1}},nn=async e=>{let t=x.value,n=L.value[e]?.latest;if(t===null){a(`插件服务未开启`,`error`);return}if(n!=null){N.value=e;try{let r=await Vt();if(await w(T(t,`/packages`),{package:e,version:n}),delete L.value[e],!await Kt(t,r)){a(`已更新到 ${n},但未能确认插件服务已完成重启;稍后刷新即可`,`warning`);return}a(`已更新到 ${n} 并重启插件服务`,`success`),await G(),await tn(!0)}catch(e){a(e?.message??`更新失败`,`error`)}finally{N.value=null}}},rn=t(null),an=t(!1),on=t(``),sn=t([]),K=t(!1),cn=t(``),q=t(``),ln=t(``),J=t(null),Y=t(!1),un=t(``),dn=t(``),fn=t(``),pn=t(``),mn=t(void 0),hn=t({}),X=t(null),gn=t(!1),Z=t(!1),_n=t(``),vn=t([]),Q=t({}),yn=t(void 0),bn=t(null),xn=t(!1),$=new Map,Sn=!1,Cn=e=>{$.set(e,($.get(e)??0)+1)};te(()=>{Sn=!0,$.clear()});let wn=(e,t)=>{q.value!==``&&q.value!==e&&Cn(q.value),q.value=e,cn.value=t.url??``,ln.value=t.instructions??``,J.value=null,K.value=!0},Tn=async e=>{let t=x.value;if(t===null)return;let n=($.get(e)??0)+1;$.set(e,n);let r=()=>!Sn&&$.get(e)===n,i=Date.now()+18e4;for(;;){if(await new Promise(e=>setTimeout(e,2e3)),!r())return;let n;try{n=await C(T(t,`/login/${encodeURIComponent(e)}`))}catch(t){r()&&q.value===e&&(J.value=t?.message??`查询登录状态失败`);return}if(!r())return;if(n.state===`success`){q.value===e&&(K.value=!1),a(`已登录${n.accountId?`(${n.accountId})`:``}`,`success`),await W(),await G();return}if(n.state===`failed`){q.value===e&&(J.value=n.error??`登录失败`);return}if(Date.now()>i){q.value===e&&(J.value=`等待超时,可关闭后重新点击「登录」`);return}}},En=async(e,t,n,r)=>{let i=x.value;if(i===null){a(`插件服务未开启`,`error`);return}Cn(e);let o={};t!==void 0&&(o.method=t),Object.keys(n).length>0&&(o.inputs=n),r!==void 0&&r!==``&&(o.key=r);let s=await w(T(i,`/login/${encodeURIComponent(e)}`),o);if(s.needMethod===!0){on.value=e,sn.value=s.methods,an.value=!0;return}if(s.needInputs!==void 0&&s.needInputs.length>0){Y.value=!1,_n.value=e,yn.value=t,vn.value=s.needInputs;let r={...s.inputs??n};for(let e of s.needInputs)r[e.key]=r[e.key]??``;Q.value=r,bn.value=null,Z.value=!0;return}if(s.needKey===!0){Z.value=!1,un.value=e,mn.value=t,dn.value=s.label??``,fn.value=s.placeholder??``,hn.value={...s.inputs??n},pn.value=``,X.value=null,Y.value=!0;return}if(s.state===`success`){Z.value=!1,Y.value=!1,a(`已登录${s.accountId?`(${s.accountId})`:``}`,`success`),await W(),await G();return}if(s.state===`failed`){let e=s.error??`登录失败`;if(Y.value){X.value=e;return}if(Z.value){bn.value=e;return}a(e,`error`);return}Z.value=!1,Y.value=!1,wn(e,s),Tn(e)},Dn=async(e,t)=>{rn.value=e;try{await En(e,t,{})}catch(e){a(e?.message??`发起登录失败`,`error`)}finally{rn.value=null}},On=t(null),kn=async e=>{let t=x.value;if(t===null){a(`插件服务未开启`,`error`);return}try{await se.confirm(`确定退出 ${e.id} 的登录?本机保存的凭据会被删除,该供应商的模型将立即不可用(插件与网关配置保留)。`,`确认退出登录`,{confirmButtonText:`退出登录`,cancelButtonText:`取消`,type:`warning`})}catch{return}Cn(e.id),q.value===e.id&&(K.value=!1),On.value=e.id;try{await he(T(t,`/login/${encodeURIComponent(e.id)}`)),a(`已退出 ${e.id} 的登录`,`success`),await W()}catch(e){let t=String(e?.message??``);a(t.includes(`405`)?`当前插件服务版本不支持退出登录,请先升级 ezllm`:e?.message??`退出登录失败`,`error`)}finally{On.value=null}},An=async e=>{an.value=!1,await Dn(on.value,e)},jn=async()=>{xn.value=!0;try{await En(_n.value,yn.value,{...Q.value})}catch(e){bn.value=e?.message??`提交失败`}finally{xn.value=!1}},Mn=async()=>{if(pn.value.trim()===``){X.value=`请填写密钥`;return}gn.value=!0,X.value=null;try{await En(un.value,mn.value,{...hn.value},pn.value)}catch(e){X.value=e?.message??`提交失败`}finally{gn.value=!1}};return u(Pt),(t,i)=>{let a=f(`el-icon`),s=f(`el-button`),u=f(`el-alert`),te=f(`el-empty`),h=f(`el-tag`),se=f(`el-dropdown-item`),b=f(`el-dropdown-menu`),x=f(`el-dropdown`),ce=f(`el-tab-pane`),le=f(`el-tabs`),S=f(`el-input`),ue=f(`el-form-item`),C=f(`el-form`),w=f(`el-dialog`),de=f(`el-option`),T=f(`el-select`);return v(),l(`div`,null,[e(`div`,je,[i[20]||=e(`div`,null,[e(`div`,{class:`page-head-title`},`插件`),e(`div`,{class:`page-head-sub`},` 订阅社区 OpenCode 插件——把订阅账号(CodeBuddy、智谱 Coding Plan 等)当作供应商接入网关 `)],-1),e(`div`,Me,[o(s,{disabled:!y.value,onClick:Qt},{default:p(()=>[o(a,null,{default:p(()=>[o(r(ae))]),_:1}),i[18]||=n(` 手动安装 `,-1)]),_:1},8,[`disabled`]),o(s,{loading:r(D),onClick:Nt},{default:p(()=>[...i[19]||=[n(`刷新`,-1)]]),_:1},8,[`loading`])])]),re.value?y.value?c(``,!0):(v(),m(u,{key:1,type:`info`,"show-icon":``,closable:!1,class:`mb-16`,title:`插件服务未运行`},{default:p(()=>[...i[21]||=[e(`div`,{class:`muted-sm`},` 插件服务与设置页「显示插件入口」共用同一配置:开关开启时随服务启动自动拉起。如仍不可用,请查看日志或重启服务。 `,-1)]]),_:1})):(v(),m(u,{key:0,type:`warning`,"show-icon":``,closable:!1,class:`mb-16`,title:`插件服务不可用`},{default:p(()=>[n(g(ie.value),1)]),_:1})),r(O)?(v(),m(u,{key:2,type:`error`,"show-icon":``,closable:!1,class:`mb-16`,title:r(O)},{default:p(()=>[o(s,{size:`small`,onClick:Mt},{default:p(()=>[...i[22]||=[n(`重试`,-1)]]),_:1})]),_:1},8,[`title`])):c(``,!0),o(le,{modelValue:I.value,"onUpdate:modelValue":i[4]||=e=>I.value=e,class:`plugin-tabs`},{default:p(()=>[o(ce,{name:`installed`},{label:p(()=>[i[23]||=n(` 已安装 `,-1),k.value.length>0?(v(),l(`span`,Ne,g(k.value.length),1)):c(``,!0)]),default:p(()=>[A.value?(v(),m(u,{key:0,type:`warning`,"show-icon":``,closable:!1,class:`installed-error`,title:A.value},null,8,[`title`])):c(``,!0),j.value&&k.value.length===0?(v(),l(`div`,Pe,`正在读取已装插件…`)):k.value.length===0&&!A.value?(v(),m(te,{key:2,description:`尚未安装任何插件`,"image-size":80},{default:p(()=>[o(s,{type:`primary`,onClick:i[0]||=e=>I.value=`market`},{default:p(()=>[n(g(z.value?`去安装插件`:`查看插件清单`),1)]),_:1})]),_:1})):c(``,!0),k.value.length>0?(v(),l(`div`,Fe,[e(`div`,Ie,[e(`span`,Le,[n(g(k.value.length)+` 个插件 · `+g(M.value.total)+` 个供应商 · `,1),e(`span`,Re,g(M.value.signedIn)+` 个已登录`,1)]),e(`div`,ze,[o(s,{size:`small`,disabled:!z.value||Ft.value,loading:Ft.value,title:`把宿主已加载的插件供应商补进网关配置:缺的整条新增,已在的只修地址/协议(模型清单保持你的选择)`,onClick:G},{default:p(()=>[...i[24]||=[n(`接入网关`,-1)]]),_:1},8,[`disabled`,`loading`]),o(s,{size:`small`,disabled:!z.value||!we.value||N.value!==null,loading:R.value,title:$t.value,onClick:i[1]||=e=>tn()},{default:p(()=>[...i[25]||=[n(`检查更新`,-1)]]),_:1},8,[`disabled`,`loading`,`title`])])]),e(`div`,Be,[(v(!0),l(d,null,_(k.value,t=>(v(),l(`div`,{key:t.package,class:`installed-card`},[e(`div`,Ve,[e(`div`,He,g(Se(t.package)),1),e(`div`,Ue,[e(`div`,We,[e(`span`,{class:`installed-name`,title:t.package},g(xe(t.package)),9,Ge),e(`span`,Ke,`v`+g(t.version||`-`),1),t.loaded?c(``,!0):(v(),m(h,{key:0,type:`danger`,size:`small`,"disable-transitions":``},{default:p(()=>[...i[26]||=[n(`加载失败`,-1)]]),_:1}))]),t.description?(v(),l(`div`,{key:0,class:`installed-desc`,title:t.description},g(t.description),9,qe)):c(``,!0),xe(t.package)===t.package?c(``,!0):(v(),l(`div`,{key:1,class:`mono installed-pkgname`,title:t.package},g(t.package),9,Je))]),e(`div`,Ye,[en(t.package)?(v(),m(s,{key:0,link:``,type:`primary`,size:`small`,disabled:N.value!==null||R.value,loading:N.value===t.package,onClick:e=>nn(t.package)},{default:p(()=>[n(`更新到 `+g(en(t.package)),1)]),_:2},1032,[`disabled`,`loading`,`onClick`])):c(``,!0),o(x,{trigger:`click`,placement:`bottom-end`,onCommand:e=>Zt(e,t)},{dropdown:p(()=>[o(b,null,{default:p(()=>[o(se,{command:`uninstall`,disabled:N.value!==null},{default:p(()=>[...i[27]||=[e(`span`,{class:`danger-text`},`卸载插件`,-1)]]),_:1},8,[`disabled`])]),_:1})]),default:p(()=>[o(s,{link:``,size:`small`,class:`card-more`,title:`更多操作`},{default:p(()=>[o(a,null,{default:p(()=>[o(r(oe))]),_:1})]),_:1})]),_:1},8,[`onCommand`])])]),t.providers.length?(v(),l(`div`,Ze,[(v(!0),l(d,null,_(t.providers,t=>(v(),l(`div`,{key:t.id,class:`installed-provider`},[e(`div`,Qe,[e(`span`,{class:`mono installed-provider-id`,title:t.id},g(t.id),9,$e),e(`span`,et,g(t.models)+` 个模型`,1)]),e(`div`,tt,[e(`span`,{class:ne([`installed-state`,{"is-on":t.signedIn}])},[e(`span`,{class:ne([`status-dot`,{running:t.signedIn}])},null,2),e(`span`,null,g(t.signedIn?`已登录`:t.needsLogin===!1?`无需登录`:`未登录`),1)],2),t.signedIn?(v(),m(s,{key:0,link:``,size:`small`,loading:On.value===t.id,onClick:e=>kn(t)},{default:p(()=>[...i[28]||=[n(`退出登录`,-1)]]),_:1},8,[`loading`,`onClick`])):t.needsLogin===!1?c(``,!0):(v(),m(s,{key:1,link:``,type:`primary`,size:`small`,loading:rn.value===t.id,onClick:e=>Dn(t.id)},{default:p(()=>[...i[29]||=[n(`登录`,-1)]]),_:1},8,[`loading`,`onClick`]))])]))),128))])):(v(),l(`div`,Xe,`未声明可用的供应商`))]))),128))])])):c(``,!0)]),_:1}),o(ce,{name:`market`,lazy:``},{label:p(()=>[i[30]||=n(` 未安装 `,-1),V.value.length>0?(v(),l(`span`,nt,g(V.value.length),1)):c(``,!0)]),default:p(()=>[e(`div`,rt,[e(`span`,it,g(jt.value),1)]),r(D)&&r(E).length===0?(v(),l(`div`,at,`正在从社区清单加载…`)):V.value.length===0?(v(),m(te,{key:1,description:r(E).length===0?`清单里没有本宿主支持的插件`:`社区清单里的插件都已安装`,"image-size":80},{default:p(()=>[r(E).length===0?(v(),m(s,{key:0,loading:r(D),onClick:i[2]||=e=>Mt(!0)},{default:p(()=>[...i[31]||=[n(`刷新清单`,-1)]]),_:1},8,[`loading`])):(v(),m(s,{key:1,onClick:i[3]||=e=>I.value=`installed`},{default:p(()=>[...i[32]||=[n(`查看已安装`,-1)]]),_:1}))]),_:1},8,[`description`])):(v(),l(`div`,ot,[(v(!0),l(d,null,_(V.value,t=>(v(),l(`div`,{key:t.package,class:`plugin-card`},[e(`div`,st,[e(`div`,ct,[H(t)?(v(),l(`img`,{key:0,src:H(t),alt:t.name,onError:e=>Ee(t)},null,40,lt)):(v(),l(`span`,ut,g(Te(t)),1))]),e(`div`,dt,[e(`div`,{class:`plugin-name`,title:t.name},g(t.name),9,ft),e(`div`,pt,[t.community?(v(),m(h,{key:0,size:`small`,type:`info`,"disable-transitions":``},{default:p(()=>[n(g(t.community),1)]),_:2},1024)):c(``,!0)])]),e(`div`,mt,[o(s,{type:`primary`,size:`small`,disabled:!z.value||N.value===t.package||t.published===!1,loading:N.value===t.package,title:t.published===!1?`该包在 npm 上不存在(可能是清单条目尚未发布)`:void 0,onClick:e=>qt(t)},{default:p(()=>[...i[33]||=[n(` 安装 `,-1)]]),_:1},8,[`disabled`,`loading`,`title`,`onClick`])])]),e(`div`,{class:`plugin-summary`,title:t.summary??``},g(t.summary??`(清单未提供简介)`),9,ht),e(`div`,gt,[e(`span`,null,`供应商 `+g(t.providers.length),1),t.weeklyDownloads===null?c(``,!0):(v(),l(`span`,_t,g(De(t.weeklyDownloads))+`/周`,1)),t.version?(v(),l(`span`,vt,`v`+g(t.version),1)):t.published===!1?(v(),l(`span`,yt,`npm 上不存在`)):(v(),l(`span`,bt,`版本未知`))])]))),128))]))]),_:1})]),_:1},8,[`modelValue`]),o(w,{modelValue:P.value,"onUpdate:modelValue":i[7]||=e=>P.value=e,title:`手动安装插件`,width:`520px`},{footer:p(()=>[o(s,{onClick:i[6]||=e=>P.value=!1},{default:p(()=>[...i[35]||=[n(`取消`,-1)]]),_:1}),o(s,{type:`primary`,loading:Ce.value,disabled:F.value.trim()===``,onClick:Jt},{default:p(()=>[...i[36]||=[n(` 安装 `,-1)]]),_:1},8,[`loading`,`disabled`])]),default:p(()=>[o(C,{"label-position":`top`},{default:p(()=>[o(ue,{label:`npm 包名`},{default:p(()=>[o(S,{modelValue:F.value,"onUpdate:modelValue":i[5]||=e=>F.value=e,placeholder:`例:@magpie-community/opencode-workbuddy-auth`,clearable:``},null,8,[`modelValue`]),i[34]||=e(`div`,{class:`muted-sm`},[n(`可带版本(`),e(`span`,{class:`mono`},`name@1.2.3`),n(`);清单加载不出来时用这个。`)],-1)]),_:1})]),_:1})]),_:1},8,[`modelValue`]),o(w,{modelValue:an.value,"onUpdate:modelValue":i[9]||=e=>an.value=e,title:`选择登录方式`,width:`460px`},{footer:p(()=>[o(s,{onClick:i[8]||=e=>an.value=!1},{default:p(()=>[...i[37]||=[n(`取消`,-1)]]),_:1})]),default:p(()=>[i[38]||=e(`div`,{class:`muted-sm`},`该插件提供多种登录方式,选一种:`,-1),e(`div`,xt,[(v(!0),l(d,null,_(sn.value,e=>(v(),m(s,{key:e.label,class:`method-btn`,onClick:t=>An(e.label)},{default:p(()=>[n(g(e.label||e.type),1)]),_:2},1032,[`onClick`]))),128))])]),_:1},8,[`modelValue`]),o(w,{modelValue:Z.value,"onUpdate:modelValue":i[11]||=e=>Z.value=e,title:`登录 ${_n.value}`,width:`480px`},{footer:p(()=>[o(s,{onClick:i[10]||=e=>Z.value=!1},{default:p(()=>[...i[39]||=[n(`取消`,-1)]]),_:1}),o(s,{type:`primary`,loading:xn.value,onClick:jn},{default:p(()=>[...i[40]||=[n(`确定`,-1)]]),_:1},8,[`loading`])]),default:p(()=>[(v(!0),l(d,null,_(vn.value,t=>(v(),l(`div`,{key:t.key,class:`field-row`},[e(`div`,St,g(t.message||t.key),1),t.type===`select`?(v(),m(T,{key:0,modelValue:Q.value[t.key],"onUpdate:modelValue":e=>Q.value[t.key]=e,class:`mt-8`,placeholder:`请选择`,style:{width:`100%`}},{default:p(()=>[(v(!0),l(d,null,_(t.options,t=>(v(),m(de,{key:t.value,label:t.label??t.value,value:t.value??``},{default:p(()=>[e(`span`,null,g(t.label??t.value),1),t.hint?(v(),l(`span`,Ct,`(`+g(t.hint)+`)`,1)):c(``,!0)]),_:2},1032,[`label`,`value`]))),128))]),_:2},1032,[`modelValue`,`onUpdate:modelValue`])):(v(),m(S,{key:1,modelValue:Q.value[t.key],"onUpdate:modelValue":e=>Q.value[t.key]=e,class:`mt-8`,placeholder:t.placeholder||``,onKeyup:ee(jn,[`enter`])},null,8,[`modelValue`,`onUpdate:modelValue`,`placeholder`]))]))),128)),bn.value?(v(),m(u,{key:0,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:bn.value},null,8,[`title`])):c(``,!0)]),_:1},8,[`modelValue`,`title`]),o(w,{modelValue:Y.value,"onUpdate:modelValue":i[14]||=e=>Y.value=e,title:`登录 ${un.value}`,width:`480px`},{footer:p(()=>[o(s,{onClick:i[13]||=e=>Y.value=!1},{default:p(()=>[...i[41]||=[n(`取消`,-1)]]),_:1}),o(s,{type:`primary`,loading:gn.value,onClick:Mn},{default:p(()=>[...i[42]||=[n(`确定`,-1)]]),_:1},8,[`loading`])]),default:p(()=>[e(`div`,wt,g(dn.value||`该登录方式需要一枚密钥`),1),o(S,{modelValue:pn.value,"onUpdate:modelValue":i[12]||=e=>pn.value=e,class:`mt-8`,placeholder:fn.value||`粘贴密钥`,"show-password":``,onKeyup:ee(Mn,[`enter`])},null,8,[`modelValue`,`placeholder`]),X.value?(v(),m(u,{key:0,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:X.value},null,8,[`title`])):c(``,!0)]),_:1},8,[`modelValue`,`title`]),o(w,{modelValue:K.value,"onUpdate:modelValue":i[16]||=e=>K.value=e,title:`登录 ${q.value}`,width:`480px`,onClose:i[17]||=e=>Cn(q.value)},{footer:p(()=>[o(s,{onClick:i[15]||=e=>K.value=!1},{default:p(()=>[...i[44]||=[n(`关闭`,-1)]]),_:1})]),default:p(()=>[e(`div`,Tt,g(ln.value||`正在读取本机已登录的凭据…`),1),cn.value?(v(),l(`div`,Et,[e(`a`,{class:`el-button el-button--primary`,href:cn.value,target:`_blank`,rel:`noopener`},` 打开登录页 `,8,Dt),i[43]||=e(`div`,{class:`muted-sm mt-8`},`在打开的页面完成登录即可,本页会自动检测(最长等待几分钟)。`,-1)])):c(``,!0),J.value?(v(),m(u,{key:1,type:`error`,"show-icon":``,closable:!1,class:`mt-8`,title:J.value},null,8,[`title`])):(v(),l(`div`,Ot,`等待登录完成…`))]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-ce128c72`]]);export{jt as default};
@@ -1 +0,0 @@
1
- .plugin-tabs[data-v-ce128c72] .el-tabs__header{margin-bottom:16px}.tab-count[data-v-ce128c72]{background:var(--el-fill-color);color:var(--el-text-color-secondary);vertical-align:1px;border-radius:999px;margin-left:4px;padding:0 6px;font-size:11px;line-height:16px;display:inline-block}.tab-toolbar[data-v-ce128c72]{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:8px 12px;margin-bottom:12px;display:flex}.tab-actions[data-v-ce128c72]{flex-shrink:0;align-items:center;gap:8px;display:flex}.plugin-grid[data-v-ce128c72]{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px;display:grid}.plugin-card[data-v-ce128c72]{border:1px solid var(--el-border-color-light);background:var(--el-bg-color);border-radius:10px;flex-direction:column;gap:10px;padding:16px;transition:border-color .15s,box-shadow .15s;display:flex;box-shadow:0 1px 2px #00000008}.plugin-card[data-v-ce128c72]:hover{border-color:var(--el-color-primary-light-5);box-shadow:0 2px 8px #0000000f}.card-top[data-v-ce128c72]{align-items:flex-start;gap:12px;display:flex}.plugin-icon[data-v-ce128c72]{background:var(--el-color-primary-light-9);width:36px;height:36px;color:var(--el-color-primary);border-radius:10px;flex-shrink:0;justify-content:center;align-items:center;font-size:15px;font-weight:600;display:flex;overflow:hidden}.plugin-icon img[data-v-ce128c72]{object-fit:contain;width:100%;height:100%}.plugin-titles[data-v-ce128c72]{flex:1;min-width:0}.plugin-name[data-v-ce128c72]{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:600;overflow:hidden}.plugin-tags[data-v-ce128c72]{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}.plugin-action[data-v-ce128c72]{flex-shrink:0}.plugin-summary[data-v-ce128c72]{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-ce128c72]{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-ce128c72]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}.installed-error[data-v-ce128c72]{margin-bottom:12px}.installed-list[data-v-ce128c72]{grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:16px;display:grid}.installed-summary[data-v-ce128c72]{color:var(--el-text-color-secondary);font-size:12px}.installed-summary-ok[data-v-ce128c72]{color:var(--el-color-success)}.installed-card[data-v-ce128c72]{border:1px solid var(--el-border-color-light);background:var(--el-bg-color);border-radius:10px;flex-direction:column;gap:10px;padding:16px;transition:border-color .15s,box-shadow .15s;display:flex;box-shadow:0 1px 2px #00000008}.installed-card[data-v-ce128c72]:hover{border-color:var(--el-color-primary-light-5);box-shadow:0 2px 8px #0000000f}.installed-head[data-v-ce128c72]{flex-wrap:wrap;align-items:flex-start;gap:8px 12px;display:flex}.installed-avatar[data-v-ce128c72]{background:var(--el-color-primary-light-9);width:36px;height:36px;color:var(--el-color-primary);border-radius:10px;flex-shrink:0;justify-content:center;align-items:center;font-size:15px;font-weight:600;display:flex}.installed-identity[data-v-ce128c72]{flex:140px;min-width:0}.installed-title[data-v-ce128c72]{align-items:center;gap:8px;min-width:0;display:flex}.installed-name[data-v-ce128c72]{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-ce128c72]{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-ce128c72]{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-ce128c72]{color:var(--el-text-color-placeholder);text-overflow:ellipsis;white-space:nowrap;margin-top:3px;font-size:11px;overflow:hidden}.installed-ops[data-v-ce128c72]{flex-shrink:0;align-items:center;gap:4px;margin-left:auto;display:flex}.installed-ops .el-button[data-v-ce128c72]{height:auto;padding:0}.installed-ops .card-more[data-v-ce128c72]{width:28px;height:28px;color:var(--el-text-color-secondary);border-radius:6px;padding:0}.installed-ops .card-more[data-v-ce128c72]:hover{color:var(--el-color-primary);background:var(--el-fill-color-darker)}.danger-text[data-v-ce128c72]{color:var(--el-color-danger)}.installed-noprovider[data-v-ce128c72]{border-top:1px solid var(--el-border-color-lighter);color:var(--el-text-color-secondary);padding-top:8px;font-size:12px}.installed-providers[data-v-ce128c72]{border-top:1px solid var(--el-border-color-lighter);padding-top:2px}.installed-provider[data-v-ce128c72]{justify-content:space-between;align-items:center;gap:12px;padding:8px 0;display:flex}.installed-provider[data-v-ce128c72]:not(:last-child){border-bottom:1px solid var(--el-border-color-lighter)}.installed-provider-info[data-v-ce128c72]{align-items:baseline;gap:8px;min-width:0;display:flex}.installed-provider-id[data-v-ce128c72]{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-ce128c72]{color:var(--el-text-color-secondary);flex-shrink:0;font-size:12px}.installed-provider-actions[data-v-ce128c72]{flex-shrink:0;align-items:center;gap:8px;display:flex}.installed-provider-actions .el-button[data-v-ce128c72]{height:auto;padding:0}.installed-state[data-v-ce128c72]{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-ce128c72]{background:var(--el-text-color-placeholder);margin-right:0}.installed-state.is-on[data-v-ce128c72]{color:var(--el-color-success)}.installed-state.is-on .status-dot[data-v-ce128c72]{background:var(--el-color-success)}.method-list[data-v-ce128c72]{flex-direction:column;gap:8px;margin-top:12px;display:flex}.method-btn[data-v-ce128c72]{justify-content:flex-start;margin-left:0}.field-row[data-v-ce128c72]:not(:first-child){margin-top:12px}