
    b6i;                     &   d dl mZmZ d dlZd dlZd dlmZ d dlmZ d dl	m
Z
 d dlZd dlZd dlZd dlmZmZmZmZmZmZmZmZmZ d dlZd dlZd dlmZ d dlmZmZ d	d
l m!Z! d	dl"m#Z#  ejH                  e%      Z& G d de'e
      Z( G d de'e
      Z) G d d      Z* G d d      Z+ G d d      Z, G d de      Z- G d de      Z. G d d      Z/ G d d      Z0 G d d      Z1e G d  d!             Z2 G d" d#      Z3 G d$ d%e3      Z4 G d& d'e3      Z5y)(    )ABCabstractmethodN)ThreadPoolExecutor)	dataclass)Enum)	Any	AwaitableCallableDictListLiteralOptionalTupleUnion)ConnectionClosedOK)
Connectionconnect   )BaseElevenLabs)__version__c                   ,    e Zd ZdZdZdZdZdZdZdZ	dZ
y	)
ClientToOrchestratorEventz9Event types that can be sent from client to orchestrator.pongclient_tool_result#conversation_initiation_client_datafeedbackcontextual_updateuser_messageuser_activityN)__name__
__module____qualname____doc__PONGCLIENT_TOOL_RESULT#CONVERSATION_INITIATION_CLIENT_DATAFEEDBACKCONTEXTUAL_UPDATEUSER_MESSAGEUSER_ACTIVITY     t/root/.openclaw/workspace/visionaryfx/venv/lib/python3.12/site-packages/elevenlabs/conversational_ai/conversation.pyr   r      s-    C D-*O'H+!L#Mr,   r   c                       e Zd ZdZdZdZy)AgentChatResponsePartTypestartdeltastopN)r    r!   r"   STARTDELTASTOPr+   r,   r-   r/   r/   '   s    EEDr,   r/   c                   0    e Zd ZdZddee   fdZdefdZy)$UserMessageClientToOrchestratorEventz%Event for sending user text messages.Ntextc                 <    t         j                  | _        || _        y N)r   r)   typer8   selfr8   s     r-   __init__z-UserMessageClientToOrchestratorEvent.__init__0   s    E^EkEk		r,   returnc                 4    | j                   | j                  dS Nr;   r8   rB   r=   s    r-   to_dictz,UserMessageClientToOrchestratorEvent.to_dict4       		49955r,   r:   )	r    r!   r"   r#   r   strr>   dictrD   r+   r,   r-   r7   r7   -   s!    /Xc] 6 6r,   r7   c                   $    e Zd ZdZddZdefdZy)%UserActivityClientToOrchestratorEventz>Event for registering user activity (ping to prevent timeout).r?   Nc                 .    t         j                  | _        y r:   )r   r*   r;   rC   s    r-   r>   z.UserActivityClientToOrchestratorEvent.__init__;   s    F_FmFm	r,   c                     d| j                   iS )Nr;   )r;   rC   s    r-   rD   z-UserActivityClientToOrchestratorEvent.to_dict>   s    		""r,   )r?   N)r    r!   r"   r#   r>   rG   rD   r+   r,   r-   rI   rI   8   s    Hn# #r,   rI   c                   (    e Zd ZdZdefdZdefdZy))ContextualUpdateClientToOrchestratorEventzPEvent for sending non-interrupting contextual updates to the conversation state.r8   c                 <    t         j                  | _        || _        y r:   )r   r(   r;   r8   r<   s     r-   r>   z2ContextualUpdateClientToOrchestratorEvent.__init__E   s    JcJuJu		r,   r?   c                 4    | j                   | j                  dS rA   rB   rC   s    r-   rD   z1ContextualUpdateClientToOrchestratorEvent.to_dictI   rE   r,   N)r    r!   r"   r#   rF   r>   rG   rD   r+   r,   r-   rM   rM   B   s    ZS 6 6r,   rM   c                   h    e Zd ZdZedeegdf   fd       Zed        Zedefd       Z	ed        Z
y)	AudioInterfacezKAudioInterface provides an abstraction for handling audio input and output.input_callbackNc                      ya?  Starts the audio interface.

        Called one time before the conversation starts.
        The `input_callback` should be called regularly with input audio chunks from
        the user. The audio should be in 16-bit PCM mono format at 16kHz. Recommended
        chunk size is 4000 samples (250 milliseconds).
        Nr+   r=   rR   s     r-   r0   zAudioInterface.startP   s     	r,   c                      ya
  Stops the audio interface.

        Called one time after the conversation ends. Should clean up any resources
        used by the audio interface and stop any audio streams. Do not call the
        `input_callback` from `start` after this method is called.
        Nr+   rC   s    r-   r2   zAudioInterface.stop[        	r,   audioc                      yzOutput audio to the user.

        The `audio` input is in 16-bit PCM mono format at 16kHz. Implementations can
        choose to do additional buffering. This method should return quickly and not
        block the calling thread.
        Nr+   r=   rY   s     r-   outputzAudioInterface.outpute   rX   r,   c                      yzInterruption signal to stop any audio output.

        User has interrupted the agent and all previosly buffered audio output should
        be stopped.
        Nr+   rC   s    r-   	interruptzAudioInterface.interrupto   s     	r,   )r    r!   r"   r#   r   r
   bytesr0   r2   r]   r`   r+   r,   r-   rQ   rQ   M   sl    UHeWd]$;     E    r,   rQ   c                   n    e Zd ZdZedeeged   f   fd       Zed        Z	edefd       Z
ed        Zy)	AsyncAudioInterfacezVAsyncAudioInterface provides an async abstraction for handling audio input and output.rR   Nc                    K   ywrT   r+   rU   s     r-   r0   zAsyncAudioInterface.start|   s      	   c                    K   ywrW   r+   rC   s    r-   r2   zAsyncAudioInterface.stop         	re   rY   c                    K   ywr[   r+   r\   s     r-   r]   zAsyncAudioInterface.output   rg   re   c                    K   ywr_   r+   rC   s    r-   r`   zAsyncAudioInterface.interrupt   s      	re   )r    r!   r"   r#   r   r
   ra   r	   r0   r2   r]   r`   r+   r,   r-   rc   rc   y   sq    `(E7IdO3K*L     %    r,   rc   c            
           e Zd ZdZddeej                     ddfdZd Zd Z		 dde
d	eeegef   eegee   f   f   d
eddfdZde
dedefdZde
dedeegdf   fdZd Zy)ClientToolsaR  Handles registration and execution of client-side tools that can be called by the agent.

    Supports both synchronous and asynchronous tools running in a dedicated event loop,
    ensuring non-blocking operation of the main conversation thread.

    Args:
        loop: Optional custom asyncio event loop to use for tool execution. If not provided,
              a new event loop will be created and run in a separate thread. Using a custom
              loop prevents "different event loop" runtime errors and allows for better
              context propagation and resource management.
    Nloopr?   c                     i | _         t        j                         | _        || _        d | _        d | _        t        j                         | _        t               | _
        y r:   )tools	threadingLocklock_custom_loop_loop_threadEvent_runningr   thread_pool)r=   rl   s     r-   r>   zClientTools.__init__   sF    mo
