
    qi"                         d Z ddlZddlZddlZddlmZmZmZ ddlm	Z	m
Z
mZmZmZmZmZmZ ddlmZmZ  G d de      Zy)z5User idle detection and timeout handling for Pipecat.    N)	AwaitableCallableUnion)BotSpeakingFrameCancelFrameEndFrameFrameFunctionCallInProgressFrameFunctionCallResultFrameUserStartedSpeakingFrameUserStoppedSpeakingFrame)FrameDirectionFrameProcessorc                       e Zd ZdZdeed ged   f   ed egee   f   f   de	f fdZ
deed ged   f   ed egee   f   f   ded egee   f   fdZddZedefd	       Zdd
Zdededdf fdZd fdZddZ xZS )UserIdleProcessora  Monitors user inactivity and triggers callbacks after timeout periods.

    .. deprecated:: 0.0.100
        UserIdleProcessor is deprecated in 0.0.100 and will be removed in a future version.
        Use LLMUserAggregator with user_idle_timeout parameter instead.

    This processor tracks user activity and triggers configurable callbacks when
    users become idle. It starts monitoring only after the first conversation
    activity and supports both basic and retry-based callback patterns.

    Example::

        # Retry callback:
        async def handle_idle(processor: "UserIdleProcessor", retry_count: int) -> bool:
            if retry_count < 3:
                await send_reminder("Are you still there?")
                return True
            return False

        # Basic callback:
        async def handle_idle(processor: "UserIdleProcessor") -> None:
            await send_reminder("Are you still there?")

        processor = UserIdleProcessor(
            callback=handle_idle,
            timeout=5.0
        )
    callbackNtimeoutc                    t        |   di | t        j                  dt               | j                  |      | _        || _        d| _        d| _	        d| _
        d| _        t        j                         | _        y)a  Initialize the user idle processor.

        Args:
            callback: Function to call when user is idle. Can be either a basic
                callback taking only the processor, or a retry callback taking
                the processor and retry count. Retry callbacks should return
                True to continue monitoring or False to stop.
            timeout: Seconds to wait before considering user idle.
            **kwargs: Additional arguments passed to FrameProcessor.
        zUserIdleProcessor is deprecated in 0.0.100 and will be removed in a future version. Use LLMUserAggregator with user_idle_timeout parameter instead.r   FN )super__init__warningswarnDeprecationWarning_wrap_callback	_callback_timeout_retry_count_interrupted_conversation_started
_idle_taskasyncioEvent_idle_event)selfr   r   kwargs	__class__s       X/opt/pipecat/venv/lib/python3.12/site-packages/pipecat/processors/user_idle_processor.pyr   zUserIdleProcessor.__init__9   ss    ( 	"6" 		
 ,,X6!%*""==?    returnc                     t        j                        }t        |j                        dddt        dt
        ffd}|S )zWraps callback to support both basic and retry signatures.

        Args:
            callback: The callback function to wrap.

        Returns:
            A wrapped callback that returns bool to indicate whether to continue monitoring.
        	processorr   retry_countr*   c                 b   K   dk(  r |        d {    y | |       d {   S 7 7 w)N   Tr   )r,   r-   r   param_counts     r(   wrapperz1UserIdleProcessor._wrap_callback.<locals>.wrapperp   s=     ay))) &i===	 * >s   /+/-//)inspect	signaturelen
parametersintbool)r%   r   sigr1   r0   s    `  @r(   r   z UserIdleProcessor._wrap_callback^   sE     )#..)	>%8 	>s 	>t 	> r)   c                 f    | j                   s%| j                  | j                               | _         yy)z4Creates the idle task if it hasn't been created yet.N)r!   create_task_idle_task_handlerr%   s    r(   _create_idle_taskz#UserIdleProcessor._create_idle_task{   s)    "..t/F/F/HIDO r)   c                     | j                   S )z}Get the current retry count.

        Returns:
            The number of times the idle callback has been triggered.
        )r   r<   s    r(   r-   zUserIdleProcessor.retry_count   s        r)   c                 ~   K   | j                   r+| j                  | j                          d{    d| _         yy7 w)z-Stops and cleans up the idle monitoring task.N)r!   cancel_taskr<   s    r(   _stopzUserIdleProcessor._stop   s4     ??""4??333"DO 3s   +=;=frame	directionc                   K   t         |   ||       d{    t        |t        t        f      r3| j                          d{    | j                  ||       d{    y| j                  ||       d{    | j                  s-t        |t        t        f      rd| _        | j                          | j                  rt        |t              r)d| _        d| _        | j                  j                          yt        |t              r"d| _        | j                  j                          yt        |t              r| j                  j                          yt        |t               r"d| _        | j                  j                          yt        |t"              r"d| _        | j                  j                          yyy7 7 ~7 g7 Ow)zProcesses incoming frames and manages idle monitoring state.

        Args:
            frame: The frame to process.
            direction: Direction of the frame flow.
        NTr   F)r   process_frame
isinstancer   r   rA   
push_framer    r   r   r=   r   r   r$   setr   r
   r   )r%   rB   rC   r'   s      r(   rE   zUserIdleProcessor.process_frame   s     g#E9555 eh45**,//%333ooeY/// ))j,.>?/
 *.D&""$ %%%!9:$%!$(!  $$&E#;<$)!  $$&E#34  $$&E#>?$(!  $$&E#:;$)!  $$& < &) 	6
 3 	0sF   GG -GGGG G:G	;EGGG	Gc                    K   t         |           d{    | j                  r| j                          d{    yy7 *7 w)z4Cleans up resources when processor is shutting down.N)r   cleanupr!   rA   )r%   r'   s    r(   rJ   zUserIdleProcessor.cleanup   s;     go??**,  	 s   AA #AAAAc                   K   d}|r`	 t        j                  | j                  j                         | j                         d{    | j                  j                          |r_yy7 ## t         j
                  $ rI | j                  s:| xj                  dz  c_        | j                  | | j                         d{  7  }Y |w xY w# | j                  j                          w xY ww)zMonitors for idle timeout and triggers callbacks.

        Runs in a loop until cancelled or callback indicates completion.
        T)r   Nr/   )
r"   wait_forr$   waitr   TimeoutErrorr   r   r   clear)r%   runnings     r(   r;   z$UserIdleProcessor._idle_task_handler   s     
 )&&t'7'7'<'<'>VVV   &&( V'' L((%%*%$(NN49J9J$KKKGL
   &&(sY   C(<A* A(A* 	C(&C((A* *AC=C >CC	 CC	 	C%%C()r*   N)__name__
__module____qualname____doc__r   r   r   r6   r7   floatr   r   r=   propertyr-   rA   r	   r   rE   rJ   r;   __classcell__)r'   s   @r(   r   r      s   :#+ )*IdO;<)3/4@AC
#+ #+J)*IdO;<)3/4@AC
 
&,io=	>:J
 !S ! !#,' ,'> ,'d ,'\)r)   r   )rT   r"   r2   r   typingr   r   r   pipecat.frames.framesr   r   r   r	   r
   r   r   r   "pipecat.processors.frame_processorr   r   r   r   r)   r(   <module>r[      s<    <    - -	 	 	 Nv) v)r)   