@livekit/rtc-node 0.13.29 → 0.13.31
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/audio_source.cjs +38 -19
- package/dist/audio_source.cjs.map +1 -1
- package/dist/audio_source.d.cts +12 -4
- package/dist/audio_source.d.ts +12 -4
- package/dist/audio_source.d.ts.map +1 -1
- package/dist/audio_source.js +38 -19
- package/dist/audio_source.js.map +1 -1
- package/dist/audio_stream-B4hGVcKz.d.cts +498 -0
- package/dist/audio_stream-DEG1JKge.d.ts +498 -0
- package/dist/audio_stream.cjs +21 -6
- package/dist/audio_stream.cjs.map +1 -1
- package/dist/audio_stream.d.cts +12 -22
- package/dist/audio_stream.d.ts +12 -22
- package/dist/audio_stream.d.ts.map +1 -1
- package/dist/audio_stream.js +19 -5
- package/dist/audio_stream.js.map +1 -1
- package/dist/data_streams/index.d.cts +1 -1
- package/dist/data_streams/index.d.ts +1 -1
- package/dist/data_streams/stream_reader.d.cts +1 -1
- package/dist/data_streams/stream_reader.d.ts +1 -1
- package/dist/data_streams/stream_writer.d.cts +1 -1
- package/dist/data_streams/stream_writer.d.ts +1 -1
- package/dist/data_streams/types.d.cts +1 -1
- package/dist/data_streams/types.d.ts +1 -1
- package/dist/frame_processor.cjs +6 -0
- package/dist/frame_processor.cjs.map +1 -1
- package/dist/frame_processor.d.cts +2 -0
- package/dist/frame_processor.d.ts +2 -0
- package/dist/frame_processor.d.ts.map +1 -1
- package/dist/frame_processor.js +6 -0
- package/dist/frame_processor.js.map +1 -1
- package/dist/index.d.cts +4 -7
- package/dist/index.d.ts +4 -7
- package/dist/participant.cjs +6 -0
- package/dist/participant.cjs.map +1 -1
- package/dist/participant.d.cts +14 -153
- package/dist/participant.d.ts +14 -153
- package/dist/participant.d.ts.map +1 -1
- package/dist/participant.js +6 -0
- package/dist/participant.js.map +1 -1
- package/dist/room.cjs +28 -0
- package/dist/room.cjs.map +1 -1
- package/dist/room.d.cts +12 -221
- package/dist/room.d.ts +12 -221
- package/dist/room.d.ts.map +1 -1
- package/dist/room.js +28 -0
- package/dist/room.js.map +1 -1
- package/dist/track.cjs +123 -0
- package/dist/track.cjs.map +1 -1
- package/dist/track.d.cts +15 -42
- package/dist/track.d.ts +15 -42
- package/dist/track.d.ts.map +1 -1
- package/dist/track.js +123 -0
- package/dist/track.js.map +1 -1
- package/dist/track_publication.d.cts +14 -47
- package/dist/track_publication.d.ts +14 -47
- package/dist/{stream_reader-CuG4b8Y-.d.cts → types-_PdPVish.d.cts} +40 -40
- package/dist/{stream_reader-CuG4b8Y-.d.ts → types-_PdPVish.d.ts} +40 -40
- package/dist/version.cjs +1 -1
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/video_stream.d.cts +12 -2
- package/dist/video_stream.d.ts +12 -2
- package/package.json +3 -3
- package/src/audio_source.test.ts +92 -0
- package/src/audio_source.ts +42 -18
- package/src/audio_stream.ts +28 -4
- package/src/audio_stream_room_lifecycle.test.ts +753 -0
- package/src/bun_runtime.test.ts +27 -0
- package/src/frame_processor.ts +4 -0
- package/src/participant.ts +17 -0
- package/src/room.ts +44 -0
- package/src/track.ts +141 -0
- package/src/version.ts +1 -1
package/dist/participant.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/participant.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport {\n DisconnectReason,\n type OwnedParticipant,\n type ParticipantInfo,\n ParticipantKind,\n type ParticipantKindDetail,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n ChatMessage as ChatMessageModel,\n DataStream_ByteHeader,\n DataStream_Chunk,\n DataStream_Header,\n DataStream_OperationType,\n DataStream_TextHeader,\n DataStream_Trailer,\n EditChatMessageRequest,\n TranscriptionSegment as ProtoTranscriptionSegment,\n type PublishDataCallback,\n PublishDataRequest,\n type PublishDataResponse,\n type PublishSipDtmfCallback,\n PublishSipDtmfRequest,\n type PublishSipDtmfResponse,\n type PublishTrackCallback,\n PublishTrackRequest,\n type PublishTrackResponse,\n type PublishTranscriptionCallback,\n PublishTranscriptionRequest,\n type PublishTranscriptionResponse,\n type SendChatMessageCallback,\n SendChatMessageRequest,\n type SendChatMessageResponse,\n type SendStreamChunkCallback,\n SendStreamChunkRequest,\n type SendStreamChunkResponse,\n type SendStreamHeaderCallback,\n SendStreamHeaderRequest,\n type SendStreamHeaderResponse,\n type SendStreamTrailerCallback,\n SendStreamTrailerRequest,\n type SendStreamTrailerResponse,\n type SetLocalAttributesCallback,\n SetLocalAttributesRequest,\n type SetLocalAttributesResponse,\n type SetLocalMetadataCallback,\n SetLocalMetadataRequest,\n type SetLocalMetadataResponse,\n type SetLocalNameCallback,\n SetLocalNameRequest,\n type SetLocalNameResponse,\n type TrackPublishOptions,\n type UnpublishTrackCallback,\n UnpublishTrackRequest,\n type UnpublishTrackResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport type {\n PerformRpcCallback,\n PerformRpcResponse,\n RegisterRpcMethodResponse,\n RpcMethodInvocationResponseResponse,\n UnregisterRpcMethodResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n PerformRpcRequest,\n RegisterRpcMethodRequest,\n RpcMethodInvocationResponseRequest,\n UnregisterRpcMethodRequest,\n} from '@livekit/rtc-ffi-bindings';\nimport type { PathLike } from 'node:fs';\nimport { open, stat } from 'node:fs/promises';\nimport {\n type ByteStreamInfo,\n type ByteStreamOptions,\n ByteStreamWriter,\n type TextStreamInfo,\n TextStreamWriter,\n} from './data_streams/index.js';\nimport { FfiClient, FfiHandle } from './ffi_client.js';\nimport { log } from './log.js';\nimport { type PerformRpcParams, RpcError, type RpcInvocationData } from './rpc.js';\nimport type { LocalTrack } from './track.js';\nimport type { RemoteTrackPublication, TrackPublication } from './track_publication.js';\nimport { LocalTrackPublication } from './track_publication.js';\nimport type { Transcription } from './transcription.js';\nimport type { ChatMessage } from './types.js';\nimport { numberToBigInt, splitUtf8 } from './utils.js';\n\nconst STREAM_CHUNK_SIZE = 15_000;\n\nexport abstract class Participant {\n /** @internal */\n info: ParticipantInfo;\n\n /** @internal */\n ffi_handle: FfiHandle;\n\n trackPublications = new Map<string, TrackPublication>();\n\n constructor(owned_info: OwnedParticipant) {\n this.info = owned_info!.info!;\n this.ffi_handle = new FfiHandle(owned_info.handle!.id!);\n }\n\n get sid(): string | undefined {\n return this.info.sid;\n }\n\n get name(): string | undefined {\n return this.info.name;\n }\n\n get identity(): string {\n return this.info.identity ?? '';\n }\n\n get metadata(): string {\n return this.info.metadata ?? '';\n }\n\n get attributes(): Record<string, string> {\n return this.info.attributes ?? {};\n }\n\n get kind(): ParticipantKind {\n return this.info.kind ?? ParticipantKind.STANDARD;\n }\n\n get kindDetails(): ParticipantKindDetail[] {\n return this.info.kindDetails ?? [];\n }\n\n get disconnectReason(): DisconnectReason | undefined {\n if (this.info.disconnectReason === DisconnectReason.UNKNOWN_REASON) {\n return undefined;\n }\n return this.info.disconnectReason;\n }\n}\n\nexport type DataPublishOptions = {\n /**\n * whether to send this as reliable or lossy.\n * For data that you need delivery guarantee (such as chat messages), use Reliable.\n * For data that should arrive as quickly as possible, but you are ok with dropped\n * packets, use Lossy.\n */\n reliable?: boolean;\n /**\n * the identities of participants who will receive the message, will be sent to every one if empty\n */\n destination_identities?: string[];\n /** the topic under which the message gets published */\n topic?: string;\n};\n\nexport class LocalParticipant extends Participant {\n private rpcHandlers: Map<string, (data: RpcInvocationData) => Promise<string>> = new Map();\n\n private ffiEventLock: Mutex;\n\n // Signal that fires when the owning Room disconnects, used to cancel\n // pending FfiClient.waitFor() listeners so they don't leak.\n private disconnectSignal: AbortSignal;\n\n trackPublications: Map<string, LocalTrackPublication> = new Map();\n\n constructor(info: OwnedParticipant, ffiEventLock: Mutex, disconnectSignal: AbortSignal) {\n super(info);\n this.ffiEventLock = ffiEventLock;\n this.disconnectSignal = disconnectSignal;\n }\n\n async publishData(data: Uint8Array, options: DataPublishOptions) {\n const req = new PublishDataRequest({\n localParticipantHandle: this.ffi_handle.handle,\n dataPtr: FfiClient.instance.retrievePtr(data),\n dataLen: BigInt(data.byteLength),\n reliable: options.reliable,\n topic: options.topic,\n destinationIdentities: options.destination_identities,\n });\n\n const res = FfiClient.instance.request<PublishDataResponse>({\n message: { case: 'publishData', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PublishDataCallback>(\n (ev) => ev.message.case == 'publishData' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async publishDtmf(code: number, digit: string) {\n const req = new PublishSipDtmfRequest({\n localParticipantHandle: this.ffi_handle.handle,\n code,\n digit,\n });\n\n const res = FfiClient.instance.request<PublishSipDtmfResponse>({\n message: { case: 'publishSipDtmf', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PublishSipDtmfCallback>(\n (ev) => ev.message.case == 'publishSipDtmf' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async publishTranscription(transcription: Transcription) {\n const req = new PublishTranscriptionRequest({\n localParticipantHandle: this.ffi_handle.handle,\n participantIdentity: transcription.participantIdentity,\n segments: transcription.segments.map(\n (s) =>\n new ProtoTranscriptionSegment({\n id: s.id,\n text: s.text,\n startTime: s.startTime,\n endTime: s.endTime,\n final: s.final,\n language: s.language,\n }),\n ),\n trackId: transcription.trackSid,\n });\n\n const res = FfiClient.instance.request<PublishTranscriptionResponse>({\n message: { case: 'publishTranscription', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PublishTranscriptionCallback>(\n (ev) => ev.message.case == 'publishTranscription' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async updateMetadata(metadata: string) {\n const req = new SetLocalMetadataRequest({\n localParticipantHandle: this.ffi_handle.handle,\n metadata: metadata,\n });\n\n const res = FfiClient.instance.request<SetLocalMetadataResponse>({\n message: { case: 'setLocalMetadata', value: req },\n });\n\n await FfiClient.instance.waitFor<SetLocalMetadataCallback>(\n (ev) => ev.message.case == 'setLocalMetadata' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n }\n\n /**\n * Returns a `StreamWriter` instance that allows to write individual chunks of text to a stream.\n * Well suited for TTS and/or streaming LLM output. If you want to simply send a text then use sendText() instead\n */\n async streamText(options?: {\n topic?: string;\n attributes?: Record<string, string>;\n destinationIdentities?: Array<string>;\n streamId?: string;\n senderIdentity?: string;\n }): Promise<TextStreamWriter> {\n const senderIdentity = options?.senderIdentity ?? this.identity;\n const streamId = options?.streamId ?? crypto.randomUUID();\n const destinationIdentities = options?.destinationIdentities;\n\n const info: TextStreamInfo = {\n streamId: streamId,\n mimeType: 'text/plain',\n topic: options?.topic ?? '',\n timestamp: Date.now(),\n };\n\n const headerReq = new SendStreamHeaderRequest({\n senderIdentity,\n destinationIdentities,\n localParticipantHandle: this.ffi_handle.handle,\n header: new DataStream_Header({\n streamId,\n mimeType: info.mimeType,\n topic: info.topic,\n timestamp: numberToBigInt(info.timestamp),\n attributes: options?.attributes,\n contentHeader: {\n case: 'textHeader',\n value: new DataStream_TextHeader({\n operationType: DataStream_OperationType.CREATE,\n version: 0,\n replyToStreamId: '',\n generated: false,\n }),\n },\n }),\n });\n\n await this.sendStreamHeader(headerReq);\n\n let nextChunkId = 0;\n const localHandle = this.ffi_handle.handle;\n const sendTrailer = this.sendStreamTrailer;\n const sendChunk = this.sendStreamChunk;\n\n const writableStream = new WritableStream<string>({\n // Implement the sink\n async write(text) {\n for (const textByteChunk of splitUtf8(text, STREAM_CHUNK_SIZE)) {\n const chunkRequest = new SendStreamChunkRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n chunk: new DataStream_Chunk({\n content: textByteChunk,\n streamId,\n chunkIndex: numberToBigInt(nextChunkId),\n }),\n });\n\n await sendChunk(chunkRequest);\n nextChunkId += 1;\n }\n },\n async close() {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: '',\n }),\n });\n await sendTrailer(trailerReq);\n },\n // Send a trailer with the error reason so the remote side's stream\n // controller is closed instead of waiting for data that won't arrive.\n async abort(err) {\n log.error(err, 'Sink Error');\n try {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: err instanceof Error ? err.message : String(err ?? ''),\n }),\n });\n await sendTrailer(trailerReq);\n } catch {\n // Best-effort: the connection may already be gone.\n }\n },\n });\n\n const writer = new TextStreamWriter(writableStream, info);\n\n return writer;\n }\n\n async sendText(\n text: string,\n options?: {\n topic?: string;\n attributes?: Record<string, string>;\n destinationIdentities?: Array<string>;\n streamId?: string;\n },\n ) {\n const writer = await this.streamText(options);\n await writer.write(text);\n await writer.close();\n return writer.info;\n }\n\n async streamBytes(options?: {\n name?: string;\n topic?: string;\n attributes?: Record<string, string>;\n destinationIdentities?: Array<string>;\n streamId?: string;\n mimeType?: string;\n totalSize?: number;\n }) {\n const senderIdentity = this.identity;\n const streamId = options?.streamId ?? crypto.randomUUID();\n const destinationIdentities = options?.destinationIdentities;\n\n const info: ByteStreamInfo = {\n streamId: streamId,\n mimeType: options?.mimeType ?? 'application/octet-stream',\n topic: options?.topic ?? '',\n timestamp: Date.now(),\n attributes: options?.attributes,\n totalSize: options?.totalSize,\n name: options?.name ?? 'unknown',\n };\n\n const headerReq = new SendStreamHeaderRequest({\n senderIdentity,\n destinationIdentities,\n localParticipantHandle: this.ffi_handle.handle,\n header: new DataStream_Header({\n streamId,\n mimeType: info.mimeType,\n topic: info.topic,\n timestamp: numberToBigInt(info.timestamp),\n attributes: info.attributes,\n totalLength: numberToBigInt(info.totalSize),\n contentHeader: {\n case: 'byteHeader',\n value: new DataStream_ByteHeader({\n name: info.name,\n }),\n },\n }),\n });\n\n await this.sendStreamHeader(headerReq);\n\n let chunkId = 0;\n const localHandle = this.ffi_handle.handle;\n const sendTrailer = this.sendStreamTrailer;\n const sendChunk = this.sendStreamChunk;\n const writeMutex = new Mutex();\n\n const writableStream = new WritableStream<Uint8Array>({\n async write(chunk) {\n const unlock = await writeMutex.lock();\n\n let byteOffset = 0;\n try {\n while (byteOffset < chunk.byteLength) {\n const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);\n const chunkRequest = new SendStreamChunkRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n chunk: new DataStream_Chunk({\n content: subChunk,\n streamId,\n chunkIndex: numberToBigInt(chunkId),\n }),\n });\n\n await sendChunk(chunkRequest);\n chunkId += 1;\n byteOffset += subChunk.byteLength;\n }\n } finally {\n unlock();\n }\n },\n async close() {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: '',\n }),\n });\n await sendTrailer(trailerReq);\n },\n // Send a trailer with the error reason so the remote side's stream\n // controller is closed instead of waiting for data that won't arrive.\n async abort(err) {\n log.error(err, 'Sink error');\n try {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: err instanceof Error ? err.message : String(err ?? ''),\n }),\n });\n await sendTrailer(trailerReq);\n } catch {\n // Best-effort: the connection may already be gone.\n }\n },\n });\n\n const byteWriter = new ByteStreamWriter(writableStream, info);\n\n return byteWriter;\n }\n\n /** Sends a file provided as PathLike to specified recipients */\n async sendFile(path: PathLike, options?: ByteStreamOptions) {\n const fileStats = await stat(path);\n const file = await open(path);\n try {\n const stream: ReadableStream<Uint8Array> = file.readableWebStream();\n const streamId = crypto.randomUUID();\n const destinationIdentities = options?.destinationIdentities;\n\n const writer = await this.streamBytes({\n streamId: streamId,\n name: options?.name,\n totalSize: fileStats.size,\n destinationIdentities,\n topic: options?.topic,\n mimeType: options?.mimeType,\n attributes: options?.attributes,\n });\n\n for await (const chunk of stream) {\n await writer.write(chunk);\n }\n await writer.close();\n } finally {\n await file.close();\n }\n }\n\n private async sendStreamHeader(req: SendStreamHeaderRequest) {\n const type = 'sendStreamHeader';\n const res = FfiClient.instance.request<SendStreamHeaderResponse>({\n message: { case: type, value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendStreamHeaderCallback>(\n (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n private sendStreamChunk = async (req: SendStreamChunkRequest) => {\n const type = 'sendStreamChunk';\n const res = FfiClient.instance.request<SendStreamChunkResponse>({\n message: { case: type, value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendStreamChunkCallback>(\n (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n };\n\n private sendStreamTrailer = async (req: SendStreamTrailerRequest) => {\n const type = 'sendStreamTrailer';\n const res = FfiClient.instance.request<SendStreamTrailerResponse>({\n message: { case: type, value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendStreamTrailerCallback>(\n (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n };\n\n /**\n * Sends a chat message to participants in the room\n *\n * @param text - The text content of the chat message.\n * @param destinationIdentities - An optional array of recipient identities to whom the message will be sent. If omitted, the message is broadcast to all participants.\n * @param senderIdentity - An optional identity of the sender. If omitted, the default sender identity is used.\n *\n */\n async sendChatMessage(\n text: string,\n destinationIdentities?: Array<string>,\n senderIdentity?: string,\n ): Promise<ChatMessage> {\n const req = new SendChatMessageRequest({\n localParticipantHandle: this.ffi_handle.handle,\n message: text,\n destinationIdentities,\n senderIdentity,\n });\n\n const res = FfiClient.instance.request<SendChatMessageResponse>({\n message: { case: 'sendChatMessage', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendChatMessageCallback>(\n (ev) => ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n switch (cb.message.case) {\n case 'chatMessage':\n const { id, timestamp, editTimestamp, message } = cb.message.value!;\n return {\n id: id!,\n timestamp: Number(timestamp),\n editTimestamp: Number(editTimestamp),\n message: message!,\n };\n case 'error':\n default:\n throw new Error(cb.message.value);\n }\n }\n\n /**\n * @experimental\n */\n async editChatMessage(\n editText: string,\n originalMessage: ChatMessage,\n destinationIdentities?: Array<string>,\n senderIdentity?: string,\n ): Promise<ChatMessage> {\n const req = new EditChatMessageRequest({\n localParticipantHandle: this.ffi_handle.handle,\n editText,\n originalMessage: new ChatMessageModel({\n ...originalMessage,\n timestamp: BigInt(originalMessage.timestamp),\n editTimestamp: originalMessage.editTimestamp\n ? BigInt(originalMessage.editTimestamp)\n : undefined,\n }),\n destinationIdentities,\n senderIdentity,\n });\n\n const res = FfiClient.instance.request<SendChatMessageResponse>({\n message: { case: 'editChatMessage', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendChatMessageCallback>(\n (ev) => ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n switch (cb.message.case) {\n case 'chatMessage':\n const { id, timestamp, editTimestamp, message } = cb.message.value!;\n return {\n id: id!,\n timestamp: Number(timestamp),\n editTimestamp: Number(editTimestamp),\n message: message!,\n };\n case 'error':\n default:\n throw new Error(cb.message.value);\n }\n }\n\n async updateName(name: string) {\n const req = new SetLocalNameRequest({\n localParticipantHandle: this.ffi_handle.handle,\n name: name,\n });\n\n const res = FfiClient.instance.request<SetLocalNameResponse>({\n message: { case: 'setLocalName', value: req },\n });\n\n await FfiClient.instance.waitFor<SetLocalNameCallback>(\n (ev) => ev.message.case == 'setLocalName' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n }\n\n async setAttributes(attributes: Record<string, string>) {\n const req = new SetLocalAttributesRequest({\n localParticipantHandle: this.ffi_handle.handle,\n attributes: Object.entries(attributes).map(([key, value]) => ({ key, value })),\n });\n\n const res = FfiClient.instance.request<SetLocalAttributesResponse>({\n message: { case: 'setLocalAttributes', value: req },\n });\n\n await FfiClient.instance.waitFor<SetLocalAttributesCallback>(\n (ev) => ev.message.case == 'setLocalAttributes' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n }\n\n async publishTrack(\n track: LocalTrack,\n options: TrackPublishOptions,\n ): Promise<LocalTrackPublication> {\n const req = new PublishTrackRequest({\n localParticipantHandle: this.ffi_handle.handle,\n trackHandle: track.ffi_handle.handle,\n options: options,\n });\n\n const unlock = await this.ffiEventLock.lock();\n\n const res = FfiClient.instance.request<PublishTrackResponse>({\n message: { case: 'publishTrack', value: req },\n });\n\n try {\n const cb = await FfiClient.instance.waitFor<PublishTrackCallback>(\n (ev) => ev.message.case == 'publishTrack' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n switch (cb.message.case) {\n case 'publication':\n const track_publication = new LocalTrackPublication(cb.message.value!);\n track_publication.track = track;\n this.trackPublications.set(track_publication.sid!, track_publication);\n\n return track_publication;\n case 'error':\n default:\n throw new Error(cb.message.value);\n }\n } finally {\n unlock();\n }\n }\n\n async unpublishTrack(trackSid: string, stopOnUnpublish?: boolean) {\n const unlock = await this.ffiEventLock.lock();\n try {\n const req = new UnpublishTrackRequest({\n localParticipantHandle: this.ffi_handle.handle,\n trackSid: trackSid,\n stopOnUnpublish: stopOnUnpublish ?? true,\n });\n\n const res = FfiClient.instance.request<UnpublishTrackResponse>({\n message: { case: 'unpublishTrack', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<UnpublishTrackCallback>(\n (ev) => ev.message.case == 'unpublishTrack' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n\n const pub = this.trackPublications.get(trackSid);\n if (pub) {\n pub.track = undefined;\n }\n this.trackPublications.delete(trackSid);\n } finally {\n unlock();\n }\n }\n\n /**\n * Initiate an RPC call to a remote participant.\n * @param params - Parameters for initiating the RPC call, see {@link PerformRpcParams}\n * @returns A promise that resolves with the response payload or rejects with an error.\n * @throws Error on failure. Details in `message`.\n */\n async performRpc({\n destinationIdentity,\n method,\n payload,\n responseTimeout,\n }: PerformRpcParams): Promise<string> {\n const req = new PerformRpcRequest({\n localParticipantHandle: this.ffi_handle.handle,\n destinationIdentity,\n method,\n payload,\n responseTimeoutMs: responseTimeout,\n });\n\n const res = FfiClient.instance.request<PerformRpcResponse>({\n message: { case: 'performRpc', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PerformRpcCallback>(\n (ev) => ev.message.case === 'performRpc' && ev.message.value.asyncId === res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw RpcError.fromProto(cb.error);\n }\n\n return cb.payload!;\n }\n\n /**\n * Establishes the participant as a receiver for calls of the specified RPC method.\n * Will overwrite any existing callback for the same method.\n *\n * @param method - The name of the indicated RPC method\n * @param handler - Will be invoked when an RPC request for this method is received\n * @returns A promise that resolves when the method is successfully registered\n *\n * @example\n * ```typescript\n * room.localParticipant?.registerRpcMethod(\n * 'greet',\n * async (data: RpcInvocationData) => {\n * console.log(`Received greeting from ${data.callerIdentity}: ${data.payload}`);\n * return `Hello, ${data.callerIdentity}!`;\n * }\n * );\n * ```\n *\n * See {@link RpcInvocationData} for more details on invocation params.\n *\n * The handler should return a Promise that resolves to a string.\n * If unable to respond within `responseTimeout`, the request will result in an error on the caller's side.\n *\n * You may throw errors of type `RpcError` with a string `message` in the handler,\n * and they will be received on the caller's side with the message intact.\n * Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` (\"Application Error\").\n */\n registerRpcMethod(method: string, handler: (data: RpcInvocationData) => Promise<string>) {\n this.rpcHandlers.set(method, handler);\n\n const req = new RegisterRpcMethodRequest({\n localParticipantHandle: this.ffi_handle.handle,\n method,\n });\n\n FfiClient.instance.request<RegisterRpcMethodResponse>({\n message: { case: 'registerRpcMethod', value: req },\n });\n }\n\n /**\n * Unregisters a previously registered RPC method.\n *\n * @param method - The name of the RPC method to unregister\n */\n unregisterRpcMethod(method: string) {\n this.rpcHandlers.delete(method);\n\n const req = new UnregisterRpcMethodRequest({\n localParticipantHandle: this.ffi_handle.handle,\n method,\n });\n\n FfiClient.instance.request<UnregisterRpcMethodResponse>({\n message: { case: 'unregisterRpcMethod', value: req },\n });\n }\n\n /** @internal */\n async handleRpcMethodInvocation(\n invocationId: bigint,\n method: string,\n requestId: string,\n callerIdentity: string,\n payload: string,\n responseTimeout: number,\n ) {\n let responseError: RpcError | null = null;\n let responsePayload: string | null = null;\n\n const handler = this.rpcHandlers.get(method);\n\n if (!handler) {\n responseError = RpcError.builtIn('UNSUPPORTED_METHOD');\n } else {\n try {\n responsePayload = await handler({ requestId, callerIdentity, payload, responseTimeout });\n } catch (error) {\n if (error instanceof RpcError) {\n responseError = error;\n } else {\n console.warn(\n `Uncaught error returned by RPC handler for ${method}. Returning APPLICATION_ERROR instead.`,\n error,\n );\n responseError = RpcError.builtIn('APPLICATION_ERROR');\n }\n }\n }\n\n const req = new RpcMethodInvocationResponseRequest({\n localParticipantHandle: this.ffi_handle.handle,\n invocationId,\n error: responseError ? responseError.toProto() : undefined,\n payload: responsePayload ?? undefined,\n });\n\n const res = FfiClient.instance.request<RpcMethodInvocationResponseResponse>({\n message: { case: 'rpcMethodInvocationResponse', value: req },\n });\n\n if (res.error) {\n console.warn(`error sending rpc method invocation response: ${res.error}`);\n }\n }\n}\n\nexport class RemoteParticipant extends Participant {\n trackPublications: Map<string, RemoteTrackPublication> = new Map();\n\n constructor(owned_info: OwnedParticipant) {\n super(owned_info);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/participant.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport {\n DisconnectReason,\n type OwnedParticipant,\n type ParticipantInfo,\n ParticipantKind,\n type ParticipantKindDetail,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n ChatMessage as ChatMessageModel,\n DataStream_ByteHeader,\n DataStream_Chunk,\n DataStream_Header,\n DataStream_OperationType,\n DataStream_TextHeader,\n DataStream_Trailer,\n EditChatMessageRequest,\n TranscriptionSegment as ProtoTranscriptionSegment,\n type PublishDataCallback,\n PublishDataRequest,\n type PublishDataResponse,\n type PublishSipDtmfCallback,\n PublishSipDtmfRequest,\n type PublishSipDtmfResponse,\n type PublishTrackCallback,\n PublishTrackRequest,\n type PublishTrackResponse,\n type PublishTranscriptionCallback,\n PublishTranscriptionRequest,\n type PublishTranscriptionResponse,\n type SendChatMessageCallback,\n SendChatMessageRequest,\n type SendChatMessageResponse,\n type SendStreamChunkCallback,\n SendStreamChunkRequest,\n type SendStreamChunkResponse,\n type SendStreamHeaderCallback,\n SendStreamHeaderRequest,\n type SendStreamHeaderResponse,\n type SendStreamTrailerCallback,\n SendStreamTrailerRequest,\n type SendStreamTrailerResponse,\n type SetLocalAttributesCallback,\n SetLocalAttributesRequest,\n type SetLocalAttributesResponse,\n type SetLocalMetadataCallback,\n SetLocalMetadataRequest,\n type SetLocalMetadataResponse,\n type SetLocalNameCallback,\n SetLocalNameRequest,\n type SetLocalNameResponse,\n type TrackPublishOptions,\n type UnpublishTrackCallback,\n UnpublishTrackRequest,\n type UnpublishTrackResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport type {\n PerformRpcCallback,\n PerformRpcResponse,\n RegisterRpcMethodResponse,\n RpcMethodInvocationResponseResponse,\n UnregisterRpcMethodResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n PerformRpcRequest,\n RegisterRpcMethodRequest,\n RpcMethodInvocationResponseRequest,\n UnregisterRpcMethodRequest,\n} from '@livekit/rtc-ffi-bindings';\nimport type { PathLike } from 'node:fs';\nimport { open, stat } from 'node:fs/promises';\nimport {\n type ByteStreamInfo,\n type ByteStreamOptions,\n ByteStreamWriter,\n type TextStreamInfo,\n TextStreamWriter,\n} from './data_streams/index.js';\nimport { FfiClient, FfiHandle } from './ffi_client.js';\nimport { log } from './log.js';\nimport { type PerformRpcParams, RpcError, type RpcInvocationData } from './rpc.js';\nimport type { LocalTrack } from './track.js';\nimport type { RemoteTrackPublication, TrackPublication } from './track_publication.js';\nimport { LocalTrackPublication } from './track_publication.js';\nimport type { Transcription } from './transcription.js';\nimport type { ChatMessage } from './types.js';\nimport { numberToBigInt, splitUtf8 } from './utils.js';\n\nconst STREAM_CHUNK_SIZE = 15_000;\n\nexport abstract class Participant {\n /** @internal */\n info: ParticipantInfo;\n\n /** @internal */\n ffi_handle: FfiHandle;\n\n trackPublications = new Map<string, TrackPublication>();\n\n constructor(owned_info: OwnedParticipant) {\n this.info = owned_info!.info!;\n this.ffi_handle = new FfiHandle(owned_info.handle!.id!);\n }\n\n get sid(): string | undefined {\n return this.info.sid;\n }\n\n get name(): string | undefined {\n return this.info.name;\n }\n\n get identity(): string {\n return this.info.identity ?? '';\n }\n\n get metadata(): string {\n return this.info.metadata ?? '';\n }\n\n get attributes(): Record<string, string> {\n return this.info.attributes ?? {};\n }\n\n get kind(): ParticipantKind {\n return this.info.kind ?? ParticipantKind.STANDARD;\n }\n\n get kindDetails(): ParticipantKindDetail[] {\n return this.info.kindDetails ?? [];\n }\n\n get disconnectReason(): DisconnectReason | undefined {\n if (this.info.disconnectReason === DisconnectReason.UNKNOWN_REASON) {\n return undefined;\n }\n return this.info.disconnectReason;\n }\n}\n\nexport type DataPublishOptions = {\n /**\n * whether to send this as reliable or lossy.\n * For data that you need delivery guarantee (such as chat messages), use Reliable.\n * For data that should arrive as quickly as possible, but you are ok with dropped\n * packets, use Lossy.\n */\n reliable?: boolean;\n /**\n * the identities of participants who will receive the message, will be sent to every one if empty\n */\n destination_identities?: string[];\n /** the topic under which the message gets published */\n topic?: string;\n};\n\nexport class LocalParticipant extends Participant {\n private rpcHandlers: Map<string, (data: RpcInvocationData) => Promise<string>> = new Map();\n\n private ffiEventLock: Mutex;\n\n // Signal that fires when the owning Room disconnects, used to cancel\n // pending FfiClient.waitFor() listeners so they don't leak.\n private disconnectSignal: AbortSignal;\n\n trackPublications: Map<string, LocalTrackPublication> = new Map();\n\n constructor(info: OwnedParticipant, ffiEventLock: Mutex, disconnectSignal: AbortSignal) {\n super(info);\n this.ffiEventLock = ffiEventLock;\n this.disconnectSignal = disconnectSignal;\n }\n\n async publishData(data: Uint8Array, options: DataPublishOptions) {\n const req = new PublishDataRequest({\n localParticipantHandle: this.ffi_handle.handle,\n dataPtr: FfiClient.instance.retrievePtr(data),\n dataLen: BigInt(data.byteLength),\n reliable: options.reliable,\n topic: options.topic,\n destinationIdentities: options.destination_identities,\n });\n\n const res = FfiClient.instance.request<PublishDataResponse>({\n message: { case: 'publishData', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PublishDataCallback>(\n (ev) => ev.message.case == 'publishData' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async publishDtmf(code: number, digit: string) {\n const req = new PublishSipDtmfRequest({\n localParticipantHandle: this.ffi_handle.handle,\n code,\n digit,\n });\n\n const res = FfiClient.instance.request<PublishSipDtmfResponse>({\n message: { case: 'publishSipDtmf', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PublishSipDtmfCallback>(\n (ev) => ev.message.case == 'publishSipDtmf' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async publishTranscription(transcription: Transcription) {\n const req = new PublishTranscriptionRequest({\n localParticipantHandle: this.ffi_handle.handle,\n participantIdentity: transcription.participantIdentity,\n segments: transcription.segments.map(\n (s) =>\n new ProtoTranscriptionSegment({\n id: s.id,\n text: s.text,\n startTime: s.startTime,\n endTime: s.endTime,\n final: s.final,\n language: s.language,\n }),\n ),\n trackId: transcription.trackSid,\n });\n\n const res = FfiClient.instance.request<PublishTranscriptionResponse>({\n message: { case: 'publishTranscription', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PublishTranscriptionCallback>(\n (ev) => ev.message.case == 'publishTranscription' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n async updateMetadata(metadata: string) {\n const req = new SetLocalMetadataRequest({\n localParticipantHandle: this.ffi_handle.handle,\n metadata: metadata,\n });\n\n const res = FfiClient.instance.request<SetLocalMetadataResponse>({\n message: { case: 'setLocalMetadata', value: req },\n });\n\n await FfiClient.instance.waitFor<SetLocalMetadataCallback>(\n (ev) => ev.message.case == 'setLocalMetadata' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n }\n\n /**\n * Returns a `StreamWriter` instance that allows to write individual chunks of text to a stream.\n * Well suited for TTS and/or streaming LLM output. If you want to simply send a text then use sendText() instead\n */\n async streamText(options?: {\n topic?: string;\n attributes?: Record<string, string>;\n destinationIdentities?: Array<string>;\n streamId?: string;\n senderIdentity?: string;\n }): Promise<TextStreamWriter> {\n const senderIdentity = options?.senderIdentity ?? this.identity;\n const streamId = options?.streamId ?? crypto.randomUUID();\n const destinationIdentities = options?.destinationIdentities;\n\n const info: TextStreamInfo = {\n streamId: streamId,\n mimeType: 'text/plain',\n topic: options?.topic ?? '',\n timestamp: Date.now(),\n };\n\n const headerReq = new SendStreamHeaderRequest({\n senderIdentity,\n destinationIdentities,\n localParticipantHandle: this.ffi_handle.handle,\n header: new DataStream_Header({\n streamId,\n mimeType: info.mimeType,\n topic: info.topic,\n timestamp: numberToBigInt(info.timestamp),\n attributes: options?.attributes,\n contentHeader: {\n case: 'textHeader',\n value: new DataStream_TextHeader({\n operationType: DataStream_OperationType.CREATE,\n version: 0,\n replyToStreamId: '',\n generated: false,\n }),\n },\n }),\n });\n\n await this.sendStreamHeader(headerReq);\n\n let nextChunkId = 0;\n const localHandle = this.ffi_handle.handle;\n const sendTrailer = this.sendStreamTrailer;\n const sendChunk = this.sendStreamChunk;\n\n const writableStream = new WritableStream<string>({\n // Implement the sink\n async write(text) {\n for (const textByteChunk of splitUtf8(text, STREAM_CHUNK_SIZE)) {\n const chunkRequest = new SendStreamChunkRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n chunk: new DataStream_Chunk({\n content: textByteChunk,\n streamId,\n chunkIndex: numberToBigInt(nextChunkId),\n }),\n });\n\n await sendChunk(chunkRequest);\n nextChunkId += 1;\n }\n },\n async close() {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: '',\n }),\n });\n await sendTrailer(trailerReq);\n },\n // Send a trailer with the error reason so the remote side's stream\n // controller is closed instead of waiting for data that won't arrive.\n async abort(err) {\n log.error(err, 'Sink Error');\n try {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: err instanceof Error ? err.message : String(err ?? ''),\n }),\n });\n await sendTrailer(trailerReq);\n } catch {\n // Best-effort: the connection may already be gone.\n }\n },\n });\n\n const writer = new TextStreamWriter(writableStream, info);\n\n return writer;\n }\n\n async sendText(\n text: string,\n options?: {\n topic?: string;\n attributes?: Record<string, string>;\n destinationIdentities?: Array<string>;\n streamId?: string;\n },\n ) {\n const writer = await this.streamText(options);\n await writer.write(text);\n await writer.close();\n return writer.info;\n }\n\n async streamBytes(options?: {\n name?: string;\n topic?: string;\n attributes?: Record<string, string>;\n destinationIdentities?: Array<string>;\n streamId?: string;\n mimeType?: string;\n totalSize?: number;\n }) {\n const senderIdentity = this.identity;\n const streamId = options?.streamId ?? crypto.randomUUID();\n const destinationIdentities = options?.destinationIdentities;\n\n const info: ByteStreamInfo = {\n streamId: streamId,\n mimeType: options?.mimeType ?? 'application/octet-stream',\n topic: options?.topic ?? '',\n timestamp: Date.now(),\n attributes: options?.attributes,\n totalSize: options?.totalSize,\n name: options?.name ?? 'unknown',\n };\n\n const headerReq = new SendStreamHeaderRequest({\n senderIdentity,\n destinationIdentities,\n localParticipantHandle: this.ffi_handle.handle,\n header: new DataStream_Header({\n streamId,\n mimeType: info.mimeType,\n topic: info.topic,\n timestamp: numberToBigInt(info.timestamp),\n attributes: info.attributes,\n totalLength: numberToBigInt(info.totalSize),\n contentHeader: {\n case: 'byteHeader',\n value: new DataStream_ByteHeader({\n name: info.name,\n }),\n },\n }),\n });\n\n await this.sendStreamHeader(headerReq);\n\n let chunkId = 0;\n const localHandle = this.ffi_handle.handle;\n const sendTrailer = this.sendStreamTrailer;\n const sendChunk = this.sendStreamChunk;\n const writeMutex = new Mutex();\n\n const writableStream = new WritableStream<Uint8Array>({\n async write(chunk) {\n const unlock = await writeMutex.lock();\n\n let byteOffset = 0;\n try {\n while (byteOffset < chunk.byteLength) {\n const subChunk = chunk.slice(byteOffset, byteOffset + STREAM_CHUNK_SIZE);\n const chunkRequest = new SendStreamChunkRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n chunk: new DataStream_Chunk({\n content: subChunk,\n streamId,\n chunkIndex: numberToBigInt(chunkId),\n }),\n });\n\n await sendChunk(chunkRequest);\n chunkId += 1;\n byteOffset += subChunk.byteLength;\n }\n } finally {\n unlock();\n }\n },\n async close() {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: '',\n }),\n });\n await sendTrailer(trailerReq);\n },\n // Send a trailer with the error reason so the remote side's stream\n // controller is closed instead of waiting for data that won't arrive.\n async abort(err) {\n log.error(err, 'Sink error');\n try {\n const trailerReq = new SendStreamTrailerRequest({\n senderIdentity,\n localParticipantHandle: localHandle,\n destinationIdentities,\n trailer: new DataStream_Trailer({\n streamId,\n reason: err instanceof Error ? err.message : String(err ?? ''),\n }),\n });\n await sendTrailer(trailerReq);\n } catch {\n // Best-effort: the connection may already be gone.\n }\n },\n });\n\n const byteWriter = new ByteStreamWriter(writableStream, info);\n\n return byteWriter;\n }\n\n /** Sends a file provided as PathLike to specified recipients */\n async sendFile(path: PathLike, options?: ByteStreamOptions) {\n const fileStats = await stat(path);\n const file = await open(path);\n try {\n const stream: ReadableStream<Uint8Array> = file.readableWebStream();\n const streamId = crypto.randomUUID();\n const destinationIdentities = options?.destinationIdentities;\n\n const writer = await this.streamBytes({\n streamId: streamId,\n name: options?.name,\n totalSize: fileStats.size,\n destinationIdentities,\n topic: options?.topic,\n mimeType: options?.mimeType,\n attributes: options?.attributes,\n });\n\n for await (const chunk of stream) {\n await writer.write(chunk);\n }\n await writer.close();\n } finally {\n await file.close();\n }\n }\n\n private async sendStreamHeader(req: SendStreamHeaderRequest) {\n const type = 'sendStreamHeader';\n const res = FfiClient.instance.request<SendStreamHeaderResponse>({\n message: { case: type, value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendStreamHeaderCallback>(\n (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n }\n\n private sendStreamChunk = async (req: SendStreamChunkRequest) => {\n const type = 'sendStreamChunk';\n const res = FfiClient.instance.request<SendStreamChunkResponse>({\n message: { case: type, value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendStreamChunkCallback>(\n (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n };\n\n private sendStreamTrailer = async (req: SendStreamTrailerRequest) => {\n const type = 'sendStreamTrailer';\n const res = FfiClient.instance.request<SendStreamTrailerResponse>({\n message: { case: type, value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendStreamTrailerCallback>(\n (ev) => ev.message.case == type && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n };\n\n /**\n * Sends a chat message to participants in the room\n *\n * @param text - The text content of the chat message.\n * @param destinationIdentities - An optional array of recipient identities to whom the message will be sent. If omitted, the message is broadcast to all participants.\n * @param senderIdentity - An optional identity of the sender. If omitted, the default sender identity is used.\n *\n */\n async sendChatMessage(\n text: string,\n destinationIdentities?: Array<string>,\n senderIdentity?: string,\n ): Promise<ChatMessage> {\n const req = new SendChatMessageRequest({\n localParticipantHandle: this.ffi_handle.handle,\n message: text,\n destinationIdentities,\n senderIdentity,\n });\n\n const res = FfiClient.instance.request<SendChatMessageResponse>({\n message: { case: 'sendChatMessage', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendChatMessageCallback>(\n (ev) => ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n switch (cb.message.case) {\n case 'chatMessage':\n const { id, timestamp, editTimestamp, message } = cb.message.value!;\n return {\n id: id!,\n timestamp: Number(timestamp),\n editTimestamp: Number(editTimestamp),\n message: message!,\n };\n case 'error':\n default:\n throw new Error(cb.message.value);\n }\n }\n\n /**\n * @experimental\n */\n async editChatMessage(\n editText: string,\n originalMessage: ChatMessage,\n destinationIdentities?: Array<string>,\n senderIdentity?: string,\n ): Promise<ChatMessage> {\n const req = new EditChatMessageRequest({\n localParticipantHandle: this.ffi_handle.handle,\n editText,\n originalMessage: new ChatMessageModel({\n ...originalMessage,\n timestamp: BigInt(originalMessage.timestamp),\n editTimestamp: originalMessage.editTimestamp\n ? BigInt(originalMessage.editTimestamp)\n : undefined,\n }),\n destinationIdentities,\n senderIdentity,\n });\n\n const res = FfiClient.instance.request<SendChatMessageResponse>({\n message: { case: 'editChatMessage', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<SendChatMessageCallback>(\n (ev) => ev.message.case == 'chatMessage' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n switch (cb.message.case) {\n case 'chatMessage':\n const { id, timestamp, editTimestamp, message } = cb.message.value!;\n return {\n id: id!,\n timestamp: Number(timestamp),\n editTimestamp: Number(editTimestamp),\n message: message!,\n };\n case 'error':\n default:\n throw new Error(cb.message.value);\n }\n }\n\n async updateName(name: string) {\n const req = new SetLocalNameRequest({\n localParticipantHandle: this.ffi_handle.handle,\n name: name,\n });\n\n const res = FfiClient.instance.request<SetLocalNameResponse>({\n message: { case: 'setLocalName', value: req },\n });\n\n await FfiClient.instance.waitFor<SetLocalNameCallback>(\n (ev) => ev.message.case == 'setLocalName' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n }\n\n async setAttributes(attributes: Record<string, string>) {\n const req = new SetLocalAttributesRequest({\n localParticipantHandle: this.ffi_handle.handle,\n attributes: Object.entries(attributes).map(([key, value]) => ({ key, value })),\n });\n\n const res = FfiClient.instance.request<SetLocalAttributesResponse>({\n message: { case: 'setLocalAttributes', value: req },\n });\n\n await FfiClient.instance.waitFor<SetLocalAttributesCallback>(\n (ev) => ev.message.case == 'setLocalAttributes' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n }\n\n async publishTrack(\n track: LocalTrack,\n options: TrackPublishOptions,\n ): Promise<LocalTrackPublication> {\n const req = new PublishTrackRequest({\n localParticipantHandle: this.ffi_handle.handle,\n trackHandle: track.ffi_handle.handle,\n options: options,\n });\n\n const unlock = await this.ffiEventLock.lock();\n\n const res = FfiClient.instance.request<PublishTrackResponse>({\n message: { case: 'publishTrack', value: req },\n });\n\n try {\n const cb = await FfiClient.instance.waitFor<PublishTrackCallback>(\n (ev) => ev.message.case == 'publishTrack' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n switch (cb.message.case) {\n case 'publication':\n const track_publication = new LocalTrackPublication(cb.message.value!);\n track_publication.track = track;\n // Stamp the server-assigned publication\n // SID onto the track so track.sid == publication.sid. Both\n // Track.pushProcessorMetadataToStream and the localTrackRepublished\n // handler look up the local publication by this SID; without it they\n // depend on createAudioTrack's provisional SID happening to match.\n if (track.info && track_publication.sid) {\n track.info.sid = track_publication.sid;\n }\n this.trackPublications.set(track_publication.sid!, track_publication);\n\n return track_publication;\n case 'error':\n default:\n throw new Error(cb.message.value);\n }\n } finally {\n unlock();\n }\n }\n\n async unpublishTrack(trackSid: string, stopOnUnpublish?: boolean) {\n const unlock = await this.ffiEventLock.lock();\n try {\n const req = new UnpublishTrackRequest({\n localParticipantHandle: this.ffi_handle.handle,\n trackSid: trackSid,\n stopOnUnpublish: stopOnUnpublish ?? true,\n });\n\n const res = FfiClient.instance.request<UnpublishTrackResponse>({\n message: { case: 'unpublishTrack', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<UnpublishTrackCallback>(\n (ev) => ev.message.case == 'unpublishTrack' && ev.message.value.asyncId == res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw new Error(cb.error);\n }\n\n const pub = this.trackPublications.get(trackSid);\n if (pub) {\n // Clear the processor's room context here too: this path races the\n // localTrackUnpublished room event, and whichever loses finds the\n // publication already gone and skips its own setRoom(null). Calling it\n // from both paths guarantees the processor is cleared (and the\n // tokenRefreshed listener detached); setRoom(null) is idempotent, so a\n // double-clear when this path wins is safe.\n if (pub.track) {\n pub.track.setRoom(null);\n }\n pub.track = undefined;\n }\n this.trackPublications.delete(trackSid);\n } finally {\n unlock();\n }\n }\n\n /**\n * Initiate an RPC call to a remote participant.\n * @param params - Parameters for initiating the RPC call, see {@link PerformRpcParams}\n * @returns A promise that resolves with the response payload or rejects with an error.\n * @throws Error on failure. Details in `message`.\n */\n async performRpc({\n destinationIdentity,\n method,\n payload,\n responseTimeout,\n }: PerformRpcParams): Promise<string> {\n const req = new PerformRpcRequest({\n localParticipantHandle: this.ffi_handle.handle,\n destinationIdentity,\n method,\n payload,\n responseTimeoutMs: responseTimeout,\n });\n\n const res = FfiClient.instance.request<PerformRpcResponse>({\n message: { case: 'performRpc', value: req },\n });\n\n const cb = await FfiClient.instance.waitFor<PerformRpcCallback>(\n (ev) => ev.message.case === 'performRpc' && ev.message.value.asyncId === res.asyncId,\n { signal: this.disconnectSignal },\n );\n\n if (cb.error) {\n throw RpcError.fromProto(cb.error);\n }\n\n return cb.payload!;\n }\n\n /**\n * Establishes the participant as a receiver for calls of the specified RPC method.\n * Will overwrite any existing callback for the same method.\n *\n * @param method - The name of the indicated RPC method\n * @param handler - Will be invoked when an RPC request for this method is received\n * @returns A promise that resolves when the method is successfully registered\n *\n * @example\n * ```typescript\n * room.localParticipant?.registerRpcMethod(\n * 'greet',\n * async (data: RpcInvocationData) => {\n * console.log(`Received greeting from ${data.callerIdentity}: ${data.payload}`);\n * return `Hello, ${data.callerIdentity}!`;\n * }\n * );\n * ```\n *\n * See {@link RpcInvocationData} for more details on invocation params.\n *\n * The handler should return a Promise that resolves to a string.\n * If unable to respond within `responseTimeout`, the request will result in an error on the caller's side.\n *\n * You may throw errors of type `RpcError` with a string `message` in the handler,\n * and they will be received on the caller's side with the message intact.\n * Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` (\"Application Error\").\n */\n registerRpcMethod(method: string, handler: (data: RpcInvocationData) => Promise<string>) {\n this.rpcHandlers.set(method, handler);\n\n const req = new RegisterRpcMethodRequest({\n localParticipantHandle: this.ffi_handle.handle,\n method,\n });\n\n FfiClient.instance.request<RegisterRpcMethodResponse>({\n message: { case: 'registerRpcMethod', value: req },\n });\n }\n\n /**\n * Unregisters a previously registered RPC method.\n *\n * @param method - The name of the RPC method to unregister\n */\n unregisterRpcMethod(method: string) {\n this.rpcHandlers.delete(method);\n\n const req = new UnregisterRpcMethodRequest({\n localParticipantHandle: this.ffi_handle.handle,\n method,\n });\n\n FfiClient.instance.request<UnregisterRpcMethodResponse>({\n message: { case: 'unregisterRpcMethod', value: req },\n });\n }\n\n /** @internal */\n async handleRpcMethodInvocation(\n invocationId: bigint,\n method: string,\n requestId: string,\n callerIdentity: string,\n payload: string,\n responseTimeout: number,\n ) {\n let responseError: RpcError | null = null;\n let responsePayload: string | null = null;\n\n const handler = this.rpcHandlers.get(method);\n\n if (!handler) {\n responseError = RpcError.builtIn('UNSUPPORTED_METHOD');\n } else {\n try {\n responsePayload = await handler({ requestId, callerIdentity, payload, responseTimeout });\n } catch (error) {\n if (error instanceof RpcError) {\n responseError = error;\n } else {\n console.warn(\n `Uncaught error returned by RPC handler for ${method}. Returning APPLICATION_ERROR instead.`,\n error,\n );\n responseError = RpcError.builtIn('APPLICATION_ERROR');\n }\n }\n }\n\n const req = new RpcMethodInvocationResponseRequest({\n localParticipantHandle: this.ffi_handle.handle,\n invocationId,\n error: responseError ? responseError.toProto() : undefined,\n payload: responsePayload ?? undefined,\n });\n\n const res = FfiClient.instance.request<RpcMethodInvocationResponseResponse>({\n message: { case: 'rpcMethodInvocationResponse', value: req },\n });\n\n if (res.error) {\n console.warn(`error sending rpc method invocation response: ${res.error}`);\n }\n }\n}\n\nexport class RemoteParticipant extends Participant {\n trackPublications: Map<string, RemoteTrackPublication> = new Map();\n\n constructor(owned_info: OwnedParticipant) {\n super(owned_info);\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/room.cjs
CHANGED
|
@@ -103,6 +103,7 @@ class Room extends import_events.default {
|
|
|
103
103
|
}
|
|
104
104
|
};
|
|
105
105
|
this.processFfiEvent = async (ffiEvent) => {
|
|
106
|
+
var _a, _b;
|
|
106
107
|
if (!this.localParticipant || !this.ffiHandle || !this.info) {
|
|
107
108
|
throw new Error("processFfiEvent called before connect");
|
|
108
109
|
}
|
|
@@ -140,11 +141,21 @@ class Room extends import_events.default {
|
|
|
140
141
|
}
|
|
141
142
|
} else if (ev.case == "localTrackPublished") {
|
|
142
143
|
const publication = this.localParticipant.trackPublications.get(ev.value.trackSid);
|
|
144
|
+
if (publication == null ? void 0 : publication.track) {
|
|
145
|
+
publication.track.setRoom(this);
|
|
146
|
+
}
|
|
143
147
|
this.emit("localTrackPublished" /* LocalTrackPublished */, publication, this.localParticipant);
|
|
144
148
|
} else if (ev.case == "localTrackUnpublished") {
|
|
145
149
|
const publication = this.localParticipant.trackPublications.get(ev.value.publicationSid);
|
|
150
|
+
const track = publication == null ? void 0 : publication.track;
|
|
151
|
+
if (track) {
|
|
152
|
+
track.setRoom(null);
|
|
153
|
+
}
|
|
146
154
|
this.localParticipant.trackPublications.delete(ev.value.publicationSid);
|
|
147
155
|
this.emit("localTrackUnpublished" /* LocalTrackUnpublished */, publication, this.localParticipant);
|
|
156
|
+
if (track && publication) {
|
|
157
|
+
publication.track = void 0;
|
|
158
|
+
}
|
|
148
159
|
} else if (ev.case == "localTrackRepublished") {
|
|
149
160
|
const value = ev.value;
|
|
150
161
|
const previousSid = value.previousSid;
|
|
@@ -154,6 +165,10 @@ class Room extends import_events.default {
|
|
|
154
165
|
publication.updateInfo(newInfo);
|
|
155
166
|
this.localParticipant.trackPublications.delete(previousSid);
|
|
156
167
|
this.localParticipant.trackPublications.set(publication.sid, publication);
|
|
168
|
+
if ((_a = publication.track) == null ? void 0 : _a.info) {
|
|
169
|
+
publication.track.info.sid = publication.sid;
|
|
170
|
+
publication.track.setRoom(this);
|
|
171
|
+
}
|
|
157
172
|
this.emit("localTrackRepublished" /* LocalTrackRepublished */, publication, previousSid, this.localParticipant);
|
|
158
173
|
} else {
|
|
159
174
|
import_log.log.warn(`RoomEvent.LocalTrackRepublished: previous publication not found: ${previousSid}`);
|
|
@@ -201,6 +216,7 @@ class Room extends import_events.default {
|
|
|
201
216
|
} else if (trackInfo.kind == import_rtc_ffi_bindings4.TrackKind.KIND_AUDIO) {
|
|
202
217
|
publication.track = new import_track.RemoteAudioTrack(ownedTrack);
|
|
203
218
|
}
|
|
219
|
+
(_b = publication.track) == null ? void 0 : _b.setRoom(this);
|
|
204
220
|
this.emit("trackSubscribed" /* TrackSubscribed */, publication.track, publication, participant);
|
|
205
221
|
} catch (e) {
|
|
206
222
|
import_log.log.warn(`RoomEvent.TrackSubscribed: ${e.message}`);
|
|
@@ -212,6 +228,7 @@ class Room extends import_events.default {
|
|
|
212
228
|
ev.value.trackSid
|
|
213
229
|
);
|
|
214
230
|
const track = publication.track;
|
|
231
|
+
track.setRoom(null);
|
|
215
232
|
publication.track = void 0;
|
|
216
233
|
publication.subscribed = false;
|
|
217
234
|
this.emit("trackUnsubscribed" /* TrackUnsubscribed */, track, publication, participant);
|
|
@@ -653,6 +670,7 @@ class Room extends import_events.default {
|
|
|
653
670
|
// disconnect() both race to get here — whichever wins emits the events,
|
|
654
671
|
// the other is a no-op. A reconnect via connect() clears hasCleanedUp.
|
|
655
672
|
cleanupOnDisconnect(reason = import_rtc_ffi_bindings2.DisconnectReason.CLIENT_INITIATED) {
|
|
673
|
+
var _a, _b;
|
|
656
674
|
if (this.hasCleanedUp) return;
|
|
657
675
|
this.hasCleanedUp = true;
|
|
658
676
|
for (const [, streamController] of this.byteStreamControllers) {
|
|
@@ -669,6 +687,16 @@ class Room extends import_events.default {
|
|
|
669
687
|
}
|
|
670
688
|
}
|
|
671
689
|
this.textStreamControllers.clear();
|
|
690
|
+
if (this.localParticipant) {
|
|
691
|
+
for (const pub of this.localParticipant.trackPublications.values()) {
|
|
692
|
+
(_a = pub.track) == null ? void 0 : _a.setRoom(null);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
for (const participant of this.remoteParticipants.values()) {
|
|
696
|
+
for (const pub of participant.trackPublications.values()) {
|
|
697
|
+
(_b = pub.track) == null ? void 0 : _b.setRoom(null);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
672
700
|
this.sidPromise = void 0;
|
|
673
701
|
this.disconnectController.abort();
|
|
674
702
|
this.updateConnectionState(import_rtc_ffi_bindings3.ConnectionState.CONN_DISCONNECTED);
|
package/dist/room.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/room.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport { EncryptionState, type EncryptionType } from '@livekit/rtc-ffi-bindings';\nimport type {\n FfiEvent,\n GetSessionStatsCallback,\n GetSessionStatsResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport { DisconnectReason, type OwnedParticipant } from '@livekit/rtc-ffi-bindings';\nimport type {\n DataStream_Trailer,\n DisconnectCallback,\n TrackPublicationInfo,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n type ConnectCallback,\n ConnectRequest,\n type ConnectResponse,\n type ConnectionQuality,\n ConnectionState,\n ContinualGatheringPolicy,\n type DataPacketKind,\n type DataStream_Chunk,\n type DataStream_Header,\n type DisconnectResponse,\n RoomOptions as FfiRoomOptions,\n type IceServer,\n IceTransportType,\n type ReadyForRoomEventResponse,\n type RoomInfo,\n type SimulateScenarioCallback,\n type SimulateScenarioKind,\n type SimulateScenarioResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport { TrackKind } from '@livekit/rtc-ffi-bindings';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport EventEmitter from 'events';\nimport { ByteStreamReader, TextStreamReader } from './data_streams/stream_reader.js';\nimport type {\n ByteStreamHandler,\n ByteStreamInfo,\n StreamController,\n TextStreamHandler,\n TextStreamInfo,\n} from './data_streams/types.js';\nimport type { E2EEOptions } from './e2ee.js';\nimport { E2EEManager, defaultE2EEOptions } from './e2ee.js';\nimport { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';\nimport { log } from './log.js';\nimport type { Participant } from './participant.js';\nimport { LocalParticipant, RemoteParticipant } from './participant.js';\nimport type { LocalTrack, RemoteTrack } from './track.js';\nimport { RemoteAudioTrack, RemoteVideoTrack } from './track.js';\nimport type { LocalTrackPublication, TrackPublication } from './track_publication.js';\nimport { RemoteTrackPublication } from './track_publication.js';\nimport type { ChatMessage } from './types.js';\nimport { bigIntToNumber } from './utils.js';\n\nexport interface RtcConfiguration {\n iceTransportType: IceTransportType;\n continualGatheringPolicy: ContinualGatheringPolicy;\n iceServers: IceServer[];\n}\n\nexport const defaultRtcConfiguration: RtcConfiguration = {\n iceTransportType: IceTransportType.TRANSPORT_ALL,\n continualGatheringPolicy: ContinualGatheringPolicy.GATHER_CONTINUALLY,\n iceServers: [],\n};\n\nexport interface RoomOptions {\n autoSubscribe: boolean;\n dynacast: boolean;\n /**\n * @deprecated Use `encryption` instead. See x for details\n */\n e2ee?: E2EEOptions;\n encryption?: E2EEOptions;\n rtcConfig?: RtcConfiguration;\n}\n\nexport const defaultRoomOptions = new FfiRoomOptions({\n autoSubscribe: true,\n dynacast: false,\n e2ee: undefined,\n encryption: undefined,\n rtcConfig: undefined,\n adaptiveStream: false,\n joinRetries: 1,\n});\n\nexport class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>) {\n private info?: RoomInfo;\n private ffiHandle?: FfiHandle;\n /**\n * used to ensure events are processed sequentially and allow for\n * the local participant to acquire the lock while doing state updates related to FFI events\n * before processing the next events\n */\n private ffiEventLock = new Mutex();\n\n private byteStreamControllers = new Map<string, StreamController<DataStream_Chunk>>();\n private textStreamControllers = new Map<string, StreamController<DataStream_Chunk>>();\n private byteStreamHandlers = new Map<string, ByteStreamHandler>();\n private textStreamHandlers = new Map<string, TextStreamHandler>();\n\n private preConnectEvents: FfiEvent[] = [];\n\n // Aborted on disconnect to cancel any pending FfiClient.waitFor() listeners,\n // preventing them from leaking when the room goes away.\n private disconnectController = new AbortController();\n\n // Guards cleanupOnDisconnect so the ConnectionStateChanged/Disconnected\n // events fire exactly once, no matter which path (explicit disconnect()\n // vs. FFI 'disconnected' event) wins the race.\n private hasCleanedUp = false;\n\n private _token?: string;\n private _serverUrl?: string;\n private _connectionState: ConnectionState = ConnectionState.CONN_DISCONNECTED;\n\n e2eeManager?: E2EEManager;\n\n remoteParticipants: Map<string, RemoteParticipant> = new Map();\n localParticipant?: LocalParticipant;\n\n constructor() {\n super();\n }\n\n get connectionState() {\n return this._connectionState;\n }\n\n get name(): string | undefined {\n return this.info?.name;\n }\n\n get metadata(): string | undefined {\n return this.info?.metadata;\n }\n\n get isConnected(): boolean {\n return this.ffiHandle != undefined && this.connectionState != ConnectionState.CONN_DISCONNECTED;\n }\n\n /** @internal */\n get token(): string | undefined {\n return this._token;\n }\n\n /** @internal */\n get serverUrl(): string | undefined {\n return this._serverUrl;\n }\n\n // Shared promise for concurrent getSid() callers. Without this, each call\n // registers its own RoomSidChanged + Disconnected listeners, and if many\n // calls race only one of each pair is cleaned up — leaking the rest.\n private sidPromise?: Promise<string>;\n\n /**\n * Gets the room's server ID. This ID is assigned by the LiveKit server\n * and is unique for each room session.\n * SID is assigned asynchronously after connection.\n * @returns Promise that resolves to the room's server ID, or empty string if not connected\n */\n async getSid(): Promise<string> {\n if (!this.isConnected) {\n return '';\n }\n if (this.info?.sid && this.info.sid !== '') {\n return this.info.sid;\n }\n if (!this.sidPromise) {\n this.sidPromise = new Promise<string>((resolve, reject) => {\n const handleDisconnect = () => {\n this.off(RoomEvent.RoomSidChanged, handleRoomUpdate);\n this.sidPromise = undefined;\n reject('Room disconnected before room server id was available');\n };\n const handleRoomUpdate = (sid: string) => {\n if (sid !== '') {\n this.off(RoomEvent.RoomSidChanged, handleRoomUpdate);\n this.off(RoomEvent.Disconnected as any, handleDisconnect);\n this.sidPromise = undefined;\n resolve(sid);\n }\n };\n this.on(RoomEvent.RoomSidChanged, handleRoomUpdate);\n this.once(RoomEvent.Disconnected, handleDisconnect);\n });\n }\n return this.sidPromise;\n }\n\n async getRtcStats() {\n if (!this.isConnected || !this.ffiHandle) {\n throw new Error('getRtcStats requires a connected room');\n }\n // subscribe before issuing the request\n const requestId = FfiClient.instance.getNextRequestAsyncId();\n const cbPromise = FfiClient.instance.waitFor<GetSessionStatsCallback>(\n (ev: FfiEvent) =>\n ev.message.case === 'getSessionStats' && ev.message.value.asyncId === requestId,\n { signal: this.disconnectController.signal },\n );\n FfiClient.instance.request<GetSessionStatsResponse>({\n message: {\n case: 'getSessionStats',\n value: {\n roomHandle: this.ffiHandle.handle,\n requestAsyncId: requestId,\n },\n },\n });\n const cb = await cbPromise;\n if (cb.message.case === 'error') {\n throw new Error(cb.message.value);\n } else if (cb.message.case === 'result') {\n return cb.message.value;\n } else {\n throw new Error('could not retrieve rtc stats');\n }\n }\n\n get numParticipants(): number {\n return this.info?.numParticipants ?? 0;\n }\n\n get numPublishers(): number {\n return this.info?.numPublishers ?? 0;\n }\n\n get creationTime(): Date {\n // TODO: workaround for Rust SDK bug, remove after updating to:\n // https://github.com/livekit/rust-sdks/pull/822\n // check if creationTime looks like seconds (less than year 3000 in ms), convert to ms if needed\n let creationTimeMs = Number(this.info?.creationTime ?? 0);\n if (creationTimeMs > 0 && creationTimeMs < 1e12) {\n creationTimeMs *= 1000;\n }\n return new Date(creationTimeMs);\n }\n\n get isRecording(): boolean {\n return this.info?.activeRecording ?? false;\n }\n\n /**\n * The time in seconds after which a room will be closed after the last\n * participant has disconnected.\n */\n get departureTimeout(): number {\n return this.info?.departureTimeout ?? 0;\n }\n\n /**\n * The time in seconds after which an empty room will be automatically closed.\n */\n get emptyTimeout(): number {\n return this.info?.emptyTimeout ?? 0;\n }\n\n /**\n * Connects to a LiveKit room using the provided URL and access token.\n * @param url - The WebSocket URL of the LiveKit server\n * @param token - A valid LiveKit access token for authentication\n * @param opts - Optional room configuration options\n * @throws ConnectError - if connection fails\n */\n async connect(url: string, token: string, opts?: RoomOptions) {\n const options = { ...defaultRoomOptions, ...opts };\n const e2eeEnabled = options.encryption || options.e2ee;\n const e2eeOptions = options.encryption\n ? { ...defaultE2EEOptions, ...options.encryption }\n : { ...defaultE2EEOptions, ...options.e2ee };\n\n const req = new ConnectRequest({\n url: url,\n token: token,\n options,\n });\n\n FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onFfiEvent);\n\n try {\n const res = FfiClient.instance.request<ConnectResponse>({\n message: {\n case: 'connect',\n value: req,\n },\n });\n\n const cb = await FfiClient.instance.waitFor<ConnectCallback>((ev: FfiEvent) => {\n return ev.message.case == 'connect' && ev.message.value.asyncId == res.asyncId;\n });\n\n log.debug('Connect callback received');\n\n switch (cb.message.case) {\n case 'result':\n this.ffiHandle = new FfiHandle(cb.message.value.room!.handle!.id!);\n this.e2eeManager = e2eeEnabled && new E2EEManager(this.ffiHandle.handle, e2eeOptions);\n\n this._token = token;\n this._serverUrl = url;\n this.info = cb.message.value.room!.info;\n // Reset the abort controller for this connection session so that\n // a previous disconnect doesn't immediately cancel new operations.\n this.disconnectController = new AbortController();\n this.hasCleanedUp = false;\n this.localParticipant = new LocalParticipant(\n cb.message.value.localParticipant!,\n this.ffiEventLock,\n this.disconnectController.signal,\n );\n\n for (const pt of cb.message.value.participants) {\n const rp = this.createRemoteParticipant(pt.participant!);\n\n for (const pub of pt.publications) {\n const publication = new RemoteTrackPublication(pub);\n rp.trackPublications.set(publication.sid!, publication);\n }\n }\n this.updateConnectionState(ConnectionState.CONN_CONNECTED);\n // Release the FFI room event gate after our listener and local state are ready.\n FfiClient.instance.request<ReadyForRoomEventResponse>({\n message: {\n case: 'readyForRoomEvent',\n value: {\n roomHandle: this.ffiHandle.handle,\n },\n },\n });\n break;\n case 'error':\n default:\n throw new ConnectError(cb.message.value || '');\n }\n } catch (e) {\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onFfiEvent);\n this.preConnectEvents = [];\n throw e;\n }\n }\n\n /**\n * Disconnects from the room and cleans up all resources.\n * This will stop all tracks and close the connection.\n */\n async disconnect() {\n if (!this.isConnected) {\n return;\n }\n\n const res = FfiClient.instance.request<DisconnectResponse>({\n message: {\n case: 'disconnect',\n value: {\n roomHandle: this.ffiHandle?.handle,\n },\n },\n });\n\n await FfiClient.instance.waitFor<DisconnectCallback>((ev: FfiEvent) => {\n return ev.message.case == 'disconnect' && ev.message.value.asyncId == res.asyncId;\n });\n\n this.cleanupOnDisconnect(DisconnectReason.CLIENT_INITIATED);\n FfiClient.instance.removeListener(FfiClientEvent.FfiEvent, this.onFfiEvent);\n\n this.removeAllListeners();\n }\n\n /**\n * Trigger a reconnection / chaos scenario for testing. Most useful in\n * tests to deterministically force a Resume (signal-only reconnect that\n * preserves the PeerConnection and existing publications) or a full\n * reconnect (the SDK rebuilds the RtcSession and re-publishes existing\n * local tracks; `RoomEvent.Reconnected` fires).\n */\n async simulateScenario(scenario: SimulateScenarioKind): Promise<void> {\n if (!this.isConnected || !this.ffiHandle) {\n throw new Error('simulateScenario requires a connected room');\n }\n const res = FfiClient.instance.request<SimulateScenarioResponse>({\n message: {\n case: 'simulateScenario',\n value: {\n roomHandle: this.ffiHandle.handle,\n scenario,\n },\n },\n });\n const cb = await FfiClient.instance.waitFor<SimulateScenarioCallback>(\n (ev: FfiEvent) =>\n ev.message.case === 'simulateScenario' && ev.message.value.asyncId === res.asyncId,\n { signal: this.disconnectController.signal },\n );\n if (cb.error) {\n throw new Error(`simulateScenario failed: ${cb.error}`);\n }\n }\n\n private updateConnectionState(newState: ConnectionState) {\n if (this._connectionState === newState) {\n return;\n }\n this._connectionState = newState;\n this.emit(RoomEvent.ConnectionStateChanged, this._connectionState);\n }\n\n // Runs at most once per connection session. The FFI layer and explicit\n // disconnect() both race to get here — whichever wins emits the events,\n // the other is a no-op. A reconnect via connect() clears hasCleanedUp.\n private cleanupOnDisconnect(reason: DisconnectReason = DisconnectReason.CLIENT_INITIATED) {\n if (this.hasCleanedUp) return;\n this.hasCleanedUp = true;\n\n // Error all in-progress stream controllers to prevent FD leaks.\n // Streams that were receiving data but never got a trailer (e.g. the sender\n // disconnected mid-transfer) would otherwise keep their ReadableStream open\n // indefinitely, leaking the underlying controller and any buffered chunks.\n // Using error() instead of close() signals an abnormal termination to consumers.\n for (const [, streamController] of this.byteStreamControllers) {\n try {\n streamController.controller.error(new Error('Disconnected while receiving'));\n } catch {\n // controller may already be closed or errored\n }\n }\n this.byteStreamControllers.clear();\n\n for (const [, streamController] of this.textStreamControllers) {\n try {\n streamController.controller.error(new Error('Disconnected while receiving'));\n } catch {\n // controller may already be closed or errored\n }\n }\n this.textStreamControllers.clear();\n\n // Clear sidPromise before removing listeners so that a reconnect\n // doesn't return a stale, permanently-pending promise.\n this.sidPromise = undefined;\n // Abort all pending FfiClient.waitFor() listeners so they don't leak.\n // This causes any in-flight operations (publishData, publishTrack, etc.)\n // to reject and clean up their event listeners.\n this.disconnectController.abort();\n\n this.updateConnectionState(ConnectionState.CONN_DISCONNECTED);\n this.emit(RoomEvent.Disconnected, reason);\n }\n\n /**\n * Registers a handler for incoming text data streams on a specific topic.\n * Text streams are used for receiving structured text data from other participants.\n * @param topic - The topic to listen for text streams on\n * @param callback - Function to handle incoming text stream data\n * @throws Error - if a handler for this topic is already registered\n */\n registerTextStreamHandler(topic: string, callback: TextStreamHandler) {\n if (this.textStreamHandlers.has(topic)) {\n throw new Error(`A text stream handler for topic \"${topic}\" has already been set.`);\n }\n this.textStreamHandlers.set(topic, callback);\n }\n\n unregisterTextStreamHandler(topic: string) {\n this.textStreamHandlers.delete(topic);\n }\n\n /**\n * Registers a handler for incoming byte data streams on a specific topic.\n * Byte streams are used for receiving binary data like files from other participants.\n * @param topic - The topic to listen for byte streams on\n * @param callback - Function to handle incoming byte stream data\n * @throws Error - if a handler for this topic is already registered\n */\n registerByteStreamHandler(topic: string, callback: ByteStreamHandler) {\n if (this.byteStreamHandlers.has(topic)) {\n throw new Error(`A byte stream handler for topic \"${topic}\" has already been set.`);\n }\n this.byteStreamHandlers.set(topic, callback);\n }\n\n unregisterByteStreamHandler(topic: string) {\n this.byteStreamHandlers.delete(topic);\n }\n\n private onFfiEvent = async (ffiEvent: FfiEvent) => {\n const unlock = await this.ffiEventLock.lock();\n try {\n if (!this.localParticipant || !this.ffiHandle || !this.info) {\n this.preConnectEvents.push(ffiEvent);\n return;\n }\n\n // process preConnectEvents if we received the connectCallback after the events were queued\n for (const ev of this.preConnectEvents) {\n await this.processFfiEvent(ev);\n }\n this.preConnectEvents = [];\n\n await this.processFfiEvent(ffiEvent);\n } finally {\n unlock();\n }\n };\n\n private processFfiEvent = async (ffiEvent: FfiEvent) => {\n if (!this.localParticipant || !this.ffiHandle || !this.info) {\n throw new Error('processFfiEvent called before connect');\n }\n\n if (ffiEvent.message.case == 'rpcMethodInvocation') {\n if (\n ffiEvent.message.value.localParticipantHandle == this.localParticipant.ffi_handle.handle\n ) {\n this.localParticipant.handleRpcMethodInvocation(\n ffiEvent.message.value.invocationId!,\n ffiEvent.message.value.method!,\n ffiEvent.message.value.requestId!,\n ffiEvent.message.value.callerIdentity!,\n ffiEvent.message.value.payload!,\n ffiEvent.message.value.responseTimeoutMs!,\n );\n }\n return;\n } else if (\n ffiEvent.message.case != 'roomEvent' ||\n ffiEvent.message.value.roomHandle != this.ffiHandle.handle\n ) {\n return;\n }\n\n const ev = ffiEvent.message.value.message;\n if (process.env.LIVEKIT_DEBUG_LOG_ROOM_EVENTS) {\n console.log('Room event:', ev);\n }\n if (ev.case == 'participantConnected') {\n const participant = this.createRemoteParticipant(ev.value.info!);\n this.remoteParticipants.set(participant.identity!, participant);\n this.emit(RoomEvent.ParticipantConnected, participant);\n } else if (ev.case == 'participantDisconnected') {\n const participant = this.remoteParticipants.get(ev.value.participantIdentity!);\n if (participant) {\n this.remoteParticipants.delete(participant.identity);\n participant.info.disconnectReason = ev.value.disconnectReason;\n this.emit(RoomEvent.ParticipantDisconnected, participant);\n } else {\n log.warn(`RoomEvent.ParticipantDisconnected: Could not find participant`);\n }\n } else if (ev.case == 'localTrackPublished') {\n const publication = this.localParticipant.trackPublications.get(ev.value.trackSid!);\n this.emit(RoomEvent.LocalTrackPublished, publication!, this.localParticipant);\n } else if (ev.case == 'localTrackUnpublished') {\n const publication = this.localParticipant.trackPublications.get(ev.value.publicationSid!);\n this.localParticipant.trackPublications.delete(ev.value.publicationSid!);\n this.emit(RoomEvent.LocalTrackUnpublished, publication!, this.localParticipant!);\n } else if ((ev.case as string) == 'localTrackRepublished') {\n const value = (ev as any).value;\n const previousSid: string = value.previousSid!;\n const newInfo: TrackPublicationInfo = value.info!;\n const publication = this.localParticipant.trackPublications.get(previousSid);\n if (publication) {\n publication.updateInfo(newInfo);\n this.localParticipant.trackPublications.delete(previousSid);\n this.localParticipant.trackPublications.set(publication.sid!, publication);\n this.emit(RoomEvent.LocalTrackRepublished, publication, previousSid, this.localParticipant);\n } else {\n log.warn(`RoomEvent.LocalTrackRepublished: previous publication not found: ${previousSid}`);\n }\n } else if (ev.case == 'localTrackSubscribed') {\n const publication = this.localParticipant.trackPublications.get(ev.value.trackSid!);\n if (publication) {\n publication.resolveFirstSubscription();\n this.emit(RoomEvent.LocalTrackSubscribed, publication!.track!);\n } else {\n log.warn(`RoomEvent.LocalTrackSubscribed: Publication not found: ${ev.value.trackSid}`);\n }\n } else if (ev.case == 'trackPublished') {\n const participant = this.remoteParticipants.get(ev.value.participantIdentity!);\n const publication = new RemoteTrackPublication(ev.value.publication!);\n if (participant) {\n participant.trackPublications.set(publication.sid!, publication);\n } else {\n log.warn(\n `RoomEvent.TrackPublished: Could not find participant: ${ev.value.participantIdentity}`,\n );\n }\n this.emit(RoomEvent.TrackPublished, publication, participant!);\n } else if (ev.case == 'trackUnpublished') {\n const participant = this.requireRemoteParticipant(ev.value.participantIdentity!);\n const publication = participant.trackPublications.get(ev.value.publicationSid!);\n participant.trackPublications.delete(ev.value.publicationSid!);\n if (publication) {\n this.emit(RoomEvent.TrackUnpublished, publication, participant);\n // Dispose eagerly so handles don't accumulate when a participant\n // publishes and unpublishes many tracks during a long-lived session.\n publication.ffiHandle.dispose();\n } else {\n log.warn(`RoomEvent.TrackUnpublished: Could not find publication`);\n }\n } else if (ev.case == 'trackSubscribed') {\n const ownedTrack = ev.value.track!;\n const trackInfo = ownedTrack.info!;\n try {\n const { participant, publication } = this.requirePublicationOfRemoteParticipant(\n ev.value.participantIdentity!,\n trackInfo.sid!,\n );\n publication.subscribed = true;\n if (trackInfo.kind == TrackKind.KIND_VIDEO) {\n publication.track = new RemoteVideoTrack(ownedTrack);\n } else if (trackInfo.kind == TrackKind.KIND_AUDIO) {\n publication.track = new RemoteAudioTrack(ownedTrack);\n }\n\n this.emit(RoomEvent.TrackSubscribed, publication.track!, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackSubscribed: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackUnsubscribed') {\n try {\n const { participant, publication } = this.requirePublicationOfRemoteParticipant(\n ev.value.participantIdentity!,\n ev.value.trackSid!,\n );\n const track = publication.track!;\n publication.track = undefined;\n publication.subscribed = false;\n this.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackUnsubscribed: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackSubscriptionFailed') {\n try {\n const participant = this.requireRemoteParticipant(ev.value.participantIdentity!);\n this.emit(\n RoomEvent.TrackSubscriptionFailed,\n ev.value.trackSid!,\n participant,\n ev.value.error,\n );\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackSubscriptionFailed: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackMuted') {\n try {\n const { participant, publication } = this.requirePublicationOfParticipant(\n ev.value.participantIdentity!,\n ev.value.trackSid!,\n );\n publication.info!.muted = true;\n if (publication.track) {\n publication.track.info!.muted = true;\n }\n this.emit(RoomEvent.TrackMuted, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackMuted: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackUnmuted') {\n try {\n const { participant, publication } = this.requirePublicationOfParticipant(\n ev.value.participantIdentity!,\n ev.value.trackSid!,\n );\n publication.info!.muted = false;\n if (publication.track) {\n publication.track.info!.muted = false;\n }\n this.emit(RoomEvent.TrackUnmuted, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackUnmuted: ${(e as Error).message}`);\n }\n } else if (ev.case == 'activeSpeakersChanged') {\n try {\n const activeSpeakers = ev.value.participantIdentities.map((identity) =>\n this.requireParticipantByIdentity(identity),\n );\n this.emit(RoomEvent.ActiveSpeakersChanged, activeSpeakers);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ActiveSpeakersChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'roomMetadataChanged') {\n this.info.metadata = ev.value.metadata ?? '';\n this.emit(RoomEvent.RoomMetadataChanged, this.info.metadata);\n } else if (ev.case == 'participantMetadataChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n participant.info.metadata = ev.value.metadata;\n this.emit(RoomEvent.ParticipantMetadataChanged, participant.metadata, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantMetadataChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'participantNameChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n participant.info.name = ev.value.name;\n this.emit(RoomEvent.ParticipantNameChanged, participant.name!, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantNameChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'participantAttributesChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n participant.info.attributes = ev.value.attributes.reduce(\n (acc, value) => {\n acc[value.key!] = value.value!;\n return acc;\n },\n {} as Record<string, string>,\n );\n if (Object.keys(ev.value.changedAttributes).length > 0) {\n const changedAttributes = ev.value.changedAttributes.reduce(\n (acc, value) => {\n acc[value.key!] = value.value!;\n return acc;\n },\n {} as Record<string, string>,\n );\n this.emit(RoomEvent.ParticipantAttributesChanged, changedAttributes, participant);\n }\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantAttributesChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'connectionQualityChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n this.emit(RoomEvent.ConnectionQualityChanged, ev.value.quality!, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ConnectionQualityChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'chatMessage') {\n const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity!);\n const { id, message: messageText, timestamp, editTimestamp, generated } = ev.value.message!;\n const message: ChatMessage = {\n id: id!,\n message: messageText!,\n timestamp: Number(timestamp),\n editTimestamp: Number(editTimestamp),\n generated,\n };\n this.emit(RoomEvent.ChatMessage, message, participant);\n } else if (ev.case == 'dataPacketReceived') {\n // Can be undefined if the data is sent from a Server SDK\n const participant = this.remoteParticipants.get(ev.value.participantIdentity!);\n const dataPacket = ev.value.value;\n switch (dataPacket.case) {\n case 'user':\n const buffer = FfiClient.instance.copyBuffer(\n dataPacket.value.data!.data!.dataPtr!,\n Number(dataPacket.value.data!.data!.dataLen),\n );\n new FfiHandle(dataPacket.value.data!.handle!.id!).dispose();\n this.emit(\n RoomEvent.DataReceived,\n buffer,\n participant,\n ev.value.kind,\n dataPacket.value.topic,\n );\n break;\n case 'sipDtmf':\n const { code, digit } = dataPacket.value;\n this.emit(RoomEvent.DtmfReceived, code!, digit!, participant!);\n break;\n default:\n break;\n }\n } else if (ev.case == 'e2eeStateChanged') {\n if (ev.value.state == EncryptionState.INTERNAL_ERROR) {\n // throw generic error until Rust SDK is updated to supply the error alongside INTERNAL_ERROR\n this.emit(RoomEvent.EncryptionError, new Error('internal server error'));\n }\n } else if (ev.case == 'connectionStateChanged') {\n this.updateConnectionState(ev.value.state!);\n /*} else if (ev.case == 'connected') {\n this.emit(RoomEvent.Connected);*/\n } else if (ev.case == 'disconnected') {\n // cleanupOnDisconnect emits RoomEvent.Disconnected itself (guarded by\n // hasCleanedUp so it fires exactly once across both disconnect paths).\n this.cleanupOnDisconnect(ev.value.reason!);\n } else if (ev.case == 'reconnecting') {\n this.emit(RoomEvent.Reconnecting);\n } else if (ev.case == 'reconnected') {\n this.emit(RoomEvent.Reconnected);\n } else if (ev.case == 'roomSidChanged') {\n this.emit(RoomEvent.RoomSidChanged, ev.value.sid!);\n } else if (ev.case === 'streamHeaderReceived' && ev.value.header) {\n this.handleStreamHeader(ev.value.header, ev.value.participantIdentity!);\n } else if (ev.case === 'streamChunkReceived' && ev.value.chunk) {\n this.handleStreamChunk(ev.value.chunk);\n } else if (ev.case === 'streamTrailerReceived' && ev.value.trailer) {\n this.handleStreamTrailer(ev.value.trailer);\n } else if (ev.case === 'roomUpdated') {\n this.info = ev.value;\n this.emit(RoomEvent.RoomUpdated);\n } else if (ev.case === 'moved') {\n this.info = ev.value;\n this.emit(RoomEvent.Moved);\n } else if (ev.case === 'participantsUpdated') {\n for (const info of ev.value.participants) {\n const participant = this.retrieveParticipantByIdentity(info.identity!);\n if (participant) {\n participant.info = info;\n }\n }\n } else if (ev.case === 'participantEncryptionStatusChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n this.emit(\n RoomEvent.ParticipantEncryptionStatusChanged,\n !!ev.value.isEncrypted,\n participant,\n );\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantEncryptionStatusChanged: ${(e as Error).message}`);\n }\n } else if (ev.case === 'tokenRefreshed') {\n this._token = ev.value.token;\n this.emit('tokenRefreshed');\n }\n };\n\n private retrieveParticipantByIdentity(identity: string): Participant | undefined {\n if (this.localParticipant?.identity === identity) {\n return this.localParticipant;\n } else {\n return this.remoteParticipants.get(identity);\n }\n }\n\n private requireParticipantByIdentity(identity: string): Participant {\n if (this.localParticipant?.identity === identity) {\n return this.localParticipant;\n } else if (this.remoteParticipants.has(identity)) {\n return this.remoteParticipants.get(identity)!;\n } else {\n throw new TypeError(`participant ${identity} not found`);\n }\n }\n\n private requireRemoteParticipant(identity: string) {\n const participant = this.remoteParticipants.get(identity);\n if (!participant) {\n throw new TypeError(`participant ${identity} not found`);\n }\n return participant;\n }\n\n private requirePublicationOfParticipant(identity: string, trackSid: string) {\n const participant = this.requireParticipantByIdentity(identity);\n const publication = participant.trackPublications.get(trackSid);\n if (!publication) {\n throw new TypeError(`publication ${trackSid} not found`);\n }\n return { participant, publication };\n }\n\n private requirePublicationOfRemoteParticipant(identity: string, trackSid: string) {\n const participant = this.requireRemoteParticipant(identity);\n const publication = participant.trackPublications.get(trackSid);\n if (!publication) {\n throw new TypeError(`publication ${trackSid} not found`);\n }\n return { participant, publication };\n }\n\n private createRemoteParticipant(ownedInfo: OwnedParticipant) {\n if (this.remoteParticipants.has(ownedInfo.info!.identity!)) {\n throw new Error('Participant already exists');\n }\n\n const participant = new RemoteParticipant(ownedInfo);\n this.remoteParticipants.set(ownedInfo.info!.identity!, participant);\n return participant;\n }\n\n private handleStreamHeader(streamHeader: DataStream_Header, participantIdentity: string) {\n if (streamHeader.contentHeader.case === 'byteHeader') {\n const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic ?? '');\n\n if (!streamHandlerCallback) {\n log.debug(\n 'ignoring incoming byte stream due to no handler for topic: %s',\n streamHeader.topic ?? 'undefined',\n );\n return;\n }\n let streamController: ReadableStreamDefaultController<DataStream_Chunk>;\n const stream = new ReadableStream({\n start: (controller) => {\n streamController = controller;\n this.byteStreamControllers.set(streamHeader.streamId!, {\n header: streamHeader,\n controller: streamController,\n startTime: Date.now(),\n });\n },\n });\n const info: ByteStreamInfo = {\n streamId: streamHeader.streamId!,\n name: streamHeader.contentHeader.value.name ?? 'unknown',\n mimeType: streamHeader.mimeType!,\n totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : undefined,\n topic: streamHeader.topic!,\n timestamp: bigIntToNumber(streamHeader.timestamp!),\n attributes: streamHeader.attributes,\n };\n streamHandlerCallback(\n new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)),\n { identity: participantIdentity },\n );\n } else if (streamHeader.contentHeader.case === 'textHeader') {\n const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic ?? '');\n\n if (!streamHandlerCallback) {\n log.debug(\n 'ignoring incoming text stream due to no handler for topic: %s',\n streamHeader.topic ?? 'undefined',\n );\n return;\n }\n let streamController: ReadableStreamDefaultController<DataStream_Chunk>;\n const stream = new ReadableStream<DataStream_Chunk>({\n start: (controller) => {\n streamController = controller;\n this.textStreamControllers.set(streamHeader.streamId!, {\n header: streamHeader,\n controller: streamController,\n startTime: Date.now(),\n });\n },\n });\n const info: TextStreamInfo = {\n streamId: streamHeader.streamId!,\n mimeType: streamHeader.mimeType!,\n totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : undefined,\n topic: streamHeader.topic!,\n timestamp: Number(streamHeader.timestamp),\n attributes: streamHeader.attributes,\n };\n streamHandlerCallback(\n new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)),\n { identity: participantIdentity },\n );\n }\n }\n\n private handleStreamChunk(chunk: DataStream_Chunk) {\n const fileBuffer = this.byteStreamControllers.get(chunk.streamId!);\n if (fileBuffer) {\n if (chunk.content!.length > 0) {\n fileBuffer.controller.enqueue(chunk);\n }\n }\n const textBuffer = this.textStreamControllers.get(chunk.streamId!);\n if (textBuffer) {\n if (chunk.content!.length > 0) {\n textBuffer.controller.enqueue(chunk);\n }\n }\n }\n\n private handleStreamTrailer(trailer: DataStream_Trailer) {\n const streamId = trailer.streamId!;\n const fileBuffer = this.byteStreamControllers.get(streamId);\n if (fileBuffer) {\n fileBuffer.controller.close();\n this.byteStreamControllers.delete(streamId);\n }\n const textBuffer = this.textStreamControllers.get(streamId);\n if (textBuffer) {\n textBuffer.controller.close();\n this.textStreamControllers.delete(streamId);\n }\n }\n}\n\nexport class ConnectError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport type RoomCallbacks = {\n participantConnected: (participant: RemoteParticipant) => void;\n participantDisconnected: (participant: RemoteParticipant) => void;\n localTrackPublished: (publication: LocalTrackPublication, participant: LocalParticipant) => void;\n localTrackUnpublished: (\n publication: LocalTrackPublication,\n participant: LocalParticipant,\n ) => void;\n /**\n * Fired when the SDK auto-republished a local track during a full\n * reconnect. The publication object's identity is preserved (the same\n * instance is updated in place with the new server-assigned SIDs);\n * `previousSid` is provided for callers that key external state on the\n * old SID and need to reconcile.\n */\n localTrackRepublished: (\n publication: LocalTrackPublication,\n previousSid: string,\n participant: LocalParticipant,\n ) => void;\n localTrackSubscribed: (track: LocalTrack) => void;\n trackPublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;\n trackUnpublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;\n trackSubscribed: (\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ) => void;\n trackUnsubscribed: (\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ) => void;\n trackSubscriptionFailed: (\n trackSid: string,\n participant: RemoteParticipant,\n reason?: string,\n ) => void;\n trackMuted: (publication: TrackPublication, participant: Participant) => void;\n trackUnmuted: (publication: TrackPublication, participant: Participant) => void;\n activeSpeakersChanged: (speakers: Participant[]) => void;\n roomMetadataChanged: (metadata: string) => void;\n roomInfoUpdated: (info: RoomInfo) => void;\n participantMetadataChanged: (metadata: string | undefined, participant: Participant) => void;\n participantNameChanged: (name: string, participant: Participant) => void;\n participantAttributesChanged: (\n changedAttributes: Record<string, string>,\n participant: Participant,\n ) => void;\n participantEncryptionStatusChanged: (isEncrypted: boolean, participant: Participant) => void;\n connectionQualityChanged: (quality: ConnectionQuality, participant: Participant) => void;\n dataReceived: (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n kind?: DataPacketKind,\n topic?: string,\n encryptionType?: EncryptionType,\n ) => void;\n chatMessage: (message: ChatMessage, participant?: Participant) => void;\n dtmfReceived: (code: number, digit: string, participant: RemoteParticipant) => void;\n encryptionError: (error: Error) => void;\n connectionStateChanged: (state: ConnectionState) => void;\n connected: () => void;\n disconnected: (reason: DisconnectReason) => void;\n reconnecting: () => void;\n reconnected: () => void;\n roomSidChanged: (sid: string) => void;\n roomUpdated: () => void;\n moved: () => void;\n tokenRefreshed: () => void;\n};\n\nexport enum RoomEvent {\n ParticipantConnected = 'participantConnected',\n ParticipantDisconnected = 'participantDisconnected',\n LocalTrackPublished = 'localTrackPublished',\n LocalTrackUnpublished = 'localTrackUnpublished',\n LocalTrackRepublished = 'localTrackRepublished',\n LocalTrackSubscribed = 'localTrackSubscribed',\n TrackPublished = 'trackPublished',\n TrackUnpublished = 'trackUnpublished',\n TrackSubscribed = 'trackSubscribed',\n TrackUnsubscribed = 'trackUnsubscribed',\n TrackSubscriptionFailed = 'trackSubscriptionFailed',\n TrackMuted = 'trackMuted',\n TrackUnmuted = 'trackUnmuted',\n ActiveSpeakersChanged = 'activeSpeakersChanged',\n RoomMetadataChanged = 'roomMetadataChanged',\n RoomSidChanged = 'roomSidChanged',\n ParticipantMetadataChanged = 'participantMetadataChanged',\n ParticipantNameChanged = 'participantNameChanged',\n ParticipantAttributesChanged = 'participantAttributesChanged',\n ParticipantEncryptionStatusChanged = 'participantEncryptionStatusChanged',\n ConnectionQualityChanged = 'connectionQualityChanged',\n DataReceived = 'dataReceived',\n ChatMessage = 'chatMessage',\n DtmfReceived = 'dtmfReceived',\n EncryptionError = 'encryptionError',\n ConnectionStateChanged = 'connectionStateChanged',\n Connected = 'connected',\n Disconnected = 'disconnected',\n Reconnecting = 'reconnecting',\n Reconnected = 'reconnected',\n RoomUpdated = 'roomUpdated',\n Moved = 'moved',\n TokenRefreshed = 'tokenRefreshed',\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAAsB;AACtB,8BAAqD;AAMrD,IAAAA,2BAAwD;AAMxD,IAAAA,2BAmBO;AACP,IAAAA,2BAA0B;AAE1B,oBAAyB;AACzB,2BAAmD;AASnD,kBAAgD;AAChD,wBAAqD;AACrD,iBAAoB;AAEpB,yBAAoD;AAEpD,mBAAmD;AAEnD,+BAAuC;AAEvC,mBAA+B;AAQxB,MAAM,0BAA4C;AAAA,EACvD,kBAAkB,0CAAiB;AAAA,EACnC,0BAA0B,kDAAyB;AAAA,EACnD,YAAY,CAAC;AACf;AAaO,MAAM,qBAAqB,IAAI,yBAAAC,YAAe;AAAA,EACnD,eAAe;AAAA,EACf,UAAU;AAAA,EACV,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,aAAa;AACf,CAAC;AAEM,MAAM,aAAc,cAAAC,QAAuD;AAAA,EAmChF,cAAc;AACZ,UAAM;AA5BR;AAAA;AAAA;AAAA;AAAA;AAAA,SAAQ,eAAe,IAAI,mBAAM;AAEjC,SAAQ,wBAAwB,oBAAI,IAAgD;AACpF,SAAQ,wBAAwB,oBAAI,IAAgD;AACpF,SAAQ,qBAAqB,oBAAI,IAA+B;AAChE,SAAQ,qBAAqB,oBAAI,IAA+B;AAEhE,SAAQ,mBAA+B,CAAC;AAIxC;AAAA;AAAA,SAAQ,uBAAuB,IAAI,gBAAgB;AAKnD;AAAA;AAAA;AAAA,SAAQ,eAAe;AAIvB,SAAQ,mBAAoC,yCAAgB;AAI5D,8BAAqD,oBAAI,IAAI;AAiX7D,SAAQ,aAAa,OAAO,aAAuB;AACjD,YAAM,SAAS,MAAM,KAAK,aAAa,KAAK;AAC5C,UAAI;AACF,YAAI,CAAC,KAAK,oBAAoB,CAAC,KAAK,aAAa,CAAC,KAAK,MAAM;AAC3D,eAAK,iBAAiB,KAAK,QAAQ;AACnC;AAAA,QACF;AAGA,mBAAW,MAAM,KAAK,kBAAkB;AACtC,gBAAM,KAAK,gBAAgB,EAAE;AAAA,QAC/B;AACA,aAAK,mBAAmB,CAAC;AAEzB,cAAM,KAAK,gBAAgB,QAAQ;AAAA,MACrC,UAAE;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,SAAQ,kBAAkB,OAAO,aAAuB;AACtD,UAAI,CAAC,KAAK,oBAAoB,CAAC,KAAK,aAAa,CAAC,KAAK,MAAM;AAC3D,cAAM,IAAI,MAAM,uCAAuC;AAAA,MACzD;AAEA,UAAI,SAAS,QAAQ,QAAQ,uBAAuB;AAClD,YACE,SAAS,QAAQ,MAAM,0BAA0B,KAAK,iBAAiB,WAAW,QAClF;AACA,eAAK,iBAAiB;AAAA,YACpB,SAAS,QAAQ,MAAM;AAAA,YACvB,SAAS,QAAQ,MAAM;AAAA,YACvB,SAAS,QAAQ,MAAM;AAAA,YACvB,SAAS,QAAQ,MAAM;AAAA,YACvB,SAAS,QAAQ,MAAM;AAAA,YACvB,SAAS,QAAQ,MAAM;AAAA,UACzB;AAAA,QACF;AACA;AAAA,MACF,WACE,SAAS,QAAQ,QAAQ,eACzB,SAAS,QAAQ,MAAM,cAAc,KAAK,UAAU,QACpD;AACA;AAAA,MACF;AAEA,YAAM,KAAK,SAAS,QAAQ,MAAM;AAClC,UAAI,QAAQ,IAAI,+BAA+B;AAC7C,gBAAQ,IAAI,eAAe,EAAE;AAAA,MAC/B;AACA,UAAI,GAAG,QAAQ,wBAAwB;AACrC,cAAM,cAAc,KAAK,wBAAwB,GAAG,MAAM,IAAK;AAC/D,aAAK,mBAAmB,IAAI,YAAY,UAAW,WAAW;AAC9D,aAAK,KAAK,mDAAgC,WAAW;AAAA,MACvD,WAAW,GAAG,QAAQ,2BAA2B;AAC/C,cAAM,cAAc,KAAK,mBAAmB,IAAI,GAAG,MAAM,mBAAoB;AAC7E,YAAI,aAAa;AACf,eAAK,mBAAmB,OAAO,YAAY,QAAQ;AACnD,sBAAY,KAAK,mBAAmB,GAAG,MAAM;AAC7C,eAAK,KAAK,yDAAmC,WAAW;AAAA,QAC1D,OAAO;AACL,yBAAI,KAAK,+DAA+D;AAAA,QAC1E;AAAA,MACF,WAAW,GAAG,QAAQ,uBAAuB;AAC3C,cAAM,cAAc,KAAK,iBAAiB,kBAAkB,IAAI,GAAG,MAAM,QAAS;AAClF,aAAK,KAAK,iDAA+B,aAAc,KAAK,gBAAgB;AAAA,MAC9E,WAAW,GAAG,QAAQ,yBAAyB;AAC7C,cAAM,cAAc,KAAK,iBAAiB,kBAAkB,IAAI,GAAG,MAAM,cAAe;AACxF,aAAK,iBAAiB,kBAAkB,OAAO,GAAG,MAAM,cAAe;AACvE,aAAK,KAAK,qDAAiC,aAAc,KAAK,gBAAiB;AAAA,MACjF,WAAY,GAAG,QAAmB,yBAAyB;AACzD,cAAM,QAAS,GAAW;AAC1B,cAAM,cAAsB,MAAM;AAClC,cAAM,UAAgC,MAAM;AAC5C,cAAM,cAAc,KAAK,iBAAiB,kBAAkB,IAAI,WAAW;AAC3E,YAAI,aAAa;AACf,sBAAY,WAAW,OAAO;AAC9B,eAAK,iBAAiB,kBAAkB,OAAO,WAAW;AAC1D,eAAK,iBAAiB,kBAAkB,IAAI,YAAY,KAAM,WAAW;AACzE,eAAK,KAAK,qDAAiC,aAAa,aAAa,KAAK,gBAAgB;AAAA,QAC5F,OAAO;AACL,yBAAI,KAAK,oEAAoE,WAAW,EAAE;AAAA,QAC5F;AAAA,MACF,WAAW,GAAG,QAAQ,wBAAwB;AAC5C,cAAM,cAAc,KAAK,iBAAiB,kBAAkB,IAAI,GAAG,MAAM,QAAS;AAClF,YAAI,aAAa;AACf,sBAAY,yBAAyB;AACrC,eAAK,KAAK,mDAAgC,YAAa,KAAM;AAAA,QAC/D,OAAO;AACL,yBAAI,KAAK,0DAA0D,GAAG,MAAM,QAAQ,EAAE;AAAA,QACxF;AAAA,MACF,WAAW,GAAG,QAAQ,kBAAkB;AACtC,cAAM,cAAc,KAAK,mBAAmB,IAAI,GAAG,MAAM,mBAAoB;AAC7E,cAAM,cAAc,IAAI,gDAAuB,GAAG,MAAM,WAAY;AACpE,YAAI,aAAa;AACf,sBAAY,kBAAkB,IAAI,YAAY,KAAM,WAAW;AAAA,QACjE,OAAO;AACL,yBAAI;AAAA,YACF,yDAAyD,GAAG,MAAM,mBAAmB;AAAA,UACvF;AAAA,QACF;AACA,aAAK,KAAK,uCAA0B,aAAa,WAAY;AAAA,MAC/D,WAAW,GAAG,QAAQ,oBAAoB;AACxC,cAAM,cAAc,KAAK,yBAAyB,GAAG,MAAM,mBAAoB;AAC/E,cAAM,cAAc,YAAY,kBAAkB,IAAI,GAAG,MAAM,cAAe;AAC9E,oBAAY,kBAAkB,OAAO,GAAG,MAAM,cAAe;AAC7D,YAAI,aAAa;AACf,eAAK,KAAK,2CAA4B,aAAa,WAAW;AAG9D,sBAAY,UAAU,QAAQ;AAAA,QAChC,OAAO;AACL,yBAAI,KAAK,wDAAwD;AAAA,QACnE;AAAA,MACF,WAAW,GAAG,QAAQ,mBAAmB;AACvC,cAAM,aAAa,GAAG,MAAM;AAC5B,cAAM,YAAY,WAAW;AAC7B,YAAI;AACF,gBAAM,EAAE,aAAa,YAAY,IAAI,KAAK;AAAA,YACxC,GAAG,MAAM;AAAA,YACT,UAAU;AAAA,UACZ;AACA,sBAAY,aAAa;AACzB,cAAI,UAAU,QAAQ,mCAAU,YAAY;AAC1C,wBAAY,QAAQ,IAAI,8BAAiB,UAAU;AAAA,UACrD,WAAW,UAAU,QAAQ,mCAAU,YAAY;AACjD,wBAAY,QAAQ,IAAI,8BAAiB,UAAU;AAAA,UACrD;AAEA,eAAK,KAAK,yCAA2B,YAAY,OAAQ,aAAa,WAAW;AAAA,QACnF,SAAS,GAAY;AACnB,yBAAI,KAAK,8BAA+B,EAAY,OAAO,EAAE;AAAA,QAC/D;AAAA,MACF,WAAW,GAAG,QAAQ,qBAAqB;AACzC,YAAI;AACF,gBAAM,EAAE,aAAa,YAAY,IAAI,KAAK;AAAA,YACxC,GAAG,MAAM;AAAA,YACT,GAAG,MAAM;AAAA,UACX;AACA,gBAAM,QAAQ,YAAY;AAC1B,sBAAY,QAAQ;AACpB,sBAAY,aAAa;AACzB,eAAK,KAAK,6CAA6B,OAAO,aAAa,WAAW;AAAA,QACxE,SAAS,GAAY;AACnB,yBAAI,KAAK,gCAAiC,EAAY,OAAO,EAAE;AAAA,QACjE;AAAA,MACF,WAAW,GAAG,QAAQ,2BAA2B;AAC/C,YAAI;AACF,gBAAM,cAAc,KAAK,yBAAyB,GAAG,MAAM,mBAAoB;AAC/E,eAAK;AAAA,YACH;AAAA,YACA,GAAG,MAAM;AAAA,YACT;AAAA,YACA,GAAG,MAAM;AAAA,UACX;AAAA,QACF,SAAS,GAAY;AACnB,yBAAI,KAAK,sCAAuC,EAAY,OAAO,EAAE;AAAA,QACvE;AAAA,MACF,WAAW,GAAG,QAAQ,cAAc;AAClC,YAAI;AACF,gBAAM,EAAE,aAAa,YAAY,IAAI,KAAK;AAAA,YACxC,GAAG,MAAM;AAAA,YACT,GAAG,MAAM;AAAA,UACX;AACA,sBAAY,KAAM,QAAQ;AAC1B,cAAI,YAAY,OAAO;AACrB,wBAAY,MAAM,KAAM,QAAQ;AAAA,UAClC;AACA,eAAK,KAAK,+BAAsB,aAAa,WAAW;AAAA,QAC1D,SAAS,GAAY;AACnB,yBAAI,KAAK,yBAA0B,EAAY,OAAO,EAAE;AAAA,QAC1D;AAAA,MACF,WAAW,GAAG,QAAQ,gBAAgB;AACpC,YAAI;AACF,gBAAM,EAAE,aAAa,YAAY,IAAI,KAAK;AAAA,YACxC,GAAG,MAAM;AAAA,YACT,GAAG,MAAM;AAAA,UACX;AACA,sBAAY,KAAM,QAAQ;AAC1B,cAAI,YAAY,OAAO;AACrB,wBAAY,MAAM,KAAM,QAAQ;AAAA,UAClC;AACA,eAAK,KAAK,mCAAwB,aAAa,WAAW;AAAA,QAC5D,SAAS,GAAY;AACnB,yBAAI,KAAK,2BAA4B,EAAY,OAAO,EAAE;AAAA,QAC5D;AAAA,MACF,WAAW,GAAG,QAAQ,yBAAyB;AAC7C,YAAI;AACF,gBAAM,iBAAiB,GAAG,MAAM,sBAAsB;AAAA,YAAI,CAAC,aACzD,KAAK,6BAA6B,QAAQ;AAAA,UAC5C;AACA,eAAK,KAAK,qDAAiC,cAAc;AAAA,QAC3D,SAAS,GAAY;AACnB,yBAAI,KAAK,oCAAqC,EAAY,OAAO,EAAE;AAAA,QACrE;AAAA,MACF,WAAW,GAAG,QAAQ,uBAAuB;AAC3C,aAAK,KAAK,WAAW,GAAG,MAAM,YAAY;AAC1C,aAAK,KAAK,iDAA+B,KAAK,KAAK,QAAQ;AAAA,MAC7D,WAAW,GAAG,QAAQ,8BAA8B;AAClD,YAAI;AACF,gBAAM,cAAc,KAAK,6BAA6B,GAAG,MAAM,mBAAoB;AACnF,sBAAY,KAAK,WAAW,GAAG,MAAM;AACrC,eAAK,KAAK,+DAAsC,YAAY,UAAU,WAAW;AAAA,QACnF,SAAS,GAAY;AACnB,yBAAI,KAAK,yCAA0C,EAAY,OAAO,EAAE;AAAA,QAC1E;AAAA,MACF,WAAW,GAAG,QAAQ,0BAA0B;AAC9C,YAAI;AACF,gBAAM,cAAc,KAAK,6BAA6B,GAAG,MAAM,mBAAoB;AACnF,sBAAY,KAAK,OAAO,GAAG,MAAM;AACjC,eAAK,KAAK,uDAAkC,YAAY,MAAO,WAAW;AAAA,QAC5E,SAAS,GAAY;AACnB,yBAAI,KAAK,qCAAsC,EAAY,OAAO,EAAE;AAAA,QACtE;AAAA,MACF,WAAW,GAAG,QAAQ,gCAAgC;AACpD,YAAI;AACF,gBAAM,cAAc,KAAK,6BAA6B,GAAG,MAAM,mBAAoB;AACnF,sBAAY,KAAK,aAAa,GAAG,MAAM,WAAW;AAAA,YAChD,CAAC,KAAK,UAAU;AACd,kBAAI,MAAM,GAAI,IAAI,MAAM;AACxB,qBAAO;AAAA,YACT;AAAA,YACA,CAAC;AAAA,UACH;AACA,cAAI,OAAO,KAAK,GAAG,MAAM,iBAAiB,EAAE,SAAS,GAAG;AACtD,kBAAM,oBAAoB,GAAG,MAAM,kBAAkB;AAAA,cACnD,CAAC,KAAK,UAAU;AACd,oBAAI,MAAM,GAAI,IAAI,MAAM;AACxB,uBAAO;AAAA,cACT;AAAA,cACA,CAAC;AAAA,YACH;AACA,iBAAK,KAAK,mEAAwC,mBAAmB,WAAW;AAAA,UAClF;AAAA,QACF,SAAS,GAAY;AACnB,yBAAI,KAAK,2CAA4C,EAAY,OAAO,EAAE;AAAA,QAC5E;AAAA,MACF,WAAW,GAAG,QAAQ,4BAA4B;AAChD,YAAI;AACF,gBAAM,cAAc,KAAK,6BAA6B,GAAG,MAAM,mBAAoB;AACnF,eAAK,KAAK,2DAAoC,GAAG,MAAM,SAAU,WAAW;AAAA,QAC9E,SAAS,GAAY;AACnB,yBAAI,KAAK,uCAAwC,EAAY,OAAO,EAAE;AAAA,QACxE;AAAA,MACF,WAAW,GAAG,QAAQ,eAAe;AACnC,cAAM,cAAc,KAAK,8BAA8B,GAAG,MAAM,mBAAoB;AACpF,cAAM,EAAE,IAAI,SAAS,aAAa,WAAW,eAAe,UAAU,IAAI,GAAG,MAAM;AACnF,cAAM,UAAuB;AAAA,UAC3B;AAAA,UACA,SAAS;AAAA,UACT,WAAW,OAAO,SAAS;AAAA,UAC3B,eAAe,OAAO,aAAa;AAAA,UACnC;AAAA,QACF;AACA,aAAK,KAAK,iCAAuB,SAAS,WAAW;AAAA,MACvD,WAAW,GAAG,QAAQ,sBAAsB;AAE1C,cAAM,cAAc,KAAK,mBAAmB,IAAI,GAAG,MAAM,mBAAoB;AAC7E,cAAM,aAAa,GAAG,MAAM;AAC5B,gBAAQ,WAAW,MAAM;AAAA,UACvB,KAAK;AACH,kBAAM,SAAS,4BAAU,SAAS;AAAA,cAChC,WAAW,MAAM,KAAM,KAAM;AAAA,cAC7B,OAAO,WAAW,MAAM,KAAM,KAAM,OAAO;AAAA,YAC7C;AACA,gBAAI,4BAAU,WAAW,MAAM,KAAM,OAAQ,EAAG,EAAE,QAAQ;AAC1D,iBAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA,GAAG,MAAM;AAAA,cACT,WAAW,MAAM;AAAA,YACnB;AACA;AAAA,UACF,KAAK;AACH,kBAAM,EAAE,MAAM,MAAM,IAAI,WAAW;AACnC,iBAAK,KAAK,mCAAwB,MAAO,OAAQ,WAAY;AAC7D;AAAA,UACF;AACE;AAAA,QACJ;AAAA,MACF,WAAW,GAAG,QAAQ,oBAAoB;AACxC,YAAI,GAAG,MAAM,SAAS,wCAAgB,gBAAgB;AAEpD,eAAK,KAAK,yCAA2B,IAAI,MAAM,uBAAuB,CAAC;AAAA,QACzE;AAAA,MACF,WAAW,GAAG,QAAQ,0BAA0B;AAC9C,aAAK,sBAAsB,GAAG,MAAM,KAAM;AAAA,MAG5C,WAAW,GAAG,QAAQ,gBAAgB;AAGpC,aAAK,oBAAoB,GAAG,MAAM,MAAO;AAAA,MAC3C,WAAW,GAAG,QAAQ,gBAAgB;AACpC,aAAK,KAAK,iCAAsB;AAAA,MAClC,WAAW,GAAG,QAAQ,eAAe;AACnC,aAAK,KAAK,+BAAqB;AAAA,MACjC,WAAW,GAAG,QAAQ,kBAAkB;AACtC,aAAK,KAAK,uCAA0B,GAAG,MAAM,GAAI;AAAA,MACnD,WAAW,GAAG,SAAS,0BAA0B,GAAG,MAAM,QAAQ;AAChE,aAAK,mBAAmB,GAAG,MAAM,QAAQ,GAAG,MAAM,mBAAoB;AAAA,MACxE,WAAW,GAAG,SAAS,yBAAyB,GAAG,MAAM,OAAO;AAC9D,aAAK,kBAAkB,GAAG,MAAM,KAAK;AAAA,MACvC,WAAW,GAAG,SAAS,2BAA2B,GAAG,MAAM,SAAS;AAClE,aAAK,oBAAoB,GAAG,MAAM,OAAO;AAAA,MAC3C,WAAW,GAAG,SAAS,eAAe;AACpC,aAAK,OAAO,GAAG;AACf,aAAK,KAAK,+BAAqB;AAAA,MACjC,WAAW,GAAG,SAAS,SAAS;AAC9B,aAAK,OAAO,GAAG;AACf,aAAK,KAAK,mBAAe;AAAA,MAC3B,WAAW,GAAG,SAAS,uBAAuB;AAC5C,mBAAW,QAAQ,GAAG,MAAM,cAAc;AACxC,gBAAM,cAAc,KAAK,8BAA8B,KAAK,QAAS;AACrE,cAAI,aAAa;AACf,wBAAY,OAAO;AAAA,UACrB;AAAA,QACF;AAAA,MACF,WAAW,GAAG,SAAS,sCAAsC;AAC3D,YAAI;AACF,gBAAM,cAAc,KAAK,6BAA6B,GAAG,MAAM,mBAAoB;AACnF,eAAK;AAAA,YACH;AAAA,YACA,CAAC,CAAC,GAAG,MAAM;AAAA,YACX;AAAA,UACF;AAAA,QACF,SAAS,GAAY;AACnB,yBAAI,KAAK,iDAAkD,EAAY,OAAO,EAAE;AAAA,QAClF;AAAA,MACF,WAAW,GAAG,SAAS,kBAAkB;AACvC,aAAK,SAAS,GAAG,MAAM;AACvB,aAAK,KAAK,gBAAgB;AAAA,MAC5B;AAAA,IACF;AAAA,EA1rBA;AAAA,EAEA,IAAI,kBAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAA2B;AAxIjC;AAyII,YAAO,UAAK,SAAL,mBAAW;AAAA,EACpB;AAAA,EAEA,IAAI,WAA+B;AA5IrC;AA6II,YAAO,UAAK,SAAL,mBAAW;AAAA,EACpB;AAAA,EAEA,IAAI,cAAuB;AACzB,WAAO,KAAK,aAAa,UAAa,KAAK,mBAAmB,yCAAgB;AAAA,EAChF;AAAA;AAAA,EAGA,IAAI,QAA4B;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,IAAI,YAAgC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAA0B;AAzKlC;AA0KI,QAAI,CAAC,KAAK,aAAa;AACrB,aAAO;AAAA,IACT;AACA,UAAI,UAAK,SAAL,mBAAW,QAAO,KAAK,KAAK,QAAQ,IAAI;AAC1C,aAAO,KAAK,KAAK;AAAA,IACnB;AACA,QAAI,CAAC,KAAK,YAAY;AACpB,WAAK,aAAa,IAAI,QAAgB,CAAC,SAAS,WAAW;AACzD,cAAM,mBAAmB,MAAM;AAC7B,eAAK,IAAI,uCAA0B,gBAAgB;AACnD,eAAK,aAAa;AAClB,iBAAO,uDAAuD;AAAA,QAChE;AACA,cAAM,mBAAmB,CAAC,QAAgB;AACxC,cAAI,QAAQ,IAAI;AACd,iBAAK,IAAI,uCAA0B,gBAAgB;AACnD,iBAAK,IAAI,mCAA+B,gBAAgB;AACxD,iBAAK,aAAa;AAClB,oBAAQ,GAAG;AAAA,UACb;AAAA,QACF;AACA,aAAK,GAAG,uCAA0B,gBAAgB;AAClD,aAAK,KAAK,mCAAwB,gBAAgB;AAAA,MACpD,CAAC;AAAA,IACH;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,cAAc;AAClB,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAEA,UAAM,YAAY,4BAAU,SAAS,sBAAsB;AAC3D,UAAM,YAAY,4BAAU,SAAS;AAAA,MACnC,CAAC,OACC,GAAG,QAAQ,SAAS,qBAAqB,GAAG,QAAQ,MAAM,YAAY;AAAA,MACxE,EAAE,QAAQ,KAAK,qBAAqB,OAAO;AAAA,IAC7C;AACA,gCAAU,SAAS,QAAiC;AAAA,MAClD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY,KAAK,UAAU;AAAA,UAC3B,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,KAAK,MAAM;AACjB,QAAI,GAAG,QAAQ,SAAS,SAAS;AAC/B,YAAM,IAAI,MAAM,GAAG,QAAQ,KAAK;AAAA,IAClC,WAAW,GAAG,QAAQ,SAAS,UAAU;AACvC,aAAO,GAAG,QAAQ;AAAA,IACpB,OAAO;AACL,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,IAAI,kBAA0B;AApOhC;AAqOI,aAAO,UAAK,SAAL,mBAAW,oBAAmB;AAAA,EACvC;AAAA,EAEA,IAAI,gBAAwB;AAxO9B;AAyOI,aAAO,UAAK,SAAL,mBAAW,kBAAiB;AAAA,EACrC;AAAA,EAEA,IAAI,eAAqB;AA5O3B;AAgPI,QAAI,iBAAiB,SAAO,UAAK,SAAL,mBAAW,iBAAgB,CAAC;AACxD,QAAI,iBAAiB,KAAK,iBAAiB,MAAM;AAC/C,wBAAkB;AAAA,IACpB;AACA,WAAO,IAAI,KAAK,cAAc;AAAA,EAChC;AAAA,EAEA,IAAI,cAAuB;AAvP7B;AAwPI,aAAO,UAAK,SAAL,mBAAW,oBAAmB;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,mBAA2B;AA/PjC;AAgQI,aAAO,UAAK,SAAL,mBAAW,qBAAoB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,eAAuB;AAtQ7B;AAuQI,aAAO,UAAK,SAAL,mBAAW,iBAAgB;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,KAAa,OAAe,MAAoB;AAC5D,UAAM,UAAU,EAAE,GAAG,oBAAoB,GAAG,KAAK;AACjD,UAAM,cAAc,QAAQ,cAAc,QAAQ;AAClD,UAAM,cAAc,QAAQ,aACxB,EAAE,GAAG,gCAAoB,GAAG,QAAQ,WAAW,IAC/C,EAAE,GAAG,gCAAoB,GAAG,QAAQ,KAAK;AAE7C,UAAM,MAAM,IAAI,wCAAe;AAAA,MAC7B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,gCAAU,SAAS,GAAG,iCAAe,UAAU,KAAK,UAAU;AAE9D,QAAI;AACF,YAAM,MAAM,4BAAU,SAAS,QAAyB;AAAA,QACtD,SAAS;AAAA,UACP,MAAM;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AAED,YAAM,KAAK,MAAM,4BAAU,SAAS,QAAyB,CAAC,OAAiB;AAC7E,eAAO,GAAG,QAAQ,QAAQ,aAAa,GAAG,QAAQ,MAAM,WAAW,IAAI;AAAA,MACzE,CAAC;AAED,qBAAI,MAAM,2BAA2B;AAErC,cAAQ,GAAG,QAAQ,MAAM;AAAA,QACvB,KAAK;AACH,eAAK,YAAY,IAAI,4BAAU,GAAG,QAAQ,MAAM,KAAM,OAAQ,EAAG;AACjE,eAAK,cAAc,eAAe,IAAI,wBAAY,KAAK,UAAU,QAAQ,WAAW;AAEpF,eAAK,SAAS;AACd,eAAK,aAAa;AAClB,eAAK,OAAO,GAAG,QAAQ,MAAM,KAAM;AAGnC,eAAK,uBAAuB,IAAI,gBAAgB;AAChD,eAAK,eAAe;AACpB,eAAK,mBAAmB,IAAI;AAAA,YAC1B,GAAG,QAAQ,MAAM;AAAA,YACjB,KAAK;AAAA,YACL,KAAK,qBAAqB;AAAA,UAC5B;AAEA,qBAAW,MAAM,GAAG,QAAQ,MAAM,cAAc;AAC9C,kBAAM,KAAK,KAAK,wBAAwB,GAAG,WAAY;AAEvD,uBAAW,OAAO,GAAG,cAAc;AACjC,oBAAM,cAAc,IAAI,gDAAuB,GAAG;AAClD,iBAAG,kBAAkB,IAAI,YAAY,KAAM,WAAW;AAAA,YACxD;AAAA,UACF;AACA,eAAK,sBAAsB,yCAAgB,cAAc;AAEzD,sCAAU,SAAS,QAAmC;AAAA,YACpD,SAAS;AAAA,cACP,MAAM;AAAA,cACN,OAAO;AAAA,gBACL,YAAY,KAAK,UAAU;AAAA,cAC7B;AAAA,YACF;AAAA,UACF,CAAC;AACD;AAAA,QACF,KAAK;AAAA,QACL;AACE,gBAAM,IAAI,aAAa,GAAG,QAAQ,SAAS,EAAE;AAAA,MACjD;AAAA,IACF,SAAS,GAAG;AACV,kCAAU,SAAS,IAAI,iCAAe,UAAU,KAAK,UAAU;AAC/D,WAAK,mBAAmB,CAAC;AACzB,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa;AAlWrB;AAmWI,QAAI,CAAC,KAAK,aAAa;AACrB;AAAA,IACF;AAEA,UAAM,MAAM,4BAAU,SAAS,QAA4B;AAAA,MACzD,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,UACL,aAAY,UAAK,cAAL,mBAAgB;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,4BAAU,SAAS,QAA4B,CAAC,OAAiB;AACrE,aAAO,GAAG,QAAQ,QAAQ,gBAAgB,GAAG,QAAQ,MAAM,WAAW,IAAI;AAAA,IAC5E,CAAC;AAED,SAAK,oBAAoB,0CAAiB,gBAAgB;AAC1D,gCAAU,SAAS,eAAe,iCAAe,UAAU,KAAK,UAAU;AAE1E,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,UAA+C;AACpE,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AACA,UAAM,MAAM,4BAAU,SAAS,QAAkC;AAAA,MAC/D,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY,KAAK,UAAU;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,KAAK,MAAM,4BAAU,SAAS;AAAA,MAClC,CAAC,OACC,GAAG,QAAQ,SAAS,sBAAsB,GAAG,QAAQ,MAAM,YAAY,IAAI;AAAA,MAC7E,EAAE,QAAQ,KAAK,qBAAqB,OAAO;AAAA,IAC7C;AACA,QAAI,GAAG,OAAO;AACZ,YAAM,IAAI,MAAM,4BAA4B,GAAG,KAAK,EAAE;AAAA,IACxD;AAAA,EACF;AAAA,EAEQ,sBAAsB,UAA2B;AACvD,QAAI,KAAK,qBAAqB,UAAU;AACtC;AAAA,IACF;AACA,SAAK,mBAAmB;AACxB,SAAK,KAAK,uDAAkC,KAAK,gBAAgB;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,SAA2B,0CAAiB,kBAAkB;AACxF,QAAI,KAAK,aAAc;AACvB,SAAK,eAAe;AAOpB,eAAW,CAAC,EAAE,gBAAgB,KAAK,KAAK,uBAAuB;AAC7D,UAAI;AACF,yBAAiB,WAAW,MAAM,IAAI,MAAM,8BAA8B,CAAC;AAAA,MAC7E,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,sBAAsB,MAAM;AAEjC,eAAW,CAAC,EAAE,gBAAgB,KAAK,KAAK,uBAAuB;AAC7D,UAAI;AACF,yBAAiB,WAAW,MAAM,IAAI,MAAM,8BAA8B,CAAC;AAAA,MAC7E,QAAQ;AAAA,MAER;AAAA,IACF;AACA,SAAK,sBAAsB,MAAM;AAIjC,SAAK,aAAa;AAIlB,SAAK,qBAAqB,MAAM;AAEhC,SAAK,sBAAsB,yCAAgB,iBAAiB;AAC5D,SAAK,KAAK,mCAAwB,MAAM;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,0BAA0B,OAAe,UAA6B;AACpE,QAAI,KAAK,mBAAmB,IAAI,KAAK,GAAG;AACtC,YAAM,IAAI,MAAM,oCAAoC,KAAK,yBAAyB;AAAA,IACpF;AACA,SAAK,mBAAmB,IAAI,OAAO,QAAQ;AAAA,EAC7C;AAAA,EAEA,4BAA4B,OAAe;AACzC,SAAK,mBAAmB,OAAO,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,0BAA0B,OAAe,UAA6B;AACpE,QAAI,KAAK,mBAAmB,IAAI,KAAK,GAAG;AACtC,YAAM,IAAI,MAAM,oCAAoC,KAAK,yBAAyB;AAAA,IACpF;AACA,SAAK,mBAAmB,IAAI,OAAO,QAAQ;AAAA,EAC7C;AAAA,EAEA,4BAA4B,OAAe;AACzC,SAAK,mBAAmB,OAAO,KAAK;AAAA,EACtC;AAAA,EAkVQ,8BAA8B,UAA2C;AA9zBnF;AA+zBI,UAAI,UAAK,qBAAL,mBAAuB,cAAa,UAAU;AAChD,aAAO,KAAK;AAAA,IACd,OAAO;AACL,aAAO,KAAK,mBAAmB,IAAI,QAAQ;AAAA,IAC7C;AAAA,EACF;AAAA,EAEQ,6BAA6B,UAA+B;AAt0BtE;AAu0BI,UAAI,UAAK,qBAAL,mBAAuB,cAAa,UAAU;AAChD,aAAO,KAAK;AAAA,IACd,WAAW,KAAK,mBAAmB,IAAI,QAAQ,GAAG;AAChD,aAAO,KAAK,mBAAmB,IAAI,QAAQ;AAAA,IAC7C,OAAO;AACL,YAAM,IAAI,UAAU,eAAe,QAAQ,YAAY;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,yBAAyB,UAAkB;AACjD,UAAM,cAAc,KAAK,mBAAmB,IAAI,QAAQ;AACxD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,UAAU,eAAe,QAAQ,YAAY;AAAA,IACzD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,gCAAgC,UAAkB,UAAkB;AAC1E,UAAM,cAAc,KAAK,6BAA6B,QAAQ;AAC9D,UAAM,cAAc,YAAY,kBAAkB,IAAI,QAAQ;AAC9D,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,UAAU,eAAe,QAAQ,YAAY;AAAA,IACzD;AACA,WAAO,EAAE,aAAa,YAAY;AAAA,EACpC;AAAA,EAEQ,sCAAsC,UAAkB,UAAkB;AAChF,UAAM,cAAc,KAAK,yBAAyB,QAAQ;AAC1D,UAAM,cAAc,YAAY,kBAAkB,IAAI,QAAQ;AAC9D,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,UAAU,eAAe,QAAQ,YAAY;AAAA,IACzD;AACA,WAAO,EAAE,aAAa,YAAY;AAAA,EACpC;AAAA,EAEQ,wBAAwB,WAA6B;AAC3D,QAAI,KAAK,mBAAmB,IAAI,UAAU,KAAM,QAAS,GAAG;AAC1D,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,UAAM,cAAc,IAAI,qCAAkB,SAAS;AACnD,SAAK,mBAAmB,IAAI,UAAU,KAAM,UAAW,WAAW;AAClE,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,cAAiC,qBAA6B;AACvF,QAAI,aAAa,cAAc,SAAS,cAAc;AACpD,YAAM,wBAAwB,KAAK,mBAAmB,IAAI,aAAa,SAAS,EAAE;AAElF,UAAI,CAAC,uBAAuB;AAC1B,uBAAI;AAAA,UACF;AAAA,UACA,aAAa,SAAS;AAAA,QACxB;AACA;AAAA,MACF;AACA,UAAI;AACJ,YAAM,SAAS,IAAI,eAAe;AAAA,QAChC,OAAO,CAAC,eAAe;AACrB,6BAAmB;AACnB,eAAK,sBAAsB,IAAI,aAAa,UAAW;AAAA,YACrD,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,WAAW,KAAK,IAAI;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AACD,YAAM,OAAuB;AAAA,QAC3B,UAAU,aAAa;AAAA,QACvB,MAAM,aAAa,cAAc,MAAM,QAAQ;AAAA,QAC/C,UAAU,aAAa;AAAA,QACvB,WAAW,aAAa,cAAc,OAAO,aAAa,WAAW,IAAI;AAAA,QACzE,OAAO,aAAa;AAAA,QACpB,eAAW,6BAAe,aAAa,SAAU;AAAA,QACjD,YAAY,aAAa;AAAA,MAC3B;AACA;AAAA,QACE,IAAI,sCAAiB,MAAM,YAAQ,6BAAe,aAAa,WAAW,CAAC;AAAA,QAC3E,EAAE,UAAU,oBAAoB;AAAA,MAClC;AAAA,IACF,WAAW,aAAa,cAAc,SAAS,cAAc;AAC3D,YAAM,wBAAwB,KAAK,mBAAmB,IAAI,aAAa,SAAS,EAAE;AAElF,UAAI,CAAC,uBAAuB;AAC1B,uBAAI;AAAA,UACF;AAAA,UACA,aAAa,SAAS;AAAA,QACxB;AACA;AAAA,MACF;AACA,UAAI;AACJ,YAAM,SAAS,IAAI,eAAiC;AAAA,QAClD,OAAO,CAAC,eAAe;AACrB,6BAAmB;AACnB,eAAK,sBAAsB,IAAI,aAAa,UAAW;AAAA,YACrD,QAAQ;AAAA,YACR,YAAY;AAAA,YACZ,WAAW,KAAK,IAAI;AAAA,UACtB,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AACD,YAAM,OAAuB;AAAA,QAC3B,UAAU,aAAa;AAAA,QACvB,UAAU,aAAa;AAAA,QACvB,WAAW,aAAa,cAAc,OAAO,aAAa,WAAW,IAAI;AAAA,QACzE,OAAO,aAAa;AAAA,QACpB,WAAW,OAAO,aAAa,SAAS;AAAA,QACxC,YAAY,aAAa;AAAA,MAC3B;AACA;AAAA,QACE,IAAI,sCAAiB,MAAM,YAAQ,6BAAe,aAAa,WAAW,CAAC;AAAA,QAC3E,EAAE,UAAU,oBAAoB;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAAyB;AACjD,UAAM,aAAa,KAAK,sBAAsB,IAAI,MAAM,QAAS;AACjE,QAAI,YAAY;AACd,UAAI,MAAM,QAAS,SAAS,GAAG;AAC7B,mBAAW,WAAW,QAAQ,KAAK;AAAA,MACrC;AAAA,IACF;AACA,UAAM,aAAa,KAAK,sBAAsB,IAAI,MAAM,QAAS;AACjE,QAAI,YAAY;AACd,UAAI,MAAM,QAAS,SAAS,GAAG;AAC7B,mBAAW,WAAW,QAAQ,KAAK;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAAoB,SAA6B;AACvD,UAAM,WAAW,QAAQ;AACzB,UAAM,aAAa,KAAK,sBAAsB,IAAI,QAAQ;AAC1D,QAAI,YAAY;AACd,iBAAW,WAAW,MAAM;AAC5B,WAAK,sBAAsB,OAAO,QAAQ;AAAA,IAC5C;AACA,UAAM,aAAa,KAAK,sBAAsB,IAAI,QAAQ;AAC1D,QAAI,YAAY;AACd,iBAAW,WAAW,MAAM;AAC5B,WAAK,sBAAsB,OAAO,QAAQ;AAAA,IAC5C;AAAA,EACF;AACF;AAEO,MAAM,qBAAqB,MAAM;AAAA,EACtC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAAA,EACf;AACF;AA0EO,IAAK,YAAL,kBAAKC,eAAL;AACL,EAAAA,WAAA,0BAAuB;AACvB,EAAAA,WAAA,6BAA0B;AAC1B,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,2BAAwB;AACxB,EAAAA,WAAA,2BAAwB;AACxB,EAAAA,WAAA,0BAAuB;AACvB,EAAAA,WAAA,oBAAiB;AACjB,EAAAA,WAAA,sBAAmB;AACnB,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,uBAAoB;AACpB,EAAAA,WAAA,6BAA0B;AAC1B,EAAAA,WAAA,gBAAa;AACb,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,2BAAwB;AACxB,EAAAA,WAAA,yBAAsB;AACtB,EAAAA,WAAA,oBAAiB;AACjB,EAAAA,WAAA,gCAA6B;AAC7B,EAAAA,WAAA,4BAAyB;AACzB,EAAAA,WAAA,kCAA+B;AAC/B,EAAAA,WAAA,wCAAqC;AACrC,EAAAA,WAAA,8BAA2B;AAC3B,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,qBAAkB;AAClB,EAAAA,WAAA,4BAAyB;AACzB,EAAAA,WAAA,eAAY;AACZ,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,kBAAe;AACf,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,iBAAc;AACd,EAAAA,WAAA,WAAQ;AACR,EAAAA,WAAA,oBAAiB;AAjCP,SAAAA;AAAA,GAAA;","names":["import_rtc_ffi_bindings","FfiRoomOptions","EventEmitter","RoomEvent"]}
|
|
1
|
+
{"version":3,"sources":["../src/room.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2024 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { Mutex } from '@livekit/mutex';\nimport { EncryptionState, type EncryptionType } from '@livekit/rtc-ffi-bindings';\nimport type {\n FfiEvent,\n GetSessionStatsCallback,\n GetSessionStatsResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport { DisconnectReason, type OwnedParticipant } from '@livekit/rtc-ffi-bindings';\nimport type {\n DataStream_Trailer,\n DisconnectCallback,\n TrackPublicationInfo,\n} from '@livekit/rtc-ffi-bindings';\nimport {\n type ConnectCallback,\n ConnectRequest,\n type ConnectResponse,\n type ConnectionQuality,\n ConnectionState,\n ContinualGatheringPolicy,\n type DataPacketKind,\n type DataStream_Chunk,\n type DataStream_Header,\n type DisconnectResponse,\n RoomOptions as FfiRoomOptions,\n type IceServer,\n IceTransportType,\n type ReadyForRoomEventResponse,\n type RoomInfo,\n type SimulateScenarioCallback,\n type SimulateScenarioKind,\n type SimulateScenarioResponse,\n} from '@livekit/rtc-ffi-bindings';\nimport { TrackKind } from '@livekit/rtc-ffi-bindings';\nimport type { TypedEventEmitter as TypedEmitter } from '@livekit/typed-emitter';\nimport EventEmitter from 'events';\nimport { ByteStreamReader, TextStreamReader } from './data_streams/stream_reader.js';\nimport type {\n ByteStreamHandler,\n ByteStreamInfo,\n StreamController,\n TextStreamHandler,\n TextStreamInfo,\n} from './data_streams/types.js';\nimport type { E2EEOptions } from './e2ee.js';\nimport { E2EEManager, defaultE2EEOptions } from './e2ee.js';\nimport { FfiClient, FfiClientEvent, FfiHandle } from './ffi_client.js';\nimport { log } from './log.js';\nimport type { Participant } from './participant.js';\nimport { LocalParticipant, RemoteParticipant } from './participant.js';\nimport type { LocalTrack, RemoteTrack } from './track.js';\nimport { RemoteAudioTrack, RemoteVideoTrack } from './track.js';\nimport type { LocalTrackPublication, TrackPublication } from './track_publication.js';\nimport { RemoteTrackPublication } from './track_publication.js';\nimport type { ChatMessage } from './types.js';\nimport { bigIntToNumber } from './utils.js';\n\nexport interface RtcConfiguration {\n iceTransportType: IceTransportType;\n continualGatheringPolicy: ContinualGatheringPolicy;\n iceServers: IceServer[];\n}\n\nexport const defaultRtcConfiguration: RtcConfiguration = {\n iceTransportType: IceTransportType.TRANSPORT_ALL,\n continualGatheringPolicy: ContinualGatheringPolicy.GATHER_CONTINUALLY,\n iceServers: [],\n};\n\nexport interface RoomOptions {\n autoSubscribe: boolean;\n dynacast: boolean;\n /**\n * @deprecated Use `encryption` instead. See x for details\n */\n e2ee?: E2EEOptions;\n encryption?: E2EEOptions;\n rtcConfig?: RtcConfiguration;\n}\n\nexport const defaultRoomOptions = new FfiRoomOptions({\n autoSubscribe: true,\n dynacast: false,\n e2ee: undefined,\n encryption: undefined,\n rtcConfig: undefined,\n adaptiveStream: false,\n joinRetries: 1,\n});\n\nexport class Room extends (EventEmitter as new () => TypedEmitter<RoomCallbacks>) {\n private info?: RoomInfo;\n private ffiHandle?: FfiHandle;\n /**\n * used to ensure events are processed sequentially and allow for\n * the local participant to acquire the lock while doing state updates related to FFI events\n * before processing the next events\n */\n private ffiEventLock = new Mutex();\n\n private byteStreamControllers = new Map<string, StreamController<DataStream_Chunk>>();\n private textStreamControllers = new Map<string, StreamController<DataStream_Chunk>>();\n private byteStreamHandlers = new Map<string, ByteStreamHandler>();\n private textStreamHandlers = new Map<string, TextStreamHandler>();\n\n private preConnectEvents: FfiEvent[] = [];\n\n // Aborted on disconnect to cancel any pending FfiClient.waitFor() listeners,\n // preventing them from leaking when the room goes away.\n private disconnectController = new AbortController();\n\n // Guards cleanupOnDisconnect so the ConnectionStateChanged/Disconnected\n // events fire exactly once, no matter which path (explicit disconnect()\n // vs. FFI 'disconnected' event) wins the race.\n private hasCleanedUp = false;\n\n private _token?: string;\n private _serverUrl?: string;\n private _connectionState: ConnectionState = ConnectionState.CONN_DISCONNECTED;\n\n e2eeManager?: E2EEManager;\n\n remoteParticipants: Map<string, RemoteParticipant> = new Map();\n localParticipant?: LocalParticipant;\n\n constructor() {\n super();\n }\n\n get connectionState() {\n return this._connectionState;\n }\n\n get name(): string | undefined {\n return this.info?.name;\n }\n\n get metadata(): string | undefined {\n return this.info?.metadata;\n }\n\n get isConnected(): boolean {\n return this.ffiHandle != undefined && this.connectionState != ConnectionState.CONN_DISCONNECTED;\n }\n\n /** @internal */\n get token(): string | undefined {\n return this._token;\n }\n\n /** @internal */\n get serverUrl(): string | undefined {\n return this._serverUrl;\n }\n\n // Shared promise for concurrent getSid() callers. Without this, each call\n // registers its own RoomSidChanged + Disconnected listeners, and if many\n // calls race only one of each pair is cleaned up — leaking the rest.\n private sidPromise?: Promise<string>;\n\n /**\n * Gets the room's server ID. This ID is assigned by the LiveKit server\n * and is unique for each room session.\n * SID is assigned asynchronously after connection.\n * @returns Promise that resolves to the room's server ID, or empty string if not connected\n */\n async getSid(): Promise<string> {\n if (!this.isConnected) {\n return '';\n }\n if (this.info?.sid && this.info.sid !== '') {\n return this.info.sid;\n }\n if (!this.sidPromise) {\n this.sidPromise = new Promise<string>((resolve, reject) => {\n const handleDisconnect = () => {\n this.off(RoomEvent.RoomSidChanged, handleRoomUpdate);\n this.sidPromise = undefined;\n reject('Room disconnected before room server id was available');\n };\n const handleRoomUpdate = (sid: string) => {\n if (sid !== '') {\n this.off(RoomEvent.RoomSidChanged, handleRoomUpdate);\n this.off(RoomEvent.Disconnected as any, handleDisconnect);\n this.sidPromise = undefined;\n resolve(sid);\n }\n };\n this.on(RoomEvent.RoomSidChanged, handleRoomUpdate);\n this.once(RoomEvent.Disconnected, handleDisconnect);\n });\n }\n return this.sidPromise;\n }\n\n async getRtcStats() {\n if (!this.isConnected || !this.ffiHandle) {\n throw new Error('getRtcStats requires a connected room');\n }\n // subscribe before issuing the request\n const requestId = FfiClient.instance.getNextRequestAsyncId();\n const cbPromise = FfiClient.instance.waitFor<GetSessionStatsCallback>(\n (ev: FfiEvent) =>\n ev.message.case === 'getSessionStats' && ev.message.value.asyncId === requestId,\n { signal: this.disconnectController.signal },\n );\n FfiClient.instance.request<GetSessionStatsResponse>({\n message: {\n case: 'getSessionStats',\n value: {\n roomHandle: this.ffiHandle.handle,\n requestAsyncId: requestId,\n },\n },\n });\n const cb = await cbPromise;\n if (cb.message.case === 'error') {\n throw new Error(cb.message.value);\n } else if (cb.message.case === 'result') {\n return cb.message.value;\n } else {\n throw new Error('could not retrieve rtc stats');\n }\n }\n\n get numParticipants(): number {\n return this.info?.numParticipants ?? 0;\n }\n\n get numPublishers(): number {\n return this.info?.numPublishers ?? 0;\n }\n\n get creationTime(): Date {\n // TODO: workaround for Rust SDK bug, remove after updating to:\n // https://github.com/livekit/rust-sdks/pull/822\n // check if creationTime looks like seconds (less than year 3000 in ms), convert to ms if needed\n let creationTimeMs = Number(this.info?.creationTime ?? 0);\n if (creationTimeMs > 0 && creationTimeMs < 1e12) {\n creationTimeMs *= 1000;\n }\n return new Date(creationTimeMs);\n }\n\n get isRecording(): boolean {\n return this.info?.activeRecording ?? false;\n }\n\n /**\n * The time in seconds after which a room will be closed after the last\n * participant has disconnected.\n */\n get departureTimeout(): number {\n return this.info?.departureTimeout ?? 0;\n }\n\n /**\n * The time in seconds after which an empty room will be automatically closed.\n */\n get emptyTimeout(): number {\n return this.info?.emptyTimeout ?? 0;\n }\n\n /**\n * Connects to a LiveKit room using the provided URL and access token.\n * @param url - The WebSocket URL of the LiveKit server\n * @param token - A valid LiveKit access token for authentication\n * @param opts - Optional room configuration options\n * @throws ConnectError - if connection fails\n */\n async connect(url: string, token: string, opts?: RoomOptions) {\n const options = { ...defaultRoomOptions, ...opts };\n const e2eeEnabled = options.encryption || options.e2ee;\n const e2eeOptions = options.encryption\n ? { ...defaultE2EEOptions, ...options.encryption }\n : { ...defaultE2EEOptions, ...options.e2ee };\n\n const req = new ConnectRequest({\n url: url,\n token: token,\n options,\n });\n\n FfiClient.instance.on(FfiClientEvent.FfiEvent, this.onFfiEvent);\n\n try {\n const res = FfiClient.instance.request<ConnectResponse>({\n message: {\n case: 'connect',\n value: req,\n },\n });\n\n const cb = await FfiClient.instance.waitFor<ConnectCallback>((ev: FfiEvent) => {\n return ev.message.case == 'connect' && ev.message.value.asyncId == res.asyncId;\n });\n\n log.debug('Connect callback received');\n\n switch (cb.message.case) {\n case 'result':\n this.ffiHandle = new FfiHandle(cb.message.value.room!.handle!.id!);\n this.e2eeManager = e2eeEnabled && new E2EEManager(this.ffiHandle.handle, e2eeOptions);\n\n this._token = token;\n this._serverUrl = url;\n this.info = cb.message.value.room!.info;\n // Reset the abort controller for this connection session so that\n // a previous disconnect doesn't immediately cancel new operations.\n this.disconnectController = new AbortController();\n this.hasCleanedUp = false;\n this.localParticipant = new LocalParticipant(\n cb.message.value.localParticipant!,\n this.ffiEventLock,\n this.disconnectController.signal,\n );\n\n for (const pt of cb.message.value.participants) {\n const rp = this.createRemoteParticipant(pt.participant!);\n\n for (const pub of pt.publications) {\n const publication = new RemoteTrackPublication(pub);\n rp.trackPublications.set(publication.sid!, publication);\n }\n }\n this.updateConnectionState(ConnectionState.CONN_CONNECTED);\n // Release the FFI room event gate after our listener and local state are ready.\n FfiClient.instance.request<ReadyForRoomEventResponse>({\n message: {\n case: 'readyForRoomEvent',\n value: {\n roomHandle: this.ffiHandle.handle,\n },\n },\n });\n break;\n case 'error':\n default:\n throw new ConnectError(cb.message.value || '');\n }\n } catch (e) {\n FfiClient.instance.off(FfiClientEvent.FfiEvent, this.onFfiEvent);\n this.preConnectEvents = [];\n throw e;\n }\n }\n\n /**\n * Disconnects from the room and cleans up all resources.\n * This will stop all tracks and close the connection.\n */\n async disconnect() {\n if (!this.isConnected) {\n return;\n }\n\n const res = FfiClient.instance.request<DisconnectResponse>({\n message: {\n case: 'disconnect',\n value: {\n roomHandle: this.ffiHandle?.handle,\n },\n },\n });\n\n await FfiClient.instance.waitFor<DisconnectCallback>((ev: FfiEvent) => {\n return ev.message.case == 'disconnect' && ev.message.value.asyncId == res.asyncId;\n });\n\n this.cleanupOnDisconnect(DisconnectReason.CLIENT_INITIATED);\n FfiClient.instance.removeListener(FfiClientEvent.FfiEvent, this.onFfiEvent);\n\n this.removeAllListeners();\n }\n\n /**\n * Trigger a reconnection / chaos scenario for testing. Most useful in\n * tests to deterministically force a Resume (signal-only reconnect that\n * preserves the PeerConnection and existing publications) or a full\n * reconnect (the SDK rebuilds the RtcSession and re-publishes existing\n * local tracks; `RoomEvent.Reconnected` fires).\n */\n async simulateScenario(scenario: SimulateScenarioKind): Promise<void> {\n if (!this.isConnected || !this.ffiHandle) {\n throw new Error('simulateScenario requires a connected room');\n }\n const res = FfiClient.instance.request<SimulateScenarioResponse>({\n message: {\n case: 'simulateScenario',\n value: {\n roomHandle: this.ffiHandle.handle,\n scenario,\n },\n },\n });\n const cb = await FfiClient.instance.waitFor<SimulateScenarioCallback>(\n (ev: FfiEvent) =>\n ev.message.case === 'simulateScenario' && ev.message.value.asyncId === res.asyncId,\n { signal: this.disconnectController.signal },\n );\n if (cb.error) {\n throw new Error(`simulateScenario failed: ${cb.error}`);\n }\n }\n\n private updateConnectionState(newState: ConnectionState) {\n if (this._connectionState === newState) {\n return;\n }\n this._connectionState = newState;\n this.emit(RoomEvent.ConnectionStateChanged, this._connectionState);\n }\n\n // Runs at most once per connection session. The FFI layer and explicit\n // disconnect() both race to get here — whichever wins emits the events,\n // the other is a no-op. A reconnect via connect() clears hasCleanedUp.\n private cleanupOnDisconnect(reason: DisconnectReason = DisconnectReason.CLIENT_INITIATED) {\n if (this.hasCleanedUp) return;\n this.hasCleanedUp = true;\n\n // Error all in-progress stream controllers to prevent FD leaks.\n // Streams that were receiving data but never got a trailer (e.g. the sender\n // disconnected mid-transfer) would otherwise keep their ReadableStream open\n // indefinitely, leaking the underlying controller and any buffered chunks.\n // Using error() instead of close() signals an abnormal termination to consumers.\n for (const [, streamController] of this.byteStreamControllers) {\n try {\n streamController.controller.error(new Error('Disconnected while receiving'));\n } catch {\n // controller may already be closed or errored\n }\n }\n this.byteStreamControllers.clear();\n\n for (const [, streamController] of this.textStreamControllers) {\n try {\n streamController.controller.error(new Error('Disconnected while receiving'));\n } catch {\n // controller may already be closed or errored\n }\n }\n this.textStreamControllers.clear();\n\n // Detach every track from this room so attached FrameProcessors receive\n // onStreamInfoCleared/onCredentialsCleared and the tokenRefreshed listener\n // is removed. Otherwise a server-initiated disconnect leaves processors with\n // stale room context and the Room holding a strong ref to each Track's bound\n // listener until GC. setRoom(null) is idempotent, so this is safe even if a\n // track was already detached (e.g. via unsubscribe/unpublish).\n if (this.localParticipant) {\n for (const pub of this.localParticipant.trackPublications.values()) {\n pub.track?.setRoom(null);\n }\n }\n for (const participant of this.remoteParticipants.values()) {\n for (const pub of participant.trackPublications.values()) {\n pub.track?.setRoom(null);\n }\n }\n\n // Clear sidPromise before removing listeners so that a reconnect\n // doesn't return a stale, permanently-pending promise.\n this.sidPromise = undefined;\n // Abort all pending FfiClient.waitFor() listeners so they don't leak.\n // This causes any in-flight operations (publishData, publishTrack, etc.)\n // to reject and clean up their event listeners.\n this.disconnectController.abort();\n\n this.updateConnectionState(ConnectionState.CONN_DISCONNECTED);\n this.emit(RoomEvent.Disconnected, reason);\n }\n\n /**\n * Registers a handler for incoming text data streams on a specific topic.\n * Text streams are used for receiving structured text data from other participants.\n * @param topic - The topic to listen for text streams on\n * @param callback - Function to handle incoming text stream data\n * @throws Error - if a handler for this topic is already registered\n */\n registerTextStreamHandler(topic: string, callback: TextStreamHandler) {\n if (this.textStreamHandlers.has(topic)) {\n throw new Error(`A text stream handler for topic \"${topic}\" has already been set.`);\n }\n this.textStreamHandlers.set(topic, callback);\n }\n\n unregisterTextStreamHandler(topic: string) {\n this.textStreamHandlers.delete(topic);\n }\n\n /**\n * Registers a handler for incoming byte data streams on a specific topic.\n * Byte streams are used for receiving binary data like files from other participants.\n * @param topic - The topic to listen for byte streams on\n * @param callback - Function to handle incoming byte stream data\n * @throws Error - if a handler for this topic is already registered\n */\n registerByteStreamHandler(topic: string, callback: ByteStreamHandler) {\n if (this.byteStreamHandlers.has(topic)) {\n throw new Error(`A byte stream handler for topic \"${topic}\" has already been set.`);\n }\n this.byteStreamHandlers.set(topic, callback);\n }\n\n unregisterByteStreamHandler(topic: string) {\n this.byteStreamHandlers.delete(topic);\n }\n\n private onFfiEvent = async (ffiEvent: FfiEvent) => {\n const unlock = await this.ffiEventLock.lock();\n try {\n if (!this.localParticipant || !this.ffiHandle || !this.info) {\n this.preConnectEvents.push(ffiEvent);\n return;\n }\n\n // process preConnectEvents if we received the connectCallback after the events were queued\n for (const ev of this.preConnectEvents) {\n await this.processFfiEvent(ev);\n }\n this.preConnectEvents = [];\n\n await this.processFfiEvent(ffiEvent);\n } finally {\n unlock();\n }\n };\n\n private processFfiEvent = async (ffiEvent: FfiEvent) => {\n if (!this.localParticipant || !this.ffiHandle || !this.info) {\n throw new Error('processFfiEvent called before connect');\n }\n\n if (ffiEvent.message.case == 'rpcMethodInvocation') {\n if (\n ffiEvent.message.value.localParticipantHandle == this.localParticipant.ffi_handle.handle\n ) {\n this.localParticipant.handleRpcMethodInvocation(\n ffiEvent.message.value.invocationId!,\n ffiEvent.message.value.method!,\n ffiEvent.message.value.requestId!,\n ffiEvent.message.value.callerIdentity!,\n ffiEvent.message.value.payload!,\n ffiEvent.message.value.responseTimeoutMs!,\n );\n }\n return;\n } else if (\n ffiEvent.message.case != 'roomEvent' ||\n ffiEvent.message.value.roomHandle != this.ffiHandle.handle\n ) {\n return;\n }\n\n const ev = ffiEvent.message.value.message;\n if (process.env.LIVEKIT_DEBUG_LOG_ROOM_EVENTS) {\n console.log('Room event:', ev);\n }\n if (ev.case == 'participantConnected') {\n const participant = this.createRemoteParticipant(ev.value.info!);\n this.remoteParticipants.set(participant.identity!, participant);\n this.emit(RoomEvent.ParticipantConnected, participant);\n } else if (ev.case == 'participantDisconnected') {\n const participant = this.remoteParticipants.get(ev.value.participantIdentity!);\n if (participant) {\n this.remoteParticipants.delete(participant.identity);\n participant.info.disconnectReason = ev.value.disconnectReason;\n this.emit(RoomEvent.ParticipantDisconnected, participant);\n } else {\n log.warn(`RoomEvent.ParticipantDisconnected: Could not find participant`);\n }\n } else if (ev.case == 'localTrackPublished') {\n const publication = this.localParticipant.trackPublications.get(ev.value.trackSid!);\n if (publication?.track) {\n publication.track.setRoom(this);\n }\n this.emit(RoomEvent.LocalTrackPublished, publication!, this.localParticipant);\n } else if (ev.case == 'localTrackUnpublished') {\n const publication = this.localParticipant.trackPublications.get(ev.value.publicationSid!);\n const track = publication?.track;\n if (track) {\n track.setRoom(null);\n }\n this.localParticipant.trackPublications.delete(ev.value.publicationSid!);\n // Emit while `publication.track` is still set, preserving the pre-existing\n // payload for callbacks. The handler is synchronous, so nulling the track\n // right after still completes before any other turn can observe it.\n this.emit(RoomEvent.LocalTrackUnpublished, publication!, this.localParticipant!);\n // Mirror trackUnsubscribed: drop the publication's track reference. This\n // also makes unpublishTrack's own setRoom(null) a no-op when it loses the\n // race (its `pub.track` guard short-circuits), avoiding a redundant clear.\n if (track && publication) {\n publication.track = undefined;\n }\n } else if ((ev.case as string) == 'localTrackRepublished') {\n const value = (ev as any).value;\n const previousSid: string = value.previousSid!;\n const newInfo: TrackPublicationInfo = value.info!;\n const publication = this.localParticipant.trackPublications.get(previousSid);\n if (publication) {\n publication.updateInfo(newInfo);\n this.localParticipant.trackPublications.delete(previousSid);\n this.localParticipant.trackPublications.set(publication.sid!, publication);\n if (publication.track?.info) {\n // Keep the local-track invariant (track.sid == publication.sid, set at\n // publishTrack) intact across republish, then re-push metadata so any\n // attached FrameProcessor learns the new publication SID / credentials.\n // setRoom with the same room is a no-op for the tokenRefreshed listener\n // but re-fans the metadata to every registered AudioStream.\n publication.track.info.sid = publication.sid;\n publication.track.setRoom(this);\n }\n this.emit(RoomEvent.LocalTrackRepublished, publication, previousSid, this.localParticipant);\n } else {\n log.warn(`RoomEvent.LocalTrackRepublished: previous publication not found: ${previousSid}`);\n }\n } else if (ev.case == 'localTrackSubscribed') {\n const publication = this.localParticipant.trackPublications.get(ev.value.trackSid!);\n if (publication) {\n publication.resolveFirstSubscription();\n this.emit(RoomEvent.LocalTrackSubscribed, publication!.track!);\n } else {\n log.warn(`RoomEvent.LocalTrackSubscribed: Publication not found: ${ev.value.trackSid}`);\n }\n } else if (ev.case == 'trackPublished') {\n const participant = this.remoteParticipants.get(ev.value.participantIdentity!);\n const publication = new RemoteTrackPublication(ev.value.publication!);\n if (participant) {\n participant.trackPublications.set(publication.sid!, publication);\n } else {\n log.warn(\n `RoomEvent.TrackPublished: Could not find participant: ${ev.value.participantIdentity}`,\n );\n }\n this.emit(RoomEvent.TrackPublished, publication, participant!);\n } else if (ev.case == 'trackUnpublished') {\n const participant = this.requireRemoteParticipant(ev.value.participantIdentity!);\n const publication = participant.trackPublications.get(ev.value.publicationSid!);\n participant.trackPublications.delete(ev.value.publicationSid!);\n if (publication) {\n this.emit(RoomEvent.TrackUnpublished, publication, participant);\n // Dispose eagerly so handles don't accumulate when a participant\n // publishes and unpublishes many tracks during a long-lived session.\n publication.ffiHandle.dispose();\n } else {\n log.warn(`RoomEvent.TrackUnpublished: Could not find publication`);\n }\n } else if (ev.case == 'trackSubscribed') {\n const ownedTrack = ev.value.track!;\n const trackInfo = ownedTrack.info!;\n try {\n const { participant, publication } = this.requirePublicationOfRemoteParticipant(\n ev.value.participantIdentity!,\n trackInfo.sid!,\n );\n publication.subscribed = true;\n if (trackInfo.kind == TrackKind.KIND_VIDEO) {\n publication.track = new RemoteVideoTrack(ownedTrack);\n } else if (trackInfo.kind == TrackKind.KIND_AUDIO) {\n publication.track = new RemoteAudioTrack(ownedTrack);\n }\n publication.track?.setRoom(this);\n\n this.emit(RoomEvent.TrackSubscribed, publication.track!, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackSubscribed: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackUnsubscribed') {\n try {\n const { participant, publication } = this.requirePublicationOfRemoteParticipant(\n ev.value.participantIdentity!,\n ev.value.trackSid!,\n );\n const track = publication.track!;\n track.setRoom(null);\n publication.track = undefined;\n publication.subscribed = false;\n this.emit(RoomEvent.TrackUnsubscribed, track, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackUnsubscribed: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackSubscriptionFailed') {\n try {\n const participant = this.requireRemoteParticipant(ev.value.participantIdentity!);\n this.emit(\n RoomEvent.TrackSubscriptionFailed,\n ev.value.trackSid!,\n participant,\n ev.value.error,\n );\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackSubscriptionFailed: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackMuted') {\n try {\n const { participant, publication } = this.requirePublicationOfParticipant(\n ev.value.participantIdentity!,\n ev.value.trackSid!,\n );\n publication.info!.muted = true;\n if (publication.track) {\n publication.track.info!.muted = true;\n }\n this.emit(RoomEvent.TrackMuted, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackMuted: ${(e as Error).message}`);\n }\n } else if (ev.case == 'trackUnmuted') {\n try {\n const { participant, publication } = this.requirePublicationOfParticipant(\n ev.value.participantIdentity!,\n ev.value.trackSid!,\n );\n publication.info!.muted = false;\n if (publication.track) {\n publication.track.info!.muted = false;\n }\n this.emit(RoomEvent.TrackUnmuted, publication, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.TrackUnmuted: ${(e as Error).message}`);\n }\n } else if (ev.case == 'activeSpeakersChanged') {\n try {\n const activeSpeakers = ev.value.participantIdentities.map((identity) =>\n this.requireParticipantByIdentity(identity),\n );\n this.emit(RoomEvent.ActiveSpeakersChanged, activeSpeakers);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ActiveSpeakersChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'roomMetadataChanged') {\n this.info.metadata = ev.value.metadata ?? '';\n this.emit(RoomEvent.RoomMetadataChanged, this.info.metadata);\n } else if (ev.case == 'participantMetadataChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n participant.info.metadata = ev.value.metadata;\n this.emit(RoomEvent.ParticipantMetadataChanged, participant.metadata, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantMetadataChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'participantNameChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n participant.info.name = ev.value.name;\n this.emit(RoomEvent.ParticipantNameChanged, participant.name!, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantNameChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'participantAttributesChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n participant.info.attributes = ev.value.attributes.reduce(\n (acc, value) => {\n acc[value.key!] = value.value!;\n return acc;\n },\n {} as Record<string, string>,\n );\n if (Object.keys(ev.value.changedAttributes).length > 0) {\n const changedAttributes = ev.value.changedAttributes.reduce(\n (acc, value) => {\n acc[value.key!] = value.value!;\n return acc;\n },\n {} as Record<string, string>,\n );\n this.emit(RoomEvent.ParticipantAttributesChanged, changedAttributes, participant);\n }\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantAttributesChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'connectionQualityChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n this.emit(RoomEvent.ConnectionQualityChanged, ev.value.quality!, participant);\n } catch (e: unknown) {\n log.warn(`RoomEvent.ConnectionQualityChanged: ${(e as Error).message}`);\n }\n } else if (ev.case == 'chatMessage') {\n const participant = this.retrieveParticipantByIdentity(ev.value.participantIdentity!);\n const { id, message: messageText, timestamp, editTimestamp, generated } = ev.value.message!;\n const message: ChatMessage = {\n id: id!,\n message: messageText!,\n timestamp: Number(timestamp),\n editTimestamp: Number(editTimestamp),\n generated,\n };\n this.emit(RoomEvent.ChatMessage, message, participant);\n } else if (ev.case == 'dataPacketReceived') {\n // Can be undefined if the data is sent from a Server SDK\n const participant = this.remoteParticipants.get(ev.value.participantIdentity!);\n const dataPacket = ev.value.value;\n switch (dataPacket.case) {\n case 'user':\n const buffer = FfiClient.instance.copyBuffer(\n dataPacket.value.data!.data!.dataPtr!,\n Number(dataPacket.value.data!.data!.dataLen),\n );\n new FfiHandle(dataPacket.value.data!.handle!.id!).dispose();\n this.emit(\n RoomEvent.DataReceived,\n buffer,\n participant,\n ev.value.kind,\n dataPacket.value.topic,\n );\n break;\n case 'sipDtmf':\n const { code, digit } = dataPacket.value;\n this.emit(RoomEvent.DtmfReceived, code!, digit!, participant!);\n break;\n default:\n break;\n }\n } else if (ev.case == 'e2eeStateChanged') {\n if (ev.value.state == EncryptionState.INTERNAL_ERROR) {\n // throw generic error until Rust SDK is updated to supply the error alongside INTERNAL_ERROR\n this.emit(RoomEvent.EncryptionError, new Error('internal server error'));\n }\n } else if (ev.case == 'connectionStateChanged') {\n this.updateConnectionState(ev.value.state!);\n /*} else if (ev.case == 'connected') {\n this.emit(RoomEvent.Connected);*/\n } else if (ev.case == 'disconnected') {\n // cleanupOnDisconnect emits RoomEvent.Disconnected itself (guarded by\n // hasCleanedUp so it fires exactly once across both disconnect paths).\n this.cleanupOnDisconnect(ev.value.reason!);\n } else if (ev.case == 'reconnecting') {\n this.emit(RoomEvent.Reconnecting);\n } else if (ev.case == 'reconnected') {\n this.emit(RoomEvent.Reconnected);\n } else if (ev.case == 'roomSidChanged') {\n this.emit(RoomEvent.RoomSidChanged, ev.value.sid!);\n } else if (ev.case === 'streamHeaderReceived' && ev.value.header) {\n this.handleStreamHeader(ev.value.header, ev.value.participantIdentity!);\n } else if (ev.case === 'streamChunkReceived' && ev.value.chunk) {\n this.handleStreamChunk(ev.value.chunk);\n } else if (ev.case === 'streamTrailerReceived' && ev.value.trailer) {\n this.handleStreamTrailer(ev.value.trailer);\n } else if (ev.case === 'roomUpdated') {\n this.info = ev.value;\n this.emit(RoomEvent.RoomUpdated);\n } else if (ev.case === 'moved') {\n this.info = ev.value;\n this.emit(RoomEvent.Moved);\n } else if (ev.case === 'participantsUpdated') {\n for (const info of ev.value.participants) {\n const participant = this.retrieveParticipantByIdentity(info.identity!);\n if (participant) {\n participant.info = info;\n }\n }\n } else if (ev.case === 'participantEncryptionStatusChanged') {\n try {\n const participant = this.requireParticipantByIdentity(ev.value.participantIdentity!);\n this.emit(\n RoomEvent.ParticipantEncryptionStatusChanged,\n !!ev.value.isEncrypted,\n participant,\n );\n } catch (e: unknown) {\n log.warn(`RoomEvent.ParticipantEncryptionStatusChanged: ${(e as Error).message}`);\n }\n } else if (ev.case === 'tokenRefreshed') {\n this._token = ev.value.token;\n this.emit('tokenRefreshed');\n }\n };\n\n private retrieveParticipantByIdentity(identity: string): Participant | undefined {\n if (this.localParticipant?.identity === identity) {\n return this.localParticipant;\n } else {\n return this.remoteParticipants.get(identity);\n }\n }\n\n private requireParticipantByIdentity(identity: string): Participant {\n if (this.localParticipant?.identity === identity) {\n return this.localParticipant;\n } else if (this.remoteParticipants.has(identity)) {\n return this.remoteParticipants.get(identity)!;\n } else {\n throw new TypeError(`participant ${identity} not found`);\n }\n }\n\n private requireRemoteParticipant(identity: string) {\n const participant = this.remoteParticipants.get(identity);\n if (!participant) {\n throw new TypeError(`participant ${identity} not found`);\n }\n return participant;\n }\n\n private requirePublicationOfParticipant(identity: string, trackSid: string) {\n const participant = this.requireParticipantByIdentity(identity);\n const publication = participant.trackPublications.get(trackSid);\n if (!publication) {\n throw new TypeError(`publication ${trackSid} not found`);\n }\n return { participant, publication };\n }\n\n private requirePublicationOfRemoteParticipant(identity: string, trackSid: string) {\n const participant = this.requireRemoteParticipant(identity);\n const publication = participant.trackPublications.get(trackSid);\n if (!publication) {\n throw new TypeError(`publication ${trackSid} not found`);\n }\n return { participant, publication };\n }\n\n private createRemoteParticipant(ownedInfo: OwnedParticipant) {\n if (this.remoteParticipants.has(ownedInfo.info!.identity!)) {\n throw new Error('Participant already exists');\n }\n\n const participant = new RemoteParticipant(ownedInfo);\n this.remoteParticipants.set(ownedInfo.info!.identity!, participant);\n return participant;\n }\n\n private handleStreamHeader(streamHeader: DataStream_Header, participantIdentity: string) {\n if (streamHeader.contentHeader.case === 'byteHeader') {\n const streamHandlerCallback = this.byteStreamHandlers.get(streamHeader.topic ?? '');\n\n if (!streamHandlerCallback) {\n log.debug(\n 'ignoring incoming byte stream due to no handler for topic: %s',\n streamHeader.topic ?? 'undefined',\n );\n return;\n }\n let streamController: ReadableStreamDefaultController<DataStream_Chunk>;\n const stream = new ReadableStream({\n start: (controller) => {\n streamController = controller;\n this.byteStreamControllers.set(streamHeader.streamId!, {\n header: streamHeader,\n controller: streamController,\n startTime: Date.now(),\n });\n },\n });\n const info: ByteStreamInfo = {\n streamId: streamHeader.streamId!,\n name: streamHeader.contentHeader.value.name ?? 'unknown',\n mimeType: streamHeader.mimeType!,\n totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : undefined,\n topic: streamHeader.topic!,\n timestamp: bigIntToNumber(streamHeader.timestamp!),\n attributes: streamHeader.attributes,\n };\n streamHandlerCallback(\n new ByteStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)),\n { identity: participantIdentity },\n );\n } else if (streamHeader.contentHeader.case === 'textHeader') {\n const streamHandlerCallback = this.textStreamHandlers.get(streamHeader.topic ?? '');\n\n if (!streamHandlerCallback) {\n log.debug(\n 'ignoring incoming text stream due to no handler for topic: %s',\n streamHeader.topic ?? 'undefined',\n );\n return;\n }\n let streamController: ReadableStreamDefaultController<DataStream_Chunk>;\n const stream = new ReadableStream<DataStream_Chunk>({\n start: (controller) => {\n streamController = controller;\n this.textStreamControllers.set(streamHeader.streamId!, {\n header: streamHeader,\n controller: streamController,\n startTime: Date.now(),\n });\n },\n });\n const info: TextStreamInfo = {\n streamId: streamHeader.streamId!,\n mimeType: streamHeader.mimeType!,\n totalSize: streamHeader.totalLength ? Number(streamHeader.totalLength) : undefined,\n topic: streamHeader.topic!,\n timestamp: Number(streamHeader.timestamp),\n attributes: streamHeader.attributes,\n };\n streamHandlerCallback(\n new TextStreamReader(info, stream, bigIntToNumber(streamHeader.totalLength)),\n { identity: participantIdentity },\n );\n }\n }\n\n private handleStreamChunk(chunk: DataStream_Chunk) {\n const fileBuffer = this.byteStreamControllers.get(chunk.streamId!);\n if (fileBuffer) {\n if (chunk.content!.length > 0) {\n fileBuffer.controller.enqueue(chunk);\n }\n }\n const textBuffer = this.textStreamControllers.get(chunk.streamId!);\n if (textBuffer) {\n if (chunk.content!.length > 0) {\n textBuffer.controller.enqueue(chunk);\n }\n }\n }\n\n private handleStreamTrailer(trailer: DataStream_Trailer) {\n const streamId = trailer.streamId!;\n const fileBuffer = this.byteStreamControllers.get(streamId);\n if (fileBuffer) {\n fileBuffer.controller.close();\n this.byteStreamControllers.delete(streamId);\n }\n const textBuffer = this.textStreamControllers.get(streamId);\n if (textBuffer) {\n textBuffer.controller.close();\n this.textStreamControllers.delete(streamId);\n }\n }\n}\n\nexport class ConnectError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport type RoomCallbacks = {\n participantConnected: (participant: RemoteParticipant) => void;\n participantDisconnected: (participant: RemoteParticipant) => void;\n localTrackPublished: (publication: LocalTrackPublication, participant: LocalParticipant) => void;\n localTrackUnpublished: (\n publication: LocalTrackPublication,\n participant: LocalParticipant,\n ) => void;\n /**\n * Fired when the SDK auto-republished a local track during a full\n * reconnect. The publication object's identity is preserved (the same\n * instance is updated in place with the new server-assigned SIDs);\n * `previousSid` is provided for callers that key external state on the\n * old SID and need to reconcile.\n */\n localTrackRepublished: (\n publication: LocalTrackPublication,\n previousSid: string,\n participant: LocalParticipant,\n ) => void;\n localTrackSubscribed: (track: LocalTrack) => void;\n trackPublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;\n trackUnpublished: (publication: RemoteTrackPublication, participant: RemoteParticipant) => void;\n trackSubscribed: (\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ) => void;\n trackUnsubscribed: (\n track: RemoteTrack,\n publication: RemoteTrackPublication,\n participant: RemoteParticipant,\n ) => void;\n trackSubscriptionFailed: (\n trackSid: string,\n participant: RemoteParticipant,\n reason?: string,\n ) => void;\n trackMuted: (publication: TrackPublication, participant: Participant) => void;\n trackUnmuted: (publication: TrackPublication, participant: Participant) => void;\n activeSpeakersChanged: (speakers: Participant[]) => void;\n roomMetadataChanged: (metadata: string) => void;\n roomInfoUpdated: (info: RoomInfo) => void;\n participantMetadataChanged: (metadata: string | undefined, participant: Participant) => void;\n participantNameChanged: (name: string, participant: Participant) => void;\n participantAttributesChanged: (\n changedAttributes: Record<string, string>,\n participant: Participant,\n ) => void;\n participantEncryptionStatusChanged: (isEncrypted: boolean, participant: Participant) => void;\n connectionQualityChanged: (quality: ConnectionQuality, participant: Participant) => void;\n dataReceived: (\n payload: Uint8Array,\n participant?: RemoteParticipant,\n kind?: DataPacketKind,\n topic?: string,\n encryptionType?: EncryptionType,\n ) => void;\n chatMessage: (message: ChatMessage, participant?: Participant) => void;\n dtmfReceived: (code: number, digit: string, participant: RemoteParticipant) => void;\n encryptionError: (error: Error) => void;\n connectionStateChanged: (state: ConnectionState) => void;\n connected: () => void;\n disconnected: (reason: DisconnectReason) => void;\n reconnecting: () => void;\n reconnected: () => void;\n roomSidChanged: (sid: string) => void;\n roomUpdated: () => void;\n moved: () => void;\n tokenRefreshed: () => void;\n};\n\nexport enum RoomEvent {\n ParticipantConnected = 'participantConnected',\n ParticipantDisconnected = 'participantDisconnected',\n LocalTrackPublished = 'localTrackPublished',\n LocalTrackUnpublished = 'localTrackUnpublished',\n LocalTrackRepublished = 'localTrackRepublished',\n LocalTrackSubscribed = 'localTrackSubscribed',\n TrackPublished = 'trackPublished',\n TrackUnpublished = 'trackUnpublished',\n TrackSubscribed = 'trackSubscribed',\n TrackUnsubscribed = 'trackUnsubscribed',\n TrackSubscriptionFailed = 'trackSubscriptionFailed',\n TrackMuted = 'trackMuted',\n TrackUnmuted = 'trackUnmuted',\n ActiveSpeakersChanged = 'activeSpeakersChanged',\n RoomMetadataChanged = 'roomMetadataChanged',\n RoomSidChanged = 'roomSidChanged',\n ParticipantMetadataChanged = 'participantMetadataChanged',\n ParticipantNameChanged = 'participantNameChanged',\n ParticipantAttributesChanged = 'participantAttributesChanged',\n ParticipantEncryptionStatusChanged = 'participantEncryptionStatusChanged',\n ConnectionQualityChanged = 'connectionQualityChanged',\n DataReceived = 'dataReceived',\n ChatMessage = 'chatMessage',\n DtmfReceived = 'dtmfReceived',\n EncryptionError = 'encryptionError',\n ConnectionStateChanged = 'connectionStateChanged',\n Connected = 'connected',\n Disconnected = 'disconnected',\n Reconnecting = 'reconnecting',\n Reconnected = 'reconnected',\n RoomUpdated = 'roomUpdated',\n Moved = 'moved',\n TokenRefreshed = 'tokenRefreshed',\n}\n"],"mappings":"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","names":["import_rtc_ffi_bindings","FfiRoomOptions","EventEmitter","RoomEvent"]}
|