diff --git a/packages/react/src/lib/VoiceProvider.tsx b/packages/react/src/lib/VoiceProvider.tsx index 62c8bd57..acb6f69e 100644 --- a/packages/react/src/lib/VoiceProvider.tsx +++ b/packages/react/src/lib/VoiceProvider.tsx @@ -353,6 +353,17 @@ export const VoiceProvider: FC = ({ toolStatus, ], ), + onSessionSettings: useCallback( + (sessionSettings: Hume.empathicVoice.SessionSettings) => { + if (checkIsDisconnecting() || checkIsDisconnected()) { + // disconnection in progress, and resources are being cleaned up. + // ignore the message + return; + } + messageStore.createSessionSettingsMessage(sessionSettings); + }, + [checkIsDisconnected, checkIsDisconnecting, messageStore], + ), onClientError, onToolCallError: useCallback( (message: string, err?: Error) => { diff --git a/packages/react/src/lib/connection-message.ts b/packages/react/src/lib/connection-message.ts index 2d6a7367..582d5cb5 100644 --- a/packages/react/src/lib/connection-message.ts +++ b/packages/react/src/lib/connection-message.ts @@ -1,4 +1,4 @@ -import { type Hume } from 'hume'; +import type { Hume } from 'hume'; export type CloseEvent = Parameters< NonNullable @@ -14,4 +14,9 @@ export type ConnectionMessage = code: CloseEvent['code']; reason: CloseEvent['reason']; receivedAt: Date; + } + | { + type: 'session_settings'; + sessionSettings: Hume.empathicVoice.SessionSettings; + receivedAt: Date; }; diff --git a/packages/react/src/lib/useMessages.ts b/packages/react/src/lib/useMessages.ts index 7652fb94..0ec7c7ab 100644 --- a/packages/react/src/lib/useMessages.ts +++ b/packages/react/src/lib/useMessages.ts @@ -1,3 +1,4 @@ +import type { Hume } from 'hume'; import { useCallback, useState } from 'react'; import type { CloseEvent, ConnectionMessage } from './connection-message'; @@ -48,6 +49,21 @@ export const useMessages = ({ ); }, []); + const createSessionSettingsMessage = useCallback( + (sessionSettings: Hume.empathicVoice.SessionSettings) => { + setMessages((prev) => + prev.concat([ + { + type: 'session_settings', + sessionSettings, + receivedAt: new Date(), + }, + ]), + ); + }, + [], + ); + const createDisconnectMessage = useCallback((event: CloseEvent) => { setMessages((prev) => prev.concat([ @@ -220,6 +236,7 @@ export const useMessages = ({ return { createConnectMessage, createDisconnectMessage, + createSessionSettingsMessage, onMessage, onPlayAudio, clearMessages, diff --git a/packages/react/src/lib/useVoiceClient.ts b/packages/react/src/lib/useVoiceClient.ts index 159b763d..8680901c 100644 --- a/packages/react/src/lib/useVoiceClient.ts +++ b/packages/react/src/lib/useVoiceClient.ts @@ -88,6 +88,9 @@ export type ToolCallHandler = ( export const useVoiceClient = (props: { onAudioMessage?: (message: AudioOutputMessage) => void; onMessage?: (message: JSONMessage) => void; + onSessionSettings?: ( + sessionSettings: Hume.empathicVoice.SessionSettings, + ) => void; onToolCall?: ToolCallHandler; onToolCallError?: (message: string, error?: Error) => void; onClientError?: (message: string, error?: Error) => void; @@ -112,6 +115,11 @@ export const useVoiceClient = (props: { const onMessage = useRef(props.onMessage); onMessage.current = props.onMessage; + const onSessionSettings = useRef( + props.onSessionSettings, + ); + onSessionSettings.current = props.onSessionSettings; + const onToolCall = useRef(props.onToolCall); onToolCall.current = props.onToolCall; @@ -198,6 +206,7 @@ export const useVoiceClient = (props: { signal.removeEventListener('abort', abortHandler); if (postConnectSettings) { socket.sendSessionSettings(postConnectSettings); + onSessionSettings.current?.(postConnectSettings); } resolve(VoiceReadyState.OPEN); } @@ -320,6 +329,7 @@ export const useVoiceClient = (props: { return; } client.current?.sendSessionSettings(sessionSettings); + onSessionSettings.current?.(sessionSettings); }, [readyState], );