UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

502 lines 59.7 kB
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{R as t,Vn as n,dn as r,un as i,wr as a,z as o}from"./control-ui-foundation-Cydpkyqa.js";import{$r as s,Bn as c,Do as l,Eo as u,Gr as ee,Jr as d,Kr as te,Oo as f,Qr as ne,Sc as re,Xr as ie,Yr as p,bc as ae,bs as oe,ei as se,qr as ce,ti as le,xs as ue,zn as de}from"./control-ui-core-Rwzhj6nO.js";import{$ as fe,K as m,X as h,at as g,c as pe,h as _,m as me,q as v,st as he,u as ge}from"./lit-runtime-CV_MH99K.js";import{B as _e,V as ve,Yn as ye,Zt as be,_ as xe,cn as Se,g as Ce,nn as we,nr as Te,sn as Ee,tr as De}from"./control-ui-core-YphAl4aM.js";import{Ft as Oe,Gt as ke,Ht as Ae,Rt as je,Wt as y,Yt as b,an as Me,en as x,in as Ne}from"./control-ui-core-vvcQQV2m.js";import{B as S,U as C,V as w,z as Pe}from"./control-ui-boot-shared-BYq7Cchl.js";import{Cr as Fe,Sr as Ie,_t as Le,ft as Re,gt as ze,ht as Be,mt as Ve,pt as He,vt as Ue,xr as We,yt as Ge}from"./control-ui-boot-shared-DfZ39Yj9.js";import{H as Ke,K as qe,L as Je,Q as T,V as Ye,W as Xe,X as E,Z as Ze,in as Qe,nt as $e,rn as et,rt as tt}from"./control-ui-boot-chat-_QSl8fbH.js";import{Is as nt,Ls as rt}from"./control-ui-boot-shared-CXVvK2AW.js";import{a as D,c as it,i as O,n as at,o as ot,r as st,s as ct,t as lt}from"./presentation-B7nRIH3E.js";import{f as ut,p as dt}from"./control-ui-boot-chat-D85X0PFX.js";import{n as ft,t as pt}from"./settings-workspace-Bseic8Tf.js";import{n as mt,t as ht}from"./plugins-hub-header-TMK2CKRh.js";var k;function A(){return(A=e((()=>{k=[`channels`,`providers`,`tools`,`contracts`,`hooks`,`mcpServers`,`cliCommands`,`cliBackends`,`skills`,`dangerousConfigFlags`]})))()}function gt(e,t){return Object.keys(e).every(e=>t.includes(e))}function _t(e){let t=n(e);if(!t||!gt(t,k))return;let r={};for(let e of k){let n=t[e];if(n!==void 0){if(!Array.isArray(n)||!n.every(i))return;r[e]=n}}return r}function vt(e){let t=n(e);if(!t||t.capabilityConsentCode!==`PLUGIN_CAPABILITY_CONSENT_REQUIRED`||!gt(t,[`capabilityConsentCode`,`pluginId`,`reviewToken`,`widened`,`acceptedAt`])||!i(t.pluginId)||!i(t.reviewToken)||t.acceptedAt!==void 0&&!i(t.acceptedAt))return;let r=t.widened===void 0?void 0:_t(t.widened);if(!(t.widened!==void 0&&!r))return{capabilityConsentCode:yt,pluginId:t.pluginId,reviewToken:t.reviewToken,...r?{widened:r}:{},...t.acceptedAt===void 0?{}:{acceptedAt:t.acceptedAt}}}var yt;function bt(){return(bt=e((()=>{A(),yt=`PLUGIN_CAPABILITY_CONSENT_REQUIRED`})))()}function xt(e){let t=n(e);if(!t)return;let i=r(t.ruleId),a=r(t.message),o=t.severity;if(!i||!a||o!==`info`&&o!==`warn`&&o!==`critical`)return;let s=r(t.file),c=r(t.evidence),l=t.line;if(!(t.file!==void 0&&!s||t.evidence!==void 0&&!c||l!==void 0&&(typeof l!=`number`||!Number.isSafeInteger(l)||l<=0)))return{ruleId:i,severity:o,message:a,...s?{file:s}:{},...l===void 0?{}:{line:l},...c?{evidence:c}:{}}}function St(e){let t=n(e);if(!t)return;let i=r(t.targetName),a=r(t.reason),o=t.targetType,s=t.requestMode;if(t.installPolicyCode!==`install_policy_warning_acknowledgement_required`||!i||!a||o!==`skill`&&o!==`plugin`||s!==`install`&&s!==`update`)return;let c;if(t.findings!==void 0){if(!Array.isArray(t.findings))return;c=[];for(let e of t.findings){let t=xt(e);if(!t)return;c.push(t)}}return{installPolicyCode:Ct,targetName:i,targetType:o,requestMode:s,reason:a,...c?{findings:c}:{}}}var Ct;function wt(){return(wt=e((()=>{Ct=`install_policy_warning_acknowledgement_required`})))()}function Tt(e,t){return e.request(`plugins.inspect`,{pluginId:t})}function Et(e){if(e instanceof Ee)return vt(e.details)}function j(){return(j=e((()=>{bt(),Se()})))()}function Dt(e){let t=e.source===`official`?e.pluginId:e.packageName;return Qe({title:x(`pluginsPage.installConfirmTitle`,{name:t}),message:x(`pluginsPage.installConfirmMessage`),confirmLabel:x(`pluginsPage.install`)})}function Ot(e){return Qe({title:x(`pluginsPage.removeConfirmTitle`,{name:e}),message:x(`pluginsPage.removeConfirmMessage`),confirmLabel:x(`pluginsPage.remove`),danger:!0})}function kt(){return(kt=e((()=>{et(),b()})))()}function At(e){if(e instanceof Ee)return St(e.details)}function jt(){return(jt=e((()=>{wt(),Se()})))()}function Mt(e,t){return e?h`<openclaw-tooltip open-on-click .content=${e}>${t}</openclaw-tooltip>`:t}function M(){return(M=e((()=>{m(),Ae()})))()}var N,Nt;function Pt(){return(Pt=e((()=>{Me(),N={pluginConsent:{widenedTitle:`What changed`,widenedDescription:`New since your last acceptance.`,previouslyAccepted:`Previously accepted {date}.`,declaredTitle:`Declared capabilities`,declaredDescription:`From the plugin manifest. OpenClaw validates the plugin against these declarations when it loads.`,declaredEmpty:`No channels, providers, or tools declared in the manifest.`,contracts:`Contracts`,hooks:`Hooks`,runtimeHooks:`Code plugins may register hooks at runtime; their hook names are not declared in the manifest.`,mcpServers:`MCP servers`,cliCommands:`CLI commands`,cliBackends:`CLI backends`,skills:`Skills`,dangerousFlags:`Dangerous config flags`,grantsTitle:`Your grants`,grantsDescription:`Set per plugin in plugins.entries.{id}. Hooks outside these grants are blocked at load.`,promptInjection:`Prompt injection`,conversationAccess:`Conversation access`,allowed:`Allowed`,blocked:`Blocked`,on:`On`,off:`Off`,grantDefault:`(default)`,grantConfigured:`(set in config)`,externalAccessHint:`Off by default for external plugins.`,modelOverrides:`Model overrides`,subagentModelOverrides:`Subagent model overrides`,modelOverride:`Model override: {value}`,allowedModels:`Allowed models: {models}`,allowedCompletionModels:`Completion models: {models}`,authProfileOverride:`Auth profile override: {value}`,agentIdOverride:`Agent ID override: {value}`,noOverrides:`No overrides configured`,loading:`Loading capability details…`,fallback:`Capability details must be available before you can approve this plugin.`,verifiedClean:`Verified clean`,reviewRecommended:`Review recommended`,reviewRequired:`Review required`,trustBlocked:`Blocked`,scanDate:`Scanned {date}`,integrity:`Integrity`,sha256:`SHA-256`,commit:`Commit`,pinnedArtifact:`Pinned to the exact installed artifact.`,sourceClawHub:`ClawHub`,sourceNpm:`npm`,sourceGit:`Git`,sourcePath:`Local path`,sourceArchive:`Archive`,sourceMarketplace:`Marketplace`,community:`Community`,enableNamed:`Enable {name}`}},Nt=Object.assign(()=>{Ne.pluginConsent=N.pluginConsent},{catalog:N})})))()}function P(e,t,n,r,i=`plugins-tile`){let a=D(e);if(a)return h`<span class=${i}>
      <img src=${a} alt="" loading="lazy" decoding="async" />
    </span>`;if(n)return h`<span class=${i}>
      <img
        class="plugins-icon"
        src=${n}
        alt=""
        loading="lazy"
        decoding="async"
        @error=${r}
      />
    </span>`;let[o,s]=ct(e),c=it(t);return h`<span
    class=${`${i} ${i}--fallback`}
    style=${`--plugins-art-a:${o};--plugins-art-b:${s}`}
    aria-hidden="true"
  >
    ${c?h`<span>${c}</span>`:y.puzzle}
  </span>`}function F(e,t,n=!1){return h`
    <div class="plugins-detail__meta-row ${n?`plugins-consent__row--warning`:``}">
      <span class="plugins-detail__meta-label">${e}</span>
      <span class="plugins-detail__meta-value">${t}</span>
    </div>
  `}function Ft(e){return h`<span class="plugins-consent__items">${e.join(`, `)}</span>`}function It(e,t=!1){return k.flatMap(n=>{let r=e[n];return r?.length&&(t||n!==`dangerousConfigFlags`)?[F(x(Kt[n]),Ft(r),t)]:[]})}function Lt(e){let t=It(e);return h`
    <section class="plugins-consent__section">
      <h3>${x(`pluginConsent.declaredTitle`)}</h3>
      <p class="plugins-consent__description">${x(`pluginConsent.declaredDescription`)}</p>
      ${t.length>0?h`<div class="plugins-consent__rows">${t}</div>`:h`<p class="plugins-consent__hint">${x(`pluginConsent.declaredEmpty`)}</p>`}
      ${e.hooks.length===0?F(x(`pluginConsent.hooks`),x(`pluginConsent.runtimeHooks`)):v}
      ${e.dangerousConfigFlags.length>0?F(x(`pluginConsent.dangerousFlags`),Ft(e.dangerousConfigFlags),!0):v}
    </section>
  `}function Rt(e){if(!e.widened)return v;let t=It(e.widened,!0);return t.length===0?v:h`
    <section class="plugins-consent__section">
      <h3>${x(`pluginConsent.widenedTitle`)}</h3>
      <p class="plugins-consent__description">
        ${x(`pluginConsent.widenedDescription`)}
        ${e.acceptedAt?x(`pluginConsent.previouslyAccepted`,{date:e.acceptedAt}):v}
      </p>
      <div class="plugins-consent__rows">${t}</div>
    </section>
  `}function zt(e,t,n){return`${x(e.effective?t:n)} ${x(e.configured===void 0?`pluginConsent.grantDefault`:`pluginConsent.grantConfigured`)}`}function I(e,t){return t===void 0?void 0:x(e,{value:x(t?`pluginConsent.allowed`:`pluginConsent.blocked`)})}function Bt(e){return[I(`pluginConsent.modelOverride`,e.allowModelOverride),e.allowedModels?.length?x(`pluginConsent.allowedModels`,{models:e.allowedModels.join(`, `)}):void 0,`allowedCompletionModels`in e&&e.allowedCompletionModels?.length?x(`pluginConsent.allowedCompletionModels`,{models:e.allowedCompletionModels.join(`, `)}):void 0,`allowAuthProfileOverride`in e?I(`pluginConsent.authProfileOverride`,e.allowAuthProfileOverride):void 0,`allowAgentIdOverride`in e?I(`pluginConsent.agentIdOverride`,e.allowAgentIdOverride):void 0].filter(Boolean).join(` · `)||x(`pluginConsent.noOverrides`)}function Vt(e,t){let n=e.hooks.allowConversationAccess;return h`
    <section class="plugins-consent__section">
      <h3>${x(`pluginConsent.grantsTitle`)}</h3>
      <p class="plugins-consent__description">${x(`pluginConsent.grantsDescription`)}</p>
      <div class="plugins-consent__rows">
        ${F(x(`pluginConsent.promptInjection`),zt(e.hooks.allowPromptInjection,`pluginConsent.allowed`,`pluginConsent.blocked`))}
        ${F(x(`pluginConsent.conversationAccess`),h`
            ${zt(n,`pluginConsent.on`,`pluginConsent.off`)}
            ${!n.effective&&n.configured===void 0&&t!==`bundled`?h`<span class="plugins-consent__hint">
                    ${x(`pluginConsent.externalAccessHint`)}
                  </span>`:v}
          `)}
        ${e.llm?F(x(`pluginConsent.modelOverrides`),Bt(e.llm)):v}
        ${e.subagent?F(x(`pluginConsent.subagentModelOverrides`),Bt(e.subagent)):v}
      </div>
    </section>
  `}function L(e,t){if(t)return x(`pluginsPage.official`);let n=e&&Object.hasOwn(R,e)?R[e]:void 0;return n?x(n):e??(t===!1?x(`pluginConsent.community`):null)}function Ht(e){return e===`source-linked`?x(`pluginsPage.verifiedSource`):e}function Ut(e){if(!e)return v;let t=e.integrityKind===`sha256`?x(`pluginConsent.sha256`):e.integrityKind===`git-commit`?x(`pluginConsent.commit`):x(`pluginConsent.integrity`);return h`
    <div class="plugins-consent__provenance">
      <span
        >${[x(qt[e.kind]),e.spec??e.packageName].filter(Boolean).join(` · `)}</span
      >
      ${e.integrity?h`<span title=${e.integrity}>
              ${t}: <code>${e.integrity.slice(0,20)}…</code>
            </span>`:v}
    </div>
    ${e.integrity?h`<p class="plugins-consent__hint">${x(`pluginConsent.pinnedArtifact`)}</p>`:v}
  `}function Wt(e){if(!e)return v;let t=x(e.disposition===`clean`?`pluginConsent.verifiedClean`:e.disposition===`review-recommended`?`pluginConsent.reviewRecommended`:e.disposition===`review-required`?`pluginConsent.reviewRequired`:`pluginConsent.trustBlocked`),n=e.disposition===`clean`?`ok`:e.disposition===`blocked`?`danger`:`warn`;return h`
    <section class="plugins-consent__trust">
      ${T({kind:n,label:t})}
      ${e.reasons?.length?h`<ul>
              ${e.reasons.map(e=>h`<li>${e}</li>`)}
            </ul>`:v}
      ${e.checkedAt?h`<p class="plugins-consent__hint">
              ${x(`pluginConsent.scanDate`,{date:e.checkedAt})}
            </p>`:v}
    </section>
  `}function Gt(e){let{consent:t,inspection:n}=e,r=t.details,i=n?.plugin,a=t.fallback,o=n?.source?.packageName??(t.intent.kind===`install`&&t.intent.request.source===`clawhub`?t.intent.request.packageName:null),s=t.pluginId??o??a?.name??`plugin`,c=i?.name??a?.name??s,l=i?.version??a?.version,u=[L(i?.origin,a?.official),o].filter(Boolean).join(` · `),ee=t.intent.kind===`install`?e.busy?x(`pluginsPage.installing`):x(`pluginsPage.installNamed`,{name:c}):e.busy?x(`pluginsPage.working`):x(`pluginConsent.enableNamed`,{name:c}),d=!e.canMutate||e.busy||e.loading||!!e.error||!n,te=h`
    <button
      type="button"
      class="btn primary"
      ?disabled=${d&&!e.mutationBlockedReason}
      aria-disabled=${e.canMutate?v:`true`}
      @click=${()=>{d||e.onConfirm()}}
    >
      ${ee}
    </button>
  `;return h`
    <openclaw-modal-dialog
      label=${c}
      style="--openclaw-modal-width: min(560px, calc(100vw - 32px));"
      @modal-cancel=${e.onCancel}
    >
      <section class="plugins-consent" data-plugin-consent=${t.intent.kind}>
        <header class="plugins-consent__header">
          ${P(s,c,e.iconUrl)}
          <div>
            <div class="plugins-detail__title">
              <h2>${c}</h2>
              ${l?h`<span class="plugins-version">${`v${l}`}</span>`:v}
            </div>
            ${u?h`<p class="plugins-consent__description">${u}</p>`:v}
          </div>
        </header>
        ${e.loading?h`<p class="plugins-consent__hint" role="status">${x(`pluginConsent.loading`)}</p>`:e.error?h`<div class="plugins-consent__error" role="alert">
                  <span>${e.error}</span>
                  <button type="button" class="btn btn--sm" @click=${e.onRetry}>
                    ${x(`pluginsPage.tryAgain`)}
                  </button>
                </div>`:n?h`
                    ${Ut(n.source)} ${Wt(n.trust)}
                    ${r?Rt(r):v}
                    ${Lt(n.declared)}
                    ${Vt(n.grants,i?.origin)}
                  `:h`<p class="plugins-consent__description">${x(`pluginConsent.fallback`)}</p>`}
        <footer class="plugins-consent__actions">
          <button type="button" class="btn" @click=${e.onCancel}>
            ${x(`pluginsPage.cancel`)}
          </button>
          ${Mt(e.mutationBlockedReason,te)}
        </footer>
      </section>
    </openclaw-modal-dialog>
  `}var Kt,qt,R;function Jt(){return(Jt=e((()=>{m(),A(),ke(),je(),M(),Je(),b(),Pt(),O(),Nt(),Kt={channels:`pluginsPage.categoryChannels`,providers:`pluginsPage.categoryProviders`,tools:`pluginsPage.categoryTools`,contracts:`pluginConsent.contracts`,hooks:`pluginConsent.hooks`,mcpServers:`pluginConsent.mcpServers`,cliCommands:`pluginConsent.cliCommands`,cliBackends:`pluginConsent.cliBackends`,skills:`pluginConsent.skills`,dangerousConfigFlags:`pluginConsent.dangerousFlags`},qt={bundled:`pluginsPage.included`,"official-catalog":`pluginsPage.official`,clawhub:`pluginConsent.sourceClawHub`,npm:`pluginConsent.sourceNpm`,git:`pluginConsent.sourceGit`,path:`pluginConsent.sourcePath`,archive:`pluginConsent.sourceArchive`,marketplace:`pluginConsent.sourceMarketplace`},R={bundled:`pluginsPage.included`,global:`pluginsPage.global`,workspace:`pluginsPage.workspace`,config:`pluginsPage.config`,official:`pluginsPage.official`}})))()}function Yt(e){switch(e){case`info`:return x(`pluginsPage.policyReviewSeverityInfo`);case`warn`:return x(`pluginsPage.policyReviewSeverityWarn`);case`critical`:return x(`pluginsPage.policyReviewSeverityCritical`)}return e}function Xt(e){switch(e){case`all`:return x(`pluginsPage.filterAll`);case`enabled`:return x(`pluginsPage.enabled`);case`disabled`:return x(`pluginsPage.disabled`);case`issues`:return x(`pluginsPage.filterIssues`);default:return e}}function Zt(e){switch(e){case`work`:return x(`pluginsPage.connectorGroupWork`);case`dev`:return x(`pluginsPage.connectorGroupDev`);case`home`:return x(`pluginsPage.connectorGroupHome`);case`life`:return x(`pluginsPage.connectorGroupLife`);default:return e}}function z(e){return`plugin:${e}`}function Qt(e){return`clawhub:${e}`}function B(e,t,n){return ne(t,e.result?.plugins??[],n)}function V(e,t){return t?!!e.busy[t]:!1}function $t(e){return`connector:${e}`}function H(e){return e.trim().toLocaleLowerCase()}function U(e,t){let n=H(t);return!n||[e.name,e.id,e.packageName,e.description,e.origin,e.category,...e.kind??[]].some(e=>e?.toLocaleLowerCase().includes(n))}function en(e,t){let n=H(t);return!n||[e.id,e.name,x(e.descriptionKey)].some(e=>e.toLocaleLowerCase().includes(n))}function W(e){return e.toSorted((e,t)=>{let n=Number(!!t.featured)-Number(!!e.featured);if(n!==0)return n;if(e.featured&&t.featured){let n=e.featuredAt,r=t.featuredAt;if(n!==void 0||r!==void 0){if(n===void 0)return 1;if(r===void 0)return-1;if(n!==r)return r-n}}return(e.order??2**53-1)-(t.order??2**53-1)||e.name.localeCompare(t.name)})}function tn(e,t=``,n=`all`){return W(e.filter(e=>{if(!e.installed||!U(e,t))return!1;switch(n){case`enabled`:return e.enabled&&e.state!==`error`;case`disabled`:return!e.enabled&&e.state!==`error`;case`issues`:return e.state===`error`;default:return!0}}))}function nn(e){let t=new Map;for(let n of e){let e=n.category??`other`,r=t.get(e)??[];r.push(n),t.set(e,r)}let n=e=>{let t=st.indexOf(e);return t===-1?st.length:t};return[...t.entries()].map(([e,t])=>({category:e,label:ot(e),plugins:t})).toSorted((e,t)=>n(e.category)-n(t.category))}function rn(e,t=``){let n=W(e.filter(e=>e.featured&&U(e,t))),r=new Set(n.map(e=>e.id));return{featured:n,official:W(e.filter(e=>!r.has(e.id)&&e.origin===`official`&&!e.installed&&U(e,t))),connectors:at.filter(e=>en(e,t))}}function an(e){switch(e.state){case`enabled`:return x(`pluginsPage.enabled`);case`disabled`:return x(`pluginsPage.disabled`);case`error`:return x(`pluginsPage.needsAttention`);case`not-installed`:return x(`pluginsPage.available`);default:return e.state}}function on(e){let t=e.state===`enabled`?`ok`:e.state===`error`?`danger`:`muted`;return T({kind:t,label:an(e)})}function sn(e){return e.state===`error`?on(e):v}function cn(e,t,n){n&&e.onInstall(t,n)}function G(e){let t=e.filter(e=>e!==v&&e!==``);return t.length===0?v:h`<span class="settings-row__desc plugins-meta">
    ${t.map((e,t)=>h`${t>0?h`<span aria-hidden="true"> · </span>`:v}${e}`)}
  </span>`}function K(e,t,n,r,i){let a=t?e:i??e,o=t??(i?r.messages[i]:void 0);if(!o)return v;if(o.installPolicyWarning){let{details:e,request:t}=o.installPolicyWarning,s=e.findings??[],c=s.length===0?x(`pluginsPage.policyReviewBodyReason`,{reason:l(e.reason)}):x(`pluginsPage.policyReviewBodyKnown`,{count:String(s.length)});return h`
      <div
        class="plugins-row-message plugins-row-message--warning plugins-policy-review"
        role="alert"
      >
        <div class="plugins-policy-review__header">
          <span class="plugins-policy-review__icon" aria-hidden="true">
            ${y.alertTriangle}
          </span>
          <div>
            <strong>${x(`pluginsPage.policyReviewTitle`)}</strong>
            ${s.length>0?h`<span class="plugins-policy-review__reason"
                    >${l(e.reason)}</span
                  >`:v}
            <span>${c}</span>
          </div>
        </div>
        ${s.length>0?h`
                <section class="plugins-policy-review__findings-panel">
                  <strong class="plugins-policy-review__findings-heading"
                    >${x(`pluginsPage.policyReviewFindings`)}</strong
                  >
                  <ul class="plugins-policy-review__findings">
                    ${s.map(e=>h`
                        <li>
                          <span class="plugins-policy-review__finding-content">
                            <span
                              class="plugins-policy-review__severity plugins-policy-review__severity--${e.severity}"
                              >${Yt(e.severity)}</span
                            >
                            <span>${l(e.message)}</span>
                          </span>
                        </li>
                      `)}
                  </ul>
                </section>
              `:v}
        ${s.length>0?h`
                <details class="plugins-policy-review__details">
                  <summary>
                    <span class="plugins-policy-review__details-chevron" aria-hidden="true"
                      >${y.chevronRight}</span
                    >
                    <span>${x(`pluginsPage.policyReviewTechnicalDetails`)}</span>
                  </summary>
                  <div class="plugins-policy-review__details-body">
                    <ul>
                      ${s.map(e=>h`
                          <li>
                            <code>${e.ruleId}</code>
                            ${e.file?h`<code
                                    >${e.file}${e.line?`:${e.line}`:``}</code
                                  >`:v}
                            ${e.evidence?h`<span>${e.evidence}</span>`:v}
                          </li>
                        `)}
                    </ul>
                  </div>
                </details>
              `:v}
        <p class="plugins-policy-review__scope">${x(`pluginsPage.policyReviewScope`)}</p>
        <div class="plugins-policy-review__actions">
          <button
            type="button"
            class="btn btn--sm"
            ?disabled=${n}
            @click=${()=>r.onDismissMessage(a)}
          >
            ${x(`pluginsPage.cancel`)}
          </button>
          ${q(r,{busy:n,className:`btn btn--sm danger`,label:x(n?`pluginsPage.installing`:`pluginsPage.installAnyway`),onClick:()=>cn(r,{...t,acknowledgeInstallPolicyWarning:!0},i)})}
        </div>
      </div>
    `}let s=o.kind===`error`?`alert`:`status`;return h`
    <div class="plugins-row-message plugins-row-message--${o.kind}" role=${s}>
      <span>${o.text}</span>
    </div>
  `}function ln(e){return!!e.target?.closest(`button, a, input, label, form, summary, .plugins-policy-review, [role='menu']`)}function q(e,t){let n=e.mutationBlockedReason;return Mt(n,h`
    <button
      type="button"
      class=${t.className}
      aria-label=${t.ariaLabel??v}
      title=${n?v:t.title??v}
      ?disabled=${!n&&(!e.canMutate||t.busy)}
      aria-disabled=${e.canMutate?v:`true`}
      @click=${n=>{t.stopPropagation&&n.stopPropagation(),!(!e.canMutate||t.busy)&&t.onClick()}}
    >
      ${t.label}
    </button>
  `)}function J(e,t,n){let r=!n.enabled;return q(e,{busy:t,className:n.className??`btn btn--sm`,label:x(t?`pluginsPage.working`:r?`pluginsPage.enableAction`:`pluginsPage.disableAction`),onClick:()=>n.onToggle(r),stopPropagation:!0})}function un(e,t,n,r){let i=x(`pluginsPage.removeNamed`,{name:n});return q(e,{busy:t,className:`btn btn--sm btn--icon plugins-remove`,label:y.trash,onClick:r,ariaLabel:i,title:i,stopPropagation:!0})}function Y(e,t,n,r,i){return e.messages[i]?.installPolicyWarning?v:q(e,{busy:t,className:`btn btn--sm plugins-install`,label:x(t?`pluginsPage.installing`:`pluginsPage.install`),onClick:()=>e.onInstall(r,i),ariaLabel:x(`pluginsPage.installNamed`,{name:n}),stopPropagation:!0})}function dn(e,t,n,r){if(!e.installed){let r=e.install;return r?Y(t,n,e.name,r,B(t,r)):h`<span class="plugins-action-note">${x(`pluginsPage.unavailable`)}</span>`}return h`
    ${J(t,n,{enabled:e.enabled,onToggle:n=>t.onSetEnabled(e.id,n,r)})}
    ${e.removable?un(t,n,e.name,()=>t.onUninstall(e.id,r)):v}
  `}function fn(e){let t=(e.result?.plugins??[]).filter(e=>e.installed),n=t.filter(e=>e.state===`error`).length,r=t.filter(e=>e.enabled&&e.state!==`error`).length,i={all:t.length,enabled:r,disabled:t.length-r-n,issues:n};return Ze({value:e.installedFilter,ariaLabel:x(`pluginsPage.filterLabel`),options:Dn.map(e=>({value:e,label:h`${Xt(e)} <span class="settings-count">${i[e]}</span>`})),onChange:t=>e.onFilterChange(t)})}function pn(e){return h`
    <h3 class="settings-row__title">
      ${e.onShowDetails?h`
              <button
                type="button"
                class="plugins-item__detail-button"
                aria-label=${e.name}
                @click=${t=>{t.stopPropagation(),e.onShowDetails?.()}}
              >
                ${e.content}
              </button>
            `:e.content}
    </h3>
  `}function X(e,t,n=!1){let r=z(e.id),i=e.install?B(t,e.install):void 0,a=t.busy[r]||V(t,i);return h`
    <article
      class="settings-row plugins-item plugins-item--clickable"
      data-plugin-id=${e.id}
      data-plugin-source=${e.origin??`unknown`}
      data-plugin-status=${e.state}
      aria-busy=${a?`true`:`false`}
      @click=${n=>{ln(n)||t.onShowDetails(e.id)}}
    >
      ${P(e.id,e.name,t.iconUrls[e.id],()=>t.onIconError(e.id))}
      <div class="settings-row__text">
        ${pn({name:e.name,content:h`
            ${e.name}
            ${e.version?h`<span class="plugins-version">v${e.version}</span>`:v}
          `,onShowDetails:()=>t.onShowDetails(e.id)})}
        <span class="settings-row__desc">
          ${e.description||x(`pluginsPage.optionalCapability`)}
        </span>
        ${G([e.origin?L(e.origin):v,n&&e.packageName?h`<span class="plugins-meta__mono">${e.packageName}</span>`:v])}
      </div>
      <div class="settings-row__control">
        ${e.installed?sn(e):v}
        ${dn(e,t,a,r)}
      </div>
      ${e.error?h`<div class="plugins-row-message plugins-row-message--error" role="alert">
              ${l(e.error)}
            </div>`:v}
      ${K(r,t.messages[r],a,t,i)}
    </article>
  `}function mn(e){let t=H(e.query),n=e.mcpServers?.filter(e=>!t||e.name.toLocaleLowerCase().includes(t)||e.target.toLocaleLowerCase().includes(t));if(t&&n&&n.length===0)return v;let r=n?n.length===0?Ye(x(`pluginsPage.mcpEmpty`)):_(n,e=>e.name,t=>hn(t,e)):Xe({label:x(`pluginsPage.loading`),rows:2});return E({title:x(`pluginsPage.mcpServersGroup`),...n?{count:n.length}:{},description:x(`pluginsPage.mcpHint`),actions:h`
        <a class="plugins-group__link" href=${e.mcpSettingsHref}
          >${x(`pluginsPage.mcpSettingsLink`)}</a
        >
        ${q(e,{busy:e.mcpBusy,className:`btn btn--sm`,label:h`<span aria-hidden="true">${y.plus}</span> ${x(`mcpServers.add`)}`,onClick:()=>e.onMcpFormToggle(!e.mcpFormOpen)})}
      `},h`
      ${e.mcpFormOpen?tt({busy:e.mcpBusy,disabled:!e.canMutate,blockedReason:e.mutationBlockedReason,onSubmit:e.onMcpAdd,onCancel:()=>e.onMcpFormToggle(!1)}):v}
      ${e.mcpMessage?h`<div
              class="plugins-row-message plugins-row-message--${e.mcpMessage.kind} plugins-group-message"
              role=${e.mcpMessage.kind===`error`?`alert`:`status`}
            >
              <span>${e.mcpMessage.text}</span>
            </div>`:v}
      ${r}
    `)}function hn(e,t){return h`
    <article class="settings-row plugins-item" data-mcp-name=${e.name}>
      ${P(e.name,e.name)}
      <div class="settings-row__text">
        <h3 class="settings-row__title">${e.name}</h3>
        <span class="settings-row__desc plugins-meta__mono">
          ${e.target||x(`mcpServers.missingTransport`)}
        </span>
        ${G([x(`pluginsPage.mcp`),e.transport,e.auth===`oauth`?x(`pluginsPage.oauth`):v])}
      </div>
      <div class="settings-row__control">
        ${J(t,t.mcpBusy,{enabled:e.enabled,onToggle:n=>t.onMcpToggle(e.name,n)})}
        ${un(t,t.mcpBusy,e.name,()=>t.onMcpRemove(e.name))}
      </div>
    </article>
  `}function gn(e){let t=nn(tn(e.result?.plugins??[],e.query,e.installedFilter)),n=!!(e.query||e.installedFilter!==`all`);return h`
    ${t.length===0?Z(x(n?`pluginsPage.noInstalledMatchTitle`:`pluginsPage.noInstalledTitle`),x(n?`pluginsPage.noMatchBody`:`pluginsPage.noInstalledBody`),n?`curious`:`sleepy`):t.map(t=>E({title:t.label,count:t.plugins.length},_(t.plugins,e=>e.id,t=>X(t,e,!0))))}
    ${mn(e)}
  `}function _n(e,t){let n=$t(e.id),r=!!t.busy[n],i=e.action.kind===`mcp`,a=i&&!!t.mcpServers?.some(t=>e.action.kind===`mcp`&&t.name===e.action.mcp.serverName);return h`
    <article
      class="settings-row plugins-item"
      data-connector-id=${e.id}
      aria-busy=${r?`true`:`false`}
    >
      ${P(e.id,e.name)}
      <div class="settings-row__text">
        <h3 class="settings-row__title">${e.name}</h3>
        <span class="settings-row__desc">${x(e.descriptionKey)}</span>
        ${G(i?[x(`pluginsPage.mcp`),x(`pluginsPage.connectorMcpNote`)]:[x(`pluginsPage.connectorClawHubNote`)])}
      </div>
      <div class="settings-row__control">
        ${i?a?T({kind:`ok`,label:x(`pluginsPage.connectorAdded`)}):q(t,{busy:r,className:`btn btn--sm`,label:x(r?`mcpServers.adding`:`pluginsPage.connectorAdd`),onClick:()=>t.onAddConnector(e)}):h`
                <button
                  type="button"
                  class="btn btn--sm"
                  @click=${()=>e.action.kind===`clawhub`&&t.onSearchClawHub(e.action.query)}
                >
                  <span aria-hidden="true">${y.search}</span>
                  ${x(`pluginsPage.connectorSearch`)}
                </button>
              `}
      </div>
      ${K(n,t.messages[n],r,t)}
    </article>
  `}function vn(e,t){return t.length===0?v:E({title:e,count:t.length},t)}function yn(e,t){return t.find(t=>t.installed&&(t.id===e.package.runtimeId||t.packageName===e.package.name||t.install?.source===`clawhub`&&t.install.packageName===e.package.name))}function bn(e,t){let n=e.package,r=yn(e,t.result?.plugins??[]),i=Qt(n.name),a={source:`clawhub`,packageName:n.name},o=B(t,a,n.runtimeId),s=t.busy[i]||V(t,o),c=n.runtimeId??n.name;return h`
    <article
      class="settings-row plugins-item ${r?`plugins-item--clickable`:``}"
      data-package-name=${n.name}
      data-plugin-source="clawhub"
      data-plugin-status=${r?.state??`not-installed`}
      aria-busy=${s?`true`:`false`}
      @click=${e=>{r&&!ln(e)&&t.onShowDetails(r.id)}}
    >
      ${P(c,n.displayName)}
      <div class="settings-row__text">
        ${pn({name:n.displayName,content:h`
            ${n.displayName}
            ${n.latestVersion?h`<span class="plugins-version">v${n.latestVersion}</span>`:v}
          `,onShowDetails:r?()=>t.onShowDetails(r.id):void 0})}
        <span class="settings-row__desc">${n.summary||n.name}</span>
        ${G([n.isOfficial?x(`pluginsPage.official`):v,n.verificationTier?Ht(n.verificationTier):v,typeof n.downloads==`number`?h`<span class="plugins-downloads">
                <span aria-hidden="true">${y.download}</span>
                ${On.format(n.downloads)}
              </span>`:v,n.family===`bundle-plugin`?x(`pluginsPage.bundlePlugin`):x(`pluginsPage.codePlugin`)])}
      </div>
      <div class="settings-row__control">
        ${r?h`${sn(r)}${dn(r,t,s,i)}`:Y(t,s,n.displayName,a,o)}
      </div>
      ${K(i,t.messages[i],s,t,o)}
    </article>
  `}function xn(e){let t=e.query.trim();if(t.length<2)return v;let n;if(e.searchError)n=h`<div class="plugins-search-state plugins-search-state--error" role="alert">
      ${e.searchError}
    </div>`;else{let r=e.searchLoading||!e.searchResults,i=e.searchResults?.length??0;n=h`
      <div
        class=${r?`plugins-search-state`:i===0?`settings-empty`:`sr-only`}
        role="status"
        aria-live="polite"
      >
        ${r?x(`pluginsPage.searching`):i===0?x(`pluginsPage.noClawHubResultsBody`,{query:t}):x(i===1?`pluginsPage.searchResultCountOne`:`pluginsPage.searchResultCount`,{count:String(i)})}
      </div>
      ${r?v:_(e.searchResults??[],e=>e.package.name,t=>bn(t,e))}
    `}return E({title:x(`pluginsPage.fromClawHub`),...e.searchResults?{count:e.searchResults.length}:{},actions:h`
        <a
          class="plugins-group__link"
          href=${d}
          target=${We}
          rel=${Ie()}
        >
          ${x(`pluginsPage.browseClawHub`)}
          <span class="plugins-group__link-icon" aria-hidden="true">${y.externalLink}</span>
        </a>
      `},n)}function Sn(e){let t=rn(e.result?.plugins??[],e.query),n=t.featured.map(t=>X(t,e)),r=t.official.map(t=>X(t,e)),i=xn(e);return!n.length&&!r.length&&!t.connectors.length?h`
      ${i===v?Z(x(`pluginsPage.noDiscoverMatchTitle`),x(`pluginsPage.noMatchBody`),`curious`):v}
      ${i}
    `:h`
    ${vn(x(`pluginsPage.featuredGroup`),n)}
    ${vn(x(`pluginsPage.officialGroup`),r)}
    ${Cn(t.connectors,e)} ${i}
  `}function Cn(e,t){if(e.length===0)return v;let n=lt.map(t=>({group:t,entries:e.filter(e=>e.group===t)})).filter(e=>e.entries.length>0);return E({title:x(`pluginsPage.connectorsGroup`),count:e.length,description:x(`pluginsPage.connectorsHint`)},n.map(e=>h`
        <h3 class="plugins-subheader" data-connector-group=${e.group}>
          ${Zt(e.group)}
        </h3>
        ${e.entries.map(e=>_n(e,t))}
      `))}function wn(e){let t=e.detailPluginId?e.result?.plugins.find(t=>t.id===e.detailPluginId):void 0;if(!t)return v;let n=z(t.id),r=t.install?B(e,t.install):void 0,i=e.busy[n]||V(e,r);return h`
    <openclaw-modal-dialog
      label=${t.name}
      style="--openclaw-modal-width: min(580px, calc(100vw - 32px));"
      @modal-cancel=${()=>e.onShowDetails(null)}
    >
      <section class="plugins-detail" data-detail-plugin-id=${t.id}>
        <button
          type="button"
          class="btn btn--sm btn--icon plugins-detail__close"
          aria-label=${x(`pluginsPage.detailClose`)}
          @click=${()=>e.onShowDetails(null)}
        >
          ${y.x}
        </button>
        ${P(t.id,t.name,e.iconUrls[t.id],()=>e.onIconError(t.id),`plugins-cover`)}
        <div class="plugins-detail__body">
          <div class="plugins-detail__title">
            <h2>${t.name}</h2>
            ${t.version?h`<span class="plugins-version">v${t.version}</span>`:v}
            ${on(t)}
          </div>
          <p class="plugins-detail__description">
            ${t.description||x(`pluginsPage.optionalCapability`)}
          </p>
          <div class="plugins-detail__actions">
            ${t.installed?J(e,i,{enabled:t.enabled,onToggle:r=>e.onSetEnabled(t.id,r,n),className:`btn ${t.enabled?``:`primary`}`}):t.install?Y(e,i,t.name,t.install,B(e,t.install)):v}
            ${t.removable?q(e,{busy:i,className:`btn plugins-detail__remove`,label:h`<span aria-hidden="true">${y.trash}</span> ${x(`pluginsPage.remove`)}`,onClick:()=>e.onUninstall(t.id,n)}):v}
          </div>
          ${t.error?h`<div class="plugins-row-message plugins-row-message--error" role="alert">
                  ${l(t.error)}
                </div>`:v}
          ${K(n,e.messages[n],i,e,r)}
          <div class="plugins-detail__meta">
            ${t.origin?F(x(`pluginsPage.detailOrigin`),L(t.origin)):v}
            ${t.category?F(x(`pluginsPage.detailCategory`),ot(t.category)):v}
            ${t.packageName?F(x(`pluginsPage.detailPackage`),h`<code>${t.packageName}</code>`):v}
            ${F(x(`pluginsPage.detailPluginId`),h`<code>${t.id}</code>`)}
          </div>
          ${t.installed?h`<section class="plugins-detail__capabilities">
                  <h3>${x(`pluginsPage.capabilities`)}</h3>
                  ${e.detailInspectionError?h`<div class="plugins-consent__error" role="alert">
                          <span>${e.detailInspectionError}</span>
                          <button
                            type="button"
                            class="btn btn--sm"
                            @click=${()=>e.onShowDetails(t.id)}
                          >
                            ${x(`pluginsPage.tryAgain`)}
                          </button>
                        </div>`:e.detailInspection?h`
                            ${Lt(e.detailInspection.declared)}
                            ${Vt(e.detailInspection.grants,e.detailInspection.plugin.origin)}
                          `:h`<p class="plugins-consent__hint">${x(`pluginConsent.loading`)}</p>`}
                </section>`:v}
        </div>
      </section>
    </openclaw-modal-dialog>
  `}function Z(e,t,n){return h`
    <div class="plugins-empty">
      <!-- Sleepy marks truly empty inventory; curious marks a filter/search miss. -->
      ${n?h`<openclaw-mascot
              class="plugins-empty__mascot"
              .mood=${n}
              .size=${84}
            ></openclaw-mascot>`:h`<span class="plugins-empty__icon" aria-hidden="true">${y.puzzle}</span>`}
      <h2>${e}</h2>
      <p>${t}</p>
    </div>
  `}function Tn(e){switch(e.activeTab){case`installed`:return gn(e);case`discover`:return Sn(e);default:return e.activeTab}}function En(e){let t=!!e.result,n=e.loading&&!t?`loading`:e.error&&!t?`error`:!e.connected&&!t?`offline`:`content`;return qe(h`
      <div class="plugins-toolbar">
        <input
          id="plugins-global-search"
          class="settings-input plugins-toolbar__search"
          name="plugins-search"
          type="search"
          autocomplete="off"
          aria-label=${x(`pluginsPage.searchLabel`)}
          .value=${ge(e.query)}
          placeholder=${x(`pluginsPage.searchPlaceholder`)}
          @input=${t=>e.onQueryChange(t.currentTarget.value)}
        />
        ${e.activeTab===`installed`&&n===`content`?fn(e):v}
        <button
          type="button"
          class="btn btn--sm btn--icon plugins-refresh"
          aria-label=${x(`pluginsPage.refresh`)}
          title=${x(`pluginsPage.refresh`)}
          ?disabled=${e.loading||!e.connected}
          @click=${e.onRefresh}
        >
          <span aria-hidden="true">${y.refresh}</span>
        </button>
      </div>

      ${e.error?h`<div class="plugins-page-error" role="alert">
              <span>${e.error}</span>
              <button type="button" class="btn btn--sm" @click=${e.onRefresh}>
                ${x(`pluginsPage.tryAgain`)}
              </button>
            </div>`:v}
      ${e.pageNotice?h`<div
              class="plugins-row-message plugins-row-message--${e.pageNotice.kind} plugins-page-notice"
              role=${e.pageNotice.kind===`error`?`alert`:`status`}
            >
              <span>${e.pageNotice.text}</span>
            </div>`:v}

      <wa-tab-panel
        id="plugins-hub-panel"
        class="plugins-panel"
        name=${e.activeTab}
        active
        aria-labelledby=${`plugins-tab-${e.activeTab}`}
      >
        ${n===`loading`?Ke(Xe({label:x(`pluginsPage.loading`)})):n===`error`?v:n===`offline`?Z(x(`pluginsPage.offlineTitle`),x(`pluginsPage.offlineBody`)):Tn(e)}
      </wa-tab-panel>
      ${wn(e)}
      ${e.consent?Gt({consent:e.consent,inspection:e.consentInspection,loading:e.consentInspectionLoading,error:e.consentInspectionError,iconUrl:e.consent.pluginId?e.iconUrls[e.consent.pluginId]:void 0,canMutate:e.canMutate,mutationBlockedReason:e.mutationBlockedReason,busy:!!e.busy[e.consent.intent.kind===`install`?e.consent.intent.installIdentity:e.consent.intent.rowKey],onCancel:e.onCancelConsent,onConfirm:e.onConfirmConsent,onRetry:e.onRetryConsentInspection}):v}
    `,{wide:!0})}var Dn,On;function Q(){return(Q=e((()=>{m(),pe(),me(),ke(),$e(),je(),Oe(),M(),Je(),b(),Fe(),f(),p(),Jt(),O(),Dn=[`all`,`enabled`,`disabled`,`issues`],On=new Intl.NumberFormat(void 0,{notation:`compact`,maximumFractionDigits:1})})))()}function kn(e,t,n){let r=t.restartRequired?`pluginsPage.${e}Restart`:`pluginsPage.${e}Success`,i=`warnings`in t?t.warnings??[]:[];return{kind:`success`,text:[x(r,{name:t.plugin.name}),...i.map(e=>l(e)),n?x(`pluginsPage.configRefreshFailed`,{error:n}):null].filter(Boolean).join(`
`)}}var An;function jn(){return(jn=e((()=>{b(),f(),j(),p(),jt(),kt(),Q(),An=class{constructor(e){this.host=e,this.consent=null,this.inspection=null,this.inspectionLoading=!1,this.inspectionError=null,this.mutationToken=0,this.mutationTokens=new Map,this.confirmedInstallScopes=new Map}reset(){this.close(),this.mutationTokens.clear(),this.confirmedInstallScopes.clear()}async runMutation(e,t,n,r={},i=t=>{this.host.setMessage(e,{kind:`error`,text:u(t)})}){let a=this.host.gateway.capture();if(!a||!this.host.canMutate()||this.host.isBusy(e)||r.confirm&&(!await r.confirm()||!this.host.gateway.isCurrent(a)||!this.host.canMutate()||this.host.isBusy(e)))return;this.host.clearPageNotice();let o=++this.mutationToken;this.mutationTokens.set(e,o);let c=()=>this.host.gateway.isCurrent(a)&&this.mutationTokens.get(e)===o,l=()=>c()&&this.mutationToken===o;this.host.setBusy(e,!0),r.preserveMessageWhilePending||this.host.setMessage(e,null);try{let e=await s(this.host.getContext().runtimeConfig,a.client,t,{canDispatch:()=>c()&&this.host.canMutate()});c()&&await n(e.value,e.refreshError,a.client,c,l)}catch(e){c()&&i(e,a)}finally{this.mutationTokens.get(e)===o&&(this.mutationTokens.delete(e),this.host.setBusy(e,!1))}}open(e,t,n){if(!this.host.canMutate())return;let r=this.host.getResult()?.plugins.find(e=>e.id===t);this.host.closeDetails(),this.inspection=null,this.inspectionError=null,this.inspectionLoading=!0,this.consent={intent:e,pluginId:t,fallback:{name:r?.name??t,...r?.version?{version:r.version}:{},...r?.origin===`official`?{official:!0}:{}},...n?{details:n}:{}},this.host.requestUpdate(),this.inspect()}close(){this.consent=null,this.inspection=null,this.inspectionLoading=!1,this.inspectionError=null,this.host.requestUpdate()}async inspect(){let e=this.consent,t=this.host.gateway.capture();if(!(!e?.pluginId||!t)){this.inspectionLoading=!0,this.inspectionError=null,this.host.requestUpdate();try{let n=await Tt(t.client,e.pluginId);this.host.gateway.isCurrent(t)&&this.consent===e&&(this.inspection=n)}catch(n){this.host.gateway.isCurrent(t)&&this.consent===e&&(this.inspectionError=u(n))}finally{this.host.gateway.isCurrent(t)&&this.consent===e&&(this.inspectionLoading=!1,this.host.requestUpdate())}}}confirm(){let e=this.consent?.intent,t=this.inspection?.reviewToken;!e||this.inspectionLoading||this.inspectionError||!t||(this.close(),e.kind===`install`?this.install({...e.request,acknowledgeCapabilities:{reviewToken:t}},e.installIdentity):this.updateEnabled(e.pluginId,!0,e.rowKey,{acknowledgeCapabilities:{reviewToken:t}}))}async install(e,t){let n=this.confirmedInstallScopes.get(t);this.confirmedInstallScopes.delete(t);let r=(e.acknowledgeInstallPolicyWarning===!0||e.acknowledgeCapabilities!==void 0)&&n&&this.host.gateway.isCurrent(n);await this.runMutation(t,t=>ie(t,e),async(e,n,r)=>{let i=z(e.plugin.id);this.host.applyMutationResult(e),i!==t&&this.host.setMessage(t,null),this.host.setMessage(i,kn(`installed`,e,n)),await this.host.refreshCatalogAfterMutation(r)},{confirm:r?void 0:()=>Dt(e),preserveMessageWhilePending:e.acknowledgeInstallPolicyWarning===!0},(n,r)=>{let i=Et(n);if(i){this.confirmedInstallScopes.set(t,r),this.open({kind:`install`,request:e,installIdentity:t},i.pluginId,i);return}let a=At(n);if(a){this.confirmedInstallScopes.set(t,r),this.host.setMessage(t,{kind:`warning`,text:a.reason,installPolicyWarning:{details:a,request:e}});return}this.host.setMessage(t,{kind:`error`,text:u(n)})})}async updateEnabled(e,t,n=z(e),r={}){await this.runMutation(n,n=>se(n,e,t,r),async(e,r,i,a)=>{this.host.applyMutationResult(e),this.host.setMessage(n,kn(t?`enabled`:`disabled`,e,r)),await this.host.refreshCatalogAfterMutation(i),a()&&!e.restartRequired&&this.host.getContext().gateway.connect()},{},r=>{let i=Et(r);if(t&&i){this.open({kind:`enable`,pluginId:e,rowKey:n},i.pluginId,i);return}this.host.setMessage(n,{kind:`error`,text:u(r)})})}}})))()}var Mn;function Nn(){return(Nn=e((()=>{Pe(),ye(),b(),oe(),ze(),f(),c(),Q(),Mn=class{constructor(e){this.host=e,this.servers=null,this.message=null,this.busy=!1,this.busyKey=null,this.formOpen=!1,this.feedbackGeneration=0,this.configTask=new S(e.element,{autoRun:!1,args:()=>[this.host.gateway.connected?this.host.gateway.client:null,this.host.getContext()?.runtimeConfig??null],task:async([e,t])=>!e||!t?w:(await t.refresh(),t.state.lastError),onComplete:()=>{this.syncServers()},onError:()=>{this.syncServers()}}),this.subscriptions=new de(e.element).effect(()=>this.host.getContext()?.runtimeConfig,e=>{this.syncServers();let t=e.subscribe(()=>this.syncServers());return()=>{this.resetFeedback(),t()}})}get refreshError(){let e=this.configTask.status===C.ERROR?u(this.configTask.error):this.configTask.status===C.COMPLETE?this.configTask.value:null;return e?x(`pluginsPage.configRefreshFailed`,{error:e}):null}get viewState(){return{mcpSettingsHref:Te(`mcp`,this.host.getContext()?.basePath??``),mcpServers:this.servers,mcpMessage:this.message,mcpBusy:this.busy,mcpFormOpen:this.formOpen,onAddConnector:e=>void this.addConnector(e),onMcpToggle:(e,t)=>void this.toggleServer(e,t),onMcpRemove:e=>void this.removeServer(e),onMcpFormToggle:e=>{this.formOpen=e,e&&(this.message=null),this.host.element.requestUpdate()},onMcpAdd:e=>void this.addServer(e)}}disconnect(){this.subscriptions.clear()}invalidate(){this.configTask.run([null,this.host.getContext().runtimeConfig])}syncServers(){let e=this.host.getContext()?.runtimeConfig.state.configSnapshot;this.servers=Ge(ue(e)),this.host.element.requestUpdate()}resetFeedback(){this.feedbackGeneration+=1,this.busy=!1,this.message=null,this.busyKey&&=(this.host.setRowBusy(this.busyKey,!1),null),this.host.element.requestUpdate()}ensureLoaded(e){e&&this.host.getContext()?.runtimeConfig.ensureLoaded().then(()=>this.syncServers())}pageError(e){let t=[e,this.refreshError].filter(e=>!!e);return t.length>0?t.join(` `):null}async refreshPage(e){await Promise.all([e(),this.refresh()])}async refresh(){let e=this.host.gateway.client;if(!e||!this.host.gateway.connected)return;let t=this.host.getContext().runtimeConfig;await this.configTask.run([e,t])}async addServer(e){let t=e.name.trim();if(!Re.test(t)){this.message={kind:`error`,text:x(`mcpServers.nameInvalid`)},this.host.element.requestUpdate();return}let n=Le(e.target,e.transport);if(!n){this.message={kind:`error`,text:x(`mcpServers.targetInvalid`)},this.host.element.requestUpdate();return}await this.mutateServers({buildPatch:e=>He(e,t,n),note:`plugins: add MCP server ${t}`,successText:x(`mcpServers.addedSuccess`,{name:t})})&&(this.formOpen=!1,this.host.element.requestUpdate())}async toggleServer(e,t){await this.mutateServers({buildPatch:n=>Be(n,e,t),note:`plugins: ${t?`enable`:`disable`} MCP server ${e}`,successText:x(t?`mcpServers.enabledSuccess`:`mcpServers.disabledSuccess`,{name:e})})}async removeServer(e){await this.mutateServers({buildPatch:t=>Ve(t,e),note:`plugins: remove MCP server ${e}`,successText:x(`mcpServers.removedSuccess`,{name:e})})}async addConnector(e){if(e.action.kind!==`mcp`)return;let t=e.action.mcp,n=$t(e.id),r=t.followUp===`oauth`?x(`pluginsPage.connectorAddedOauth`,{name:e.name,command:`openclaw mcp login ${t.serverName}`}):t.followUp===`endpoint`?x(`pluginsPage.connectorAddedEndpoint`,{name:e.name}):x(`pluginsPage.connectorAddedReady`,{name:e.name});await this.mutateServers({buildPatch:e=>He(e,t.serverName,structuredClone(t.config)),note:`plugins: add MCP connector ${t.serverName}`,successText:r,busyKey:n})&&(this.host.setRowMessage(n,{kind:`success`,text:r}),this.message=null,this.host.element.requestUpdate())}async mutateServers(e){if(!this.host.canMutate()||this.busy)return!1;let t=this.feedbackGeneration,n=this.host.getContext().runtimeConfig;this.busy=!0,this.busyKey=e.busyKey??null,e.busyKey&&(this.host.setRowBusy(e.busyKey,!0),this.host.setRowMessage(e.busyKey,null)),this.message=null,this.host.element.requestUpdate();let r=await Ue(n,{buildPatch:e.buildPatch,note:e.note});return t===this.feedbackGeneration&&(this.busy=!1,this.busyKey=null,e.busyKey&&this.host.setRowBusy(e.busyKey,!1),r.ok?(this.syncServers(),this.message={kind:`success`,text:e.successText},this.host.element.requestUpdate(),!0):(e.busyKey?this.host.setRowMessage(e.busyKey,{kind:`error`,text:r.error}):this.message={kind:`error`,text:r.error},this.host.element.requestUpdate(),!1))}}})))()}function Pn(e,t){if(!e)return e;let n=e.plugins.findIndex(e=>e.id===t.id),r=[...e.plugins];return n>=0?r[n]=t:r.push(t),{...e,plugins:r}}var $;function Fn(){return(Fn=e((()=>{o(),Pe(),m(),fe(),ye(),xe(),_e(),we(),pt(),b(),f(),j(),p(),rt(),re(),dt(),kt(),jn(),ht(),Nn(),O(),te(),Q(),$=class extends ae{constructor(...e){super(...e),this.result=null,this.error=null,this.activeTab=`installed`,this.query=``,this.installedFilter=`all`,this.debouncedSearchQuery=``,this.busy={},this.messages={},this.detail=null,this.iconUrls={},this.pageNotice=null,this.routeDataConsumed=!1,this.normalizedLocation=``,this.searchTimer=null,this.iconMisses=new Set,this.iconRequests=new Map,this.iconAuthCandidates=[],this.gateway=new nt(this,{getGateway:()=>this.context?.gateway,onIdentityChange:()=>{this.result=null,this.error=null,this.messages={},this.pageNotice=null},invalidateRequests:e=>this.invalidateRequests(e.snapshot.phase!==`connected`||!e.snapshot.client),onSnapshot:e=>this.handleGatewaySnapshot(e)}),this.consentController=new An({gateway:this.gateway,getContext:()=>this.context,getResult:()=>this.result,canMutate:()=>this.canMutate(),isBusy:e=>!!this.busy[e],setBusy:(e,t)=>this.setBusy(e,t),setMessage:(e,t)=>this.setMessage(e,t),clearPageNotice:()=>{this.pageNotice=null},closeDetails:()=>{this.detail=null},applyMutationResult:e=>this.applyMutationResult(e),refreshCatalogAfterMutation:e=>this.refreshCatalogAfterMutation(e),requestUpdate:()=>this.requestUpdate()}),this.catalogTask=new S(this,{autoRun:!1,args:()=>[this.gateway.connected?this.gateway.client:null],task:([e],{signal:t})=>e?e.request(`plugins.list`,{},{signal:t}):w,onComplete:e=>{this.replaceResult(e)},onError:e=>{this.error=u(e)}}),this.mcpController=new Mn({element:this,gateway:this.gateway,getContext:()=>this.context,canMutate:()=>this.canMutate(),setRowBusy:(e,t)=>this.setBusy(e,t),setRowMessage:(e,t)=>this.setMessage(e,t)}),this.searchTask=new S(this,{args:()=>[this.gateway.connected&&this.activeTab===`discover`?this.gateway.client:null,this.debouncedSearchQuery],task:async([e,t],{signal:n})=>!e||t.length<2?w:(await e.request(`plugins.search`,{query:t,limit:20},{signal:n})).results}),this.handleDocumentKeydown=e=>{if(!document.querySelector(`.shell-nav[aria-modal='true']`)&&e.key===`Escape`){if(this.consentController.consent){this.consentController.close(),e.stopPropagation();return}this.detail&&(this.detail=null,e.stopPropagation())}}}willUpdate(e){e.has(`routeData`)&&(this.applyRouteData(),this.syncCanonicalLocation())}connectedCallback(){super.connectedCallback(),document.addEventListener(`keydown`,this.handleDocumentKeydown,!0),this.syncCanonicalLocation()}disconnectedCallback(){document.removeEventListener(`keydown`,this.handleDocumentKeydown,!0),this.mcpController.disconnect(),this.clearSearchTimer(),this.resetPluginIcons(),super.disconnectedCallback()}handleGatewaySnapshot(e){let t=e.snapshot,n=ve({hello:t.hello,settings:{token:this.context.gateway.connection.token},password:this.context.gateway.connection.password}),r=n.length!==this.iconAuthCandidates.length||n.some((e,t)=>e!==this.iconAuthCandidates[t]);this.iconAuthCandidates=n;let i=!e.initial&&(e.identityChanged||e.connectionChanged||r)&&t.phase===`connected`&&this.routeDataConsumed;!e.initial&&r&&!e.identityChanged&&!e.connectionChanged&&(this.gateway.invalidate(),this.invalidateRequests(t.phase!==`connected`||!t.client)),!e.initial&&(e.identityChanged||e.connectionChanged||r)&&(this.resetPluginIcons(),this.busy={},this.mcpController.resetFeedback(),this.debouncedSearchQuery=``),i?this.mcpController.refreshPage(()=>this.refreshCatalog()):this.ensureInitialData(),this.mcpController.ensureLoaded(t.phase===`connected`),!e.initial&&(e.identityChanged||e.connectionChanged||r)&&t.phase===`connected`&&this.activeTab===`discover`&&this.scheduleSearch()}applyRouteData(){let e=this.routeData;if(!e)return;this.routeDataConsumed=!0;let t=ce(e.location,this.context.basePath);if(t!==this.activeTab&&this.changeTab(t),!this.gateway.isRouteDataCurrent(e)){this.ensureInitialData();return}this.replaceResult(e.result),this.error=e.error,this.ensureInitialData()}syncCanonicalLocation(){let e=this.context,t=this.routeData?.location;if(!e||!t)return;let n=ee(t,e.basePath);if(!n){this.normalizedLocation=``;return}let r=`${t.pathname}${t.search}${t.hash}`;this.normalizedLocation!==r&&(this.normalizedLocation=r,e.replace(`plugins`,n))}invalidateRequests(e=!0){this.clearSearchTimer(),this.debouncedSearchQuery=``,e&&this.catalogTask.run([null]),this.mcpController.invalidate(),this.searchTask.run([null,``]),this.detail=null,this.consentController.reset()}replaceResult(e,t=!1){t?this.reconcilePluginIcons(e):this.resetPluginIcons(),this.result=e,this.syncPluginIcons()}reconcilePluginIcons(e){let t=new Set((e?.plugins??[]).filter(e=>e.hasIcon&&!D(e.id)).map(e=>e.id)),n={...this.iconUrls},r=!1;for(let[e,i]of Object.entries(n))t.has(e)||(URL.revokeObjectURL(i),delete n[e],r=!0);r&&(this.iconUrls=n);for(let[e,n]of this.iconRequests)t.has(e)||(clearTimeout(n.timeout),n.controller.abort(),this.iconRequests.delete(e));for(let e of this.iconMisses)t.has(e)||this.iconMisses.delete(e)}resetPluginIcons(){for(let e of this.iconRequests.values())clearTimeout(e.timeout),e.controller.abort();for(let e of Object.values(this.iconUrls))URL.revokeObjectURL(e);this.iconRequests.clear(),this.iconMisses.clear(),this.iconUrls={}}syncPluginIcons(){for(let e of this.result?.plugins??[])!e.hasIcon||D(e.id)||this.iconUrls[e.id]||this.iconMisses.has(e.id)||this.iconRequests.has(e.id)||this.fetchPluginIcon(e.id)}fetchPluginIcon(e){let t=new AbortController,n=setTimeout(()=>t.abort(new DOMException(`plugin icon fetch timed out`,`TimeoutError`)),1e4),r={controller:t,timeout:n};this.iconRequests.set(e,r),ut({pluginId:e,resourceBasePath:this.context.resourceBasePath,gatewayUrl:this.context.gateway.connection.gatewayUrl,auth:{hello:this.context.gateway.snapshot.hello,settings:{token:this.context.gateway.connection.token},password:this.context.gateway.connection.password},signal:t.signal}).then(t=>{if(this.iconRequests.get(e)!==r||!this.isConnected){t&&URL.revokeObjectURL(t);return}t?this.iconUrls={...this.iconUrls,[e]:t}:this.iconMisses.add(e)}).catch(()=>{this.iconRequests.get(e)===r&&this.iconMisses.add(e)}).finally(()=>{clearTimeout(n),this.iconRequests.get(e)===r&&this.iconRequests.delete(e)})}handlePluginIconError(e){this.invalidatePluginIcon(e),this.iconMisses.add(e)}invalidatePluginIcon(e){let t=this.iconRequests.get(e);t&&(clearTimeout(t.timeout),t.controller.abort(),this.iconRequests.delete(e));let n=this.iconUrls[e];n&&URL.revokeObjectURL(n);let r={...this.iconUrls};delete r[e],this.iconUrls=r,this.iconMisses.delete(e)}clearSearchTimer(){this.searchTimer&&=(clearTimeout(this.searchTimer),null)}get loading(){return this.gateway.connected&&(!this.routeDataConsumed||this.catalogTask.status===C.PENDING)}get searchResults(){return this.searchTask.status===C.COMPLETE&&this.debouncedSearchQuery===this.query.trim()?this.searchTask.value??null:null}get searchLoading(){return this.activeTab===`discover`&&this.debouncedSearchQuery.length>=2&&this.searchTask.status===C.PENDING}get searchError(){return this.searchTask.status===C.ERROR&&this.debouncedSearchQuery===this.query.trim()?u(this.searchTask.error):null}ensureInitialData(){!this.routeDataConsumed||!this.gateway.connected||!this.gateway.client||this.loading||this.result||this.error||this.refreshCatalog()}async refreshCatalog(){let e=this.gateway.client;!e||!this.gateway.connected||(this.error=null,await this.catalogTask.run([e]))}selectHubTab(e){if(e===`installed`||e===`discover`){this.changeTab(e),this.context.navigate(`plugins`,{pathname:De(e,this.context.basePath)});return}this.context.navigate(e===`skills`?`skills`:`skill-workshop`)}changeTab(e){this.activeTab=e,this.clearSearchTimer(),this.debouncedSearchQuery=``,this.searchTask.run([null,``]),e===`discover`&&this.scheduleSearch()}changeQuery(e){this.query=e,this.clearSearchTimer(),this.debouncedSearchQuery=``,this.searchTask.run([null,``]),this.activeTab===`discover`&&this.scheduleSearch()}openClawHubSearch(e){this.query=e,this.changeTab(`discover`)}scheduleSearch(){let e=this.query.trim();e.length<2||!this.gateway.connected||!this.gateway.client||(this.searchTimer=setTimeout(()=>{this.searchTimer=null,this.searchClawHub(e)},300))}async searchClawHub(e){let t=this.gateway.client;!t||!this.gateway.connected||e.length<2||(this.debouncedSearchQuery=e,await this.searchTask.run([t,e]))}mutationBlockedReason(){if(!this.gateway.connected)return x(`pluginsPage.connectToChange`);let e=this.context.gateway.snapshot.hello?.auth??null;return be(e)?this.result&&!this.result.mutationAllowed?x(`pluginsPage.changesDisabled`):null:x(`pluginsPage.adminRequired`)}canMutate(){return!!this.result?.mutationAllowed&&this.mutationBlockedReason()===null}setBusy(e,t){let n={...this.busy};t?n[e]=!0:delete n[e],this.busy=n}setMessage(e,t){let n={...this.messages};t?n[e]=t:delete n[e],this.messages=n}applyMutationResult(e){this.invalidatePluginIcon(e.plugin.id),this.replaceResult(Pn(this.result,e.plugin),!0)}async refreshCatalogAfterMutation(e){this.error=null,await this.catalogTask.run([e])}async showDetails(e){let t=e?{pluginId:e,inspection:null,error:null}:null;this.detail=t;let n=e?this.result?.plugins.find(t=>t.id===e):void 0;if(!n?.installed||!t)return;let r=this.gateway.capture();if(r)try{let e=await Tt(r.client,n.id);this.gateway.isCurrent(r)&&this.detail===t&&(this.detail={...t,inspection:e})}catch(e){this.gateway.isCurrent(r)&&this.detail===t&&(this.detail={...t,error:u(e)})}}updateEnabled(e,t,n){return this.consentController.updateEnabled(e,t,n)}async uninstall(e,t){let n=this.result?.plugins.find(t=>t.id===e)?.name??e;await this.consentController.runMutation(t,t=>le(t,e),async(e,t,n,r,i)=>{i()&&(this.pageNotice={kind:`success`,text:[x(`pluginsPage.removedRestart`,{name:e.pluginId}),...(e.warnings??[]).map(e=>l(e)),t?x(`pluginsPage.configRefreshFailed`,{error:t}):null].filter(Boolean).join(`
`)}),await this.refreshCatalogAfterMutation(n)},{confirm:()=>Ot(n)})}render(){let e=this.mutationBlockedReason();return h`
      ${mt({active:this.activeTab,onSelect:e=>this.selectHubTab(e)})}
      ${ft(h`
        ${En({connected:this.gateway.connected,loading:this.loading,result:this.result,error:this.mcpController.pageError(this.error),activeTab:this.activeTab,query:this.query,installedFilter:this.installedFilter,searchResults:this.searchResults,searchLoading:this.searchLoading,searchError:this.searchError,busy:this.busy,messages:this.messages,detailPluginId:this.detail?.pluginId??null,detailInspection:this.detail?.inspection??null,detailInspectionError:this.detail?.error??null,consent:this.consentController.consent,consentInspection:this.consentController.inspection,consentInspectionLoading:this.consentController.inspectionLoading,consentInspectionError:this.consentController.inspectionError,iconUrls:this.iconUrls,canMutate:this.canMutate(),mutationBlockedReason:e,pageNotice:this.pageNotice,...this.mcpController.viewState,onQueryChange:e=>this.changeQuery(e),onFilterChange:e=>{this.installedFilter=e},onRefresh:()=>void this.mcpController.refreshPage(()=>this.refreshCatalog()),onIconError:e=>this.handlePluginIconError(e),onShowDetails:e=>void this.showDetails(e),onSetEnabled:(e,t,n)=>void this.updateEnabled(e,t,n),onInstall:(e,t)=>void this.consentController.install(e,t),onCancelConsent:()=>this.consentController.close(),onConfirmConsent:()=>this.consentController.confirm(),onRetryConsentInspection:()=>void this.consentController.inspect(),onDismissMessage:e=>this.setMessage(e,null),onUninstall:(e,t)=>void this.uninstall(e,t),onSearchClawHub:e=>this.openClawHubSearch(e)})}
      `)}
    `}},a([t({context:Ce,subscribe:!0})],$.prototype,`context`,void 0),a([he({attribute:!1})],$.prototype,`routeData`,void 0),a([g()],$.prototype,`result`,void 0),a([g()],$.prototype,`error`,void 0),a([g()],$.prototype,`activeTab`,void 0),a([g()],$.prototype,`query`,void 0),a([g()],$.prototype,`installedFilter`,void 0),a([g()],$.prototype,`debouncedSearchQuery`,void 0),a([g()],$.prototype,`busy`,void 0),a([g()],$.prototype,`messages`,void 0),a([g()],$.prototype,`detail`,void 0),a([g()],$.prototype,`iconUrls`,void 0),a([g()],$.prototype,`pageNotice`,void 0),customElements.get(`openclaw-plugins-page`)||customElements.define(`openclaw-plugins-page`,$)})))()}Fn();
//# sourceMappingURL=plugins-page-BxcoX8GP.js.map