
    "<iT                    (   d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	m
Z
 ddlmZmZ ddlmZmZmZ ddlZddlmZ ddlmZmZmZmZ dd	lmZmZ dd
lmZmZ ddlmZ  ee           Z!erddl"m#Z#m$Z$ ddZ% G d de          Z& ed          Z' G d dej(        ee'                   Z) G d de)d                   Z* G d de)ej+        j,                           Z- G d de)e.ej+        j/        ej+        j0        z                              Z1dS )zSEP-1686 client Task classes.    )annotationsN)	AwaitableCallable)datetimetimezone)TYPE_CHECKINGGenericTypeVar)ClientSession)SUPPORTED_PROTOCOL_VERSIONS_default_elicitation_callback_default_list_roots_callback_default_sampling_callback)GetTaskResultTaskStatusNotification)MessageMessageHandler)
get_logger)CallToolResultClientsessionr   returnmcp.types.InitializeResultc                  K   | j         t          k    rt          j                                        nd}| j        t          k    rt          j                                        nd}| j        t          k    r t          j        
                    d          nd}|                     t          j                            t          j                            t          j                            t          j        j        t          j                            ||di i|          | j                                      t          j        j                   d{V }|j        t(          vrt+          d|j                   |j        | _        |                     t          j                            t          j                                                             d{V  |S )	z5Initialize a session with task capabilities declared.NT)listChangedtasks)samplingelicitationexperimentalroots)protocolVersioncapabilities
clientInfo)paramsz.Unsupported protocol version from the server: )_sampling_callbackr   mcptypesSamplingCapability_elicitation_callbackr   ElicitationCapability_list_roots_callbackr   RootsCapabilitysend_requestClientRequestInitializeRequestInitializeRequestParamsLATEST_PROTOCOL_VERSIONClientCapabilities_client_infoInitializeResultr!   r   RuntimeErrorr"   _server_capabilitiessend_notificationClientNotificationInitializedNotification)r   r   r   r    results        /Users/kimhansen/Desktop/03 Workspace/ceo-agents/chl-effectiveness/mcp-servers/whoop/.venv/lib/python3.11/site-packages/fastmcp/client/tasks.py_task_capable_initializer<   %   s      %)CCC 		$$&&&  (,III 		'')))  '+GGG 		!!d!333 
 ''	I''y88$'I$E!$!=!=!)$/&-r]#	 "> " "  '3 9 	 	 (  	
 	
 		"       F$ %@@@UV=SUU
 
 	
 $*#6G 

#
#	$$SY%F%F%H%HII         M    c                  0     e Zd ZdZd
 fdZd fd	Z xZS )TaskNotificationHandlerzEMessageHandler that routes task status notifications to Task objects.clientr   c                z    t                                                       t          j        |          | _        d S N)super__init__weakrefref_client_ref)selfr@   	__class__s     r;   rD   z TaskNotificationHandler.__init__\   s1    07F0C0Cr=   messager   r   Nonec                ,  K   t          |t          j        j                  rJt          |j        t
                    r0|                                 }|r|                    |j                   t                      	                    |           d{V  dS )z7Dispatch messages, including task status notifications.N)

