UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

616 lines 43.7 kB
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./rfb-3fIY7_Ix.js","./rolldown-runtime-DkW27tQK.js"])))=>i.map(i=>d[i]); import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{ii as t,ri as n,wr as r}from"./control-ui-foundation-Cydpkyqa.js";import{As as i,Bn as a,Do as o,Eo as s,Oo as c,Sc as ee,ca as te,ua as ne,ws as re,xc as ie,zn as ae}from"./control-ui-core-Rwzhj6nO.js";import{$ as oe,K as l,Q as se,X as u,at as d,dt as f,q as p,st as m}from"./lit-runtime-CV_MH99K.js";import{F as h,Gt as g,Kt as ce,V as le,Wt as _,Yt as v,an as ue,en as y,in as b,l as de,qt as fe,u as pe}from"./control-ui-core-vvcQQV2m.js";import{cn as x,sn as S}from"./control-ui-boot-chat-_QSl8fbH.js";import{c as me,l as he}from"./control-ui-boot-chat-Bia0O-uD.js";import{n as ge,r as C,t as _e}from"./dock-layout-controller-DJtLlZ8p.js";import{n as ve,t as ye}from"./scrollbar-styles-Cosje8h4.js";import{n as be,t as xe}from"./desktop-focus-window-CY5JuBq7.js";var w,T;function E(){return(E=e((()=>{ue(),w={desktop:{title:b.desktop.title,openWindow:b.desktop.openWindow,unavailable:b.desktop.unavailable,toggle:b.desktop.toggle,hide:`Hide desktop panel`,resize:`Resize desktop panel`,dockBottom:`Dock to bottom`,dockRight:`Dock to right`,enterFullscreen:`Enter fullscreen`,exitFullscreen:`Exit fullscreen`,fullscreenUnavailable:`Fullscreen is unavailable in this browser`,pickerTitle:`Desktop sources`,thisMachine:`This machine`,refresh:`Refresh`,refreshing:`Refreshing…`,loading:`Loading desktop sources…`,empty:`No desktop-capable sources are available.`,sourceUnavailable:`The requested desktop source is unavailable. Choose another source.`,connect:`Connect`,connecting:`Connecting to desktop…`,takeControl:`Take control`,switchToViewOnly:`Switch to view only`,viewOnly:`View only`,control:`Control`,keyboard:`Keyboard`,keyboardInput:`Remote desktop keyboard input`,touchControls:`Remote desktop controls`,fit:`Fit`,fitScreen:`Fit screen`,actualSize:`Use actual size`,back:`Back`,disconnect:`Disconnect`,reconnect:b.desktop.reconnect,passwordPrompt:`Enter the VNC password for this machine.`,passwordLabel:`VNC password`,accountPrompt:`Enter a macOS account to authenticate Screen Sharing.`,usernameLabel:`macOS username`,accountPasswordLabel:`macOS password`,controlTaken:`Another operator took control`,disconnected:`Desktop disconnected: {reason}`,closeCode:`connection closed with code {code}`,unknownReason:`unknown reason`,errors:{listFailed:`Could not load desktop sources: {error}`,fullscreenFailed:`Could not change fullscreen mode: {error}`,securityFailed:`Desktop security negotiation failed: {reason}`,connectionFailed:`Reconnect. If it fails again, check the browser console and desktop service logs.`}}},T=Object.assign(()=>Object.assign(b.desktop,w.desktop),{catalog:w})})))()}function Se(e,t=globalThis.location?.href){let n=new URL(t??globalThis.location.href,globalThis.location?.href);n.protocol===`http:`?n.protocol=`ws:`:n.protocol===`https:`&&(n.protocol=`wss:`);let r=new URL(e,n);if(r.protocol===`http:`?r.protocol=`ws:`:r.protocol===`https:`&&(r.protocol=`wss:`),r.protocol!==`ws:`&&r.protocol!==`wss:`)throw Error(`Desktop observer URL must use WebSocket transport`);return r.toString()}var D,O;function k(){return(k=e((()=>{t(),D=async()=>(await n(()=>import(`./rfb-3fIY7_Ix.js`),__vite__mapDeps([0,1]),import.meta.url)).default,O=class{constructor(e,t=e=>new WebSocket(e),n=D){this.rfbConstructor=e,this.createWebSocket=t,this.loadRfb=n}async connect(e){let t=this.rfbConstructor??await this.loadRfb(),n=Se(e.wsUrl,e.gatewayUrl);if(!e.isCurrent())throw new DOMException(`Desktop connection is no longer current`,`AbortError`);let r=this.createWebSocket(n),i;r.addEventListener(`close`,e=>{i={code:e.code,reason:e.reason}});let a=new t(e.target,r,e.credentials?{credentials:e.credentials}:void 0);a.background=e.background??getComputedStyle(e.target).backgroundColor,a.viewOnly=e.viewOnly,a.scaleViewport=e.scaleViewport??!0;let o=!1;a.addEventListener(`connect`,()=>e.onConnect?.()),a.addEventListener(`disconnect`,t=>{o=!0;let{clean:n}=t.detail;e.onDisconnect?.({...i,clean:n})}),a.addEventListener(`securityfailure`,t=>{let n=t.detail??{};e.onSecurityFailure?.(n)});let s=t=>{e.target.querySelector(`canvas`)?.dispatchEvent(t)},c=e=>new KeyboardEvent(e.type,{key:e.key,code:e.code,location:e.location,ctrlKey:e.ctrlKey,shiftKey:e.shiftKey,altKey:e.altKey,metaKey:e.metaKey,repeat:e.repeat,isComposing:e.isComposing,bubbles:!0,cancelable:!0});return{disconnect:()=>{o||(o=!0,a.disconnect())},disableInput:()=>{a.viewOnly=!0},setScaleViewport:e=>{a.scaleViewport=e},sendKeyboardEvent:e=>s(c(e)),sendText:e=>{let t=e.replace(/\r\n?/g,` `);for(let e=0;e<t.length;e+=1)s(new KeyboardEvent(`keydown`,{key:t.charAt(e)===` `?`Enter`:t.charAt(e),code:`Unidentified`,bubbles:!0,cancelable:!0}))},sendBackspace:()=>{for(let e of[`keydown`,`keyup`])s(new KeyboardEvent(e,{key:`Backspace`,code:`Backspace`,bubbles:!0,cancelable:!0}))}}}}})))()}function Ce(e){return y(e===`browser`?`browser.title`:`terminal.title`)}function we(e){return e===`browser`?_.chrome:_.terminal}function A(){return(A=e((()=>{v(),g()})))()}function j(e){return e.id===`gateway`?{kind:`host`}:e.id.startsWith(`node:`)&&e.id.length>5?{kind:`node`,nodeId:e.id.slice(5)}:{kind:`environment`,environmentId:e.id}}function M(e){return u` <div class="desktop-content"> ${e.notice} ${e.state===`picker`?e.picker:e.state===`inventory-error`||e.state===`disconnected`?e.recovery:e.state===`credentials`?e.credentials:e.connection} </div> `}function Te(e){return u` <header class="rail-header bp-header"> <div class="rail-header__title bp-title">${y(`desktop.title`)}</div> <div class="rail-header__actions bp-actions"> <button class="rail-header__action bp-icon ${e.dock===`bottom`?`is-active`:``}" type="button" title=${y(`desktop.dockBottom`)} aria-label=${y(`desktop.dockBottom`)} @click=${()=>e.onDock(`bottom`)} > ${_.panelBottomOpen} </button> <button class="rail-header__action bp-icon ${e.dock===`right`?`is-active`:``}" type="button" title=${y(`desktop.dockRight`)} aria-label=${y(`desktop.dockRight`)} @click=${()=>e.onDock(`right`)} > ${_.panelRightOpen} </button> <button class="rail-header__action bp-icon bp-open-window" type="button" title=${y(`desktop.openWindow`)} aria-label=${y(`desktop.openWindow`)} @click=${e.onOpenWindow} > ${_.externalLink} </button> ${e.fullscreenControl} <button class="rail-header__action bp-icon" type="button" title=${y(`desktop.hide`)} aria-label=${y(`desktop.hide`)} @click=${e.onClose} > ${_.x} </button> </div> </header> `}function Ee(e){return u` <div class="desktop-toolbar"> <span>${y(`desktop.pickerTitle`)}</span> <span class="desktop-toolbar__spacer"></span> <button class="desktop-button" type="button" ?disabled=${e.loading} @click=${e.onRefresh} > ${e.loading?y(`desktop.refreshing`):y(`desktop.refresh`)} </button> </div> <div class="desktop-picker"> ${e.loading&&e.environments.length===0?x(`desktop`,y(`desktop.loading`)):e.environments.length===0?u`<div class="desktop-status">${y(`desktop.empty`)}</div>`:e.environments.map(t=>De(t,e.onConnect))} </div> `}function De(e,t){let n=e.worker,r=j(e);return u` <div class="desktop-environment"> <div class="desktop-environment__details"> <div class="desktop-environment__id"> ${r.kind===`host`?y(`desktop.thisMachine`):e.id} </div> <div class="desktop-environment__meta"> <span>${n?.state??e.status}</span> </div> ${n&&n.attachedSessionIds.length>0?u`<div class="desktop-environment__sessions"> ${n.attachedSessionIds.map(e=>u`<span class="desktop-session">${e}</span>`)} </div>`:p} </div> <button class="desktop-button desktop-button--primary" type="button" @click=${()=>t(e.id)} > ${y(`desktop.connect`)} </button> </div> `}function Oe(e){return u` <div class="desktop-status"> <form class="desktop-credentials" @submit=${e.onSubmit}> <div>${y(e.ardAccount?`desktop.accountPrompt`:`desktop.passwordPrompt`)}</div> ${e.ardAccount?u`<label class="desktop-credentials__label"> ${y(`desktop.usernameLabel`)} <input class="desktop-credentials__input" name="username" type="text" autocomplete="off" .value=${e.username} required /> </label>`:p} <label class="desktop-credentials__label"> ${y(e.ardAccount?`desktop.accountPasswordLabel`:`desktop.passwordLabel`)} <input class="desktop-credentials__input" name="password" type="password" autocomplete="off" required /> </label> <button class="desktop-button desktop-button--primary" type="submit"> ${y(`desktop.connect`)} </button> </form> </div> `}function ke(e){return u` <div class="desktop-toolbar desktop-toolbar--connection"> ${e.showApps&&e.desktopApps.length>0?u`<div class="desktop-apps"> ${e.desktopApps.map(t=>{let n=e.launchingApp===t,r=Ce(t);return u`<button class="desktop-app-button" type="button" title=${r} aria-label=${r} aria-busy=${n?`true`:`false`} ?disabled=${!e.environmentSelected||n} @click=${()=>e.onLaunch(t)} > <span class="desktop-app-button__icon ${n?`desktop-app-button__icon--launching`:``}" aria-hidden="true" > ${we(t)} </span> <span>${r}</span> </button>`})} </div>`:p} <span class="desktop-toolbar__spacer"></span> <button class="desktop-toolbar-action" type="button" title=${y(`desktop.disconnect`)} aria-label=${y(`desktop.disconnect`)} @click=${e.onDisconnect} > ${y(`desktop.disconnect`)} </button> </div> <div class="desktop-stage"> <div class="desktop-surface"></div> ${e.controlling?p:u`<button class="desktop-stage__take-control" type="button" title=${y(`desktop.takeControl`)} aria-label=${y(`desktop.takeControl`)} @click=${e.onTakeControl} ></button>`} ${e.state===`connecting`?x(`desktop`,y(`desktop.connecting`),!1,!0):p} </div> `}function Ae(e,t){return e?u`<div class="desktop-note desktop-note--error" role="alert">${e}</div>`:t?u`<div class="desktop-note" role="status">${t}</div>`:p}function N(){return(N=e((()=>{l(),v(),E(),g(),S(),A(),T()})))()}function je(e){let t=u` <div class="desktop-stage"> <div class="desktop-surface"></div> ${e.state===`connecting`?x(`desktop`,y(`desktop.connecting`),!1,!0):p} <textarea class="desktop-keyboard-input" inputmode="text" autocomplete="off" autocapitalize="off" spellcheck="false" tabindex="-1" aria-label=${y(`desktop.keyboardInput`)} .value=${e.keyboardInputValue} @keydown=${e.onKeyboardEvent} @keyup=${e.onKeyboardEvent} @input=${e.onKeyboardInput} ></textarea> <nav class="desktop-touch-toolbar" aria-label=${y(`desktop.touchControls`)}> <button class="desktop-touch-action" type="button" aria-label=${y(e.controlling?`desktop.switchToViewOnly`:`desktop.takeControl`)} aria-pressed=${e.controlling?`true`:`false`} @click=${e.onControlToggle} > <span class="desktop-touch-action__icon" aria-hidden="true"> ${e.controlling?_.hand:_.eye} </span> <span class="desktop-touch-action__label"> ${y(e.controlling?`desktop.control`:`desktop.viewOnly`)} </span> </button> <button class="desktop-touch-action" type="button" aria-label=${y(`desktop.keyboard`)} @click=${e.onKeyboardFocus} > <span class="desktop-touch-action__icon" aria-hidden="true">${P}</span> <span class="desktop-touch-action__label">${y(`desktop.keyboard`)}</span> </button> <button class="desktop-touch-action" type="button" aria-label=${y(e.scaleViewport?`desktop.actualSize`:`desktop.fitScreen`)} aria-pressed=${e.scaleViewport?`true`:`false`} @click=${e.onScaleToggle} > <span class="desktop-touch-action__icon" aria-hidden="true"> ${e.scaleViewport?_.minimize:_.maximize} </span> <span class="desktop-touch-action__label">${y(`desktop.fit`)}</span> </button> <button class="desktop-touch-action" type="button" aria-label=${y(`desktop.back`)} @click=${e.onClose} > <span class="desktop-touch-action__icon" aria-hidden="true">${_.arrowLeft}</span> <span class="desktop-touch-action__label">${y(`desktop.back`)}</span> </button> </nav> </div> `;return u` <section class="desktop-document" aria-label=${y(`desktop.title`)}> ${M({state:e.state,notice:e.notice,picker:e.picker,recovery:e.recovery,credentials:e.credentials,connection:t})} </section> `}var P;function F(){return(F=e((()=>{l(),v(),E(),ce(),g(),S(),N(),T(),P=fe(se` <rect width="20" height="14" x="2" y="5" rx="2" /> <path d="M6 9h.01" /> <path d="M10 9h.01" /> <path d="M14 9h.01" /> <path d="M18 9h.01" /> <path d="M6 13h.01" /> <path d="M10 13h.01" /> <path d="M14 13h.01" /> <path d="M18 13h.01" /> <path d="M8 17h8" /> `)})))()}var I,L;function R(){return(R=e((()=>{I=`________________`,L=class{constructor(e){this.options=e,this.value=I}focus(){let e=this.options.input();e?.focus({preventScroll:!0}),e?.setSelectionRange(e.value.length,e.value.length)}reset(e){this.value=I;let t=e??this.options.input();t&&(t.value=I)}handleKeyboardEvent(e){let t=this.options.connection();!this.options.controlling()||!t||(t.sendKeyboardEvent(e),e.preventDefault())}handleInput(e){let t=e.currentTarget;if(!this.options.controlling()){this.reset(t);return}let n=t.value,r=this.options.connection(),i=0,a=Math.min(this.value.length,n.length);for(;i<a&&this.value.charAt(i)===n.charAt(i);)i+=1;for(let e=this.value.length-i;e>0;--e)r?.sendBackspace();if(r?.sendText(n.slice(i)),n.length<1||n.length>32){this.reset(t);return}this.value=n}}})))()}var z;function B(){return(B=e((()=>{z=class{constructor(){this.current=null,this.retained=null,this.connected=!1}get handle(){return this.connected?this.current:null}begin(e){let t=e?this.connected?this.current:this.retained:null,n=this.current,r=this.retained;this.current=null,this.retained=t,this.connected=!1,n!==t&&n?.disconnect(),r!==t&&r?.disconnect(),t?.disableInput()}attach(e){this.current=e}markConnected(){this.connected=!0;let e=this.retained;this.retained=null,e?.disconnect()}disconnect(){this.begin(!1)}}})))()}function Me(e){if(!e||typeof e!=`object`||!(`details`in e))return null;let t=e.details;if(!t||typeof t!=`object`||!(`code`in t)||t.code!==V)return null;let n=`auth`in t?t.auth:void 0;return n===`vnc-password`||n===`ard-account`?n:null}var V;function H(){return(H=e((()=>{V=`DESKTOP_CREDENTIALS_REQUIRED`})))()}var U;function W(){return(W=e((()=>{l(),g(),U=class{constructor(e,t){this.host=e,this.options=t,this.active=!1,this.errorText=null,this.restoreFocus=!1,this.onFullscreenChange=()=>this.handleFullscreenChange(),e.addController(this)}hostConnected(){document.addEventListener(`fullscreenchange`,this.onFullscreenChange)}hostDisconnected(){document.removeEventListener(`fullscreenchange`,this.onFullscreenChange),this.restoreFocus=!1,this.fullscreenElement()===this.options.section()&&document.exitFullscreen().catch(()=>{})}renderButton(){let e=this.supported(),t=this.active?this.options.exitLabel():e?this.options.enterLabel():this.options.unavailableLabel();return u`<openclaw-tooltip .content=${t}> <button class=${this.options.buttonClass} type="button" aria-label=${t} aria-pressed=${this.active?`true`:`false`} aria-disabled=${e?`false`:`true`} @click=${()=>void this.toggle()} > <span class=${this.options.iconClass} aria-hidden="true"> ${this.active?_.minimize:_.maximize} </span> </button> </openclaw-tooltip>`}async exit(){if(this.active)try{await document.exitFullscreen()}catch(e){this.setError(this.options.errorMessage(e))}}fullscreenElement(){return(this.host.renderRoot instanceof ShadowRoot?this.host.renderRoot.fullscreenElement:null)??document.fullscreenElement}supported(){return document.fullscreenEnabled&&typeof Element.prototype.requestFullscreen==`function`}handleFullscreenChange(){let e=this.active;this.active=this.fullscreenElement()===this.options.section(),this.options.onChange(),this.host.requestUpdate(),e&&!this.active&&this.restoreFocus&&this.host.updateComplete.then(()=>{this.host.renderRoot.querySelector(this.options.buttonSelector)?.focus(),this.restoreFocus=!1})}async toggle(){if(this.setError(null),this.active){await this.exit();return}let e=this.options.section();if(!e||!this.supported()){this.setError(this.options.unavailableLabel());return}this.restoreFocus=!0;try{await e.requestFullscreen()}catch(e){this.restoreFocus=!1,this.setError(this.options.errorMessage(e))}}setError(e){this.errorText=e,e&&this.options.onError?.(e),this.host.requestUpdate()}}})))()}var G;function K(){return(K=e((()=>{v(),E(),c(),W(),T(),G=class extends U{constructor(e,t){super(e,{...t,buttonClass:`bp-icon desktop-fullscreen-button`,buttonSelector:`.desktop-fullscreen-button`,iconClass:`desktop-fullscreen-icon`,enterLabel:()=>y(`desktop.enterFullscreen`),exitLabel:()=>y(`desktop.exitFullscreen`),unavailableLabel:()=>y(`desktop.fullscreenUnavailable`),errorMessage:e=>y(`desktop.errors.fullscreenFailed`,{error:s(e)})})}}})))()}function Ne(e){return u` <div class="desktop-status"> ${e.inventoryError?p:u`<div> ${y(`desktop.disconnected`,{reason:e.reason??y(`desktop.unknownReason`)})} </div>`} <button class="desktop-button desktop-button--primary" type="button" @click=${e.onRetry}> ${y(e.inventoryError?`common.retry`:`desktop.reconnect`)} </button> </div> `}function q(){return(q=e((()=>{l(),v(),E(),T()})))()}var J;function Y(){return(Y=e((()=>{l(),J=f` /* The inset sizes this to the viewport on its own. Do not reintroduce viewport height units: Android WebView hosts the Control UI in a container that resolves dvh/vh/svh/lvh to 0, which collapses the viewer to a blank page. */ .desktop-document { position: fixed; inset: 0; display: flex; overflow: hidden; box-sizing: border-box; background: var(--bg); } .desktop-document .desktop-content { width: 100%; } .desktop-document .desktop-stage { width: 100%; } .desktop-touch-toolbar { position: absolute; z-index: 3; right: 12px; bottom: max(12px, env(safe-area-inset-bottom)); left: 12px; display: flex; width: max-content; max-width: calc(100% - 24px); align-items: center; justify-content: center; gap: 4px; margin: 0 auto; padding: 5px; border: 1px solid color-mix(in srgb, var(--text) 16%, transparent); border-radius: 14px; background: color-mix(in srgb, var(--bg) 84%, transparent); box-shadow: 0 8px 28px rgb(0 0 0 / 35%); backdrop-filter: blur(16px); } .desktop-touch-action { display: inline-flex; min-width: 48px; height: 44px; align-items: center; justify-content: center; gap: 5px; border: 0; border-radius: 10px; padding: 0 9px; background: transparent; color: var(--text); font: inherit; font-size: 11px; } .desktop-touch-action[aria-pressed="true"] { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); } .desktop-touch-action:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 1px; } .desktop-touch-action__icon { display: inline-flex; width: 18px; height: 18px; } .desktop-touch-action__icon svg { width: 100%; height: 100%; stroke-width: 1.8; } .desktop-keyboard-input { position: fixed; bottom: 0; left: 50%; width: 1px; height: 1px; border: 0; padding: 0; opacity: 0; pointer-events: none; } @media (max-width: 430px) { .desktop-touch-action { min-width: 44px; padding: 0 7px; } .desktop-touch-action__label { display: none; } } `})))()}var X;function Z(){return(Z=e((()=>{l(),X=f` .desktop-apps { display: flex; min-width: 0; align-items: center; gap: 3px; } .desktop-app-button, .desktop-toolbar-action { display: inline-flex; align-items: center; gap: 5px; border: 0; border-radius: 4px; padding: 5px 7px; background: transparent; color: var(--muted); font: inherit; font-size: 12px; white-space: nowrap; } .desktop-app-button { color: var(--text); } .desktop-app-button:hover:not(:disabled), .desktop-toolbar-action:hover:not(:disabled) { background: color-mix(in srgb, var(--text) 8%, transparent); color: var(--text); } .desktop-app-button:focus-visible, .desktop-toolbar-action:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 1px; } .desktop-app-button:disabled, .desktop-toolbar-action:disabled { cursor: default; opacity: 0.55; } .desktop-app-button__icon { display: inline-flex; width: 15px; height: 15px; } .desktop-app-button__icon svg { width: 100%; height: 100%; stroke-width: 1.75; } .desktop-app-button__icon--launching { animation: desktop-app-launch 900ms linear infinite; } @keyframes desktop-app-launch { 50% { opacity: 0.6; transform: rotate(180deg) scale(0.92); } 100% { transform: rotate(360deg); } } @media (prefers-reduced-motion: reduce) { .desktop-app-button__icon--launching { animation: none; } } `})))()}var Pe,Fe;function Ie(){return(Ie=e((()=>{l(),ye(),C(),Y(),Z(),Pe=f` .bp--embedded { position: relative; width: 100%; height: 100%; } .bp--bottom { left: var(--shell-nav-width, 0); right: calc(var(--oc-terminal-reserve-right, 0px) + var(--oc-browser-reserve-right, 0px)); bottom: calc(var(--oc-terminal-reserve-bottom, 0px) + var(--oc-browser-reserve-bottom, 0px)); } .bp--right { top: var(--shell-topbar-height, 0); right: calc(var(--oc-terminal-reserve-right, 0px) + var(--oc-browser-reserve-right, 0px)); bottom: calc(var(--oc-terminal-reserve-bottom, 0px) + var(--oc-browser-reserve-bottom, 0px)); } .bp-title { min-width: 0; } .bp-icon[aria-disabled="true"] { opacity: 0.4; } .desktop-fullscreen-icon > svg { width: 15px; height: 15px; } .bp:fullscreen { inset: 0; width: 100%; height: 100%; border: 0; } .desktop-content { display: flex; flex: 1; min-height: 0; flex-direction: column; } .desktop-toolbar { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-bottom: 1px solid var(--border, #262b34); } .desktop-toolbar--connection { min-height: 42px; gap: 12px; } .desktop-toolbar__spacer { flex: 1; } .desktop-button { border: 1px solid var(--border, #262b34); border-radius: 6px; padding: 5px 10px; background: transparent; color: var(--text, #d7dae0); font: inherit; font-size: 12px; } .desktop-button:hover:not(:disabled) { background: color-mix(in srgb, var(--text, #d7dae0) 10%, transparent); } .desktop-button--primary { border-color: var(--accent, #ff5c5c); color: var(--accent, #ff5c5c); } .desktop-button:disabled { opacity: 0.5; } .desktop-session { overflow: hidden; max-width: 100%; color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; } .desktop-note { padding: 7px 12px; border-bottom: 1px solid var(--border, #262b34); color: var(--muted, #8a919e); font-size: 12px; } .desktop-note--error { color: var(--danger, #ff6b6b); } .desktop-picker, .desktop-status { display: flex; flex: 1; min-height: 0; flex-direction: column; gap: 10px; overflow: auto; padding: 14px; background: var(--panel); } .desktop-status { align-items: center; justify-content: center; text-align: center; color: var(--muted, #8a919e); } .desktop-credentials { display: flex; width: min(320px, 100%); flex-direction: column; gap: 10px; text-align: left; } .desktop-credentials__label { display: flex; flex-direction: column; gap: 5px; color: var(--text, #d7dae0); font-size: 12px; } .desktop-credentials__input { border: 1px solid var(--border, #262b34); border-radius: 6px; padding: 7px 9px; background: var(--bg, #111318); color: var(--text, #d7dae0); font: inherit; } .desktop-environment { display: flex; align-items: center; gap: 10px; padding: 10px; border: 1px solid var(--border, #262b34); border-radius: 8px; } .desktop-environment__details { display: flex; flex: 1; min-width: 0; flex-direction: column; gap: 5px; } .desktop-environment__id { overflow: hidden; color: var(--text, #d7dae0); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; } .desktop-environment__meta, .desktop-environment__sessions { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; color: var(--muted, #8a919e); font-size: 11px; } .desktop-stage { position: relative; flex: 1; min-height: 0; overflow: hidden; background: var(--bg); } .desktop-surface { position: absolute; inset: 0; background: var(--bg); } /* View-only affordance: clicking anywhere on the desktop takes control. */ .desktop-stage__take-control { position: absolute; inset: 0; border: 0; padding: 0; background: transparent; cursor: var(--cursor-action, pointer); } .desktop-stage__take-control:focus-visible { outline: 2px solid var(--accent, #ff5c5c); outline-offset: -2px; } `,Fe=[ge,X,Pe,J,ve]})))()}async function Le(e,t){let n;try{n=(await e?.request(`sessions.describe`,{key:t}))?.session??void 0}catch{}return he(n)}var Re;function ze(){return(ze=e((()=>{te(),i(),a(),me(),Re=class{constructor(e,t,n,r){this.host=e,this.currentTarget=t,this.onTargetChange=n,this.onInventoryChange=r,this.refreshId=0,new ae(e).effect(()=>e.available?e.client:null,t=>t.addEventListener(n=>{if(!e.isConnected||!e.available||t!==e.client)return;if(n.event===`presence`||n.event===`node.pair.resolved`||n.event===`node.runnerInventory.changed`){this.onInventoryChange();return}let r=e.documentMode&&e.sessionKey!==null&&e.requestedSource===null&&n.event===`sessions.changed`?ne(n.payload):null;r&&re(r.key,e.sessionKey)&&this.resolveTarget(e=>{(e===null||e!==this.currentTarget())&&this.onTargetChange(e)})}))}invalidate(){this.refreshId+=1}async resolveInventoryTarget(e,t,n){let r=n=>t(e.some(e=>e.id===n)?n:null),i=this.host.requestedSource??n;return i===void 0&&this.host.documentMode&&this.host.sessionKey!==null?this.resolveTarget(r):r(i??null)}async resolveTarget(e){let{client:t,sessionKey:n}=this.host;if(!t||!n)return;let r=++this.refreshId,i=await Le(t,n);if(!(r!==this.refreshId||!this.host.isConnected||t!==this.host.client||n!==this.host.sessionKey||!this.host.documentMode||!this.host.available||this.host.requestedSource!==null))return e(i)}}})))()}var Q;function $(){return($=e((()=>{l(),oe(),v(),E(),c(),ee(),C(),le(),k(),F(),xe(),R(),B(),H(),K(),pe(),q(),Ie(),N(),ze(),T(),Q=class extends ie{constructor(...e){super(...e),this.client=null,this.available=!1,this.suppressed=!1,this.documentMode=!1,this.requestedSource=null,this.sessionKey=null,this.documentControl=!1,this.basePath=``,this.embedded=!1,this.presented=!1,this.refreshOnPresentation=!0,this.onDocumentClose=null,this.onFocusTargetChange=null,this.desktopClientFactory=()=>new O,this.environments=[],this.loading=!1,this.state=`picker`,this.environmentId=null,this.source=null,this.controlling=!1,this.errorText=null,this.noticeText=null,this.disconnectedReason=null,this.launchingApp=null,this.launchErrorText=null,this.desktopApps=[],this.scaleViewport=!0,this.connection=new z,this.pendingConnection=null,this.operationId=0,this.launchOperationId=0,this.controlTakeoverRecoveryUsed=!1,this.sourceSelection=`pending`,this.sessionSource=new Re(this,()=>this.environmentId,e=>{this.usesAutomaticSource&&(this.returnToPicker(`pending`),this.refreshEnvironments(void 0,e))},()=>{this.state===`picker`&&!this.suppressed&&(this.embedded?this.presented:this.documentMode||this.dockLayout.open)&&this.refreshEnvironments()}),this.mobileKeyboard=new L({connection:()=>this.connection.handle,controlling:()=>this.controlling,input:()=>this.shadowRoot?.querySelector(`.desktop-keyboard-input`)}),this.dockLayout=new _e(this,{layout:de,reservationPrefix:`desktop`,isAvailable:()=>this.available,isFullscreen:()=>this.fullscreenMode.active}),this.fullscreenMode=new G(this,{section:()=>this.renderRoot.querySelector(`section.bp`),onChange:()=>this.dockLayout.syncReservation()}),this.onToggleRequest=e=>this.handleToggleRequest(e)}static{this.styles=Fe}connectedCallback(){super.connectedCallback(),this.embedded||window.addEventListener(h,this.onToggleRequest),this.dockLayout.setSuppressed(this.suppressed),(this.documentMode&&this.available||!this.embedded&&this.dockLayout.open)&&this.refreshEnvironments()}disconnectedCallback(){window.removeEventListener(h,this.onToggleRequest),this.disconnectConnection(),this.credentials=void 0,super.disconnectedCallback()}updated(e){if(e.has(`embedded`)&&(this.embedded?window.removeEventListener(h,this.onToggleRequest):window.addEventListener(h,this.onToggleRequest)),e.has(`suppressed`)){let e=this.dockLayout.setSuppressed(this.suppressed);this.suppressed?this.returnToPicker():e&&this.refreshEnvironments()}let t=e.has(`client`)||e.has(`available`),n=t||e.has(`embedded`)||e.has(`presented`)||e.has(`documentMode`)||e.has(`requestedSource`)&&(!this.embedded||this.usesAutomaticSource)||e.has(`sessionKey`)||e.has(`documentControl`);(this.documentMode||this.embedded)&&n?(this.returnToPicker(`pending`),this.available&&(!this.embedded||this.presented&&this.refreshOnPresentation)&&this.refreshEnvironments()):t&&(!this.available&&this.dockLayout.open?(this.dockLayout.hideWithoutPersisting(),this.returnToPicker()):this.available&&this.dockLayout.restoreOpenState()&&this.refreshEnvironments()),this.dockLayout.syncReservation(),this.onFocusTargetChange?.({kind:`desktop`,control:this.controlling,...this.sourceSelection===`picker`?{}:this.sourceSelection===`explicit`||this.sessionKey===null?{source:this.environmentId}:{session:this.sessionKey}})}handleToggleRequest(e){if(this.documentMode)return;let t=e instanceof CustomEvent&&typeof e.detail==`object`&&e.detail!==null?e.detail:null;if(this.embedded){if(!this.presented)return;if(t?.open===!1){this.returnToPicker();return}if(!this.available||!this.client)return;t?.environmentId?this.connectRequestedEnvironment(t.environmentId):(this.returnToPicker(),this.refreshEnvironments());return}if((t?.dock===`right`||t?.dock===`bottom`)&&this.dockLayout.setDock(t.dock,!1),t?.open===!1){this.closePanel();return}if(!this.available)return;let n=this.dockLayout.open;this.dockLayout.setOpen(!0),t?.environmentId?this.connectRequestedEnvironment(t.environmentId):n?t?.open!==!0&&this.closePanel():this.refreshEnvironments()}closePanel(){this.returnToPicker(),this.dockLayout.setOpen(!1)}get usesAutomaticSource(){return this.sourceSelection===`pending`||this.sourceSelection===`resolved`}returnToPicker(e=`picker`){this.sessionSource.invalidate(),this.disconnectConnection(),this.clearLaunchState(),this.state=`picker`,this.sourceSelection=e,this.environmentId=null,this.source=null,this.credentials=void 0,this.credentialAuth=void 0,this.desktopApps=[],this.controlling=!1,this.disconnectedReason=null}disconnectConnection(e=!1){this.operationId+=1,this.pendingConnection=null,this.connection.begin(e),this.mobileKeyboard.reset()}clearLaunchState(){this.launchOperationId+=1,this.launchingApp=null,this.launchErrorText=null}async refreshEnvironments(e,t){let n=this.client;if(!n||!this.available||this.embedded&&!this.presented)return!1;this.sessionSource.invalidate();let r=e??++this.operationId;this.loading=!0,this.errorText=null;let i=!1;try{let e=await n.request(`environments.list`,{});if(r!==this.operationId)return!1;this.environments=e.environments.filter(e=>e.desktop===!0),i=!0}catch(e){r===this.operationId&&(this.errorText=y(`desktop.errors.listFailed`,{error:s(e)}),(this.requestedSource!==null||this.sessionKey!==null)&&(this.state=`inventory-error`))}finally{r===this.operationId&&(this.loading=!1)}return i&&this.sourceSelection===`pending`&&await this.sessionSource.resolveInventoryTarget(this.environments,async e=>{r===this.operationId&&(e===null?(this.requestedSource!==null||this.sessionKey!==null)&&(this.noticeText=y(`desktop.sourceUnavailable`)):(this.sourceSelection=`resolved`,await this.connectEnvironment(e,this.documentControl)))},t),i}async connectRequestedEnvironment(e){this.returnToPicker(`explicit`),this.environmentId=e,this.state=`connecting`;let t=this.operationId,n=await this.refreshEnvironments(t);if(t===this.operationId){if(!n){this.state=`inventory-error`;return}this.connectEnvironment(e,!1)}}async connectEnvironment(e,t,n={}){let r=this.client;if(!e||!r||!this.available||this.embedded&&!this.presented)return;this.environmentId!==e&&(this.clearLaunchState(),this.credentials=void 0,this.credentialAuth=void 0);let i=this.environments.find(t=>t.id===e);this.desktopApps=[...i?.worker?.desktopApps??[]],this.disconnectConnection(this.environmentId===e);let a=this.operationId,o=j(i??{id:e});this.environmentId=e,this.source=o,this.controlling=t,this.state=`connecting`,this.errorText=null,this.disconnectedReason=null,n.preserveNotice||(this.noticeText=null),this.controlTakeoverRecoveryUsed=n.takeoverRecovery===!0;try{let n=o.kind!==`environment`&&this.credentials?.password&&(this.credentialAuth===`vnc-password`||this.credentialAuth===`ard-account`&&this.credentials.username)?this.credentials:void 0,i=await r.request(`desktop.observe`,{source:o,control:t,...n?{credentials:n}:{}});if(a!==this.operationId)return;this.controlling=i.control;let s=i.preauthenticated?void 0:i.vncPassword?{password:i.vncPassword}:i.auth===`vnc-password`?this.credentials:void 0;if(i.auth===`vnc-password`&&i.preauthenticated!==!0&&!s?.password){this.connection.disconnect(),this.credentialAuth=`vnc-password`,this.pendingConnection={environmentId:e,control:t,observed:i,operationId:a},this.state=`credentials`;return}i.auth===`ard-account`&&(this.credentialAuth=`ard-account`),await this.connectObserved({environmentId:e,control:t,observed:i,operationId:a},i.auth===`vnc-password`?s:void 0)}catch(n){let r=Me(n);if(r&&a===this.operationId){this.connection.disconnect(),this.credentialAuth=r,this.pendingConnection={environmentId:e,control:t,operationId:a},this.state=`credentials`;return}this.failConnection(a,n)}}async connectObserved(e,t){let n=this.client;if(!(!n||e.operationId!==this.operationId)){this.state=`connecting`;try{if(await this.updateComplete,e.operationId!==this.operationId)return;let r=this.shadowRoot?.querySelector(`.desktop-surface`);if(!r)throw Error(`Desktop render target is unavailable`);let i=await this.desktopClientFactory().connect({background:getComputedStyle(r).backgroundColor,isCurrent:()=>e.operationId===this.operationId,wsUrl:e.observed.wsPath,gatewayUrl:n.gatewayUrl,credentials:t,viewOnly:!e.observed.control,scaleViewport:this.scaleViewport,target:r,onConnect:()=>{e.operationId===this.operationId&&(this.connection.markConnected(),this.state=`connected`)},onDisconnect:t=>{e.operationId===this.operationId&&this.handleDesktopDisconnect(e.environmentId,t)},onSecurityFailure:t=>{if(e.operationId===this.operationId){let n=o(t.reason,y(`desktop.unknownReason`));this.errorText=y(`desktop.errors.securityFailed`,{reason:n}),this.failConnection(e.operationId,Error(n))}}});if(e.operationId!==this.operationId){i.disconnect();return}this.connection.attach(i)}catch(t){this.failConnection(e.operationId,t)}}}failConnection(e,t){e===this.operationId&&(this.disconnectConnection(),this.state=`disconnected`,this.disconnectedReason=s(t),this.clearLaunchState())}handleCredentialsSubmit(e){e.preventDefault();let t=this.pendingConnection;if(!t||t.operationId!==this.operationId)return;let n=new FormData(e.currentTarget),r=n.get(`password`);if(typeof r!=`string`||r.length===0)return;let i=n.get(`username`);if(this.credentialAuth===`ard-account`&&(typeof i!=`string`||i.trim().length===0))return;let a={...typeof i==`string`&&i.trim()?{username:i.trim()}:{},password:r};this.credentials=a,this.pendingConnection=null,t.observed?this.connectObserved({...t,observed:t.observed},a):this.connectEnvironment(t.environmentId,t.control)}handleDesktopDisconnect(e,{code:t,reason:n,clean:r}){if(this.disconnectConnection(),this.clearLaunchState(),t===1008&&this.credentialAuth===`ard-account`){this.credentials=this.credentials?.username?{username:this.credentials.username}:void 0,this.pendingConnection={environmentId:e,control:this.controlling,operationId:this.operationId},this.state=`credentials`,this.errorText=y(`desktop.errors.securityFailed`,{reason:o(n,y(`desktop.unknownReason`))});return}if(t===4e3&&n===`control-taken`&&this.controlling&&!this.controlTakeoverRecoveryUsed){this.noticeText=y(`desktop.controlTaken`),this.connectEnvironment(e,!1,{preserveNotice:!0,takeoverRecovery:!0});return}this.state=`disconnected`,this.disconnectedReason=o(n,t?y(`desktop.closeCode`,{code:String(t)}):``)||(r?null:y(`desktop.errors.connectionFailed`))}async launchApp(e){let{client:t,source:n}=this;if(!t||this.embedded&&!this.presented||n?.kind!==`environment`||this.state!==`connecting`&&this.state!==`connected`||!this.desktopApps.includes(e)||this.launchingApp===e)return;let r=++this.launchOperationId;this.launchingApp=e,this.launchErrorText=null;try{if(await t.request(`desktop.launch`,{source:n,app:e}),r!==this.launchOperationId)return}catch(e){if(r!==this.launchOperationId)return;this.launchErrorText=s(e)}this.launchingApp=null}render(){if(!this.available||!this.documentMode&&!this.embedded&&!this.dockLayout.open)return p;let e=Ae(this.fullscreenMode.errorText??this.launchErrorText??this.errorText,this.noticeText),t=Ee({environments:this.environments,loading:this.loading,onRefresh:()=>void this.refreshEnvironments(),onConnect:e=>{this.sourceSelection=`explicit`,this.connectEnvironment(e,!1)}}),n=Oe({ardAccount:this.credentialAuth===`ard-account`,username:this.credentials?.username??``,onSubmit:e=>this.handleCredentialsSubmit(e)}),r=Ne({inventoryError:this.state===`inventory-error`,reason:this.disconnectedReason,onRetry:()=>{if(this.state===`inventory-error`&&(this.documentMode||!this.environmentId)){this.sourceSelection!==`picker`&&(this.sourceSelection=`pending`),this.state=`picker`,this.refreshEnvironments();return}if(this.state===`inventory-error`&&this.environmentId){this.connectRequestedEnvironment(this.environmentId);return}this.connectEnvironment(this.environmentId,this.controlling)}});if(this.documentMode)return je({state:this.state,controlling:this.controlling,scaleViewport:this.scaleViewport,keyboardInputValue:this.mobileKeyboard.value,notice:e,picker:t,credentials:n,recovery:r,onControlToggle:()=>void this.connectEnvironment(this.environmentId,!this.controlling),onKeyboardFocus:()=>this.mobileKeyboard.focus(),onKeyboardEvent:e=>this.mobileKeyboard.handleKeyboardEvent(e),onKeyboardInput:e=>this.mobileKeyboard.handleInput(e),onScaleToggle:()=>{this.scaleViewport=!this.scaleViewport,this.connection.handle?.setScaleViewport(this.scaleViewport)},onClose:()=>this.onDocumentClose?.()});let i=ke({state:this.state,controlling:this.controlling,desktopApps:this.desktopApps,environmentSelected:this.environmentId!==null,launchingApp:this.launchingApp,showApps:this.source?.kind===`environment`,onLaunch:e=>void this.launchApp(e),onTakeControl:()=>void this.connectEnvironment(this.environmentId,!0),onDisconnect:()=>this.returnToPicker()}),a=this.dockLayout.dock,o=this.embedded||this.fullscreenMode.active?``:a===`bottom`?`height:${this.dockLayout.height}px`:`width:${this.dockLayout.width}px`;return u` <section class="bp bp--${this.embedded?`embedded`:a}" style=${o} aria-label=${y(`desktop.title`)} > ${this.embedded?p:this.dockLayout.renderResizer(`bp`,y(`desktop.resize`))} ${this.embedded?p:Te({dock:a,fullscreenControl:this.fullscreenMode.renderButton(),onDock:e=>this.dockLayout.setDock(e),onOpenWindow:()=>be(this.basePath,this.environmentId,this.controlling),onClose:()=>this.closePanel()})} ${M({state:this.state,notice:e,picker:t,recovery:r,credentials:n,connection:i})} </section> `}},r([m({attribute:!1})],Q.prototype,`client`,void 0),r([m({type:Boolean})],Q.prototype,`available`,void 0),r([m({type:Boolean})],Q.prototype,`suppressed`,void 0),r([m({type:Boolean})],Q.prototype,`documentMode`,void 0),r([m({attribute:!1})],Q.prototype,`requestedSource`,void 0),r([m({attribute:!1})],Q.prototype,`sessionKey`,void 0),r([m({type:Boolean})],Q.prototype,`documentControl`,void 0),r([m({attribute:!1})],Q.prototype,`basePath`,void 0),r([m({type:Boolean})],Q.prototype,`embedded`,void 0),r([m({type:Boolean})],Q.prototype,`presented`,void 0),r([m({type:Boolean})],Q.prototype,`refreshOnPresentation`,void 0),r([m({attribute:!1})],Q.prototype,`onDocumentClose`,void 0),r([m({attribute:!1})],Q.prototype,`onFocusTargetChange`,void 0),r([d()],Q.prototype,`environments`,void 0),r([d()],Q.prototype,`loading`,void 0),r([d()],Q.prototype,`state`,void 0),r([d()],Q.prototype,`environmentId`,void 0),r([d()],Q.prototype,`source`,void 0),r([d()],Q.prototype,`controlling`,void 0),r([d()],Q.prototype,`errorText`,void 0),r([d()],Q.prototype,`noticeText`,void 0),r([d()],Q.prototype,`disconnectedReason`,void 0),r([d()],Q.prototype,`launchingApp`,void 0),r([d()],Q.prototype,`launchErrorText`,void 0),r([d()],Q.prototype,`desktopApps`,void 0),r([d()],Q.prototype,`scaleViewport`,void 0),r([d()],Q.prototype,`sourceSelection`,void 0),customElements.get(`openclaw-desktop-panel`)||customElements.define(`openclaw-desktop-panel`,Q)})))()}$(); //# sourceMappingURL=desktop-panel-C0q8O3Dk.js.map