§
    öŽ’jý  ã                   óÔ   — d Z ddlmZmZ ddlmZmZ ddlmZmZ ddl	m
Z
mZ ddlZddlmZ ddlmZmZmZ e G d	„ d
¦  «        ¦   «         Z G d„ de¦  «        Z G d„ de¦  «        ZdS )a)  
TaskMessageQueue - FIFO queue for task-related messages.

This implements the core message queue pattern from the MCP Tasks spec.
When a handler needs to send a request (like elicitation) during a task-augmented
request, the message is enqueued instead of sent directly. Messages are delivered
to the client only through the `tasks/result` endpoint.

This pattern enables:
1. Decoupling request handling from message delivery
2. Proper bidirectional communication via the tasks/result stream
3. Automatic status management (working <-> input_required)
é    )ÚABCÚabstractmethod)Ú	dataclassÚfield)ÚdatetimeÚtimezone)ÚAnyÚLiteralN)ÚResolver)ÚJSONRPCNotificationÚJSONRPCRequestÚ	RequestIdc                   óª   — e Zd ZU dZed         ed<   	 eez  ed<   	  ed„ ¬¦  «        Z	e
ed<   	 dZeeeef                  dz  ed	<   	 dZedz  ed
<   dS )ÚQueuedMessagez™
    A message queued for delivery via tasks/result.

    Messages are stored with their type and a resolver for requests
    that expect responses.
    )ÚrequestÚnotificationÚtypeÚmessagec                  ó>   — t          j        t          j        ¦  «        S ©N)r   Únowr   Úutc© ó    úYC:\Projects\DSCons\.venv\Lib\site-packages\mcp\shared\experimental\tasks\message_queue.pyú<lambda>zQueuedMessage.<lambda>)   s   € ½¼ÅXÄ\Ñ8RÔ8R€ r   )Údefault_factoryÚ	timestampNÚresolverÚoriginal_request_id)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r
   Ú__annotations__r   r   r   r   r   r   r   ÚdictÚstrr	   r    r   r   r   r   r   r      s§   € € € € € € ðð ð Ð+Ô
,Ð,Ð,Ñ,ØQàÐ1Ñ1Ð1Ð1Ñ1Ø'à˜%Ð0RÐ0RÐSÑSÔS€IˆxÐSÐSÑSØ(à04€Hˆh�t˜C ˜H”~Ô&¨Ñ-Ð4Ð4Ñ4ØDà,0Ð˜ TÑ)Ð0Ð0Ñ0ØNÐNr   r   c                   ó  — e Zd ZdZedededdfd„¦   «         Zedededz  fd„¦   «         Zedededz  fd„¦   «         Z	edede
fd	„¦   «         Zededee         fd
„¦   «         Zededdfd„¦   «         Zededdfd„¦   «         ZdS )ÚTaskMessageQueuea"  
    Abstract interface for task message queuing.

    This is a FIFO queue that stores messages to be delivered via `tasks/result`.
    When a task-augmented handler calls elicit() or sends a notification, the
    message is enqueued here instead of being sent directly to the client.

    The `tasks/result` handler then dequeues and sends these messages through
    the transport, with `relatedRequestId` set to the tasks/result request ID
    so responses are routed correctly.

    Implementations can use in-memory storage, Redis, etc.
    Útask_idr   ÚreturnNc              ƒ   ó
   K  — dS )zœ
        Add a message to the queue for a task.

        Args:
            task_id: The task identifier
            message: The message to enqueue
        Nr   )Úselfr*   r   s      r   ÚenqueuezTaskMessageQueue.enqueueB   ó
   è è € € € r   c              ƒ   ó
   K  — dS )zÆ
        Remove and return the next message from the queue.

        Args:
            task_id: The task identifier

        Returns:
            The next message, or None if queue is empty
        Nr   ©r-   r*   s     r   ÚdequeuezTaskMessageQueue.dequeueL   r/   r   c              ƒ   ó
   K  — dS )zÀ
        Return the next message without removing it.

        Args:
            task_id: The task identifier

        Returns:
            The next message, or None if queue is empty
        Nr   r1   s     r   ÚpeekzTaskMessageQueue.peekX   r/   r   c              ƒ   ó
   K  — dS )z®
        Check if the queue is empty for a task.

        Args:
            task_id: The task identifier

        Returns:
            True if no messages are queued
        Nr   r1   s     r   Úis_emptyzTaskMessageQueue.is_emptyd   r/   r   c              ƒ   ó
   K  — dS )a  
        Remove and return all messages from the queue.

        This is useful for cleanup when a task is cancelled or completed.

        Args:
            task_id: The task identifier

        Returns:
            All queued messages (may be empty)
        Nr   r1   s     r   ÚclearzTaskMessageQueue.clearp   r/   r   c              ƒ   ó
   K  — dS )zì
        Wait until a message is available in the queue.

        This blocks until either:
        1. A message is enqueued for this task
        2. The wait is cancelled

        Args:
            task_id: The task identifier
        Nr   r1   s     r   Úwait_for_messagez!TaskMessageQueue.wait_for_message~   r/   r   c              ƒ   ó
   K  — dS )z½
        Signal that a message is available for a task.

        This wakes up any coroutines waiting in wait_for_message().

        Args:
            task_id: The task identifier
        Nr   r1   s     r   Únotify_message_availablez)TaskMessageQueue.notify_message_available‹   r/   r   )r!   r"   r#   r$   r   r'   r   r.   r2   r4   Úboolr6   Úlistr8   r:   r<   r   r   r   r)   r)   3   sv  € € € € € ðð ð ð Sð °=ð ÀTð ð ð ñ „^ðð ð	 Sð 	¨]¸TÑ-Að 	ð 	ð 	ñ „^ð	ð ð	 #ð 	¨-¸$Ñ*>ð 	ð 	ð 	ñ „^ð	ð ð	 cð 	¨dð 	ð 	ð 	ñ „^ð	ð ð 3ð ¨4°Ô+>ð ð ð ñ „^ðð ð
