livedesk 0.1.696 → 0.1.697

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ import{j as A}from"./pwa-startup-BiuYh5eN.js";const W=15e3;function xe(n,e=W){const t=Number(n),i=Number.isFinite(Number(e))?Number(e):W;return Math.max(250,Math.min(12e4,Math.trunc(Number.isFinite(t)?t:i)))}class pe extends Error{constructor(e){super(`VuvoDesk Hub request timed out after ${e} ms.`),this.name="HubRequestTimeoutError",this.code="livedesk-hub-request-timeout",this.timeoutMs=e}}async function We(n,e,t){const i=xe(e),r=new AbortController;let s=!1;const o=()=>{r.signal.aborted||r.abort(n?.reason)};n?.aborted?o():n?.addEventListener("abort",o,{once:!0});const a=setTimeout(()=>{s=!0,r.signal.aborted||r.abort(new pe(i))},i);try{return await t(r.signal)}catch(c){throw s?new pe(i):c}finally{clearTimeout(a),n?.removeEventListener("abort",o)}}function dn(n,e){if(n.current)return n.current;const t=Promise.resolve().then(e);return n.current=t,t.finally(()=>{n.current===t&&(n.current=null)}).catch(()=>{}),t}const oe=16*1024,k=6*1024*1024,Be=12*1024*1024,M=24,O=oe-M,ve=1,Ue=2,ge=32,Z=4294967295,ee=Symbol("direct-console-wire-budget-reserve"),te=Object.freeze([76,68,67,87]),ye=Object.freeze({control:1,text:2,binary:3}),He=Object.freeze({1:"control",2:"text",3:"binary"});class B extends Error{constructor(e,t=void 0){super(String(e||"direct-console-wire-error")),this.name="DirectConsoleWireError",this.code=String(e||"direct-console-wire-error"),t!==void 0&&(this.details=t)}}function g(n,e=void 0){throw new B(n,e)}function ae(n,e){return n===void 0?{}:((!n||typeof n!="object"||Array.isArray(n))&&g(`${e}-options-invalid`),n)}function G(n,e,t,i){const r=Number(n);return(!Number.isInteger(r)||r<t||r>i)&&g(e),r}function ke(n){return n===void 0?k:G(n,"max-message-bytes-invalid",1,Z)}function Fe(n,e){const t=n===void 0?e?"text":"binary":String(n);return Object.hasOwn(ye,t)||g("message-kind-invalid"),e&&t==="binary"&&g("binary-message-requires-bytes"),!e&&t!=="binary"&&g(`${t}-message-requires-text`),t}function qe(n){if(typeof n=="string")return{bytes:new TextEncoder().encode(n),isText:!0};if(n instanceof Uint8Array)return{bytes:n,isText:!1};if(n instanceof ArrayBuffer)return{bytes:new Uint8Array(n),isText:!1};g("message-payload-invalid")}function Ge(n){if(n instanceof Uint8Array)return n;if(n instanceof ArrayBuffer)return new Uint8Array(n);g("wire-chunk-type-invalid")}function je(n,{kind:e,messageId:t,chunkIndex:i,chunkCount:r,totalLength:s}){n.set(te,0);const o=new DataView(n.buffer,n.byteOffset,M);o.setUint8(4,ve),o.setUint8(5,ye[e]),o.setUint16(6,0,!1),o.setUint32(8,t,!1),o.setUint32(12,i,!1),o.setUint32(16,r,!1),o.setUint32(20,s,!1)}function $e(n,e){const t=Ge(n);(t.byteLength<M||t.byteLength>oe)&&g("wire-chunk-length-invalid");for(let u=0;u<te.length;u+=1)t[u]!==te[u]&&g("wire-magic-invalid");const i=new DataView(t.buffer,t.byteOffset,M);i.getUint8(4)!==ve&&g("wire-version-invalid");const r=He[i.getUint8(5)];r||g("wire-kind-invalid"),i.getUint16(6,!1)!==0&&g("wire-reserved-invalid");const s=i.getUint32(8,!1),o=i.getUint32(12,!1),a=i.getUint32(16,!1),c=i.getUint32(20,!1);c>e&&g("message-too-large");const d=Math.max(1,Math.ceil(c/O));(a!==d||o>=a)&&g("wire-chunk-layout-invalid");const f=t.byteLength-M,l=o<a-1?O:c-o*O;return f!==l&&g("wire-chunk-layout-invalid"),{bytes:t,kind:r,messageId:s,chunkIndex:o,chunkCount:a,totalLength:c,payloadLength:f}}function Me(n=void 0){const e=ae(n,"budget"),t=e.maxBytes===void 0?Be:G(e.maxBytes,"budget-max-bytes-invalid",1,Number.MAX_SAFE_INTEGER);let i=0,r=0;const s=()=>Object.freeze({maxBytes:t,retainedBytes:i,reservationCount:r}),o=a=>{const c=G(a,"budget-reservation-invalid",0,Number.MAX_SAFE_INTEGER);c>t-i&&g("shared-budget-overflow"),i+=c,r+=1;let d=!0;return Object.freeze({byteLength:c,release(){return d?(d=!1,i-=c,r-=1,(i<0||r<0)&&(i=0,r=0,g("shared-budget-underflow")),!0):!1}})};return Object.freeze({inspect:s,[ee]:o})}function Ve(n,e=void 0){const t=ae(e,"encode"),i=G(t.messageId,"message-id-invalid",0,Z),r=ke(t.maxMessageBytes),s=qe(n),o=Fe(t.kind,s.isText),a=s.bytes.byteLength;(a>r||a>Z)&&g("message-too-large");const c=Math.max(1,Math.ceil(a/O)),d=new Array(c);for(let f=0;f<c;f+=1){const l=f*O,u=Math.min(O,a-l),m=new Uint8Array(M+u);je(m,{kind:o,messageId:i,chunkIndex:f,chunkCount:c,totalLength:a}),u>0&&m.set(s.bytes.subarray(l,l+u),M),d[f]=m}return d}function me(n=void 0){const e=ae(n,"assembler"),t=ke(e.maxMessageBytes),i=e.maxPendingMessages===void 0?Ue:Number(e.maxPendingMessages);(!Number.isSafeInteger(i)||i<1||i>ge)&&g("max-pending-messages-invalid");const r=e.budget===void 0?Me():e.budget;(!r||typeof r[ee]!="function"||typeof r.inspect!="function")&&g("shared-budget-invalid");const s=new Map,o=new Map;let a=!1;const c=()=>{for(const b of s.values())b.reservation.release();s.clear()},d=()=>{o.clear()},f=()=>{let b=0;for(const C of s.values())b+=C.totalLength;let h=0;for(const C of o.values())h+=C.remainingChunks;return Object.freeze({disposed:a,maxMessageBytes:t,maxPendingMessages:i,pendingMessages:s.size,pendingBytes:b,abandonedMessages:o.size,abandonedChunksRemaining:h,budget:r.inspect()})},l=()=>(a||(a=!0,c(),d()),f()),u=b=>{throw a=!0,c(),d(),b instanceof B?b:new B("wire-chunk-malformed")};return Object.freeze({abandonPending:()=>{a&&g("assembler-disposed");for(const[b,h]of s.entries()){if(o.size>=ge){const C=o.keys().next().value;o.delete(C)}o.set(b,{kind:h.kind,chunkCount:h.chunkCount,totalLength:h.totalLength,receivedChunks:new Uint8Array(h.receivedChunks),remainingChunks:Math.max(0,h.chunkCount-h.receivedChunkCount)}),h.reservation.release()}return s.clear(),f()},dispose:l,inspect:f,push:b=>{a&&g("assembler-disposed");try{const h=$e(b,t),C=o.get(h.messageId);if(C)return(C.kind!==h.kind||C.chunkCount!==h.chunkCount||C.totalLength!==h.totalLength)&&g("wire-message-metadata-mismatch"),C.receivedChunks[h.chunkIndex]===0&&(C.receivedChunks[h.chunkIndex]=1,C.remainingChunks-=1),C.remainingChunks<=0&&o.delete(h.messageId),null;let w=s.get(h.messageId);if(w)(w.kind!==h.kind||w.chunkCount!==h.chunkCount||w.totalLength!==h.totalLength)&&g("wire-message-metadata-mismatch");else{s.size>=i&&g("pending-message-limit");const he=r[ee](h.totalLength);let fe;try{fe=new Uint8Array(h.totalLength)}catch{he.release(),g("message-allocation-failed")}w={kind:h.kind,chunkCount:h.chunkCount,totalLength:h.totalLength,receivedChunks:new Uint8Array(h.chunkCount),receivedChunkCount:0,receivedBytes:0,buffer:fe,reservation:he},s.set(h.messageId,w)}w.receivedChunks[h.chunkIndex]!==0&&g("duplicate-wire-chunk");const L=h.chunkIndex*O,Ne=L+h.payloadLength;if((L<0||Ne>w.totalLength)&&g("wire-chunk-overlap"),h.payloadLength>0&&w.buffer.set(h.bytes.subarray(M),L),w.receivedChunks[h.chunkIndex]=1,w.receivedChunkCount+=1,w.receivedBytes+=h.payloadLength,w.receivedChunkCount<w.chunkCount)return null;w.receivedBytes!==w.totalLength&&g("wire-message-length-mismatch");let de;try{de=w.kind==="binary"?w.buffer:new TextDecoder("utf-8",{fatal:!0}).decode(w.buffer)}catch{g("wire-text-invalid")}finally{s.delete(h.messageId),w.reservation.release()}return Object.freeze({messageId:h.messageId,kind:w.kind,byteLength:w.totalLength,data:de})}catch(h){return u(h)}}})}const ze="Direct connection signaling is unavailable. Try again.",Xe="Desktop Hub is offline.",Ye="A direct connection could not be established on this network.",Te=750,Ke=2e3,Je=1500,Qe=3e3,Ze=512*1024,et=64*1024;function tt(n){return n.replace(/^a=sctp-init:[^\r\n]*(?:\r?\n|$)/gm,"")}function we(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/Ze*1e3);return Math.min(Ke,Te+t)}function nt(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/et*1e3);return Math.max(Je,Math.min(Qe,Te+t))}const ne=Object.freeze({"signal-service-unavailable":ze,"hub-unavailable":Xe,"p2p-unavailable":Ye});function ce(n){const e=new Error(ne[n]);return e.name="ConsoleDirectError",e.code=n,e.directFailureKind=n,e}function S(){return ce("signal-service-unavailable")}function Y(){return ce("hub-unavailable")}function p(){return ce("p2p-unavailable")}function K(n){const e=String(n?.directFailureKind||n?.code||""),t=`${e}
2
+ ${String(n?.message||n||"")}`.toLowerCase(),i=Object.hasOwn(ne,e)?e:/hub[- ]?(offline|unavailable)|desktop hub is offline/.test(t)?"hub-unavailable":/signal|websocket|wake-service/.test(t)?"signal-service-unavailable":"p2p-unavailable";return Object.freeze({kind:i,message:ne[i],retryAt:0})}function it({userId:n,connectionId:e,hubEpoch:t,generation:i}){const r={userId:String(n||""),connectionId:String(e||""),hubEpoch:String(t||""),generation:Number(i)};if(!r.userId||!r.connectionId||!r.hubEpoch||!Number.isSafeInteger(r.generation)||r.generation<1)throw new Error("console-direct-owner-invalid");return Object.freeze(r)}function rt(n,e){return!!n&&!!e&&n.userId===e.userId&&n.connectionId===e.connectionId&&n.hubEpoch===e.hubEpoch&&n.generation===e.generation}const Ae="https://livedesk-wake.lovecrdm.workers.dev",st="stun:stun.cloudflare.com:3478",ot="livedesk-console-signal-v2",at="livedesk-auth.",ct="livedesk-control-v1",lt="livedesk-ws-v1:",ut=1e4,F=12e3,be=1e4,dt=5e3,ht=5e3,ft=15e3,pt=15e3,Ee=24,gt=16,Ce=32,mt=64,wt=64,bt=4*1024,Et=1024*1024,Ct=new Set(["/api/remote/status","/api/remote/devices"]),Se=4*1024*1024,St=12*1024*1024,Ie=8*1024*1024+oe,It=8,Lt=1,vt=2,yt=2,kt=new Set(["rtc-offer","rtc-ice","rtc-close"]),Mt=new Set(["frame","atlas","input","audio"]),N=/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;function Tt(n){const e=String(Ae).trim(),t=new URL(e);return t.protocol=t.protocol==="http:"?"ws:":t.protocol==="https:"?"wss:":t.protocol,t.pathname="/v2/rtc/console",t.search="",t.searchParams.set("workspaceId",n),t.hash="",t.toString()}function At(n){const e=String(Ae).trim(),t=new URL(e);if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error("console-direct-signal-http-url-invalid");return t.pathname=n,t.search="",t.hash="",t.toString()}function Ot(n){const e=String(n?.accessToken||"").trim(),t=String(n?.user?.id||"").trim(),i=String(n?.workspaceId||"").trim(),r=String(n?.workspaceKind||"").trim().toLowerCase(),s=String(n?.workspaceRole||"").trim().toLowerCase(),o=Number(n?.membershipRevision||0);return e&&t&&N.test(i)&&["personal","team"].includes(r)&&["owner","operator"].includes(s)&&Number.isSafeInteger(o)&&o>=1&&(r!=="personal"||i===t)?{accessToken:e,user:{id:t},workspaceId:i,workspaceKind:r,workspaceRole:s,membershipRevision:o}:null}function Dt(){const n="".split(/[\s,]+/).map(t=>t.trim()).filter(t=>/^stun:[^\s@]+$/i.test(t)&&t.length<=512),e=[...new Set(n)].slice(0,4);return e.length>0?e:[st]}function Rt(n){let e="";for(let i=0;i<n.byteLength;i+=32768)e+=String.fromCharCode(...n.subarray(i,Math.min(n.byteLength,i+32768)));return btoa(e)}function Pt(n){const e=atob(n),t=new Uint8Array(e.length);for(let i=0;i<e.length;i+=1)t[i]=e.charCodeAt(i);return t}async function _t(n){if(n==null)return new Uint8Array;if(typeof n=="string")return new TextEncoder().encode(n);if(n instanceof URLSearchParams)return new TextEncoder().encode(n.toString());if(n instanceof Blob)return new Uint8Array(await n.arrayBuffer());if(n instanceof ArrayBuffer)return new Uint8Array(n);if(ArrayBuffer.isView(n))return new Uint8Array(n.buffer,n.byteOffset,n.byteLength);throw new Error("This request body cannot be sent through the direct mobile Console connection.")}function Nt(n){const e=new Headers(n?.headers||{}),t={};for(const i of["accept","content-type","if-match","range","x-livedesk-csrf"]){const r=e.get(i);r&&(t[i]=r)}return t}function _(n){return/(?:^|\r?\n)(?:a=)?candidate:[^\r\n]*\btyp\s+relay(?:\s|$)/i.test(String(n||""))}function ie(n,e=1e3){const t=Number(n);return Number.isInteger(t)&&t>=0&&t<=65535?t:e}function q(n,e="console-direct-failed"){return n instanceof Error?n:new Error(String(n||e))}function re(n){if(n instanceof ArrayBuffer||n instanceof Uint8Array)return n;throw new B("wire-chunk-type-invalid")}function xt(n){const e=re(n),t=e instanceof Uint8Array?e:new Uint8Array(e),i={chunkBytes:t.byteLength,headerReadable:!1,messageId:0,chunkIndex:0,chunkCount:0,totalLength:0};if(t.byteLength<Ee)return i;const r=new DataView(t.buffer,t.byteOffset,Ee);return{...i,headerReadable:t[0]===76&&t[1]===68&&t[2]===67&&t[3]===87,messageId:r.getUint32(8,!1),chunkIndex:r.getUint32(12,!1),chunkCount:r.getUint32(16,!1),totalLength:r.getUint32(20,!1)}}function Wt(n,e){return e?e.aborted?Promise.reject(e.reason||new Error("Mobile Console request cancelled.")):new Promise((t,i)=>{let r=!1;const s=a=>{r||(r=!0,e.removeEventListener("abort",o),a())},o=()=>s(()=>i(e.reason||new Error("Mobile Console request cancelled.")));e.addEventListener("abort",o,{once:!0}),n.then(a=>s(()=>t(a)),a=>s(()=>i(a)))}):n}class Bt extends EventTarget{constructor(e,t,i,r){super(),this.manager=e,this.channelId=t,this.purpose=i,this.url=r}manager;channelId;purpose;url;protocol="livedesk-ws-v1";extensions="";binaryType="blob";readyState=WebSocket.CONNECTING;onopen=null;onmessage=null;onerror=null;onclose=null;handoffConnectingOwner(e){if(this.readyState!==WebSocket.CONNECTING)throw new Error("media-handoff-after-open");this.manager=e}get bufferedAmount(){return this.manager.logicalBufferedAmount(this.channelId)}send(e){if(this.readyState!==WebSocket.OPEN)throw new DOMException("WebSocket is not open.","InvalidStateError");this.manager.sendLogicalMessage(this.channelId,e)}close(e=1e3,t=""){this.readyState===WebSocket.CLOSED||this.readyState===WebSocket.CLOSING||(this.readyState=WebSocket.CLOSING,this.manager.closeLogicalChannel(this.channelId,ie(e),String(t||"").slice(0,120),!0))}managerOpened(){if(this.readyState!==WebSocket.CONNECTING)return;this.readyState=WebSocket.OPEN;const e=new Event("open");this.onopen?.call(this,e),this.dispatchEvent(e)}managerMessage(e){if(this.readyState!==WebSocket.OPEN)return;const t=new MessageEvent("message",{data:e});this.onmessage?.call(this,t),this.dispatchEvent(t)}managerError(){if(this.readyState===WebSocket.CLOSED)return;const e=new Event("error");this.onerror?.call(this,e),this.dispatchEvent(e)}managerClosed(e,t,i=!1){if(this.readyState===WebSocket.CLOSED)return;i&&this.managerError(),this.readyState=WebSocket.CLOSED;const r=new CloseEvent("close",{code:ie(e,1006),reason:String(t||"").slice(0,120),wasClean:e===1e3});this.onclose?.call(this,r),this.dispatchEvent(r)}}class le{constructor(e=null){this.mediaParent=e}mediaParent;mediaPeers=new Map;mediaPeerVersion=0;recentMediaClosures=[];session=null;preferred=!1;generation=0;stage="idle";signalSocket=null;signalReady=!1;consoleId="";hubEpoch="";peerOwner=null;peer=null;controlChannel=null;controlAssembler=null;controlWireDeadline=null;wireBudget=null;remoteDescriptionApplied=!1;localOfferSent=!1;pendingLocalCandidates=[];pendingRemoteCandidates=[];directReady=!1;connectPromise=null;resolveConnect=null;rejectConnect=null;connectTimer=null;peerDisconnectTimer=null;wireMessageId=0;pendingHttp=new Map;channels=new Map;livenessEvidenceEpoch=0;consecutiveLivenessRequestTimeouts=0;livenessRequestTimeoutCount=0;consecutiveMediaLogicalOpenFailures=0;logicalChannelFailureCount=0;lastLogicalChannelFailure=null;partialMediaWireTimeoutCount=0;lastPartialMediaWireTimeout=null;preOpenMediaCoalesceCount=0;lastPreOpenMediaCoalesce=null;logicalWireFailureCount=0;lastLogicalWireFailure=null;controlMediaRecoveryCount=0;lastControlMediaRecovery=null;livenessMediaRecoveryGeneration=0;mediaAttachmentHoldGeneration=0;lastFailure=null;lastTerminalWireBytes=0;lastTerminalWireReservations=0;workspaceReauthAttempt=null;configure(e){const t=Ot(e),i=this.session?`${this.session.user.id}
3
+ ${this.session.workspaceId}
4
+ ${this.session.workspaceRole}`:"",r=t?`${t.user.id}
5
+ ${t.workspaceId}
6
+ ${t.workspaceRole}`:"";this.session=t,i!==r&&(this.teardown("console-session-replaced",null,!0),this.recentMediaClosures.length=0,this.lastFailure=null)}preferDirect(){this.preferred=!0}markLocalHubReachable(){this.preferred=!1,this.teardown("local-hub-reachable",null,!0),this.lastFailure=null}resume(){if(this.invalidateLivenessEvidence(),this.hasReadyPayloadPeer()){this.lastFailure=null;return}this.teardown("console-resume",null,!0),this.lastFailure=null}suspendLivenessEvidence(){this.invalidateLivenessEvidence()}retry(){this.preferred=!0,this.teardown("console-manual-retry",null,!0),this.lastFailure=null}shouldUseDirect(){return this.preferred&&!!this.session?.accessToken}inspect(){const e=[...this.mediaPeers.entries()].map(([l,u])=>({channelId:l,connectionId:u.peerOwner?.connectionId||null,generation:u.generation,stage:u.stage,directReady:u.directReady,peerCount:u.peer?1:0,controlChannels:u.controlChannel?1:0,logicalChannels:u.channels.size,openLogicalChannels:[...u.channels.values()].filter(m=>m.opened).length,resourceTimers:+(u.connectTimer!==null)+ +(u.peerDisconnectTimer!==null)+ +(u.controlWireDeadline!==null)+[...u.channels.values()].reduce((m,E)=>m+ +(E.openDeadline!==null)+ +(E.wireDeadline!==null),0),sendBufferedBytes:u.peerBufferedAmount(),partialMediaWireTimeoutCount:u.partialMediaWireTimeoutCount,logicalChannelFailureCount:u.logicalChannelFailureCount,lastPartialMediaWireTimeout:u.lastPartialMediaWireTimeout,lastLogicalChannelFailure:u.lastLogicalChannelFailure})),t=this.wireBudget?.inspect()||{retainedBytes:0,reservationCount:0},i=[this,...this.mediaPeers.values()],r=i.flatMap(l=>[...l.channels.values()]),s=r.filter(l=>l.wireDeadline!==null).length,o=r.filter(l=>l.openDeadline!==null).length,a=i.filter(l=>l.connectTimer!==null).length,c=i.filter(l=>l.peerDisconnectTimer!==null).length,d=i.filter(l=>l.controlWireDeadline!==null).length,f=this.workspaceReauthAttempt?.deadline==null?0:1;return Object.freeze({preferred:this.preferred,stage:this.stage,directReady:this.directReady,generation:this.generation,consoleId:this.consoleId||null,connectionId:this.peerOwner?.connectionId||null,signalSockets:this.signalSocket?1:0,mediaPeerVersion:this.mediaPeerVersion,mediaPeers:e,recentMediaClosures:this.recentMediaClosures.slice(),peerCount:+!!this.peer+e.reduce((l,u)=>l+u.peerCount,0),controlChannels:this.controlChannel?1:0,mediaControlChannels:e.reduce((l,u)=>l+u.controlChannels,0),logicalChannels:this.channels.size+e.reduce((l,u)=>l+u.logicalChannels,0),openLogicalChannels:[...this.channels.values()].filter(l=>l.opened).length+e.reduce((l,u)=>l+u.openLogicalChannels,0),pendingHttpRequests:this.pendingHttp.size,livenessEvidenceEpoch:this.livenessEvidenceEpoch,workspaceReauthRequests:this.workspaceReauthAttempt?1:0,consecutiveLivenessRequestTimeouts:this.consecutiveLivenessRequestTimeouts,livenessRequestTimeoutCount:this.livenessRequestTimeoutCount,consecutiveMediaLogicalOpenFailures:this.consecutiveMediaLogicalOpenFailures,logicalChannelFailureCount:this.logicalChannelFailureCount,lastLogicalChannelFailure:this.lastLogicalChannelFailure,partialMediaWireTimeoutCount:this.partialMediaWireTimeoutCount,lastPartialMediaWireTimeout:this.lastPartialMediaWireTimeout,preOpenMediaCoalesceCount:this.preOpenMediaCoalesceCount,lastPreOpenMediaCoalesce:this.lastPreOpenMediaCoalesce,logicalWireFailureCount:this.logicalWireFailureCount,lastLogicalWireFailure:this.lastLogicalWireFailure,controlMediaRecoveryCount:this.controlMediaRecoveryCount,lastControlMediaRecovery:this.lastControlMediaRecovery,mediaAttachmentHoldGeneration:this.mediaAttachmentHoldGeneration,heldMediaLogicalChannels:[...this.channels.values()].filter(l=>(l.purpose==="frame"||l.purpose==="atlas")&&l.owner===null&&l.dataChannel===null).length,pendingRemoteCandidates:this.pendingRemoteCandidates.length,pendingLocalCandidates:this.pendingLocalCandidates.length,connectTimers:a,peerDisconnectTimers:c,controlWireTimers:d,workspaceReauthTimers:f,logicalOpenTimers:o,logicalWireTimers:s,resourceTimers:a+c+d+f+o+s+this.pendingHttp.size,wireRetainedBytes:t.retainedBytes,wireReservations:t.reservationCount,sendBufferedBytes:this.peerBufferedAmount()+e.reduce((l,u)=>l+u.sendBufferedBytes,0),lastTerminalWireBytes:this.lastTerminalWireBytes,lastTerminalWireReservations:this.lastTerminalWireReservations,failure:this.lastFailure})}nextMessageId(){return this.wireMessageId=this.wireMessageId>=4294967295?1:this.wireMessageId+1,this.wireMessageId}isSignalOwner(e,t){return e===this.generation&&this.signalSocket===t}isPeerOwner(e){return rt(this.peerOwner,e)}hasReadyPayloadPeer(){return this.directReady&&!!this.peerOwner&&!!this.peer&&this.peer?.connectionState!=="failed"&&this.peer?.connectionState!=="closed"&&this.controlChannel?.readyState==="open"}detachSignalFromReadyPeer(e,t,i){if(!this.isSignalOwner(e,t)||!this.hasReadyPayloadPeer())return!1;this.cancelWorkspaceReauthAttempt(e,t),this.signalSocket=null,this.signalReady=!1,this.consoleId="";try{t.close(1e3,i)}catch{}return!0}clearConnectTimer(){this.connectTimer!==null&&(window.clearTimeout(this.connectTimer),this.connectTimer=null)}clearPeerDisconnectTimer(){this.peerDisconnectTimer!==null&&(window.clearTimeout(this.peerDisconnectTimer),this.peerDisconnectTimer=null)}cancelWorkspaceReauthAttempt(e,t){const i=this.workspaceReauthAttempt;if(!i||e!==void 0&&i.generation!==e||t!==void 0&&i.socket!==t)return!1;this.workspaceReauthAttempt=null,i.deadline!==null&&(window.clearTimeout(i.deadline),i.deadline=null);try{i.controller.abort()}catch{}return!0}refreshPeerDisconnectDeadline(e,t){if(!this.isPeerOwner(e)||this.peer!==t)return;if(!(t.connectionState==="disconnected"||t.iceConnectionState==="disconnected")){this.clearPeerDisconnectTimer();return}if(this.peerDisconnectTimer!==null)return;const r=window.setTimeout(()=>{this.peerDisconnectTimer===r&&(this.peerDisconnectTimer=null,!(!this.isPeerOwner(e)||this.peer!==t)&&(t.connectionState==="disconnected"||t.iceConnectionState==="disconnected")&&this.fail(p(),"peer-disconnected-timeout",!0))},dt);this.peerDisconnectTimer=r}clearControlWireDeadline(){this.controlWireDeadline!==null&&(window.clearTimeout(this.controlWireDeadline),this.controlWireDeadline=null)}refreshControlWireDeadline(e,t){if((t.inspect().pendingMessages||0)===0){this.clearControlWireDeadline();return}if(this.controlWireDeadline!==null)return;const r=window.setTimeout(()=>{this.controlWireDeadline===r&&(this.controlWireDeadline=null,!(!this.isPeerOwner(e)||this.controlAssembler!==t)&&(t.inspect().pendingMessages||0)>0&&this.fail(p(),"control-wire-assembly-timeout",!0))},ft);this.controlWireDeadline=r}resolveCurrentConnect(){const e=this.resolveConnect;this.resolveConnect=null,this.rejectConnect=null,this.connectPromise=null,this.clearConnectTimer(),e?.()}rejectCurrentConnect(e){const t=this.rejectConnect;this.resolveConnect=null,this.rejectConnect=null,this.connectPromise=null,this.clearConnectTimer(),t?.(e)}signal(e){if(!kt.has(String(e.type||"")))throw new Error("console-direct-signal-type-forbidden");if(this.mediaParent){const{manager:i,owner:r,channelId:s}=this.mediaParent;if(!i.isPeerOwner(r)||i.mediaPeers.get(s)!==this)throw new Error("console-direct-media-parent-stale");i.sendControl({type:"media-signal",connectionId:r.connectionId,hubEpoch:r.hubEpoch,mediaId:s,signal:e});return}const t=this.signalSocket;if(!t||t.readyState!==WebSocket.OPEN||!this.signalReady)throw S();t.send(JSON.stringify(e))}peerBufferedAmount(){let e=Number(this.controlChannel?.bufferedAmount||0);for(const t of this.channels.values())e+=Number(t.dataChannel?.bufferedAmount||0);return e}sendWire(e,t,i,r){if(e.readyState!=="open")throw new Error("console-direct-data-channel-not-open");const s=Ve(t,{messageId:this.nextMessageId(),kind:i,maxMessageBytes:r}),o=s.reduce((a,c)=>a+c.byteLength,0);if(o>Se||this.peerBufferedAmount()>Se-o)throw new Error("console-direct-send-buffer-full");for(const a of s)e.send(a)}sendControl(e){const t=this.controlChannel;if(!t||!this.directReady||!this.peerOwner)throw p();this.sendWire(t,JSON.stringify(e),"control",k)}fail(e,t,i=!0){this.lastFailure=K(e),this.teardown(t,e,i)}teardown(e,t,i,r=!1){const s=this.signalSocket,o=this.peerOwner;if(i&&(this.mediaParent||s?.readyState===WebSocket.OPEN&&this.signalReady)&&o)try{this.signal({type:"rtc-close",connectionId:o.connectionId,hubEpoch:o.hubEpoch,reason:String(e||"console-direct-closed").slice(0,120)})}catch{}for(const l of[...this.mediaPeers.values()])l.teardown(e,t,!1);if(this.mediaPeers.clear(),this.mediaParent?.manager.mediaPeers.get(this.mediaParent.channelId)===this){const l=this.mediaParent.manager.recentMediaClosures;l.push({channelId:this.mediaParent.channelId,generation:this.generation,reason:String(e).slice(0,120),occurredAt:Date.now(),logicalFailure:this.lastLogicalChannelFailure}),l.length>8&&l.shift(),this.mediaParent.manager.mediaPeers.delete(this.mediaParent.channelId)}this.mediaPeerVersion=0,r?this.stage="hub-offline":(this.generation+=1,this.stage="idle",this.signalSocket=null,this.signalReady=!1,this.consoleId="",this.cancelWorkspaceReauthAttempt()),this.hubEpoch="",this.peerOwner=null,this.directReady=!1,this.remoteDescriptionApplied=!1,this.localOfferSent=!1,this.pendingLocalCandidates=[],this.pendingRemoteCandidates=[],this.invalidateLivenessEvidence(),this.clearConnectTimer(),this.clearPeerDisconnectTimer();const a=t||new Error(e||"console-direct-closed");this.rejectCurrentConnect(a);for(const[l,u]of this.pendingHttp)window.clearTimeout(u.timeout),u.detachAbort(),u.reject(a),this.pendingHttp.delete(l);for(const l of[...this.channels.values()])this.retireLogicalEntry(l,t?1011:1001,e,!!t,!1);this.clearControlWireDeadline(),this.controlAssembler?.dispose(),this.controlAssembler=null;const c=this.controlChannel;if(this.controlChannel=null,c){c.onopen=null,c.onmessage=null,c.onerror=null,c.onclose=null;try{c.close()}catch{}}const d=this.peer;if(this.peer=null,d){d.onicecandidate=null,d.onconnectionstatechange=null,d.oniceconnectionstatechange=null;try{d.close()}catch{}}if(!r)try{s?.close(1e3,String(e||"console-direct-closed").slice(0,120))}catch{}const f=this.wireBudget?.inspect();this.lastTerminalWireBytes=Number(f?.retainedBytes||0),this.lastTerminalWireReservations=Number(f?.reservationCount||0),this.wireBudget=null}async connect(){if(this.directReady&&this.peerOwner&&this.controlChannel?.readyState==="open")return;if(this.connectPromise)return this.connectPromise;if(this.mediaParent)return this.connectMediaPeer();const e=this.session;if(!e)throw S();const t=this.signalSocket?.readyState===WebSocket.OPEN&&this.signalReady;if(t&&this.stage==="hub-offline"){const s=Y();throw this.lastFailure=K(s),s}if(t&&this.stage==="p2p"&&this.peerOwner&&this.peer){const s=this.generation,o=new Promise((a,c)=>{this.resolveConnect=a,this.rejectConnect=c});return this.connectPromise=o,this.connectTimer===null&&(this.connectTimer=window.setTimeout(()=>{s===this.generation&&!this.directReady&&this.fail(p(),"direct-ready-timeout",!0)},F)),o}const i=this.generation+1;this.generation=i,this.stage="signal",this.lastFailure=null;const r=new Promise((s,o)=>{this.resolveConnect=s,this.rejectConnect=o});this.connectPromise=r,this.connectTimer=window.setTimeout(()=>{if(i!==this.generation)return;const s=this.stage==="signal"?S():p();this.fail(s,this.stage==="signal"?"signal-timeout":"direct-ready-timeout",!1)},this.stage==="signal"?ut:F);try{const s=new WebSocket(Tt(e.workspaceId),[ot,`${at}${e.accessToken}`]);this.signalSocket=s,s.addEventListener("message",o=>{if(!this.isSignalOwner(i,s)||typeof o.data!="string")return;let a;try{a=JSON.parse(o.data)}catch{this.fail(S(),"invalid-signal-json",!1);return}this.handleSignal(a,i,s)}),s.addEventListener("error",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-detached-after-ready")||this.fail(S(),"signal-service-unavailable",!1))}),s.addEventListener("close",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-closed-after-ready")||this.fail(S(),"signal-service-closed",!1))})}catch{this.fail(S(),"signal-constructor-failed",!1)}return r}connectMediaPeer(){const e=this.mediaParent;if(!e.manager.isPeerOwner(e.owner)||!e.manager.hasReadyPayloadPeer()||e.manager.mediaPeers.get(e.channelId)!==this)return Promise.reject(new Error("console-direct-media-parent-stale"));this.session=e.manager.session,this.consoleId=e.channelId,this.hubEpoch=e.owner.hubEpoch,this.stage="p2p";const t=++this.generation,i=new Promise((r,s)=>{this.resolveConnect=r,this.rejectConnect=s});return this.connectPromise=i,this.connectTimer=window.setTimeout(()=>{t===this.generation&&!this.directReady&&this.fail(p(),"media-direct-ready-timeout",!0)},F),this.beginPeer(t,e.owner.hubEpoch),i}handleMediaSignal(e,t){if(this.mediaParent||t.connectionId!==e.connectionId||t.hubEpoch!==e.hubEpoch)return;const i=this.mediaPeers.get(String(t.mediaId||"")),r=t.signal,s=i?.peerOwner;!i||!s||!r||i.mediaParent?.owner!==e||r.connectionId!==s.connectionId||r.hubEpoch!==s.hubEpoch||(r.type==="rtc-answer"?i.acceptAnswer(s,r.description):r.type==="rtc-ice"?i.acceptRemoteCandidate(s,r.candidate,r.sdpMid):r.type==="rtc-close"&&i.fail(p(),String(r.reason||"media-peer-closed").slice(0,120),!1))}handleSignal(e,t,i){if(!this.isSignalOwner(t,i))return;if(e.type==="workspace-reauth-required"){const s=this.session,o=String(e.workspaceId||s?.workspaceId||"").trim(),a=String(e.challengeNonce||"").trim();if(!s||o!==s.workspaceId||!N.test(a)){this.fail(S(),"workspace-reauth-owner-mismatch",!1);return}if(this.workspaceReauthAttempt?.challengeNonce===a&&this.workspaceReauthAttempt.generation===t&&this.workspaceReauthAttempt.socket===i)return;this.cancelWorkspaceReauthAttempt();const c=new AbortController,d={challengeNonce:a,generation:t,socket:i,controller:c,deadline:null},f=Number(e.deadlineAt||0),l=Number.isFinite(f)&&f>0?Math.max(1,f-Date.now()):be;d.deadline=window.setTimeout(()=>{this.workspaceReauthAttempt===d&&this.cancelWorkspaceReauthAttempt(t,i)},Math.max(1,Math.min(be,l))),this.workspaceReauthAttempt=d,(async()=>{try{await fetch(At("/v2/rtc/reauth"),{method:"POST",headers:{Authorization:`Bearer ${s.accessToken}`,"Content-Type":"application/json"},body:JSON.stringify({workspaceId:s.workspaceId,challengeNonce:a}),signal:c.signal,cache:"no-store"})}catch{}})().finally(()=>{this.workspaceReauthAttempt===d&&(this.workspaceReauthAttempt=null,d.deadline!==null&&(window.clearTimeout(d.deadline),d.deadline=null))});return}if(e.type==="workspace-access-refreshed"||e.type==="workspace-reauth-ok"){e.type==="workspace-reauth-ok"&&this.cancelWorkspaceReauthAttempt(t,i);return}if(e.type==="workspace-access-expired"){this.fail(S(),"workspace-access-expired",!1);return}if(e.type==="signal-ready"){const s=String(e.consoleId||""),o=String(e.hubEpoch||"");if(e.role!=="console"||!N.test(s)){this.fail(S(),"invalid-signal-ready",!1);return}if(this.signalReady=!0,this.consoleId=s,e.hubOnline!==!0){const a=Y();this.lastFailure=K(a),this.teardown("hub-offline",a,!1,!0);return}if(!N.test(o)){this.fail(S(),"invalid-hub-epoch",!1);return}if(this.peerOwner){this.peerOwner.hubEpoch!==o&&this.fail(p(),"hub-epoch-replaced",!1);return}this.hubEpoch=o,this.stage="p2p",this.lastFailure=null,this.clearConnectTimer(),this.connectTimer=window.setTimeout(()=>{t===this.generation&&!this.directReady&&this.fail(p(),"direct-ready-timeout",!0)},F),this.beginPeer(t,o);return}const r=this.peerOwner;if(!(!r||String(e.connectionId||"")!==r.connectionId||String(e.hubEpoch||"")!==r.hubEpoch)){if(e.type==="rtc-answer")this.acceptAnswer(r,e.description);else if(e.type==="rtc-ice")this.acceptRemoteCandidate(r,e.candidate,e.sdpMid);else if(e.type==="rtc-close"){const s=String(e.reason||"rtc-closed"),o=/hub-offline/i.test(s)?Y():p();this.fail(o,s,!1)}}}beginPeer(e,t){if(e!==this.generation||this.peer)return;const i=this.session;if(!i){this.fail(S(),"session-missing",!1);return}const r=it({userId:i.user.id,connectionId:crypto.randomUUID(),hubEpoch:t,generation:e});this.consecutiveMediaLogicalOpenFailures=0,this.peerOwner=r,this.wireBudget=this.mediaParent?.manager.wireBudget||Me({maxBytes:St}),this.controlAssembler=me({budget:this.wireBudget,maxMessageBytes:k});let s;try{s=new RTCPeerConnection({iceServers:[{urls:Dt()}],iceTransportPolicy:"all",bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"})}catch{this.fail(p(),"peer-constructor-failed",!0);return}this.peer=s;const o=s.createDataChannel(ct,{ordered:!0});o.binaryType="arraybuffer",this.controlChannel=o,s.onicecandidate=a=>{if(!this.isPeerOwner(r)||this.peer!==s||!a.candidate)return;const c=String(a.candidate.candidate||"");if(_(c)){this.fail(p(),"relay-ice-candidate-forbidden",!0);return}if(new TextEncoder().encode(c).byteLength>bt){this.fail(p(),"local-ice-candidate-invalid",!0);return}if(!this.localOfferSent){if(this.pendingLocalCandidates.length>=wt){this.fail(p(),"local-ice-capacity-reached",!0);return}this.pendingLocalCandidates.push({candidate:c,sdpMid:a.candidate.sdpMid});return}try{this.signal({type:"rtc-ice",connectionId:r.connectionId,hubEpoch:r.hubEpoch,candidate:c,sdpMid:a.candidate.sdpMid})}catch{this.fail(S(),"signal-ice-failed",!1)}},s.onconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.connectionState==="failed"||s.connectionState==="closed"){this.fail(p(),`peer-${s.connectionState}`,!0);return}this.refreshPeerDisconnectDeadline(r,s)}},s.oniceconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.iceConnectionState==="failed"||s.iceConnectionState==="closed"){this.fail(p(),`ice-${s.iceConnectionState}`,!0);return}this.refreshPeerDisconnectDeadline(r,s)}},o.onmessage=a=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.handleControlWire(r,a.data)},o.onerror=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(p(),"control-channel-error",!0)},o.onclose=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(p(),"control-channel-closed",!0)},(async()=>{try{const a=await s.createOffer();if(!this.isPeerOwner(r)||this.peer!==s)return;if(a.type!=="offer"||_(a.sdp))throw new Error("relay-sdp-forbidden");if(await s.setLocalDescription(a),!this.isPeerOwner(r)||this.peer!==s)return;const c=s.localDescription||a;if(c.type!=="offer"||_(c.sdp))throw new Error("relay-sdp-forbidden");this.signal({type:"rtc-offer",connectionId:r.connectionId,hubEpoch:r.hubEpoch,description:{type:"offer",sdp:tt(c.sdp||"")}}),this.localOfferSent=!0;const d=this.pendingLocalCandidates;this.pendingLocalCandidates=[];for(const f of d){if(!this.isPeerOwner(r)||this.peer!==s)return;this.signal({type:"rtc-ice",connectionId:r.connectionId,hubEpoch:r.hubEpoch,...f})}}catch(a){if(!this.isPeerOwner(r))return;const c=/signal/i.test(String(a?.message||""))?S():p();this.fail(c,"rtc-offer-failed",!0)}})()}async acceptAnswer(e,t){const i=this.peer;if(!(!this.isPeerOwner(e)||!i||this.remoteDescriptionApplied)){if(t?.type!=="answer"||typeof t.sdp!="string"||_(t.sdp)){this.fail(p(),"rtc-answer-invalid",!0);return}try{if(await i.setRemoteDescription({type:"answer",sdp:t.sdp}),!this.isPeerOwner(e)||this.peer!==i)return;this.remoteDescriptionApplied=!0;const r=this.pendingRemoteCandidates;this.pendingRemoteCandidates=[];for(const s of r){if(!this.isPeerOwner(e)||this.peer!==i)return;await i.addIceCandidate(s.candidate?s:null)}}catch{this.isPeerOwner(e)&&this.fail(p(),"rtc-answer-apply-failed",!0)}}}async acceptRemoteCandidate(e,t,i){if(!this.isPeerOwner(e))return;const r=String(t??""),s=i==null?null:String(i);if(r.length>4*1024||s!==null&&s.length>256||_(r)){this.fail(p(),"rtc-candidate-invalid",!0);return}const o=this.peer;if(o){if(!this.remoteDescriptionApplied){if(this.pendingRemoteCandidates.length>=mt){this.fail(p(),"rtc-candidate-capacity",!0);return}this.pendingRemoteCandidates.push({candidate:r,sdpMid:s});return}try{await o.addIceCandidate(r?{candidate:r,sdpMid:s}:null)}catch{this.isPeerOwner(e)&&this.fail(p(),"rtc-candidate-apply-failed",!0)}}}handleControlWire(e,t){const i=this.controlAssembler;if(!(!this.isPeerOwner(e)||!i))try{const r=i.push(re(t));if(this.refreshControlWireDeadline(e,i),!r)return;if(r.kind!=="control"||typeof r.data!="string")throw new Error("control-wire-kind-invalid");const s=JSON.parse(r.data);if(s.type==="direct-ready"){if(s.connectionId!==e.connectionId||s.hubEpoch!==e.hubEpoch||this.controlChannel?.readyState!=="open")throw new Error("direct-ready-owner-invalid");this.directReady||(this.mediaPeerVersion=!this.mediaParent&&s.mediaPeerVersion===1?1:0,this.consecutiveLivenessRequestTimeouts=0,this.directReady=!0,this.stage="ready",this.resolveCurrentConnect());return}if(s.type==="media-signal"){this.handleMediaSignal(e,s);return}if(s.type==="http-response"){this.handleHttpResponse(e,s);return}if(s.type==="ws-opened"||s.type==="ws-closed"||s.type==="ws-error"){this.handleLogicalLifecycle(e,s);return}throw new Error("control-message-type-invalid")}catch{this.isPeerOwner(e)&&this.fail(p(),"control-wire-invalid",!0)}}handleLogicalLifecycle(e,t){if(t.connectionId!==e.connectionId||t.hubEpoch!==e.hubEpoch)throw new Error("logical-lifecycle-owner-invalid");const i=String(t.channelId||"");if(!N.test(i))throw new Error("logical-lifecycle-channel-invalid");const r=this.channels.get(i);if(!r)return;const s=r.dataChannel;if(!s||!r.openRequested||!this.logicalEntryIsCurrent(r,e,s))throw new Error("logical-lifecycle-owner-invalid");if(t.type==="ws-opened"){if(r.opened)return;r.opened=!0,(r.purpose==="frame"||r.purpose==="atlas")&&(this.consecutiveMediaLogicalOpenFailures=0),this.clearLogicalOpenDeadline(r);const o=r.pendingInbound.splice(0);if(r.pendingInboundBytes=0,r.socket.managerOpened(),!this.logicalEntryIsCurrent(r,e,s)||!r.opened)return;for(const a of o)this.deliverLogicalMessage(r,a);return}if(t.type==="ws-closed"){this.retireLogicalEntry(r,ie(t.code,1e3),String(t.reason||""),!1,!1);return}this.retireLogicalEntry(r,1011,String(t.error||"console-direct-websocket-error"),!0,!1)}handleHttpResponse(e,t){const i=String(t.requestId||""),r=this.pendingHttp.get(i);if(!r||r.generation!==e.generation||!this.isPeerOwner(e))return;this.consecutiveLivenessRequestTimeouts=0,this.livenessMediaRecoveryGeneration=0;const s=this.mediaAttachmentHoldGeneration===e.generation;this.pendingHttp.delete(i),window.clearTimeout(r.timeout),r.detachAbort();try{const o=Number(t.status||502),a=t.bodyBase64?Pt(t.bodyBase64):new TextEncoder().encode(JSON.stringify({ok:!1,error:t.error||"console-direct-request-failed"})),c=new Response(a,{status:Number.isInteger(o)&&o>=200&&o<=599?o:502,statusText:String(t.statusText||""),headers:t.headers||{"content-type":"application/json"}});r.resolve(c),s&&(this.mediaAttachmentHoldGeneration=0,this.attachHeldMediaChannels(e))}catch(o){r.reject(q(o))}}async fetch(e,t,i){await Wt(this.connect(),t?.signal);const r=this.peerOwner;if(!r||!this.directReady||this.controlChannel?.readyState!=="open")throw p();if(this.pendingHttp.size>=Ce)throw new Error("console-direct-http-capacity-reached");const s=await _t(t?.body);if(s.byteLength>Et)throw new Error("console-direct-http-body-too-large");if(!this.isPeerOwner(r)||!this.directReady)throw p();if(this.pendingHttp.size>=Ce)throw new Error("console-direct-http-capacity-reached");if(t?.signal?.aborted)throw t.signal.reason||new Error("Mobile Console request cancelled.");const o=crypto.randomUUID(),a=Number.isFinite(i)&&i>0?Math.floor(i):4e3,c=String(t?.method||"GET").toUpperCase(),d=c==="GET"&&Ct.has(e),f=d?this.livenessEvidenceEpoch:null,l=new Promise((u,m)=>{const E=(C,w=!1)=>{const L=this.pendingHttp.get(o);if(L){this.pendingHttp.delete(o),window.clearTimeout(L.timeout),L.detachAbort();try{this.sendControl({type:"http-cancel",requestId:o})}catch{}m(C),w&&d&&this.recordLivenessRequestTimeout(r,L.livenessEvidenceEpoch)}},b=()=>E(t?.signal?.reason instanceof Error?t.signal.reason:new Error("Mobile Console request cancelled."));t?.signal?.addEventListener("abort",b,{once:!0});const h=window.setTimeout(()=>{E(new Error("Mobile Console direct request timed out."),!0)},a);this.pendingHttp.set(o,{generation:r.generation,livenessEvidenceEpoch:f,resolve:u,reject:m,timeout:h,detachAbort:()=>t?.signal?.removeEventListener("abort",b)})});try{this.sendControl({type:"http-request",requestId:o,method:c,path:e,headers:Nt(t),bodyBase64:s.byteLength>0?Rt(s):""})}catch(u){const m=this.pendingHttp.get(o);m&&(this.pendingHttp.delete(o),window.clearTimeout(m.timeout),m.detachAbort(),m.reject(q(u))),this.fail(p(),"control-send-failed",!0)}return l}openWebSocket(e,t){if(!Mt.has(t))throw new Error("console-direct-purpose-invalid");if(this.channels.size+this.mediaPeers.size>=gt)throw new Error("console-direct-channel-capacity-reached");const i=crypto.randomUUID(),r=new Bt(this,i,t,e),s={channelId:i,path:e,purpose:t,socket:r,owner:null,dataChannel:null,assembler:null,openDeadline:null,wireDeadline:null,wireScheduledAtEpochMs:0,wireStartedAtEpochMs:0,wireLastProgressAtEpochMs:0,wireAbsoluteDeadlineAtEpochMs:0,openRequested:!1,opened:!1,pendingInbound:[],pendingInboundBytes:0};return this.channels.set(i,s),this.connect().then(()=>{if(this.channels.get(i)===s){if(!this.mediaParent&&this.mediaPeerVersion===1&&this.peerOwner&&(t==="frame"||t==="atlas")){const o=new le({manager:this,owner:this.peerOwner,channelId:i});this.channels.delete(i),this.mediaPeers.set(i,o),o.channels.set(i,s),r.handoffConnectingOwner(o),o.connect().then(()=>{o.channels.get(i)===s&&o.attachLogicalChannel(s)}).catch(a=>{o.retireLogicalEntry(s,1011,q(a).message,!0,!1)});return}this.attachLogicalChannel(s)}}).catch(o=>{this.channels.get(i)===s&&this.retireLogicalEntry(s,1011,q(o).message,!0,!1)}),r}attachLogicalChannel(e){const t=this.peerOwner,i=this.peer,r=this.wireBudget;if(!t||!i||!r||!this.directReady||this.channels.get(e.channelId)!==e){this.retireLogicalEntry(e,1011,"console-direct-not-ready",!0,!1);return}const s=e.purpose==="frame"||e.purpose==="atlas";if(s&&this.mediaAttachmentHoldGeneration===t.generation)return;e.owner=t;let o;try{o=i.createDataChannel(`${lt}${e.channelId}:${e.purpose}`,{ordered:!0})}catch{this.retireLogicalOpenFailure(e,t,1011,"console-direct-channel-create-failed",!0,!0);return}o.binaryType="arraybuffer",e.dataChannel=o,e.assembler=me({budget:r,maxMessageBytes:s?Ie:k,maxPendingMessages:s?It:2}),this.refreshLogicalOpenDeadline(e,t,o),o.onopen=()=>{if(this.logicalEntryIsCurrent(e,t,o))try{this.sendControl({type:"ws-open",connectionId:t.connectionId,hubEpoch:t.hubEpoch,channelId:e.channelId,purpose:e.purpose,path:e.path}),e.openRequested=!0}catch{this.retireLogicalEntry(e,1011,"console-direct-ws-open-failed",!0,!1)}},o.onmessage=a=>{this.logicalEntryIsCurrent(e,t,o)&&this.handleLogicalWire(e,t,a.data)},o.onerror=()=>{this.logicalEntryIsCurrent(e,t,o)&&this.retireLogicalOpenFailure(e,t,1011,"console-direct-channel-error",!0,!1)},o.onclose=()=>{this.logicalEntryIsCurrent(e,t,o)&&this.retireLogicalOpenFailure(e,t,1006,"console-direct-channel-closed",!1,!1)}}retireLogicalOpenFailure(e,t,i,r,s,o){if(this.channels.get(e.channelId)!==e||!this.isPeerOwner(t))return;const a=!e.openRequested&&(e.purpose==="frame"||e.purpose==="atlas");this.logicalChannelFailureCount+=1,this.lastLogicalChannelFailure=Object.freeze({reason:String(r||"console-direct-logical-channel-failed").slice(0,120),purpose:e.purpose,generation:t.generation,occurredAt:Date.now()}),a&&(this.consecutiveMediaLogicalOpenFailures+=1);const c=[...this.channels.values()].some(f=>f!==e&&f.opened&&(f.purpose==="frame"||f.purpose==="atlas")&&f.dataChannel?.readyState==="open"),d=a&&!c&&(o||this.consecutiveMediaLogicalOpenFailures>=yt);this.retireLogicalEntry(e,i,r,s,!1),d&&this.isPeerOwner(t)&&this.fail(p(),"console-direct-media-channel-unusable",!0)}logicalEntryIsCurrent(e,t,i){return this.channels.get(e.channelId)===e&&e.owner===t&&e.dataChannel===i&&this.isPeerOwner(t)}clearLogicalOpenDeadline(e){e.openDeadline!==null&&(window.clearTimeout(e.openDeadline),e.openDeadline=null)}refreshLogicalOpenDeadline(e,t,i){this.clearLogicalOpenDeadline(e);const r=window.setTimeout(()=>{e.openDeadline===r&&(e.openDeadline=null,!(!this.logicalEntryIsCurrent(e,t,i)||e.opened)&&this.retireLogicalOpenFailure(e,t,1011,"console-direct-logical-open-timeout",!0,!1))},ht);e.openDeadline=r}invalidateLivenessEvidence(){this.livenessEvidenceEpoch+=1,this.consecutiveLivenessRequestTimeouts=0,this.livenessMediaRecoveryGeneration=0,this.peerOwner||(this.mediaAttachmentHoldGeneration=0)}attachHeldMediaChannels(e){if(!this.isPeerOwner(e)||!this.directReady)return 0;let t=0;for(const i of[...this.channels.values()])i.owner!==null||i.dataChannel!==null||i.purpose!=="frame"&&i.purpose!=="atlas"||(this.attachLogicalChannel(i),t+=1);return t}recoverControlFromMediaPressure(e){if(!this.isPeerOwner(e)||this.livenessMediaRecoveryGeneration===e.generation)return!1;const t=[...this.channels.values()].filter(i=>(i.purpose==="frame"||i.purpose==="atlas")&&i.owner===e&&i.dataChannel?.readyState==="open");if(t.length===0)return!1;this.livenessMediaRecoveryGeneration=e.generation,this.mediaAttachmentHoldGeneration=e.generation,this.livenessEvidenceEpoch+=1,this.consecutiveLivenessRequestTimeouts=0,this.controlMediaRecoveryCount+=1,this.lastControlMediaRecovery=Object.freeze({generation:e.generation,retiredMediaLanes:t.length,occurredAt:Date.now()});for(const i of t)this.retireLogicalEntry(i,1013,"console-direct-control-media-recovery",!1,!0);return!0}recordLivenessRequestTimeout(e,t){t===null||t!==this.livenessEvidenceEpoch||!this.isPeerOwner(e)||!this.directReady||(this.livenessRequestTimeoutCount+=1,this.consecutiveLivenessRequestTimeouts+=1,!(this.consecutiveLivenessRequestTimeouts<2)&&(this.recoverControlFromMediaPressure(e)||this.fail(p(),"control-http-timeout",!0)))}handleLogicalWire(e,t,i){const r=e.assembler;if(!r||!this.logicalEntryIsCurrent(e,t,e.dataChannel))return;const s=r.inspect();let o={chunkBytes:0,headerReadable:!1,messageId:0,chunkIndex:0,chunkCount:0,totalLength:0};try{o=xt(i);const a=r.push(re(i));if(this.refreshLogicalWireDeadline(e,t),!a)return;if(a.kind==="control")throw new Error("logical-control-forbidden");let c;if(a.kind==="text"&&typeof a.data=="string")c={kind:"text",data:a.data,byteLength:a.byteLength};else if(a.kind==="binary"&&a.data instanceof Uint8Array)c={kind:"binary",data:a.data,byteLength:a.byteLength};else throw new Error("logical-wire-kind-invalid");if(!e.opened){this.queuePreOpenLogicalMessage(e,c);return}this.deliverLogicalMessage(e,c)}catch(a){this.logicalWireFailureCount+=1,this.lastLogicalWireFailure=Object.freeze({errorCode:a instanceof B?a.code:a instanceof Error?a.message.slice(0,120):"logical-wire-invalid",purpose:e.purpose,generation:t.generation,pendingMessagesBefore:Math.max(0,Number(s.pendingMessages||0)),pendingBytesBefore:Math.max(0,Number(s.pendingBytes||0)),...o,occurredAt:Date.now()}),this.retireLogicalEntry(e,1011,"console-direct-wire-invalid",!0,!1)}}queuePreOpenLogicalMessage(e,t){const i=e.purpose==="frame"||e.purpose==="atlas",r=i?Ie:k;if(i){if(e.pendingInbound.length===0){e.pendingInbound.push(t),e.pendingInboundBytes=t.byteLength;return}if(e.pendingInbound.length<vt&&e.pendingInboundBytes+t.byteLength<=r){e.pendingInbound.push(t),e.pendingInboundBytes+=t.byteLength;return}const s=e.pendingInbound[0],o=s.byteLength+t.byteLength,a=o<=r?"replace-latest":"drop-over-budget";a==="replace-latest"&&(e.pendingInbound=[s,t],e.pendingInboundBytes=o),this.preOpenMediaCoalesceCount+=1,this.lastPreOpenMediaCoalesce=Object.freeze({action:a,purpose:e.purpose==="atlas"?"atlas":"frame",generation:e.owner?.generation||0,retainedMessages:e.pendingInbound.length,retainedBytes:e.pendingInboundBytes,incomingBytes:t.byteLength,occurredAt:Date.now()});return}if(e.pendingInbound.length>=Lt||e.pendingInboundBytes+t.byteLength>r)throw new Error("logical-preopen-buffer-full");e.pendingInbound.push(t),e.pendingInboundBytes+=t.byteLength}deliverLogicalMessage(e,t){if(t.kind==="text"){e.socket.managerMessage(t.data);return}const i=t.data;if(e.socket.binaryType==="arraybuffer"){const r=i.buffer instanceof ArrayBuffer&&i.byteOffset===0&&i.byteLength===i.buffer.byteLength?i.buffer:i.slice().buffer;e.socket.managerMessage(r)}else e.socket.managerMessage(new Blob([i]))}logicalBufferedAmount(e){return Number(this.channels.get(e)?.dataChannel?.bufferedAmount||0)}clearLogicalWireDeadline(e){e.wireDeadline!==null&&(window.clearTimeout(e.wireDeadline),e.wireDeadline=null),e.wireScheduledAtEpochMs=0,e.wireStartedAtEpochMs=0,e.wireLastProgressAtEpochMs=0,e.wireAbsoluteDeadlineAtEpochMs=0}scheduleLogicalWireDeadline(e,t){const i=e.purpose==="frame"||e.purpose==="atlas",r=Date.now(),s=e.assembler?.inspect(),o=i?we(Number(s?.pendingBytes||0)):Number.POSITIVE_INFINITY,a=i?Math.max(1,o-(r-e.wireLastProgressAtEpochMs)):Number.POSITIVE_INFINITY,c=Math.max(1,e.wireAbsoluteDeadlineAtEpochMs-r),d=Math.min(a,c),f=r+d;if(e.wireDeadline!==null&&e.wireScheduledAtEpochMs<=f)return;e.wireDeadline!==null&&window.clearTimeout(e.wireDeadline);const l=window.setTimeout(()=>{if(e.wireDeadline!==l)return;e.wireDeadline=null,e.wireScheduledAtEpochMs=0;const u=e.dataChannel;if(!u||!this.logicalEntryIsCurrent(e,t,u))return;const m=e.assembler?.inspect(),E=Number(m?.pendingMessages||0);if(E===0){this.clearLogicalWireDeadline(e);return}const b=Date.now(),h=Math.max(0,b-e.wireLastProgressAtEpochMs),C=Math.max(0,b-e.wireStartedAtEpochMs),w=i?we(Number(m?.pendingBytes||0)):Number.POSITIVE_INFINITY;if(!(!i||h>=w||b>=e.wireAbsoluteDeadlineAtEpochMs)){this.scheduleLogicalWireDeadline(e,t);return}if(i){this.partialMediaWireTimeoutCount+=1,this.lastPartialMediaWireTimeout=Object.freeze({recovery:"abandon-message",purpose:e.purpose,generation:t.generation,pendingMessages:E,pendingBytes:Math.max(0,Number(m?.pendingBytes||0)),stalledForMs:h,lifetimeMs:C,idleDeadlineMs:w,absoluteDeadlineMs:Math.max(0,e.wireAbsoluteDeadlineAtEpochMs-e.wireStartedAtEpochMs),occurredAt:b}),e.assembler?.abandonPending(),this.clearLogicalWireDeadline(e);return}this.retireLogicalEntry(e,1011,"console-direct-partial-message-timeout",!0,!1)},d);e.wireDeadline=l,e.wireScheduledAtEpochMs=f}refreshLogicalWireDeadline(e,t){const i=e.assembler?.inspect();if(Number(i?.pendingMessages||0)===0){this.clearLogicalWireDeadline(e);return}const s=Date.now(),o=e.purpose==="frame"||e.purpose==="atlas";e.wireStartedAtEpochMs<=0&&(e.wireStartedAtEpochMs=s,e.wireAbsoluteDeadlineAtEpochMs=s+(o?nt(Number(i?.pendingBytes||0)):pt)),e.wireLastProgressAtEpochMs=s,this.scheduleLogicalWireDeadline(e,t)}sendLogicalMessage(e,t){const i=this.channels.get(e),r=i?.dataChannel;if(!i||!r||!i.opened||r.readyState!=="open")throw new DOMException("WebSocket is not open.","InvalidStateError");try{if(typeof t=="string")this.sendWire(r,t,"text",k);else if(t instanceof ArrayBuffer)this.sendWire(r,t,"binary",k);else if(ArrayBuffer.isView(t)){const s=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);this.sendWire(r,s,"binary",k)}else throw new DOMException("Blob sends are not supported by the direct Console channel.","NotSupportedError")}catch(s){throw this.retireLogicalEntry(i,1011,"console-direct-send-failed",!0,!1),s}}closeLogicalChannel(e,t,i,r){const s=this.channels.get(e);s&&this.retireLogicalEntry(s,t,i,!1,r)}retireLogicalEntry(e,t,i,r,s){if(this.channels.get(e.channelId)!==e)return;this.channels.delete(e.channelId);const o=e.dataChannel,a=e.owner;if(s&&a&&e.openRequested&&this.isPeerOwner(a)&&this.controlChannel?.readyState==="open")try{this.sendControl({type:"ws-close",connectionId:a.connectionId,hubEpoch:a.hubEpoch,channelId:e.channelId,code:t,reason:i})}catch{r=!0}if(this.clearLogicalWireDeadline(e),this.clearLogicalOpenDeadline(e),e.assembler?.dispose(),e.assembler=null,e.pendingInbound=[],e.pendingInboundBytes=0,e.dataChannel=null,e.owner=null,e.openRequested=!1,e.opened=!1,o){o.onopen=null,o.onmessage=null,o.onerror=null,o.onclose=null;try{o.close()}catch{}}e.socket.managerClosed(t,i,r),this.mediaParent&&this.channels.size===0&&this.peerOwner&&this.teardown(i||"media-lane-idle",null,!0)}}const I=new le;function Oe(n){I.configure(n)}function Ut(){I.preferDirect()}function Ht(){I.markLocalHubReachable()}function hn(){I.resume()}function fn(){I.suspendLivenessEvidence()}function pn(){I.retry()}function J(n,e,t){return I.preferDirect(),I.fetch(n,e,t)}function gn(n,e,t){return I.shouldUseDirect()?I.openWebSocket(e,t):new WebSocket(n)}function mn(){return I.inspect()}function Ft(n){let e=null;return{run(){if(e)return e;const t=Promise.resolve().then(n);e=t.finally(()=>{(e===t||e===i)&&(e=null)});const i=e;return i}}}async function qt(n,e){return n&&await n.catch(()=>{}),e()}function Gt(n,e={}){if(e.publicConsole===!0)throw new Error("Public Console does not create a Hub cookie session.");return n?.workspaceKind==="team"&&n?.workspaceRole==="operator"?{accessToken:n.accessToken,workspaceId:n.workspaceId}:{accessToken:n.accessToken,refreshToken:n.refreshToken,expiresAt:n.expiresAt,user:n.user,workspaceId:n.workspaceId}}function ue(n){return!n?.user?.id||!n?.workspaceId?"":[n.user.id,n.workspaceId,n.workspaceKind,n.workspaceRole,Number(n.membershipRevision||0)].join(`
7
+ `)}function jt(n){const e=ue(n);return!e||!n?.accessToken||!n?.refreshToken?"":[e,n.accessToken,n.refreshToken,Number(n.expiresAt||0)].join(`
8
+ `)}function $t({publicConsole:n,path:e,requiresUiSession:t}){return n?String(e||"").split("?")[0]==="/api/auth/session"?"reject-auth-session":t?"direct":"local":"local"}const x=5179,P=H(`http://127.0.0.1:${x}`);function Vt(n){const e=n.split(".").map(t=>Number(t));return e.length===4&&e.every(t=>Number.isInteger(t)&&t>=0&&t<=255)?e:[]}function De(n){const e=n.trim().toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"||e==="[::1]"}function zt(n){const e=n.trim().toLowerCase();return!e||e==="0.0.0.0"||e==="::"||e==="[::]"}function Re(n){const e=Vt(n);return e.length===0?!1:e[0]===10||e[0]===172&&e[1]>=16&&e[1]<=31||e[0]===192&&e[1]===168}function Xt(n){return n.includes(":")&&!n.startsWith("[")?`[${n}]`:n}function Yt(n){const e=String(n||"").trim();if(!e)return null;const t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`tcp://${e}`;try{const i=new URL(t),r=i.hostname.replace(/^\[|\]$/g,""),s=Number(i.port);return!r||!Number.isInteger(s)||s<1||s>65535||zt(r)?null:{host:r,port:s}}catch{return null}}function H(n){const e=String(n||"").trim()||`http://127.0.0.1:${x}`,t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`http://${e}`;try{const i=new URL(t);return i.port||(i.port=String(x)),i.hash="",i.search="",i.toString().replace(/\/+$/,"")}catch{return`http://127.0.0.1:${x}`}}function Kt(n){const e=Yt(n);return e?H(`http://${Xt(e.host)}:${x}`):""}function wn(n){const t=[n?.endpoint,...Array.isArray(n?.endpoint_candidates)?n.endpoint_candidates:[]].map(i=>Kt(String(i||""))).filter(Boolean);return[...new Set(t)]}function Jt(n=P){if(!(typeof window>"u"||window.location.protocol!=="https:"))try{const e=new URL(n);if(e.protocol!=="http:")return;if(De(e.hostname))return"loopback";if(Re(e.hostname))return"local"}catch{return}}function bn(n,e=P){const t=new URL(n,H(e));return t.protocol=t.protocol==="https:"?"wss:":"ws:",t.toString()}let v=null,R="",T="";const y=new Map,D=new Map,U=new Map,j=new Set;function z(n){const e=U.get(n);e!==void 0&&typeof window<"u"&&window.clearTimeout(e),U.delete(n)}function Pe(){for(const n of U.keys())z(n)}function se(n){const e=Number(n||0);if(Number.isFinite(e)&&e>0)return e<1e10?e*1e3:e;const t=Date.parse(String(n||""));return Number.isFinite(t)?t:0}function _e(n,e,t){if(z(n),typeof window>"u"||e<=Date.now())return;const i=Math.max(1e3,Math.min(45e3,e-Date.now()-15e3)),r=window.setTimeout(()=>{U.delete(n),!(t!==R||v?.workspaceKind!=="team")&&V(n,!0).catch(()=>{})},i);U.set(n,r)}function Qt(n,e,t){const i=v?.workspaceKind==="team",r=i?se(e.accessExpiresAt)||Date.now()+6e4:0;y.set(n,{csrfToken:e.csrfToken,expiresAt:e.expiresAt,accessExpiresAt:r,ownerSignature:T}),j.add(n),i?_e(n,r,t):z(n)}function En(n){const e=n?.accessToken&&n?.refreshToken&&n?.user?.id?n:null,t=ue(e),i=jt(e);if(t!==T&&(e&&y.clear(),T=t),i!==R&&(Pe(),R=i,e?.workspaceKind==="team"))for(const[r,s]of y)s.ownerSignature===t&&_e(r,s.accessExpiresAt,i);v=e,Oe(e?{accessToken:e.accessToken,user:{id:e.user.id},workspaceId:e.workspaceId,workspaceKind:e.workspaceKind,workspaceRole:e.workspaceRole,membershipRevision:e.membershipRevision}:null),e&&X()&&Ut()}function X(){if(typeof window>"u"||window.location.protocol!=="https:")return!1;const n=window.location.hostname.replace(/^\[|\]$/g,"");return!De(n)&&!Re(n)}function Q(n){const e=n.split("?")[0];return e==="/api/health"||e==="/api/runtime/status"||e==="/api/auth/status"||e==="/api/auth/session"}async function $(n,e,t,i,r){const s=Jt(t);return s&&(e.targetAddressSpace=s),We(r,i,async o=>{e.signal=o;try{return await fetch(`${t}${n}`,e)}catch(a){throw!o.aborted&&s?new Error("VuvoDesk Hub is not reachable at this local network address. If Chrome shows a local network prompt, allow it; otherwise restart the Hub so port 5179 is open on the network."):a}})}async function V(n,e=!1){if(X())throw new Error("Public Console uses verified P2P authorization instead of a Hub cookie session.");const t=y.get(n);if(!e&&t&&t.ownerSignature===T&&t.expiresAt>Date.now()+3e4&&(t.accessExpiresAt===0||t.accessExpiresAt>Date.now()+15e3))return;e&&y.delete(n);const i=v,r=R;if(!i)return;const s=D.get(n);if(s)return s.authSignature===r?s.promise:s.promise.catch(()=>{}).then(()=>V(n,e));let o;const a=(async()=>{const c=await $("/api/auth/session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Gt(i,{publicConsole:!1})),credentials:"include",cache:"no-store"},n,W),d=await c.json().catch(()=>null);if(!c.ok)throw new Error(`${c.status} ${d?.error||c.statusText}`);const f=String(d?.uiSession?.csrfToken||"").trim(),l=Number(d?.uiSession?.expiresAt||0);if(!f||!Number.isFinite(l)||l<=Date.now())throw new Error("VuvoDesk Hub did not issue a valid UI session.");if(r!==R)throw y.set(n,{csrfToken:f,expiresAt:l,accessExpiresAt:se(d?.uiSession?.accessExpiresAt),ownerSignature:ue(i)}),j.add(n),new Error("VuvoDesk workspace changed while the Hub session was opening.");Qt(n,{csrfToken:f,expiresAt:l,accessExpiresAt:se(d?.uiSession?.accessExpiresAt)},r)})().finally(()=>{D.get(n)===o&&D.delete(n)});return o={authSignature:r,promise:a},D.set(n,o),a}async function Zt(){const n=new Set(j);for(const t of D.keys())n.add(t);X()||n.add(H(P));const e=[...n].map(t=>qt(D.get(t)?.promise,async()=>{const i=y.get(t),r=await $("/api/auth/session",{method:"DELETE",headers:i?.csrfToken?{"X-LiveDesk-CSRF":i.csrfToken}:{},credentials:"include",cache:"no-store"},t,W);if(!r.ok&&r.status!==401){const s=await r.json().catch(()=>null);throw new Error(`${r.status} ${s?.error||r.statusText}`)}j.delete(t),y.delete(t),z(t)}));await Promise.all(e)}const en=Ft(Zt);function Cn(){return v=null,R="",T="",Pe(),Oe(null),en.run()}async function tn(n,e,t=P){const i=H(t),{timeoutMs:r=W,signal:s,transport:o="auto",...a}=e||{},c=!Q(n),d=c?T:"",f=()=>!c||!!d&&d===T,l=()=>{if(!f())throw new Error("VuvoDesk workspace changed while the Hub request was running.")},u=$t({publicConsole:X(),path:n,requiresUiSession:c});if(c&&!v)throw new Error("VuvoDesk account authority is not available for this Hub request.");const m=()=>{const E=String(a.method||"GET").toUpperCase(),b=y.get(i),h=b?.ownerSignature===T?b.csrfToken:"";return{...a,...s?{signal:s}:{},headers:{...a.headers||{},...!["GET","HEAD","OPTIONS"].includes(E)&&h?{"X-LiveDesk-CSRF":h}:{}},credentials:"include",cache:"no-store"}};if(u==="reject-auth-session")throw new Error("Public Console does not create a Hub cookie session.");if(u==="direct"){if(l(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");return J(n,m(),r)}if(o==="p2p"){if(l(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");if(!v||Q(n))throw new Error("Mobile Console direct connection requires an authenticated management request.");return J(n,m(),r)}try{c&&await V(i),l();let E=await $(n,m(),i,r,s);if(l(),Ht(),c&&E.status===401&&v){const b=await E.clone().json().catch(()=>null);/^hub-ui-session-(required|expired)$/.test(String(b?.error||""))&&(await V(i,!0),l(),E=await $(n,m(),i,r,s),l())}return E}catch(E){if(!f()||s?.aborted||!v||Q(n))throw E;return J(n,m(),r)}}async function nn(n,e,t=P){const i=await tn(n,{...e||{},headers:{"Content-Type":"application/json",...e?.headers||{}}},t);let r=null;try{r=await i.json()}catch(s){if(e?.signal?.aborted)throw s;r=null}if(!i.ok){const s=r&&typeof r=="object"&&"error"in r?String(r.error||""):"";throw new Error(`${i.status} ${s||i.statusText}`)}return r}async function Sn({baseUrl:n=P,targetRole:e,previousRuntimePid:t=0,allowedStates:i=["running","waiting-auth"],timeoutMs:r=3e4}){const s=Date.now()+r;let o=null;for(;Date.now()<s;){try{const c=await nn("/api/runtime/status",void 0,n),d=String(c.role||"").toLowerCase(),f=String(c.state||"").toLowerCase(),l=Number(c.runtimePid||0),u=t>1?l>1&&l!==t:l>1;if(d===e&&i.map(m=>m.toLowerCase()).includes(f)&&u)return c}catch(c){o=c}await new Promise(c=>setTimeout(c,300))}const a=o instanceof Error?` ${o.message}`:"";throw new Error(`VuvoDesk runtime did not become ${e} with a new process.${a}`)}function In(n,e=120){if(typeof window>"u")return;const t=new URL(window.location.href);t.port=String(n),t.pathname="/",t.search="",t.hash="";const i=t.toString();let r=0;const s=()=>{fetch(i,{cache:"no-store",mode:"no-cors"}).then(()=>window.location.replace(i)).catch(()=>{if(r+=1,r>=e){window.location.replace(i);return}window.setTimeout(s,250)})};s()}function Ln(n){if(!n)return"-";const e=Date.now()-Date.parse(n);return Number.isFinite(e)?e<1e3?"now":e<6e4?`${Math.round(e/1e3)}s`:e<36e5?`${Math.round(e/6e4)}m`:`${Math.round(e/36e5)}h`:"-"}async function vn(n){await navigator.clipboard.writeText(n)}const rn=5,Le=20,sn=50,on=Number.POSITIVE_INFINITY,an=5,yn={free:{name:"Free",price:"$0",limit:rn,people:1,audience:"Personal, ad-supported",note:"Up to 5 personal devices supported by a standard banner."},ltd:{name:"Plus",price:"$5",ltd:"$79 LTD",limit:Le,people:1,audience:"Creators and homelabs",note:`${Le} devices, no ads, personal use.`},pro:{name:"Pro / Business",price:"$15",ltd:"$199 LTD",limit:sn,people:1,audience:"Schools, academies, studios, and businesses",note:"Up to 50 devices for school, academy, and commercial use."},team:{name:"Team",price:"$49",limit:on,people:an,audience:"Shared business operations",note:"Commercial use, a shared Team Space, and up to 5 people using their own accounts."}},cn="0.1.697",ln={version:cn},kn=String(ln.version).trim();function Mn({size:n=22}){return A.jsxs("svg",{width:n,height:n,viewBox:"0 0 28 28",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[A.jsx("rect",{x:"2.5",y:"4",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.42"}),A.jsx("path",{d:"M7 16v1.5h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.42"}),A.jsx("rect",{x:"10.5",y:"2.5",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.62"}),A.jsx("path",{d:"M15 14.5V16h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.62"}),A.jsx("rect",{x:"6.5",y:"8.5",width:"15",height:"10",rx:"1.7",fill:"currentColor",fillOpacity:"0.12",stroke:"currentColor",strokeWidth:"1.9"}),A.jsx("path",{d:"M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9",stroke:"currentColor",strokeWidth:"1.9",strokeLinecap:"round"})]})}export{P as D,rn as F,kn as L,Mn as M,Le as P,an as T,sn as a,Cn as b,vn as c,K as d,pn as e,Ln as f,Jt as g,nn as h,X as i,gn as j,bn as k,H as l,hn as m,In as n,tn as o,yn as p,En as q,dn as r,fn as s,wn as t,mn as u,Sn as w};
@@ -1 +1 @@
1
- import{j as e}from"./pwa-startup-BiuYh5eN.js";import{r as i,W as ee,S as te,F as q,b as be,M as F,c as je,L as Re,P as we,A as $}from"./icons-ChMazCZR.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-CiDB9DkB.js";import"./pwa-bootstrap-ljOQTt2e.js";const v={revision:0,settings:{connection:{showThisComputer:!1,temporaryRouterMapping:!1},security:{accessMode:"trusted-only"},control:{allowKeyboardMouse:!0,allowRemoteRestart:!1},filesAudio:{allowFileTransfer:!0,allowRemoteAudio:!0,rollingBufferEnabled:!1,recordingQuality:"standard",timelapseIntervalSeconds:10,includeRemoteCursor:!0}}},Z=[{id:"connection",label:"Connection",icon:ee},{id:"remote-access",label:"Remote Access",icon:te},{id:"capture-audio",label:"Capture & Audio",icon:q},{id:"agent",label:"Agent",icon:be}];function A(t,n){return t?.settings?.[n]||v.settings[n]||{}}function _(t,n){return{...t,settings:{...t.settings,[n.section]:{...A(t,n.section),[n.key]:n.value}}}}function O(t){return{revision:Number(t.revision||0),updatedAt:t.updatedAt,settings:t.settings}}function h({icon:t,title:n,description:a,children:m,recommended:l=!1}){return e.jsxs("div",{className:"product-setting-row",children:[e.jsx("div",{className:"product-setting-control",children:m}),t&&e.jsx("span",{className:"product-setting-icon",children:e.jsx(t,{size:17})}),e.jsxs("div",{className:"product-setting-copy",children:[e.jsx("strong",{children:n}),l&&e.jsx("em",{children:"Recommended"}),e.jsx("small",{children:a})]})]})}function x({checked:t,onChange:n,label:a}){return e.jsxs("label",{className:"product-switch",children:[e.jsx("input",{"aria-label":a,type:"checkbox",checked:t,onChange:m=>n(m.target.checked)}),e.jsx("span",{})]})}function U({value:t,onChange:n,options:a,label:m}){return e.jsx("select",{"aria-label":m,value:String(t),onChange:l=>n(l.target.value),children:a.map(([l,K])=>e.jsx("option",{value:l,children:K},l))})}function Te({hubUrl:t="",mobileLayout:n=!1,runtimeRole:a="hub",runtimeDeviceId:m="",sessionAccessToken:l="",showThisComputerSetting:K=!0,onShowThisComputerChange:D,initialTab:J="connection",pin:se,agent:ne,captureGallery:ie,desktopUpdate:oe}){const[r,Q]=i.useState(()=>n&&J==="connection"?"remote-access":J),[b,k]=i.useState(null),[re,j]=i.useState("loading"),[G,T]=i.useState(""),[z,E]=i.useState("idle"),[L,H]=i.useState(""),R=i.useRef(null),g=i.useRef(null),p=i.useRef([]),M=i.useRef(Promise.resolve()),ce=i.useRef(0),f=i.useRef(0);i.useEffect(()=>{const s=++f.current;let u=!0;return p.current=[],g.current=null,R.current=null,M.current=Promise.resolve(),j("loading"),C("/api/settings",void 0,t).then(o=>{if(!u||s!==f.current)return;const c=O(o);g.current=c,R.current=c,k(c),j("saved")}).catch(o=>{!u||s!==f.current||(T(o instanceof Error?o.message:String(o)),g.current=v,R.current=v,k(v),j("failed"))}),()=>{u=!1}},[t]);const ae=async(s,u,o)=>{const c={id:++ce.current,section:s,key:u,value:o},I=f.current;p.current.push(c);const X=_(R.current||g.current||v,c);R.current=X,k(X),j("saving"),T(""),M.current=M.current.then(async()=>{if(I!==f.current)return;let S=null,y=null;for(let N=0;N<2&&!S;N+=1){const ve=g.current||v;try{const w=await C("/api/settings",{method:"PATCH",body:JSON.stringify({revision:ve.revision,[c.section]:{[c.key]:c.value}})},t);S=O(w)}catch(w){if(y=w,N!==0||!String(w instanceof Error?w.message:w).startsWith("409 "))break;try{const W=await C("/api/settings",void 0,t);if(I!==f.current)return;g.current=O(W)}catch(W){y=W;break}}}if(I!==f.current)return;p.current=p.current.filter(N=>N.id!==c.id),S&&(g.current=S);const xe=g.current||v,Y=p.current.reduce(_,xe);R.current=Y,k(Y),S?(T(""),j(p.current.length>0?"saving":"saved")):(j(p.current.length>0?"saving":"failed"),T(y instanceof Error?y.message:String(y||"Settings could not be saved.")))}),await M.current},d=(s,u)=>o=>{ae(s,u,o)},le=async()=>{if(a!=="hub"||!m||!l){E("failed"),H("Sign in to this Hub before changing its runtime role.");return}E("changing"),H("");try{const s=await C("/api/runtime/status",void 0,t);await C("/api/runtime/role",{method:"POST",headers:{Authorization:`Bearer ${l}`},body:JSON.stringify({role:"client"})},t),E("accepted"),await Se({baseUrl:t,targetRole:"client",previousRuntimePid:Number(s.runtimePid||0),allowedStates:["running","waiting-auth"]}),ye(5179)}catch(s){E("failed"),H(s instanceof Error?s.message:String(s))}},de=A(b,"security"),V=A(b,"control"),B=A(b,"filesAudio"),P=A(b,"connection"),ue=`settings-panel-${r}`,he=n?Z.filter(s=>s.id!=="connection"):Z;i.useEffect(()=>{n&&r==="connection"&&Q("remote-access")},[r,n]),i.useEffect(()=>{b&&D?.(!!P.showThisComputer)},[P.showThisComputer,D,b]);const ge=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[se,oe,a==="hub"&&e.jsx("section",{className:"settings-section-card",children:e.jsx(h,{icon:ee,title:"Help mobile devices connect",description:"Temporarily opens a router port while a direct mobile connection starts, then removes it. Uses no video relay. Requires a compatible router.",children:e.jsx(x,{checked:!!P.temporaryRouterMapping,onChange:d("connection","temporaryRouterMapping"),label:"Help mobile devices connect"})})}),K&&e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Hub computer list"}),e.jsx("h3",{children:"This computer"})]}),e.jsx(F,{size:20})]}),e.jsx(h,{icon:F,title:"Show this computer",description:"Show this Hub computer in its own Wall and computer lists. It stays available from other computers and the mobile app when hidden.",children:e.jsx(x,{checked:!!P.showThisComputer,onChange:d("connection","showThisComputer"),label:"Show this computer"})})]}),e.jsxs("section",{className:"settings-section-card runtime-role-settings",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Runtime role"}),e.jsx("h3",{children:"Use this computer as a Client"})]}),e.jsx(je,{size:20})]}),e.jsx("p",{className:"settings-help",children:"Stop hosting from this computer and reconnect it to the selected Hub."}),z==="accepted"?e.jsx("p",{className:"settings-help runtime-role-success",children:"VuvoDesk is restarting as Client."}):L?e.jsx("p",{className:"settings-help runtime-role-error",role:"alert",children:L}):null,e.jsx("button",{className:"settings-reset",onClick:()=>{le()},disabled:z==="changing"||a!=="hub",type:"button",children:z==="changing"?"Switching role...":"Switch this computer to Client"})]})]}),me=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Remote access"}),e.jsx("h3",{children:"Who may connect?"})]}),e.jsx(Re,{size:20})]}),e.jsx(h,{icon:te,title:"Access mode",description:"Choose the default permission boundary for remote sessions.",recommended:!0,children:e.jsx(U,{value:String(de.accessMode),onChange:d("security","accessMode"),label:"Access mode",options:[["trusted-only","Trusted devices only"],["block-remote-access","Block remote access"]]})})]}),e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Session permissions"}),e.jsx("h3",{children:"What may remote users do?"})]}),e.jsx(F,{size:20})]}),e.jsx(h,{icon:F,title:"Keyboard and mouse control",description:"Allow Control to send keyboard and pointer input.",recommended:!0,children:e.jsx(x,{checked:!!V.allowKeyboardMouse,onChange:d("control","allowKeyboardMouse"),label:"Keyboard and mouse control"})}),e.jsx(h,{icon:we,title:"Power actions",description:"Allow confirmed sleep, restart, and shut down commands from the Hub.",children:e.jsx(x,{checked:!!V.allowRemoteRestart,onChange:d("control","allowRemoteRestart"),label:"Power actions"})}),e.jsx(h,{icon:q,title:"File transfer",description:"Allow files to be delivered to connected computers.",children:e.jsx(x,{checked:!!B.allowFileTransfer,onChange:d("filesAudio","allowFileTransfer"),label:"File transfer"})}),e.jsx(h,{icon:$,title:"Remote audio",description:"Allow sound capture from connected computers.",children:e.jsx(x,{checked:!!B.allowRemoteAudio,onChange:d("filesAudio","allowRemoteAudio"),label:"Remote audio"})})]})]}),pe=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Capture"}),e.jsx("h3",{children:"Recording defaults"})]}),e.jsx(q,{size:20})]}),e.jsx(h,{icon:$,title:"Keep a Last 30s buffer",description:"Keep recent video in memory until you explicitly save it.",children:e.jsx(x,{checked:!!B.rollingBufferEnabled,onChange:d("filesAudio","rollingBufferEnabled"),label:"Keep a Last 30s buffer"})}),e.jsx(h,{icon:$,title:"Timelapse interval",description:"Choose how often a timelapse frame is captured.",children:e.jsx(U,{value:Number(B.timelapseIntervalSeconds),onChange:s=>d("filesAudio","timelapseIntervalSeconds")(Number(s)),label:"Timelapse interval",options:[["5","5 seconds"],["10","10 seconds"],["30","30 seconds"],["60","60 seconds"]]})})]}),ie]}),fe=r==="connection"?ge:r==="remote-access"?me:r==="capture-audio"?pe:ne;return e.jsxs("section",{className:"settings-page",children:[e.jsx("div",{className:"settings-page-tabs",role:"tablist","aria-label":"VuvoDesk settings",children:he.map(({id:s,label:u,icon:o})=>e.jsxs("button",{className:r===s?"active":"",id:`settings-tab-${s}`,role:"tab","aria-selected":r===s,"aria-controls":`settings-panel-${s}`,tabIndex:r===s?0:-1,onClick:()=>Q(s),type:"button",children:[e.jsx(o,{size:16}),u]},s))}),re==="saving"&&e.jsx("div",{className:"product-save-state",role:"status",children:"Saving settings..."}),G&&e.jsx("div",{className:"agent-settings-alert error",role:"alert",children:G}),e.jsx("section",{className:"settings-page-panel",id:ue,role:"tabpanel","aria-labelledby":`settings-tab-${r}`,tabIndex:0,children:fe})]})}export{Te as SettingsPage};
1
+ import{j as e}from"./pwa-startup-BiuYh5eN.js";import{r as i,W as ee,S as te,F as q,b as be,M as F,c as je,L as Re,P as we,A as $}from"./icons-ChMazCZR.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-led0pnag.js";import"./pwa-bootstrap-ljOQTt2e.js";const v={revision:0,settings:{connection:{showThisComputer:!1,temporaryRouterMapping:!1},security:{accessMode:"trusted-only"},control:{allowKeyboardMouse:!0,allowRemoteRestart:!1},filesAudio:{allowFileTransfer:!0,allowRemoteAudio:!0,rollingBufferEnabled:!1,recordingQuality:"standard",timelapseIntervalSeconds:10,includeRemoteCursor:!0}}},Z=[{id:"connection",label:"Connection",icon:ee},{id:"remote-access",label:"Remote Access",icon:te},{id:"capture-audio",label:"Capture & Audio",icon:q},{id:"agent",label:"Agent",icon:be}];function A(t,n){return t?.settings?.[n]||v.settings[n]||{}}function _(t,n){return{...t,settings:{...t.settings,[n.section]:{...A(t,n.section),[n.key]:n.value}}}}function O(t){return{revision:Number(t.revision||0),updatedAt:t.updatedAt,settings:t.settings}}function h({icon:t,title:n,description:a,children:m,recommended:l=!1}){return e.jsxs("div",{className:"product-setting-row",children:[e.jsx("div",{className:"product-setting-control",children:m}),t&&e.jsx("span",{className:"product-setting-icon",children:e.jsx(t,{size:17})}),e.jsxs("div",{className:"product-setting-copy",children:[e.jsx("strong",{children:n}),l&&e.jsx("em",{children:"Recommended"}),e.jsx("small",{children:a})]})]})}function x({checked:t,onChange:n,label:a}){return e.jsxs("label",{className:"product-switch",children:[e.jsx("input",{"aria-label":a,type:"checkbox",checked:t,onChange:m=>n(m.target.checked)}),e.jsx("span",{})]})}function U({value:t,onChange:n,options:a,label:m}){return e.jsx("select",{"aria-label":m,value:String(t),onChange:l=>n(l.target.value),children:a.map(([l,K])=>e.jsx("option",{value:l,children:K},l))})}function Te({hubUrl:t="",mobileLayout:n=!1,runtimeRole:a="hub",runtimeDeviceId:m="",sessionAccessToken:l="",showThisComputerSetting:K=!0,onShowThisComputerChange:D,initialTab:J="connection",pin:se,agent:ne,captureGallery:ie,desktopUpdate:oe}){const[r,Q]=i.useState(()=>n&&J==="connection"?"remote-access":J),[b,k]=i.useState(null),[re,j]=i.useState("loading"),[G,T]=i.useState(""),[z,E]=i.useState("idle"),[L,H]=i.useState(""),R=i.useRef(null),g=i.useRef(null),p=i.useRef([]),M=i.useRef(Promise.resolve()),ce=i.useRef(0),f=i.useRef(0);i.useEffect(()=>{const s=++f.current;let u=!0;return p.current=[],g.current=null,R.current=null,M.current=Promise.resolve(),j("loading"),C("/api/settings",void 0,t).then(o=>{if(!u||s!==f.current)return;const c=O(o);g.current=c,R.current=c,k(c),j("saved")}).catch(o=>{!u||s!==f.current||(T(o instanceof Error?o.message:String(o)),g.current=v,R.current=v,k(v),j("failed"))}),()=>{u=!1}},[t]);const ae=async(s,u,o)=>{const c={id:++ce.current,section:s,key:u,value:o},I=f.current;p.current.push(c);const X=_(R.current||g.current||v,c);R.current=X,k(X),j("saving"),T(""),M.current=M.current.then(async()=>{if(I!==f.current)return;let S=null,y=null;for(let N=0;N<2&&!S;N+=1){const ve=g.current||v;try{const w=await C("/api/settings",{method:"PATCH",body:JSON.stringify({revision:ve.revision,[c.section]:{[c.key]:c.value}})},t);S=O(w)}catch(w){if(y=w,N!==0||!String(w instanceof Error?w.message:w).startsWith("409 "))break;try{const W=await C("/api/settings",void 0,t);if(I!==f.current)return;g.current=O(W)}catch(W){y=W;break}}}if(I!==f.current)return;p.current=p.current.filter(N=>N.id!==c.id),S&&(g.current=S);const xe=g.current||v,Y=p.current.reduce(_,xe);R.current=Y,k(Y),S?(T(""),j(p.current.length>0?"saving":"saved")):(j(p.current.length>0?"saving":"failed"),T(y instanceof Error?y.message:String(y||"Settings could not be saved.")))}),await M.current},d=(s,u)=>o=>{ae(s,u,o)},le=async()=>{if(a!=="hub"||!m||!l){E("failed"),H("Sign in to this Hub before changing its runtime role.");return}E("changing"),H("");try{const s=await C("/api/runtime/status",void 0,t);await C("/api/runtime/role",{method:"POST",headers:{Authorization:`Bearer ${l}`},body:JSON.stringify({role:"client"})},t),E("accepted"),await Se({baseUrl:t,targetRole:"client",previousRuntimePid:Number(s.runtimePid||0),allowedStates:["running","waiting-auth"]}),ye(5179)}catch(s){E("failed"),H(s instanceof Error?s.message:String(s))}},de=A(b,"security"),V=A(b,"control"),B=A(b,"filesAudio"),P=A(b,"connection"),ue=`settings-panel-${r}`,he=n?Z.filter(s=>s.id!=="connection"):Z;i.useEffect(()=>{n&&r==="connection"&&Q("remote-access")},[r,n]),i.useEffect(()=>{b&&D?.(!!P.showThisComputer)},[P.showThisComputer,D,b]);const ge=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[se,oe,a==="hub"&&e.jsx("section",{className:"settings-section-card",children:e.jsx(h,{icon:ee,title:"Help mobile devices connect",description:"Temporarily opens a router port while a direct mobile connection starts, then removes it. Uses no video relay. Requires a compatible router.",children:e.jsx(x,{checked:!!P.temporaryRouterMapping,onChange:d("connection","temporaryRouterMapping"),label:"Help mobile devices connect"})})}),K&&e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Hub computer list"}),e.jsx("h3",{children:"This computer"})]}),e.jsx(F,{size:20})]}),e.jsx(h,{icon:F,title:"Show this computer",description:"Show this Hub computer in its own Wall and computer lists. It stays available from other computers and the mobile app when hidden.",children:e.jsx(x,{checked:!!P.showThisComputer,onChange:d("connection","showThisComputer"),label:"Show this computer"})})]}),e.jsxs("section",{className:"settings-section-card runtime-role-settings",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Runtime role"}),e.jsx("h3",{children:"Use this computer as a Client"})]}),e.jsx(je,{size:20})]}),e.jsx("p",{className:"settings-help",children:"Stop hosting from this computer and reconnect it to the selected Hub."}),z==="accepted"?e.jsx("p",{className:"settings-help runtime-role-success",children:"VuvoDesk is restarting as Client."}):L?e.jsx("p",{className:"settings-help runtime-role-error",role:"alert",children:L}):null,e.jsx("button",{className:"settings-reset",onClick:()=>{le()},disabled:z==="changing"||a!=="hub",type:"button",children:z==="changing"?"Switching role...":"Switch this computer to Client"})]})]}),me=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Remote access"}),e.jsx("h3",{children:"Who may connect?"})]}),e.jsx(Re,{size:20})]}),e.jsx(h,{icon:te,title:"Access mode",description:"Choose the default permission boundary for remote sessions.",recommended:!0,children:e.jsx(U,{value:String(de.accessMode),onChange:d("security","accessMode"),label:"Access mode",options:[["trusted-only","Trusted devices only"],["block-remote-access","Block remote access"]]})})]}),e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Session permissions"}),e.jsx("h3",{children:"What may remote users do?"})]}),e.jsx(F,{size:20})]}),e.jsx(h,{icon:F,title:"Keyboard and mouse control",description:"Allow Control to send keyboard and pointer input.",recommended:!0,children:e.jsx(x,{checked:!!V.allowKeyboardMouse,onChange:d("control","allowKeyboardMouse"),label:"Keyboard and mouse control"})}),e.jsx(h,{icon:we,title:"Power actions",description:"Allow confirmed sleep, restart, and shut down commands from the Hub.",children:e.jsx(x,{checked:!!V.allowRemoteRestart,onChange:d("control","allowRemoteRestart"),label:"Power actions"})}),e.jsx(h,{icon:q,title:"File transfer",description:"Allow files to be delivered to connected computers.",children:e.jsx(x,{checked:!!B.allowFileTransfer,onChange:d("filesAudio","allowFileTransfer"),label:"File transfer"})}),e.jsx(h,{icon:$,title:"Remote audio",description:"Allow sound capture from connected computers.",children:e.jsx(x,{checked:!!B.allowRemoteAudio,onChange:d("filesAudio","allowRemoteAudio"),label:"Remote audio"})})]})]}),pe=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[e.jsxs("section",{className:"settings-section-card",children:[e.jsxs("div",{className:"settings-section-heading",children:[e.jsxs("div",{children:[e.jsx("span",{children:"Capture"}),e.jsx("h3",{children:"Recording defaults"})]}),e.jsx(q,{size:20})]}),e.jsx(h,{icon:$,title:"Keep a Last 30s buffer",description:"Keep recent video in memory until you explicitly save it.",children:e.jsx(x,{checked:!!B.rollingBufferEnabled,onChange:d("filesAudio","rollingBufferEnabled"),label:"Keep a Last 30s buffer"})}),e.jsx(h,{icon:$,title:"Timelapse interval",description:"Choose how often a timelapse frame is captured.",children:e.jsx(U,{value:Number(B.timelapseIntervalSeconds),onChange:s=>d("filesAudio","timelapseIntervalSeconds")(Number(s)),label:"Timelapse interval",options:[["5","5 seconds"],["10","10 seconds"],["30","30 seconds"],["60","60 seconds"]]})})]}),ie]}),fe=r==="connection"?ge:r==="remote-access"?me:r==="capture-audio"?pe:ne;return e.jsxs("section",{className:"settings-page",children:[e.jsx("div",{className:"settings-page-tabs",role:"tablist","aria-label":"VuvoDesk settings",children:he.map(({id:s,label:u,icon:o})=>e.jsxs("button",{className:r===s?"active":"",id:`settings-tab-${s}`,role:"tab","aria-selected":r===s,"aria-controls":`settings-panel-${s}`,tabIndex:r===s?0:-1,onClick:()=>Q(s),type:"button",children:[e.jsx(o,{size:16}),u]},s))}),re==="saving"&&e.jsx("div",{className:"product-save-state",role:"status",children:"Saving settings..."}),G&&e.jsx("div",{className:"agent-settings-alert error",role:"alert",children:G}),e.jsx("section",{className:"settings-page-panel",id:ue,role:"tabpanel","aria-labelledby":`settings-tab-${r}`,tabIndex:0,children:fe})]})}export{Te as SettingsPage};