
    >|h:                         d dl mZ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 d dlZd dlmZ d dlmZ d dlmZ ddlmZ  G d	 d
e      Z G d d      Z G d d      Z G d d      Zy)    )ABCabstractmethodN)CallableOptional	AwaitableUnionAny)ThreadPoolExecutor)connect)ConnectionClosedOK   )BaseElevenLabsc                   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).
        N )selfr   s     h/var/www/html/test/engine/venv/lib/python3.12/site-packages/elevenlabs/conversational_ai/conversation.pystartzAudioInterface.start   s     	    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   r   s    r   stopz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   r   s     r   outputzAudioInterface.output'   r   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   r   s    r   	interruptzAudioInterface.interrupt1   s     	r   )__name__
__module____qualname____doc__r   r   bytesr   r   r   r    r   r   r   r   r      sl    UHeWd]$;     E    r   r   c            
           e Zd ZdZ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y	)ClientToolszHandles 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.
    c                     i | _         t        j                         | _        d | _        d | _        t        j                         | _        t               | _	        y N)
tools	threadingLocklock_loop_threadEvent_runningr
   thread_poolr   s    r   __init__zClientTools.__init__B   s>    mo
NN$	
!)-/r   c                       j                   j                         r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_loopr.   set_event_loopr1   setrun_foreverclearcloser   s   r   run_event_loopz)ClientTools.start.<locals>.run_event_loopO   s     //1DJ""4::.MM"

&&(##%

  "!
 ##%

  "!
s   B+ +=C(TzClientTools-EventLoop)targetdaemonname)r1   is_setr+   Threadr/   r   wait)r   r=   s   ` r   r   zClientTools.startJ   sT    ==!		" !''~dQhir   c                    | j                   r| j                  j                         rf| j                   j                  | j                   j                         | j
                  j                          | j                  j                  d       yyy)z6Gracefully stop the event loop and clean up resources.F)rC   N)	r.   r1   rA   call_soon_threadsafer   r/   joinr2   shutdownr   s    r   r   zClientTools.stop_   s`    ::$--..0JJ++DJJOO<LL%%5%1 1:r   	tool_namehandleris_asyncreturnNc                     | 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)r-   callable
ValueErrorr*   )r   rH   rI   rJ   s       r   registerzClientTools.registerf   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.
        rM   z' is not registeredN)r-   r*   rO   r6   get_event_looprun_in_executorr2   )r   rH   rQ   rI   rJ   s        r   handlezClientTools.handlez   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       fd}t        j                   |        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 runningc                     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)Nclient_tool_resulttool_call_idzClient tool: z called successfully.F)typerZ   resultis_errorT)rU   get	Exceptionstr)r\   responseerV   rQ   r   rH   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=N)r1   rA   RuntimeErrorr6   run_coroutine_threadsafer.   )r   rH   rQ   rV   rc   s   ```` r   execute_toolzClientTools.execute_tool   s@    
 }}##%FGG	$ 	(()>)@$**Mr   )F)r!   r"   r#   r$   r3   r   r   r`   r   r   dictr	   r   boolrP   rU   rf   r   r   r   r'   r'   ;   s    0*2 	88 x,hvy~7M.NNO8 	8
 
8(ic it i iNc Nt NxQUPVX\P\G] Nr   r'   c                   >    e Zd ZdZ	 	 	 d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_variablesc                 F    |xs i | _         |xs i | _        |xs i | _        y r)   )rk   rl   rm   )r   rk   rl   rm   s       r   r3   z#ConversationInitiationData.__init__   s*     %*,H,NB)!2!8br   )NNN)r!   r"   r#   r$   r   rg   r3   r   r   r   rj   rj      s=    5 &*7;,0	9TN9 '/tn9 $D>	9r   rj   c                      e Zd ZU eed<   eed<   eed<   eed<   eed<   e	e
   ed<   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j                     ed<   ej                  ed<   e	e   ed<   eed<   dddddddded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gdf      de	eegdf      fdZd Zd Zde	e   fdZdefdZd Zd Zd Zy)Conversationclientagent_idrequires_authconfigaudio_interfaceclient_toolsNcallback_agent_response"callback_agent_response_correctioncallback_user_transcriptcallback_latency_measurementr/   _should_stop_conversation_id_last_interrupt_id)rt   rv   rw   rx   ry   rz   c                P   || _         || _        || _        || _        || _        |xs
 t               | _        |xs
 t               | _        || _	        |	| _
        |
