+
    wi                         R t ^ RIHt ^ RIHt ^ RIHtHt ^ RIHt ^ RI	H
t
 ^ RIHt ^ RIHt ^ RIHtHtHtHtHtHtHtHtHtHt R	tR
tR R ltR R ltR R ltRR R llt]R R l4       t R# )z
Helper functions for pure task management.

These helpers work with pure TaskContext and don't require server dependencies.
For server-integrated task helpers, use mcp.server.experimental.
)AsyncIterator)asynccontextmanager)datetimetimezone)uuid4)McpError)TaskContext)	TaskStore)
INVALID_PARAMSTASK_STATUS_CANCELLEDTASK_STATUS_COMPLETEDTASK_STATUS_FAILEDTASK_STATUS_WORKINGCancelTaskResult	ErrorDataTaskTaskMetadata
TaskStatusz0io.modelcontextprotocol/model-immediate-responsez$io.modelcontextprotocol/related-taskc                0    V ^8  d   QhR\         R\        /# )   statusreturn)r   bool)formats   "Y/home/ubuntu/.local/lib/python3.14/site-packages/mcp/shared/experimental/tasks/helpers.py__annotate__r   &   s     X X
 Xt X    c                *    V \         \        \        39   # )z
Check if a task status represents a terminal state.

Terminal states are those where the task has finished and will not change.

Args:
    status: The task status to check

Returns:
    True if the status is terminal (completed, failed, or cancelled)
)r   r   r   r   s   &r   is_terminalr   &   s     +-?AVWWWr   c                <    V ^8  d   QhR\         R\        R\        /# )r   storetask_idr   )r	   strr   )r   s   "r   r   r   5   s&     1; 1;1;1; 1;r   c                |  "   V P                  V4      G Rj  xL
 pVf   \        \        \        RV 2R7      4      h\	        VP
                  4      '       d)   \        \        \        RVP
                   R2R7      4      hV P                  V\        R7      G Rj  xL
 p\        R/ VP                  4       B #  L L5i)a  
Cancel a task with spec-compliant validation.

Per spec: "Receivers MUST reject cancellation of terminal status tasks
with -32602 (Invalid params)"

This helper validates that the task exists and is not in a terminal state
before setting it to "cancelled".

Args:
    store: The task store
    task_id: The task identifier to cancel

Returns:
    CancelTaskResult with the cancelled task state

Raises:
    McpError: With INVALID_PARAMS (-32602) if:
        - Task does not exist
        - Task is already in a terminal state (completed, failed, cancelled)

Example:
    @server.experimental.cancel_task()
    async def handle_cancel(request: CancelTaskRequest) -> CancelTaskResult:
        return await cancel_task(store, request.params.taskId)
NzTask not found: )codemessagez&Cannot cancel task in terminal state ''r    )
get_taskr   r   r
   r   r   update_taskr   r   
model_dump)r!   r"   taskcancelled_tasks   &&  r   cancel_taskr.   5   s     < ((D|#*7)4
 	
 4;;#@QO
 	
 !,,W=R,SSN:n779::' )$ Ts"   B<B8BB<B:B<:B<c                $    V ^8  d   QhR\         /# )r   r   )r#   )r   s   "r   r   r   i   s      # r   c                 (    \        \        4       4      # )zGenerate a unique task ID.)r#   r   r(   r   r   generate_task_idr1   i   s    uw<r   Nc                J    V ^8  d   QhR\         R\        R,          R\        /# )r   metadatar"   Nr   )r   r#   r   )r   s   "r   r   r   n   s*      4Z 
r   c           	         \         P                  ! \        P                  4      p\	        T;'       g    \        4       \        VVV P                  RR7      # )z
Create a Task object with initial state.

This is a helper for TaskStore implementations.

Args:
    metadata: Task metadata
    task_id: Optional task ID (generated if not provided)

Returns:
    A new Task in "working" status
i  )taskIdr   	createdAtlastUpdatedAtttlpollInterval)r   nowr   utcr   r1   r   r8   )r3   r"   r:   s   && r   create_task_stater<   n   sE      ,,x||
$C,,*,"LL r   c                R    V ^8  d   QhR\         R\        R\        \        ,          /# )r   r"   r!   r   )r#   r	   r   r   )r   s   "r   r   r      s+     *# *#*#*# ;*#r   c               Z  "   VP                  V 4      G Rj  xL
 pVf   \        RV  R24      h\        W!4      p V5x  R#  L*  \         dZ   p\	        TP
                  P                  4      '       g*   TP                  \        T4      4      G Rj  xL 
   Rp?R#  Rp?R# Rp?ii ; i5i)a  
Context manager for safe task execution (pure, no server dependencies).

Loads a task from the store and provides a TaskContext for the work.
If an unhandled exception occurs, the task is automatically marked as failed
and the exception is suppressed (since the failure is captured in task state).

This is useful for distributed workers that don't have a server session.

Args:
    task_id: The task identifier to execute
    store: The task store (must be accessible by the worker)

Yields:
    TaskContext for updating status and completing/failing the task

Raises:
    ValueError: If the task is not found in the store

Example (distributed worker):
    async def worker_process(task_id: str):
        store = RedisTaskStore(redis_url)
        async with task_execution(task_id, store) as ctx:
            await ctx.update_status("Working...")
            result = await do_work()
            await ctx.complete(result)
NzTask z
 not found)	r)   
ValueErrorr   	Exceptionr   r,   r   failr#   )r"   r!   r,   ctxes   &&   r   task_executionrD      s     @ ((D|5	455
d
"C#	 )  # 388??++((3q6""" ,#sE   B+A"B+A  B+B(AB#BB#B+#B((B+)N)!__doc__collections.abcr   
contextlibr   r   r   uuidr   mcp.shared.exceptionsr   %mcp.shared.experimental.tasks.contextr   #mcp.shared.experimental.tasks.storer	   	mcp.typesr
   r   r   r   r   r   r   r   r   r   MODEL_IMMEDIATE_RESPONSE_KEYRELATED_TASK_METADATA_KEYr   r.   r1   r<   rD   r(   r   r   <module>rO      sl    * * '  * = 9     R  C X1;h
6 *# *#r   