o
    i                     @   sl   d Z ddlmZ ddlmZmZmZ ddlmZ ddl	m
Z
 er&ddlmZ edejdZG d	d
 d
ZdS )a  
Experimental client-side task support.

This module provides client methods for interacting with MCP tasks.

WARNING: These APIs are experimental and may change without notice.

Example:
    # Call a tool as a task
    result = await session.experimental.call_tool_as_task("tool_name", {"arg": "value"})
    task_id = result.task.taskId

    # Get task status
    status = await session.experimental.get_task(task_id)

    # Get task result when complete
    if status.status == "completed":
        result = await session.experimental.get_task_result(task_id, CallToolResult)

    # List all tasks
    tasks = await session.experimental.list_tasks()

    # Cancel a task
    await session.experimental.cancel_task(task_id)
    )AsyncIterator)TYPE_CHECKINGAnyTypeVarN)poll_until_terminal)ClientSessionResultT)boundc                   @   s   e Zd ZdZdddZ	dddd	d
edeeef dB dedeeef dB de	j
f
ddZdede	jfddZdedee defddZ	ddedB de	jfddZdede	jfddZdedee	j fddZdS )ExperimentalClientFeaturesz
    Experimental client features for tasks and other experimental APIs.

    WARNING: These APIs are experimental and may change without notice.

    Access via session.experimental:
        status = await session.experimental.get_task(task_id)
    sessionr   returnNc                 C   s
   || _ d S N)_session)selfr    r   Q/home/ubuntu/.local/lib/python3.10/site-packages/mcp/client/experimental/tasks.py__init__1   s   
z#ExperimentalClientFeatures.__init__i`  )ttlmetaname	argumentsr   r   c                   sZ   d}|durt jjdi |}| jt t jt j||t j|d|ddt j	I dH S )a  Call a tool as a task, returning a CreateTaskResult for polling.

        This is a convenience method for calling tools that support task execution.
        The server will return a task reference instead of the immediate result,
        which can then be polled via `get_task()` and retrieved via `get_task_result()`.

        Args:
            name: The tool name
            arguments: Tool arguments
            ttl: Task time-to-live in milliseconds (default: 60000 = 1 minute)
            meta: Optional metadata to include in the request

        Returns:
            CreateTaskResult containing the task reference

        Example:
            # Create task
            result = await session.experimental.call_tool_as_task(
                "long_running_tool", {"input": "data"}
            )
            task_id = result.task.taskId

            # Poll for completion
            while True:
                status = await session.experimental.get_task(task_id)
                if status.status == "completed":
                    break
                await asyncio.sleep(0.5)

            # Get result
            final = await session.experimental.get_task_result(task_id, CallToolResult)
        N)r   )r   r   task_metaparamsr   )
typesRequestParamsMetar   send_requestClientRequestCallToolRequestCallToolRequestParamsTaskMetadataCreateTaskResult)r   r   r   r   r   r   r   r   r   call_tool_as_task4   s"   (


z,ExperimentalClientFeatures.call_tool_as_tasktask_idc                    .   | j ttjtj|ddtjI dH S )z
        Get the current status of a task.

        Args:
            task_id: The task identifier

        Returns:
            GetTaskResult containing the task status and metadata
        taskIdr   N)r   r   r   r   GetTaskRequestGetTaskRequestParamsGetTaskResultr   r%   r   r   r   get_taskn      


z#ExperimentalClientFeatures.get_taskresult_typec                    s,   | j ttjtj|dd|I dH S )a  
        Get the result of a completed task.

        The result type depends on the original request type:
        - tools/call tasks return CallToolResult
        - Other request types return their corresponding result type

        Args:
            task_id: The task identifier
            result_type: The expected result type (e.g., CallToolResult)

        Returns:
            The task result, validated against result_type
        r'   r   N)r   r   r   r   GetTaskPayloadRequestGetTaskPayloadRequestParams)r   r%   r/   r   r   r   get_task_result   s   

z*ExperimentalClientFeatures.get_task_resultcursorc                    s:   |r	t j|dnd}| jt t j|dt jI dH S )z
        List all tasks.

        Args:
            cursor: Optional pagination cursor

        Returns:
            ListTasksResult containing tasks and optional next cursor
        )r3   Nr   )r   PaginatedRequestParamsr   r   r   ListTasksRequestListTasksResult)r   r3   r   r   r   r   
list_tasks   s   

z%ExperimentalClientFeatures.list_tasksc                    r&   )z
        Cancel a running task.

        Args:
            task_id: The task identifier

        Returns:
            CancelTaskResult with the updated task state
        r'   r   N)r   r   r   r   CancelTaskRequestCancelTaskRequestParamsCancelTaskResultr,   r   r   r   cancel_task   r.   z&ExperimentalClientFeatures.cancel_taskc                 C  s(   t | j|2 z	3 dH W }|V  q6 dS )ak  
        Poll a task until it reaches a terminal status.

        Yields GetTaskResult for each poll, allowing the caller to react to
        status changes (e.g., handle input_required). Exits when task reaches
        a terminal status (completed, failed, cancelled).

        Respects the pollInterval hint from the server.

        Args:
            task_id: The task identifier

        Yields:
            GetTaskResult for each poll

        Example:
            async for status in session.experimental.poll_task(task_id):
                print(f"Status: {status.status}")
                if status.status == "input_required":
                    # Handle elicitation request via tasks/result
                    pass

            # Task is now terminal, get the result
            result = await session.experimental.get_task_result(task_id, CallToolResult)
        N)r   r-   )r   r%   statusr   r   r   	poll_task   s   z$ExperimentalClientFeatures.poll_task)r   r   r   Nr   )__name__
__module____qualname____doc__r   strdictr   intr   r#   r$   r+   r-   typer   r2   r6   r7   r:   r;   r   r=   r   r   r   r   r
   '   sD    
	
:

r
   )rA   collections.abcr   typingr   r   r   	mcp.typesr   %mcp.shared.experimental.tasks.pollingr   mcp.client.sessionr   Resultr   r
   r   r   r   r   <module>   s    