livedesk 0.1.656 → 0.1.658

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.
Files changed (42) hide show
  1. package/hub/src/remote-hub.js +47 -24
  2. package/hub/src/server.js +200 -13
  3. package/hub/src/shared-wall-profile-contract.mjs +40 -0
  4. package/hub/src/shared-wall-profile-contract.test.mjs +38 -0
  5. package/package.json +1 -1
  6. package/web/dist/app.html +5 -11
  7. package/web/dist/app.webmanifest +1 -1
  8. package/web/dist/assets/AgentSettingsTab-8WnOGkVa.js +1 -0
  9. package/web/dist/assets/{AgentsPage-DEdUBoe0.js → AgentsPage-CCO7AwAO.js} +6 -6
  10. package/web/dist/assets/CaptureGallery-7NXD-vaQ.js +1 -0
  11. package/web/dist/assets/DesktopUpdatePanel-CiGXFhqj.js +1 -0
  12. package/web/dist/assets/{App-DK9GZcvU.js → HubApp-AhKLyz3K.js} +13 -13
  13. package/web/dist/assets/MonitorStackIcon-DBuXI_Oa.js +8 -0
  14. package/web/dist/assets/SettingsPage-DnOdy3MQ.js +1 -0
  15. package/web/dist/assets/SettingsTabs-DfjoCvK4.js +1 -0
  16. package/web/dist/assets/{ShareFilesPage-BiCS0Nyd.js → ShareFilesPage-C3Jv7EII.js} +3 -3
  17. package/web/dist/assets/SupportPage-B16Jl8Jq.js +2 -0
  18. package/web/dist/assets/VuvoDeskApp-CU4N6t3c.js +1 -0
  19. package/web/dist/assets/app--miKlon3.js +2 -0
  20. package/web/dist/assets/client-8jUbxy3j.js +1 -0
  21. package/web/dist/assets/icons-CuXJn-Hz.js +1 -0
  22. package/web/dist/assets/main-DVNv6hc-.js +2 -0
  23. package/web/dist/assets/preload-helper-DD1OZmLC.js +1 -0
  24. package/web/dist/assets/pwa-bootstrap-BCid3CYk.js +1 -0
  25. package/web/dist/assets/pwa-startup-xxamnV7P.js +1 -0
  26. package/web/dist/assets/react-rvm9rmed.js +9 -0
  27. package/web/dist/index.html +11 -7
  28. package/web/dist/sw.js +14 -4
  29. package/web/dist/vuvodesk-build-evidence.json +93 -73
  30. package/web/dist/assets/AgentSettingsTab-D0271Ynp.js +0 -1
  31. package/web/dist/assets/CaptureGallery-C0xqFLap.js +0 -1
  32. package/web/dist/assets/DesktopUpdatePanel-uMaTnBsl.js +0 -1
  33. package/web/dist/assets/SettingsPage-BoFLQBfH.js +0 -1
  34. package/web/dist/assets/SettingsTabs-D0zQN-Mo.js +0 -1
  35. package/web/dist/assets/SupportPage-D241Vkb1.js +0 -2
  36. package/web/dist/assets/VuvoDeskApp-36bRXXS2.js +0 -1
  37. package/web/dist/assets/app-hMd5uyvT.js +0 -1
  38. package/web/dist/assets/icons-CacEbnZu.js +0 -1
  39. package/web/dist/assets/main-DT492iHt.js +0 -2
  40. package/web/dist/assets/react-Cfedt3N5.js +0 -1
  41. package/web/dist/assets/styles-Ba1tPFHg.js +0 -16
  42. /package/web/dist/assets/{App-DFLBNvIi.css → HubApp-DFLBNvIi.css} +0 -0
