UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

160 lines • 14.2 kB
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Eu as t,Fs as n,Sl as r,ai as i,fi as a,il as o,ju as s,nl as c,rl as l}from"./control-ui-core-BncvAZjR.js";import{Fa as u,La as d,Na as f,Oa as p,Pa as m,Ra as h,Sa as g,So as _,Xi as v,Zi as y,ba as ee,c as b,ga as te,ha as ne,ja as x,ka as re,mo as S,na as C,ra as w,s as ie,sa as ae,ua as oe,wa as T,yo as se,za as ce}from"./control-ui-core-9qYjK5B2.js";import{$ as E,X as D,Y as O,ct as le,nt as ue,ut as de}from"./lit-runtime-B8uOr6OX.js";import{_a as fe,ia as pe,ii as k,ro as A,wo as j}from"./ui-DuRgK6kL.js";import{_i as M,h as N}from"./control-ui-boot-shared-xfDhIVun.js";import"./control-ui-boot-shared-styles-BaQ2sAfZ.js";import{n as P,t as F}from"./en-settings-KEcvGj5Z.js";import{a as I,o as L}from"./settings-targets-B_ZHOn2L.js";import{i as R,n as z,r as B,t as me}from"./config-form.tiers-CqQphhDm.js";import{n as he,o as ge,r as _e}from"./config-form.search-DJEvDtN5.js";import{c as V,g as ve,i as ye,m as be,o as xe,r as Se}from"./setup-schema-CsxjHw97.js";function Ce(e,t){let n=s(e.labelKey),r=t?Object.entries(e.nativeSearchKeys??{}).filter(([,e])=>e(t)).map(([e])=>e):[];return{routeId:e.routeId,...e.search===void 0?{}:{search:e.search},hash:e.hash,label:n,searchText:[n,...[...e.searchKeys,...r].map(e=>s(e)),e.aliases??``].join(` `)}}function we(e,t){let n=U[e],r=t.properties;if(!n||!r)return t;let i=new Set(n);return{...t,properties:Object.fromEntries(Object.entries(r).filter(([e])=>i.has(e)))}}function Te(e){if(!e.query.trim())return[];let t=ge(e.query),n=t.tags.length===0&&t.text?H.filter(t=>(e.identityAvailable||!t.requiresIdentity)&&(e.multipleProfiles||!t.requiresMultipleProfiles)&&(e.nativeDeviceSettings||!t.requiresNativeDeviceSettings)&&p(t.routeId,e.canAdmin!==!1,e.nativeDeviceSettings)).map(t=>Ce(t,e.nativeDeviceSettings?.snapshot??null)).filter(e=>u(e.searchText,t.text)):[],r=fe(e.schema)?e.schema:null;if(!r||a(r)!==`object`||!r.properties)return n;let i=W.get(r);(!i||i.hints!==e.uiHints)&&(i={hints:e.uiHints,sections:new Map},W.set(r,i));let o=e.value??{};for(let[t,a]of Object.entries(r.properties)){let r=be(t);if(!p(r,e.canAdmin!==!1,e.nativeDeviceSettings))continue;let s=i.sections.get(t);if(!s){let n=t===`wizard`?ye(a):we(r,a);s={schema:n,tiers:z({schema:n,path:[t],hints:e.uiHints})},i.sections.set(t,s)}let{schema:c,tiers:l}=s,d=B[t],f=n=>!!(n&&_e({key:t,schema:n,value:o[t],hints:e.uiHints,query:e.query,label:d?.label,description:d?.description,textMatcher:u})),m=f(l.common),h=f(l.advanced);if(!m&&!h)continue;let g=encodeURIComponent(t),_=`#config-section-${g}`;n.push({routeId:r,label:d?.label??c.title??t,...r===`memory`?{pathname:se(`settings`,e.basePath),hash:_}:r===`plugin-settings`?{search:`?tab=advanced`,hash:`#plugin-settings-advanced`}:{search:`?section=${g}${h||t===`wizard`?`&advanced=1`:``}`,hash:_}})}return n}var H,U,W;function G(){return(G=e((()=>{T(),S(),R(),he(),me(),t(),F(),i(),ve(),V(),L(),Se(),P(),H=Object.values(I),U={memory:xe,"plugin-settings":[`enabled`,`allow`,`deny`,`load`,`slots`],updates:[`channel`,`checkOnStart`,`auto`]},W=new WeakMap})))()}function K(e,t){return E`<button class="btn btn--xs settings-save-indicator__action" type="button" @click=${t} > ${e} </button>`}var q,J;function Y(){return(Y=e((()=>{O(),ue(),t(),w(),ae(),q=2e3,J=class extends pe{constructor(...e){super(...e),this.savedVisible=!1}createRenderRoot(){return this}willUpdate(){let e=this.props?.status;this.previousStatus===`saving`&&e===`saved`?(this.clearSavedTimer(),this.savedVisible=!0,this.savedTimer=globalThis.setTimeout(()=>{this.savedTimer=void 0,this.savedVisible=!1},q)):e!==`saved`&&(this.clearSavedTimer(),this.savedVisible=!1),this.previousStatus=e}disconnectedCallback(){this.clearSavedTimer(),super.disconnectedCallback()}clearSavedTimer(){globalThis.clearTimeout(this.savedTimer),this.savedTimer=void 0}renderClaw(e){return E`<span class="settings-save-indicator__claw ${e}" aria-hidden="true" >${oe().mascot===`none`?C.mark:C.claw}</span >`}render(){let e=this.props;if(!e)return D;let t,n=``,r=``,i=``;if(e.applying)t=E` <span class="settings-save-indicator__spinner" aria-hidden="true" >${C.loader}</span > <span>${s(`configView.applying`)}</span>`;else if(e.status===`saving`)t=E` ${this.renderClaw(`settings-save-indicator__claw--saving`)} <span>${s(`configView.autoSaveSaving`)}</span>`;else if(e.status===`recovery`)n=` settings-save-indicator--danger settings-save-indicator--recovery`,t=E`<span>${e.lastError}</span> ${K(s(`configView.recoveryReload`),e.onReload)}`;else if(e.status===`rejected`)n=` settings-save-indicator--rejected`,t=E`<span>${s(`configView.autoSaveRejected`)}</span> <span>${s(`configView.autoSaveRejectedHint`)}</span> ${e.lastError?E`<details> <summary>${s(`configView.rejectionDetails`)}</summary> <span>${e.lastError}</span> </details>`:D} ${K(s(`configView.retry`),e.onRetry)} ${K(s(`configView.recoveryReload`),e.onReload)}`;else if(e.status===`error`)i=e.lastError?.trim()??``,r=i?`${s(`configView.autoSaveFailed`)}: ${i}`:``,n=` settings-save-indicator--danger`,t=E` <span>${s(`configView.autoSaveFailed`)}</span> ${K(s(`configView.retry`),e.onRetry)}`;else if(e.status===`paused`)t=E` <span>${s(`configView.autoSavePaused`)}</span> ${K(s(`configView.saveNow`),e.onSave)}`;else if(e.status===`conflict`)n=` settings-save-indicator--danger`,t=E` <span>${s(`configView.autoSaveConflict`)}</span> ${K(s(`common.reload`),e.onReload)}`;else if(this.savedVisible)n=` settings-save-indicator--saved`,t=E` ${this.renderClaw(`settings-save-indicator__claw--saved`)} <span class="settings-save-indicator__check" aria-hidden="true">${C.check}</span> <span>${s(`configView.autoSaveSaved`)}</span>`;else if(e.needsApply)t=E` <button class="btn btn--xs settings-save-indicator__apply" type="button" ?disabled=${e.applyDisabled} @click=${e.onApply} > ${s(`configView.applyChanges`)} </button>`;else return D;return E`<div class="settings-save-indicator${n}" role="status" aria-live="polite" aria-label=${r||D} title=${i||D} > ${t} </div>`}},k([de({attribute:!1})],J.prototype,`props`,void 0),k([le()],J.prototype,`savedVisible`,void 0),customElements.get(`openclaw-settings-save-indicator`)||customElements.define(`openclaw-settings-save-indicator`,J)})))()}function Ee(e,t){if(t.pathname)return!1;let n=j(t.label);return[f(e),h(e)].some(e=>j(e)===n)}function De(e,t,n,r){let i=ce(n,r),a=t.filter(e=>p(e.routeId,n,r)),o=j(e);if(!o)return i.map(e=>({labelKey:e.labelKey,items:e.routes.map(e=>({routeId:e,blocks:[]}))}));let c=i.flatMap(e=>e.routes),l=[...new Set([...c,...ee.filter(e=>p(e,n,r)),...a.map(e=>e.routeId)])],m=l.filter(e=>[f(e),h(e),d(e)].some(e=>u(e,o))),g=new Set(m),_=i.flatMap(e=>e.labelKey&&u(s(e.labelKey),o)?e.routes.filter(e=>!g.has(e)&&(g.add(e),!0)):[]),v=new Map,y=new Set;for(let e of a){let t=`${e.routeId}\u0000${e.pathname??``}\u0000${e.search??``}\u0000${e.hash}`;if(y.has(t))continue;y.add(t);let n=v.get(e.routeId)??[];n.push(e),v.set(e.routeId,n)}let b=[...m,..._];return[...b.length>0?[{labelKey:null,items:b.map(e=>({routeId:e,blocks:(v.get(e)??[]).filter(t=>!Ee(e,t))}))}]:[],...l.filter(e=>!g.has(e)&&v.has(e)).map(e=>({labelKey:null,items:[{routeId:e,blocks:v.get(e)??[]}]}))]}function Oe(e,t){let r=m(e.activeRouteId)===t;return E` <a href=${_(t,e.basePath)} class="settings-sidebar__item ${r?`settings-sidebar__item--active`:``}" aria-current=${r?`page`:D} @focus=${n=>x(e.preloadTimers,t,n,e.onPreload,r)} @blur=${t=>g(e.preloadTimers,t)} @pointerenter=${n=>x(e.preloadTimers,t,n,e.onPreload,r)} @pointerleave=${t=>g(e.preloadTimers,t)} @touchstart=${{handleEvent:n=>x(e.preloadTimers,t,n,e.onPreload,r,!0),passive:!0}} @click=${r=>{n(r)&&(r.preventDefault(),e.onNavigate(t))}} > <span class="settings-sidebar__item-icon" aria-hidden="true" >${C[re(t)]}</span > <span class="settings-sidebar__item-label" >${f(t,e.nativeDeviceSettings?.snapshot)}</span > ${e.presentation===`embed-list`?E`<span class="settings-row__chevron" aria-hidden="true">${C.chevronRight}</span>`:D} </a> `}function ke(e,t){let r=(t.pathname??_(t.routeId,e.basePath))+(t.search??``)+t.hash,i=e.activeRouteId===t.routeId&&(t.pathname===void 0||e.activePathname===t.pathname)&&e.activeHash===t.hash&&(t.search===void 0||e.activeSearch===t.search);return E` <a href=${r} class="settings-sidebar__subitem ${i?`settings-sidebar__subitem--active`:``}" aria-current=${i?`location`:D} @click=${r=>{n(r)&&(r.preventDefault(),e.onNavigate(t.routeId,{...t.pathname?{pathname:t.pathname}:{},...t.search?{search:t.search}:{},hash:t.hash}))}} > <span class="settings-sidebar__subitem-label">${t.label}</span> </a> `}function Ae(e){e.closest(`.settings-sidebar`)?.querySelector(`.settings-sidebar__search`)?.classList.toggle(`settings-sidebar__search--scrolled`,e.scrollTop>0)}function je(e){let t=new Map(e.map(e=>[e.id,e])),n=new Map,r=[];for(let i of e){let e=i.creatorAgentId;if(e&&e!==i.id&&t.has(e)){let t=n.get(e)??[];t.push(i),n.set(e,t)}else r.push(i)}let i=[],a=new Set,o=(e,t)=>{if(!a.has(e.id)){a.add(e.id),i.push({agent:e,...t>0&&e.creatorAgentId?{creatorAgentId:e.creatorAgentId}:{}});for(let r of n.get(e.id)??[])o(r,t+1)}};return r.forEach(e=>o(e,0)),e.forEach(e=>o(e,0)),i}function X(e){let t=l(e.agents).map(e=>Object.assign({},e,{id:A(e.id),creatorAgentId:e.creatorAgentId?A(e.creatorAgentId):e.creatorAgentId})),n=je(t).map(({agent:e,creatorAgentId:t})=>({value:e.id,label:o(e),agent:e,description:t?s(`agents.createdBy`,{id:t}):void 0}));return E`<div class="settings-sidebar__agent"> <openclaw-agent-select .options=${n} .identityById=${Object.fromEntries(e.agentIdentity.entries().map(e=>[e.agentId,e]))} .value=${e.settingsAgentSelection.state.selectedId??``} .accessibleLabel=${s(`agentScope.label`)} .menuLabel=${s(`agentScope.label`)} .disabled=${n.length<=1} .onSelect=${t=>e.settingsAgentSelection.set(t)} @wa-show=${()=>void e.agentIdentity.ensure(t.map(e=>e.id))} ></openclaw-agent-select> </div>`}function Z(e){return e.connectionStatus===null?E`<openclaw-settings-save-indicator .props=${e.saveIndicator} ></openclaw-settings-save-indicator>`:b({kind:e.connectionStatus,lastError:e.lastError,onRetry:e.onRetryConnect})}function Q(e){return E`<header class="native-embed-header"> ${e.presentation===`embed-page`?E`<button class="native-embed-header__back btn btn--ghost" type="button" aria-label=${s(`common.back`)} @click=${e.onExit} > <span aria-hidden="true">${C.chevronLeft}</span>${s(`common.back`)} </button>`:D} <h1 class="page-title"> ${e.presentation===`embed-list`?s(`nav.settings`):f(e.activeRouteId,e.nativeDeviceSettings?.snapshot)} </h1> ${Z(e)} </header>`}function Me(e){if(e.presentation===`embed-page`)return E`${Q(e)} ${X(e)}`;let t=e.searchBlockMatches??(e.searchParams?Te(e.searchParams):[]),n=De(e.searchQuery,t,e.canAdmin!==!1,e.nativeDeviceSettings??null),r=E` <nav class="settings-sidebar__nav" aria-label=${s(`common.settingsSections`)} @scroll=${e=>Ae(e.currentTarget)} > ${n.length===0?E`<p class="settings-sidebar__empty" role="status"> ${s(`nav.settingsSearchNoResults`)} </p>`:n.map(t=>E` <div class="settings-sidebar__group"> ${t.labelKey?E`<div class="settings-sidebar__group-label">${s(t.labelKey)}</div>`:D} ${t.items.map(t=>E` ${Oe(e,t.routeId)} ${t.blocks.map(t=>ke(e,t))} `)} </div> `)} </nav>`;return e.presentation===`embed-list`?E`<section class="settings-embed-list"> ${Q(e)} ${X(e)} ${r} </section>`:E` <aside class="settings-sidebar"> <header class="settings-sidebar__header" @mousedown=${ne}> <button type="button" class="settings-sidebar__back" @click=${()=>e.onExit()}> <span class="settings-sidebar__back-icon" aria-hidden="true">${C.arrowLeft}</span> ${s(`nav.exitSettings`)} ${y(`esc`,{className:`settings-sidebar__esc`,ariaHidden:!0})} </button> <h1 class="settings-sidebar__title">${s(`nav.settings`)}</h1> </header> ${X(e)} <div class="settings-sidebar__search" role="search"> <span class="settings-sidebar__search-icon" aria-hidden="true">${C.search}</span> <input class="settings-sidebar__search-input" type="search" autocomplete="off" spellcheck="false" aria-label=${s(`nav.settingsSearchLabel`)} placeholder=${s(`nav.settingsSearchPlaceholder`)} .value=${e.searchQuery} @input=${t=>e.onSearchQueryChange(t.currentTarget.value)} @keydown=${t=>{if(t.key===`Escape`){if(t.preventDefault(),e.searchQuery){e.onSearchQueryChange(``);return}e.onExit()}}} /> ${e.searchQuery?E` <button type="button" class="settings-sidebar__search-clear" aria-label=${s(`nav.settingsSearchClear`)} @click=${t=>{let n=t.currentTarget.parentElement?.querySelector(`input`);e.onSearchQueryChange(``),n?.focus()}} > ${C.x} </button> `:D} </div> ${r} <footer class="settings-sidebar__footer"> ${Z(e)} <openclaw-sidebar-build-chip .basePath=${e.basePath} .gatewayVersion=${e.gatewayVersion||null} .variant=${`settings`} .onNavigate=${()=>e.onNavigate(`about`)} ></openclaw-sidebar-build-chip> </footer> </aside> `}function $(){return($=e((()=>{O(),T(),S(),te(),t(),c(),r(),G(),ie(),w(),v(),M(),Y(),N()})))()}$();export{Me as renderSettingsSidebar};