| _        | j                  j                          d| _        t        j                         | _        d| _        d| _        y)a  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.
            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_user_transcript: Callback for user transcripts.
            callback_latency_measurement: Callback for latency measurements (in milliseconds).
        Nr   )rq   rr   rs   ru   rw   rj   rt   r'   rv   rx   ry   rz   r   r/   r+   r0   r{   r|   r}   )r   rq   rr   rs   ru   rt   rv   rw   rx   ry   rz   s              r   r3   zConversation.__init__   s    @  *.'>$< : <(9KM2T/(@%,H)!%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)rs   _get_signed_url_get_wss_urlr+   rB   _runr/   r   )r   ws_urls     r   start_sessionzConversation.start_session   sO    
 ,0+=+=%%'4CTCTCV ''tyyyIr   c                     | j                   j                          | j                  j                          | j                  j	                          y)z6Ends the conversation session and cleans up resources.N)ru   r   rv   r{   r9   r   s    r   end_sessionzConversation.end_session   s8    !!# r   rK   c                 |    | j                   st        d      | j                   j                          | j                  S )zWaits 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.
        zSession not started.)r/   rd   rF   r|   r   s    r   wait_for_session_endz!Conversation.wait_for_session_end  s3     ||566$$$r   r   c           
      8    t        |d      5 j                  t        j                  d j                  j
                   j                  j                   j                  j                  d              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        y # t        $ r} j!                          Y d }~Bd }~wt"        $ r Y Pt$        $ r(}t'        d|         j!                          Y d }~{d }~ww xY w# 1 sw Y   y xY w)	Ni   )max_size#conversation_initiation_client_data)r[   custom_llm_extra_bodyrl   rm   c                 2   	 j                  t        j                  dt        j                  |       j                         i             y # t        $ r j                          Y y t        $ r(}t        d|        j                          Y d }~y d }~ww xY w)Nuser_audio_chunkz Error sending user audio chunk: )
sendjsondumpsbase64	b64encodedecoder   r   r_   print)r   rb   r   wss     r   r   z)Conversation._run.<locals>.input_callback  s    'GG

 2F4D4DU4K4R4R4T * '$$&  '<QC@A$$&&'s   AA B&B.BBg      ?)timeoutzError receiving message: )r   r   r   r   rt   rk   rl   rm   ru   r   r{   rA   loadsrecv_handle_messager   r   TimeoutErrorr_   r   )r   r   r   messagerb   r   s   `    @r   r   zConversation._run  sY   V&67 (	'2GG

 E151G1G8<8`8`-1[[-J-J		'   &&~6''..0'"jj)=>G((//1A(	' (	'B (("5 ''..09(	' (	'D * '$$&&#   '5aS9:$$&&'M(	' (	'sZ   B!F2?D1;D1F1	F:E
FFFF%FFFFFc                     |d   dk(  r|d   } j                   J |d    _         y |d   dk(  rU|d   }t        |d          j                  k  ry t        j                  |d         } j
                  j                  |       y |d   d	k(  r5 j                  r(|d
   } j                  |d	   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(  r3|d   }t        |d          _         j
                  j                          y |d   dk(  r`|d   }j                  t        j                  d|d   d              j                  r$|d   r j                  t        |d                y y y |d   dk(  r`|j!                  di       }|j!                  d      }d|d   i|j!                  di       } fd} j"                  j%                  |||       y y )Nr[    conversation_initiation_metadata&conversation_initiation_metadata_eventconversation_idr   audio_eventevent_idaudio_base_64agent_responseagent_response_eventagent_response_correctionagent_response_correction_eventoriginal_agent_responsecorrected_agent_responseuser_transcriptuser_transcription_eventinterruptioninterruption_eventping
ping_eventpong)r[   r   ping_msclient_tool_callrH   rZ   rQ   c                     j                   j                         s%j                  t        j                  |              y y r)   )r{   rA   r   r   r   )ra   r   r   s    r   send_responsez3Conversation._handle_message.<locals>.send_responsel  s/    ((//1GGDJJx01 2r   )r|   intr}   r   	b64decoderu   r   rw   striprx   ry   r    r   r   r   rz   r^   rv   rf   )	r   r   r   eventr   	tool_callrH   rQ   r   s	   ` `      r   r   zConversation._handle_message=  s   6?@@DEE((000$)*;$<D!V_'M*E5$%)@)@@$$U?%;<E  ''.V_ 00++ 67,,U3C-D-J-J-LM , V_ ;;66 AB7734::<eD^>_>e>e>g 7
 V_ 11,, :;--e4E.F.L.L.NO - V_.01E&)%
*;&<D#  **,V_&L)EGG

 &$)*$5 00U95E11#eI6F2GH 6F0V_ 22$6;I!k2I()N*Cgy}}UaceGfgJ2 **9j-Pr   c                     | j                   j                  j                  }|j                  ddd      }| d| j                   S )Nhttpr      z!/v1/convai/conversation?agent_id=)rq   _client_wrapper	_base_urlreplacerr   )r   base_urlbase_ws_urls      r   r   zConversation._get_wss_urlt  sA    ;;..88&&vtQ7?OOr   c                 z    | j                   j                  j                  | j                        }|j                  S )N)rr   )rq   conversational_aiget_signed_urlrr   
signed_url)r   ra   s     r   r   zConversation._get_signed_urlz  s/    ;;00???W"""r   )r!   r"   r#   r   __annotations__r`   rh   rj   r   r   r'   r   r   r+   rB   r0   r3   r   r   r   r   r   r   r   r   r   r   rp   rp      s   M&&##;''%hud{&;<<(03*d:J1K(LL&xt'<=="*8SE4K+@"AAi&&''//!sm# 8<.2CGSWDHHL0$0$ 0$
 0$ (0$ 340$ {+0$ "*(C5$;*?!@0$ -5XsCj$>N5O,P0$ #+8SE4K+@"A0$ '/xt/D&E0$d 
%hsm 
%)'3 )'V5nP#r   rp   )abcr   r   r   r   r+   typingr   r   r   r   r	   r6   concurrent.futuresr
   websockets.sync.clientr   websockets.exceptionsr   base_clientr   r   r'   rj   rp   r   r   r   <module>r      sX    #    < <  1 * 4 ()S )XhN hNV9 9H# H#r   