@urun-sh/core 0.1.35 → 0.1.37

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.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{a as M,b as v,c as k}from"./chunk-BSNDJBHD.mjs";var H="session-api.prod.cloud.urun.sh",K=["https://session-api.use2.prod.cloud.urun.sh","https://session-api.usw2.prod.cloud.urun.sh"];function b(s){return s.trim().replace(/\/+$/,"")}function C(s,e){let t=[],r=n=>{if(!n)return;let o=b(n);o&&!t.includes(o)&&t.push(o)};r(s);for(let n of e??[])r(n);for(let n of ee(s))r(n);return t}var q=120,V=1e3,W=3;function Y(s){if(!s)return null;try{let e=new URL(s),t=e.pathname.replace(/\/api\/sessions\/create\/?$/,"");return b(`${e.origin}${t}`)}catch{return null}}async function L(s){let e=C(s.baseUrl,s.fallbackUrls),t=null,r=e.length>1;for(let n of e)try{return await z(n,s,{pollAttempts:q,retryAfterLimitMs:r?V:void 0})}catch(o){if(t=o instanceof Error?o:new Error(String(o)),t instanceof w)throw t}throw t??new Error("[urun] session allocation failed")}async function z(s,e,t){let r,n,o,i=s,l=0,h=new Set;for(let p=0;p<t.pollAttempts;p++){n=o??await E(e),o=void 0;let d=r?await fetch(`${i}/api/session-requests/${encodeURIComponent(r)}`,{headers:A(e,n)}):await fetch(`${i}/api/sessions/create`,{method:"POST",redirect:"manual",headers:{...A(e,n),"Content-Type":"application/json","Idempotency-Key":e.idempotencyKey},body:JSON.stringify(X(e))});if(!r&&(d.status===307||d.status===308)){let u=Y(d.headers.get("location"));if(u&&u!==i&&l<W){l+=1,i=u;continue}throw new Error(`[urun] session create redirected from ${i} without a usable target`)}let a=await $(d);if(d.ok&&(a.status==="allocated"||!a.status&&!!a.session_id)&&!!a.session_id){let u=a.session_id;if(!a.ws_url)throw new w(`[urun] gateway allocated session ${u} without ws_url`);if(!D(a.ws_url))throw new w(`[urun] gateway allocated session ${u} with non-absolute ws_url`);return{baseUrl:i,sessionId:u,wsUrl:a.ws_url,response:a}}if(d.status===202||a.status==="pending"||a.status==="queued"||a.queued){if(r=a.request_id||r,!r)throw new Error("[urun] gateway queued session without request_id");await Z(Q(d,a,t.retryAfterLimitMs));continue}if((d.status===401||d.status===403)&&e.getAccessToken){let u=n??"";h.add(u);let _=await E(e,{forceRefresh:!0,reason:"unauthorized"});if(_&&!h.has(_)){o=_,r=void 0;continue}}let m=a.error_message||a.error_code||`HTTP ${d.status}`;throw new Error(`[urun] session allocation failed at ${i}: ${m}`)}throw new Error(`[urun] timed out waiting for session allocation at ${i}`)}function A(s,e){let t={"X-Tenant-Id":s.orgId,"X-Auth-Provider":s.authProvider||"default","X-User-Id":"anonymous"};return e&&(t.Authorization=`Bearer ${e}`),t}async function E(s,e){return s.getAccessToken?await s.getAccessToken(e)??void 0:s.jwt}function X(s){return{app:s.app,function:s.functionName,gpus:1,idempotency_key:s.idempotencyKey}}async function j(s){let e=C(s.baseUrl,s.fallbackUrls),t=null;for(let r of e)try{let n={baseUrl:r,app:"",functionName:"",orgId:s.orgId,jwt:s.jwt,getAccessToken:s.getAccessToken,authProvider:s.authProvider,idempotencyKey:""},o=await E(n),i=await fetch(`${b(r)}/api/sessions/${encodeURIComponent(s.sessionId)}/viewer-connect`,{headers:A(n,o)});if(!i.ok)throw new Error(`[urun] viewer-connect for ${s.sessionId} failed: HTTP ${i.status}`);let l=await $(i);if(!l.ws_url||!D(l.ws_url))throw new w(`[urun] viewer-connect returned no usable ws_url for ${s.sessionId}`);return{baseUrl:b(r),sessionId:s.sessionId,wsUrl:l.ws_url,response:l}}catch(n){if(t=n instanceof Error?n:new Error(String(n)),t instanceof w)throw t}throw t??new Error("[urun] viewer-connect failed")}async function $(s){try{let e=await s.json();return e&&typeof e=="object"?e:{}}catch{return{}}}function Q(s,e,t){let r=Number(s.headers.get("Retry-After")||""),n=Number(e.retry_after_seconds??r),o=t??1e4;return Number.isFinite(n)&&n>0?Math.min(n*1e3,o):1e3}function Z(s){return new Promise(e=>setTimeout(e,s))}var w=class extends Error{};function D(s){try{let e=new URL(s);return e.protocol==="ws:"||e.protocol==="wss:"}catch{return!1}}function ee(s){try{return new URL(s).hostname!==H?[]:K}catch{return[]}}import*as g from"yjs";var N=Symbol("urun:doc:remote"),te=Symbol("urun:doc:local");function R(s){return s!==null&&typeof s=="object"&&!Array.isArray(s)}function P(s,e){let t={...s};for(let r of Object.keys(e)){let n=e[r],o=t[r];R(n)&&R(o)?t[r]=P(o,n):t[r]=n}return t}function re(s,e){let t=e.split("."),r=s;for(let n of t){if(r==null||typeof r!="object")return;r=r[n]}return r}function B(s){return s===void 0?s:JSON.parse(JSON.stringify(s))}var I=class{_doc=new g.Doc;_root=this._doc.getMap("session");_listeners=new Set;_key;_sessionId;_transport;_transportUnsubs=[];_synced;_pendingPatches=[];_observer=()=>this.notify();_updateHandler=(e,t)=>{t!==N&&this._transport?.sendDocSync(e)};constructor(e,t,r){this._key=e,this._sessionId=t,this._transport=r??null,this._synced=this._transport===null,this._root.observeDeep(this._observer),this._doc.on("update",this._updateHandler),this._transport&&(this._transportUnsubs.push(this._transport.onDocSync(n=>this.applyRemote(n)),this._transport.onDocSyncReady(()=>this.sendHello())),this._transport.isOpen&&this.sendHello())}setSessionId(e){this._sessionId=e}set(e){if(!this._synced){this._pendingPatches.push(B(e)),this.notify();return}this.applyPatch(e)}get(e,t){let r=this.snapshot();return e?re(r,e)??t:r}on(e,t){return this._listeners.add(t),()=>this._listeners.delete(t)}dispose(){this._root.unobserveDeep(this._observer),this._doc.off("update",this._updateHandler);for(let e of this._transportUnsubs)e();this._transportUnsubs=[],this._transport=null,this._listeners.clear(),this._doc.destroy()}sendHello(){this._transport&&this._transport.sendDocSync(g.encodeStateAsUpdate(this._doc))}applyRemote(e){if(g.applyUpdate(this._doc,e,N),!this._synced){this._synced=!0;let t=this._pendingPatches.splice(0);for(let r of t)this.applyPatch(r)}}applyPatch(e){this._doc.transact(()=>{let t=this._root.toJSON();for(let[r,n]of Object.entries(e)){let o=t[r],i=R(n)&&R(o)?P(o,n):B(n);JSON.stringify(i)!==JSON.stringify(o)&&this._root.set(r,i)}},te)}snapshot(){let e=this._root.toJSON();for(let t of this._pendingPatches)e=P(e,t);return e}notify(){let e=this.snapshot();for(let t of this._listeners)t(e)}};var se=new Set(["control"]),O=class{constructor(e,t){this._name=e;this._transport=t;this._track=this._transport.getTrackByName(this._name)??null,this._unsubscribeTransport=this._transport.on("track",()=>{let r=this._transport.getTrackByName(this._name)??null;r!==this._track&&this._setTrack(r)})}_name;_transport;_track=null;_handlers=new Map;_unsubscribeTransport=null;get track(){let e=this._transport.getTrackByName(this._name)??this._track;return e!==this._track&&this._setTrack(e),this._track}async attach(e){await this._transport.addTrack(e)}async detach(){this._transport.removeTrack()}async seek(e){if(e!=="live"&&(!Number.isFinite(e)||e<0))throw new Error('[urun] stream.seek target must be "live" or a non-negative number of seconds');this._transport.seekStream(this._name,e)}on(e,t){let r=this._handlers.get(e);return r||(r=new Set,this._handlers.set(e,r)),r.add(t),()=>{r?.delete(t),r?.size===0&&this._handlers.delete(e)}}dispose(){this._unsubscribeTransport?.(),this._unsubscribeTransport=null,this._handlers.clear()}_setTrack(e){this._track=e,e&&e.addEventListener("ended",()=>{this._track===e&&this._setTrack(null)},{once:!0});let t=this._handlers.get("track");if(t)for(let r of t)r(e)}},S=class s{_sessionId;_multiplexer;_transport;_docs=new Map;_streams=new Map;constructor(e,t,r){this._sessionId=e,this._multiplexer=t,this._transport=r}static async attach(e,t){let r=await j({baseUrl:t.baseUrl,fallbackUrls:t.fallbackUrls,sessionId:e,orgId:t.orgId,jwt:t.jwt,getAccessToken:t.getAccessToken,authProvider:t.authProvider}),n=t.getAccessToken?await t.getAccessToken()??void 0:t.jwt,o=new v,i=new k({url:r.wsUrl,orgId:t.orgId,jwt:n,authProvider:t.authProvider,sessionId:e}),l=new s(e,o,i);return i.on("connected",()=>{i.multiplexer&&o.setTarget(i.multiplexer)}),i.setConnection({url:r.wsUrl,sessionId:e}),await i.connect({role:"viewer"}),l}get id(){return this._sessionId}get phase(){return this._transport.phase}onPhase(e){return e(this._transport.phase),this._transport.on("phase",e)}setSessionId(e){if(e===this._sessionId)return;this._multiplexer.rewriteSessionChannels?.call(this._multiplexer,this._sessionId,e),this._sessionId=e;for(let r of this._docs.values())r.setSessionId(e)}stream(e){let t=this._streams.get(e);return t||(t=new O(e,this._transport),this._streams.set(e,t)),t}doc(e){let t=this._docs.get(e);return t||(t=new I(e,this._sessionId,se.has(e)?this._transport:null),this._docs.set(e,t)),t}disconnect(){for(let e of this._docs.values())e.dispose();this._docs.clear();for(let e of this._streams.values())e.dispose();this._streams.clear(),this._transport.disconnect()}};var ne=new Set(["then","catch","finally","toJSON",Symbol.toPrimitive]);function oe(s,e){return new Proxy({},{get(t,r){if(!(ne.has(r)||typeof r!="string"))return n=>{let o=n??{},i=()=>`s_${Date.now()}_${Math.random().toString(36).slice(2)}`,l=i(),h=new v,p=new k({url:"",orgId:e.orgId,jwt:e.jwt,authProvider:e.authProvider,sessionId:l}),d=new S(l,h,p),a=async c=>{let m=await L({baseUrl:e.baseUrl,fallbackUrls:e.fallbackUrls,app:s,functionName:r,orgId:e.orgId,jwt:e.jwt,getAccessToken:e.getAccessToken,authProvider:e.authProvider,idempotencyKey:c}),u=e.getAccessToken?await e.getAccessToken()??void 0:e.jwt;return d.setSessionId(m.sessionId),{url:m.wsUrl,sessionId:m.sessionId,jwt:u}};return p.setConnectionResolver(()=>a(i())),p.on("connected",()=>{p.multiplexer&&h.setTarget(p.multiplexer)}),(async()=>{let c=await a(l);p.setAuth({jwt:c.jwt,authProvider:e.authProvider,orgId:e.orgId}),p.setConnection({url:c.url,sessionId:c.sessionId}),await p.connect({app:s,functionName:r,args:o})})().catch(c=>{console.error(`[urun] Failed to connect session for ${r}:`,c)}),d}}})}var G=3e4,F="stream:",x=class{_ws;_multiplexer;_pendingRpc=new Map;_rpcId=0;constructor(e,t){this._ws=e,this._multiplexer=t,this._ws.addEventListener("message",r=>{let n;try{n=JSON.parse(typeof r.data=="string"?r.data:"")}catch{return}if(n.rpcId&&this._pendingRpc.has(n.rpcId)){let o=this._pendingRpc.get(n.rpcId);this._pendingRpc.delete(n.rpcId),clearTimeout(o.timer),n.error?o.reject(new Error(n.error)):o.resolve(n.result)}})}async get(e){return this._sendRpc("store.get",{key:e})}async has(e){return await this._sendRpc("store.has",{key:e})}on(e,t){let r=`${F}${e}`;return this._multiplexer.on(r,n=>{t(n)})}emit(e,t){let r=`${F}${e}`,n=typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{data:t};this._multiplexer.emit(r,n)}_getInternals(){return{multiplexer:this._multiplexer,ws:this._ws}}_sendRpc(e,t){return new Promise((r,n)=>{if(!this._ws||this._ws.readyState!==WebSocket.OPEN){n(new Error("WebSocket not open"));return}let o=String(++this._rpcId),i=setTimeout(()=>{this._pendingRpc.has(o)&&(this._pendingRpc.delete(o),n(new Error(`RPC request "${e}" timed out after ${G}ms`)))},G);this._pendingRpc.set(o,{resolve:r,reject:n,timer:i}),this._ws.send(JSON.stringify({rpcId:o,type:e,...t}))})}};function ie(s){let r=`${s.baseUrl.replace(/\/$/,"").replace(/^http/,"ws")}/store/${encodeURIComponent(s.orgId)}`,n=new WebSocket(r);(s.jwt||s.apiKey)&&n.addEventListener("open",()=>{n.send(JSON.stringify({type:"auth",orgId:s.orgId,jwt:s.jwt,authProvider:s.authProvider,apiKey:s.apiKey}))});let o=new M(n);return new x(n,o)}var ae='video/mp4; codecs="avc1.42E01E"';function ce(s,e){let t=e?.codec??ae,r=document.createElement("video");r.muted=!0,r.playsInline=!0;let n=new MediaSource,o=URL.createObjectURL(n);r.src=o,n.addEventListener("sourceopen",()=>{let c;try{c=n.addSourceBuffer(t)}catch(f){throw f instanceof DOMException&&f.name==="NotSupportedError"?new Error(`Codec not supported: "${t}". Ensure the codec string matches the fMP4 container format. Common values: video/mp4; codecs="avc1.42E01E" (H.264 Baseline), video/mp4; codecs="avc1.4D401F" (H.264 Main).`):f}let m=s.getReader();function u(){return c.updating?new Promise(f=>{c.addEventListener("updateend",()=>f(),{once:!0})}):Promise.resolve()}async function _(){try{for(;;){let{done:f,value:U}=await m.read();if(f){await u(),n.readyState==="open"&&n.endOfStream();return}await u();try{c.appendBuffer(U)}catch(y){if(y instanceof DOMException&&y.name==="QuotaExceededError"){let T=c.buffered;if(T.length>0){let J=T.start(T.length-1);c.remove(0,J),await u(),c.appendBuffer(U)}else throw y}else throw y}}}catch{if(n.readyState==="open")try{n.endOfStream("decode")}catch{}}}_()}),r.play().catch(()=>{});let i=r,l=i.captureStream??i.mozCaptureStream;if(!l)throw new Error("captureStream() is not supported in this browser. videoStream() requires HTMLMediaElement.captureStream() support.");let h=l.call(r),p=h.getTracks(),d=0,a=p.length;if(a===0)r.addEventListener("emptied",()=>{URL.revokeObjectURL(o)},{once:!0});else for(let c of p)c.addEventListener("ended",()=>{d++,d>=a&&URL.revokeObjectURL(o)});return h}export{oe as App,S as Session,ie as createStore,ce as videoStream};
1
+ import{a as F,b as P,e as O}from"./chunk-FPOLGUA2.mjs";var re="session-api.prod.cloud.urun.sh",ne=["https://session-api.use2.prod.cloud.urun.sh","https://session-api.usw2.prod.cloud.urun.sh"];function U(n){return n.trim().replace(/\/+$/,"")}function G(n,e){let t=[],r=s=>{if(!s)return;let o=U(s);o&&!t.includes(o)&&t.push(o)};r(n);for(let s of e??[])r(s);for(let s of pe(n))r(s);return t}var se=120,oe=1e3,ie=3;function ae(n){if(!n)return null;try{let e=new URL(n),t=e.pathname.replace(/\/api\/sessions\/create\/?$/,"");return U(`${e.origin}${t}`)}catch{return null}}async function J(n){let e=G(n.baseUrl,n.fallbackUrls),t=null,r=e.length>1;for(let s of e)try{return await ce(s,n,{pollAttempts:se,retryAfterLimitMs:r?oe:void 0})}catch(o){if(t=o instanceof Error?o:new Error(String(o)),t instanceof b)throw t}throw t??new Error("[urun] session allocation failed")}async function ce(n,e,t){let r,s,o,i=n,a=0,f=new Set;for(let p=0;p<t.pollAttempts;p++){s=o??await L(e),o=void 0;let d=r?await fetch(`${i}/api/session-requests/${encodeURIComponent(r)}`,{headers:D(e,s)}):await fetch(`${i}/api/sessions/create`,{method:"POST",redirect:"manual",headers:{...D(e,s),"Content-Type":"application/json","Idempotency-Key":e.idempotencyKey},body:JSON.stringify(ue(e))});if(!r&&(d.status===307||d.status===308)){let h=ae(d.headers.get("location"));if(h&&h!==i&&a<ie){a+=1,i=h;continue}throw new Error(`[urun] session create redirected from ${i} without a usable target`)}let c=await H(d);if(d.ok&&(c.status==="allocated"||!c.status&&!!c.session_id)&&!!c.session_id){let h=c.session_id;if(!c.ws_url)throw new b(`[urun] gateway allocated session ${h} without ws_url`);if(!Y(c.ws_url))throw new b(`[urun] gateway allocated session ${h} with non-absolute ws_url`);return{baseUrl:i,sessionId:h,wsUrl:c.ws_url,response:c}}if(d.status===202||c.status==="pending"||c.status==="queued"||c.queued){if(r=c.request_id||r,!r)throw new Error("[urun] gateway queued session without request_id");await de(le(d,c,t.retryAfterLimitMs));continue}if((d.status===401||d.status===403)&&e.getAccessToken){let h=s??"";f.add(h);let g=await L(e,{forceRefresh:!0,reason:"unauthorized"});if(g&&!f.has(g)){o=g,r=void 0;continue}}let m=c.error_message||c.error_code||`HTTP ${d.status}`;throw new Error(`[urun] session allocation failed at ${i}: ${m}`)}throw new Error(`[urun] timed out waiting for session allocation at ${i}`)}function D(n,e){let t={"X-Tenant-Id":n.orgId,"X-Auth-Provider":n.authProvider||"default","X-User-Id":"anonymous"};return e&&(t.Authorization=`Bearer ${e}`),t}async function L(n,e){return n.getAccessToken?await n.getAccessToken(e)??void 0:n.jwt}function ue(n){return{app:n.app,function:n.functionName,gpus:1,idempotency_key:n.idempotencyKey}}async function K(n){let e=G(n.baseUrl,n.fallbackUrls),t=null;for(let r of e)try{let s={baseUrl:r,app:"",functionName:"",orgId:n.orgId,jwt:n.jwt,getAccessToken:n.getAccessToken,authProvider:n.authProvider,idempotencyKey:""},o=await L(s),i=await fetch(`${U(r)}/api/sessions/${encodeURIComponent(n.sessionId)}/viewer-connect`,{headers:D(s,o)});if(!i.ok)throw new Error(`[urun] viewer-connect for ${n.sessionId} failed: HTTP ${i.status}`);let a=await H(i);if(!a.ws_url||!Y(a.ws_url))throw new b(`[urun] viewer-connect returned no usable ws_url for ${n.sessionId}`);return{baseUrl:U(r),sessionId:n.sessionId,wsUrl:a.ws_url,response:a}}catch(s){if(t=s instanceof Error?s:new Error(String(s)),t instanceof b)throw t}throw t??new Error("[urun] viewer-connect failed")}async function H(n){try{let e=await n.json();return e&&typeof e=="object"?e:{}}catch{return{}}}function le(n,e,t){let r=Number(n.headers.get("Retry-After")||""),s=Number(e.retry_after_seconds??r),o=t??1e4;return Number.isFinite(s)&&s>0?Math.min(s*1e3,o):1e3}function de(n){return new Promise(e=>setTimeout(e,n))}var b=class extends Error{};function Y(n){try{let e=new URL(n);return e.protocol==="ws:"||e.protocol==="wss:"}catch{return!1}}function pe(n){try{return new URL(n).hostname!==re?[]:ne}catch{return[]}}import*as R from"yjs";var V=Symbol("urun:doc:remote"),he=Symbol("urun:doc:local");function M(n){return n!==null&&typeof n=="object"&&!Array.isArray(n)}function j(n,e){let t={...n};for(let r of Object.keys(e)){let s=e[r],o=t[r];M(s)&&M(o)?t[r]=j(o,s):t[r]=s}return t}function fe(n,e){let t=e.split("."),r=n;for(let s of t){if(r==null||typeof r!="object")return;r=r[s]}return r}function W(n){return n===void 0?n:JSON.parse(JSON.stringify(n))}var q=class{_doc=new R.Doc;_root=this._doc.getMap("session");_listeners=new Set;_key;_sessionId;_transport;_transportUnsubs=[];_synced;_pendingPatches=[];_texts=new Map;_observer=()=>this.notify();_updateHandler=(e,t)=>{t!==V&&this._transport?.sendDocSync(this._key,e)};constructor(e,t,r){this._key=e,this._sessionId=t,this._transport=r??null,this._synced=this._transport===null,this._root.observeDeep(this._observer),this._doc.on("update",this._updateHandler),this._transport&&(this._transportUnsubs.push(this._transport.onDocSync(this._key,s=>this.applyRemote(s)),this._transport.onDocSyncReady(()=>this.sendHello())),this._transport.isOpen&&this.sendHello())}setSessionId(e){this._sessionId=e}set(e){if(!this._synced){this._pendingPatches.push(W(e)),this.notify();return}this.applyPatch(e)}get(e,t){let r=this.snapshot();return e?fe(r,e)??t:r}on(e,t){return this._listeners.add(t),()=>this._listeners.delete(t)}text(e){let t=this._texts.get(e);return t||(t=new $(this._doc.getText(`text:${e}`)),this._texts.set(e,t)),t}dispose(){this._root.unobserveDeep(this._observer),this._doc.off("update",this._updateHandler);for(let e of this._transportUnsubs)e();this._transportUnsubs=[],this._transport=null,this._listeners.clear();for(let e of this._texts.values())e.dispose();this._texts.clear(),this._doc.destroy()}sendHello(){this._transport&&this._transport.sendDocSync(this._key,R.encodeStateAsUpdate(this._doc))}applyRemote(e){if(R.applyUpdate(this._doc,e,V),!this._synced){this._synced=!0;let t=this._pendingPatches.splice(0);for(let r of t)this.applyPatch(r)}}applyPatch(e){this._doc.transact(()=>{let t=this._root.toJSON();for(let[r,s]of Object.entries(e)){let o=t[r],i=M(s)&&M(o)?j(o,s):W(s);JSON.stringify(i)!==JSON.stringify(o)&&this._root.set(r,i)}},he)}snapshot(){let e=this._root.toJSON();for(let t of this._pendingPatches)e=j(e,t);return e}notify(){let e=this.snapshot();for(let t of this._listeners)t(e)}},$=class{constructor(e){this._ytext=e;this._observer=t=>{for(let r of t.delta)if(typeof r.insert=="string"&&r.insert.length>0){let s=r.insert;for(let o of this._delta)o(s)}},this._ytext.observe(this._observer)}_ytext;_delta=new Set;_observer;append(e){e.length!==0&&this._ytext.insert(this._ytext.length,e)}toString(){return this._ytext.toString()}get length(){return this._ytext.length}on(e,t){return this._delta.add(t),()=>this._delta.delete(t)}dispose(){this._ytext.unobserve(this._observer),this._delta.clear()}};var y=class extends Error{requestId;code;constructor(e,t){super(e),this.name="RequestError",this.requestId=t?.requestId,this.code=t?.code,t?.cause!==void 0&&(this.cause=t.cause),Object.setPrototypeOf(this,new.target.prototype)}},T=class extends y{timeoutMs;constructor(e,t){super(`[urun] request timed out after ${e}ms`,{requestId:t}),this.name="RequestTimeoutError",this.timeoutMs=e,Object.setPrototypeOf(this,new.target.prototype)}},k=class extends y{constructor(e){super("[urun] request aborted",{requestId:e}),this.name="RequestAbortError",Object.setPrototypeOf(this,new.target.prototype)}},x=class extends y{constructor(e){super("[urun] request cancelled: session disconnected",{requestId:e}),this.name="RequestCancelledError",Object.setPrototypeOf(this,new.target.prototype)}};var ge=new Set,z="rpc";function X(){let n=globalThis.crypto;return n?.randomUUID?n.randomUUID():`req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`}function me(n,e,t,r,s){return{[Symbol.asyncIterator](){let o=[],i=null,a=!1,f=null,p=!1,d=n.text(e),c=null,u=null,m=null,h=()=>{c?.(),c=null,u?.(),u=null,m?.(),m=null,r?.removeEventListener("abort",S),p&&n.set({requests:{[e]:null}})},g=()=>{if(i){if(o.length>0){let l=i;i=null,l.resolve({value:o.shift(),done:!1})}else if(f!==null){let l=i;i=null,l.reject(f)}else if(a){let l=i;i=null,l.resolve({value:void 0,done:!0})}}},_=l=>{a||(o.push(l),g())},v=l=>{a||(f=l,a=!0,h(),g())},w=()=>{a||(a=!0,h(),g())},S=()=>v(new k(e)),E=l=>{if(l)if(l.error!==void 0&&l.error!==null){let I=typeof l.error=="string"?l.error:JSON.stringify(l.error);v(new y(I,{requestId:e,code:l.code}))}else l.done&&w()},ee=()=>{if(p)return;if(p=!0,r){if(r.aborted){v(new k(e));return}r.addEventListener("abort",S,{once:!0})}m=s?.(C=>v(C))??null,c=d.on("delta",_),u=n.on("change",C=>{if(a)return;let te=C.responses;E(te?.[e])}),n.set({requests:{[e]:{payload:t,stream:!0}}});let l=d.toString();l.length>0&&o.push(l);let I=n.get();E(I.responses?.[e])};return{next(){if(ee(),o.length>0)return Promise.resolve({value:o.shift(),done:!1});if(f!==null){let l=f;return f=null,Promise.reject(l)}return a?Promise.resolve({value:void 0,done:!0}):new Promise((l,I)=>{i={resolve:l,reject:I}})},return(){return a||(a=!0,h()),Promise.resolve({value:void 0,done:!0})},throw(l){return a||(a=!0,h()),Promise.reject(l)}}}}}var N=class{constructor(e,t){this._name=e;this._transport=t;this._track=this._transport.getTrackByName(this._name)??null,this._unsubscribeTransport=this._transport.on("track",()=>{let r=this._transport.getTrackByName(this._name)??null;r!==this._track&&this._setTrack(r)})}_name;_transport;_track=null;_handlers=new Map;_unsubscribeTransport=null;get track(){let e=this._transport.getTrackByName(this._name)??this._track;return e!==this._track&&this._setTrack(e),this._track}async attach(e){await this._transport.addTrack(e)}async detach(){this._transport.removeTrack()}async seek(e){if(e!=="live"&&(!Number.isFinite(e)||e<0))throw new Error('[urun] stream.seek target must be "live" or a non-negative number of seconds');this._transport.seekStream(this._name,e)}on(e,t){let r=this._handlers.get(e);return r||(r=new Set,this._handlers.set(e,r)),r.add(t),()=>{r?.delete(t),r?.size===0&&this._handlers.delete(e)}}dispose(){this._unsubscribeTransport?.(),this._unsubscribeTransport=null,this._handlers.clear()}_setTrack(e){this._track=e,e&&e.addEventListener("ended",()=>{this._track===e&&this._setTrack(null)},{once:!0});let t=this._handlers.get("track");if(t)for(let r of t)r(e)}},A=class n{_sessionId;_multiplexer;_transport;_docs=new Map;_streams=new Map;_activeRequests=new Set;constructor(e,t,r){this._sessionId=e,this._multiplexer=t,this._transport=r,this._wireControlDocIncarnation()}_wireControlDocIncarnation(){let e=this.doc("control");this._transport.applyControlDocState(e.get()),e.on("change",t=>{this._transport.applyControlDocState(t)})}static async attach(e,t){let r=await K({baseUrl:t.baseUrl,fallbackUrls:t.fallbackUrls,sessionId:e,orgId:t.orgId,jwt:t.jwt,getAccessToken:t.getAccessToken,authProvider:t.authProvider}),s=t.getAccessToken?await t.getAccessToken()??void 0:t.jwt,o=new P,i=new O({url:r.wsUrl,orgId:t.orgId,jwt:s,authProvider:t.authProvider,sessionId:e}),a=new n(e,o,i);return i.on("connected",()=>{i.multiplexer&&o.setTarget(i.multiplexer)}),i.setConnection({url:r.wsUrl,sessionId:e}),await i.connect({role:"viewer"}),a}get id(){return this._sessionId}get phase(){return this._transport.phase}onPhase(e){return e(this._transport.phase),this._transport.on("phase",e)}setSessionId(e){if(e===this._sessionId)return;this._multiplexer.rewriteSessionChannels?.call(this._multiplexer,this._sessionId,e),this._sessionId=e;for(let r of this._docs.values())r.setSessionId(e)}stream(e){let t=this._streams.get(e);return t||(t=new N(e,this._transport),this._streams.set(e,t)),t}doc(e){let t=this._docs.get(e);return t||(t=new q(e,this._sessionId,ge.has(e)?null:this._transport),this._docs.set(e,t)),t}request(e,t={}){let r=this.doc(z),s=X();return new Promise((o,i)=>{let a=!1,f=null,p=null,d=null,c=()=>{p&&(clearTimeout(p),p=null),f&&(f(),f=null),d&&(this._activeRequests.delete(d),d=null),t.signal?.removeEventListener("abort",m),r.set({requests:{[s]:null}})},u=g=>{a||(a=!0,c(),g())},m=()=>u(()=>i(new k(s)));if(t.signal){if(t.signal.aborted){a=!0,i(new k(s));return}t.signal.addEventListener("abort",m,{once:!0})}let h=g=>{let v=g.responses?.[s];if(v==null)return;let w=v;if(w.error!==void 0&&w.error!==null){let S=typeof w.error=="string"?w.error:JSON.stringify(w.error);u(()=>i(new y(S,{requestId:s,code:w.code})))}else u(()=>o(w.result))};f=r.on("change",h),d=g=>u(()=>i(g)),this._activeRequests.add(d),typeof t.timeout=="number"&&t.timeout>=0&&(p=setTimeout(()=>u(()=>i(new T(t.timeout,s))),t.timeout)),r.set({requests:{[s]:{payload:e}}}),h(r.get())})}requestStream(e,t={}){let r=this.doc(z),s=X();return me(r,s,e,t.signal,o=>(this._activeRequests.add(o),()=>this._activeRequests.delete(o)))}disconnect(){let e=Array.from(this._activeRequests);this._activeRequests.clear();for(let t of e)try{t(new x)}catch{}for(let t of this._docs.values())t.dispose();this._docs.clear();for(let t of this._streams.values())t.dispose();this._streams.clear(),this._transport.disconnect()}};var we=new Set(["then","catch","finally","toJSON",Symbol.toPrimitive]);function _e(n,e){return new Proxy({},{get(t,r){if(!(we.has(r)||typeof r!="string"))return s=>{let o=s??{},i=()=>`s_${Date.now()}_${Math.random().toString(36).slice(2)}`,a=i(),f=new P,p=new O({url:"",orgId:e.orgId,jwt:e.jwt,authProvider:e.authProvider,sessionId:a}),d=new A(a,f,p),c=async u=>{let m=await J({baseUrl:e.baseUrl,fallbackUrls:e.fallbackUrls,app:n,functionName:r,orgId:e.orgId,jwt:e.jwt,getAccessToken:e.getAccessToken,authProvider:e.authProvider,idempotencyKey:u}),h=e.getAccessToken?await e.getAccessToken()??void 0:e.jwt;return d.setSessionId(m.sessionId),{url:m.wsUrl,sessionId:m.sessionId,jwt:h}};return p.setConnectionResolver(()=>c(i())),p.on("connected",()=>{p.multiplexer&&f.setTarget(p.multiplexer)}),(async()=>{let u=await c(a);p.setAuth({jwt:u.jwt,authProvider:e.authProvider,orgId:e.orgId}),p.setConnection({url:u.url,sessionId:u.sessionId}),await p.connect({app:n,functionName:r,args:o})})().catch(u=>{console.error(`[urun] Failed to connect session for ${r}:`,u)}),d}}})}var Q=3e4,Z="stream:",B=class{_ws;_multiplexer;_pendingRpc=new Map;_rpcId=0;constructor(e,t){this._ws=e,this._multiplexer=t,this._ws.addEventListener("message",r=>{let s;try{s=JSON.parse(typeof r.data=="string"?r.data:"")}catch{return}if(s.rpcId&&this._pendingRpc.has(s.rpcId)){let o=this._pendingRpc.get(s.rpcId);this._pendingRpc.delete(s.rpcId),clearTimeout(o.timer),s.error?o.reject(new Error(s.error)):o.resolve(s.result)}})}async get(e){return this._sendRpc("store.get",{key:e})}async has(e){return await this._sendRpc("store.has",{key:e})}on(e,t){let r=`${Z}${e}`;return this._multiplexer.on(r,s=>{t(s)})}emit(e,t){let r=`${Z}${e}`,s=typeof t=="object"&&t!==null&&!Array.isArray(t)?t:{data:t};this._multiplexer.emit(r,s)}_getInternals(){return{multiplexer:this._multiplexer,ws:this._ws}}_sendRpc(e,t){return new Promise((r,s)=>{if(!this._ws||this._ws.readyState!==WebSocket.OPEN){s(new Error("WebSocket not open"));return}let o=String(++this._rpcId),i=setTimeout(()=>{this._pendingRpc.has(o)&&(this._pendingRpc.delete(o),s(new Error(`RPC request "${e}" timed out after ${Q}ms`)))},Q);this._pendingRpc.set(o,{resolve:r,reject:s,timer:i}),this._ws.send(JSON.stringify({rpcId:o,type:e,...t}))})}};function ve(n){let r=`${n.baseUrl.replace(/\/$/,"").replace(/^http/,"ws")}/store/${encodeURIComponent(n.orgId)}`,s=new WebSocket(r);(n.jwt||n.apiKey)&&s.addEventListener("open",()=>{s.send(JSON.stringify({type:"auth",orgId:n.orgId,jwt:n.jwt,authProvider:n.authProvider,apiKey:n.apiKey}))});let o=new F(s);return new B(s,o)}var ye='video/mp4; codecs="avc1.42E01E"';function Se(n,e){let t=e?.codec??ye,r=document.createElement("video");r.muted=!0,r.playsInline=!0;let s=new MediaSource,o=URL.createObjectURL(s);r.src=o,s.addEventListener("sourceopen",()=>{let u;try{u=s.addSourceBuffer(t)}catch(_){throw _ instanceof DOMException&&_.name==="NotSupportedError"?new Error(`Codec not supported: "${t}". Ensure the codec string matches the fMP4 container format. Common values: video/mp4; codecs="avc1.42E01E" (H.264 Baseline), video/mp4; codecs="avc1.4D401F" (H.264 Main).`):_}let m=n.getReader();function h(){return u.updating?new Promise(_=>{u.addEventListener("updateend",()=>_(),{once:!0})}):Promise.resolve()}async function g(){try{for(;;){let{done:_,value:v}=await m.read();if(_){await h(),s.readyState==="open"&&s.endOfStream();return}await h();try{u.appendBuffer(v)}catch(w){if(w instanceof DOMException&&w.name==="QuotaExceededError"){let S=u.buffered;if(S.length>0){let E=S.start(S.length-1);u.remove(0,E),await h(),u.appendBuffer(v)}else throw w}else throw w}}}catch{if(s.readyState==="open")try{s.endOfStream("decode")}catch{}}}g()}),r.play().catch(()=>{});let i=r,a=i.captureStream??i.mozCaptureStream;if(!a)throw new Error("captureStream() is not supported in this browser. videoStream() requires HTMLMediaElement.captureStream() support.");let f=a.call(r),p=f.getTracks(),d=0,c=p.length;if(c===0)r.addEventListener("emptied",()=>{URL.revokeObjectURL(o)},{once:!0});else for(let u of p)u.addEventListener("ended",()=>{d++,d>=c&&URL.revokeObjectURL(o)});return f}export{_e as App,k as RequestAbortError,x as RequestCancelledError,y as RequestError,T as RequestTimeoutError,A as Session,ve as createStore,Se as videoStream};
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- type TransportState = 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'failed';
3
+ type TransportState = 'connecting' | 'connected' | 'reconnecting' | 'renegotiating' | 'disconnected' | 'failed';
4
4
 
