@ikonai/sdk 1.7.0 → 1.8.0
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/assets/protocol-worker-PNQ9dfGq.js +3 -0
- package/channel/channel-manager.d.ts +1 -0
- package/client/ikon-client-config.d.ts +3 -0
- package/client/ikon-client.d.ts +13 -27
- package/index.d.ts +4 -3
- package/index.js +5796 -2502
- package/media/index.d.ts +2 -0
- package/media/media-permission.d.ts +47 -0
- package/package.json +5 -2
- package/transport/http-stream-transport.d.ts +1 -1
- package/transport/keepalive-watchdog.d.ts +15 -0
- package/transport/web-socket-transport.d.ts +1 -1
- package/transport/web-transport-transport.d.ts +1 -4
- package/utils/boot-signal.d.ts +14 -0
- package/utils/browser-compat.d.ts +17 -0
- package/utils/browser-support.d.ts +15 -10
- package/utils/query-params.d.ts +18 -0
- package/assets/protocol-worker-CW7oSQmQ.js +0 -3
- package/ikon-media-CdIF9gbL.js +0 -3154
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
function e(e){return e}function t(e){if(e.length<8)throw Error(`Protocol message too short`);return(e[4]|e[5]<<8|e[6]<<16|e[7]<<24)>>>0}function n(e){return t(e)&4294901760}function r(e){let t=te(e),n=new DataView(t.buffer,t.byteOffset,t.byteLength);if(t.length<27)throw Error(`Protocol payload too short`);let r=n.getUint32(0,!0),i=n.getUint32(4,!0),a=n.getUint32(8,!0),o=n.getUint32(12,!0),s=n.getUint32(16,!0),c=n.getUint32(20,!0),l=n.getUint8(24),u=n.getUint8(25),d=n.getUint8(26);if(27+c*4>t.length)throw Error(`Protocol header exceeds payload length`);let f=[],p=27;for(let e=0;e<c;e++)f.push(n.getUint32(p,!0)),p+=4;return{length:r,opcode:i,senderId:a,trackId:o,sequenceId:s,targetIds:f,payloadVersion:l,payloadType:u,flags:d}}function i(t,n,r,i,a){let o=a?.trackId??0,s=a?.sequenceId??0,c=a?.flags??0,l=a?.targetIds??[],u=a?.payloadType??8,d=27+l.length*4,f=d+n.length,p=new Uint8Array(f),m=new DataView(p.buffer);m.setUint32(0,f,!0),m.setUint32(4,t>>>0,!0),m.setUint32(8,i>>>0,!0),m.setUint32(12,o>>>0,!0),m.setUint32(16,s>>>0,!0),m.setUint32(20,l.length>>>0,!0),m.setUint8(24,r&255),m.setUint8(25,u&255),m.setUint8(26,c&255);let h=27;for(let e=0;e<l.length;e++)m.setUint32(h,l[e]>>>0,!0),h+=4;return p.set(n,d),e(p)}let a=function(e){return e[e.Null=1]=`Null`,e[e.Bool=2]=`Bool`,e[e.Int32=3]=`Int32`,e[e.Int64=4]=`Int64`,e[e.UInt32=5]=`UInt32`,e[e.UInt64=6]=`UInt64`,e[e.Float32=7]=`Float32`,e[e.Float64=8]=`Float64`,e[e.Array=9]=`Array`,e[e.Dict=10]=`Dict`,e[e.Object=11]=`Object`,e[e.String=12]=`String`,e[e.Binary=13]=`Binary`,e[e.Guid=14]=`Guid`,e}({});const o=new TextEncoder;new TextDecoder(`utf-8`,{fatal:!0});var s=class e{buffer=new f;cached;constructor(e=1){this.buffer.writeByte(161),this.buffer.writeVarUInt(e>>>0)}writeInt32Field(e,t){this.writeFixedField(e,3,()=>this.buffer.writeInt32(t|0))}writeUInt32Field(e,t){this.writeFixedField(e,5,()=>this.buffer.writeUInt32(t>>>0))}writeInt64Field(e,t){this.writeFixedField(e,4,()=>this.buffer.writeBigInt64(t))}writeUInt64Field(e,t){this.writeFixedField(e,6,()=>this.buffer.writeBigUInt64(t))}writeFloat32Field(e,t){this.writeFixedField(e,7,()=>this.buffer.writeFloat32(t))}writeFloat64Field(e,t){this.writeFixedField(e,8,()=>this.buffer.writeFloat64(t))}writeBoolField(e,t){this.writeFixedField(e,2,()=>this.buffer.writeByte(+!!t))}writeGuidField(e,t){let n=t instanceof d?t.asBytes():t;if(n.length!==16)throw Error(`Guid payload must be 16 bytes`);this.writeFixedField(e,14,()=>this.buffer.writeBytes(n))}writeStringField(e,t){let n=o.encode(t??``);this.writeVariableField(e,12,n)}writeBinaryField(e,t){this.writeVariableField(e,13,t)}writeObjectField(t,n,r){let i=new e(n);r(i);let a=i.finish();this.writeVariableField(t,11,a)}writeArrayField(e,t,n){let r=new c(t);n(r);let i=r.finish();this.writeVariableField(e,9,i)}writeDictionaryField(e,t,n,r){let i=new l(t,n);r(i);let a=i.finish();this.writeVariableField(e,10,a)}finish(){return this.cached||=(this.buffer.writeByte(162),this.buffer.toUint8Array()),this.cached}writeFixedField(e,t,n){this.writeFieldHeader(e,t,0),n()}writeVariableField(e,t,n){this.writeFieldHeader(e,t,n.length),this.buffer.writeBytes(n)}writeFieldHeader(e,t,n){this.buffer.writeUInt32(e>>>0),this.buffer.writeByte(p(t)),m(t)&&this.buffer.writeVarUInt(n>>>0)}},c=class e{elementType;payload=new f;count=0;constructor(e){this.elementType=e}writeInt32(e){this.ensureElementType(3),this.count++,this.payload.writeInt32(e|0)}writeUInt32(e){this.ensureElementType(5),this.count++,this.payload.writeUInt32(e>>>0)}writeInt64(e){this.ensureElementType(4),this.count++,this.payload.writeBigInt64(e)}writeUInt64(e){this.ensureElementType(6),this.count++,this.payload.writeBigUInt64(e)}writeFloat32(e){this.ensureElementType(7),this.count++,this.payload.writeFloat32(e)}writeFloat64(e){this.ensureElementType(8),this.count++,this.payload.writeFloat64(e)}writeBool(e){this.ensureElementType(2),this.count++,this.payload.writeByte(+!!e)}writeGuid(e){this.ensureElementType(14),this.count++;let t=e instanceof d?e.asBytes():e;if(t.length!==16)throw Error(`Guid payload must be 16 bytes`);this.payload.writeBytes(t)}writeString(e){this.ensureElementType(12),this.count++;let t=o.encode(e??``);this.payload.writeVarUInt(t.length),this.payload.writeBytes(t)}writeBinary(e){this.ensureElementType(13),this.count++,this.payload.writeVarUInt(e.length),this.payload.writeBytes(e)}writeObject(e,t){this.ensureElementType(11),this.count++;let n=new s(e);t(n);let r=n.finish();this.payload.writeVarUInt(r.length),this.payload.writeBytes(r)}writeArray(t,n){this.ensureElementType(9),this.count++;let r=new e(t);n(r);let i=r.finish();this.payload.writeBytes(i)}writeDictionary(e,t,n){this.ensureElementType(10),this.count++;let r=new l(e,t);n(r);let i=r.finish();this.payload.writeBytes(i)}finish(){let e=new f;return e.writeByte(p(this.elementType)),e.writeVarUInt(this.count),e.writeBytes(this.payload.toUint8Array()),e.toUint8Array()}ensureElementType(e){if(this.elementType!==e)throw Error(`Array element type is ${a[this.elementType]}, expected ${a[e]}`)}},l=class{keyType;valueType;payload=new f;count=0;entryOpen=!1;constructor(e,t){this.keyType=e,this.valueType=t,h(e)}beginEntry(){if(this.entryOpen)throw Error(`Previous dictionary entry not completed`);return this.count++,this.entryOpen=!0,new u(this.keyType,this.valueType,this.payload,()=>{this.entryOpen=!1})}finish(){if(this.entryOpen)throw Error(`Dictionary entry not completed`);let e=new f;return e.writeByte(p(this.keyType)),e.writeByte(p(this.valueType)),e.writeVarUInt(this.count),e.writeBytes(this.payload.toUint8Array()),e.toUint8Array()}},u=class{keyType;valueType;payload;onComplete;keyWritten=!1;valueWritten=!1;completed=!1;constructor(e,t,n,r){this.keyType=e,this.valueType=t,this.payload=n,this.onComplete=r}writeKeyInt32(e){this.ensureKeyType(3),this.payload.writeInt32(e|0),this.keyWritten=!0}writeKeyUInt32(e){this.ensureKeyType(5),this.payload.writeUInt32(e>>>0),this.keyWritten=!0}writeKeyInt64(e){this.ensureKeyType(4),this.payload.writeBigInt64(e),this.keyWritten=!0}writeKeyUInt64(e){this.ensureKeyType(6),this.payload.writeBigUInt64(e),this.keyWritten=!0}writeKeyFloat32(e){this.ensureKeyType(7),this.payload.writeFloat32(e),this.keyWritten=!0}writeKeyFloat64(e){this.ensureKeyType(8),this.payload.writeFloat64(e),this.keyWritten=!0}writeKeyBool(e){this.ensureKeyType(2),this.payload.writeByte(+!!e),this.keyWritten=!0}writeKeyGuid(e){this.ensureKeyType(14);let t=e instanceof d?e.asBytes():e;if(t.length!==16)throw Error(`Guid payload must be 16 bytes`);this.payload.writeBytes(t),this.keyWritten=!0}writeKeyString(e){this.ensureKeyType(12);let t=o.encode(e??``);this.payload.writeVarUInt(t.length),this.payload.writeBytes(t),this.keyWritten=!0}writeKeyBinary(e){this.ensureKeyType(13),this.payload.writeVarUInt(e.length),this.payload.writeBytes(e),this.keyWritten=!0}writeValueInt32(e){this.ensureValueType(3),this.payload.writeInt32(e|0),this.valueWritten=!0}writeValueUInt32(e){this.ensureValueType(5),this.payload.writeUInt32(e>>>0),this.valueWritten=!0}writeValueInt64(e){this.ensureValueType(4),this.payload.writeBigInt64(e),this.valueWritten=!0}writeValueUInt64(e){this.ensureValueType(6),this.payload.writeBigUInt64(e),this.valueWritten=!0}writeValueFloat32(e){this.ensureValueType(7),this.payload.writeFloat32(e),this.valueWritten=!0}writeValueFloat64(e){this.ensureValueType(8),this.payload.writeFloat64(e),this.valueWritten=!0}writeValueBool(e){this.ensureValueType(2),this.payload.writeByte(+!!e),this.valueWritten=!0}writeValueGuid(e){this.ensureValueType(14);let t=e instanceof d?e.asBytes():e;if(t.length!==16)throw Error(`Guid payload must be 16 bytes`);this.payload.writeBytes(t),this.valueWritten=!0}writeNullValue(){this.ensureValueType(1),this.valueWritten=!0}writeValueBinary(e){this.ensureValueType(13),this.payload.writeVarUInt(e.length),this.payload.writeBytes(e),this.valueWritten=!0}writeValueString(e){this.ensureValueType(12);let t=o.encode(e??``);this.payload.writeVarUInt(t.length),this.payload.writeBytes(t),this.valueWritten=!0}writeValueObject(e,t){this.ensureValueType(11);let n=new s(e);t(n);let r=n.finish();this.payload.writeVarUInt(r.length),this.payload.writeBytes(r),this.valueWritten=!0}writeValueArray(e,t){this.ensureValueType(9);let n=new c(e);t(n);let r=n.finish();this.payload.writeBytes(r),this.valueWritten=!0}writeValueDictionary(e,t,n){this.ensureValueType(10);let r=new l(e,t);n(r);let i=r.finish();this.payload.writeBytes(i),this.valueWritten=!0}complete(){if(!this.completed){if(!this.keyWritten||!this.valueWritten)throw Error(`Dictionary entry must write both key and value`);this.completed=!0,this.onComplete()}}ensureKeyType(e){if(this.keyType!==e)throw Error(`Dictionary key type is ${a[this.keyType]}, expected ${a[e]}`)}ensureValueType(e){if(this.valueType!==e)throw Error(`Dictionary value type is ${a[this.valueType]}, expected ${a[e]}`)}},d=class e{bytes;constructor(e){this.bytes=e}static fromString(t){if(!t)throw Error(`Guid string is empty`);let n=t.replace(/-/g,``);if(n.length!==32)throw Error(`Guid string must be 32 hex characters`);let r=new Uint8Array(16),i=e.parseHexSlice(n,0,8),a=e.parseHexSlice(n,8,4),o=e.parseHexSlice(n,12,4);e.writeUInt32LE(r,0,i),e.writeUInt16LE(r,4,a),e.writeUInt16LE(r,6,o);for(let t=0;t<8;t++)r[8+t]=e.parseHexSlice(n,16+t*2,2);return new e(r)}static fromBytes(t){if(t.length!==16)throw Error(`Guid byte array must be 16 bytes`);return new e(Uint8Array.from(t))}static createZero(){return new e(new Uint8Array(16))}static createRandom(){let t=new Uint8Array(16),n=globalThis.crypto;if(n?.getRandomValues)n.getRandomValues(t);else for(let e=0;e<t.length;e++)t[e]=Math.floor(Math.random()*256);return t[6]=t[6]&15|64,t[8]=t[8]&63|128,new e(t)}toString(){let t=this.bytes;return[e.toHex(e.readUInt32LE(t,0),8),e.toHex(e.readUInt16LE(t,4),4),e.toHex(e.readUInt16LE(t,6),4),ee(t.subarray(8,10)),ee(t.subarray(10,16))].join(`-`)}asBytes(){return this.bytes.slice()}static parseHexSlice(e,t,n){let r=e.substr(t,n),i=Number.parseInt(r,16);if(Number.isNaN(i))throw Error(`Guid string contains invalid characters`);return i>>>0}static writeUInt32LE(e,t,n){let r=n>>>0;e[t]=r&255,e[t+1]=r>>>8&255,e[t+2]=r>>>16&255,e[t+3]=r>>>24&255}static writeUInt16LE(e,t,n){let r=n&65535;e[t]=r&255,e[t+1]=r>>>8&255}static readUInt32LE(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0}static readUInt16LE(e,t){return(e[t]|e[t+1]<<8)&65535}static toHex(e,t){return(e>>>0).toString(16).padStart(t,`0`)}},f=class e{static INITIAL_CAPACITY=256;buffer;dataView;length=0;constructor(){this.buffer=new Uint8Array(e.INITIAL_CAPACITY),this.dataView=new DataView(this.buffer.buffer)}ensureCapacity(e){let t=this.length+e;if(t<=this.buffer.length)return;let n=this.buffer.length;for(;n<t;)n*=2;let r=new Uint8Array(n);r.set(this.buffer.subarray(0,this.length)),this.buffer=r,this.dataView=new DataView(this.buffer.buffer)}writeByte(e){this.ensureCapacity(1),this.buffer[this.length++]=e&255}writeBytes(e){this.ensureCapacity(e.length),this.buffer.set(e,this.length),this.length+=e.length}writeUInt32(e){this.ensureCapacity(4),this.dataView.setUint32(this.length,e>>>0,!0),this.length+=4}writeInt32(e){this.ensureCapacity(4),this.dataView.setInt32(this.length,e|0,!0),this.length+=4}writeFloat32(e){this.ensureCapacity(4),this.dataView.setFloat32(this.length,e,!0),this.length+=4}writeFloat64(e){this.ensureCapacity(8),this.dataView.setFloat64(this.length,e,!0),this.length+=8}writeBigInt64(e){this.ensureCapacity(8),this.dataView.setBigInt64(this.length,e,!0),this.length+=8}writeBigUInt64(e){this.ensureCapacity(8),this.dataView.setBigUint64(this.length,e,!0),this.length+=8}writeVarUInt(e){let t=e>>>0;for(;t>=128;)this.ensureCapacity(1),this.buffer[this.length++]=t&127|128,t>>>=7;this.ensureCapacity(1),this.buffer[this.length++]=t&127}toUint8Array(){return this.buffer.slice(0,this.length)}};function p(e,t=0){if(t&240)throw Error(`Teleport flags must fit into 4 bits`);return(e&15)<<4|t&15}function m(e){return e===12||e===13||e===9||e===11||e===10}function h(e){if(e===9||e===11||e===10||e===1)throw Error(`Dictionary keys must be primitive Teleport types`)}function ee(e){return Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}function te(e){return e instanceof Uint8Array?e:new Uint8Array(e)}let g=function(e){return e[e.None=0]=`None`,e[e.WebSocket=1]=`WebSocket`,e[e.WebSocketProxy=2]=`WebSocketProxy`,e[e.WebTransport=4]=`WebTransport`,e[e.WebTransportProxy=8]=`WebTransportProxy`,e[e.Tcp=16]=`Tcp`,e[e.TcpProxy=32]=`TcpProxy`,e[e.Https=64]=`Https`,e[e.WebRTC=128]=`WebRTC`,e[e.TcpTls=256]=`TcpTls`,e[e.Udp=512]=`Udp`,e[e.UdpDtls=1024]=`UdpDtls`,e[e.HttpStream=2048]=`HttpStream`,e[e.HttpStreamProxy=4096]=`HttpStreamProxy`,e}({}),_=function(e){return e[e.NONE=0]=`NONE`,e[e.CONSTANT_GROUP_BITS=15]=`CONSTANT_GROUP_BITS`,e[e.CONSTANT_GROUP_OFFSET=16]=`CONSTANT_GROUP_OFFSET`,e[e.GROUP_CORE=65536]=`GROUP_CORE`,e[e.CORE_AUTH_RESPONSE=65537]=`CORE_AUTH_RESPONSE`,e[e.CORE_AUTH_TICKET=65538]=`CORE_AUTH_TICKET`,e[e.CORE_GLOBAL_STATE=65539]=`CORE_GLOBAL_STATE`,e[e.CORE_ON_SERVER_STATUS_PING=65540]=`CORE_ON_SERVER_STATUS_PING`,e[e.CORE_ON_USER_JOINED=65541]=`CORE_ON_USER_JOINED`,e[e.CORE_ON_USER_LEFT=65542]=`CORE_ON_USER_LEFT`,e[e.CORE_ON_CLIENT_JOINED=65543]=`CORE_ON_CLIENT_JOINED`,e[e.CORE_ON_CLIENT_LEFT=65544]=`CORE_ON_CLIENT_LEFT`,e[e.CORE_ON_SERVER_STARTED=65545]=`CORE_ON_SERVER_STARTED`,e[e.CORE_ON_SERVER_STOPPED=65546]=`CORE_ON_SERVER_STOPPED`,e[e.CORE_ON_SERVER_STOPPING=65547]=`CORE_ON_SERVER_STOPPING`,e[e.CORE_ON_CLIENT_READY=65548]=`CORE_ON_CLIENT_READY`,e[e.CORE_CLIENT_READY=65549]=`CORE_CLIENT_READY`,e[e.CORE_SERVER_INIT=65550]=`CORE_SERVER_INIT`,e[e.CORE_ON_PLUGIN_RELOADED=65551]=`CORE_ON_PLUGIN_RELOADED`,e[e.CORE_DYNAMIC_CONFIG=65555]=`CORE_DYNAMIC_CONFIG`,e[e.CORE_PROXY_RPC_AUTH_TICKET=65556]=`CORE_PROXY_RPC_AUTH_TICKET`,e[e.CORE_UPDATE_CLIENT_CONTEXT=65558]=`CORE_UPDATE_CLIENT_CONTEXT`,e[e.CORE_BACKGROUND_WORK_ACTIVE=65559]=`CORE_BACKGROUND_WORK_ACTIVE`,e[e.CORE_RESET_IDLE=65560]=`CORE_RESET_IDLE`,e[e.CORE_CLIENT_DISCONNECTING=65561]=`CORE_CLIENT_DISCONNECTING`,e[e.CORE_ON_APP_READY=65562]=`CORE_ON_APP_READY`,e[e.CORE_ON_FRONTEND_RELOADED=65563]=`CORE_ON_FRONTEND_RELOADED`,e[e.CORE_ON_USER_DATA_ERASED=65564]=`CORE_ON_USER_DATA_ERASED`,e[e.CORE_WEBRTC_OFFER=65566]=`CORE_WEBRTC_OFFER`,e[e.CORE_WEBRTC_ANSWER=65567]=`CORE_WEBRTC_ANSWER`,e[e.CORE_WEBRTC_ICE_CANDIDATE=65568]=`CORE_WEBRTC_ICE_CANDIDATE`,e[e.CORE_WEBRTC_READY=65569]=`CORE_WEBRTC_READY`,e[e.CORE_WEBRTC_AUDIO_SEGMENT=65570]=`CORE_WEBRTC_AUDIO_SEGMENT`,e[e.CORE_WEBRTC_TRACK_MAP=65571]=`CORE_WEBRTC_TRACK_MAP`,e[e.CORE_WEBRTC_VIDEO_CAPTURE=65572]=`CORE_WEBRTC_VIDEO_CAPTURE`,e[e.CORE_WEBRTC_ICE_SERVERS_REQUEST=65573]=`CORE_WEBRTC_ICE_SERVERS_REQUEST`,e[e.CORE_WEBRTC_ICE_SERVERS_RESPONSE=65574]=`CORE_WEBRTC_ICE_SERVERS_RESPONSE`,e[e.CORE_WEBRTC_CLOSE=65575]=`CORE_WEBRTC_CLOSE`,e[e.CORE_RELAY_AGENT_AUTH=65576]=`CORE_RELAY_AGENT_AUTH`,e[e.CORE_RELAY_AGENT_AUTH_RESULT=65577]=`CORE_RELAY_AGENT_AUTH_RESULT`,e[e.CORE_RELAY_HEARTBEAT=65578]=`CORE_RELAY_HEARTBEAT`,e[e.CORE_RELAY_TCP_CONNECTION_OPENED=65579]=`CORE_RELAY_TCP_CONNECTION_OPENED`,e[e.CORE_RELAY_TCP_CONNECTION_CLOSED=65580]=`CORE_RELAY_TCP_CONNECTION_CLOSED`,e[e.CORE_RELAY_TCP_DATA=65581]=`CORE_RELAY_TCP_DATA`,e[e.CORE_RELAY_UDP_DATA=65582]=`CORE_RELAY_UDP_DATA`,e[e.CORE_RELAY_ADD_TUNNEL=65583]=`CORE_RELAY_ADD_TUNNEL`,e[e.CORE_RELAY_TUNNEL_ADDED=65584]=`CORE_RELAY_TUNNEL_ADDED`,e[e.CORE_RELAY_REMOVE_TUNNEL=65585]=`CORE_RELAY_REMOVE_TUNNEL`,e[e.CORE_IKON_SERVER_ENDPOINT_HOST_INFO=65586]=`CORE_IKON_SERVER_ENDPOINT_HOST_INFO`,e[e.CORE_CLIENT_INITIALIZATION=65587]=`CORE_CLIENT_INITIALIZATION`,e[e.CORE_CLIENT_LIFECYCLE_BATCH=65588]=`CORE_CLIENT_LIFECYCLE_BATCH`,e[e.CORE_APP_CONFIG=65589]=`CORE_APP_CONFIG`,e[e.GROUP_KEEPALIVE=131072]=`GROUP_KEEPALIVE`,e[e.KEEPALIVE_REQUEST=131073]=`KEEPALIVE_REQUEST`,e[e.KEEPALIVE_RESPONSE=131074]=`KEEPALIVE_RESPONSE`,e[e.GROUP_EVENTS=262144]=`GROUP_EVENTS`,e[e.EVENTS_PROFILE_UPDATE=262145]=`EVENTS_PROFILE_UPDATE`,e[e.EVENTS_SPEECH_PLAYBACK_COMPLETE=262147]=`EVENTS_SPEECH_PLAYBACK_COMPLETE`,e[e.GROUP_ANALYTICS=524288]=`GROUP_ANALYTICS`,e[e.ANALYTICS_LOGS=524289]=`ANALYTICS_LOGS`,e[e.ANALYTICS_EVENTS=524290]=`ANALYTICS_EVENTS`,e[e.ANALYTICS_USAGES=524291]=`ANALYTICS_USAGES`,e[e.ANALYTICS_USAGE=524292]=`ANALYTICS_USAGE`,e[e.ANALYTICS_SPECIAL_LOG=524293]=`ANALYTICS_SPECIAL_LOG`,e[e.ANALYTICS_PROCESSING_UPDATE=524294]=`ANALYTICS_PROCESSING_UPDATE`,e[e.ANALYTICS_REACTIVE_PROCESSING_UPDATE=524295]=`ANALYTICS_REACTIVE_PROCESSING_UPDATE`,e[e.ANALYTICS_IKON_PROXY_SERVER_STATS=524296]=`ANALYTICS_IKON_PROXY_SERVER_STATS`,e[e.ANALYTICS_IKON_RELAY_SERVER_STATS=524297]=`ANALYTICS_IKON_RELAY_SERVER_STATS`,e[e.ANALYTICS_IKON_TURN_SERVER_STATS=524298]=`ANALYTICS_IKON_TURN_SERVER_STATS`,e[e.ANALYTICS_IKON_HOST_SERVER_STATS=524299]=`ANALYTICS_IKON_HOST_SERVER_STATS`,e[e.ANALYTICS_TRAFFIC_USAGE=524300]=`ANALYTICS_TRAFFIC_USAGE`,e[e.GROUP_ACTIONS=1048576]=`GROUP_ACTIONS`,e[e.ACTION_CALL=1048577]=`ACTION_CALL`,e[e.ACTION_ACTIVE=1048578]=`ACTION_ACTIVE`,e[e.ACTION_TEXT_OUTPUT=1048579]=`ACTION_TEXT_OUTPUT`,e[e.ACTION_TEXT_OUTPUT_DELTA=1048580]=`ACTION_TEXT_OUTPUT_DELTA`,e[e.ACTION_TEXT_OUTPUT_DELTA_FULL=1048581]=`ACTION_TEXT_OUTPUT_DELTA_FULL`,e[e.ACTION_SET_STATE=1048582]=`ACTION_SET_STATE`,e[e.ACTION_TAP=1048583]=`ACTION_TAP`,e[e.ACTION_PAN=1048584]=`ACTION_PAN`,e[e.ACTION_ZOOM=1048585]=`ACTION_ZOOM`,e[e.ACTION_OPEN_EXTERNAL_URL=1048592]=`ACTION_OPEN_EXTERNAL_URL`,e[e.ACTION_FUNCTION_REGISTER=1048600]=`ACTION_FUNCTION_REGISTER`,e[e.ACTION_FUNCTION_CALL=1048601]=`ACTION_FUNCTION_CALL`,e[e.ACTION_FUNCTION_RESULT=1048602]=`ACTION_FUNCTION_RESULT`,e[e.ACTION_GENERATE_ANSWER=1048603]=`ACTION_GENERATE_ANSWER`,e[e.ACTION_REGENERATE_ANSWER=1048604]=`ACTION_REGENERATE_ANSWER`,e[e.ACTION_CLEAR_STATE=1048606]=`ACTION_CLEAR_STATE`,e[e.ACTION_CLASSIFICATION_RESULT=1048609]=`ACTION_CLASSIFICATION_RESULT`,e[e.ACTION_AUDIO_STOP=1048610]=`ACTION_AUDIO_STOP`,e[e.ACTION_CALL_TEXT=1048611]=`ACTION_CALL_TEXT`,e[e.ACTION_CANCEL_GENERATION=1048613]=`ACTION_CANCEL_GENERATION`,e[e.ACTION_SPEECH_RECOGNIZED=1048615]=`ACTION_SPEECH_RECOGNIZED`,e[e.ACTION_CALL_RESULT=1048616]=`ACTION_CALL_RESULT`,e[e.ACTION_DOWNLOAD=1048618]=`ACTION_DOWNLOAD`,e[e.ACTION_PLAY_SOUND=1048621]=`ACTION_PLAY_SOUND`,e[e.ACTION_STOP_SOUND=1048623]=`ACTION_STOP_SOUND`,e[e.ACTION_START_RECORDING=1048624]=`ACTION_START_RECORDING`,e[e.ACTION_STOP_RECORDING=1048625]=`ACTION_STOP_RECORDING`,e[e.ACTION_FUNCTION_ENUMERATION_ITEM=1048627]=`ACTION_FUNCTION_ENUMERATION_ITEM`,e[e.ACTION_FUNCTION_ENUMERATION_END=1048628]=`ACTION_FUNCTION_ENUMERATION_END`,e[e.ACTION_FUNCTION_CANCEL=1048629]=`ACTION_FUNCTION_CANCEL`,e[e.ACTION_FUNCTION_DISPOSE=1048630]=`ACTION_FUNCTION_DISPOSE`,e[e.ACTION_FUNCTION_ERROR=1048631]=`ACTION_FUNCTION_ERROR`,e[e.ACTION_FUNCTION_ACK=1048632]=`ACTION_FUNCTION_ACK`,e[e.ACTION_FUNCTION_AWAITING_APPROVAL=1048633]=`ACTION_FUNCTION_AWAITING_APPROVAL`,e[e.ACTION_FUNCTION_APPROVAL_REQUIRED=1048634]=`ACTION_FUNCTION_APPROVAL_REQUIRED`,e[e.ACTION_FUNCTION_APPROVAL_RESPONSE=1048635]=`ACTION_FUNCTION_APPROVAL_RESPONSE`,e[e.UI_UPDATE_ACK=1048636]=`UI_UPDATE_ACK`,e[e.ACTION_CALL2=1048637]=`ACTION_CALL2`,e[e.ACTION_FUNCTION_REGISTER_BATCH=1048638]=`ACTION_FUNCTION_REGISTER_BATCH`,e[e.ACTION_CUSTOM_USER_MESSAGE=1048641]=`ACTION_CUSTOM_USER_MESSAGE`,e[e.ACTION_URL_CHANGED=1048642]=`ACTION_URL_CHANGED`,e[e.ACTION_FILE_UPLOAD_PRE_START2=1048643]=`ACTION_FILE_UPLOAD_PRE_START2`,e[e.ACTION_FILE_UPLOAD_PRE_START_RESPONSE2=1048644]=`ACTION_FILE_UPLOAD_PRE_START_RESPONSE2`,e[e.ACTION_FILE_UPLOAD_START2=1048645]=`ACTION_FILE_UPLOAD_START2`,e[e.ACTION_FILE_UPLOAD_START_RESPONSE2=1048646]=`ACTION_FILE_UPLOAD_START_RESPONSE2`,e[e.ACTION_FILE_UPLOAD_DATA2=1048647]=`ACTION_FILE_UPLOAD_DATA2`,e[e.ACTION_FILE_UPLOAD_ACK2=1048648]=`ACTION_FILE_UPLOAD_ACK2`,e[e.ACTION_FILE_UPLOAD_END2=1048649]=`ACTION_FILE_UPLOAD_END2`,e[e.ACTION_FILE_UPLOAD_COMPLETE2=1048650]=`ACTION_FILE_UPLOAD_COMPLETE2`,e[e.ACTION_FUNCTION_ENUMERATION_ITEM_BATCH=1048651]=`ACTION_FUNCTION_ENUMERATION_ITEM_BATCH`,e[e.ACTION_CALL_ACK=1048652]=`ACTION_CALL_ACK`,e[e.ACTION_TRIGGER_CRON=1048653]=`ACTION_TRIGGER_CRON`,e[e.ACTION_RESULT=1048654]=`ACTION_RESULT`,e[e.UI_RESYNC_REQUEST=1048655]=`UI_RESYNC_REQUEST`,e[e.ACTION_USER_DATA_ERASURE=1048656]=`ACTION_USER_DATA_ERASURE`,e[e.ACTION_FILE_UPLOAD_RESUME2=1048657]=`ACTION_FILE_UPLOAD_RESUME2`,e[e.ACTION_FILE_UPLOAD_RESUME_RESPONSE2=1048658]=`ACTION_FILE_UPLOAD_RESUME_RESPONSE2`,e[e.GROUP_UI=2097152]=`GROUP_UI`,e[e.UI_STREAM_BEGIN=2097153]=`UI_STREAM_BEGIN`,e[e.UI_STREAM_END=2097154]=`UI_STREAM_END`,e[e.UI_STYLES=2097188]=`UI_STYLES`,e[e.UI_UPDATE=2097190]=`UI_UPDATE`,e[e.UI_STYLES_BATCH=2097192]=`UI_STYLES_BATCH`,e[e.UI_STYLES_DELETE=2097193]=`UI_STYLES_DELETE`,e[e.GROUP_COMMON=4128768]=`GROUP_COMMON`,e[e.GROUP_AUDIO=4194304]=`GROUP_AUDIO`,e[e.AUDIO_STREAM_BEGIN=4194305]=`AUDIO_STREAM_BEGIN`,e[e.AUDIO_STREAM_END=4194306]=`AUDIO_STREAM_END`,e[e.AUDIO_FRAME_VOLUME=4194308]=`AUDIO_FRAME_VOLUME`,e[e.AUDIO_FRAME=4194309]=`AUDIO_FRAME`,e[e.AUDIO_SHAPE_FRAME=4194310]=`AUDIO_SHAPE_FRAME`,e[e.AUDIO_PLAYBACK_REPORT=4194311]=`AUDIO_PLAYBACK_REPORT`,e[e.GROUP_VIDEO=8388608]=`GROUP_VIDEO`,e[e.VIDEO_STREAM_BEGIN=8388609]=`VIDEO_STREAM_BEGIN`,e[e.VIDEO_STREAM_END=8388610]=`VIDEO_STREAM_END`,e[e.VIDEO_FRAME=8388611]=`VIDEO_FRAME`,e[e.VIDEO_REQUEST_IDR_FRAME=8388612]=`VIDEO_REQUEST_IDR_FRAME`,e[e.VIDEO_INVALIDATE_FRAME=8388613]=`VIDEO_INVALIDATE_FRAME`,e[e.GROUP_ALL=16711680]=`GROUP_ALL`,e[e.GROUP_APP_LOCAL=1073741824]=`GROUP_APP_LOCAL`,e[e.CONSTANT_GROUP_MASK=2147418112]=`CONSTANT_GROUP_MASK`,e}({});function v(e){let t={};return e&&Object.assign(t,e),t}function ne(e){return new s(1).finish()}function y(e,t,n){return i(131074,ne(e),1,t,n)}var b=class extends Error{cause;constructor(e,t){super(e),this.cause=t,this.name=`ConnectionError`}},x=class extends b{constructor(e,t){super(e,t),this.name=`TransportError`}},S=class extends x{constructor(e){super(`No keepalive received within ${e}ms`),this.name=`KeepaliveTimeoutError`}},C=class extends x{constructor(e,t){super(e,t),this.name=`AuthRejectedError`}},w=class extends b{constructor(e){super(`Maximum reconnection attempts (${e}) exceeded`),this.name=`MaxRetriesExceededError`}},re=class extends b{pinnedTransport;pinnedTier;offeredTypes;constructor(e,t,n){let r=[e&&`?ikon-transport=${e}`,t&&`?ikon-proxy=${t}`].filter(Boolean).join(` and `);super(`No entrypoint matches ${r||`the pinned transport`}; the server offered [${n.join(`, `)}]. Change or remove the pin.`),this.pinnedTransport=e,this.pinnedTier=t,this.offeredTypes=n,this.name=`NoMatchingEndpointTypeError`}};function ie(e,t){return new Promise((n,r)=>{let i=()=>{clearTimeout(a),r(new DOMException(`Aborted`,`AbortError`))},a=setTimeout(()=>{t?.removeEventListener(`abort`,i),n()},e);if(t?.aborted){clearTimeout(a),r(new DOMException(`Aborted`,`AbortError`));return}t?.addEventListener(`abort`,i,{once:!0})})}let ae=1;const oe=new Map;function se(e){ae=e}const ce={0:`DEBUG`,1:`INFO`,2:`WARN`,3:`ERROR`,4:`NONE`};function le(e,t){return`[${e}] ${t}`}function T(e,t,n,r){let i={timestamp:new Date().toISOString(),level:e,levelName:ce[e],component:t,message:n,args:r};for(let[t,n]of oe)if(e>=(n?.minLevel??2))try{t(i)}catch{}if(ae<=e){let i=le(t,n);switch(e){case 0:console.debug(i,...r);break;case 1:console.info(i,...r);break;case 2:console.warn(i,...r);break;case 3:console.error(i,...r)}}}function E(e){return{debug(t,...n){T(0,e,t,n)},info(t,...n){T(1,e,t,n)},warn(t,...n){T(2,e,t,n)},error(t,...n){T(3,e,t,n)}}}function ue(e){if(typeof window>`u`)return null;let t=new URLSearchParams(window.location.search),n=t.get(e);return n===null?t.get(e.replace(/-/g,`_`)):n}function de(e){let t=ue(e);return t===`true`||t!==`false`&&null}function fe(){return de(`ikon-retry`)!==!1}const pe=E(`KeepaliveWatchdog`);var D=class{timeoutMs;what;onTimeout;timeout=null;constructor(e,t,n){this.timeoutMs=e,this.what=t,this.onTimeout=n}reset(){this.clear(),!(this.timeoutMs<=0)&&(this.timeout=setTimeout(()=>{pe.error(`No keepalive received in ${this.timeoutMs}ms, closing ${this.what}`),this.onTimeout(new S(this.timeoutMs))},this.timeoutMs))}clear(){this.timeout&&=(clearTimeout(this.timeout),null)}},O=class{buffer=new Uint8Array(65536);bufferOffset=0;bufferLength=0;dataView=null;dataViewBuffer=null;push(e,t){this.append(e);let n=this.getDataView();for(;this.bufferLength>=4;){let e=n.getUint32(this.bufferOffset,!0);if(e<4)throw this.reset(),Error(`Invalid protocol message length: ${e}`);if(this.bufferLength<e)return;let r=this.buffer.subarray(this.bufferOffset,this.bufferOffset+e);this.bufferOffset+=e,this.bufferLength-=e,t(r)}this.bufferLength===0&&(this.bufferOffset=0)}reset(){this.bufferOffset=0,this.bufferLength=0}append(e){let t=this.bufferLength+e.length,n=this.bufferOffset+this.bufferLength;if(n+e.length>this.buffer.length){if(t>this.buffer.length){let e=Math.max(t,this.buffer.length*2),r=new Uint8Array(e);r.set(this.buffer.subarray(this.bufferOffset,n)),this.buffer=r,this.bufferOffset=0,this.dataViewBuffer=null}else this.buffer.copyWithin(0,this.bufferOffset,n),this.bufferOffset=0}this.buffer.set(e,this.bufferOffset+this.bufferLength),this.bufferLength+=e.length}getDataView(){let e=this.buffer.buffer;return this.dataViewBuffer!==e&&(this.dataViewBuffer=e,this.dataView=new DataView(e)),this.dataView}};const k=E(`HttpStreamTransport`),A=[`binary`,`sse`,`poll`];var j=class{framer=new O;callbacks;sessionId;keepaliveTimeoutMs;connectionTimeoutMs;pinnedMode;preferredMode;baseUri=``;sid=``;mode=`binary`;downstreamAbort=null;keepalive=null;keepaliveResponseMessage=null;isClosed=!1;connected=!1;connecting=!1;sendQueue=[];sendPumpRunning=!1;firstMessageResolver=null;constructor(e){this.callbacks=e.callbacks,this.sessionId=e.sessionId,this.keepaliveTimeoutMs=e.keepaliveTimeoutMs,this.connectionTimeoutMs=e.connectionTimeoutMs??1e4,this.pinnedMode=e.httpStreamMode,this.preferredMode=e.httpStreamPreferredMode}get isConnected(){return this.connected&&!this.isClosed}get activeMode(){return this.mode}async connect(e,t){this.isClosed=!1,this.connecting=!0,this.baseUri=e;let n=Date.now(),r=null,i=this.pinnedMode?[this.pinnedMode]:me(this.preferredMode);for(let e of i){if(this.isClosed)throw new x(`HTTP stream closed while connecting`);try{this.sid=ge(),await this.openMode(t,e),this.mode=e,this.connected=!0,this.connecting=!1,this.resetKeepaliveTimeout(),k.debug(`HTTP stream connected in ${e} mode in ${Date.now()-n}ms`);return}catch(t){if(r=t instanceof Error?t:Error(String(t)),this.abortDownstream(),t instanceof C)throw this.connecting=!1,t;k.debug(`HTTP stream ${e} mode failed after ${Date.now()-n}ms: ${r.message}`)}}throw this.connecting=!1,new x(`HTTP stream failed in every mode: ${r?.message??`unknown error`}`,r??void 0)}send(e){if(this.isClosed){k.warn(`Cannot send: HTTP stream closed`);return}this.sendQueue.push(e),this.runSendPump()}close(){this.isClosed=!0,this.connected=!1,this.clearKeepaliveTimeout(),this.abortDownstream(),this.sendQueue.length=0}async openMode(e,t){let n=new AbortController;this.downstreamAbort=n;let r=Math.min(3500,this.connectionTimeoutMs),i=setTimeout(()=>n.abort(),r);try{await this.openChannel(e,t,n.signal),await this.openDownstream(t,n,r)}finally{clearTimeout(i)}}async openChannel(e,t,n){let r;try{r=await fetch(this.openUrl(t),{method:`POST`,headers:{"Content-Type":`text/plain`},body:_e(e),cache:`no-store`,credentials:`omit`,signal:n})}catch(e){throw n.aborted?new x(`HTTP stream channel did not open before the mode deadline`):e}if(r.status===401||r.status===403)throw new C(`HTTP stream rejected the auth ticket (${r.status})`);if(!r.ok)throw new x(`HTTP stream could not be opened, status ${r.status}`)}async openDownstream(e,t,n){this.framer.reset();let r=new Promise((e,r)=>{let i=()=>{this.firstMessageResolver=null,r(new x(`No server message in ${n}ms`))};t.signal.addEventListener(`abort`,i,{once:!0}),this.firstMessageResolver=()=>{t.signal.removeEventListener(`abort`,i),this.firstMessageResolver=null,e()}}),i=await fetch(this.streamUrl(e),{method:`GET`,headers:{Accept:e===`sse`?`text/event-stream`:`application/octet-stream`},cache:`no-store`,credentials:`omit`,signal:t.signal});if(i.status===401||i.status===403)throw new C(`HTTP stream rejected the auth ticket (${i.status})`);if(!i.ok||!i.body)throw new x(`HTTP stream request failed with status ${i.status}`);this.runDownstreamLoop(e,i,t),await r}async runDownstreamLoop(e,t,n){let r=t;try{for(;r&&!this.isClosed&&!n.signal.aborted;){if(await this.readResponse(e,r),e!==`poll`){this.isClosed||this.handleClose(`HTTP stream ended`,!1);return}if(r=await fetch(this.streamUrl(e),{method:`GET`,headers:{Accept:`application/octet-stream`},cache:`no-store`,credentials:`omit`,signal:n.signal}),r.status===410){this.handleClose(`HTTP stream channel is gone`,!1);return}if(!r.ok||!r.body){this.handleClose(`HTTP stream poll failed with status ${r.status}`,!1);return}}}catch(e){if(n.signal.aborted||this.isClosed)return;k.debug(`HTTP stream read loop ended: ${e instanceof Error?e.message:e}`),this.handleClose(`HTTP stream read failed`,!1)}}async readResponse(e,t){let n=t.body.getReader(),r=e===`sse`?new he:null;for(;;){let{value:e,done:t}=await n.read();if(t)return;if(e){if(r){r.push(e,e=>this.framer.push(e,e=>this.handleProtocolMessage(e)));continue}this.framer.push(e,e=>this.handleProtocolMessage(e))}}}async runSendPump(){if(!this.sendPumpRunning){this.sendPumpRunning=!0;try{for(;this.sendQueue.length>0&&!this.isClosed;){let e=this.takeBatch(),t=await fetch(this.sendUrl(),{method:`POST`,headers:{"Content-Type":`text/plain`},body:e,cache:`no-store`,credentials:`omit`});if(t.status===410){this.handleClose(`HTTP stream channel is gone`,!1);return}if(!t.ok)throw new x(`HTTP stream send failed with status ${t.status}`)}}catch(e){if(this.isClosed)return;k.warn(`HTTP stream send failed: ${e instanceof Error?e.message:e}`),this.handleClose(`HTTP stream send failed`,!1)}finally{this.sendPumpRunning=!1}}}takeBatch(){let e=0,t=0;for(;t<this.sendQueue.length;){let n=this.sendQueue[t].length;if(t>0&&e+n>1048576)break;e+=n,t++}let n=new Uint8Array(e),r=0;for(let e=0;e<t;e++)n.set(this.sendQueue[e],r),r+=this.sendQueue[e].length;return this.sendQueue.splice(0,t),n}streamUrl(e){return`${this.baseUri}${this.baseUri.includes(`?`)?`&`:`?`}sid=${this.sid}&mode=${e}`}openUrl(e){return`${this.streamUrl(e)}&open=1`}sendUrl(){return`${this.baseUri}${this.baseUri.includes(`?`)?`&`:`?`}sid=${this.sid}`}getKeepaliveResponse(){return this.keepaliveResponseMessage||=y(v(),this.sessionId),this.keepaliveResponseMessage}handleProtocolMessage(e){try{let t=r(e).opcode;if(this.firstMessageResolver&&this.firstMessageResolver(),t===_.KEEPALIVE_REQUEST){this.send(this.getKeepaliveResponse()),this.resetKeepaliveTimeout();return}this.resetKeepaliveTimeout(),this.callbacks.onProtocolMessage(e.slice())}catch(e){k.error(`Failed to process protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))}}handleClose(e,t){this.isClosed||this.connecting||(this.isClosed=!0,this.connected=!1,this.clearKeepaliveTimeout(),this.abortDownstream(),this.callbacks.onClose(e,t))}abortDownstream(){this.downstreamAbort&&=(this.downstreamAbort.abort(),null)}resetKeepaliveTimeout(){this.keepalive??=new D(this.keepaliveTimeoutMs,`HTTP stream`,e=>{this.callbacks.onError(e),this.close()}),this.keepalive.reset()}clearKeepaliveTimeout(){this.keepalive?.clear()}};function me(e){return e?[e,...A.filter(t=>t!==e)]:A}var he=class{decoder=new TextDecoder;pending=``;push(e,t){this.pending+=this.decoder.decode(e,{stream:!0});let n=this.pending.indexOf(`
|
|
2
|
+
`);for(;n!==-1;){let e=this.pending.slice(0,n);this.pending=this.pending.slice(n+1),e.startsWith(`data: `)&&t(ve(e.slice(6))),n=this.pending.indexOf(`
|
|
3
|
+
`)}}};function ge(){let e=new Uint8Array(16);crypto.getRandomValues(e);let t=``;for(let n of e)t+=n.toString(16).padStart(2,`0`);return t}function _e(e){let t=``;for(let n of e)t+=String.fromCharCode(n);return btoa(t)}function ve(e){let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n}const M=E(`WebSocketTransport`);var ye=class{ws=null;keepalive=null;isClosed=!1;keepaliveResponseMessage=null;firstMessageResolver=null;keepaliveTimeoutMs;connectionTimeoutMs;callbacks;sessionId;constructor(e){this.callbacks=e.callbacks,this.sessionId=e.sessionId,this.keepaliveTimeoutMs=e.keepaliveTimeoutMs,this.connectionTimeoutMs=e.connectionTimeoutMs??1e4}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}async connect(e,t){this.isClosed=!1;let n=Date.now();return new Promise((r,i)=>{try{this.ws=new WebSocket(e),this.ws.binaryType=`arraybuffer`}catch(e){i(new x(`Failed to create WebSocket: ${e}`,e instanceof Error?e:void 0));return}let a=!1,o=!1,s=()=>{clearTimeout(u),this.ws&&(this.ws.onopen=null,this.ws.onerror=null,this.ws.onclose=null,this.ws.onmessage=null)},c=()=>{o||(o=!0,clearTimeout(u),this.firstMessageResolver=null,M.debug(`WebSocket connected in ${Date.now()-n}ms`),r())},l=e=>{o||(o=!0,this.firstMessageResolver=null,s(),i(e))};this.firstMessageResolver=c;let u=setTimeout(()=>{this.ws?.close(),M.warn(`WebSocket connection timeout after ${this.connectionTimeoutMs}ms`),l(new x(`WebSocket connection timeout`))},this.connectionTimeoutMs);this.ws.onopen=()=>{a=!0,this.ws.send(t),this.resetKeepaliveTimeout()},this.ws.onerror=()=>{M.debug(`WebSocket connection failed after ${Date.now()-n}ms`),l(new x(`WebSocket connection failed`))},this.ws.onclose=e=>{if(this.clearKeepaliveTimeout(),!o){l(a?new C(`WebSocket closed before first server message`):new x(`WebSocket connection closed before opening`));return}if(this.isClosed)return;let t=e.wasClean&&(e.code===1e3||e.code===1001),n=e.reason||`code=${e.code}`;this.callbacks.onClose(n,t)},this.ws.onmessage=e=>{this.handleProtocolMessage(new Uint8Array(e.data))}})}send(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(e):M.warn(`Cannot send: WebSocket not connected`)}close(){this.isClosed=!0,this.clearKeepaliveTimeout(),this.ws&&=(this.ws.close(1e3,`Client closing`),null)}getKeepaliveResponse(){return this.keepaliveResponseMessage||=y(v(),this.sessionId),this.keepaliveResponseMessage}handleProtocolMessage(e){try{let t=r(e).opcode;if(this.firstMessageResolver&&this.firstMessageResolver(),t===_.KEEPALIVE_REQUEST){this.send(this.getKeepaliveResponse()),this.resetKeepaliveTimeout();return}this.resetKeepaliveTimeout(),this.callbacks.onProtocolMessage(e)}catch(e){M.error(`Failed to process protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))}}resetKeepaliveTimeout(){this.keepalive??=new D(this.keepaliveTimeoutMs,`connection`,e=>{this.callbacks.onError(e),this.close()}),this.keepalive.reset()}clearKeepaliveTimeout(){this.keepalive?.clear()}};const N=E(`WebTransportTransport`);function P(){return typeof WebTransport<`u`}var be=class{transport=null;stream=null;reader=null;writer=null;keepalive=null;readLoopActive=!1;isClosed=!1;framer=new O;keepaliveResponseMessage=null;firstMessageResolver=null;firstMessageRejecter=null;keepaliveTimeoutMs;connectionTimeoutMs;callbacks;sessionId;constructor(e){this.callbacks=e.callbacks,this.sessionId=e.sessionId,this.keepaliveTimeoutMs=e.keepaliveTimeoutMs,this.connectionTimeoutMs=e.connectionTimeoutMs??1e4}get isConnected(){return this.transport!==null&&this.writer!==null}async connect(e,t){if(!P())throw new x(`WebTransport is not supported in this browser`);this.isClosed=!1;let n=Date.now(),r=new Promise((e,t)=>{this.firstMessageResolver=e,this.firstMessageRejecter=t});try{this.transport=new WebTransport(e);let i,a=new Promise((e,t)=>{i=setTimeout(()=>t(new x(`WebTransport connection timeout`)),this.connectionTimeoutMs)});try{await Promise.race([this.transport.ready,a])}catch(e){throw e instanceof x&&N.warn(`WebTransport connection timeout after ${this.connectionTimeoutMs}ms`),e}finally{clearTimeout(i)}this.transport.closed.then(()=>{this.handleClose(`Connection closed`,!0)}).catch(e=>{N.error(`WebTransport connection closed with error:`,e),this.handleClose(e instanceof Error?e.message:`Connection error`,!1)}),this.stream=await this.transport.createBidirectionalStream(),this.reader=this.stream.readable.getReader(),this.writer=this.stream.writable.getWriter(),await this.writer.write(t),this.resetKeepaliveTimeout(),this.startReadLoop();let o=Math.max(this.connectionTimeoutMs-(Date.now()-n),1),s,c=new Promise((e,t)=>{s=setTimeout(()=>t(new x(`WebTransport closed before first server message`)),o)});try{await Promise.race([r,c])}finally{clearTimeout(s)}this.firstMessageResolver=null,this.firstMessageRejecter=null,N.info(`WebTransport connected in ${Date.now()-n}ms`)}catch(e){this.firstMessageResolver=null,this.firstMessageRejecter=null,this.isClosed=!0,this.cleanup();let t=Date.now()-n;throw N.warn(`WebTransport connection failed after ${t}ms: ${e}`),new x(`Failed to connect WebTransport: ${e}`,e instanceof Error?e:void 0)}}send(e){if(!this.writer){N.warn(`Cannot send: WebTransport not connected`);return}this.writer.write(e).catch(e=>{N.error(`Failed to send protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))})}close(){this.isClosed=!0,this.clearKeepaliveTimeout(),this.readLoopActive=!1,this.cleanup()}async startReadLoop(){if(this.reader){this.readLoopActive=!0;try{for(;this.readLoopActive&&this.reader;){let{value:e,done:t}=await this.reader.read();if(t)break;e&&this.framer.push(e,e=>this.handleProtocolMessage(e))}this.readLoopActive&&this.handleClose(`Stream ended`,!1)}catch(e){this.readLoopActive&&(N.error(`Read loop error:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e))))}}}getKeepaliveResponse(){return this.keepaliveResponseMessage||=y(v(),this.sessionId),this.keepaliveResponseMessage}handleProtocolMessage(e){try{let t=r(e).opcode;if(this.firstMessageResolver&&this.firstMessageResolver(),t===_.KEEPALIVE_REQUEST){this.send(this.getKeepaliveResponse()),this.resetKeepaliveTimeout();return}this.resetKeepaliveTimeout(),this.callbacks.onProtocolMessage(e)}catch(e){N.error(`Failed to process protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))}}handleClose(e,t){if(!this.isClosed){if(this.isClosed=!0,this.clearKeepaliveTimeout(),this.readLoopActive=!1,this.cleanup(),this.firstMessageRejecter){this.firstMessageRejecter(new C(`WebTransport closed before first server message: ${e}`)),this.firstMessageResolver=null,this.firstMessageRejecter=null;return}this.callbacks.onClose(e,t)}}resetKeepaliveTimeout(){this.keepalive??=new D(this.keepaliveTimeoutMs,`connection`,e=>{this.callbacks.onError(e),this.close()}),this.keepalive.reset()}clearKeepaliveTimeout(){this.keepalive?.clear()}cleanup(){if(this.reader&&=(this.reader.releaseLock(),null),this.writer&&=(this.writer.releaseLock(),null),this.stream=null,this.framer.reset(),this.transport){try{this.transport.close()}catch{}this.transport=null}}};const F=E(`Channel`);var xe=class{state=`disconnected`;transport=null;config;entrypoint;constructor(e){this.config=e,this.entrypoint=e.entrypoint}get channelState(){return this.state}get opcodeGroups(){return this.entrypoint.OpcodeGroupsFromServer}get type(){return this.entrypoint.Type}get isConnected(){return this.transport?.isConnected??!1}get httpStreamMode(){return this.transport instanceof j?this.transport.activeMode:null}async connect(){if(this.state!==`disconnected`)throw Error(`Cannot connect: already in state ${this.state}`);this.setState(`connecting`);try{await this.connectTransport(),this.setState(`connected`)}catch(e){throw this.setState(`disconnected`),e}}disconnect(){this.transport&&=(this.transport.close(),null),this.setState(`disconnected`)}triggerReconnect(e){this.transport&&=(this.transport.close(),null),this.config.onClose?.(e,!1)}checkHealth(){this.state===`connected`&&this.transport&&!this.transport.isConnected&&this.handleClose(`Transport dead after tab resume`,!1)}send(e){if(!this.transport?.isConnected){F.warn(`Cannot send: channel not connected`);return}this.transport.send(e)}async connectTransport(){let e=this.entrypoint,t={sessionId:this.config.sessionId,keepaliveTimeoutMs:this.config.keepaliveTimeoutMs,connectionTimeoutMs:this.config.connectionTimeoutMs,httpStreamMode:this.config.httpStreamMode,httpStreamPreferredMode:this.config.httpStreamPreferredMode,callbacks:{onProtocolMessage:e=>this.handleProtocolMessage(e),onClose:(e,t)=>this.handleClose(e,t),onError:e=>this.handleError(e)}};switch(e.Type){case g.WebSocket:case g.WebSocketProxy:this.transport=new ye(t);break;case g.WebTransport:case g.WebTransportProxy:if(!P())throw Error(`WebTransport is not supported in this browser`);this.transport=new be(t);break;case g.HttpStream:case g.HttpStreamProxy:this.transport=new j(t);break;default:throw Error(`Unsupported entrypoint type: ${g[e.Type]}`)}await this.transport.connect(e.Uri,e.AuthTicket)}handleProtocolMessage(n){try{let r=e(n);if(t(r)===_.CORE_ON_SERVER_STOPPING){F.debug(`Received server stopping message`),this.setState(`stopped`),this.transport?.close();return}this.config.onProtocolMessage?.(r)}catch(e){F.error(`Failed to handle protocol message:`,e),this.config.onError?.(e instanceof Error?e:Error(String(e)))}}handleClose(e,t){this.transport=null,this.config.onClose?.(e,t)}handleError(e){this.config.onError?.(e),e instanceof S&&this.handleClose(`Keepalive timeout`,!1)}setState(e){this.state!==e&&(this.state=e,this.config.onStateChange?.(e))}};const I=E(`ChannelManager`);var Se=class e{channels=new Map;activeType=null;state=`idle`;reconnectAttempts=0;shouldReconnect=!0;entrypoints=[];abortController=null;connectionTimeoutMs;stabilityTimer=null;config;constructor(e){this.config=e}get managerState(){return this.state}get activeHttpStreamMode(){for(let e of this.channels.values()){let t=e.httpStreamMode;if(t)return t}return null}get activeEndpointType(){return this.activeType}async connect(e,t){if(this.state!==`idle`&&this.state!==`offline`)throw Error(`Cannot connect: already in state ${this.state}`);if(this.entrypoints=e,this.shouldReconnect=!0,this.reconnectAttempts=0,this.abortController=new AbortController,t?.retry){this.attemptReconnect();return}await this.connectInternal()}disconnect(){this.shouldReconnect=!1,this.abortController?.abort(),this.abortController=null,this.disconnectAll(),this.setState(`idle`)}sendProtocolMessage(e){let t=n(e);for(let[n,r]of this.channels)if(n&t){r.send(e);return}this.state===`connected`&&I.warn(`No channel found for message`)}sendToAll(e){for(let t of this.channels.values())t.send(e)}checkHealth(){if(this.state===`connected`)for(let e of this.channels.values())e.checkHealth()}triggerReconnect(e){if(this.state===`connected`){I.debug(`Forcing reconnect: ${e}`);for(let t of this.channels.values())t.triggerReconnect(e)}}async connectInternal(t=!1){this.setState(`connecting`);let n=this.entrypoints.filter(t=>t.Type!==g.WebRTC&&!e.isNativeOnlyType(t.Type)),r=this.groupByType(n);if(r.size===0)throw this.setState(`offline`),Error(`No entrypoints available`);let i;if(this.config.orderedEndpointTypes!==void 0){let e=new Set(r.keys());i=this.config.orderedEndpointTypes.filter(t=>e.has(t))}else i=this.config.endpointSelector?this.config.endpointSelector.getOrderedTypes(r):Array.from(r.keys());if(i.length===0)throw this.setState(`offline`),new re(null,null,[...r.keys()].map(e=>g[e]));this.connectionTimeoutMs=i.length>1?5e3:1e4,I.debug(`Endpoint types to try: [${i.map(e=>g[e]).join(`, `)}], transport timeout: ${this.connectionTimeoutMs}ms`);for(let e of i){if(!this.shouldReconnect)return;let t=r.get(e),n=Date.now();I.debug(`Trying ${g[e]} (${t.length} channel(s))`);try{await this.connectAllChannels(t),this.config.endpointSelector?.rememberWorkingType(e),this.config.onRememberWorkingType?.(e),this.activeType=e,I.debug(`Connected via ${g[e]} in ${Date.now()-n}ms`),this.setState(`connected`),this.startStabilityTimer();return}catch(t){I.warn(`Failed to connect using ${g[e]} after ${Date.now()-n}ms: ${t instanceof Error?t.message:t}`);let i=this.channels.size>0;if(this.disconnectAll(),t instanceof C)throw t;if(i&&this.config.onRefreshEntrypoints)try{I.info(`Partial connection detected, refreshing entrypoints`);let e=await this.config.onRefreshEntrypoints();this.entrypoints=e.entrypoints,this.config.sessionId=e.sessionId;let t=e.entrypoints.filter(e=>e.Type!==g.WebRTC),n=this.groupByType(t);for(let[e,t]of n)r.set(e,t)}catch(e){I.warn(`Failed to refresh entrypoints: ${e}`)}}}throw t||this.setState(`offline`),Error(`Failed to connect using any endpoint type`)}async connectAllChannels(e){if(e.length===0)throw Error(`No entrypoints to connect`);let t=(await Promise.allSettled(e.map(e=>this.connectChannel(e)))).filter(e=>e.status===`rejected`);if(t.length>0){let e=t.map(e=>e.reason instanceof Error?e.reason.message:String(e.reason));throw t.some(e=>e.reason instanceof C)?new C(e.join(`, `)):Error(e.join(`, `))}}async connectChannel(e){let t=new xe({entrypoint:e,sessionId:this.config.sessionId,keepaliveTimeoutMs:this.config.keepaliveTimeoutMs,connectionTimeoutMs:this.connectionTimeoutMs,httpStreamMode:this.config.httpStreamMode,httpStreamPreferredMode:this.config.httpStreamPreferredMode,onProtocolMessage:e=>{this.config.onProtocolMessage?.(e)},onStateChange:t=>{this.handleChannelStateChange(e.OpcodeGroupsFromServer,t)},onClose:(t,n)=>{this.handleChannelClose(e.OpcodeGroupsFromServer,t,n)},onError:e=>{this.config.onError?.(e)}});await t.connect(),this.channels.set(e.OpcodeGroupsFromServer,t)}static isNativeOnlyType(e){switch(e){case g.Tcp:case g.TcpTls:case g.TcpProxy:case g.Udp:case g.UdpDtls:case g.Https:return!0;default:return!1}}groupByType(e){let t=new Map;for(let n of e){let e=t.get(n.Type)??[];e.push(n),t.set(n.Type,e)}return t}handleChannelStateChange(e,t){t===`stopped`&&(this.shouldReconnect=!1,this.disconnectAll(),this.setState(`stopped`))}handleChannelClose(e,t,n){this.state!==`idle`&&this.state!==`stopped`&&this.state!==`offline`&&this.channels.has(e)&&this.state===`connected`&&(I.warn(`Channel closed unexpectedly, attempting reconnect`),this.disconnectAll(),this.attemptReconnect())}async attemptReconnect(){if(this.shouldReconnect){if(!fe()){I.warn(`Retry disabled via ikon-retry=false, skipping reconnect`),this.setState(`offline`),this.config.onError?.(new w(0));return}if(this.reconnectAttempts>=this.config.maxReconnectAttempts){I.warn(`Max reconnect attempts (${this.config.maxReconnectAttempts}) reached`),this.setState(`offline`),this.config.onError?.(new w(this.config.maxReconnectAttempts));return}if(this.setState(`reconnecting`),this.reconnectAttempts++,this.reconnectAttempts>1){I.info(`Reconnecting in ${this.config.reconnectBackoffMs}ms (attempt ${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);try{await ie(this.config.reconnectBackoffMs,this.abortController?.signal)}catch{return}}else I.info(`Reconnecting immediately (attempt ${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);if(this.shouldReconnect)try{await this.connectInternal(!0)}catch(e){if(e instanceof C){I.warn(`Auth rejected during reconnect, stopping retries and signaling full re-auth`),this.config.onError?.(e),this.setState(`offline`);return}if(e instanceof re){I.warn(`${e.message} Not retrying`),this.config.onError?.(e),this.setState(`offline`);return}await this.attemptReconnect()}}}disconnectAll(){for(let e of this.channels.values())e.disconnect();this.channels.clear(),this.activeType=null}setState(e){this.state!==e&&(this.state===`connected`&&e!==`connected`&&this.clearStabilityTimer(),this.state=e,this.config.onStateChange?.(e))}startStabilityTimer(){this.clearStabilityTimer(),this.stabilityTimer=setTimeout(()=>{this.stabilityTimer=null,this.state===`connected`&&(this.reconnectAttempts=0)},5e3)}clearStabilityTimer(){this.stabilityTimer&&=(clearTimeout(this.stabilityTimer),null)}};const L=E(`ProtocolWorker`),R=(e,t)=>{self.postMessage(e,t??[])};let z=null,B=null,V=null,H,U=null;const W=[],G=[],K=new Map,q=[],J=[],Y=new Map,X=[];function Z(){try{z?.disconnect()}catch(e){L.warn(`Failed to disconnect channel manager: ${e}`)}z=null;for(let e=0;e<G.length;e++)try{G[e].port.close()}catch{}W.length=0,G.length=0,K.clear();for(let e=0;e<J.length;e++)try{J[e].port.close()}catch{}q.length=0,J.length=0,Y.clear()}function Q(e){let t=e instanceof Error?e:Error(String(e));R({type:`error`,error:{name:t.name,message:t.message,stack:t.stack}})}function Ce(){let e=0;for(let t=0;t<G.length;t++)e|=G[t].opcodeGroupsMask;return e}function we(e){if(H===void 0)return!0;let t=n(e);return(t&H)!==0||(t&Ce())!==0}function $(e){X.length=0;for(let t=0;t<G.length;t++){let n=G[t];(n.opcodeGroupsMask&e)!==0&&X.push(n.port)}return X}function Te(e,t){return(n(e)&t)!==0}function Ee(t,n){if(!z||!n||typeof n!=`object`)return;let r=n;if(!(r.type!==`send`||!(r.message instanceof ArrayBuffer)))try{let n=e(new Uint8Array(r.message));if(!Te(n,t))return;z.sendProtocolMessage(n),U&&U.postMessage({direction:`sent`,message:Array.from(n)})}catch(e){Q(e)}}async function De(e){Z(),z=new Se({sessionId:e.sessionId,keepaliveTimeoutMs:e.keepaliveTimeoutMs,reconnectBackoffMs:e.reconnectBackoffMs,maxReconnectAttempts:e.maxReconnectAttempts,orderedEndpointTypes:e.orderedEndpointTypes,httpStreamMode:e.httpStreamMode,httpStreamPreferredMode:e.httpStreamPreferredMode,webRtcEnabled:e.webRtcEnabled,onStateChange:e=>{R({type:`state`,state:e,activeType:z?.activeEndpointType??void 0,httpStreamMode:z?.activeHttpStreamMode??void 0})},onRememberWorkingType:()=>{R({type:`state`,state:z?.managerState??`idle`,activeType:z?.activeEndpointType??void 0,httpStreamMode:z?.activeHttpStreamMode??void 0})},onError:e=>{Q(e)},onRefreshEntrypoints:()=>new Promise((e,t)=>{B=e,V=t,R({type:`refreshEntrypoints`})}),onProtocolMessage:e=>{U&&U.postMessage({direction:`received`,message:Array.from(e)});let t=n(e),i=we(e),a=$(t);if(!(!i&&a.length===0))try{let t=r(e),n=e.buffer instanceof ArrayBuffer&&e.byteOffset===0&&e.byteLength===e.buffer.byteLength,o=a.length>0;if(o&&!i&&a.length===1&&n){let n=e.buffer;a[0].postMessage({type:`protocol`,message:n,headers:t},[n]);return}if(!o&&i&&n){let n=e.buffer;R({type:`protocol`,message:n,headers:t},[n]);return}if(o&&n){let n=[];for(let t=1;t<a.length;t++)n.push(e.slice().buffer);let r=i?e.slice().buffer:null,o=e.buffer;a[0].postMessage({type:`protocol`,message:o,headers:t},[o]);for(let e=1;e<a.length;e++)a[e].postMessage({type:`protocol`,message:n[e-1],headers:t},[n[e-1]]);r&&R({type:`protocol`,message:r,headers:t},[r]);return}if(o)for(let n of a){let r=e.slice().buffer;n.postMessage({type:`protocol`,message:r,headers:t},[r])}if(i){let n=e.slice().buffer;R({type:`protocol`,message:n,headers:t},[n])}}catch(e){Q(e)}}}),await z.connect(e.entrypoints,{retry:e.retry})}self.addEventListener(`message`,t=>{let i=t.data;if(i.type===`connect`){De(i).catch(e=>{L.error(`Failed to connect: ${e}`),Q(e),Z()});return}if(i.type===`disconnect`){Z(),R({type:`state`,state:`idle`});return}if(i.type===`send`){if(!z)return;try{let t=e(new Uint8Array(i.message));z.sendProtocolMessage(t),U&&U.postMessage({direction:`sent`,message:Array.from(t)})}catch(e){Q(e)}return}if(i.type===`setInterest`){H=i.opcodeGroupsMask;return}if(i.type===`enableDevtools`){i.enabled&&!U?U=new BroadcastChannel(`ikon:devtools`):!i.enabled&&U&&(U.close(),U=null);return}if(i.type===`setLogLevel`){se(i.level);return}if(i.type===`checkHealth`){z?.checkHealth();return}if(i.type===`triggerReconnect`){z?.triggerReconnect(i.reason);return}if(i.type===`refreshedEntrypoints`){B&&(B({entrypoints:i.entrypoints,sessionId:i.sessionId}),B=null,V=null);return}if(i.type===`refreshEntrypointsFailed`){V&&=(V(Error(`Failed to refresh entrypoints`)),B=null,null);return}if(i.type===`forwardToPorts`){try{let t=e(new Uint8Array(i.message)),a=$(n(t));if(a.length>0){let e=r(t);for(let n of a){let r=t.slice().buffer;n.postMessage({type:`protocol`,message:r,headers:e},[r])}}}catch(e){Q(e)}return}if(i.type===`attachPort`){try{i.port.start?.()}catch{}let e=W.length;W.push(i.portId),G.push({port:i.port,opcodeGroupsMask:i.opcodeGroupsMask}),K.set(i.portId,e);return}if(i.type===`detachPort`){let e=K.get(i.portId);if(e!==void 0){let t=G[e];try{t.port.close()}catch{}let n=W.length-1;if(e!==n){let t=W[n];W[e]=t,G[e]=G[n],K.set(t,e)}W.length--,G.length--,K.delete(i.portId)}return}if(i.type===`attachSendPort`){let e=Y.get(i.portId);if(e!==void 0){let t=J[e];try{t.port.close()}catch{}let n=q.length-1;if(e!==n){let t=q[n];q[e]=t,J[e]=J[n],Y.set(t,e)}q.length--,J.length--,Y.delete(i.portId)}let t={port:i.port,opcodeGroupsMask:i.opcodeGroupsMask},n=q.length;q.push(i.portId),J.push(t),Y.set(i.portId,n);try{t.port.start?.()}catch{}t.port.addEventListener(`message`,e=>{Ee(t.opcodeGroupsMask,e.data)});return}if(i.type===`detachSendPort`){let e=Y.get(i.portId);if(e!==void 0){let t=J[e];try{t.port.close()}catch{}let n=q.length-1;if(e!==n){let t=q[n];q[e]=t,J[e]=J[n],Y.set(t,e)}q.length--,J.length--,Y.delete(i.portId)}return}});
|
|
@@ -394,6 +394,9 @@ export interface IkonClientConfig {
|
|
|
394
394
|
*/
|
|
395
395
|
interceptInternalLinks?: boolean;
|
|
396
396
|
}
|
|
397
|
+
/** Where a local dev server listens when nothing says otherwise; the vite template bakes the same pair. */
|
|
398
|
+
export declare const DEFAULT_LOCAL_SERVER_HOST = "localhost";
|
|
399
|
+
export declare const DEFAULT_LOCAL_SERVER_PORT = 8443;
|
|
397
400
|
export declare const DEFAULT_SLOW_CONNECTION_THRESHOLD_MS = 5000;
|
|
398
401
|
export declare const DEFAULT_CONNECTION_TIMEOUT_MS = 180000;
|
|
399
402
|
export declare const PROTOCOL_WORKER_CONNECT_TIMEOUT_MS = 30000;
|
package/client/ikon-client.d.ts
CHANGED
|
@@ -67,39 +67,13 @@ export interface ActionOutcome {
|
|
|
67
67
|
success: boolean;
|
|
68
68
|
errorMessage: string;
|
|
69
69
|
}
|
|
70
|
-
/**
|
|
71
|
-
* IkonClient is the main entry point for connecting to an Ikon server.
|
|
72
|
-
*
|
|
73
|
-
* Features:
|
|
74
|
-
* - Manages connection lifecycle
|
|
75
|
-
* - Provides UI-friendly connection states (waitingForExternalConnectUrl, connecting, connected, reconnecting, offline)
|
|
76
|
-
* - Handles timeouts for connection establishment
|
|
77
|
-
* - Passes protocol messages to application via callback
|
|
78
|
-
* - Multi-channel support (core, audio, video on separate connections)
|
|
79
|
-
* - Smart endpoint selection (WT → WS → WTProxy → WSProxy)
|
|
80
|
-
*
|
|
81
|
-
* Usage:
|
|
82
|
-
* ```typescript
|
|
83
|
-
* const client = new IkonClient({
|
|
84
|
-
* local: { host: 'localhost', httpsPort: 8443 },
|
|
85
|
-
* onProtocolMessage: (message) => {
|
|
86
|
-
* const opcode = getOpcode(message)
|
|
87
|
-
* // Handle protocol messages
|
|
88
|
-
* },
|
|
89
|
-
* onConnectionStateChange: (state) => {
|
|
90
|
-
* // Update UI based on state
|
|
91
|
-
* }
|
|
92
|
-
* })
|
|
93
|
-
*
|
|
94
|
-
* await client.connect()
|
|
95
|
-
* ```
|
|
96
|
-
*/
|
|
97
70
|
export declare class IkonClient {
|
|
98
71
|
private channelManager;
|
|
99
72
|
private protocolWorker;
|
|
100
73
|
private preloadedWorker;
|
|
101
74
|
private workerManagerState;
|
|
102
75
|
private authResponse;
|
|
76
|
+
private _resumedSession;
|
|
103
77
|
private _connectUrl;
|
|
104
78
|
private _brandingRequired;
|
|
105
79
|
private currentState;
|
|
@@ -309,6 +283,12 @@ export declare class IkonClient {
|
|
|
309
283
|
* Returns undefined if not connected.
|
|
310
284
|
*/
|
|
311
285
|
get sessionId(): number | undefined;
|
|
286
|
+
/**
|
|
287
|
+
* True when this client joined a session another connection opened (a `window.__IKON_RESUME__`
|
|
288
|
+
* hand-off) rather than authenticating one of its own. Such a client starts with no UI tree: the stream
|
|
289
|
+
* began before it arrived, so it has to ask the app for a full snapshot.
|
|
290
|
+
*/
|
|
291
|
+
get resumedSession(): boolean;
|
|
312
292
|
/**
|
|
313
293
|
* The Ikon server instance serving this connection. Stable across soft reconnects (cached
|
|
314
294
|
* entrypoints, same instance); changes when a full re-authentication lands on a different
|
|
@@ -562,6 +542,10 @@ export declare class IkonClient {
|
|
|
562
542
|
*/
|
|
563
543
|
private setErrorState;
|
|
564
544
|
private connectProtocol;
|
|
545
|
+
/** Media setup that must follow EVERY successful protocol connect. It used to live only on the
|
|
546
|
+
* worker path's tail, so the two no-Worker fallbacks connected without audio, video or WebRTC —
|
|
547
|
+
* a silent client on exactly the browsers that already lack workers. */
|
|
548
|
+
private finishMediaSetup;
|
|
565
549
|
private ensureVisemeTracker;
|
|
566
550
|
/**
|
|
567
551
|
* Builds and enables the custom (non-WebRTC) playback pipeline. This is the
|
|
@@ -612,6 +596,7 @@ export declare class IkonClient {
|
|
|
612
596
|
private connectProtocolOnMainThread;
|
|
613
597
|
private disconnectProtocol;
|
|
614
598
|
private getServerKeepaliveTimeoutMs;
|
|
599
|
+
private getSoftRetryWindowMs;
|
|
615
600
|
private groupEntrypointsByType;
|
|
616
601
|
/**
|
|
617
602
|
* Tell the developer — and through them, whoever runs the network — that this session is on the
|
|
@@ -677,6 +662,7 @@ export declare class IkonClient {
|
|
|
677
662
|
private requestExternalConnectUrl;
|
|
678
663
|
private attemptReconnectOnVisible;
|
|
679
664
|
private handleBrowserOffline;
|
|
665
|
+
private forceReconnectAfterOffline;
|
|
680
666
|
/**
|
|
681
667
|
* Clear all timers.
|
|
682
668
|
*/
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { IkonClient, type ActionOutcome, type ProtocolMessageHandler, type StateHandler, type ProtocolMessageSubscriptionOptions, type ProtocolMessagePort, type ProtocolSendPort, type WebRTCTrackMapInfo } from './client/ikon-client';
|
|
2
2
|
export { AppMessaging, appMessaging, type AppMessageType, type AppMessageSubscription } from './app-messaging';
|
|
3
3
|
export type { IkonClientConfig, LocalConfig, ApiKeyConfig, SessionTokenConfig, CloudConnectionConfig, CommonConnectionConfig, TimeoutConfig, BackendType, AudioConfig, VideoConfig, MediaSessionConfig, WebRtcConfig } from './client/ikon-client-config';
|
|
4
|
+
export { DEFAULT_LOCAL_SERVER_HOST, DEFAULT_LOCAL_SERVER_PORT, DEFAULT_SLOW_CONNECTION_THRESHOLD_MS } from './client/ikon-client-config';
|
|
4
5
|
export type { ConnectionState } from './client/connection-state';
|
|
5
6
|
export { isConnecting, isConnected, isOffline, isError } from './client/connection-state';
|
|
6
7
|
export { ChannelManager, type ChannelManagerConfig, type ChannelManagerState } from './channel/channel-manager';
|
|
@@ -20,7 +21,7 @@ export { abortSignalTimeout, abortSignalAny } from './utils/abort-signal';
|
|
|
20
21
|
export { createPkceChallenge, takePkceVerifier, restorePkceVerifier, isPkceSupported } from './utils/pkce';
|
|
21
22
|
export { isEmbedded, startEmbeddedOAuthSignIn, adoptPkceVerifierFromUrl, onEmbeddedOAuthResult, type EmbeddedOAuthResult } from './utils/embedded-oauth';
|
|
22
23
|
export { initializeInspectMode, isInspectModeEnabled, enableInspectMode, IKON_INSPECT_MODE_CHANGED_EVENT } from './utils/inspect-mode';
|
|
23
|
-
export { getProxyTierParam, getTransportParam, getConnectParam, getSessionParam, getSameOriginParam, getDebugParam, getDebugOverlayParam, getInspectParam, getLangParam, getAudioParam, getVideoParam, getWebRtcParam, getIceTransportPolicyParam, getRetryParam, getSnapshotParam, getSignedOutParam, setSdkUrlParam, IKON_PARAM_PROXY, IKON_PARAM_TRANSPORT, IKON_PARAM_CONNECT, IKON_PARAM_SESSION, IKON_PARAM_SAME_ORIGIN, IKON_PARAM_DEBUG, IKON_PARAM_DEBUG_OVERLAY, IKON_PARAM_INSPECT, IKON_PARAM_LANG, IKON_PARAM_AUDIO, IKON_PARAM_VIDEO, IKON_PARAM_WEBRTC, IKON_PARAM_ICE_TRANSPORT, IKON_PARAM_RETRY, IKON_PARAM_SNAPSHOT, IKON_PARAM_SIGNED_OUT, IKON_PARAM_OAUTH_TOKEN, IKON_PARAM_OAUTH_CODE, IKON_PARAM_OAUTH_PROVIDER, IKON_PARAM_OAUTH_PKCE, type TransportFamily, type PinnedTransport, } from './utils/query-params';
|
|
24
|
+
export { getProxyTierParam, getTransportParam, getConnectParam, getResumeHandoff, getSessionParam, getSameOriginParam, getDebugParam, getDebugOverlayParam, getInspectParam, getLangParam, getAudioParam, getVideoParam, getWebRtcParam, getIceTransportPolicyParam, getRetryParam, getSnapshotParam, getSignedOutParam, setSdkUrlParam, IKON_PARAM_PROXY, IKON_PARAM_TRANSPORT, IKON_PARAM_CONNECT, IKON_PARAM_SESSION, IKON_PARAM_SAME_ORIGIN, IKON_PARAM_DEBUG, IKON_PARAM_DEBUG_OVERLAY, IKON_PARAM_INSPECT, IKON_PARAM_LANG, IKON_PARAM_AUDIO, IKON_PARAM_VIDEO, IKON_PARAM_WEBRTC, IKON_PARAM_ICE_TRANSPORT, IKON_PARAM_RETRY, IKON_PARAM_SNAPSHOT, IKON_PARAM_SIGNED_OUT, IKON_PARAM_OAUTH_TOKEN, IKON_PARAM_OAUTH_CODE, IKON_PARAM_OAUTH_PROVIDER, IKON_PARAM_OAUTH_PKCE, type TransportFamily, type PinnedTransport, } from './utils/query-params';
|
|
24
25
|
export type { HttpStreamMode } from './transport/transport';
|
|
25
26
|
export { getOpcodeName } from './utils/opcode-names';
|
|
26
27
|
export { initializeLogSink, setSendLogsCallback, getBufferedLogs, takeBufferedLogs, flushLogs, clearLogBuffer, getLogBufferSize } from './utils/log-sink';
|
|
@@ -34,7 +35,7 @@ export { loginErrorInterceptor, reprovisionAfterLogin, consumeLoginHandoff, getL
|
|
|
34
35
|
export type { LoginPromptState, LoginPendingCall } from './login';
|
|
35
36
|
export { IKON_AUTH_BASE_URL, IKON_AUTH_URL_PROD, IKON_AUTH_URL_DEV, IKON_BACKEND_URL_PROD, IKON_BACKEND_URL_DEV, deriveAuthUrl, deriveCrossOriginAuthUrl, getSameOriginAuthUrl, deriveBackendUrl, deriveBackendType, parseUrlParams, isCloudEnvironment, getUrlWithoutSession, type UrlParams } from './connection/urls';
|
|
36
37
|
export { getOrCreateDeviceId, clearDeviceId, extractUserIdFromToken } from './storage';
|
|
37
|
-
export { IkonMedia, IkonAudioPlayback, IkonVideoPlayback, VisemeTracker, isSharedArrayBufferSupported, isAudioWorkletSupported, IkonMediaCapture, IkonVideoCapture, IkonAudioCapture, IkonImageCapture, isMobileBrowserLikely } from './media';
|
|
38
|
-
export type { IkonMediaConfig, IkonAudioPlaybackConfig, IkonVideoPlaybackConfig, IkonVideoCaptureHandle, IkonVideoCaptureRequest, IkonVideoCaptureOptions, VideoCaptureSource, IkonAudioCaptureHandle, IkonAudioCaptureRequest, IkonAudioCaptureOptions, IkonImageCaptureRequest, IkonImageCaptureResult, IkonNativeCameraCaptureRequest, IkonNativeCameraFacing } from './media';
|
|
38
|
+
export { IkonMedia, IkonAudioPlayback, IkonVideoPlayback, VisemeTracker, isSharedArrayBufferSupported, isAudioWorkletSupported, IkonMediaCapture, IkonVideoCapture, IkonAudioCapture, IkonImageCapture, isMobileBrowserLikely, queryMediaPermission, requestMediaPermission, watchMediaPermission } from './media';
|
|
39
|
+
export type { IkonMediaConfig, IkonAudioPlaybackConfig, IkonVideoPlaybackConfig, IkonVideoCaptureHandle, IkonVideoCaptureRequest, IkonVideoCaptureOptions, VideoCaptureSource, IkonAudioCaptureHandle, IkonAudioCaptureRequest, IkonAudioCaptureOptions, IkonImageCaptureRequest, IkonImageCaptureResult, IkonNativeCameraCaptureRequest, IkonNativeCameraFacing, MediaPermissionState, MediaPermissionKind } from './media';
|
|
39
40
|
export { WebRTCConnection, WebRTCSignaling, WEBRTC_AUDIO_CODEC, WEBRTC_AUDIO_SAMPLE_RATE, WEBRTC_AUDIO_CHANNELS, WEBRTC_AUDIO_BITRATE, WEBRTC_AUDIO_JITTER_BUFFER_TARGET_MS, WEBRTC_VIDEO_CODEC, WEBRTC_VIDEO_MAX_BITRATE, WEBRTC_VIDEO_MAX_FRAMERATE, WEBRTC_BUNDLE_POLICY, WEBRTC_RTCP_MUX_POLICY, WEBRTC_DATA_CHANNEL_LABEL, WEBRTC_DATA_CHANNEL_ORDERED, WEBRTC_DATA_CHANNEL_MAX_RETRANSMITS, WEBRTC_MAX_AUDIO_TRACKS, WEBRTC_MAX_VIDEO_TRACKS } from './webrtc';
|
|
40
41
|
export type { WebRTCConnectionConfig, WebRTCConnectionState, WebRTCSignalingConfig } from './webrtc';
|