diff --git a/.changeset/ninety-kangaroos-kneel.md b/.changeset/ninety-kangaroos-kneel.md new file mode 100644 index 000000000..582cad618 --- /dev/null +++ b/.changeset/ninety-kangaroos-kneel.md @@ -0,0 +1,7 @@ +--- +"@livekit/components-core": patch +"@livekit/components-react": minor +"@livekit/components-styles": patch +--- + +Add support for datastream based chat diff --git a/package.json b/package.json index ad224f1c5..14514787b 100644 --- a/package.json +++ b/package.json @@ -34,11 +34,13 @@ "@livekit/changesets-changelog-github": "^0.0.4", "@rushstack/heft": "^0.68.0", "glob": "^11.0.0", + "globals": "^15.14.0", "husky": "^8.0.3", "nodemon": "^3.0.3", "prettier": "^3.2.5", "turbo": "^2.1.1", - "typescript": "5.7.3" + "typescript": "5.7.3", + "typescript-eslint": "^8.24.0" }, "engines": { "node": ">=18" diff --git a/packages/core/etc/components-core.api.md b/packages/core/etc/components-core.api.md index 5bd03421c..5e1a3d426 100644 --- a/packages/core/etc/components-core.api.md +++ b/packages/core/etc/components-core.api.md @@ -10,7 +10,7 @@ import { ChatMessage } from 'livekit-client'; import { ConnectionQuality } from 'livekit-client'; import { ConnectionState } from 'livekit-client'; import { DataPacket_Kind } from 'livekit-client'; -import type { DataPublishOptions } from 'livekit-client'; +import { DataPublishOptions } from 'livekit-client'; import { LocalAudioTrack } from 'livekit-client'; import { LocalParticipant } from 'livekit-client'; import { LocalVideoTrack } from 'livekit-client'; @@ -27,6 +27,7 @@ import { Room } from 'livekit-client'; import { RoomEvent } from 'livekit-client'; import type { RoomEventCallbacks } from 'livekit-client/dist/src/room/Room'; import type { ScreenShareCaptureOptions } from 'livekit-client'; +import { SendTextOptions } from 'livekit-client'; import { setLogLevel as setLogLevel_2 } from 'livekit-client'; import { Track } from 'livekit-client'; import { TrackEvent as TrackEvent_2 } from 'livekit-client'; @@ -156,8 +157,7 @@ export const cssPrefix = "lk"; // @public (undocumented) export const DataTopic: { - readonly CHAT: "lk-chat-topic"; - readonly CHAT_UPDATE: "lk-chat-update-topic"; + readonly CHAT: "lk.chat"; }; // @public (undocumented) @@ -262,13 +262,18 @@ export function isWeb(): boolean; // @public (undocumented) export interface LegacyChatMessage extends ChatMessage { // (undocumented) - ignore?: boolean; + ignoreLegacy?: boolean; } +// @public @deprecated (undocumented) +export const LegacyDataTopic: { + readonly CHAT: "lk-chat-topic"; +}; + // @public (undocumented) export interface LegacyReceivedChatMessage extends ReceivedChatMessage { // (undocumented) - ignore?: boolean; + ignoreLegacy?: boolean; } // @alpha @@ -497,24 +502,19 @@ export type SetMediaDeviceOptions = { export function setupChat(room: Room, options?: ChatOptions): { messageObservable: Observable; isSendingObservable: BehaviorSubject; - send: (message: string) => Promise; - update: (message: string, originalMessageOrId: string | ChatMessage) => Promise<{ - readonly message: string; - readonly editTimestamp: number; - readonly id: string; - readonly timestamp: number; - }>; + send: (message: string, options?: SendTextOptions) => Promise; }; // @public (undocumented) export function setupChatMessageHandler(room: Room): { chatObservable: Observable<[message: ChatMessage, participant?: LocalParticipant | RemoteParticipant | undefined]>; - send: (text: string) => Promise; + send: (text: string, options: SendTextOptions) => Promise; edit: (text: string, originalMsg: ChatMessage) => Promise<{ readonly message: string; readonly editTimestamp: number; readonly id: string; readonly timestamp: number; + readonly attachedFiles?: Array; }>; }; diff --git a/packages/core/src/components/chat.ts b/packages/core/src/components/chat.ts index 4f8c56d77..e9c21f053 100644 --- a/packages/core/src/components/chat.ts +++ b/packages/core/src/components/chat.ts @@ -1,13 +1,14 @@ /* eslint-disable camelcase */ -import type { Participant, Room, ChatMessage } from 'livekit-client'; +import type { Participant, Room, ChatMessage, SendTextOptions } from 'livekit-client'; import { compareVersions, RoomEvent } from 'livekit-client'; -import { BehaviorSubject, Subject, scan, map, takeUntil, merge } from 'rxjs'; +import { BehaviorSubject, Subject, scan, map, takeUntil, from, filter } from 'rxjs'; import { DataTopic, + LegacyDataTopic, sendMessage, - setupChatMessageHandler, setupDataMessageHandler, } from '../observables/dataChannel'; +import { log } from '../logger'; /** @public */ export type { ChatMessage }; @@ -18,11 +19,11 @@ export interface ReceivedChatMessage extends ChatMessage { } export interface LegacyChatMessage extends ChatMessage { - ignore?: boolean; + ignoreLegacy?: boolean; } export interface LegacyReceivedChatMessage extends ReceivedChatMessage { - ignore?: boolean; + ignoreLegacy?: boolean; } /** @@ -41,83 +42,87 @@ export type ChatOptions = { messageEncoder?: (message: LegacyChatMessage) => Uint8Array; /** @deprecated the new chat API doesn't rely on encoders and decoders anymore and uses a dedicated chat API instead */ messageDecoder?: (message: Uint8Array) => LegacyReceivedChatMessage; - /** @deprecated the new chat API doesn't rely on topics anymore and uses a dedicated chat API instead */ channelTopic?: string; - /** @deprecated the new chat API doesn't rely on topics anymore and uses a dedicated chat API instead */ + /** @deprecated the new chat API doesn't rely on update topics anymore and uses a dedicated chat API instead */ updateChannelTopic?: string; }; -type RawMessage = { - payload: Uint8Array; - topic: string | undefined; - from: Participant | undefined; -}; - -const encoder = new TextEncoder(); -const decoder = new TextDecoder(); +const topicSubjectMap: WeakMap>> = new WeakMap(); -const topicSubjectMap: Map>> = new Map(); +function isIgnorableChatMessage(msg: ReceivedChatMessage | LegacyReceivedChatMessage) { + return (msg as LegacyChatMessage).ignoreLegacy == true; +} -const encode = (message: LegacyReceivedChatMessage) => encoder.encode(JSON.stringify(message)); +const decodeLegacyMsg = (message: Uint8Array) => + JSON.parse(new TextDecoder().decode(message)) as LegacyReceivedChatMessage | ReceivedChatMessage; -const decode = (message: Uint8Array) => - JSON.parse(decoder.decode(message)) as LegacyReceivedChatMessage | ReceivedChatMessage; +const encodeLegacyMsg = (message: LegacyReceivedChatMessage) => + new TextEncoder().encode(JSON.stringify(message)); export function setupChat(room: Room, options?: ChatOptions) { - const onDestroyObservable = new Subject(); - - const serverSupportsChatApi = () => + const serverSupportsDataStreams = () => room.serverInfo?.edition === 1 || - (!!room.serverInfo?.version && compareVersions(room.serverInfo?.version, '1.17.2') > 0); - - const { messageDecoder, messageEncoder, channelTopic, updateChannelTopic } = options ?? {}; + (!!room.serverInfo?.version && compareVersions(room.serverInfo?.version, '1.8.2') > 0); - const topic = channelTopic ?? DataTopic.CHAT; + const onDestroyObservable = new Subject(); - const updateTopic = updateChannelTopic ?? DataTopic.CHAT_UPDATE; + const topic = options?.channelTopic ?? DataTopic.CHAT; + const legacyTopic = options?.channelTopic ?? LegacyDataTopic.CHAT; let needsSetup = false; if (!topicSubjectMap.has(room)) { needsSetup = true; } - const topicMap = topicSubjectMap.get(room) ?? new Map>(); - const messageSubject = topicMap.get(topic) ?? new Subject(); + const topicMap = topicSubjectMap.get(room) ?? new Map>(); + const messageSubject = topicMap.get(topic) ?? new Subject(); topicMap.set(topic, messageSubject); topicSubjectMap.set(room, topicMap); + const finalMessageDecoder = options?.messageDecoder ?? decodeLegacyMsg; if (needsSetup) { - /** Subscribe to all appropriate messages sent over the wire. */ - const { messageObservable } = setupDataMessageHandler(room, [topic, updateTopic]); - messageObservable.pipe(takeUntil(onDestroyObservable)).subscribe(messageSubject); + room.registerTextStreamHandler(topic, async (reader, participantInfo) => { + const { id, timestamp } = reader.info; + const streamObservable = from(reader).pipe( + scan((acc: string, chunk: string) => { + return acc + chunk; + }), + map((chunk: string) => { + console.log('text stream updated', { id, chunk, attributes: reader.info.attributes }); + return { + id, + timestamp, + message: chunk, + from: room.getParticipantByIdentity(participantInfo.identity), + // editTimestamp: type === 'update' ? timestamp : undefined, + } as ReceivedChatMessage; + }), + ); + streamObservable.subscribe({ + next: (value) => messageSubject.next(value), + }); + }); + + /** legacy chat protocol handling */ + const { messageObservable } = setupDataMessageHandler(room, [legacyTopic]); + messageObservable + .pipe( + map((msg) => { + const parsedMessage = finalMessageDecoder(msg.payload); + if (isIgnorableChatMessage(parsedMessage)) { + return undefined; + } + const newMessage: ReceivedChatMessage = { ...parsedMessage, from: msg.from }; + return newMessage; + }), + filter((msg) => !!msg), + takeUntil(onDestroyObservable), + ) + .subscribe(messageSubject); } - const { chatObservable, send: sendChatMessage } = setupChatMessageHandler(room); - - const finalMessageDecoder = messageDecoder ?? decode; /** Build up the message array over time. */ - const messagesObservable = merge( - messageSubject.pipe( - map((msg) => { - const parsedMessage = finalMessageDecoder(msg.payload); - const newMessage = { ...parsedMessage, from: msg.from }; - if (isIgnorableChatMessage(newMessage)) { - return undefined; - } - return newMessage; - }), - ), - chatObservable.pipe( - map(([msg, participant]) => { - return { ...msg, from: participant }; - }), - ), - ).pipe( - scan((acc, value) => { - // ignore legacy message updates - if (!value) { - return acc; - } - // handle message updates + const messagesObservable = messageSubject.pipe( + scan((acc, value) => { if ( 'id' in value && acc.find((msg) => msg.from?.identity === value.from?.identity && msg.id === value.id) @@ -128,10 +133,9 @@ export function setupChat(room: Room, options?: ChatOptions) { acc[replaceIndex] = { ...value, timestamp: originalMsg.timestamp, - editTimestamp: value.editTimestamp ?? value.timestamp, + editTimestamp: value.timestamp, }; } - return [...acc]; } return [...acc, value]; @@ -140,42 +144,37 @@ export function setupChat(room: Room, options?: ChatOptions) { ); const isSending$ = new BehaviorSubject(false); + const finalMessageEncoder = options?.messageEncoder ?? encodeLegacyMsg; - const finalMessageEncoder = messageEncoder ?? encode; - - const send = async (message: string) => { - isSending$.next(true); - try { - const chatMessage = await sendChatMessage(message); - const encodedLegacyMsg = finalMessageEncoder({ - ...chatMessage, - ignore: serverSupportsChatApi(), - }); - await sendMessage(room.localParticipant, encodedLegacyMsg, { - reliable: true, - topic, - }); - return chatMessage; - } finally { - isSending$.next(false); + const send = async (message: string, options?: SendTextOptions) => { + if (!options) { + options = {}; } - }; - - const update = async (message: string, originalMessageOrId: string | ChatMessage) => { - const timestamp = Date.now(); - const originalMessage: ChatMessage = - typeof originalMessageOrId === 'string' - ? { id: originalMessageOrId, message: '', timestamp } - : originalMessageOrId; + options.topic ??= topic; isSending$.next(true); + try { - const editedMessage = await room.localParticipant.editChatMessage(message, originalMessage); - const encodedLegacyMessage = finalMessageEncoder(editedMessage); - await sendMessage(room.localParticipant, encodedLegacyMessage, { - topic: updateTopic, - reliable: true, + const info = await room.localParticipant.sendText(message, options); + const chatMsg: ReceivedChatMessage = { + id: info.id, + timestamp: Date.now(), + message, + from: room.localParticipant, + }; + messageSubject.next(chatMsg); + const encodedLegacyMsg = finalMessageEncoder({ + ...chatMsg, + ignoreLegacy: serverSupportsDataStreams(), }); - return editedMessage; + try { + await sendMessage(room.localParticipant, encodedLegacyMsg, { + reliable: true, + topic: legacyTopic, + }); + } catch (error) { + log.info('could not send message in legacy chat format', error); + } + return chatMsg; } finally { isSending$.next(false); } @@ -184,7 +183,9 @@ export function setupChat(room: Room, options?: ChatOptions) { function destroy() { onDestroyObservable.next(); onDestroyObservable.complete(); + messageSubject.complete(); topicSubjectMap.delete(room); + room.unregisterTextStreamHandler(topic); } room.once(RoomEvent.Disconnected, destroy); @@ -192,12 +193,5 @@ export function setupChat(room: Room, options?: ChatOptions) { messageObservable: messagesObservable, isSendingObservable: isSending$, send, - update, }; } - -function isIgnorableChatMessage( - msg: ReceivedChatMessage | LegacyReceivedChatMessage, -): msg is ReceivedChatMessage { - return (msg as LegacyChatMessage).ignore == true; -} diff --git a/packages/core/src/components/textStream.ts b/packages/core/src/components/textStream.ts new file mode 100644 index 000000000..1ea99ccd3 --- /dev/null +++ b/packages/core/src/components/textStream.ts @@ -0,0 +1,107 @@ +import { RoomEvent, type Room } from 'livekit-client'; +import type { TextStreamInfo } from 'livekit-client/dist/src/room/types'; +import { from, scan, Subject, type Observable } from 'rxjs'; +import { share } from 'rxjs/operators'; + +export interface TextStreamData { + text: string; + participantInfo: { identity: string }; // Replace with the correct type from livekit-client + streamInfo: TextStreamInfo; +} + +// Singleton getters for lazy initialization +let observableCacheInstance: Map> | null = null; +let roomInstanceMapInstance: WeakMap | null = null; +let nextRoomId = 0; + +// Get or create the observable cache +function getObservableCache(): Map> { + if (!observableCacheInstance) { + observableCacheInstance = new Map>(); + } + return observableCacheInstance; +} + +// Get or create the room instance map +function getRoomInstanceMap(): WeakMap { + if (!roomInstanceMapInstance) { + roomInstanceMapInstance = new WeakMap(); + } + return roomInstanceMapInstance; +} + +// Helper to generate cache key +function getCacheKey(room: Room, topic: string): string { + const instanceMap = getRoomInstanceMap(); + + // Get or create a unique ID for this room instance + let roomId = instanceMap.get(room); + if (!roomId) { + roomId = `room_${nextRoomId++}`; + instanceMap.set(room, roomId); + } + + return `${roomId}:${topic}`; +} + +export function setupTextStream(room: Room, topic: string): Observable { + const cacheKey = getCacheKey(room, topic); + const observableCache = getObservableCache(); + + // Check if we already have an observable for this room and topic + const existingObservable = observableCache.get(cacheKey); + if (existingObservable) { + return existingObservable; + } + + const textStreamsSubject = new Subject(); + const textStreams: TextStreamData[] = []; + + room.registerTextStreamHandler(topic, async (reader, participantInfo) => { + // Create an observable from the reader + const streamObservable = from(reader).pipe( + scan((acc: string, chunk: string) => { + return acc + chunk; + }, ''), + ); + + // Subscribe to the stream and update our array when new chunks arrive + streamObservable.subscribe((accumulatedText) => { + console.log('accumulatedText', accumulatedText); + // Find and update the stream in our array + const index = textStreams.findIndex((stream) => stream.streamInfo.id === reader.info.id); + if (index !== -1) { + textStreams[index] = { + ...textStreams[index], + text: accumulatedText, + }; + + // Emit the updated array + textStreamsSubject.next([...textStreams]); + } else { + // Handle case where stream ID wasn't found (new stream) + textStreams.push({ + text: accumulatedText, + participantInfo, + streamInfo: reader.info, + }); + + // Emit the updated array with the new stream + textStreamsSubject.next([...textStreams]); + } + }); + }); + + // Create shared observable and store in cache + const sharedObservable = textStreamsSubject.asObservable().pipe(share()); + observableCache.set(cacheKey, sharedObservable); + + // Add cleanup when room is disconnected + room.once(RoomEvent.Disconnected, () => { + room.unregisterTextStreamHandler(topic); + textStreamsSubject.complete(); + getObservableCache().delete(cacheKey); + }); + + return sharedObservable; +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 5f26d5f0c..6dd59b8d5 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -30,4 +30,6 @@ export * from './observables/dom-event'; export * from './persistent-storage'; +export * from './components/textStream'; + export { log, setLogLevel, setLogExtension } from './logger'; diff --git a/packages/core/src/observables/dataChannel.ts b/packages/core/src/observables/dataChannel.ts index 21d527c25..cff44e91e 100644 --- a/packages/core/src/observables/dataChannel.ts +++ b/packages/core/src/observables/dataChannel.ts @@ -1,17 +1,23 @@ -import type { - ChatMessage, - DataPublishOptions, - LocalParticipant, - Participant, - Room, +import { + type ChatMessage, + type DataPublishOptions, + type LocalParticipant, + type Participant, + type Room, + type SendTextOptions, } from 'livekit-client'; import type { Subscriber } from 'rxjs'; import { Observable, filter, map } from 'rxjs'; import { createChatObserver, createDataObserver } from './room'; +import { ReceivedChatMessage } from '../components/chat'; export const DataTopic = { + CHAT: 'lk.chat-temp', +} as const; + +/** @deprecated */ +export const LegacyDataTopic = { CHAT: 'lk-chat-topic', - CHAT_UPDATE: 'lk-chat-update-topic', } as const; /** Publish data from the LocalParticipant. */ @@ -82,9 +88,10 @@ export function setupDataMessageHandler( export function setupChatMessageHandler(room: Room) { const chatObservable = createChatObserver(room); - const send = async (text: string) => { - const msg = await room.localParticipant.sendChatMessage(text); - return msg; + const send = async (text: string, options: SendTextOptions): Promise => { + const msg = await room.localParticipant.sendChatMessage(text, options); + await room.localParticipant.sendText(text, options); + return { ...msg, from: room.localParticipant, attachedFiles: options.attachments }; }; const edit = async (text: string, originalMsg: ChatMessage) => { diff --git a/packages/core/src/track-reference/test-utils.ts b/packages/core/src/track-reference/test-utils.ts index 1cd681ef0..86435aa1a 100644 --- a/packages/core/src/track-reference/test-utils.ts +++ b/packages/core/src/track-reference/test-utils.ts @@ -23,6 +23,7 @@ export const mockTrackReferencePublished = (id: string, source: Track.Source): T : Track.Kind.Audio; return { participant: new Participant(`${id}`, `${id}`), + // @ts-ignore publication: new TrackPublication(kind, `${id}`, `${id}`), source: source, }; @@ -43,8 +44,9 @@ export const mockTrackReferenceSubscribed = ( ? Track.Kind.Video : Track.Kind.Audio; + // @ts-ignore const publication = new TrackPublication(kind, `${id}`, `${id}`); - // @ts-expect-error + // @ts-ignore publication.track = {}; return { participant: options.mockParticipant diff --git a/packages/core/src/utilis.test.ts b/packages/core/src/utilis.test.ts index 63febc41e..4fecfb24d 100644 --- a/packages/core/src/utilis.test.ts +++ b/packages/core/src/utilis.test.ts @@ -5,9 +5,11 @@ import type { PinState } from './types'; describe('Test isTrackReferencePinned', () => { const participantA = new Participant('dummy-participant', 'A_id', 'track_A_name'); + // @ts-ignore const trackA = new TrackPublication(Track.Kind.Video, 'track_A_id', 'track_A_name'); trackA.trackSid = 'track_a_sid'; const participantB = new Participant('participant_B', 'B_id', 'B_name'); + // @ts-ignore const trackB = new TrackPublication(Track.Kind.Video, 'track_B_id', 'track_B_name'); trackB.trackSid = 'track_b_sid'; const trackReferenceA = { diff --git a/packages/react/etc/components-react.api.md b/packages/react/etc/components-react.api.md index cc0496698..76fdb564b 100644 --- a/packages/react/etc/components-react.api.md +++ b/packages/react/etc/components-react.api.md @@ -9,7 +9,6 @@ import { AudioCaptureOptions } from 'livekit-client'; import { CaptureOptionsBySource } from '../../../packages/core/dist/index.d.ts'; import { CaptureOptionsBySource as CaptureOptionsBySource_2 } from '../../packages/core/dist/index.d.ts'; import { ChatMessage } from '../packages/core/dist/index.d.ts'; -import { ChatMessage as ChatMessage_2 } from 'livekit-client'; import { ChatOptions } from '../../packages/core/dist/index.d.ts'; import { ConnectionQuality } from 'livekit-client'; import { ConnectionState as ConnectionState_2 } from 'livekit-client'; @@ -58,6 +57,7 @@ import { RoomConnectOptions } from 'livekit-client'; import { RoomEvent } from 'livekit-client'; import { RoomOptions } from 'livekit-client'; import { ScreenShareCaptureOptions } from 'livekit-client'; +import { SendTextOptions } from 'livekit-client'; import { setLogExtension } from '../packages/core/dist/index.d.ts'; import { setLogLevel } from '../packages/core/dist/index.d.ts'; import { SetMediaDeviceOptions } from '../../packages/core/dist/index.d.ts'; @@ -720,13 +720,7 @@ export function useAudioWaveform(trackOrTrackReference?: LocalAudioTrack | Remot // @public export function useChat(options?: ChatOptions): { - send: (message: string) => Promise; - update: (message: string, originalMessageOrId: string | ChatMessage_2) => Promise<{ - readonly message: string; - readonly editTimestamp: number; - readonly id: string; - readonly timestamp: number; - }>; + send: (message: string, options?: SendTextOptions) => Promise; chatMessages: ReceivedChatMessage_2[]; isSending: boolean; }; diff --git a/packages/react/src/components/ChatEntry.tsx b/packages/react/src/components/ChatEntry.tsx index 90382a10a..183fe3c29 100644 --- a/packages/react/src/components/ChatEntry.tsx +++ b/packages/react/src/components/ChatEntry.tsx @@ -47,6 +47,8 @@ export const ChatEntry: ( const time = new Date(entry.timestamp); const locale = navigator ? navigator.language : 'en-US'; + const name = entry.from?.name ?? entry.from?.identity; + return (
  • {(!hideTimestamp || !hideName || hasBeenEdited) && ( - {!hideName && ( - - {entry.from?.name ?? entry.from?.identity} - - )} + {!hideName && {name}} {(!hideTimestamp || hasBeenEdited) && ( diff --git a/packages/react/src/components/participant/ParticipantTile.tsx b/packages/react/src/components/participant/ParticipantTile.tsx index 5d0706e0b..c49eeae3f 100644 --- a/packages/react/src/components/participant/ParticipantTile.tsx +++ b/packages/react/src/components/participant/ParticipantTile.tsx @@ -22,6 +22,7 @@ import { VideoTrack } from './VideoTrack'; import { AudioTrack } from './AudioTrack'; import { useParticipantTile } from '../../hooks'; import { useIsEncrypted } from '../../hooks/useIsEncrypted'; +import { useTranscription } from '../../hooks/useTranscription'; /** * The `ParticipantContextIfNeeded` component only creates a `ParticipantContext` @@ -71,6 +72,7 @@ export interface ParticipantTileProps extends React.HTMLAttributes void; } @@ -100,12 +102,15 @@ export const ParticipantTile: ( children, onParticipantClick, disableSpeakingIndicator, + showTranscription = true, ...htmlProps }: ParticipantTileProps, ref, ) { const trackReference = useEnsureTrackRef(trackRef); + const { activeTranscription } = useTranscription(trackReference.participant.identity); + const { elementProps } = useParticipantTile({ htmlProps, disableSpeakingIndicator, @@ -184,6 +189,32 @@ export const ParticipantTile: ( )} + {showTranscription && activeTranscription && ( +
    +
    + {activeTranscription.text} +
    +
    + )} diff --git a/packages/react/src/hooks/useChat.ts b/packages/react/src/hooks/useChat.ts index c87be44aa..75c99b312 100644 --- a/packages/react/src/hooks/useChat.ts +++ b/packages/react/src/hooks/useChat.ts @@ -26,5 +26,5 @@ export function useChat(options?: ChatOptions) { const isSending = useObservableState(setup.isSendingObservable, false); const chatMessages = useObservableState(setup.messageObservable, []); - return { send: setup.send, update: setup.update, chatMessages, isSending }; + return { send: setup.send, chatMessages, isSending }; } diff --git a/packages/react/src/hooks/useReceiveByteStream.ts b/packages/react/src/hooks/useReceiveByteStream.ts new file mode 100644 index 000000000..e63098532 --- /dev/null +++ b/packages/react/src/hooks/useReceiveByteStream.ts @@ -0,0 +1,21 @@ +import * as React from 'react'; +import { useRoomContext } from '../context'; +import type { ByteStreamHandler } from 'livekit-client'; + +/** + * @beta + * set up a byte stream handler for the given topic + * @param topic - the topic to listen to + * @param onByteStreamReceived - the handler to call when a byte stream is received + * @returns a function to unregister the byte stream handler + */ +export function useReceiveByteStream(topic: string, onByteStreamReceived: ByteStreamHandler) { + const room = useRoomContext(); + + React.useEffect(() => { + room.registerByteStreamHandler(topic, onByteStreamReceived); + return () => { + room.unregisterByteStreamHandler(topic); + }; + }, [room, onByteStreamReceived, topic]); +} diff --git a/packages/react/src/hooks/useReceiveTextStream.ts b/packages/react/src/hooks/useReceiveTextStream.ts new file mode 100644 index 000000000..d1a46be4a --- /dev/null +++ b/packages/react/src/hooks/useReceiveTextStream.ts @@ -0,0 +1,21 @@ +import * as React from 'react'; +import { useRoomContext } from '../context'; +import type { TextStreamHandler } from 'livekit-client'; + +/** + * @beta + * set up a text stream handler for the given topic + * @param topic - the topic to listen to + * @param onTextStreamReceived - the handler to call when a text stream is received + * @returns a function to unregister the text stream handler + */ +export function useReceiveTextStream(topic: string, onTextStreamReceived: TextStreamHandler) { + const room = useRoomContext(); + + React.useEffect(() => { + room.registerTextStreamHandler(topic, onTextStreamReceived); + return () => { + room.unregisterTextStreamHandler(topic); + }; + }, [room, onTextStreamReceived, topic]); +} diff --git a/packages/react/src/hooks/useTextStream.ts b/packages/react/src/hooks/useTextStream.ts new file mode 100644 index 000000000..1982630d5 --- /dev/null +++ b/packages/react/src/hooks/useTextStream.ts @@ -0,0 +1,24 @@ +import * as React from 'react'; +import { ConnectionState } from 'livekit-client'; +import { setupTextStream, type TextStreamData } from '@livekit/components-core'; +import { useRoomContext } from '../context'; +import { useConnectionState } from './useConnectionStatus'; +import { useObservableState } from './internal'; + +export function useTextStream(topic: string) { + const room = useRoomContext(); + + const connectionState = useConnectionState(room); + const isDisconnected = React.useMemo( + () => connectionState === ConnectionState.Disconnected, + [connectionState], + ); + + const textStreamObservable = React.useMemo(() => { + return setupTextStream(room, topic); + }, [room, topic, isDisconnected]); + + const textStreams = useObservableState(textStreamObservable, []); + + return { textStreams }; +} diff --git a/packages/react/src/hooks/useTranscription.ts b/packages/react/src/hooks/useTranscription.ts new file mode 100644 index 000000000..9f053596f --- /dev/null +++ b/packages/react/src/hooks/useTranscription.ts @@ -0,0 +1,17 @@ +import * as React from 'react'; +import { useTextStream } from './useTextStream'; + +export function useTranscription(participantIdentity: string) { + const { textStreams } = useTextStream('lk.chat'); + + const filteredMessages = React.useMemo( + () => textStreams.filter((stream) => stream.participantInfo.identity === participantIdentity), + [textStreams, participantIdentity], + ); + + const activeTranscription = React.useMemo(() => { + return filteredMessages.at(-1); + }, [filteredMessages]); + + return { activeTranscription: activeTranscription, transcriptions: filteredMessages }; +} diff --git a/packages/react/src/prefabs/Chat.tsx b/packages/react/src/prefabs/Chat.tsx index 7fe8fd80d..a3f570733 100644 --- a/packages/react/src/prefabs/Chat.tsx +++ b/packages/react/src/prefabs/Chat.tsx @@ -1,4 +1,4 @@ -import type { ChatMessage, ChatOptions } from '@livekit/components-core'; +import { type ChatMessage, type ChatOptions } from '@livekit/components-core'; import * as React from 'react'; import { useMaybeLayoutContext } from '../context'; import { cloneSingleChild } from '../utils'; @@ -6,7 +6,7 @@ import type { MessageFormatter } from '../components/ChatEntry'; import { ChatEntry } from '../components/ChatEntry'; import { useChat } from '../hooks/useChat'; import { ChatToggle } from '../components'; -import { ChatCloseIcon } from '../assets/icons'; +import ChatCloseIcon from '../assets/icons/ChatCloseIcon'; /** @public */ export interface ChatProps extends React.HTMLAttributes, ChatOptions { @@ -32,14 +32,14 @@ export function Chat({ channelTopic, ...props }: ChatProps) { - const inputRef = React.useRef(null); const ulRef = React.useRef(null); + const inputRef = React.useRef(null); const chatOptions: ChatOptions = React.useMemo(() => { return { messageDecoder, messageEncoder, channelTopic }; }, [messageDecoder, messageEncoder, channelTopic]); - const { send, chatMessages, isSending } = useChat(chatOptions); + const { chatMessages, send, isSending } = useChat(chatOptions); const layoutContext = useMaybeLayoutContext(); const lastReadMsgAt = React.useRef(0); @@ -47,11 +47,9 @@ export function Chat({ async function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (inputRef.current && inputRef.current.value.trim() !== '') { - if (send) { - await send(inputRef.current.value); - inputRef.current.value = ''; - inputRef.current.focus(); - } + await send(inputRef.current.value); + inputRef.current.value = ''; + inputRef.current.focus(); } } diff --git a/packages/react/src/prefabs/VoiceAssistantControlBar.tsx b/packages/react/src/prefabs/VoiceAssistantControlBar.tsx index ece660ec6..970aa87e6 100644 --- a/packages/react/src/prefabs/VoiceAssistantControlBar.tsx +++ b/packages/react/src/prefabs/VoiceAssistantControlBar.tsx @@ -1,7 +1,6 @@ import { Track } from 'livekit-client'; import * as React from 'react'; import { MediaDeviceMenu } from './MediaDeviceMenu'; -import { DisconnectButton } from '../components/controls/DisconnectButton'; import { TrackToggle } from '../components/controls/TrackToggle'; import { useLocalParticipant, @@ -10,7 +9,7 @@ import { } from '../hooks'; import { mergeProps } from '../utils'; import { StartMediaButton } from '../components/controls/StartMediaButton'; -import { BarVisualizer } from '../components'; +import { BarVisualizer, DisconnectButton } from '../components'; import type { TrackReferenceOrPlaceholder } from '@livekit/components-core'; /** @beta */ diff --git a/packages/styles/scss/prefabs/chat.scss b/packages/styles/scss/prefabs/chat.scss index 109e4a83c..8221fbe25 100644 --- a/packages/styles/scss/prefabs/chat.scss +++ b/packages/styles/scss/prefabs/chat.scss @@ -92,6 +92,11 @@ color: inherit; } + * { + margin-block-start: 0.25em; + margin-block-end: 0.25em; + } + &:last-child { margin-bottom: 0.25rem; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5bdd01fc6..d2ae20068 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,8 +7,8 @@ settings: catalogs: default: livekit-client: - specifier: ^2.8.1 - version: 2.8.1 + specifier: ^2.9.5 + version: 2.9.5 importers: @@ -26,6 +26,9 @@ importers: glob: specifier: ^11.0.0 version: 11.0.1 + globals: + specifier: ^15.14.0 + version: 15.14.0 husky: specifier: ^8.0.3 version: 8.0.3 @@ -41,6 +44,9 @@ importers: typescript: specifier: 5.7.3 version: 5.7.3 + typescript-eslint: + specifier: ^8.24.0 + version: 8.24.0(eslint@8.57.1)(typescript@5.7.3) docs/docs: dependencies: @@ -58,7 +64,7 @@ importers: version: link:../../packages/styles livekit-client: specifier: 'catalog:' - version: 2.8.1 + version: 2.9.5 react: specifier: ^18.2.0 version: 18.3.1 @@ -122,10 +128,10 @@ importers: version: link:../../packages/styles '@livekit/track-processors': specifier: ^0.3.2 - version: 0.3.2(livekit-client@2.8.1) + version: 0.3.2(livekit-client@2.9.5) livekit-client: specifier: 'catalog:' - version: 2.8.1 + version: 2.9.5 livekit-server-sdk: specifier: ^2.6.1 version: 2.6.1 @@ -165,7 +171,7 @@ importers: version: 1.6.13 livekit-client: specifier: 'catalog:' - version: 2.8.1 + version: 2.9.5 loglevel: specifier: 1.9.1 version: 1.9.1 @@ -214,13 +220,13 @@ importers: version: link:../core '@livekit/krisp-noise-filter': specifier: ^0.2.12 - version: 0.2.12(livekit-client@2.8.1) + version: 0.2.12(livekit-client@2.9.5) clsx: specifier: 2.1.1 version: 2.1.1 livekit-client: specifier: 'catalog:' - version: 2.8.1 + version: 2.9.5 tslib: specifier: ^2.6.2 version: 2.8.1 @@ -406,7 +412,7 @@ importers: version: 8.57.1 eslint-config-next: specifier: ^15.0.0 - version: 15.1.6(eslint@8.57.1)(typescript@5.7.3) + version: 15.1.7(eslint@8.57.1)(typescript@5.7.3) eslint-config-prettier: specifier: ^8.10.0 version: 8.10.0(eslint@8.57.1) @@ -418,7 +424,7 @@ importers: version: 13.0.0(eslint-plugin-react-hooks@5.1.0(eslint@8.57.1))(eslint-plugin-react@7.37.4(eslint@8.57.1))(eslint@8.57.1) eslint-config-turbo: specifier: ^2.0.0 - version: 2.4.0(eslint@8.57.1)(turbo@2.4.0) + version: 2.4.1(eslint@8.57.1)(turbo@2.4.0) eslint-plugin-import: specifier: ^2.29.1 version: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) @@ -2077,12 +2083,12 @@ packages: '@livekit/mutex@1.1.1': resolution: {integrity: sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==} - '@livekit/protocol@1.30.0': - resolution: {integrity: sha512-SDI9ShVKj8N3oOSinr8inaxD3FXgmgoJlqN35uU/Yx1sdoDeQbzAuBFox7bYjM+VhnZ1V22ivIDjAsKr00H+XQ==} - '@livekit/protocol@1.32.0': resolution: {integrity: sha512-GXH59x4Zk5D7I9Bk5si+HiTP6R+I/Ynf1e+5rYRKkskgxdsnBdzCehF09qau55bEoGyVcmCQ4gmekHKetjEC3Q==} + '@livekit/protocol@1.33.0': + resolution: {integrity: sha512-361mBlFgI3nvn8oSQIL38gDUBGbOSwsEOqPgX0c1Jwz75/sD/TTvPeAM4zAz6OrV5Q4vI4Ruswecnyv5SG4oig==} + '@livekit/track-processors@0.3.2': resolution: {integrity: sha512-4JUCzb7yIKoVsTo8J6FTzLZJHcI6DihfX/pGRDg0SOGaxprcDPrt8jaDBBTsnGBSXHeMxl2ugN+xQjdCWzLKEA==} peerDependencies: @@ -2127,8 +2133,8 @@ packages: '@next/eslint-plugin-next@12.3.4': resolution: {integrity: sha512-BFwj8ykJY+zc1/jWANsDprDIu2MgwPOIKxNVnrKvPs+f5TPegrVnem8uScND+1veT4B7F6VeqgaNLFW1Hzl9Og==} - '@next/eslint-plugin-next@15.1.6': - resolution: {integrity: sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw==} + '@next/eslint-plugin-next@15.1.7': + resolution: {integrity: sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ==} '@next/swc-darwin-arm64@14.2.13': resolution: {integrity: sha512-IkAmQEa2Htq+wHACBxOsslt+jMoV3msvxCn0WFSfJSkv/scy+i/EukBKNad36grRxywaXUYJc9mxEGkeIs8Bzg==} @@ -3521,6 +3527,14 @@ packages: typescript: optional: true + '@typescript-eslint/eslint-plugin@8.24.0': + resolution: {integrity: sha512-aFcXEJJCI4gUdXgoo/j9udUYIHgF23MFkg09LFz2dzEmU0+1Plk4rQWv/IYKvPHAtlkkGoB3m5e6oUp+JPsNaQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/parser@5.62.0': resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3551,6 +3565,13 @@ packages: typescript: optional: true + '@typescript-eslint/parser@8.24.0': + resolution: {integrity: sha512-MFDaO9CYiard9j9VepMNa9MTcqVvSny2N4hkY6roquzj8pdCBRENhErrteaQuu7Yjn1ppk0v1/ZF9CG3KIlrTA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/scope-manager@5.62.0': resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3567,6 +3588,10 @@ packages: resolution: {integrity: sha512-DsuOZQji687sQUjm4N6c9xABJa7fjvfIdjqpSIIVOgaENf2jFXiM9hIBZOL3hb6DHK9Nvd2d7zZnoMLf9e0OtQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.24.0': + resolution: {integrity: sha512-HZIX0UByphEtdVBKaQBgTDdn9z16l4aTUz8e8zPQnyxwHBtf5vtl1L+OhH+m1FGV9DrRmoDuYKqzVrvWDcDozw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@7.18.0': resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -3586,6 +3611,13 @@ packages: typescript: optional: true + '@typescript-eslint/type-utils@8.24.0': + resolution: {integrity: sha512-8fitJudrnY8aq0F1wMiPM1UUgiXQRJ5i8tFjq9kGfRajU+dbPyOuHbl0qRopLEidy0MwqgTHDt6CnSeXanNIwA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/types@5.62.0': resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3602,6 +3634,10 @@ packages: resolution: {integrity: sha512-q2/Bxa0gMOu/2/AKALI0tCKbG2zppccnRIRCW6BaaTlRVaPKft4oVYPp7WOPpcnsgbr0qROAVCVKCvIQ0tbWog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.24.0': + resolution: {integrity: sha512-VacJCBTyje7HGAw7xp11q439A+zeGG0p0/p2zsZwpnMzjPB5WteaWqt4g2iysgGFafrqvyLWqq6ZPZAOCoefCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3638,6 +3674,12 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.24.0': + resolution: {integrity: sha512-ITjYcP0+8kbsvT9bysygfIfb+hBj6koDsu37JZG7xrCiy3fPJyNmfVtaGsgTUSEuTzcvME5YI5uyL5LD1EV5ZQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/utils@6.19.1': resolution: {integrity: sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==} engines: {node: ^16.0.0 || >=18.0.0} @@ -3656,6 +3698,13 @@ packages: peerDependencies: eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/utils@8.24.0': + resolution: {integrity: sha512-07rLuUBElvvEb1ICnafYWr4hk8/U7X9RDCOqd9JcAMtjh/9oRmcfN4yGzbPVirgMR0+HLVHehmu19CWeh7fsmQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3672,6 +3721,10 @@ packages: resolution: {integrity: sha512-ba0lNI19awqZ5ZNKh6wCModMwoZs457StTebQ0q1NP58zSi2F6MOZRXwfKZy+jB78JNJ/WH8GSh2IQNzXX8Nag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.24.0': + resolution: {integrity: sha512-kArLq83QxGLbuHrTMoOEWO+l2MwsNS2TGISEdx8xgqpkbytB07XmlQyQdNDrCc1ecSqx0cnmhGvpX+VBwqqSkg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -4768,8 +4821,9 @@ packages: resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} engines: {node: '>= 0.4'} - es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} es-to-primitive@1.3.0: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} @@ -4846,8 +4900,8 @@ packages: typescript: optional: true - eslint-config-next@15.1.6: - resolution: {integrity: sha512-Wd1uy6y7nBbXUSg9QAuQ+xYEKli5CgUhLjz1QHW11jLDis5vK5XB3PemL6jEmy7HrdhaRFDz+GTZ/3FoH+EUjg==} + eslint-config-next@15.1.7: + resolution: {integrity: sha512-zXoMnYUIy3XHaAoOhrcYkT9UQWvXqWju2K7NNsmb5wd/7XESDwof61eUdW4QhERr3eJ9Ko/vnXqIrj8kk/drYw==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: '>=3.3.1' @@ -4877,8 +4931,8 @@ packages: eslint-plugin-n: '^15.0.0 || ^16.0.0 ' eslint-plugin-promise: ^6.0.0 - eslint-config-turbo@2.4.0: - resolution: {integrity: sha512-AiRdy83iwyG4+iMSxXQGUbEClxkGxSlXYH8E2a+0972ao75OWnlDBiiuLMOzDpJubR+QVGC4zonn29AIFCSbFw==} + eslint-config-turbo@2.4.1: + resolution: {integrity: sha512-IFlqpBrWgVG1VJO34H2X2IgxU363CB67Bzsd/MekcD7gPAcRtNIyn8cQXibZL/+jZxdbacp1JLm26iHPg8XqgQ==} peerDependencies: eslint: '>6.6.0' turbo: '>2.0.0' @@ -5014,8 +5068,8 @@ packages: eslint-plugin-tsdoc@0.4.0: resolution: {integrity: sha512-MT/8b4aKLdDClnS8mP3R/JNjg29i0Oyqd/0ym6NnQf+gfKbJJ4ZcSh2Bs1H0YiUMTBwww5JwXGTWot/RwyJ7aQ==} - eslint-plugin-turbo@2.4.0: - resolution: {integrity: sha512-qCgoRi/OTc1VMxab7+sdKiV1xlkY4qjK9sM+kS7+WogrB1DxLguJSQXvk4HA13SD5VmJsq+8FYOw5q4EUk6Ixg==} + eslint-plugin-turbo@2.4.1: + resolution: {integrity: sha512-sTJZrgn7G1rF7RHZcj367g2cT0+E5v0lt9LD+nBpTnCyDA/yB0PwSm/QM+aXQ39vxuK9sqlUL2LyPXyGFvUXsg==} peerDependencies: eslint: '>6.6.0' turbo: '>2.0.0' @@ -5032,6 +5086,10 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -5218,8 +5276,8 @@ packages: resolution: {integrity: sha512-xiXLmMH2Z7OmdE9Q+MjljUMr/rbemFqZIRxaeZieVScG4HzQrKKhNcCYZbWTGpoN7ZPi7z8ClQbeVPq6t5AszQ==} engines: {node: '>=0.4.0'} - for-each@0.3.4: - resolution: {integrity: sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==} + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} foreground-child@3.3.0: @@ -6070,8 +6128,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - livekit-client@2.8.1: - resolution: {integrity: sha512-HPv9iHNrnBANI9ucK7CKZspx0sBZK3hjR2EbwaV08+J3RM9+tNGL2ob2n76nxJLEZG7LzdWlLZdbr4fQBP6Hkg==} + livekit-client@2.9.5: + resolution: {integrity: sha512-2EJmiB4XItaRjTEmL4XxGzsahLYTer9T5N6lKyhBHQxwH4GrjBWewPySvJEO8zCpD2nvWZCmCQjIJx0+w+y6DA==} livekit-server-sdk@2.6.1: resolution: {integrity: sha512-j/8TOlahIyWnycNkuSzTv6q+win4JTbDGNH48iMsZDMnJBks9hhC9UwAO4ES42sAorIAxGkrH58hxt4KdTkZaQ==} @@ -6135,6 +6193,10 @@ packages: resolution: {integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==} engines: {node: '>= 0.6.0'} + loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -7197,8 +7259,8 @@ packages: resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} engines: {node: '>= 10.13.0'} - sdp-transform@2.14.2: - resolution: {integrity: sha512-icY6jVao7MfKCieyo1AyxFYm1baiM+fA00qW/KrNNVlkxHAd34riEKuEkUe4bBb3gJwLJZM+xT60Yj1QL8rHiA==} + sdp-transform@2.15.0: + resolution: {integrity: sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==} hasBin: true sdp@3.2.0: @@ -7677,6 +7739,12 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + ts-debounce@4.0.0: resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==} @@ -7835,6 +7903,13 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + typescript-eslint@8.24.0: + resolution: {integrity: sha512-/lmv4366en/qbB32Vz5+kCNZEMf6xYHwh1z48suBwZvAtnXKbP+YhGe8OLE2BqC67LMqKkCNLtjejdwsdW6uOQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.8.0' + typescript@5.4.2: resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} engines: {node: '>=14.17'} @@ -9905,25 +9980,25 @@ snapshots: transitivePeerDependencies: - encoding - '@livekit/krisp-noise-filter@0.2.12(livekit-client@2.8.1)': + '@livekit/krisp-noise-filter@0.2.12(livekit-client@2.9.5)': dependencies: - livekit-client: 2.8.1 + livekit-client: 2.9.5 '@livekit/mutex@1.1.1': {} - '@livekit/protocol@1.30.0': + '@livekit/protocol@1.32.0': dependencies: '@bufbuild/protobuf': 1.10.0 - '@livekit/protocol@1.32.0': + '@livekit/protocol@1.33.0': dependencies: '@bufbuild/protobuf': 1.10.0 - '@livekit/track-processors@0.3.2(livekit-client@2.8.1)': + '@livekit/track-processors@0.3.2(livekit-client@2.9.5)': dependencies: '@mediapipe/holistic': 0.5.1675471629 '@mediapipe/tasks-vision': 0.10.9 - livekit-client: 2.8.1 + livekit-client: 2.9.5 '@manypkg/find-root@1.1.0': dependencies: @@ -10024,7 +10099,7 @@ snapshots: dependencies: glob: 7.1.7 - '@next/eslint-plugin-next@15.1.6': + '@next/eslint-plugin-next@15.1.7': dependencies: fast-glob: 3.3.1 @@ -11974,6 +12049,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@8.24.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.24.0 + '@typescript-eslint/type-utils': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.24.0 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.2)': dependencies: '@typescript-eslint/scope-manager': 5.62.0 @@ -12012,6 +12104,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.24.0 + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.24.0 + debug: 4.4.0(supports-color@5.5.0) + eslint: 8.57.1 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -12032,6 +12136,11 @@ snapshots: '@typescript-eslint/types': 8.1.0 '@typescript-eslint/visitor-keys': 8.1.0 + '@typescript-eslint/scope-manager@8.24.0': + dependencies: + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/visitor-keys': 8.24.0 + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.1)(typescript@5.7.3)': dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.7.3) @@ -12056,6 +12165,17 @@ snapshots: - eslint - supports-color + '@typescript-eslint/type-utils@8.24.0(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + debug: 4.4.0(supports-color@5.5.0) + eslint: 8.57.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@5.62.0': {} '@typescript-eslint/types@6.19.1': {} @@ -12064,6 +12184,8 @@ snapshots: '@typescript-eslint/types@8.1.0': {} + '@typescript-eslint/types@8.24.0': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.2)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -12123,6 +12245,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.24.0(typescript@5.7.3)': + dependencies: + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/visitor-keys': 8.24.0 + debug: 4.4.0(supports-color@5.5.0) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.7.3) + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@6.19.1(eslint@8.57.1)(typescript@5.4.2)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) @@ -12159,6 +12295,17 @@ snapshots: - supports-color - typescript + '@typescript-eslint/utils@8.24.0(eslint@8.57.1)(typescript@5.7.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.24.0 + '@typescript-eslint/types': 8.24.0 + '@typescript-eslint/typescript-estree': 8.24.0(typescript@5.7.3) + eslint: 8.57.1 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -12179,6 +12326,11 @@ snapshots: '@typescript-eslint/types': 8.1.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.24.0': + dependencies: + '@typescript-eslint/types': 8.24.0 + eslint-visitor-keys: 4.2.0 + '@ungap/structured-clone@1.3.0': {} '@vitejs/plugin-react@3.1.0(vite@5.4.14(@types/node@22.13.1)(sass@1.84.0)(terser@5.38.1))': @@ -12538,7 +12690,7 @@ snapshots: es-abstract: 1.23.9 es-errors: 1.3.0 es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 + es-shim-unscopables: 1.1.0 array.prototype.findlastindex@1.2.5: dependencies: @@ -12547,21 +12699,21 @@ snapshots: es-abstract: 1.23.9 es-errors: 1.3.0 es-object-atoms: 1.1.1 - es-shim-unscopables: 1.0.2 + es-shim-unscopables: 1.1.0 array.prototype.flat@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 + es-shim-unscopables: 1.1.0 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 es-abstract: 1.23.9 - es-shim-unscopables: 1.0.2 + es-shim-unscopables: 1.1.0 array.prototype.tosorted@1.1.4: dependencies: @@ -12569,7 +12721,7 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.23.9 es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 + es-shim-unscopables: 1.1.0 arraybuffer.prototype.slice@1.0.4: dependencies: @@ -13442,7 +13594,7 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - es-shim-unscopables@1.0.2: + es-shim-unscopables@1.1.0: dependencies: hasown: 2.0.2 @@ -13623,7 +13775,7 @@ snapshots: eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.2))(eslint-import-resolver-typescript@2.7.1)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.4(eslint@8.57.1) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1) @@ -13633,9 +13785,9 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-config-next@15.1.6(eslint@8.57.1)(typescript@5.7.3): + eslint-config-next@15.1.7(eslint@8.57.1)(typescript@5.7.3): dependencies: - '@next/eslint-plugin-next': 15.1.6 + '@next/eslint-plugin-next': 15.1.7 '@rushstack/eslint-patch': 1.10.5 '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3) '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) @@ -13666,14 +13818,14 @@ snapshots: eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0)(eslint-plugin-n@17.15.1(eslint@8.57.1))(eslint-plugin-promise@7.2.1(eslint@8.57.1))(eslint@8.57.1): dependencies: eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1) eslint-plugin-n: 17.15.1(eslint@8.57.1) eslint-plugin-promise: 7.2.1(eslint@8.57.1) - eslint-config-turbo@2.4.0(eslint@8.57.1)(turbo@2.4.0): + eslint-config-turbo@2.4.1(eslint@8.57.1)(turbo@2.4.0): dependencies: eslint: 8.57.1 - eslint-plugin-turbo: 2.4.0(eslint@8.57.1)(turbo@2.4.0) + eslint-plugin-turbo: 2.4.1(eslint@8.57.1)(turbo@2.4.0) turbo: 2.4.0 eslint-import-resolver-node@0.3.9: @@ -13688,7 +13840,7 @@ snapshots: dependencies: debug: 4.4.0(supports-color@5.5.0) eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.2))(eslint-import-resolver-typescript@2.7.1)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1) glob: 7.2.3 is-glob: 4.0.3 resolve: 1.22.10 @@ -13708,29 +13860,28 @@ snapshots: is-glob: 4.0.3 stable-hash: 0.0.4 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.1)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 2.7.1(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/parser': 8.24.0(eslint@8.57.1)(typescript@5.7.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.7.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color @@ -13741,7 +13892,7 @@ snapshots: eslint: 8.57.1 eslint-compat-utils: 0.5.1(eslint@8.57.1) - eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.2))(eslint-import-resolver-typescript@2.7.1)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -13752,7 +13903,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@8.57.1)(typescript@5.4.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@2.7.1)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -13764,13 +13915,13 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 5.62.0(eslint@8.57.1)(typescript@5.4.2) + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.7.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-typescript@3.7.0)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -13799,6 +13950,35 @@ snapshots: - eslint-import-resolver-webpack - supports-color + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1): dependencies: aria-query: 5.3.2 @@ -13908,7 +14088,7 @@ snapshots: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - eslint-plugin-turbo@2.4.0(eslint@8.57.1)(turbo@2.4.0): + eslint-plugin-turbo@2.4.1(eslint@8.57.1)(turbo@2.4.0): dependencies: dotenv: 16.0.3 eslint: 8.57.1 @@ -13926,6 +14106,8 @@ snapshots: eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@4.2.0: {} + eslint@8.57.1: dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) @@ -14201,7 +14383,7 @@ snapshots: flow-parser@0.259.1: {} - for-each@0.3.4: + for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -15332,13 +15514,13 @@ snapshots: lines-and-columns@1.2.4: {} - livekit-client@2.8.1: + livekit-client@2.9.5: dependencies: '@livekit/mutex': 1.1.1 - '@livekit/protocol': 1.30.0 + '@livekit/protocol': 1.33.0 events: 3.3.0 - loglevel: 1.9.1 - sdp-transform: 2.14.2 + loglevel: 1.9.2 + sdp-transform: 2.15.0 ts-debounce: 4.0.0 tslib: 2.8.1 typed-emitter: 2.1.0 @@ -15397,6 +15579,8 @@ snapshots: loglevel@1.9.1: {} + loglevel@1.9.2: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -16504,7 +16688,7 @@ snapshots: ajv-formats: 2.1.1(ajv@8.17.1) ajv-keywords: 5.1.0(ajv@8.17.1) - sdp-transform@2.14.2: {} + sdp-transform@2.15.0: {} sdp@3.2.0: {} @@ -17046,6 +17230,10 @@ snapshots: dependencies: typescript: 5.7.3 + ts-api-utils@2.0.1(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + ts-debounce@4.0.0: {} ts-dedent@2.2.0: {} @@ -17164,7 +17352,7 @@ snapshots: typed-array-byte-length@1.0.3: dependencies: call-bind: 1.0.8 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 @@ -17173,7 +17361,7 @@ snapshots: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 @@ -17182,7 +17370,7 @@ snapshots: typed-array-length@1.0.7: dependencies: call-bind: 1.0.8 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 is-typed-array: 1.1.15 possible-typed-array-names: 1.1.0 @@ -17211,6 +17399,16 @@ snapshots: typedarray@0.0.6: {} + typescript-eslint@8.24.0(eslint@8.57.1)(typescript@5.7.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.24.0(@typescript-eslint/parser@8.24.0(eslint@8.57.1)(typescript@5.7.3))(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/parser': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + '@typescript-eslint/utils': 8.24.0(eslint@8.57.1)(typescript@5.7.3) + eslint: 8.57.1 + typescript: 5.7.3 + transitivePeerDependencies: + - supports-color + typescript@5.4.2: {} typescript@5.7.2: {} @@ -17622,7 +17820,7 @@ snapshots: available-typed-arrays: 1.0.7 call-bind: 1.0.8 call-bound: 1.0.3 - for-each: 0.3.4 + for-each: 0.3.5 gopd: 1.2.0 has-tostringtag: 1.0.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a471be0c0..9c11dbf55 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,4 +5,4 @@ packages: - 'tooling/*' catalog: - livekit-client: ^2.8.1 + livekit-client: ^2.9.5