NN$	 
!)-/r,   c                 X     j                   j                         ry j                  , j                   _         j                   j	                          y fd}t        j                  |dd       _         j                  j                           j                   j                          y)zHStart the event loop in a separate thread for handling async operations.Nc                     t        j                          _        t        j                   j                          j                  j                          	  j                  j                           j                  j                           j                  j                          d  _        y #  j                  j                           j                  j                          d  _        w xY wr:   )	asyncionew_event_looprs   set_event_looprv   setrun_foreverclearcloserC   s   r-   run_event_loopz)ClientTools.start.<locals>.run_event_loop   s    $335
&&tzz2!!#&JJ**,MM'')JJ$$&!%DJ MM'')JJ$$&!%DJs   B+ +=C(TzClientTools-EventLoop)targetdaemonname)
rv   is_setrr   rs   r}   ro   Threadrt   r0   wait)r=   r   s   ` r-   r0   zClientTools.start   s}    ==!(**DJMM	& %++>$UlmDLLL MM r,   c                    | j                   r| j                  j                         r| j                  | j                  j	                          nU| j                   j                  | j                   j                         | j                  r| j                  j                          | j                  j                  d       yyy)z6Gracefully stop the event loop and clean up resources.NF)r   )rs   rv   r   rr   r   call_soon_threadsafer2   rt   joinrw   shutdownrC   s    r-   r2   zClientTools.stop   s    ::$--..0  ,##% 

//

@<<LL%%'%%5%1 1:r,   	tool_namehandleris_asyncc                     | j                   5  t        |      st        d      || j                  v rt        d| d      ||f| j                  |<   ddd       y# 1 sw Y   yxY w)a  Register a new tool that can be called by the AI agent.

        Args:
            tool_name: Unique identifier for the tool
            handler: Function that implements the tool's logic
            is_async: Whether the handler is an async function
        zHandler must be callableTool 'z' is already registeredN)rq   callable
ValueErrorrn   )r=   r   r   r   s       r-   registerzClientTools.register   sh     YY 	8G$ !;<<DJJ& 6)4K!LMM%,h$7DJJy!	8 	8 	8s   AAA$
parametersc                 D  K   | j                   5  || j                  vrt        d| d      | j                  |   \  }}ddd       r |       d{   S t        j                         j                  | j                  |       d{   S # 1 sw Y   RxY w7 G7 w)zpExecute a registered tool with the given parameters.

        Returns the result of the tool execution.
        r   z' is not registeredN)rq   rn   r   rz   get_event_looprun_in_executorrw   )r=   r   r   r   r   s        r-   handlezClientTools.handle   s     
 YY 	6

* 6)4G!HII $

9 5GX	6
  ,,, //1AA$BRBRT[]ghhh	6 	6 -hs9   B 0BB B6B BB BB B callbackc                       j                   j                         st        d       j                  t        d       fd} j	                   |              y)zExecute a tool and send its result via the provided callback.

        This method is non-blocking and handles both sync and async tools.
        z%ClientTools event loop is not runningNzEvent loop is not availablec                     K   	 j                         d {   } dj                  d      | xs d ddd} |       y 7 +# t        $ r)}dj                  d      t        |      dd}Y d }~8d }~ww xY ww)Nr   tool_call_idzClient tool: z called successfully.F)r;   r   resultis_errorT)r   get	ExceptionrF   )r   responseer   r   r=   r   s      r-   _execute_and_callbackz7ClientTools.execute_tool.<locals>._execute_and_callback  s     #{{9jAA0$.NN>$B$X-	{BW(X %	 X B  0$.NN>$B!!f $	s=   A=A A"A 	A=A 	A:A50A=5A::A=)rv   r   RuntimeErrorrs   _schedule_coroutine)r=   r   r   r   r   s   ```` r-   execute_toolzClientTools.execute_tool  sP    
 }}##%FGG::<==	$ 	  !6!89r,   c                     | j                   | j                  j                  |      S t        j                  || j                        S )z3Schedule a coroutine on the appropriate event loop.)rr   rs   create_taskrz   run_coroutine_threadsafe)r=   coros     r-   r   zClientTools._schedule_coroutine%  s:    (::))$//33D$**EEr,   r:   )F)r    r!   r"   r#   r   rz   AbstractEventLoopr>   r0   r2   rF   r   r
   rG   r   r	   boolr   r   r   r   r+   r,   r-   rk   rk      s    
0Xg&?&?@ 0D 0!62" 	88 x,hvy~7M.NNO8 	8
 
8(ic it i i:c :t :xQUPVX\P\G] :>Fr,   rk   c            
       J    e Zd ZdZ	 	 	 	 ddee   dee   dee   dee   fdZy)	ConversationInitiationDataz+Configuration options for the Conversation.N
extra_bodyconversation_config_overridedynamic_variablesuser_idc                 T    |xs i | _         |xs i | _        |xs i | _        || _        y r:   )r   r   r   r   )r=   r   r   r   r   s        r-   r>   z#ConversationInitiationData.__init__0  s1     %*,H,NB)!2!8br,   )NNNN)r    r!   r"   r#   r   rG   rF   r>   r+   r,   r-   r   r   -  sN    5 &*7;,0!%
TN
 '/tn
 $D>	

 #
r,   r   c                   x    e Zd ZdZ	 	 	 	 	 	 ddedee   dee   dee   deee      deee      d	eee      fd
Zy)OnPremInitiationDataz;Configuration options for the Conversation in on-prem mode.Non_prem_conversation_url#post_call_transcription_webhook_urlpost_call_audio_webhook_urlagent_config_dictoverride_agent_config_listtools_config_listprompt_knowledge_basec                 f    || _         || _        || _        || _        || _        || _        || _        y r:   )r   r   r   r   r   r   r   )r=   r   r   r   r   r   r   r   s           r-   r>   zOnPremInitiationData.__init__@  s=     )A%3V0+F(!2*D'!2%:"r,   )NNNNNN)	r    r!   r"   r#   rF   r   rG   r   r>   r+   r,   r-   r   r   =  s    E
 >B59,0;?2659;"%; .6c]; &.c]	;
 $D>; %-T$Z$8; $DJ/;  (S	2;r,   r   c                   B    e Zd ZU dZee   ed<   ee   ed<   ee   ed<   y)AudioEventAlignmentzEAudio alignment data containing character-level timing information. dcharschar_start_times_mschar_durations_msN)r    r!   r"   r#   r   rF   __annotations__intr+   r,   r-   r   r   S  s#    O9c"Cy r,   r   c                   ~    e Zd ZdZ	 ddddddededee   dedee   d	ee	   d
ee
   fdZd Zd Zd Zd Zd Zd Zy)BaseConversationzMBase class for conversation implementations with shared parameters and logic.N)configclient_toolson_prem_configclientagent_idr   requires_authr   r   r   c                    || _         || _        || _        || _        |xs
 t	               | _        |xs
 t               | _        || _        | j                  j                          d | _
        d| _        y )Nr   )r   r   r   r   r   r   rk   r   r   r0   _conversation_id_last_interrupt_id)r=   r   r   r   r   r   r   r   s           r-   r>   zBaseConversation.__init___  sj      *< : <(9KM,! $"#r,   c                    | j                   r| j                   j                  S | j                  j                  j	                         }t
        j                  j                  |      j                  |j                  d      rdnd      j                         }|j                  d      s|dz  }| d| j                   dt         S )Nhttpswssws)scheme/z v1/convai/conversation?agent_id=z&source=python_sdk&version=)r   r   r   _client_wrapperget_base_urlurllibparseurlparse_replace
startswithgeturlendswithr   r   )r=   base_http_urlbase_ws_urls      r-   _get_wss_urlzBaseConversation._get_wss_urlw  s    &&???33@@BLL!!-0Xm&>&>w&GUTXRVX 	 ##C(3K>t}}oMhithuvvr,   c                     | j                   j                  j                  j                  | j                        }|j
                  }d|v rdnd}| | dt         S )N)r   ?&zsource=python_sdk&version=)r   conversational_aiconversationsget_signed_urlr   
signed_urlr   )r=   r   r   	separators       r-   _get_signed_urlz BaseConversation._get_signed_url  s[    ;;00>>MMW[WdWdMe((
*,C#	i[(B;-PPr,   c           
      ,   t        j                  d| j                  j                  | j                  j                  | j                  j
                  | j                  j                  | j                  j                  | j                  j                  d      S )Nenclave_setup_config)r;   r   r   r   r   r   r   )	jsondumpsr   r   r   r   r   r   r   rC   s    r-   "_create_on_prem_initiation_messagez3BaseConversation._create_on_prem_initiation_message  su    zz.%)%8%8%J%J.2.A.A.\.\%)%8%8%J%J7;7J7J7n7n/3/B/B/^/^)-)<)<)R)R

 
	
r,   c           	          t        j                  d| j                  j                  | j                  j                  | j                  j
                  dt        dd| j                  rd| j                  i      S i       S )Nr   
python_sdk)sourceversion)r;   custom_llm_extra_bodyr   r   source_infor   )r   r   r   r   r   r   r   r   rC   s    r-   _create_initiation_messagez+BaseConversation._create_initiation_message  s|    zz=)-)?)?040X0X%)[[%B%B** 
 15It||,

 	
 CE

 	
r,   c                    |d   dk(  r|d   }| j                   J |d   | _         y|d   dk(  r|d   }t        |d         | j                  k  ryt        j                  |d	         }|j                  |       |j                  rZd
|v rU|d
   }t        |j                  dg       |j                  dg       |j                  dg             }|j                  |       yyy|d   dk(  r5|j                  r(|d   }|j                  |d   j                                yy|d   dk(  rb|j                  rU|j                  di       }|j                  dd      }|j                  dd      }	 t        |      }	|j#                  ||	       yy|d   dk(  rG|j$                  r:|d   }|j'                  |d   j                         |d   j                                yy|d   dk(  r5|j(                  r(|d   }|j+                  |d   j                                yy|d   dk(  r)|d   }t        |d         | _        |j-                          y|d   dk(  rG|d   }|j/                  |       |j0                  r$|d    r|j3                  t        |d                 yyy|d   d!k(  rO|j                  d!i       }
|
j                  d"      }d#|
d#   i|
j                  d$i       }|j5                  ||       yy# t        $ r t        j                   }	Y w xY w)%zCore message handling logic shared between sync and async implementations.

        Args:
            message: The parsed message dictionary
            message_handler: Handler object with methods for different operations
        r;    conversation_initiation_metadata&conversation_initiation_metadata_eventNconversation_idrY   audio_eventevent_idaudio_base_64	alignmentr   r   r   r   r   r   agent_responseagent_response_eventagent_chat_response_parttext_response_partr8    r1   agent_response_correctionagent_response_correction_eventoriginal_agent_responsecorrected_agent_responseuser_transcriptuser_transcription_eventinterruptioninterruption_eventping
ping_eventping_msclient_tool_callr   r   r   r   r   r   base64	b64decodehandle_audio_outputcallback_audio_alignmentr   r   handle_audio_alignmentcallback_agent_responsehandle_agent_responsestrip!callback_agent_chat_response_partr/   r   r4   handle_agent_chat_response_part"callback_agent_response_correction handle_agent_response_correctioncallback_user_transcripthandle_user_transcripthandle_interruptionhandle_pingcallback_latency_measurementhandle_latency_measurementhandle_client_tool_callr=   messagemessage_handlereventrY   alignment_datar   r8   part_type_str	part_type	tool_callr   r   s                r-   _handle_message_corez%BaseConversation._handle_message_core  sc    6?@@DEE((000$)*;$<D!V_'M*E5$%)@)@@$$U?%;<E//677K5<P!&{!3/(,,Wb9(6(:(:;PRT(U&4&8&89Lb&Q	
  66yA =Q7 V_ 0066 6755e<L6M6S6S6UV 7 V_ ::@@$8"=yy, %		&' :@ 9- HI  ??iP A V_ ;;AA AB@@34::<eD^>_>e>e>g B V_ 1177 :;66u=N7O7U7U7WX 8 V_.01E&)%
*;&<D#//1V_&L)E''.;;i@P::3uY?O;PQ AQ; V_ 22$6;I!k2I()N*Cgy}}UaceGfgJ33IzJC " @ 9 ? ?I@s   (K+ +LLc                   K   |d   dk(  r|d   }| j                   J |d   | _         y|d   dk(  r|d   }t        |d         | j                  k  ryt        j                  |d	         }|j                  |       d{    |j                  rbd
|v r]|d
   }t        |j                  dg       |j                  dg       |j                  dg             }|j                  |       d{    yyy|d   dk(  r=|j                  r0|d   }|j                  |d   j                                d{    yy|d   dk(  rj|j                  r]|j                  di       }|j                  dd      }|j                  dd      }	 t        |      }	|j#                  ||	       d{    yy|d   dk(  rO|j$                  rB|d   }|j'                  |d   j                         |d   j                                d{    yy|d   dk(  r=|j(                  r0|d   }|j+                  |d   j                                d{    yy|d   dk(  r1|d   }t        |d         | _        |j-                          d{    y|d   dk(  rW|d   }|j/                  |       d{    |j0                  r,|d    r&|j3                  t        |d                 d{    yyy|d   d!k(  rO|j                  d!i       }
|
j                  d"      }d#|
d#   i|
j                  d$i       }|j5                  ||       yy7 7 N7 # t        $ r t        j                   }	Y w xY w7 7 h7 &7 7 7 w)%z.Async wrapper for core message handling logic.r;   r   r   Nr   rY   r   r   r   r   r   r   r   r   r   r  r  r  r8   r  r1   r  r  r  r  r	  r
  r  r  r  r  r  r  r   r   r   r  r%  s                r-   _handle_message_core_asyncz+BaseConversation._handle_message_core_async  s    6?@@DEE((000$)*;$<D!V_'M*E5$%)@)@@$$U?%;<E!55e<<<77K5<P!&{!3/(,,Wb9(6(:(:;PRT(U&4&8&89Lb&Q	
 &<<YGGG =Q7 V_ 0066 67%;;EBR<S<Y<Y<[\\\ 7 V_ ::@@$8"=yy, %		&' :@ 9- HI &EEdIVVV A V_ ;;AA AB%FF34::<eD^>_>e>e>g   B V_ 1177 :;%<<UCT=U=[=[=]^^^ 8 V_.01E&)%
*;&<D#!55777V_&L)E!--e444;;i@P%@@U9EUAVWWW AQ; V_ 22$6;I!k2I()N*Cgy}}UaceGfgJ33IzJq = H
 ] " @ 9 ? ?I@V
 _
 8 5Ws   A<M->L5?A+M-*L8+AM-0L;1AM-L> M-"M#AM-9M!:AM->M$?9M-8M'9&M-M) 5M-M+A M-8M-;M->MM-MM-!M-$M-'M-)M-+M-r:   )r    r!   r"   r#   r   rF   r   r   r   rk   r   r>   r   r   r   r   r-  r/  r+   r,   r-   r   r   \  s    W "&	$ 8<.29=$$ $ #	$ $ 34$ {+$ !!56$0wQ

IVDr,   r   c            !       n    e Zd ZU eed<   eeegdf      ed<   eeeegdf      ed<   eeeegdf      ed<   eeegdf      ed<   eee	gdf      ed<   eee
gdf      ed<   ee   ed	<   eej                     ed
<   ej                  ed<   ee   ed<   	 d!ddddddddddd
dededee   dededee   dee   deeegdf      deeeegdf      deeeegdf      deeegdf      deee	gdf      deee
gdf      d	ee   dee   f fdZd Zd Zdee   fdZdefdZd ZdefdZdefdZd  Z xZS )"Conversationaudio_interfaceNr  r  r  r  r"  r  callback_end_sessionrt   _should_stop_ws
r   r   r  r  r  r  r"  r  r3  r   r   r   r   r   r   r   r   c          	          t         |   |||||||       || _        || _        |	| _        |
| _        || _        || _        || _        || _	        d| _
        d| _        t        j                         | _        y)a3  Conversational AI session.

        BETA: This API is subject to change without regard to backwards compatibility.

        Args:
            client: The ElevenLabs client to use for the conversation.
            agent_id: The ID of the agent to converse with.
            user_id: The ID of the user conversing with the agent.
            requires_auth: Whether the agent requires authentication.
            audio_interface: The audio interface to use for input and output.
            client_tools: The client tools to use for the conversation.
            callback_agent_response: Callback for agent responses.
            callback_agent_response_correction: Callback for agent response corrections.
                First argument is the original response (previously given to
                callback_agent_response), second argument is the corrected response.
            callback_agent_chat_response_part: Callback for streaming text response chunks.
                First argument is the text chunk, second argument is the type (START, DELTA, STOP).
            callback_user_transcript: Callback for user transcripts.
            callback_latency_measurement: Callback for latency measurements (in milliseconds).
            callback_audio_alignment: Callback for audio alignment data with character-level timing.
        r   r   r   r   r   r   r   N)superr>   r2  r  r  r  r  r"  r  r3  rt   r5  ro   ru   r4  r=   r   r   r   r   r2  r   r   r  r  r  r  r"  r  r3  r   	__class__s                   r-   r>   zConversation.__init__I  s    R 	'%) 	 	
  /'>$2T/1R.(@%,H)(@%$8!)-%OO-r,   c                     | j                   r| j                         n| j                         }t        j                  | j
                  |f      | _        | j                  j                          y)zoStarts the conversation session.

        Will run in background thread until `end_session` is called.
        )r   argsN)r   r   r   ro   r   _runrt   r0   r=   ws_urls     r-   start_sessionzConversation.start_session  sO    
 ,0+=+=%%'4CTCTCV ''tyyyIr,   c                     | j                   j                          | j                  j                          d| _        | j                  j                          | j                  r| j                          yyz6Ends the conversation session and cleans up resources.Nr2  r2   r   r5  r4  r}   r3  rC   s    r-   end_sessionzConversation.end_session  sY    !!# $$%%' %r,   r?   c                 |    | j                   st        d      | j                   j                          | j                  S )Waits for the conversation session to end.

        You must call `end_session` before calling this method, otherwise it will block.

        Returns the conversation ID, if available.
        Session not started.)rt   r   r   r   rC   s    r-   wait_for_session_endz!Conversation.wait_for_session_end  s3     ||566$$$r,   r8   c                    | j                   st        d      t        |      }	 | j                   j                  t	        j
                  |j                                      y# t        $ r}t        j                  d|         d}~ww xY w)Send a text message from the user to the agent.

        Args:
            text: The text message to send to the agent.

        Raises:
            RuntimeError: If the session is not active or websocket is not connected.
        /Session not started or websocket not connected.r8   Error sending user message: N
r5  r   r7   sendr   r   rD   r   loggererrorr=   r8   r(  r   s       r-   send_user_messagezConversation.send_user_message  sl     xxPQQ4$?	HHMM$**U]]_56 	LL7s;<	   <A" "	B	+BB	c                    | j                   st        d      t               }	 | j                   j                  t	        j
                  |j                                      y# t        $ r}t        j                  d|         d}~ww xY w)Register user activity to prevent session timeout.

        This sends a ping to the orchestrator to reset the timeout timer.

        Raises:
            RuntimeError: If the session is not active or websocket is not connected.
        rL  !Error registering user activity: N
r5  r   rI   rP  r   r   rD   r   rQ  rR  r=   r(  r   s      r-   register_user_activityz#Conversation.register_user_activity  sj     xxPQQ57	HHMM$**U]]_56 	LL<QC@A	s   <A   	B)BBc                    | j                   st        d      t        |      }	 | j                   j                  t	        j
                  |j                                      y# t        $ r}t        j                  d|         d}~ww xY w)a  Send a contextual update to the conversation.

        Contextual updates are non-interrupting content that is sent to the server
        to update the conversation state without directly prompting the agent.

        Args:
            content: The contextual information to send to the conversation.

        Raises:
            RuntimeError: If the session is not active or websocket is not connected.
        rL  rM  !Error sending contextual update: N
r5  r   rM   rP  r   r   rD   r   rQ  rR  rS  s       r-   send_contextual_updatez#Conversation.send_contextual_update  sl     xxPQQ9tD	HHMM$**U]]_56 	LL<QC@A	rU  r@  c                 @    t        |d      5  _         j                  rj                   j	                                j                   j                                 _         fd} j                  j                  |        j                  j                         sw	 t        j                  j                  d            } j                  j                         r
	 d d d        y  j                  |        j                  j                         swd  _        d d d        y # t        $ r} j                          Y d }~Id }~wt         $ r Y Wt"        $ r2}t$        j'                  d|         j                          Y d }~d }~ww xY w# 1 sw Y   y xY w)N   max_sizec                 F   	 j                  t        j                  dt        j                  |       j                         i             y # t        $ r j                          Y y t        $ r2}t        j                  d|        j                          Y d }~y d }~ww xY wNuser_audio_chunkz Error sending user audio chunk: rP  r   r   r  	b64encodedecoder   rE  r   rQ  rR  rY   r   r=   r   s     r-   rR   z)Conversation._run.<locals>.input_callback  s    'GG

 2F4D4DU4K4R4R4T * '$$&  'LL#CA3!GH$$&&'s   AA B &B .(BB       ?timeoutError receiving message: )r   r5  r   rP  r   r   r2  r0   r4  r   r   loadsrecv_handle_messager   rE  TimeoutErrorr   rQ  rR  )r=   r@  rR   r&  r   r   s   `    @r-   r>  zConversation._run  s^   V&67 %	2DH""??ABGGD3356DH'   &&~6''..0'"jj)=>G((//17%	 %	8 (("5 ''..0 DHK%	 %	: * '$$&&#   'LL#<QC!@A$$&&'C%	 %	s`   BF%?D+.D+ FF+	F4E	F	FFF(FFFFFc                 N     G d d      } || |      }| j                  ||       y )Nc                   N    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)8Conversation._handle_message.<locals>.SyncMessageHandlerc                     || _         || _        |j                  | _        |j                  | _        |j                  | _        |j
                  | _        |j                  | _        |j                  | _        y r:   conversationr   r  r  r  r  r"  r  r=   rx  r   s      r-   r>   zAConversation._handle_message.<locals>.SyncMessageHandler.__init__  e    $0!/;/S/S,:F:i:i79E9g9g60<0U0U-4@4]4]10<0U0U-r,   c                 N    | j                   j                  j                  |       y r:   rx  r2  r]   r\   s     r-   r  zLConversation._handle_message.<locals>.SyncMessageHandler.handle_audio_output  s    !!1188?r,   c                 :    | j                   j                  |       y r:   rx  r  r=   r   s     r-   r  zOConversation._handle_message.<locals>.SyncMessageHandler.handle_audio_alignment  s    !!::9Er,   c                 :    | j                   j                  |       y r:   rx  r  r=   r   s     r-   r  zNConversation._handle_message.<locals>.SyncMessageHandler.handle_agent_response  s    !!99(Cr,   c                 <    | j                   j                  ||       y r:   rx  r  r=   original	correcteds      r-   r  zYConversation._handle_message.<locals>.SyncMessageHandler.handle_agent_response_correction   s    !!DDXyYr,   c                 <    | j                   j                  ||       y r:   rx  r  r=   r8   r+  s      r-   r  zXConversation._handle_message.<locals>.SyncMessageHandler.handle_agent_chat_response_part#  s    !!CCD)Tr,   c                 :    | j                   j                  |       y r:   rx  r  r=   
