openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
71 lines • 18.8 kB
JavaScript
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Ic as t,Lc as n,Lu as r,Pu as i,Rs as a,W as o,Xu as s,Yu as c,z as l,zs as u,zu as d}from"./control-ui-core-CBJ5efDh.js";import{Ar as f,Fr as p,Nr as m,Or as h,Pr as g,ba as _,ca as ee,da as te,jr as ne,la as re,sa as v,ya as ie}from"./control-ui-core-DtLivg_r.js";import{G as y,J as b,K as x,W as S,ct as C}from"./lit-runtime-IOnANfcZ.js";import{L as ae,U as oe}from"./control-ui-boot-shared-CkXlyZBY.js";import{At as se,jt as ce,kt as le}from"./control-ui-boot-shared-UG5ko-VG.js";import{Fo as w,N as ue,wa as T}from"./ui-CmSP4d14.js";import{F as de,M as fe,N as pe,j as me}from"./control-ui-boot-shared-VLPz5vN2.js";import{fa as he,pa as E}from"./control-ui-boot-shared-XreXSF7h.js";import{Al as D}from"./control-ui-boot-shared-dOnP4mAA.js";import{F as O,I as k,P as A}from"./control-ui-boot-chat-XPUNenUd.js";import{at as j,ot as M,st as N}from"./control-ui-boot-chat-CmENwCKi.js";import{a as P,i as F,n as I,o as L,r as R,s as ge,t as _e}from"./link-reader-response-2ZxZ1BKy.js";function ve(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,u=r.faviconDataUrl&&!i.has(r.faviconDataUrl)?r.faviconDataUrl:void 0;e.setAttribute(`aria-label`,c),x(b`<header class="link-hovercard__header">
<span class="link-hovercard__identity"
>${u?b`<img src=${u} alt="" =${()=>a(u)} =${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()}
>${d(`browser.openExternal`)}${v.externalLink}</a
>
</header>
${l?b`<img class="link-hovercard__image" src=${l} alt="" =${()=>a(l)} =${o} />`:y}
<section class="link-hovercard__body">
<div class="link-hovercard__title">${c}</div>
${r.description?b`<p class="link-hovercard__description">${r.description}</p>`:y}
</section>`,e)}function z(){return(z=e((()=>{S(),i(),ee()})))()}function B(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)&&!oe(n)?t.href:void 0}function ye(e,t){let n=T(t)?w(t.title):void 0;if(!T(t)||!n||typeof t.url!=`string`||!R(e,t.url))throw Error(`Invalid link preview response`);let r=T(t.badge)?t.badge:void 0,i=[`neutral`,`positive`,`negative`,`attention`,`accent`].find(e=>e===r?.tone),a=r&&typeof r.label==`string`&&i?{label:r.label,tone:i,timestamp:w(r.timestamp)}:void 0;return{url:t.url,title:n,subtitle:w(t.subtitle),badge:a,author:w(t.author),authorUrl:w(t.authorUrl),coAuthors:Array.isArray(t.coAuthors)?t.coAuthors.flatMap(e=>{let t=T(e)?w(e.name):void 0;return t&&T(e)?[{name:t,imageUrl:B(w(e.imageUrl))}]:[]}):void 0,coAuthorCount:typeof t.coAuthorCount==`number`&&Number.isSafeInteger(t.coAuthorCount)&&t.coAuthorCount>=0?t.coAuthorCount:void 0,createdAt:w(t.createdAt),updatedAt:w(t.updatedAt),imageUrl:B(w(t.imageUrl)),metadata:Array.isArray(t.metadata)?t.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 V(e,t=!1){let n=B(e);return n?b`<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)}}
/>`:y}function be(e){let t=e.coAuthors??[],n=Math.max(t.length,e.coAuthorCount??0);if(!n)return y;let r=t.filter(e=>B(e.imageUrl)).slice(0,3),i=n-r.length,a=n-t.length,o=t.map(e=>e.name).join(`, `)+(a?` +`+a:``),c=d(`linkReader.coAuthors`,{authors:o.trim()});return b`<span
class="link-reader-hovercard__coauthors"
role="img"
aria-label=${c}
title=${c}
>
${r.map(e=>b`<span class="link-reader-hovercard__coauthor" aria-hidden="true">
${s(e.name,1).toUpperCase()}${V(e.imageUrl,!0)}
</span>`)}
${i?b`<span class="link-reader-hovercard__coauthors-more">+${i}</span>`:y}
</span>`}function H(e,t,n,r=!1){return b`<a
class=${e}
href=${t}
target=${le}
rel=${se()}
?data-link-reader-external=${r}
>${n}</a
>`}function xe(e){e.dataset.loading=`true`,e.removeAttribute(`data-state`),e.removeAttribute(`data-cached`),e.setAttribute(`aria-label`,d(`linkReader.loadingPreview`)),x(b`<div class="link-reader-hovercard__skeleton" aria-hidden="true">
${[[`header`,[`badge`,`subtitle`,`time`]],[`title`,[`title`]],[`footer`,[`author`,`metadata`]]].map(([e,t])=>b`<div class=${`link-reader-hovercard__`+e}>${t.map(e=>b`<span class=${`skeleton link-reader-hovercard__placeholder--`+e}></span>`)}</div>`)}
</div>`,e)}function U(e){return b`<p class="link-reader-hovercard__error" role="status">${e}</p>`}function Se(e,t,n){e.dataset.loading=`false`,e.removeAttribute(`data-cached`),e.removeAttribute(`data-state`),e.setAttribute(`aria-label`,d(`linkReader.previewUnavailable`));let r=E(t.href),i=r?d(r.kind===`pull`?`linkReader.previewPullRequest`:`linkReader.previewIssue`,{number:String(r.number)}):t.reader.label;x(b`<div class="link-reader-hovercard__error-header">
<span class="link-reader-hovercard__error-source"
>${r?ie:y}<span>${i}</span></span
>
${H(`link-reader-hovercard__error-open`,t.href,b`${d(`linkReader.openExternal`,{provider:t.reader.label})}<span aria-hidden="true">${te.externalLink}</span>`)}
</div>
<div class="link-reader-hovercard__error-body">
<div class="link-reader-hovercard__title">${d(`linkReader.previewUnavailable`)}</div>
${U(n)}
</div>`,e)}function W(e,t,n=!1,r){e.dataset.loading=`false`,e.dataset.cached=String(n),e.dataset.state=t.badge?.tone??`neutral`;let i=t.updatedAt??t.createdAt,a=I(t.authorUrl,t.href),o=b`${V(t.imageUrl)}${t.author?b`<span class="link-reader-hovercard__author-name">${t.author}</span>`:y}`;x(b`<div class="link-reader-hovercard__header">
${t.badge?b`<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>`:y}
${H(`link-reader-hovercard__subtitle`,t.href,t.subtitle??t.reader.label)}
${n?b`<span class="link-reader-hovercard__time">${d(`linkReader.cachedPreview`)}</span>`:i?b`<time class="link-reader-hovercard__time" datetime=${i}>${l(Date.parse(i))}</time>`:y}
</div>
${H(`link-reader-hovercard__title`,t.href,t.title)}
<div class="link-reader-hovercard__footer">
${t.author||t.imageUrl?a?H(`link-reader-hovercard__author`,a,o,!0):b`<span class="link-reader-hovercard__author">${o}</span>`:y}
${be(t)}
<span class="link-reader-hovercard__metadata"
>${t.metadata?.map(({label:e,value:t,tone:n})=>b`<span class="link-reader-hovercard__metric" data-tone=${n??y}>${e?e+`: `:``}${t}</span>`)}</span
>
</div>
${r?U(r):y}`,e),e.setAttribute(`aria-label`,d(`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((()=>{ae(),S(),i(),ce(),o(),c(),he(),_(),re(),_e(),K=new WeakMap})))()}var J,Y,X,Z,Q;function $(){return($=e((()=>{me(),S(),i(),L(),O(),n(),F(),z(),q(),ne(),N(),ge(),J=3e5,Y=3e4,X=100,Z=0,Q=class e extends C{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=h,this.subscriptions=new t(this),this.gatewayClient=null,this.readerDescriptors=h,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 j(()=>this.close()),this.stopI18n=null,this.previewTask=new fe(this,{autoRun:!1,args:()=>[this.activeTarget],task:async([e],{signal:t})=>e?{...await this.loadPreview(e,t),...e}:pe}),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=a(e),n=t?g(t,this):null;t&&n&&this.activateFromBootstrap(t,n,`pointer`,250)},this.handlePointerOut=e=>{let t=a(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=a(e),n=t?g(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.watchStore(()=>this.pagePreviewContext?.gateway,()=>this.retirePage()),this.subscriptions.watchStore(()=>this.pagePreviewContext?.config,()=>{this.client&&!this.pagePreviewContext?.config.current.automaticallyFetchFavicons&&A(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=p(t.url,[e.reader]);return n&&m(n)===m(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=p(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??=r.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===de.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??M(`openclaw-link-reader-hovercard-`+ ++Z,`link-reader-hovercard`);t?W(a,t,n,r):r&&this.activeTarget?Se(a,this.activeTarget,r):xe(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),this.hovercard.markTrigger(e),this.hovercard.mount(e,t,`vertical`,!0,()=>x(y,t)))}ownsAnchor(t){let n=u(t);for(;n&&!(n instanceof e);)n=u(n);return n===this}currentPage(e){let t=g(e.anchor,this);return this.isConnected&&this.page===e&&e.anchor.isConnected&&this.ownsAnchor(e.anchor)&&!(!t||t.reader||t.href!==e.href)&&f(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&&f(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),k(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??M(`openclaw-link-preview-`+ ++Z,`link-hovercard`);ve(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(m(e));return t&&!t.controller.signal.aborted&&t.expiresAt>Date.now()?t:void 0}loadPreview(e,t){let n=m(e),r=Date.now(),i=this.cachedPreview(e);if(this.cache.delete(n),i)return this.cache.set(n,i),D(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 ye(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})};return this.cache.set(n,l),this.syncInlineStates(),ue(this.cache,X),D(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};