@@ -0,0 +1,8 @@
1
+ import{j as v}from"./pwa-startup-xxamnV7P.js";const N=15e3;function Ie(n,e=N){const t=Number(n),i=Number.isFinite(Number(e))?Number(e):N;return Math.max(250,Math.min(12e4,Math.trunc(Number.isFinite(t)?t:i)))}class ue 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 Ae(n,e,t){const i=Ie(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 ue(i))},i);try{return await t(r.signal)}catch(c){throw s?new ue(i):c}finally{clearTimeout(a),n?.removeEventListener("abort",o)}}function Jt(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,y=6*1024*1024,De=12*1024*1024,T=24,I=oe-T,me=1,Oe=2,Re=32,Z=4294967295,ee=Symbol("direct-console-wire-budget-reserve"),te=Object.freeze([76,68,67,87]),be=Object.freeze({control:1,text:2,binary:3}),Me=Object.freeze({1:"control",2:"text",3:"binary"});class H 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 H(n,e)}function ae(n,e){return n===void 0?{}:((!n||typeof n!="object"||Array.isArray(n))&&g(`${e}-options-invalid`),n)}function F(n,e,t,i){const r=Number(n);return(!Number.isInteger(r)||r<t||r>i)&&g(e),r}function Ee(n){return n===void 0?y:F(n,"max-message-bytes-invalid",1,Z)}function _e(n,e){const t=n===void 0?e?"text":"binary":String(n);return Object.hasOwn(be,t)||g("message-kind-invalid"),e&&t==="binary"&&g("binary-message-requires-bytes"),!e&&t!=="binary"&&g(`${t}-message-requires-text`),t}function Pe(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 Ne(n){if(n instanceof Uint8Array)return n;if(n instanceof ArrayBuffer)return new Uint8Array(n);g("wire-chunk-type-invalid")}function xe(n,{kind:e,messageId:t,chunkIndex:i,chunkCount:r,totalLength:s}){n.set(te,0);const o=new DataView(n.buffer,n.byteOffset,T);o.setUint8(4,me),o.setUint8(5,be[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 We(n,e){const t=Ne(n);(t.byteLength<T||t.byteLength>oe)&&g("wire-chunk-length-invalid");for(let p=0;p<te.length;p+=1)t[p]!==te[p]&&g("wire-magic-invalid");const i=new DataView(t.buffer,t.byteOffset,T);i.getUint8(4)!==me&&g("wire-version-invalid");const r=Me[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 u=Math.max(1,Math.ceil(c/I));(a!==u||o>=a)&&g("wire-chunk-layout-invalid");const h=t.byteLength-T,d=o<a-1?I:c-o*I;return h!==d&&g("wire-chunk-layout-invalid"),{bytes:t,kind:r,messageId:s,chunkIndex:o,chunkCount:a,totalLength:c,payloadLength:h}}function Se(n=void 0){const e=ae(n,"budget"),t=e.maxBytes===void 0?De:F(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=F(a,"budget-reservation-invalid",0,Number.MAX_SAFE_INTEGER);c>t-i&&g("shared-budget-overflow"),i+=c,r+=1;let u=!0;return Object.freeze({byteLength:c,release(){return u?(u=!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 Ue(n,e=void 0){const t=ae(e,"encode"),i=F(t.messageId,"message-id-invalid",0,Z),r=Ee(t.maxMessageBytes),s=Pe(n),o=_e(t.kind,s.isText),a=s.bytes.byteLength;(a>r||a>Z)&&g("message-too-large");const c=Math.max(1,Math.ceil(a/I)),u=new Array(c);for(let h=0;h<c;h+=1){const d=h*I,p=Math.min(I,a-d),l=new Uint8Array(T+p);xe(l,{kind:o,messageId:i,chunkIndex:h,chunkCount:c,totalLength:a}),p>0&&l.set(s.bytes.subarray(d,d+p),T),u[h]=l}return u}function he(n=void 0){const e=ae(n,"assembler"),t=Ee(e.maxMessageBytes),i=e.maxPendingMessages===void 0?Oe:Number(e.maxPendingMessages);(!Number.isSafeInteger(i)||i<1||i>Re)&&g("max-pending-messages-invalid");const r=e.budget===void 0?Se():e.budget;(!r||typeof r[ee]!="function"||typeof r.inspect!="function")&&g("shared-budget-invalid");const s=new Map;let o=!1;const a=()=>{for(const p of s.values())p.reservation.release();s.clear()},c=()=>{let p=0;for(const l of s.values())p+=l.totalLength;return Object.freeze({disposed:o,maxMessageBytes:t,maxPendingMessages:i,pendingMessages:s.size,pendingBytes:p,budget:r.inspect()})},u=()=>(o||(o=!0,a()),c()),h=p=>{throw o=!0,a(),p instanceof H?p:new H("wire-chunk-malformed")};return Object.freeze({dispose:u,inspect:c,push:p=>{o&&g("assembler-disposed");try{const l=We(p,t);let f=s.get(l.messageId);if(f)(f.kind!==l.kind||f.chunkCount!==l.chunkCount||f.totalLength!==l.totalLength)&&g("wire-message-metadata-mismatch");else{s.size>=i&&g("pending-message-limit");const B=r[ee](l.totalLength);let L;try{L=new Uint8Array(l.totalLength)}catch{B.release(),g("message-allocation-failed")}f={kind:l.kind,chunkCount:l.chunkCount,totalLength:l.totalLength,receivedChunks:new Uint8Array(l.chunkCount),receivedChunkCount:0,receivedBytes:0,buffer:L,reservation:B},s.set(l.messageId,f)}f.receivedChunks[l.chunkIndex]!==0&&g("duplicate-wire-chunk");const b=l.chunkIndex*I,A=b+l.payloadLength;if((b<0||A>f.totalLength)&&g("wire-chunk-overlap"),l.payloadLength>0&&f.buffer.set(l.bytes.subarray(T),b),f.receivedChunks[l.chunkIndex]=1,f.receivedChunkCount+=1,f.receivedBytes+=l.payloadLength,f.receivedChunkCount<f.chunkCount)return null;f.receivedBytes!==f.totalLength&&g("wire-message-length-mismatch");let U;try{U=f.kind==="binary"?f.buffer:new TextDecoder("utf-8",{fatal:!0}).decode(f.buffer)}catch{g("wire-text-invalid")}finally{s.delete(l.messageId),f.reservation.release()}return Object.freeze({messageId:l.messageId,kind:f.kind,byteLength:f.totalLength,data:U})}catch(l){return h(l)}}})}const Be="Direct connection signaling is unavailable. Try again.",He="Desktop Hub is offline.",Fe="A direct connection could not be established on this network.",ne=750,qe=1500,je=3e3,$e=64*1024;function Ge(n){const e=Math.max(0,Number(n)||0),t=Math.ceil(e/$e*1e3);return Math.max(qe,Math.min(je,ne+t))}const ie=Object.freeze({"signal-service-unavailable":Be,"hub-unavailable":He,"p2p-unavailable":Fe});function ce(n){const e=new Error(ie[n]);return e.name="ConsoleDirectError",e.code=n,e.directFailureKind=n,e}function m(){return ce("signal-service-unavailable")}function z(){return ce("hub-unavailable")}function w(){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(ie,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:ie[i],retryAt:0})}function Ve({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 ze(n,e){return!!n&&!!e&&n.userId===e.userId&&n.connectionId===e.connectionId&&n.hubEpoch===e.hubEpoch&&n.generation===e.generation}const Ce="https://livedesk-wake.lovecrdm.workers.dev",Ke="stun:stun.cloudflare.com:3478",Xe="livedesk-console-signal-v2",Ye="livedesk-auth.",Je="livedesk-control-v1",Qe="livedesk-ws-v1:",Ze=1e4,X=12e3,de=1e4,et=5e3,tt=5e3,nt=15e3,it=15e3,rt=16,fe=32,st=64,ot=1024*1024,at=new Set(["/api/remote/status","/api/remote/devices"]),pe=4*1024*1024,ct=12*1024*1024,ge=8*1024*1024+oe,lt=8,ut=1,ht=2,dt=new Set(["rtc-offer","rtc-ice","rtc-close"]),ft=new Set(["frame","atlas","input","audio"]),_=/^[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 pt(n){const e=String(Ce).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 gt(n){const e=String(Ce).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 wt(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&&_.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 mt(){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:[Ke]}function bt(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 Et(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 St(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 Ct(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 M(n){return/(?:^|\r?\n)(?:a=)?candidate:[^\r\n]*\btyp\s+relay(?:\s|$)/i.test(String(n||""))}function re(n,e=1e3){const t=Number(n);return Number.isInteger(t)&&t>=0&&t<=65535?t:e}function Y(n,e="console-direct-failed"){return n instanceof Error?n:new Error(String(n||e))}function we(n){if(n instanceof ArrayBuffer||n instanceof Uint8Array)return n;throw new H("wire-chunk-type-invalid")}function yt(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 Tt 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;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,re(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:re(e,1006),reason:String(t||"").slice(0,120),wasClean:e===1e3});this.onclose?.call(this,r),this.dispatchEvent(r)}}class kt{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;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;lastFailure=null;lastTerminalWireBytes=0;lastTerminalWireReservations=0;workspaceReauthAttempt=null;configure(e){const t=wt(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.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.wireBudget?.inspect()||{retainedBytes:0,reservationCount:0},t=[...this.channels.values()].filter(c=>c.wireDeadline!==null).length,i=[...this.channels.values()].filter(c=>c.openDeadline!==null).length,r=this.connectTimer===null?0:1,s=this.peerDisconnectTimer===null?0:1,o=this.controlWireDeadline===null?0:1,a=this.workspaceReauthAttempt?.deadline==null?0:1;return Object.freeze({preferred:this.preferred,stage:this.stage,directReady:this.directReady,generation:this.generation,signalSockets:this.signalSocket?1:0,peerCount:this.peer?1:0,controlChannels:this.controlChannel?1:0,logicalChannels:this.channels.size,openLogicalChannels:[...this.channels.values()].filter(c=>c.opened).length,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,pendingRemoteCandidates:this.pendingRemoteCandidates.length,connectTimers:r,peerDisconnectTimers:s,controlWireTimers:o,workspaceReauthTimers:a,logicalOpenTimers:i,logicalWireTimers:t,resourceTimers:r+s+o+a+i+t+this.pendingHttp.size,wireRetainedBytes:e.retainedBytes,wireReservations:e.reservationCount,sendBufferedBytes:this.peerBufferedAmount(),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 ze(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(w(),"peer-disconnected-timeout",!0))},et);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(w(),"control-wire-assembly-timeout",!0))},nt);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(!dt.has(String(e.type||"")))throw new Error("console-direct-signal-type-forbidden");const t=this.signalSocket;if(!t||t.readyState!==WebSocket.OPEN||!this.signalReady)throw m();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=Ue(t,{messageId:this.nextMessageId(),kind:i,maxMessageBytes:r}),o=s.reduce((a,c)=>a+c.byteLength,0);if(o>pe||this.peerBufferedAmount()>pe-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 w();this.sendWire(t,JSON.stringify(e),"control",y)}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&&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{}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.pendingRemoteCandidates=[],this.invalidateLivenessEvidence(),this.clearConnectTimer(),this.clearPeerDisconnectTimer();const a=t||new Error(e||"console-direct-closed");this.rejectCurrentConnect(a);for(const[d,p]of this.pendingHttp)window.clearTimeout(p.timeout),p.detachAbort(),p.reject(a),this.pendingHttp.delete(d);for(const d of[...this.channels.values()])this.retireLogicalEntry(d,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 u=this.peer;if(this.peer=null,u){u.onicecandidate=null,u.onconnectionstatechange=null,u.oniceconnectionstatechange=null;try{u.close()}catch{}}if(!r)try{s?.close(1e3,String(e||"console-direct-closed").slice(0,120))}catch{}const h=this.wireBudget?.inspect();this.lastTerminalWireBytes=Number(h?.retainedBytes||0),this.lastTerminalWireReservations=Number(h?.reservationCount||0),this.wireBudget=null}async connect(){if(this.directReady&&this.peerOwner&&this.controlChannel?.readyState==="open")return;if(this.connectPromise)return this.connectPromise;const e=this.session;if(!e)throw m();const t=this.signalSocket?.readyState===WebSocket.OPEN&&this.signalReady;if(t&&this.stage==="hub-offline"){const s=z();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(w(),"direct-ready-timeout",!0)},X)),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"?m():w();this.fail(s,this.stage==="signal"?"signal-timeout":"direct-ready-timeout",!1)},this.stage==="signal"?Ze:X);try{const s=new WebSocket(pt(e.workspaceId),[Xe,`${Ye}${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(m(),"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(m(),"signal-service-unavailable",!1))}),s.addEventListener("close",()=>{this.isSignalOwner(i,s)&&(this.detachSignalFromReadyPeer(i,s,"signal-closed-after-ready")||this.fail(m(),"signal-service-closed",!1))})}catch{this.fail(m(),"signal-constructor-failed",!1)}return r}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||!_.test(a)){this.fail(m(),"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,u={challengeNonce:a,generation:t,socket:i,controller:c,deadline:null},h=Number(e.deadlineAt||0),d=Number.isFinite(h)&&h>0?Math.max(1,h-Date.now()):de;u.deadline=window.setTimeout(()=>{this.workspaceReauthAttempt===u&&this.cancelWorkspaceReauthAttempt(t,i)},Math.max(1,Math.min(de,d))),this.workspaceReauthAttempt=u,(async()=>{try{await fetch(gt("/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===u&&(this.workspaceReauthAttempt=null,u.deadline!==null&&(window.clearTimeout(u.deadline),u.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(m(),"workspace-access-expired",!1);return}if(e.type==="signal-ready"){const s=String(e.consoleId||""),o=String(e.hubEpoch||"");if(e.role!=="console"||!_.test(s)){this.fail(m(),"invalid-signal-ready",!1);return}if(this.signalReady=!0,this.consoleId=s,e.hubOnline!==!0){const a=z();this.lastFailure=K(a),this.teardown("hub-offline",a,!1,!0);return}if(!_.test(o)){this.fail(m(),"invalid-hub-epoch",!1);return}if(this.peerOwner){this.peerOwner.hubEpoch!==o&&this.fail(w(),"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(w(),"direct-ready-timeout",!0)},X),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)?z():w();this.fail(o,s,!1)}}}beginPeer(e,t){if(e!==this.generation||this.peer)return;const i=this.session;if(!i){this.fail(m(),"session-missing",!1);return}const r=Ve({userId:i.user.id,connectionId:crypto.randomUUID(),hubEpoch:t,generation:e});this.consecutiveMediaLogicalOpenFailures=0,this.peerOwner=r,this.wireBudget=Se({maxBytes:ct}),this.controlAssembler=he({budget:this.wireBudget,maxMessageBytes:y});let s;try{s=new RTCPeerConnection({iceServers:[{urls:mt()}],iceTransportPolicy:"all",bundlePolicy:"max-bundle",rtcpMuxPolicy:"require"})}catch{this.fail(w(),"peer-constructor-failed",!0);return}this.peer=s;const o=s.createDataChannel(Je,{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(M(c)){this.fail(w(),"relay-ice-candidate-forbidden",!0);return}try{this.signal({type:"rtc-ice",connectionId:r.connectionId,hubEpoch:r.hubEpoch,candidate:c,sdpMid:a.candidate.sdpMid})}catch{this.fail(m(),"signal-ice-failed",!1)}},s.onconnectionstatechange=()=>{if(!(!this.isPeerOwner(r)||this.peer!==s)){if(s.connectionState==="failed"||s.connectionState==="closed"){this.fail(w(),`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(w(),`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(w(),"control-channel-error",!0)},o.onclose=()=>{!this.isPeerOwner(r)||this.controlChannel!==o||this.fail(w(),"control-channel-closed",!0)},(async()=>{try{const a=await s.createOffer();if(!this.isPeerOwner(r)||this.peer!==s)return;if(a.type!=="offer"||M(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"||M(c.sdp))throw new Error("relay-sdp-forbidden");this.signal({type:"rtc-offer",connectionId:r.connectionId,hubEpoch:r.hubEpoch,description:{type:"offer",sdp:c.sdp||""}})}catch(a){if(!this.isPeerOwner(r))return;const c=/signal/i.test(String(a?.message||""))?m():w();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"||M(t.sdp)){this.fail(w(),"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(w(),"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||M(r)){this.fail(w(),"rtc-candidate-invalid",!0);return}const o=this.peer;if(o){if(!this.remoteDescriptionApplied){if(this.pendingRemoteCandidates.length>=st){this.fail(w(),"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(w(),"rtc-candidate-apply-failed",!0)}}}handleControlWire(e,t){const i=this.controlAssembler;if(!(!this.isPeerOwner(e)||!i))try{const r=i.push(we(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.consecutiveLivenessRequestTimeouts=0,this.directReady=!0,this.stage="ready",this.resolveCurrentConnect());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(w(),"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(!_.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,re(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))){this.consecutiveLivenessRequestTimeouts=0,this.pendingHttp.delete(i),window.clearTimeout(r.timeout),r.detachAbort();try{const s=Number(t.status||502),o=t.bodyBase64?Et(t.bodyBase64):new TextEncoder().encode(JSON.stringify({ok:!1,error:t.error||"console-direct-request-failed"}));r.resolve(new Response(o,{status:Number.isInteger(s)&&s>=200&&s<=599?s:502,statusText:String(t.statusText||""),headers:t.headers||{"content-type":"application/json"}}))}catch(s){r.reject(Y(s))}}}async fetch(e,t,i){await yt(this.connect(),t?.signal);const r=this.peerOwner;if(!r||!this.directReady||this.controlChannel?.readyState!=="open")throw w();if(this.pendingHttp.size>=fe)throw new Error("console-direct-http-capacity-reached");const s=await St(t?.body);if(s.byteLength>ot)throw new Error("console-direct-http-body-too-large");if(!this.isPeerOwner(r)||!this.directReady)throw w();if(this.pendingHttp.size>=fe)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(),u=c==="GET"&&at.has(e),h=u?this.livenessEvidenceEpoch:null,d=new Promise((p,l)=>{const f=(U,B=!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{}l(U),B&&u&&this.recordLivenessRequestTimeout(r,L.livenessEvidenceEpoch)}},b=()=>f(t?.signal?.reason instanceof Error?t.signal.reason:new Error("Mobile Console request cancelled."));t?.signal?.addEventListener("abort",b,{once:!0});const A=window.setTimeout(()=>{f(new Error("Mobile Console direct request timed out."),!0)},a);this.pendingHttp.set(o,{generation:r.generation,livenessEvidenceEpoch:h,resolve:p,reject:l,timeout:A,detachAbort:()=>t?.signal?.removeEventListener("abort",b)})});try{this.sendControl({type:"http-request",requestId:o,method:c,path:e,headers:Ct(t),bodyBase64:s.byteLength>0?bt(s):""})}catch(p){const l=this.pendingHttp.get(o);l&&(this.pendingHttp.delete(o),window.clearTimeout(l.timeout),l.detachAbort(),l.reject(Y(p))),this.fail(w(),"control-send-failed",!0)}return d}openWebSocket(e,t){if(!ft.has(t))throw new Error("console-direct-purpose-invalid");if(this.channels.size>=rt)throw new Error("console-direct-channel-capacity-reached");const i=crypto.randomUUID(),r=new Tt(this,i,t,e),s={channelId:i,path:e,purpose:t,socket:r,owner:null,dataChannel:null,assembler:null,openDeadline:null,wireDeadline:null,wireStartedAtEpochMs:0,wireLastProgressAtEpochMs:0,wireAbsoluteDeadlineAtEpochMs:0,openRequested:!1,opened:!1,pendingInbound:[],pendingInboundBytes:0};return this.channels.set(i,s),this.connect().then(()=>{this.channels.get(i)===s&&this.attachLogicalChannel(s)}).catch(o=>{this.channels.get(i)===s&&this.retireLogicalEntry(s,1011,Y(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}e.owner=t;const s=e.purpose==="frame"||e.purpose==="atlas";let o;try{o=i.createDataChannel(`${Qe}${e.channelId}:${e.purpose}`,s?{ordered:!1,maxPacketLifeTime:120}:{ordered:!0})}catch{this.retireLogicalOpenFailure(e,t,1011,"console-direct-channel-create-failed",!0,!0);return}o.binaryType="arraybuffer",e.dataChannel=o,e.assembler=he({budget:r,maxMessageBytes:s?ge:y,maxPendingMessages:s?lt: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(h=>h!==e&&h.opened&&(h.purpose==="frame"||h.purpose==="atlas")&&h.dataChannel?.readyState==="open"),u=a&&!c&&(o||this.consecutiveMediaLogicalOpenFailures>=ht);this.retireLogicalEntry(e,i,r,s,!1),u&&this.isPeerOwner(t)&&this.fail(w(),"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))},tt);e.openDeadline=r}invalidateLivenessEvidence(){this.livenessEvidenceEpoch+=1,this.consecutiveLivenessRequestTimeouts=0}recordLivenessRequestTimeout(e,t){t===null||t!==this.livenessEvidenceEpoch||!this.isPeerOwner(e)||!this.directReady||(this.livenessRequestTimeoutCount+=1,this.consecutiveLivenessRequestTimeouts+=1,!(this.consecutiveLivenessRequestTimeouts<2)&&this.fail(w(),"control-http-timeout",!0))}handleLogicalWire(e,t,i){const r=e.assembler;if(!(!r||!this.logicalEntryIsCurrent(e,t,e.dataChannel)))try{const s=r.push(we(i));if(this.refreshLogicalWireDeadline(e,t),!s)return;if(s.kind==="control")throw new Error("logical-control-forbidden");let o;if(s.kind==="text"&&typeof s.data=="string")o={kind:"text",data:s.data,byteLength:s.byteLength};else if(s.kind==="binary"&&s.data instanceof Uint8Array)o={kind:"binary",data:s.data,byteLength:s.byteLength};else throw new Error("logical-wire-kind-invalid");if(!e.opened){this.queuePreOpenLogicalMessage(e,o);return}this.deliverLogicalMessage(e,o)}catch{this.retireLogicalEntry(e,1011,"console-direct-wire-invalid",!0,!1)}}queuePreOpenLogicalMessage(e,t){const i=e.purpose==="frame"||e.purpose==="atlas"?ge:y;if(e.pendingInbound.length>=ut||e.pendingInboundBytes+t.byteLength>i)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,r=i.buffer.slice(i.byteOffset,i.byteOffset+i.byteLength);e.socket.managerMessage(e.socket.binaryType==="arraybuffer"?r:new Blob([r]))}logicalBufferedAmount(e){return Number(this.channels.get(e)?.dataChannel?.bufferedAmount||0)}clearLogicalWireDeadline(e){e.wireDeadline!==null&&(window.clearTimeout(e.wireDeadline),e.wireDeadline=null),e.wireStartedAtEpochMs=0,e.wireLastProgressAtEpochMs=0,e.wireAbsoluteDeadlineAtEpochMs=0}scheduleLogicalWireDeadline(e,t){e.wireDeadline!==null&&window.clearTimeout(e.wireDeadline);const i=e.purpose==="frame"||e.purpose==="atlas",r=Date.now(),s=i?Math.max(1,ne-(r-e.wireLastProgressAtEpochMs)):Number.POSITIVE_INFINITY,o=Math.max(1,e.wireAbsoluteDeadlineAtEpochMs-r),a=window.setTimeout(()=>{if(e.wireDeadline!==a)return;e.wireDeadline=null;const c=e.dataChannel;if(!c||!this.logicalEntryIsCurrent(e,t,c))return;const u=e.assembler?.inspect(),h=Number(u?.pendingMessages||0);if(h===0){this.clearLogicalWireDeadline(e);return}const d=Date.now(),p=Math.max(0,d-e.wireLastProgressAtEpochMs),l=Math.max(0,d-e.wireStartedAtEpochMs);if(!(!i||p>=ne||d>=e.wireAbsoluteDeadlineAtEpochMs)){this.scheduleLogicalWireDeadline(e,t);return}i&&(this.partialMediaWireTimeoutCount+=1,this.lastPartialMediaWireTimeout=Object.freeze({purpose:e.purpose,generation:t.generation,pendingMessages:h,pendingBytes:Math.max(0,Number(u?.pendingBytes||0)),stalledForMs:p,lifetimeMs:l,occurredAt:d})),this.retireLogicalEntry(e,1011,"console-direct-partial-message-timeout",!0,!1)},Math.min(s,o));e.wireDeadline=a}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?Ge(Number(i?.pendingBytes||0)):it)),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",y);else if(t instanceof ArrayBuffer)this.sendWire(r,t,"binary",y);else if(ArrayBuffer.isView(t)){const s=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);this.sendWire(r,s,"binary",y)}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)}}const E=new kt;function ye(n){E.configure(n)}function Lt(){E.preferDirect()}function vt(){E.markLocalHubReachable()}function Qt(){E.resume()}function Zt(){E.suspendLivenessEvidence()}function en(){E.retry()}function J(n,e,t){return E.preferDirect(),E.fetch(n,e,t)}function tn(n,e,t){return E.shouldUseDirect()?E.openWebSocket(e,t):new WebSocket(n)}function nn(){return E.inspect()}function It(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 At(n,e){return n&&await n.catch(()=>{}),e()}function Dt(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 le(n){return!n?.user?.id||!n?.workspaceId?"":[n.user.id,n.workspaceId,n.workspaceKind,n.workspaceRole,Number(n.membershipRevision||0)].join(`
7
+ `)}function Ot(n){const e=le(n);return!e||!n?.accessToken||!n?.refreshToken?"":[e,n.accessToken,n.refreshToken,Number(n.expiresAt||0)].join(`
8
+ `)}function Rt({publicConsole:n,path:e,requiresUiSession:t}){return n?String(e||"").split("?")[0]==="/api/auth/session"?"reject-auth-session":t?"direct":"local":"local"}const P=5179,R=W(`http://127.0.0.1:${P}`);function Mt(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 Te(n){const e=n.trim().toLowerCase();return e==="localhost"||e==="127.0.0.1"||e==="::1"||e==="[::1]"}function _t(n){const e=n.trim().toLowerCase();return!e||e==="0.0.0.0"||e==="::"||e==="[::]"}function ke(n){const e=Mt(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 Pt(n){return n.includes(":")&&!n.startsWith("[")?`[${n}]`:n}function Nt(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||_t(r)?null:{host:r,port:s}}catch{return null}}function W(n){const e=String(n||"").trim()||`http://127.0.0.1:${P}`,t=/^[a-z][a-z\d+.-]*:\/\//i.test(e)?e:`http://${e}`;try{const i=new URL(t);return i.port||(i.port=String(P)),i.hash="",i.search="",i.toString().replace(/\/+$/,"")}catch{return`http://127.0.0.1:${P}`}}function xt(n){const e=Nt(n);return e?W(`http://${Pt(e.host)}:${P}`):""}function rn(n){const t=[n?.endpoint,...Array.isArray(n?.endpoint_candidates)?n.endpoint_candidates:[]].map(i=>xt(String(i||""))).filter(Boolean);return[...new Set(t)]}function Wt(n=R){if(!(typeof window>"u"||window.location.protocol!=="https:"))try{const e=new URL(n);if(e.protocol!=="http:")return;if(Te(e.hostname))return"loopback";if(ke(e.hostname))return"local"}catch{return}}function sn(n,e=R){const t=new URL(n,W(e));return t.protocol=t.protocol==="https:"?"wss:":"ws:",t.toString()}let S=null,O="",k="";const C=new Map,D=new Map,x=new Map,q=new Set;function G(n){const e=x.get(n);e!==void 0&&typeof window<"u"&&window.clearTimeout(e),x.delete(n)}function Le(){for(const n of x.keys())G(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 ve(n,e,t){if(G(n),typeof window>"u"||e<=Date.now())return;const i=Math.max(1e3,Math.min(45e3,e-Date.now()-15e3)),r=window.setTimeout(()=>{x.delete(n),!(t!==O||S?.workspaceKind!=="team")&&$(n,!0).catch(()=>{})},i);x.set(n,r)}function Ut(n,e,t){const i=S?.workspaceKind==="team",r=i?se(e.accessExpiresAt)||Date.now()+6e4:0;C.set(n,{csrfToken:e.csrfToken,expiresAt:e.expiresAt,accessExpiresAt:r,ownerSignature:k}),q.add(n),i?ve(n,r,t):G(n)}function on(n){const e=n?.accessToken&&n?.refreshToken&&n?.user?.id?n:null,t=le(e),i=Ot(e);if(t!==k&&(e&&C.clear(),k=t),i!==O&&(Le(),O=i,e?.workspaceKind==="team"))for(const[r,s]of C)s.ownerSignature===t&&ve(r,s.accessExpiresAt,i);S=e,ye(e?{accessToken:e.accessToken,user:{id:e.user.id},workspaceId:e.workspaceId,workspaceKind:e.workspaceKind,workspaceRole:e.workspaceRole,membershipRevision:e.membershipRevision}:null),e&&V()&&Lt()}function V(){if(typeof window>"u"||window.location.protocol!=="https:")return!1;const n=window.location.hostname.replace(/^\[|\]$/g,"");return!Te(n)&&!ke(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 j(n,e,t,i,r){const s=Wt(t);return s&&(e.targetAddressSpace=s),Ae(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 $(n,e=!1){if(V())throw new Error("Public Console uses verified P2P authorization instead of a Hub cookie session.");const t=C.get(n);if(!e&&t&&t.ownerSignature===k&&t.expiresAt>Date.now()+3e4&&(t.accessExpiresAt===0||t.accessExpiresAt>Date.now()+15e3))return;e&&C.delete(n);const i=S,r=O;if(!i)return;const s=D.get(n);if(s)return s.authSignature===r?s.promise:s.promise.catch(()=>{}).then(()=>$(n,e));let o;const a=(async()=>{const c=await j("/api/auth/session",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Dt(i,{publicConsole:!1})),credentials:"include",cache:"no-store"},n,N),u=await c.json().catch(()=>null);if(!c.ok)throw new Error(`${c.status} ${u?.error||c.statusText}`);const h=String(u?.uiSession?.csrfToken||"").trim(),d=Number(u?.uiSession?.expiresAt||0);if(!h||!Number.isFinite(d)||d<=Date.now())throw new Error("VuvoDesk Hub did not issue a valid UI session.");if(r!==O)throw C.set(n,{csrfToken:h,expiresAt:d,accessExpiresAt:se(u?.uiSession?.accessExpiresAt),ownerSignature:le(i)}),q.add(n),new Error("VuvoDesk workspace changed while the Hub session was opening.");Ut(n,{csrfToken:h,expiresAt:d,accessExpiresAt:se(u?.uiSession?.accessExpiresAt)},r)})().finally(()=>{D.get(n)===o&&D.delete(n)});return o={authSignature:r,promise:a},D.set(n,o),a}async function Bt(){const n=new Set(q);for(const t of D.keys())n.add(t);V()||n.add(W(R));const e=[...n].map(t=>At(D.get(t)?.promise,async()=>{const i=C.get(t),r=await j("/api/auth/session",{method:"DELETE",headers:i?.csrfToken?{"X-LiveDesk-CSRF":i.csrfToken}:{},credentials:"include",cache:"no-store"},t,N);if(!r.ok&&r.status!==401){const s=await r.json().catch(()=>null);throw new Error(`${r.status} ${s?.error||r.statusText}`)}q.delete(t),C.delete(t),G(t)}));await Promise.all(e)}const Ht=It(Bt);function an(){return S=null,O="",k="",Le(),ye(null),Ht.run()}async function Ft(n,e,t=R){const i=W(t),{timeoutMs:r=N,signal:s,transport:o="auto",...a}=e||{},c=!Q(n),u=c?k:"",h=()=>!c||!!u&&u===k,d=()=>{if(!h())throw new Error("VuvoDesk workspace changed while the Hub request was running.")},p=Rt({publicConsole:V(),path:n,requiresUiSession:c});if(c&&!S)throw new Error("VuvoDesk account authority is not available for this Hub request.");const l=()=>{const f=String(a.method||"GET").toUpperCase(),b=C.get(i),A=b?.ownerSignature===k?b.csrfToken:"";return{...a,...s?{signal:s}:{},headers:{...a.headers||{},...!["GET","HEAD","OPTIONS"].includes(f)&&A?{"X-LiveDesk-CSRF":A}:{}},credentials:"include",cache:"no-store"}};if(p==="reject-auth-session")throw new Error("Public Console does not create a Hub cookie session.");if(p==="direct"){if(d(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");return J(n,l(),r)}if(o==="p2p"){if(d(),s?.aborted)throw s.reason||new Error("VuvoDesk Hub request cancelled.");if(!S||Q(n))throw new Error("Mobile Console direct connection requires an authenticated management request.");return J(n,l(),r)}try{c&&await $(i),d();let f=await j(n,l(),i,r,s);if(d(),vt(),c&&f.status===401&&S){const b=await f.clone().json().catch(()=>null);/^hub-ui-session-(required|expired)$/.test(String(b?.error||""))&&(await $(i,!0),d(),f=await j(n,l(),i,r,s),d())}return f}catch(f){if(!h()||s?.aborted||!S||Q(n))throw f;return J(n,l(),r)}}async function qt(n,e,t=R){const i=await Ft(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 cn({baseUrl:n=R,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 qt("/api/runtime/status",void 0,n),u=String(c.role||"").toLowerCase(),h=String(c.state||"").toLowerCase(),d=Number(c.runtimePid||0),p=t>1?d>1&&d!==t:d>1;if(u===e&&i.map(l=>l.toLowerCase()).includes(h)&&p)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 ln(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 un(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 hn(n){await navigator.clipboard.writeText(n)}const jt=5,$t=15,Gt=50,Vt=Number.POSITIVE_INFINITY,zt=5,dn={free:{name:"Free",price:"$0",limit:jt,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:$t,people:1,audience:"Creators and homelabs",note:"15 devices, no ads, personal use."},pro:{name:"Pro / Business",price:"$15",ltd:"$199 LTD",limit:Gt,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:Vt,people:zt,audience:"Shared business operations",note:"Commercial use, a shared Team Space, and up to 5 people using their own accounts."}},Kt="0.1.658",Xt={version:Kt},fn=String(Xt.version).trim();function pn({size:n=22}){return v.jsxs("svg",{width:n,height:n,viewBox:"0 0 28 28",fill:"none",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",children:[v.jsx("rect",{x:"2.5",y:"4",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.42"}),v.jsx("path",{d:"M7 16v1.5h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.42"}),v.jsx("rect",{x:"10.5",y:"2.5",width:"14",height:"9",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7",opacity:"0.62"}),v.jsx("path",{d:"M15 14.5V16h5",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",opacity:"0.62"}),v.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"}),v.jsx("path",{d:"M12 21v1.5H9.5M16 21v1.5h2.5M9.5 22.5h9",stroke:"currentColor",strokeWidth:"1.9",strokeLinecap:"round"})]})}export{R as D,jt as F,fn as L,pn as M,$t as P,zt as T,Gt as a,an as b,hn as c,K as d,en as e,un as f,Wt as g,qt as h,V as i,tn as j,sn as k,W as l,Qt as m,ln as n,Ft as o,dn as p,on as q,Jt as r,Zt as s,rn as t,nn as u,cn as w};
@@ -0,0 +1 @@
1
+ import{j as e}from"./pwa-startup-xxamnV7P.js";import{r as i,W as je,S as ee,F as D,b as ve,M,c as be,L as we,P as Re,A as $}from"./icons-CuXJn-Hz.js";import{h as C,w as Se,n as ye}from"./MonitorStackIcon-DBuXI_Oa.js";import"./pwa-bootstrap-BCid3CYk.js";const x={revision:0,settings:{connection:{showThisComputer:!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:je},{id:"remote-access",label:"Remote Access",icon:ee},{id:"capture-audio",label:"Capture & Audio",icon:D},{id:"agent",label:"Agent",icon:ve}];function A(t,n){return t?.settings?.[n]||x.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 g({icon:t,title:n,description:d,children:m,recommended:a=!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}),a&&e.jsx("em",{children:"Recommended"}),e.jsx("small",{children:d})]})]})}function R({checked:t,onChange:n,label:d}){return e.jsxs("label",{className:"product-switch",children:[e.jsx("input",{"aria-label":d,type:"checkbox",checked:t,onChange:m=>n(m.target.checked)}),e.jsx("span",{})]})}function U({value:t,onChange:n,options:d,label:m}){return e.jsx("select",{"aria-label":m,value:String(t),onChange:a=>n(a.target.value),children:d.map(([a,F])=>e.jsx("option",{value:a,children:F},a))})}function Te({hubUrl:t="",mobileLayout:n=!1,runtimeRole:d="hub",runtimeDeviceId:m="",sessionAccessToken:a="",showThisComputerSetting:F=!0,onShowThisComputerChange:J,initialTab:Q="connection",pin:te,agent:se,captureGallery:ne,desktopUpdate:ie}){const[r,q]=i.useState(()=>n&&Q==="connection"?"remote-access":Q),[j,k]=i.useState(null),[oe,v]=i.useState("loading"),[G,T]=i.useState(""),[K,E]=i.useState("idle"),[L,z]=i.useState(""),b=i.useRef(null),u=i.useRef(null),p=i.useRef([]),B=i.useRef(Promise.resolve()),re=i.useRef(0),f=i.useRef(0);i.useEffect(()=>{const s=++f.current;let l=!0;return p.current=[],u.current=null,b.current=null,B.current=Promise.resolve(),v("loading"),C("/api/settings",void 0,t).then(o=>{if(!l||s!==f.current)return;const c=O(o);u.current=c,b.current=c,k(c),v("saved")}).catch(o=>{!l||s!==f.current||(T(o instanceof Error?o.message:String(o)),u.current=x,b.current=x,k(x),v("failed"))}),()=>{l=!1}},[t]);const ce=async(s,l,o)=>{const c={id:++re.current,section:s,key:l,value:o},H=f.current;p.current.push(c);const X=_(b.current||u.current||x,c);b.current=X,k(X),v("saving"),T(""),B.current=B.current.then(async()=>{if(H!==f.current)return;let S=null,y=null;for(let N=0;N<2&&!S;N+=1){const xe=u.current||x;try{const w=await C("/api/settings",{method:"PATCH",body:JSON.stringify({revision:xe.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(H!==f.current)return;u.current=O(W)}catch(W){y=W;break}}}if(H!==f.current)return;p.current=p.current.filter(N=>N.id!==c.id),S&&(u.current=S);const fe=u.current||x,Y=p.current.reduce(_,fe);b.current=Y,k(Y),S?(T(""),v(p.current.length>0?"saving":"saved")):(v(p.current.length>0?"saving":"failed"),T(y instanceof Error?y.message:String(y||"Settings could not be saved.")))}),await B.current},h=(s,l)=>o=>{ce(s,l,o)},ae=async()=>{if(d!=="hub"||!m||!a){E("failed"),z("Sign in to this Hub before changing its runtime role.");return}E("changing"),z("");try{const s=await C("/api/runtime/status",void 0,t);await C("/api/runtime/role",{method:"POST",headers:{Authorization:`Bearer ${a}`},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"),z(s instanceof Error?s.message:String(s))}},le=A(j,"security"),V=A(j,"control"),P=A(j,"filesAudio"),I=A(j,"connection"),de=`settings-panel-${r}`,ue=n?Z.filter(s=>s.id!=="connection"):Z;i.useEffect(()=>{n&&r==="connection"&&q("remote-access")},[r,n]),i.useEffect(()=>{j&&J?.(!!I.showThisComputer)},[I.showThisComputer,J,j]);const he=e.jsxs("div",{className:"settings-tab-content product-settings-content",children:[te,ie,F&&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(M,{size:20})]}),e.jsx(g,{icon:M,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(R,{checked:!!I.showThisComputer,onChange:h("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(be,{size:20})]}),e.jsx("p",{className:"settings-help",children:"Stop hosting from this computer and reconnect it to the selected Hub."}),K==="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:()=>{ae()},disabled:K==="changing"||d!=="hub",type:"button",children:K==="changing"?"Switching role...":"Switch this computer to Client"})]})]}),ge=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(we,{size:20})]}),e.jsx(g,{icon:ee,title:"Access mode",description:"Choose the default permission boundary for remote sessions.",recommended:!0,children:e.jsx(U,{value:String(le.accessMode),onChange:h("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(M,{size:20})]}),e.jsx(g,{icon:M,title:"Keyboard and mouse control",description:"Allow Control to send keyboard and pointer input.",recommended:!0,children:e.jsx(R,{checked:!!V.allowKeyboardMouse,onChange:h("control","allowKeyboardMouse"),label:"Keyboard and mouse control"})}),e.jsx(g,{icon:Re,title:"Power actions",description:"Allow confirmed sleep, restart, and shut down commands from the Hub.",children:e.jsx(R,{checked:!!V.allowRemoteRestart,onChange:h("control","allowRemoteRestart"),label:"Power actions"})}),e.jsx(g,{icon:D,title:"File transfer",description:"Allow files to be delivered to connected computers.",children:e.jsx(R,{checked:!!P.allowFileTransfer,onChange:h("filesAudio","allowFileTransfer"),label:"File transfer"})}),e.jsx(g,{icon:$,title:"Remote audio",description:"Allow sound capture from connected computers.",children:e.jsx(R,{checked:!!P.allowRemoteAudio,onChange:h("filesAudio","allowRemoteAudio"),label:"Remote audio"})})]})]}),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:"Capture"}),e.jsx("h3",{children:"Recording defaults"})]}),e.jsx(D,{size:20})]}),e.jsx(g,{icon:$,title:"Keep a Last 30s buffer",description:"Keep recent video in memory until you explicitly save it.",children:e.jsx(R,{checked:!!P.rollingBufferEnabled,onChange:h("filesAudio","rollingBufferEnabled"),label:"Keep a Last 30s buffer"})}),e.jsx(g,{icon:$,title:"Timelapse interval",description:"Choose how often a timelapse frame is captured.",children:e.jsx(U,{value:Number(P.timelapseIntervalSeconds),onChange:s=>h("filesAudio","timelapseIntervalSeconds")(Number(s)),label:"Timelapse interval",options:[["5","5 seconds"],["10","10 seconds"],["30","30 seconds"],["60","60 seconds"]]})})]}),ne]}),pe=r==="connection"?he:r==="remote-access"?ge:r==="capture-audio"?me:se;return e.jsxs("section",{className:"settings-page",children:[e.jsx("div",{className:"settings-page-tabs",role:"tablist","aria-label":"VuvoDesk settings",children:ue.map(({id:s,label:l,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}),l]},s))}),oe==="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:de,role:"tabpanel","aria-labelledby":`settings-tab-${r}`,tabIndex:0,children:pe})]})}export{Te as SettingsPage};
@@ -0,0 +1 @@
1
+ import{j as i}from"./pwa-startup-xxamnV7P.js";import"./icons-CuXJn-Hz.js";import"./pwa-bootstrap-BCid3CYk.js";function r({children:t}){return i.jsx("div",{className:"settings-tab-content",children:t})}export{r as PinSettingsTab};