transcripts     r-   r  zOConversation._handle_message.<locals>.SyncMessageHandler.handle_user_transcript&  s    !!:::Fr,   c                 L    | j                   j                  j                          y r:   rx  r2  r`   rC   s    r-   r   zLConversation._handle_message.<locals>.SyncMessageHandler.handle_interruption)  s    !!11;;=r,   c                 l    | j                   j                  t        j                  d|d   d             y Nr   r   )r;   r   r   rP  r   r   r=   r(  s     r-   r!  zDConversation._handle_message.<locals>.SyncMessageHandler.handle_ping,  s.    JJ$*(-j(9r,   c                 :    | j                   j                  |       y r:   rx  r"  r=   latencys     r-   r#  zSConversation._handle_message.<locals>.SyncMessageHandler.handle_latency_measurement6  s    !!>>wGr,   c                 ^      fd} j                   j                  j                  |||       y )Nc                     j                   j                  j                         s/j                  j	                  t        j                  |              y y r:   )rx  r4  r   r   rP  r   r   r   r=   s    r-   send_responsezgConversation._handle_message.<locals>.SyncMessageHandler.handle_client_tool_call.<locals>.send_response:  s:    ,,99@@BTZZ%9: Cr,   rx  r   r   r=   r   r   r  s   `   r-   r$  zPConversation._handle_message.<locals>.SyncMessageHandler.handle_client_tool_call9  s)    ; !!..;;IzS`ar,   Nr    r!   r"   r>   r  r  r  r  r  r  r   r!  r#  r$  r+   r,   r-   SyncMessageHandlerru    sB    V@FDZUG>Hbr,   r  )r-  )r=   r&  r   r  r   s        r-   rq  zConversation._handle_message  s-    2	b 2	bh %T2.!!'73r,   r:   )r    r!   r"   rQ   r   r   r
   rF   r/   r   r   ro   r   ru   r   r   r   r   rk   r   r>   rA  rE  rI  rT  r[  r_  r>  rq  __classcell__r;  s   @r-   r1  r1  ;  s]   ##%hud{&;<<(03*d:J1K(LL'/#?X9Y[_9_0`'aa&xt'<=="*8SE4K+@"AA&x1D0Et0K'LMM"8,,i&&''//!	*	 "&	>. 8<.2CGSWhlDHHLTX379=#>.>. >. #	>. >. (>. 34>. {+>. "*(C5$;*?!@>. -5XsCj$>N5O,P>. ,4HcC\=]_c=c4d+e>. #+8SE4K+@"A>. '/xt/D&E>. #+85H4I44O+P"Q>.  'x0!>." !!56#>.@(