¨cð 
°dð 
ð 
ð 
ñ „^ð
ð ð°cð ¸dð ð ð ñ „^ðð ð r   r)   c                   óÚ   — e Zd ZdZdd„Zdedee         fd„Zdededdfd„Z	dededz  fd	„Z
dededz  fd
„Zdedefd„Zdedee         fd„Zdeddfd„Zdeddfd„Zddedz  ddfd„ZdS )ÚInMemoryTaskMessageQueueaA  
    In-memory implementation of TaskMessageQueue.

    This is suitable for single-process servers. For distributed systems,
    implement TaskMessageQueue with Redis, RabbitMQ, etc.

    Features:
    - FIFO ordering per task
    - Async wait for message availability
    - Thread-safe for single-process async use
    r+   Nc                 ó"   — i | _         i | _        d S r   )Ú_queuesÚ_events)r-   s    r   Ú__init__z!InMemoryTaskMessageQueue.__init__¤   s   € Ø79ˆŒØ/1ˆŒˆˆr   r*   c                 óB   — || j         vr
g | j         |<   | j         |         S )z#Get or create the queue for a task.)rB   r1   s     r   Ú
_get_queuez#InMemoryTaskMessageQueue._get_queue¨   s(   € à˜$œ,Ð&Ð&Ø$&ˆDŒL˜Ñ!ØŒ|˜GÔ$Ð$r   r   c              ƒ   ó”   K  — |                       |¦  «        }|                     |¦  «         |                      |¦  «        ƒ d{V —† dS )zAdd a message to the queue.N)rF   Úappendr<   )r-   r*   r   Úqueues       r   r.   z InMemoryTaskMessageQueue.enqueue®   sU   è è € à—’ Ñ(Ô(ˆØ�Š�WÑÔÐà×+Ò+¨GÑ4Ô4Ð4Ð4Ð4Ð4Ð4Ð4Ð4Ð4Ð4r   c              ƒ   ób   K  — |                       |¦  «        }|sdS |                     d¦  «        S )z#Remove and return the next message.Nr   )rF   Úpop©r-   r*   rI   s      r   r2   z InMemoryTaskMessageQueue.dequeueµ   s4   è è € à—’ Ñ(Ô(ˆØð 	Ø�4Ø�yŠy˜‰|Œ|Ðr   c              ƒ   óH   K  — |                       |¦  «        }|sdS |d         S )z,Return the next message without removing it.Nr   )rF   rL   s      r   r4   zInMemoryTaskMessageQueue.peek¼   s-   è è € à—’ Ñ(Ô(ˆØð 	Ø�4Ø�QŒxˆr   c              ƒ   óV   K  — |                       |¦  «        }t          |¦  «        dk    S )zCheck if the queue is empty.r   )rF   ÚlenrL   s      r   r6   z!InMemoryTaskMessageQueue.is_emptyÃ   s'   è è € à—’ Ñ(Ô(ˆÝ�5‰zŒz˜QŠÐr   c              ƒ   óz   K  — |                       |¦  «        }t          |¦  «        }|                     ¦   «          |S )zRemove and return all messages.)rF   r>   r8   )r-   r*   rI   Úmessagess       r   r8   zInMemoryTaskMessageQueue.clearÈ   s4   è è € à—’ Ñ(Ô(ˆÝ˜‘;”;ˆØ�Š‰ŒˆØˆr   c              ƒ   ó  K  — |                       |¦  «        ƒ d{V —†sdS t          j        ¦   «         | j        |<   | j        |         }|                       |¦  «        ƒ d{V —†sdS |                     ¦   «         ƒ d{V —† dS )z"Wait until a message is available.N)r6   ÚanyioÚEventrC   Úwait)r-   r*   Úevents      r   r:   z)InMemoryTaskMessageQueue.wait_for_messageÏ   s¨   è è € ð —]’] 7Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+ð 	ØˆFõ !&¤¡¤ˆŒ�WÑØ”˜WÔ%ˆð —]’] 7Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+ð 	ØˆFð �jŠj‰lŒlÐÐÐÐÐÐÐÐÐr   c              ƒ   ó^   K  — || j         v r!| j         |                              ¦   «          dS dS )z#Signal that a message is available.N)rC   Úsetr1   s     r   r<   z1InMemoryTaskMessageQueue.notify_message_availableà   s:   è è € à�d”lÐ"Ð"ØŒL˜Ô!×%Ò%Ñ'Ô'Ð'Ð'Ð'ð #Ð"r   c                 óÞ   — |�8| j                              |d¦  «         | j                             |d¦  «         dS | j                              ¦   «          | j                             ¦   «          dS )z�
        Clean up queues and events.

        Args:
            task_id: If provided, clean up only this task. Otherwise clean up all.
        N)rB   rK   rC   r8   r1   s     r   Úcleanupz InMemoryTaskMessageQueue.cleanupå   sn   € ð ÐØŒL×Ò˜W dÑ+Ô+Ð+ØŒL×Ò˜W dÑ+Ô+Ð+Ð+Ð+àŒL×ÒÑ Ô Ð ØŒL×ÒÑ Ô Ð Ð Ð r   )r+   Nr   )r!   r"   r#   r$   rD   r'   r>   r   rF   r.   r2   r4   r=   r6   r8   r:   r<   rZ   r   r   r   r@   r@   —   sˆ  € € € € € ð
