openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
37 lines • 11.5 kB
JavaScript
import{n as e}from"./rolldown-runtime-8BhlS34s.js";import{Ac as t,Bs as n,Eu as r,Ft as i,It as a,Rs as o,Su as s,Tu as c,Vs as l,du as u,ju as d,kc as f,pu as p}from"./control-ui-core-BncvAZjR.js";import{Ti as m,wi as h,xr as g,yr as _}from"./control-ui-core-9qYjK5B2.js";import{$ as v,X as y,Y as b,ct as x,d as ee,nt as S,u as C,ut as w}from"./lit-runtime-B8uOr6OX.js";import{$t as T,Ft as E,Pt as D,Qt as O,Xr as k,Xt as A,Zr as j,Zt as M,en as N,ii as P,ma as F}from"./ui-DuRgK6kL.js";import{F as I,L,R as te}from"./control-ui-boot-chat-Ck7W_FPO.js";import{l as R,u as z}from"./control-ui-boot-chat-BPMc7uzL.js";import{_n as B,dn as V,sn as H,un as U}from"./control-ui-boot-chat-C8hdsB2M.js";import{a as W,i as G,n as K,t as q}from"./widget-sandbox-host-BtiBzdny.js";function J(e){let t=Z.get(e.client);(!t||t.generation!==e.generation)&&(t={generation:e.generation,requests:new Map},Z.set(e.client,t));let n=t.requests.get(e.docId);if(n)return n;let r=e.client.request(`canvas.document.view`,{docId:e.docId},{timeoutMs:K});if(t.requests.size<32){let n=t.requests;n.set(e.docId,r),r.finally(()=>n.delete(e.docId)).catch(()=>{})}return r}var Y,X,Z,Q;function $(){return($=e((()=>{j(),N(),A(),b(),S(),C(),m(),g(),r(),a(),p(),o(),E(),W(),I(),c(),t(),z(),V(),Y=new Set,X=6e5,Z=new WeakMap,Q=class extends s{constructor(){super(),this.docId=``,this.sessionKey=``,this.title=``,this.connectionGeneration=0,this.error=``,this.runtimeError=``,this.resourceError=!1,this.sandboxOrigin=``,this.scrollNonce=``,this.scriptsAllowed=!0,this.sandboxGeneration=0,this.retryDelayMs=1e3,this.pending=!1,this.handleMessage=e=>{let t=this.sandboxHost,n=this.viewOwner;if(!t||!this.sameOwner(n)||e.source!==t.frame.contentWindow||e.origin!==this.sandboxOrigin)return;t.handleMessage(e);let r=F(e.data);if(r?.type===`openclaw:widget-scroll`&&this.scrollNonce&&r.nonce===this.scrollNonce&&typeof r.deltaY==`number`&&Number.isFinite(r.deltaY)){R(new WheelEvent(`wheel`,{deltaY:r.deltaY,cancelable:!0}),this.closest(`.chat-thread`));return}if(r?.type===`openclaw:widget-runtime-error`){if(!this.sessionKey||typeof r.message!=`string`)return;if(!this.isCurrent(this.validated)||!navigator.onLine||/failed to fetch|load failed|networkerror|network request failed|importing a module script failed|failed to load module script/i.test(r.message)){this.resourceError=!0;return}let e={message:r.message.slice(0,500),line:typeof r.line==`number`&&Number.isInteger(r.line)?r.line:void 0,column:typeof r.column==`number`&&Number.isInteger(r.column)?r.column:void 0};this.runtimeError||=e.message;let t=this.messageTimestamp;if(typeof t!=`number`||!Number.isFinite(t)||Date.now()-t>X)return;let i=`error\0${this.sessionKey}\0${n.docId}`;if(Y.has(i)||!H(i,Date.now()))return;Y.add(i);let a=e.line===void 0?``:`, line ${e.line}${e.column===void 0?``:`, column ${e.column}`}`,o=`Inline widget "${this.title.slice(0,80)}" (${n.docId}) threw a script error after rendering: ${e.message}${a}. Fix the script and show the widget again; if show_widget is unavailable in this turn, reply with the corrected widget code and show it on the next turn.`;n.client.request(`wake`,{mode:`now`,sessionKey:this.sessionKey,text:o}).catch(e=>console.warn(`Widget runtime error wake failed`,e));return}if(r?.type===`openclaw:widget-size`&&typeof r.height==`number`&&Number.isFinite(r.height)&&r.height>0&&(this.contentHeight=Math.min(8e3,Math.max(48,Math.trunc(r.height)))),r?.type===`openclaw:widget-bridge-ready`&&this.postHostState(),r?.type!==`openclaw:widget-prompt-offer`){r?.type===`openclaw:widget-bridge-port-offer`&&e.ports[0]?.close();return}let i=e.ports[0];if(!i||this.promptPort||!t.loaded){i?.close();return}this.promptPort=i,i.addEventListener(`message`,e=>{this.isCurrent(this.validated)&&this.sandboxHost===t&&this.promptPort===i&&e.data?.type===`openclaw:widget-prompt`&&U(t.frame,e.data.prompt,`${this.sessionKey}\0${this.docId}\0${this.validated.generation}`)}),i.start(),i.postMessage({type:`openclaw:widget-prompt-host-ready`})},new f(this).watchStore(()=>this.context?.gateway)}clearRetry(){window.clearTimeout(this.slowTimer),this.slowTimer=void 0,window.clearTimeout(this.retryTimer),this.retryTimer=void 0}scheduleRetry(e,t=0){this.retryTimer===void 0&&(this.pending=!0,this.retryTimer=window.setTimeout(()=>{this.retryTimer=void 0,this.isCurrent(e)&&(this.binding=void 0,this.requestUpdate())},M(Math.max(this.retryDelayMs,t))),this.retryDelayMs=Math.min(this.retryDelayMs*2,3e4))}get allowScripts(){return this.scriptsAllowed}set allowScripts(e){e!==this.scriptsAllowed&&(this.clearSandbox(),this.sandboxGeneration+=1,this.view&&(this.error=``),this.scriptsAllowed=e)}get documentHtml(){return this.sameOwner(this.viewOwner)?this.view?.html:void 0}connectedCallback(){super.connectedCallback(),window.addEventListener(`message`,this.handleMessage)}disconnectedCallback(){window.removeEventListener(`message`,this.handleMessage),this.clearView(),super.disconnectedCallback()}clearView(){this.clearRetry(),this.validated=void 0,this.viewOwner=void 0,this.sandboxGeneration+=1,this.runtimeError=``,this.resourceError=!1,this.binding=void 0,this.view=void 0,this.clearSandbox()}clearSandbox(){this.scrollNonce=``,this.sandboxHost?.dispose(),this.sandboxHost=void 0,this.promptPort?.close(),this.promptPort=void 0,this.releaseTheme?.(),this.releaseTheme=void 0,this.contentHeight=void 0}sameOwner(e){let t=this.context?.gateway,n=t?.snapshot;return!(!e||!t||!n||e.client!==n.client||e.docId!==this.docId||e.sessionKey!==this.sessionKey||e.connectionRevision!==t.connectionRevision||e.gatewayUrl!==t.connection.gatewayUrl||n.lastErrorAuthReason||n.phase===`stopped`||n.phase===`connected`&&(e.profileId&&n.selfUser?.id&&e.profileId!==n.selfUser.id||e.recoveryScope!==n.hello?.auth?.recoveryScope||!_(n.hello?.auth??null)))}isCurrent(e){return this.sameOwner(e)&&this.isConnected&&this.binding===e&&l(this.context.gateway.snapshot)&&e.generation===i()}willUpdate(){let e=this.context?.gateway,t=e?.snapshot.client;if((this.binding&&!this.sameOwner(this.binding)||this.viewOwner&&!this.sameOwner(this.viewOwner))&&this.clearView(),!e||!t||!this.docId){this.clearView();return}if(!l(e.snapshot)){this.binding=void 0,this.clearRetry(),this.validated=void 0,this.sandboxHost?.setActive(!1),this.pending=!0;return}if(!_(e.snapshot.hello?.auth??null)){this.error=d(`board.widget.sandboxUnavailable`);return}let r=e.snapshot.selfUser?.id;r&&(this.binding&&!this.binding.profileId&&(this.binding.profileId=r),this.viewOwner&&!this.viewOwner.profileId&&(this.viewOwner.profileId=r));let a=i();if(this.binding?.generation===a)return;this.clearRetry(),this.validated=void 0,this.error=``;let o={client:t,docId:this.docId,sessionKey:this.sessionKey,generation:a,connectionRevision:e.connectionRevision,gatewayUrl:e.connection.gatewayUrl,profileId:e.snapshot.selfUser?.id??this.viewOwner?.profileId??null,recoveryScope:e.snapshot.hello?.auth?.recoveryScope};this.binding=o,this.pending=!!this.view,this.slowTimer=window.setTimeout(()=>{this.isCurrent(o)&&(this.pending=!0)},q),J(o).then(e=>{if(!this.isCurrent(o))return;this.clearRetry();let t=this.view;t&&(t.html!==e.html||t.sandboxUrl!==e.sandboxUrl||t.sandboxPort!==e.sandboxPort||t.sandboxOrigin!==e.sandboxOrigin)&&(this.clearSandbox(),this.runtimeError=``,this.resourceError=!1,this.sandboxGeneration+=1),this.view=e,this.viewOwner=o,this.validated=o,this.pending=!1,this.retryDelayMs=1e3,this.sandboxHost?.setActive(!0)}).catch(t=>{if(this.isCurrent(o)){if(this.clearRetry(),n(t,e.snapshot)||t instanceof T||t instanceof O&&t.gatewayCode===`UNAVAILABLE`&&t.retryable){this.scheduleRetry(o,t instanceof O?t.retryAfterMs:void 0);return}this.view=void 0,this.clearSandbox(),this.pending=!1,this.error=u(t)}})}updated(){let e=this.querySelector(`iframe`),t=this.view,n=this.binding;this.allowScripts&&e&&t&&this.isCurrent(n)&&!this.sandboxHost&&(this.releaseTheme=te(e,this.sandboxOrigin),this.scrollNonce=D(),this.sandboxHost=new G({frame:e,sandboxOrigin:this.sandboxOrigin,sandboxUrl:e.src,documentKey:`${n.docId}\0${n.generation}`,loadDocument:async()=>t.html,onLoaded:()=>{this.pending=!1,this.postHostState()},onRendered:()=>this.postHostState(),onError:e=>this.fail(e),onReadyTimeout:()=>{this.pending=!0},onPending:()=>{this.pending=!0}}))}fail(e){this.clearSandbox(),this.error=u(e)}postHostState(){let e=this.sandboxHost?.frame;e&&(L(e,this.sandboxOrigin),e.contentWindow?.postMessage({type:`openclaw:widget-chat-host`},this.sandboxOrigin),e.contentWindow?.postMessage({type:`openclaw:widget-board-host`,nonce:this.scrollNonce},this.sandboxOrigin))}render(){if(this.error)return v`<div class="board-widget__error" role="alert">
${this.error}
<button
class="btn btn--small"
=${()=>{this.clearView(),this.requestUpdate()}}
>
${d(`common.retry`)}
</button>
</div>`;if(!this.view||!this.context)return this.pending?v`<div
class="board-widget__notice"
role="status"
style=${`min-height:${this.preferredHeight??420}px`}
>
${d(`board.widget.waitingForConnection`)}
</div>`:v`<div
class="skeleton"
role="status"
aria-label=${d(`common.loading`)}
style=${`min-height:${this.preferredHeight??420}px`}
></div>`;let e;try{this.allowScripts&&(e=B(this.view.sandboxUrl,this.view.sandboxPort,this.view.sandboxOrigin,this.context.gateway.connection.gatewayUrl,window.location.origin),this.sandboxOrigin=new URL(e).origin)}catch(e){return v`<div role="alert">${u(e)}</div>`}let t=this.contentHeight??this.preferredHeight;return ee(this.sandboxGeneration,v`${this.pending?v`<div class="board-widget__notice" role="status">${d(`board.widget.waitingForConnection`)}</div>`:y}${this.resourceError?v`<div class="board-widget__notice" role="status">
${d(`board.widget.resourceUnavailable`)}
<button
class="btn btn--small"
=${()=>{this.clearView(),this.requestUpdate()}}
>
${d(`common.retry`)}
</button>
</div>`:y}${this.runtimeError?v`<div class="board-widget__notice" role="status">${d(`board.widget.runtimeError`,{message:this.runtimeError})}</div>`:y}<iframe
class="chat-tool-card__preview-frame"
title=${this.title}
src=${e??y}
srcdoc=${this.allowScripts?y:this.view.html}
sandbox=${this.allowScripts?`allow-scripts allow-same-origin allow-forms`:``}
referrerpolicy="origin"
style=${t?`height:${t}px;min-height:${t}px`:y}
=${()=>this.sandboxHost?.handleFrameError()}
></iframe>`)}},P([k({context:h,subscribe:!0})],Q.prototype,`context`,void 0),P([w()],Q.prototype,`docId`,void 0),P([w()],Q.prototype,`sessionKey`,void 0),P([w({type:Number})],Q.prototype,`messageTimestamp`,void 0),P([w()],Q.prototype,`title`,void 0),P([w({type:Number})],Q.prototype,`preferredHeight`,void 0),P([w({type:Number})],Q.prototype,`connectionGeneration`,void 0),P([x()],Q.prototype,`view`,void 0),P([x()],Q.prototype,`error`,void 0),P([x()],Q.prototype,`runtimeError`,void 0),P([x()],Q.prototype,`resourceError`,void 0),P([x()],Q.prototype,`contentHeight`,void 0),P([x()],Q.prototype,`pending`,void 0),P([w({type:Boolean})],Q.prototype,`allowScripts`,null),customElements.get(`openclaw-canvas-widget-view`)||customElements.define(`openclaw-canvas-widget-view`,Q)})))()}$();export{Q as OpenClawCanvasWidgetView};