openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
616 lines • 43.7 kB
JavaScript
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`)}
=${()=>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`)}
=${()=>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`)}
=${e.onOpenWindow}
>
${_.externalLink}
</button>
${e.fullscreenControl}
<button
class="rail-header__action bp-icon"
type="button"
title=${y(`desktop.hide`)}
aria-label=${y(`desktop.hide`)}
=${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}
=${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"
=${()=>t(e.id)}
>
${y(`desktop.connect`)}
</button>
</div>
`}function Oe(e){return u`
<div class="desktop-status">
<form class="desktop-credentials" =${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}
=${()=>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`)}
=${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`)}
=${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}
=${e.onKeyboardEvent}
=${e.onKeyboardEvent}
=${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`}
=${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`)}
=${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`}
=${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`)}
=${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`}
=${()=>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" =${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;
}
(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;
}
desktop-app-launch {
50% {
opacity: 0.6;
transform: rotate(180deg) scale(0.92);
}
100% {
transform: rotate(360deg);
}
}
(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