ð 
ð2ð 2ð 2ð 2ð% #ð %¨$¨}Ô*=ð %ð %ð %ð %ð5 Sð 5°=ð 5ÀTð 5ð 5ð 5ð 5ð Sð ¨]¸TÑ-Að ð ð ð ð #ð ¨-¸$Ñ*>ð ð ð ð ð cð ¨dð ð ð ð ð
 3ð ¨4°Ô+>ð ð ð ð ð¨cð °dð ð ð ð ð"(°cð (¸dð (ð (ð (ð (ð
!ð !˜s T™zð !°Tð !ð !ð !ð !ð !ð !r   r@   )r$   Úabcr   r   Údataclassesr   r   r   r   Útypingr	   r
   rS   Ú&mcp.shared.experimental.tasks.resolverr   Ú	mcp.typesr   r   r   r   r)   r@   r   r   r   ú<module>r`      sX  ððð ð $Ð #Ð #Ð #Ð #Ð #Ð #Ð #Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø Ð Ð Ð Ð Ð Ð Ð à €€€à ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø DÐ DÐ DÐ DÐ DÐ DÐ DÐ DÐ DÐ Dð ðOð Oð Oð Oð Oñ Oô Oñ „ðOð0að að að að a�sñ aô að aðHZ!ð Z!ð Z!ð Z!ð Z!Ð/ñ Z!ô Z!ð Z!ð Z!ð Z!r   