5
5
  type SessionPhaseName = 'idle' | 'queued' | 'provisioning' | 'connecting' | 'live' | 'error' | 'ended';
6
6
 
@@ -36,6 +36,15 @@ interface TransportSessionOptions {
36
36
  authProvider?: string;
37
37
 
38
38
  sessionId?: string;
39
+
40
+ mediaLiveness?: MediaLivenessOptions;
41
+ }
42
+
43
+ interface MediaLivenessOptions {
44
+
45
+ pollMs?: number;
46
+
47
+ stallTimeoutMs?: number;
39
48
  }
40
49
 
41
50
  type ChannelName = 'scene_graph' | 'ui_components' | 'events' | 'agent_status' | 'control';
@@ -139,6 +148,17 @@ interface Store {
139
148
  emit(name: string, data: unknown): void;
140
149
  }
141
150
 
151
+ interface SessionText {
152
+
153
+ append(text: string): void;
154
+
155
+ toString(): string;
156
+
157
+ readonly length: number;
158
+
159
+ on(event: 'delta', handler: (inserted: string) => void): () => void;
160
+ }
161
+
142
162
  interface SessionDocument {
143
163
 
144
164
  set(patch: Record<string, unknown>): void;
@@ -146,6 +166,8 @@ interface SessionDocument {
146
166
  get(path?: string, defaultValue?: unknown): unknown;
147
167
 
148
168
  on(event: 'change', handler: (snapshot: Record<string, unknown>) => void): () => void;
169
+
170
+ text(field: string): SessionText;
149
171
  }
150
172
 
151
173
  interface SessionStream {
@@ -161,6 +183,18 @@ interface SessionStream {
161
183
  on(event: 'track', handler: (track: MediaStreamTrack | null) => void): () => void;
162
184
  }
163
185
 
186
+ interface RequestOptions {
187
+
188
+ timeout?: number;
189
+
190
+ signal?: AbortSignal;
191
+ }
192
+
193
+ interface RequestStreamOptions {
194
+
195
+ signal?: AbortSignal;
196
+ }
197
+
164
198
  interface Session {
165
199
 
166
200
  readonly id: string;
@@ -171,6 +205,10 @@ interface Session {
171
205
 
172
206
  doc(key: string): SessionDocument;
173
207
 
208
+ request(payload: unknown, options?: RequestOptions): Promise<unknown>;
209
+
210
+ requestStream(payload: unknown, options?: RequestStreamOptions): AsyncIterable<string>;
211
+
174
212
  onPhase(handler: (phase: SessionPhase) => void): () => void;
175
213
 
176
214
  disconnect(): void;
@@ -242,6 +280,13 @@ interface TransportConnection {
242
280
  sessionId: string;
243
281
  jwt?: string;
244
282
  }
283
+
284
+ declare function encodeDocSyncFrame(docKey: string, payload: Uint8Array): Uint8Array;
285
+
286
+ declare function decodeDocSyncFrame(frame: Uint8Array): {
287
+ docKey: string;
288
+ payload: Uint8Array;
289
+ } | null;
245
290
  interface TransportEvents {
246
291
  connected: () => void;
247
292
  disconnected: () => void;
@@ -250,7 +295,7 @@ interface TransportEvents {
250
295
  started: () => void;
251
296
  audioTransportReady: () => void;
252
297
 
253
- docSync: (payload: Uint8Array) => void;
298
+ docSync: (docKey: string, payload: Uint8Array) => void;
254
299
 
255
300
  docSyncReady: () => void;
256
301
 
@@ -303,7 +348,21 @@ declare class TransportSession {
303
348
  private _phase;
304
349
  private _requestId;
305
350
  private _liveReached;
351
+
352
+ private _mediaMonitorTimer;
353
+
354
+ private _lastInboundTotal;
355
+
356
+ private _mediaEverFlowed;
357
+
358
+ private _lastInboundAdvanceAt;
359
+
360
+ private _mediaDeathHandled;
361
+
362
+ private _currentEpoch;
306
363
  get state(): TransportState;
364
+
365
+ get currentIncarnation(): number;
307
366
  get phase(): SessionPhase;
308
367
  get sessionId(): string | null;
309
368
  get tracks(): Map<string, MediaStreamTrack>;
@@ -315,16 +374,26 @@ declare class TransportSession {
315
374
  constructor(options?: TransportSessionOptions);
316
375
  setConnection(options: Pick<TransportSessionOptions, 'url' | 'fallbackUrls' | 'sessionId'>): void;
317
376
  setConnectionResolver(resolveConnection: (() => Promise<TransportConnection>) | null): void;
377
+
378
+ applyControlDocState(state: Record<string, unknown> | null | undefined): void;
379
+
380
+ setIncarnation(epoch: number): void;
381
+
382
+ isStaleIncarnation(epoch: number): boolean;
383
+
384
+ isStaleClosedMarker(marker: Record<string, unknown> | null | undefined): boolean;
318
385
  connect(startOptions?: SessionStartOptions): Promise<void>;
319
386
  disconnect(): void;
320
387
  on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): () => void;
321
388
  sendInput(data: Record<string, unknown>, sequence?: number): void;
322
389
 
323
- sendDocSync(payload: Uint8Array): void;
390
+ sendDocSync(docKey: string, payload: Uint8Array): void;
324
391
 
325
- onDocSync(handler: (payload: Uint8Array) => void): () => void;
392
+ onDocSync(docKey: string, handler: (payload: Uint8Array) => void): () => void;
326
393
 
327
394
  onDocSyncReady(handler: () => void): () => void;
395
+
396
+ private _emitDocSyncFrame;
328
397
  addTrack(track: MediaStreamTrack): Promise<void>;
329
398
  removeTrack(): void;
330
399
  requestDiagnostics(): void;
@@ -341,6 +410,14 @@ declare class TransportSession {
341
410
  private _failoverRecvToTcp;
342
411
  private _onCreateSendTransport;
343
412
  private _onConsume;
413
+ private _mediaPollMs;
414
+ private _mediaStallTimeoutMs;
415
+
416
+ private _startMediaMonitor;
417
+ private _stopMediaMonitor;
418
+ private _sampleMediaLiveness;
419
+
420
+ private _renegotiate;
344
421
  private _attemptReconnect;
345
422
  private _connectUrls;
346
423
  private _connectOnce;
@@ -358,4 +435,4 @@ declare class TransportSession {
358
435
  private _emitError;
359
436
  }
360
437
 
361
- export { type App as A, type ChannelEndpoint as C, type Layer as L, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type SceneGraph as h, type Session as i, type SessionDocument as j, type SessionPhase as k, type SessionPhaseName as l, type SessionStartOptions as m, type SessionStream as n, type Store as o, type StoreOptions as p, type TransportSessionOptions as q, type TransportState as r };
438
+ export { type App as A, type ChannelEndpoint as C, type Layer as L, type RequestOptions as R, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type RequestStreamOptions as h, type SceneGraph as i, type Session as j, type SessionDocument as k, type SessionPhase as l, type SessionPhaseName as m, type SessionStartOptions as n, type SessionStream as o, type SessionText as p, type Store as q, type StoreOptions as r, type TransportSessionOptions as s, type TransportState as t, decodeDocSyncFrame as u, encodeDocSyncFrame as v };
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- type TransportState = 'connecting' | 'connected' | 'reconnecting' | 'disconnected' | 'failed';
3
+ type TransportState = 'connecting' | 'connected' | 'reconnecting' | 'renegotiating' | 'disconnected' | 'failed';
4
4
 
5
5
  type SessionPhaseName = 'idle' | 'queued' | 'provisioning' | 'connecting' | 'live' | 'error' | 'ended';
6
6
 
@@ -36,6 +36,15 @@ interface TransportSessionOptions {
36
36
  authProvider?: string;
37
37
 
38
38
  sessionId?: string;
39
+
40
+ mediaLiveness?: MediaLivenessOptions;
41
+ }
42
+
43
+ interface MediaLivenessOptions {
44
+
45
+ pollMs?: number;
46
+
47
+ stallTimeoutMs?: number;
39
48
  }
40
49
 
41
50
  type ChannelName = 'scene_graph' | 'ui_components' | 'events' | 'agent_status' | 'control';
@@ -139,6 +148,17 @@ interface Store {
139
148
  emit(name: string, data: unknown): void;
140
149
  }
141
150
 
151
+ interface SessionText {
152
+
153
+ append(text: string): void;
154
+
155
+ toString(): string;
156
+
157
+ readonly length: number;
158
+
159
+ on(event: 'delta', handler: (inserted: string) => void): () => void;
160
+ }
161
+
142
162
  interface SessionDocument {
143
163
 
144
164
  set(patch: Record<string, unknown>): void;
@@ -146,6 +166,8 @@ interface SessionDocument {
146
166
  get(path?: string, defaultValue?: unknown): unknown;
147
167
 
148
168
  on(event: 'change', handler: (snapshot: Record<string, unknown>) => void): () => void;
169
+
170
+ text(field: string): SessionText;
149
171
  }
150
172
 
151
173
  interface SessionStream {
@@ -161,6 +183,18 @@ interface SessionStream {
161
183
  on(event: 'track', handler: (track: MediaStreamTrack | null) => void): () => void;
162
184
  }
163
185
 
186
+ interface RequestOptions {
187
+
188
+ timeout?: number;
189
+
190
+ signal?: AbortSignal;
191
+ }
192
+
193
+ interface RequestStreamOptions {
194
+
195
+ signal?: AbortSignal;
196
+ }
197
+
164
198
  interface Session {
165
199
 
166
200
  readonly id: string;
@@ -171,6 +205,10 @@ interface Session {
171
205
 
172
206
  doc(key: string): SessionDocument;
173
207
 
208
+ request(payload: unknown, options?: RequestOptions): Promise<unknown>;
209
+
210
+ requestStream(payload: unknown, options?: RequestStreamOptions): AsyncIterable<string>;
211
+
174
212
  onPhase(handler: (phase: SessionPhase) => void): () => void;
175
213
 
176
214
  disconnect(): void;
@@ -242,6 +280,13 @@ interface TransportConnection {
242
280
  sessionId: string;
243
281
  jwt?: string;
244
282
  }
283
+
284
+ declare function encodeDocSyncFrame(docKey: string, payload: Uint8Array): Uint8Array;
285
+
286
+ declare function decodeDocSyncFrame(frame: Uint8Array): {
287
+ docKey: string;
288
+ payload: Uint8Array;
289
+ } | null;
245
290
  interface TransportEvents {
246
291
  connected: () => void;
247
292
  disconnected: () => void;
@@ -250,7 +295,7 @@ interface TransportEvents {
250
295
  started: () => void;
251
296
  audioTransportReady: () => void;
252
297
 
253
- docSync: (payload: Uint8Array) => void;
298
+ docSync: (docKey: string, payload: Uint8Array) => void;
254
299
 
255
300
  docSyncReady: () => void;
256
301
 
@@ -303,7 +348,21 @@ declare class TransportSession {
303
348
  private _phase;
304
349
  private _requestId;
305
350
  private _liveReached;
351
+
352
+ private _mediaMonitorTimer;
353
+
354
+ private _lastInboundTotal;
355
+
356
+ private _mediaEverFlowed;
357
+
358
+ private _lastInboundAdvanceAt;
359
+
360
+ private _mediaDeathHandled;
361
+
362
+ private _currentEpoch;
306
363
  get state(): TransportState;
364
+
365
+ get currentIncarnation(): number;
307
366
  get phase(): SessionPhase;
308
367
  get sessionId(): string | null;
309
368
  get tracks(): Map<string, MediaStreamTrack>;
@@ -315,16 +374,26 @@ declare class TransportSession {
315
374
  constructor(options?: TransportSessionOptions);
316
375
  setConnection(options: Pick<TransportSessionOptions, 'url' | 'fallbackUrls' | 'sessionId'>): void;
317
376
  setConnectionResolver(resolveConnection: (() => Promise<TransportConnection>) | null): void;
377
+
378
+ applyControlDocState(state: Record<string, unknown> | null | undefined): void;
379
+
380
+ setIncarnation(epoch: number): void;
381
+
382
+ isStaleIncarnation(epoch: number): boolean;
383
+
384
+ isStaleClosedMarker(marker: Record<string, unknown> | null | undefined): boolean;
318
385
  connect(startOptions?: SessionStartOptions): Promise<void>;
319
386
  disconnect(): void;
320
387
  on<E extends keyof TransportEvents>(event: E, handler: TransportEvents[E]): () => void;
321
388
  sendInput(data: Record<string, unknown>, sequence?: number): void;
322
389
 
323
- sendDocSync(payload: Uint8Array): void;
390
+ sendDocSync(docKey: string, payload: Uint8Array): void;
324
391
 
325
- onDocSync(handler: (payload: Uint8Array) => void): () => void;
392
+ onDocSync(docKey: string, handler: (payload: Uint8Array) => void): () => void;
326
393
 
327
394
  onDocSyncReady(handler: () => void): () => void;
395
+
396
+ private _emitDocSyncFrame;
328
397
  addTrack(track: MediaStreamTrack): Promise<void>;
329
398
  removeTrack(): void;
330
399
  requestDiagnostics(): void;
@@ -341,6 +410,14 @@ declare class TransportSession {
341
410
  private _failoverRecvToTcp;
342
411
  private _onCreateSendTransport;
343
412
  private _onConsume;
413
+ private _mediaPollMs;
414
+ private _mediaStallTimeoutMs;
415
+
416
+ private _startMediaMonitor;
417
+ private _stopMediaMonitor;
418
+ private _sampleMediaLiveness;
419
+
420
+ private _renegotiate;
344
421
  private _attemptReconnect;
345
422
  private _connectUrls;
346
423
  private _connectOnce;
@@ -358,4 +435,4 @@ declare class TransportSession {
358
435
  private _emitError;
359
436
  }
360
437
 
361
- export { type App as A, type ChannelEndpoint as C, type Layer as L, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type SceneGraph as h, type Session as i, type SessionDocument as j, type SessionPhase as k, type SessionPhaseName as l, type SessionStartOptions as m, type SessionStream as n, type Store as o, type StoreOptions as p, type TransportSessionOptions as q, type TransportState as r };
438
+ export { type App as A, type ChannelEndpoint as C, type Layer as L, type RequestOptions as R, type SceneContext as S, TransportSession as T, type AppOptions as a, type AttachOptions as b, type ChannelMessage as c, ChannelMultiplexer as d, type ChannelName as e, type LayoutConfig as f, type LayoutContext as g, type RequestStreamOptions as h, type SceneGraph as i, type Session as j, type SessionDocument as k, type SessionPhase as l, type SessionPhaseName as m, type SessionStartOptions as n, type SessionStream as o, type SessionText as p, type Store as q, type StoreOptions as r, type TransportSessionOptions as s, type TransportState as t, decodeDocSyncFrame as u, encodeDocSyncFrame as v };
@@ -1 +1 @@
1
- export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, m as SessionStartOptions, T as TransportSession, q as TransportSessionOptions } from './internal-B-5h9uZU.mjs';
1
+ export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, n as SessionStartOptions, T as TransportSession, s as TransportSessionOptions, u as decodeDocSyncFrame, v as encodeDocSyncFrame } from './internal-B7GoThNN.mjs';
@@ -1 +1 @@
1
- export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, m as SessionStartOptions, T as TransportSession, q as TransportSessionOptions } from './internal-B-5h9uZU.js';
1
+ export { c as ChannelMessage, d as ChannelMultiplexer, e as ChannelName, n as SessionStartOptions, T as TransportSession, s as TransportSessionOptions, u as decodeDocSyncFrame, v as encodeDocSyncFrame } from './internal-B7GoThNN.js';