%hsm 
%c &$3 ,&3 &P64r,   r1  c            "           e Zd ZU eed<   eeeged   f      ed<   eeeeged   f      ed<   eeee	ged   f      ed<   eeeged   f      ed<   eee
ged   f      ed<   eeeged   f      ed<   eeg ed   f      ed	<   eej                     ed
<   ej                  ed<   eej                      ed<   	 d!ddddddddddd
dededee   dededee   dee   deeeged   f      deeeeged   f      deeee	ged   f      deeeged   f      deee
ged   f      deeeged   f      d	eeg ed   f      dee   f fdZd Zd Zdee   fdZdefdZd ZdefdZdefdZd  Z xZS )"AsyncConversationr2  Nr  r  r  r  r"  r  r3  _taskr4  r5  r6  r   r   r   r   r   r   r   c          	          t         |   |||||||       || _        || _        |	| _        |
| _        || _        || _        || _        || _	        d| _
        d| _        t        j                         | _        y)a  Async Conversational AI session.

        BETA: This API is subject to change without regard to backwards compatibility.

        Args:
            client: The ElevenLabs client to use for the conversation.
            agent_id: The ID of the agent to converse with.
            user_id: The ID of the user conversing with the agent.
            requires_auth: Whether the agent requires authentication.
            audio_interface: The async audio interface to use for input and output.
            client_tools: The client tools to use for the conversation.
            callback_agent_response: Async callback for agent responses.
            callback_agent_response_correction: Async callback for agent response corrections.
                First argument is the original response (previously given to
                callback_agent_response), second argument is the corrected response.
            callback_agent_chat_response_part: Async callback for streaming text response chunks.
                First argument is the text chunk, second argument is the type (START, DELTA, STOP).
            callback_user_transcript: Async callback for user transcripts.
            callback_latency_measurement: Async callback for latency measurements (in milliseconds).
            callback_audio_alignment: Async callback for audio alignment data with character-level timing.
            callback_end_session: Async callback for when session ends.
        r8  N)r9  r>   r2  r  r  r  r  r"  r  r3  r  r5  rz   ru   r4  r:  s                   r-   r>   zAsyncConversation.__init__R  s    T 	'%) 	 	
  /'>$2T/1R.(@%,H)(@%$8!
