openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
71 lines • 18.9 kB
JavaScript
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Ji as t,io as n}from"./control-ui-foundation-ZY_Flbbd.js";import{Eu as r,N as i,R as a,Tu as o,_s as s,cc as c,gs as l,hu as u,pu as d,sc as ee,uu as f}from"./control-ui-core-3P365fbR.js";import{Cr as p,Dr as m,Er as h,Or as g,Qi as _,Xi as v,Zi as te,ea as ne,oa as re,sa as ie,wr as y,xr as b}from"./control-ui-core-CFW9Qtjn.js";import{$ as x,X as S,Y as C,Z as w,pt as ae}from"./lit-runtime-P5vbNq6b.js";import{F as oe,V as se}from"./control-ui-boot-shared-3SP_aL-Y.js";import{Ca as T,Gn as ce,Kn as le,bi as ue,qn as de,xi as fe,yi as pe}from"./control-ui-boot-shared-DoKu-5Ju.js";import{L as me,R as E,V as D,z as O}from"./control-ui-boot-shared-DBJri5ri.js";import{Fo as k,Io as A,Xn as j,Yn as M,Zn as N}from"./control-ui-boot-shared-CG9HtEG-.js";import{a as P,i as F,n as I,o as L,r as R,s as z,t as he}from"./link-reader-response-Cct0r21o.js";function ge(e,t,n,r,i,a,o){let s=new URL(t).host,c=r.title||n||s,l=r.imageDataUrl&&!i.has(r.imageDataUrl)?r.imageDataUrl:void 0,d=r.faviconDataUrl&&!i.has(r.faviconDataUrl)?r.faviconDataUrl:void 0;e.setAttribute(`aria-label`,c),w(x`<header class="link-hovercard__header">
<span class="link-hovercard__identity"
>${d?x`<img src=${d} alt="" =${()=>a(d)} =${o} />`:v.globe}<span
>${s}</span
></span
>
<a
class="link-hovercard__open"
href=${t}
target="_blank"
rel="noopener noreferrer"
data-link-reader-external
=${e=>e.stopPropagation()}
>${u(`browser.openExternal`)}${v.externalLink}</a
>
</header>
${l?x`<img class="link-hovercard__image" src=${l} alt="" =${()=>a(l)} =${o} />`:S}
<section class="link-hovercard__body">
<div class="link-hovercard__title">${c}</div>
${r.description?x`<p class="link-hovercard__description">${r.description}</p>`:S}
</section>`,e)}function B(){return(B=e((()=>{C(),f(),te()})))()}function V(e){if(!e)return;if(/^data:image\/(?:gif|jpeg|png|webp);base64,/u.test(e))return e;let t=URL.parse(e),n=t?.hostname.replace(/\.+$/u,``)??``;return t?.protocol===`https:`&&!t.username&&!t.password&&t.origin!==window.location.origin&&n.includes(`.`)&&!/(?:^|\.)(?:localhost|local|internal|localdomain)$/u.test(n)&&!se(n)?t.href:void 0}function _e(e,r){let i=t(r)?n(r.title):void 0;if(!t(r)||!i||typeof r.url!=`string`||!R(e,r.url))throw Error(`Invalid link preview response`);let a=t(r.badge)?r.badge:void 0,o=[`neutral`,`positive`,`negative`,`attention`,`accent`].find(e=>e===a?.tone),s=a&&typeof a.label==`string`&&o?{label:a.label,tone:o,timestamp:n(a.timestamp)}:void 0;return{url:r.url,title:i,subtitle:n(r.subtitle),badge:s,author:n(r.author),authorUrl:n(r.authorUrl),coAuthors:Array.isArray(r.coAuthors)?r.coAuthors.flatMap(e=>{let r=t(e)?n(e.name):void 0;return r&&t(e)?[{name:r,imageUrl:V(n(e.imageUrl))}]:[]}):void 0,coAuthorCount:typeof r.coAuthorCount==`number`&&Number.isSafeInteger(r.coAuthorCount)&&r.coAuthorCount>=0?r.coAuthorCount:void 0,createdAt:n(r.createdAt),updatedAt:n(r.updatedAt),imageUrl:V(n(r.imageUrl)),metadata:Array.isArray(r.metadata)?r.metadata.flatMap(e=>t(e)&&typeof e.label==`string`&&typeof e.value==`string`?[{label:e.label,value:e.value,tone:e.tone===`positive`||e.tone===`negative`?e.tone:void 0}]:[]):void 0}}function H(e,t=!1){let n=V(e);return n?x`<img
class="link-reader-hovercard__image"
alt=""
decoding="async"
crossorigin="anonymous"
referrerpolicy="no-referrer"
src=${n}
=${e=>{e.currentTarget instanceof HTMLImageElement&&(t?e.currentTarget.hidden=!0:e.currentTarget.remove())}}
=${e=>{t&&e.currentTarget instanceof HTMLImageElement&&(e.currentTarget.hidden=!1)}}
/>`:S}function ve(e){let t=e.coAuthors??[],n=Math.max(t.length,e.coAuthorCount??0);if(!n)return S;let i=t.filter(e=>V(e.imageUrl)).slice(0,3),a=n-i.length,o=n-t.length,s=t.map(e=>e.name).join(`, `)+(o?` +`+o:``),c=u(`linkReader.coAuthors`,{authors:s.trim()});return x`<span
class="link-reader-hovercard__coauthors"
role="img"
aria-label=${c}
title=${c}
>
${i.map(e=>x`<span class="link-reader-hovercard__coauthor" aria-hidden="true">
${r(e.name,1).toUpperCase()}${H(e.imageUrl,!0)}
</span>`)}
${a?x`<span class="link-reader-hovercard__coauthors-more">+${a}</span>`:S}
</span>`}function U(e,t,n,r=!1){return x`<a
class=${e}
href=${t}
target=${pe}
rel=${ue()}
?data-link-reader-external=${r}
>${n}</a
>`}function ye(e){e.dataset.loading=`true`,e.removeAttribute(`data-state`),e.removeAttribute(`data-cached`),e.setAttribute(`aria-label`,u(`linkReader.loadingPreview`)),w(x`<div class="link-reader-hovercard__skeleton" aria-hidden="true">
${[[`header`,[`badge`,`subtitle`,`time`]],[`title`,[`title`]],[`footer`,[`author`,`metadata`]]].map(([e,t])=>x`<div class=${`link-reader-hovercard__`+e}>${t.map(e=>x`<span class=${`skeleton link-reader-hovercard__placeholder--`+e}></span>`)}</div>`)}
</div>`,e)}function W(e){return x`<p class="link-reader-hovercard__error" role="status">${e}</p>`}function be(e,t,n){e.dataset.loading=`false`,e.removeAttribute(`data-cached`),e.removeAttribute(`data-state`),e.setAttribute(`aria-label`,u(`linkReader.previewUnavailable`));let r=A(t.href),i=r?u(r.kind===`pull`?`linkReader.previewPullRequest`:`linkReader.previewIssue`,{number:String(r.number)}):t.reader.label;w(x`<div class="link-reader-hovercard__error-header">
<span class="link-reader-hovercard__error-source"
>${r?re:S}<span>${i}</span></span
>
${U(`link-reader-hovercard__error-open`,t.href,x`${u(`linkReader.openExternal`,{provider:t.reader.label})}<span aria-hidden="true">${ne.externalLink}</span>`)}
</div>
<div class="link-reader-hovercard__error-body">
<div class="link-reader-hovercard__title">${u(`linkReader.previewUnavailable`)}</div>
${W(n)}
</div>`,e)}function xe(e,t,n=!1,r){e.dataset.loading=`false`,e.dataset.cached=String(n),e.dataset.state=t.badge?.tone??`neutral`;let a=t.updatedAt??t.createdAt,o=I(t.authorUrl,t.href),s=x`${H(t.imageUrl)}${t.author?x`<span class="link-reader-hovercard__author-name">${t.author}</span>`:S}`;w(x`<div class="link-reader-hovercard__header">
${t.badge?x`<span class="link-reader-hovercard__state" data-tone=${t.badge.tone}><span class="link-reader-hovercard__state-dot" aria-hidden="true"></span>${t.badge.label}</span>`:S}
${U(`link-reader-hovercard__subtitle`,t.href,t.subtitle??t.reader.label)}
${n?x`<span class="link-reader-hovercard__time">${u(`linkReader.cachedPreview`)}</span>`:a?x`<time class="link-reader-hovercard__time" datetime=${a}>${i(Date.parse(a))}</time>`:S}
</div>
${U(`link-reader-hovercard__title`,t.href,t.title)}
<div class="link-reader-hovercard__footer">
${t.author||t.imageUrl?o?U(`link-reader-hovercard__author`,o,s,!0):x`<span class="link-reader-hovercard__author">${s}</span>`:S}
${ve(t)}
<span class="link-reader-hovercard__metadata"
>${t.metadata?.map(({label:e,value:t,tone:n})=>x`<span class="link-reader-hovercard__metric" data-tone=${n??S}>${e?e+`: `:``}${t}</span>`)}</span
>
</div>
${r?W(r):S}`,e),e.setAttribute(`aria-label`,u(`linkReader.previewAriaLabel`,{title:t.title}))}function G(e,t){let n=K.get(e);n||(n=new Map,K.set(e,n));let r=t??``,i=n.get(r);return(!i||i.generation!==e.connectionGeneration||i.recoveryScope!==e.recoveryScope)&&(i={generation:e.connectionGeneration,recoveryScope:e.recoveryScope,succeeded:!1},n.set(r,i)),i}var K;function q(){return(q=e((()=>{oe(),C(),f(),fe(),a(),o(),k(),ie(),_(),he(),K=new WeakMap})))()}var J,Y,X,Z,Q;function $(){return($=e((()=>{me(),C(),f(),L(),le(),c(),F(),B(),q(),y(),N(),z(),J=3e5,Y=3e4,X=100,Z=0,Q=class e extends ae{static{this.properties={client:{attribute:!1,noAccessor:!0},agentId:{attribute:!1,noAccessor:!0},readers:{attribute:!1,noAccessor:!0},previewSeeds:{attribute:!1,noAccessor:!0},pagePreviewContext:{attribute:!1},claimedReaders:{attribute:!1,noAccessor:!0}}}get claimedReaders(){return this.allReaders}set claimedReaders(e){e.length===this.allReaders.length&&e.every((e,t)=>e===this.allReaders[t])||(this.allReaders=e,this.retirePage())}constructor(){super(),this.page=null,this.allReaders=b,this.subscriptions=new ee(this),this.gatewayClient=null,this.readerDescriptors=b,this.seeds=null,this.cache=new Map,this.previewContext=null,this.allowLoading=!1,this.requestStarted=!1,this.inlineObserver=new MutationObserver(()=>this.syncInlineStates()),this.activeAnchor=null,this.activeTarget=null,this.activeTrigger=null,this.hovercard=new M(()=>this.close()),this.stopI18n=null,this.previewTask=new E(this,{autoRun:!1,args:()=>[this.activeTarget],task:async([e],{signal:t})=>e?{...await this.loadPreview(e,t),...e}:O}),this.activeAnchorObserver=new MutationObserver(()=>{if(this.page){this.retirePage();return}let e=this.activeAnchor;e&&(!this.ownsAnchor(e)||e.href!==this.activeTarget?.href)&&this.close()}),this.handlePointerOver=e=>{if(e.pointerType===`touch`)return;let t=l(e),n=t?m(t,this):null;t&&n&&this.activateFromBootstrap(t,n,`pointer`,250)},this.handlePointerOut=e=>{let t=l(e);if(t&&t===this.activeAnchor&&!(e.relatedTarget instanceof Node&&t.contains(e.relatedTarget))){if(this.page){this.hovercard.schedulePointerExit();return}this.hovercard.pointerInside=!1,this.scheduleIntentClose()}},this.handleCardPointerLeave=()=>{this.hovercard.pointerOverCard=!1,this.activeTrigger===`pointer`&&(this.hovercard.cardFocusInside=!1),this.hovercard.scheduleClose()},this.handleFocusIn=e=>{if(this.hovercard.restoringFocus)return;let t=l(e),n=t?m(t,this):null;t&&n&&(n.reader||t.matches(`:focus-visible`))&&this.activateFromBootstrap(t,n,`focus`,0)},this.handleFocusOut=e=>{this.activeAnchor&&(e.relatedTarget instanceof Node&&this.activeAnchor.contains(e.relatedTarget)||(this.hovercard.focusInside=!1,this.scheduleIntentClose()))},this.handleClick=()=>{this.close()},this.subscriptions.watch(()=>this.pagePreviewContext?.gateway,(e,t)=>e.subscribe(t),()=>this.retirePage()),this.subscriptions.watch(()=>this.pagePreviewContext?.config,(e,t)=>e.subscribe(t),()=>{this.client&&!this.pagePreviewContext?.config.current.automaticallyFetchFavicons&&ce(this.client),this.retirePage()})}get readers(){return this.readerDescriptors}set readers(e){e.length===this.readerDescriptors.length&&e.every((e,t)=>e===this.readerDescriptors[t])||(this.invalidatePreviewContext(),this.readerDescriptors=e,this.dispatchEvent(new Event(`link-reader-capabilities-changed`)))}get previewSeeds(){return this.seeds?.previews??[]}set previewSeeds(e){this.seeds={client:this.client,agentId:this.agentId,generation:this.client?.connectionGeneration,recoveryScope:this.client?.recoveryScope,previews:e},this.requestUpdate()}seedPreview(e){let t=this.seeds;if(!t||t.client!==this.client||t.agentId!==this.agentId||t.generation!==this.client?.connectionGeneration||t.recoveryScope!==this.client?.recoveryScope)return;let n=t.previews.find(t=>{let n=g(t.url,[e.reader]);return n&&h(n)===h(e)});return n?{...n,...e}:void 0}get client(){return this.gatewayClient}set client(e){e!==this.gatewayClient&&(this.invalidatePreviewContext(),this.gatewayClient=e,this.dispatchEvent(new Event(`link-reader-capabilities-changed`)))}get agentId(){return this.selectedAgentId}set agentId(e){e!==this.selectedAgentId&&(this.invalidatePreviewContext(),this.selectedAgentId=e,this.dispatchEvent(new Event(`link-reader-capabilities-changed`)))}invalidatePreviewContext(){this.seeds=null,this.previewContext=null,this.close(),this.clearPreviews()}syncPreviewContext(){let e=this.client?G(this.client,this.agentId):null;return e!==this.previewContext&&(this.previewContext=e,this.close(),this.clearPreviews()),e}syncInlineStates(){this.syncPreviewContext();for(let e of this.querySelectorAll(`a.markdown-github-item`)){if(!this.ownsAnchor(e))continue;let t=g(e.href,this.readers),n=t?this.cachedPreview(t)?.preview:void 0;n?.badge?(e.setAttribute(`aria-description`,n.badge.label),e.dataset.linkReaderTone=n.badge.tone):(delete e.dataset.linkReaderTone,e.removeAttribute(`aria-description`))}}clearPreviews(){for(let e of this.cache.values())e.controller.abort();this.cache.clear(),this.syncInlineStates()}async prefetch(e,t){this.isConnected&&this.client?.connected&&this.readers.includes(e.reader)&&e.reader.linkReader.previewMethod&&!t.aborted&&(this.syncPreviewContext(),await this.loadPreview(e,t),t.aborted||this.syncInlineStates())}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),this.style.display=`contents`,this.inlineObserver.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`href`]}),this.addEventListener(`pointerover`,this.handlePointerOver),this.addEventListener(`pointerout`,this.handlePointerOut),this.addEventListener(`focusin`,this.handleFocusIn),this.addEventListener(`focusout`,this.handleFocusOut),this.addEventListener(`keydown`,this.hovercard.handleTriggerKeyDown),this.addEventListener(`click`,this.handleClick),this.stopI18n??=d.subscribe(()=>this.requestUpdate())}disconnectedCallback(){this.removeEventListener(`pointerover`,this.handlePointerOver),this.removeEventListener(`pointerout`,this.handlePointerOut),this.removeEventListener(`focusin`,this.handleFocusIn),this.removeEventListener(`focusout`,this.handleFocusOut),this.removeEventListener(`keydown`,this.hovercard.handleTriggerKeyDown),this.removeEventListener(`click`,this.handleClick),this.inlineObserver.disconnect(),this.stopI18n?.(),this.stopI18n=null,this.close(),this.clearPreviews(),super.disconnectedCallback()}updated(){let e=this.syncPreviewContext();if(this.syncInlineStates(),this.page){this.retirePage(),this.page&&this.hovercard.card&&this.showPage(this.page);return}let t=this.activeAnchor,n=this.activeTarget;if(t&&n&&this.requestStarted){if(!this.isConnected||!this.ownsAnchor(t)||t.href!==n.href){this.close();return}this.previewTask.render({pending:()=>{let r=this.seedPreview(n);this.hovercard.held&&(r?this.show(t,r,!0):this.allowLoading&&e?.succeeded&&this.show(t))},complete:e=>{e.href===n.href&&(this.hovercard.card||this.hovercard.held)&&this.show(t,e)},error:e=>{(this.hovercard.card||this.hovercard.held)&&this.show(t,this.seedPreview(n),!0,P(e))}})}}scheduleIntentClose(){this.previewTask.status===D.PENDING&&!this.hovercard.held?this.close():this.hovercard.scheduleClose()}activateFromBootstrap(e,t,n,r){if(this.ownsAnchor(e)){if(!t.reader){this.activatePage(e,t,n,r);return}this.client&&this.readers.includes(t.reader)&&t.reader.linkReader.previewMethod&&(this.activate(e,t,r),this.activeTrigger=n,n===`pointer`?this.hovercard.pointerInside=!0:this.hovercard.focusInside=!0)}}activate(e,t,n){let r=this.syncPreviewContext();(e!==this.activeAnchor||this.activeTarget?.href!==t.href)&&(this.close(),this.allowLoading=!(!r?.succeeded||this.cachedPreview(t)),this.activeAnchor=e,this.activeTarget=t,this.activeAnchorObserver.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`href`]}),this.hovercard.scheduleOpen(n,()=>{if(this.syncPreviewContext()!==r)return;this.requestStarted=!0;let n=this.seedPreview(t);n&&this.show(e,n,!0),this.previewTask.run([t])},e))}show(e,t,n=!1,r){let i=this.hovercard.card,a=i??j(`openclaw-link-reader-hovercard-`+ ++Z,`link-reader-hovercard`);t?xe(a,t,n,r):r&&this.activeTarget?be(a,this.activeTarget,r):ye(a),this.mountPreview(e,a,!!i),t&&!n&&this.previewContext&&(this.previewContext.succeeded=!0)}mountPreview(e,t,n){n?this.hovercard.position():(t.addEventListener(`pointerleave`,this.handleCardPointerLeave),t.addEventListener(`keydown`,this.hovercard.handleCardKeyDown),this.hovercard.markTrigger(e),this.hovercard.mount(e,t,`vertical`,!0,()=>w(S,t)))}ownsAnchor(t){let n=s(t);for(;n&&!(n instanceof e);)n=s(n);return n===this}currentPage(e){let t=m(e.anchor,this);return this.isConnected&&this.page===e&&e.anchor.isConnected&&this.ownsAnchor(e.anchor)&&!(!t||t.reader||t.href!==e.href)&&p(this)&&this.client===e.client&&e.client.connectionGeneration===e.generation&&e.client.recoveryScope===e.recoveryScope}retirePage(){this.page&&!this.currentPage(this.page)&&this.close()}activatePage(e,t,n,r){let i=this.client;if(i&&p(this)){if(this.syncPreviewContext(),this.retirePage(),this.page?.anchor!==e||this.page.href!==t.href){this.close();let n={anchor:e,href:t.href,client:i,generation:i.connectionGeneration,recoveryScope:i.recoveryScope,controller:new AbortController,preview:{},failedImages:new Set};this.page=n,this.activeAnchor=e,this.activeAnchorObserver.observe(this,{childList:!0,subtree:!0,attributes:!0,attributeFilter:[`href`,`download`,`data-file-path`,`data-session-href`,`data-link-reader-external`,`class`,`hidden`]});let a=e.getRootNode();a instanceof ShadowRoot&&this.activeAnchorObserver.observe(a,{childList:!0,subtree:!0,attributes:!0}),this.hovercard.scheduleOpen(r,()=>{if(!this.currentPage(n)){this.close();return}this.showPage(n),de(i,n.href,n.controller.signal).then(e=>{this.currentPage(n)&&(n.preview=e,this.showPage(n))}).catch(()=>{})},e)}this.activeTrigger=n,n===`pointer`?this.hovercard.pointerInside=!0:this.hovercard.focusInside=!0,this.hovercard.clearClose()}}showPage(e){let t=this.hovercard.card,n=t??j(`openclaw-link-preview-`+ ++Z,`link-hovercard`);ge(n,e.href,e.anchor.textContent?.trim()??``,e.preview,e.failedImages,t=>{this.currentPage(e)&&(e.failedImages.add(t),this.showPage(e))},()=>this.hovercard.position()),this.mountPreview(e.anchor,n,!!t)}cachedPreview(e){let t=this.cache.get(h(e));return t&&!t.controller.signal.aborted&&t.expiresAt>Date.now()?t:void 0}loadPreview(e,t){let n=h(e),r=Date.now(),i=this.cachedPreview(e);if(this.cache.delete(n),i)return this.cache.set(n,i),T(i,{},t);let a=new AbortController,o=this.client,s=this.previewContext,c=this.agentId,l={expiresAt:r+J,controller:a,subscribers:new Set,promise:(async()=>{let t=e.reader.linkReader.previewMethod;if(!o||!t||!this.readers.includes(e.reader))throw Error(`Link preview requires an available reader`);return _e(e,await o.request(t,{...c?{agentId:c}:{},url:e.href},{signal:a.signal}))})().then(e=>(!a.signal.aborted&&this.cache.get(n)===l&&o===this.client&&c===this.agentId&&o&&G(o,c)===s&&(l.preview=e,this.syncInlineStates()),e)).catch(e=>{throw l.expiresAt=Date.now()+Y,this.syncInlineStates(),e})};for(this.cache.set(n,l),this.syncInlineStates();this.cache.size>X;){let e=this.cache.keys().next().value;if(!e)break;this.cache.delete(e)}return T(l,{},t)}close(){this.page?.controller.abort(),this.page=null,this.requestStarted=!1,this.allowLoading=!1,this.hovercard.reset(),this.activeAnchorObserver.disconnect(),this.previewTask.run([null]),this.activeAnchor=null,this.activeTarget=null,this.activeTrigger=null}}})))()}$();export{Q as LinkReaderHovercardProvider};