isinstancer&   r'   ServerNotificationrootr   rG    _handle_task_status_notificationrC   dispatch)rH   rJ   r@   rI   s      r;   rQ   z TaskNotificationHandler.dispatch`   s      gsy;<< 	J',(>?? J))++ J;;GLIIIggw'''''''''''r=   )r@   r   )rJ   r   r   rK   )__name__
__module____qualname____doc__rD   rQ   __classcell__rI   s   @r;   r?   r?   Y   sg        OOD D D D D D( ( ( ( ( ( ( ( ( (r=   r?   TaskResultTc                      e Zd ZdZ	 d"d#d	Zd$dZed%d            Zed&d            Zd'dZ	d(dZ
d)dZej        d*d            Zdddd+dZd$d Zd! ZdS ),Taska  
    Abstract base class for MCP background tasks (SEP-1686).

    Provides a uniform API whether the server accepts background execution
    or executes synchronously (graceful degradation per SEP-1686).

    Subclasses:
        - ToolTask: For tool calls (result type: CallToolResult)
        - PromptTask: For prompts (future, result type: GetPromptResult)
        - ResourceTask: For resources (future, result type: ReadResourceResult)
    Nr@   r   task_idstrimmediate_resultTaskResultT | Nonec                z    || _         || _        || _        |du| _        d| _        d| _        g | _        d| _        dS )z
        Create a Task wrapper.

        Args:
            client: The FastMCP client
            task_id: The task identifier
            immediate_result: If server executed synchronously, the immediate result
        N)_client_task_id_immediate_result_is_immediate_status_cache_status_event_status_callbacks_cached_result)rH   r@   r[   r]   s       r;   rD   zTask.__init__{   sV     !1-T9 4837  	 37r=   r   rK   c                v    | j         rdS 	 | j        j        }dS # t          $ r}t          d          |d}~ww xY w)zValidate that client context is still active.

        Raises:
            RuntimeError: If accessed outside client context (unless immediate)
        NzoCannot access task results outside client context. Task futures must be used within 'async with client:' block.)rc   r`   r   r5   )rH   _es      r;   _check_client_connectedzTask._check_client_connected   sc      	F	$AAA 	 	 	O  	s    
838c                    | j         S )zGet the task ID.)ra   rH   s    r;   r[   zTask.task_id   s     }r=   boolc                    | j         S )zCheck if server executed the task immediately.

        Returns:
            True if server executed synchronously (graceful degradation or no task support)
            False if server accepted background execution
        )rc   rm   s    r;   returned_immediatelyzTask.returned_immediately   s     !!r=   statusr   c                <   || _         | j        | j                                         | j        D ]l}	  ||          }t	          j        |          rt          j        |           7# t          $ r)}t          
                    d| d           Y d}~ed}~ww xY wdS )a  Process incoming notifications/tasks/status (internal).

        Called by Client when a notification is received for this task.
        Updates cache, triggers events, and invokes user callbacks.

        Args:
            status: Task status from notification
        NzTask callback error: T)exc_info)rd   re   setrf   inspectisawaitableasynciocreate_task	Exceptionloggerwarning)rH   rq   callbackr:   rj   s        r;   _handle_status_notificationz Task._handle_status_notification   s     $ )""$$$ . 	K 	KHK!&))&v.. 0'/// K K K:q::TJJJJJJJJK	K 	Ks   3A&&
B0BBr|   1Callable[[GetTaskResult], None | Awaitable[None]]c                :    | j                             |           dS )a>  Register callback for status change notifications.

        The callback will be invoked when a notifications/tasks/status is received
        for this task (optional server feature per SEP-1686 lines 436-444).

        Supports both sync and async callbacks (auto-detected).

        Args:
            callback: Function to call with GetTaskResult when status changes.
                     Can return None (sync) or Awaitable[None] (async).

        Example:
            >>> task = await client.call_tool("slow_operation", {}, task=True)
            >>>
            >>> def on_update(status: GetTaskResult):
            ...     print(f"Task {status.taskId} is now {status.status}")
            >>>
            >>> task.on_status_change(on_update)
            >>> result = await task  # Callback fires when status changes
        N)rf   append)rH   r|   s     r;   on_status_changezTask.on_status_change   s!    0 	%%h/////r=   c                .  K   |                                   | j        r8t          j        t          j                  }t          | j        d||dd          S | j        	| j        }|S | j	        
                    | j                   d{V | _        | j        S )zGet current task status.

        If server executed immediately, returns synthetic completed status.
        Otherwise queries the server for current status.
        	completedNi  )taskIdrq   	createdAtlastUpdatedAtttlpollInterval)rk   rc   r   nowr   utcr   ra   rd   r`   get_task_status)rH   r   cacheds      r;   rq   zTask.status   s       	$$&&& 
	,x|,,C }"!!    )'FM $(<#?#?#N#NNNNNNN!!r=   rX   c                
   K   dS )zWait for and return the task result.

        Must be implemented by subclasses to return the appropriate result type.
        N rm   s    r;   r:   zTask.result  s       	r=   g     r@)statetimeoutr   
str | Noner   floatc          	       K   |                                   | j        r|                                  d{V S | j        t	          j                    | _        t          j                    }h d}d}	 | j        r'| j        j        }|||v r| j        S n||k    r| j        S t          j                    |z
  }||k    r t          d| j	         d|pd d| d	          ||z
  }	 t	          j
        | j                                        t          ||          
           d{V  | j                                         n?# t          j        $ r- | j                            | j	                   d{V | _        Y nw xY w)a  Wait for task to reach a specific state or complete.

        Uses event-based waiting when notifications are available (fast),
        with fallback to polling (reliable). Optimally wakes up immediately
        on status changes when server sends notifications/tasks/status.

        Args:
            state: Desired state ('submitted', 'working', 'completed', 'failed').
                   If None, waits for any terminal state (completed/failed)
            timeout: Maximum time to wait in seconds

        Returns:
            GetTaskResult: Final task status

        Raises:
            TimeoutError: If desired state not reached within timeout
        N>   failed	cancelledr   g      ?TzTask z did not reach zterminal statez within s)r   )rk   rc   rq   re   rw   Eventtimerd   TimeoutErrorra   wait_forwaitminclearr`   r   )	rH   r   r   startterminal_statespoll_intervalcurrentelapsed	remainings	            r;   r   z	Task.wait  s     ( 	$$&&& 	'&&&&&&& %!(D	>>>	W! .,3=/11#11 2%%-- ikkE)G'!!"gDMgg%:SCSgg]dggg    ')IW&&++--s=)7T7T          "((****' W W W+/<+G+G+V+V%V%V%V%V%V%V"""W3	Ws   !AD< <9E87E8c                   K   | j         rdS |                                  | j                            | j                   d{V  d| _        dS )aO  Cancel this task, transitioning it to cancelled state.

        Sends a tasks/cancel protocol request. The server will attempt to halt
        execution and move the task to cancelled state.

        Note: If server executed immediately (graceful degradation), this is a no-op
        as there's no server-side task to cancel.
        N)rc   rk   r`   cancel_taskra   rd   rm   s    r;   cancelzTask.cancelO  sb        	F$$&&&l&&t}555555555!r=   c                N    |                                                                  S )z!Allow 'await task' to get result.)r:   	__await__rm   s    r;   r   zTask.__await__`  s    {{}}&&(((r=   rB   )r@   r   r[   r\   r]   r^   )r   rK   )r   r\   )r   rn   )rq   r   r   rK   )r|   r~   r   rK   )r   r   )r   rX   )r   r   r   r   r   r   )rR   rS   rT   rU   rD   rk   propertyr[   rp   r}   r   rq   abcabstractmethodr:   r   r   r   r   r=   r;   rZ   rZ   n   sC       
 
  04	7 7 7 7 76   "    X " " " X"K K K K40 0 0 04" " " "< 	    &*E=W =W =W =W =W =W~" " " "") ) ) ) )r=   rZ   c                  0     e Zd ZdZ	 dd fd
ZddZ xZS )ToolTaskaM  
    Represents a tool call that may execute in background or immediately.

    Provides a uniform API whether the server accepts background execution
    or executes synchronously (graceful degradation per SEP-1686).

    Usage:
        task = await client.call_tool_as_task("analyze", args)

        # Check status
        status = await task.status()

        # Wait for completion
        await task.wait()

        # Get result (waits if needed)
        result = await task.result()  # Returns CallToolResult

        # Or just await the task directly
        result = await task
    Nr@   r   r[   r\   	tool_namer]   CallToolResult | Nonec                \    t                                          |||           || _        dS )a  
        Create a ToolTask wrapper.

        Args:
            client: The FastMCP client
            task_id: The task identifier
            tool_name: Name of the tool being executed
            immediate_result: If server executed synchronously, the immediate result
        N)rC   rD   
_tool_name)rH   r@   r[   r   r]   rI   s        r;   rD   zToolTask.__init__|  s-      	*:;;;#r=   r   r   c                X  K   | j         | j         S | j        r| j        J | j        }ny|                                  |                                  d{V  | j                            | j                   d{V }t          |t                    rMt          j        j                            |          }| j                            | j        |d           d{V }nt          |t          j        j                  r)| j                            | j        |d           d{V }n|t!          |d          rjt!          |d          rZt          j                            |j        |j        |j                  }| j                            | j        |d           d{V }n|}|| _         |S )a#  Wait for and return the tool result.

        If server executed immediately, returns the immediate result.
        Otherwise waits for background task to complete and retrieves result.

        Returns:
            CallToolResult: The parsed tool result (same as call_tool returns)
        NT)raise_on_errorcontentstructured_content)r   structuredContent_meta)rg   rc   rb   rk   r   r`   get_task_resultra   rM   dictr&   r'   r   model_validate_parse_call_tool_resultr   hasattrr   r   meta)rH   r:   
raw_result
mcp_results       r;   r:   zToolTask.result  s(      *&& (	()555+FF ((*** ))++  $|;;DMJJJJJJJJJ *d++ ( Y5DDZPP
#|CCOZ  D           J	(@AA (#|CCOZ  D          
 :y11 (g 47 7 ( "%!9!9 * 2*4*G(o ": " "J
 $(<#G#GD $H $ $      FF
 (F %r=   rB   )r@   r   r[   r\   r   r\   r]   r   )r   r   rR   rS   rT   rU   rD   r:   rV   rW   s   @r;   r   r   e  se         6 37$ $ $ $ $ $ $&9 9 9 9 9 9 9 9r=   r   r   c                  0     e Zd ZdZ	 dd fd
ZddZ xZS )
PromptTaskac  
    Represents a prompt call that may execute in background or immediately.

    Provides a uniform API whether the server accepts background execution
    or executes synchronously (graceful degradation per SEP-1686).

    Usage:
        task = await client.get_prompt_as_task("analyze", args)
        result = await task  # Returns GetPromptResult
    Nr@   r   r[   r\   prompt_namer]    mcp.types.GetPromptResult | Nonec                \    t                                          |||           || _        dS )a  
        Create a PromptTask wrapper.

        Args:
            client: The FastMCP client
            task_id: The task identifier
            prompt_name: Name of the prompt being executed
            immediate_result: If server executed synchronously, the immediate result
        N)rC   rD   _prompt_name)rH   r@   r[   r   r]   rI   s        r;   rD   zPromptTask.__init__  s0      	*:;;;'r=   r   mcp.types.GetPromptResultc                R  K   | j         | j         S | j        r| j        J | j        }nw|                                  |                                  d{V  | j                            | j                   d{V }t          j	        j
                            |          }|| _         |S )a#  Wait for and return the prompt result.

        If server executed immediately, returns the immediate result.
        Otherwise waits for background task to complete and retrieves result.

        Returns:
            GetPromptResult: The prompt result with messages and description
        N)rg   rc   rb   rk   r   r`   r   ra   r&   r'   GetPromptResultr   )rH   r:   r   s      r;   r:   zPromptTask.result  s       *&& 	J)555+FF ((*** ))++  $|;;DMJJJJJJJJJ Y.==jIIF %r=   rB   )r@   r   r[   r\   r   r\   r]   r   )r   r   r   rW   s   @r;   r   r     sf        	 	  >B( ( ( ( ( ( (&       r=   r   c                  0     e Zd ZdZ	 dd fd
ZddZ xZS )ResourceTaskaw  
    Represents a resource read that may execute in background or immediately.

    Provides a uniform API whether the server accepts background execution
    or executes synchronously (graceful degradation per SEP-1686).

    Usage:
        task = await client.read_resource_as_task("file://data.txt")
        contents = await task  # Returns list[ReadResourceContents]
    Nr@   r   r[   r\   urir]   Llist[mcp.types.TextResourceContents | mcp.types.BlobResourceContents] | Nonec                \    t                                          |||           || _        dS )a  
        Create a ResourceTask wrapper.

        Args:
            client: The FastMCP client
            task_id: The task identifier
            uri: URI of the resource being read
            immediate_result: If server executed synchronously, the immediate result
        N)rC   rD   _uri)rH   r@   r[   r   r]   rI   s        r;   rD   zResourceTask.__init__  s-    & 	*:;;;			r=   r   Elist[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]c                6  K   | j         | j         S | j        r| j        J | j        }nh|                                  |                                  d{V  | j                            | j                   d{V }t          |t          j
        j                  rt          |j                  }nt          |t                    rd|v rg }|d         D ]}t          |t                    rtd|v r8|                    t          j
        j                            |                     S|                    t          j
        j                            |                     |                    |           |}nt          |t                    r|n|g}|| _         |S )a  Wait for and return the resource contents.

        If server executed immediately, returns the immediate result.
        Otherwise waits for background task to complete and retrieves result.

        Returns:
            list[ReadResourceContents]: The resource contents
        Ncontentsblob)rg   rc   rb   rk   r   r`   r   ra   rM   r&   r'   ReadResourceResultlistr   r   r   BlobResourceContentsr   TextResourceContents)rH   r:   r   parsed_contentsitems        r;   r:   zResourceTask.result0  s      *&& #	V)555+FF ((*** ))++  $|;;DMJJJJJJJJJ *ci&BCC Vj122J-- V*
2J2J"$&z2 5 5D!$-- 
5!T>>+22 #	 > M Md S S    ,22 #	 > M Md S S    (..t4444( (2*d'C'CU* %r=   rB   )r@   r   r[   r\   r   r\   r]   r   )r   r   r   rW   s   @r;   r   r     se        	 	&       ,6 6 6 6 6 6 6 6r=   r   )r   r   r   r   )2rU   
__future__r   r   rw   ru   r   rE   collections.abcr   r   r   r   typingr   r	   r
   	mcp.typesr&   r   mcp.client.sessionr   r   r   r   r   r   fastmcp.client.messagesr   r   fastmcp.utilities.loggingr   rR   rz   fastmcp.client.clientr   r   r<   r?   rX   ABCrZ   r   r'   r   r   r   r   r   r   r   r=   r;   <module>r      s   # # " " " " " " 



     / / / / / / / / ' ' ' ' ' ' ' ' 2 2 2 2 2 2 2 2 2 2                      < ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; 0 0 0 0 0 0	H		 =<<<<<<<<1 1 1 1h( ( ( ( (n ( ( ($ gm$$t) t) t) t) t)37GK( t) t) t)nc c c c ct$% c c cL> > > > >ci/0 > > >BZ Z Z Z Zci,sy/MM	NOZ Z Z Z Zr=   