@@ -61,12 +61,29 @@ type AgentInstanceCommon = {
6161} ;
6262
6363type AgentStateAvailable = AgentInstanceCommon & {
64- state : "listening" | " thinking" | "speaking" ;
64+ state : "thinking" | "speaking" ;
6565 failureReasons : null ;
6666
6767 /** Is the agent ready for user interaction? */
6868 isAvailable : true ;
6969
70+ /** Is the audio preconnect buffer currently available? */
71+ isPreConnectBufferEnabled : false ;
72+
73+ cameraTrack : TrackReference | null ;
74+ microphoneTrack : TrackReference | null ;
75+ } ;
76+
77+ type AgentStateAvailableListening = AgentInstanceCommon & {
78+ state : "listening" ;
79+ failureReasons : null ;
80+
81+ /** Is the agent ready for user interaction? */
82+ isAvailable : true ;
83+
84+ /** Is the audio preconnect buffer currently available? */
85+ isPreConnectBufferEnabled : boolean ;
86+
7087 cameraTrack : TrackReference | null ;
7188 microphoneTrack : TrackReference | null ;
7289} ;
@@ -78,17 +95,23 @@ type AgentStateUnAvailable = AgentInstanceCommon & {
7895 /** Is the agent ready for user interaction? */
7996 isAvailable : false ;
8097
98+ /** Is the audio preconnect buffer currently available? */
99+ isPreConnectBufferEnabled : false ;
100+
81101 cameraTrack : TrackReference | null ;
82102 microphoneTrack : TrackReference | null ;
83103} ;
84104
85105type AgentStateConnecting = AgentInstanceCommon & {
86- state : "connecting" ;
106+ state : "disconnected" | " connecting";
87107 failureReasons : null ;
88108
89109 /** Is the agent ready for user interaction? */
90110 isAvailable : false ;
91111
112+ /** Is the audio preconnect buffer currently available? */
113+ isPreConnectBufferEnabled : false ;
114+
92115 cameraTrack : null ;
93116 microphoneTrack : null ;
94117} ;
@@ -100,6 +123,9 @@ type AgentStateFailed = AgentInstanceCommon & {
100123 /** Is the agent ready for user interaction? */
101124 isAvailable : false ;
102125
126+ /** Is the audio preconnect buffer currently available? */
127+ isPreConnectBufferEnabled : false ;
128+
103129 cameraTrack : null ;
104130 microphoneTrack : null ;
105131} ;
@@ -115,7 +141,7 @@ type AgentActions = {
115141 waitUntilMicrophone : ( signal ?: AbortSignal ) => Promise < TrackReference > ;
116142} ;
117143
118- type AgentStateCases = AgentStateConnecting | AgentStateAvailable | AgentStateUnAvailable | AgentStateFailed ;
144+ type AgentStateCases = AgentStateConnecting | AgentStateAvailable | AgentStateAvailableListening | AgentStateUnAvailable | AgentStateFailed ;
119145export type AgentInstance = AgentStateCases & AgentActions ;
120146
121147const generateDerivedStateValues = < State extends AgentState > ( state : State ) => ( {
@@ -314,42 +340,44 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
314340 agentTimeoutFailureReason,
315341 startAgentTimeout,
316342 clearAgentTimeout,
317- updateAgentTimeoutState : updateAgentTimeoutConversationalState ,
343+ updateAgentTimeoutState,
318344 updateAgentTimeoutParticipantExists,
319345 } = useAgentTimeoutIdStore ( ) ;
320346
321347 const failureReasons = useMemo ( ( ) => {
322348 return agentTimeoutFailureReason ? [ agentTimeoutFailureReason ] : [ ] ;
323349 } , [ agentTimeoutFailureReason ] ) ;
324350
325- const state = useMemo ( ( ) => {
351+ const [ state , isPreConnectBufferEnabled ] = useMemo ( ( ) => {
326352 if ( failureReasons . length > 0 ) {
327- return 'failed' ;
353+ return [ 'failed' as const , false ] ;
328354 }
329355
330- let newState : AgentState = 'connecting' ;
356+ let state : AgentState = 'disconnected' ;
357+ let preconnectBufferEnabled = false ;
331358
332359 if ( roomConnectionState !== ConnectionState . Disconnected ) {
333- newState = 'initializing ' ;
360+ state = 'connecting ' ;
334361 }
335362
336363 // If the microphone preconnect buffer is active, then the state should be "listening" rather
337364 // than "initializing"
338365 if ( localMicTrack ) {
339- newState = 'listening' ;
366+ state = 'listening' ;
367+ preconnectBufferEnabled = true ;
340368 }
341369
342370 if ( agentParticipant && agentParticipantAttributes [ ParticipantAgentAttributes . AgentState ] ) {
343- const agentState = agentParticipantAttributes [ ParticipantAgentAttributes . AgentState ] as AgentSdkStates ;
344- newState = agentState ;
371+ state = agentParticipantAttributes [ ParticipantAgentAttributes . AgentState ] as AgentSdkStates ;
372+ preconnectBufferEnabled = false ;
345373 }
346374
347- return newState ;
375+ return [ state , preconnectBufferEnabled ] as [ AgentState , boolean ] ;
348376 } , [ failureReasons , roomConnectionState , localMicTrack , agentParticipant , agentParticipantAttributes ] ) ;
349377
350378 useEffect ( ( ) => {
351379 emitter . emit ( AgentEvent . StateChanged , state ) ;
352- updateAgentTimeoutConversationalState ( state ) ;
380+ updateAgentTimeoutState ( state ) ;
353381 } , [ emitter , state ] ) ;
354382 useEffect ( ( ) => {
355383 updateAgentTimeoutParticipantExists ( agentParticipant !== null ) ;
@@ -382,18 +410,19 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
382410 } ;
383411
384412 switch ( state ) {
385- case 'listening' :
386- case 'thinking' :
387- case 'speaking' :
413+ case 'disconnected' :
414+ case 'connecting' :
388415 return {
389416 ...common ,
390417
391418 state,
392419 ...generateDerivedStateValues ( state ) ,
420+ isPreConnectBufferEnabled : false ,
393421 failureReasons : null ,
394422
395- cameraTrack : videoTrack ,
396- microphoneTrack : audioTrack ,
423+ // Clear inner values if no longer connected
424+ cameraTrack : null ,
425+ microphoneTrack : null ,
397426 } ;
398427
399428 case 'initializing' :
@@ -403,23 +432,38 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
403432
404433 state,
405434 ...generateDerivedStateValues ( state ) ,
435+ isPreConnectBufferEnabled : false ,
406436 failureReasons : null ,
407437
408438 cameraTrack : videoTrack ,
409439 microphoneTrack : audioTrack ,
410440 } ;
411441
412- case 'connecting ' :
442+ case 'listening ' :
413443 return {
414444 ...common ,
415445
416446 state,
417447 ...generateDerivedStateValues ( state ) ,
448+ isPreConnectBufferEnabled,
418449 failureReasons : null ,
419450
420- // Clear inner values if no longer connected
421- cameraTrack : null ,
422- microphoneTrack : null ,
451+ cameraTrack : videoTrack ,
452+ microphoneTrack : audioTrack ,
453+ } ;
454+
455+ case 'thinking' :
456+ case 'speaking' :
457+ return {
458+ ...common ,
459+
460+ state,
461+ ...generateDerivedStateValues ( state ) ,
462+ isPreConnectBufferEnabled : false ,
463+ failureReasons : null ,
464+
465+ cameraTrack : videoTrack ,
466+ microphoneTrack : audioTrack ,
423467 } ;
424468
425469 case 'failed' :
@@ -428,6 +472,7 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
428472
429473 state : 'failed' ,
430474 ...generateDerivedStateValues ( 'failed' ) ,
475+ isPreConnectBufferEnabled : false ,
431476 failureReasons,
432477
433478 // Clear inner values if no longer connected
@@ -443,6 +488,7 @@ export function useAgent(conversation: ConversationStub, _name?: string): AgentI
443488 state ,
444489 videoTrack ,
445490 audioTrack ,
491+ isPreConnectBufferEnabled ,
446492 ] ) ;
447493
448494 const waitUntilAvailable = useCallback ( async ( signal ?: AbortSignal ) => {
0 commit comments