#MMOr,   c                    K   | j                   r| j                         n| j                         }t        j                  | j                  |            | _        yw)zmStarts the conversation session.

        Will run in background task until `end_session` is called.
        N)r   r   r   rz   r   r>  r  r?  s     r-   rA  zAsyncConversation.start_session  sD     
 ,0+=+=%%'4CTCTCV((6):;
s   AAc                   K   | j                   j                          d{    | j                  j                          d| _        | j                  j                          | j                  r| j                          d{    yy7 e7 wrC  rD  rC   s    r-   rE  zAsyncConversation.end_session  st     ""''))) $$++--- % 	* .s"   B
BAB
?B B
B
r?   c                 |   K   | j                   st        d      | j                    d{    | j                  S 7 w)rG  rH  N)r  r   r   rC   s    r-   rI  z&AsyncConversation.wait_for_session_end  s9      zz566jj$$$ 	s   '<:<r8   c                 4  K   | j                   st        d      t        |      }	 | j                   j                  t	        j
                  |j                                      d{    y7 # t        $ r}t        j                  d|         d}~ww xY ww)rK  rL  rM  NrN  rO  rS  s       r-   rT  z#AsyncConversation.send_user_message  su      xxPQQ4$?	((--

5==? ;<<< 	LL7s;<	:   $B?A. &A,'A. +B,A. .	B7BBBc                 0  K   | j                   st        d      t               }	 | j                   j                  t	        j
                  |j                                      d{    y7 # t        $ r}t        j                  d|         d}~ww xY ww)rW  rL  NrX  rY  rZ  s      r-   r[  z(AsyncConversation.register_user_activity  ss      xxPQQ57	((--

5==? ;<<< 	LL<QC@A	s:   "B?A, $A*%A, )B*A, ,	B5BBBc                 4  K   | j                   st        d      t        |      }	 | j                   j                  t	        j
                  |j                                      d{    y7 # t        $ r}t        j                  d|         d}~ww xY ww)a  Send a contextual update to the conversation.

        Contextual updates are non-interrupting content that is sent to the server
        to update the conversation state without directly prompting the agent.

        Args:
            text: The contextual information to send to the conversation.

        Raises:
            RuntimeError: If the session is not active or websocket is not connected.
        rL  rM  Nr]  r^  rS  s       r-   r_  z(AsyncConversation.send_contextual_update  su      xxPQQ9tD	((--

5==? ;<<< 	LL<QC@A	r  r@  c                    K   t        j                  |d      4 d {    _         j                  r'j	                   j                                d {    j	                   j                                d {     fd} j                  j                  |       d {    	  j                  j                         s	 t        j                  j                         d       d {   } j                  j                         r	 d  _        d d d       d {    y t        j                  |      } j!                  |       d {     j                  j                         sd  _        d d d       d {    y 7 m7 67 7 7 7 t7 F# t        j"                  $ r Y Yt$        $ r  j'                          d {  7   Y at(        $ r;}t*        j-                  d|         j'                          d {  7   Y d }~d }~ww xY w# d  _        w xY w7 # 1 d {  7  sw Y   y xY ww)Nra  rb  c                   K   	 j                  t        j                  dt        j                  |       j                         i             d {    y 7 # t        $ r j                          d {  7   Y y t        $ r;}t        j                  d|        j                          d {  7   Y d }~y d }~ww xY wwre  rg  rj  s     r-   rR   z.AsyncConversation._run.<locals>.input_callback  s     -''

 2F4D4DU4K4R4R4T   * -**,,,  -LL#CA3!GH**,,,-se   CA
A AA CA B>3A64B>9C;B>+B9.B1/B94C9B>>Crk  rl  rn  )
websocketsr   r5  r   rP  r   r   r2  r0   r4  r   rz   wait_forrp  r   ro  rq  rr  r   rE  r   rQ  rR  )r=   r@  rR   message_strr&  r   r   s   `     @r-   r>  zAsyncConversation._run  s    %%f7GH )	  )	 BDH""ggdEEGHHH''$99;<<<- &&,,^<<< ++224,3,<,<RWWYPS,T&T,,335"  S)	  )	  )	 : #'**["9"227B??? ++224"  S)	  )	  )	  I<" =
 'U5)	 < @"// - "..000$ '@%DE"..000
  S)	  )	  )	  )	 s4  H?FH?6H*F&H*F(H**F+H*0H(F3F4FH*H?%F&H?+*FFFH5H*<H?H(H?H*H*H*FH?FH1H3HGHHH+H	H
HHHH	H%%H*(H?*H<0H31H<8H?c                 j   K    G d d      } || |      }| j                  ||       d {    y 7 w)Nc                   N    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zy)>AsyncConversation._handle_message.<locals>.AsyncMessageHandlerc                     || _         || _        |j                  | _        |j                  | _        |j                  | _        |j
                  | _        |j                  | _        |j                  | _        y r:   rw  ry  s      r-   r>   zGAsyncConversation._handle_message.<locals>.AsyncMessageHandler.__init__  rz  r,   c                 j   K   | j                   j                  j                  |       d {    y 7 wr:   r|  r\   s     r-   r  zRAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_audio_output$  s&     ''77>>uEEE   )313c                 V   K   | j                   j                  |       d {    y 7 wr:   r~  r  s     r-   r  zUAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_audio_alignment'  s      ''@@KKK   )')c                 V   K   | j                   j                  |       d {    y 7 wr:   r  r  s     r-   r  zTAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_agent_response*  s      ''??IIIr  c                 X   K   | j                   j                  ||       d {    y 7 wr:   r  r  s      r-   r  z_AsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_agent_response_correction-  s#     ''JJ8U^___    *(*c                 X   K   | j                   j                  ||       d {    y 7 wr:   r  r  s      r-   r  z^AsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_agent_chat_response_part0  s#     ''II$PYZZZr  c                 V   K   | j                   j                  |       d {    y 7 wr:   r  r  s     r-   r  zUAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_user_transcript3  s      ''@@LLLr  c                 h   K   | j                   j                  j                          d {    y 7 wr:   r  rC   s    r-   r   zRAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_interruption6  s$     ''77AACCCs   (202c                    K   | j                   j                  t        j                  d|d   d             d {    y 7 wr  r  r  s     r-   r!  zJAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_ping9  s<     ggllJJ$*(-j(9  s   8AA Ac                 V   K   | j                   j                  |       d {    y 7 wr:   r  r  s     r-   r#  zYAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_latency_measurementC  s      ''DDWMMMr  c                 ^      fd} j                   j                  j                  |||       y )Nc                     j                   j                  j                         sBt        j                  j
                  j                  t        j                  |                    y y r:   )	rx  r4  r   rz   r   r   rP  r   r   r  s    r-   r  zmAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_client_tool_call.<locals>.send_responseG  sE    ,,99@@B++DGGLLH9M,NO Cr,   r  r  s   `   r-   r$  zVAsyncConversation._handle_message.<locals>.AsyncMessageHandler.handle_client_tool_callF  s*    P !!..;;IzS`ar,   Nr  r+   r,   r-   AsyncMessageHandlerr    sC    VFLJ`[MDNbr,   r  )r/  )r=   r&  r   r  r   s        r-   rq  z!AsyncConversation._handle_message  s9     2	b 2	bh &dB/ --gw???r  r:   ) r    r!   r"   rc   r   r   r
   rF   r	   r/   r   r   rz   Taskru   r  WebSocketClientProtocolr   r   r   rk   r   r>   rA  rE  rI  rT  r[  r_  r>  rq  r  r  s   @r-   r  r  D  s   ((%huio/E&FGG(03*iPTo:U1V(WW'/#?X9Y[dei[j9j0k'll&xy0F'GHH"*8SE9T?4J+K"LL&x1D0EyQU0V'WXX"8B	$,?#@AAGLL!!--	*44	55 "&	?, 8<.2NR^bswOSSW_cHL9=#?,?, ?, #	?, ?, -?, 34?, {+?, "*(C5)D/3I*J!K?, -5XsCj)TX/>Y5Z,[?, ,4HcC\=]_him_n=n4o+p?, #+8SE9T?4J+K"L?, '/xy8N/O&P?, #+85H4I9UY?4Z+["\?,  'xIdO0C'DE!?," !!56#?,B<.
%HSM 
%C &$ ,*  * X8@r,   r  )6abcr   r   rz   r  concurrent.futuresr   dataclassesr   enumr   r   loggingro   typingr   r	   r
   r   r   r   r   r   r   urllib.parser   r  websockets.exceptionsr   websockets.sync.clientr   r   base_clientr   r   r   	getLoggerr    rQ  rF   r   r/   r7   rI   rM   rQ   rc   rk   r   r   r   r   r1  r  r+   r,   r-   <module>r     s   #   1 !     X X X   4 6 ( ! 
		8	$$T $T 6 6# #6 6)S )X)# )XEF EFP  ; ;, ! ! !\ \~F4# F4RL@( L@r,   