
    i.                       d Z ddlm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
mZ ddlZddlmZ  ej                  e      Ze	rddlmZ dZd	Zd
ZdZ	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZy)aY  Background task elicitation support (SEP-1686).

This module provides elicitation capabilities for background tasks running
in Docket workers. Unlike regular MCP requests, background tasks don't have
an active request context, so elicitation requires special handling:

1. Set task status to "input_required" via Redis
2. Send notifications/tasks/status with elicitation metadata
3. Wait for client to send input via tasks/sendInput
4. Resume task execution with the provided input

This uses the public MCP SDK APIs where possible, with minimal use of
internal APIs for background task coordination.
    )annotationsN)datetimetimezone)TYPE_CHECKINGAnycast)ServerSession)FastMCPz2fastmcp:task:{session_id}:{task_id}:elicit:requestz3fastmcp:task:{session_id}:{task_id}:elicit:responsez1fastmcp:task:{session_id}:{task_id}:elicit:statusi  c           
     	  K   |j                   }|t        d      t        t        j                               }ddlm}  |       }||j                  }	nt        |dd      }	|	t        d      t        j                  |	|       }
t        j                  |	|       }t        j                  |	|       }|||d}|j                         4 d{   }|j                  |j                  |
      t!        j"                  |      t$        	       d{    |j                  |j                  |      d
t$        	       d{    ddd      d{    t'        j(                  t*        j,                        j/                         }d| d|||t$        dz  dd| d||||ddid}ddlm} 	  ||	||       d{    t$        }	 |j                         4 d{   }tC        tD        |jG                  |j                  |      g|             d{   }|r|\  }}t!        jH                  |      }|j;                  |j                  |
      |j                  |             d{    t<        j>                  jA                  |jK                  dd      |jK                  d            cddd      d{    S ddd      d{    	 |j                         4 d{   }|j;                  |j                  |
      |j                  |      |j                  |             d{    ddd      d{    t<        j>                  jA                  dd      S 7 7 Q7 %7 # 1 d{  7  sw Y   )xY w7 # t4        $ r}t6        j9                  d| |       	 |j                         4 d{  7  }|j;                  |j                  |
      |j                  |             d{  7   ddd      d{  7   n# 1 d{  7  sw Y   nxY wn# t4        $ r Y nw xY wt<        j>                  jA                  dd      cY d}~S d}~ww xY w7 7 N7 7 7 # 1 d{  7  sw Y   xY w# t4        $ r"}t6        j9                  d| |       Y d}~d}~ww xY w7 7 7 }# 1 d{  7  sw Y   xY w# t4        $ r"}t6        jM                  d| |       Y d}~d}~ww xY ww)a  Send an elicitation request from a background task.

    This function handles the complexity of eliciting user input when running
    in a Docket worker context where there's no active MCP request.

    Args:
        task_id: The background task ID
        session: The MCP ServerSession for this task
        message: The message to display to the user
        schema: The JSON schema for the expected response
        fastmcp: The FastMCP server instance

    Returns:
        ElicitResult containing the user's response

    Raises:
        RuntimeError: If Docket is not available
        McpError: If the elicitation request fails
    Nz}Background task elicitation requires Docket. Ensure 'fastmcp[tasks]' is installed and the server has task-enabled components.r   )get_task_context_fastmcp_state_prefixzCannot determine session_id for elicitation. This typically means elicit_for_task() was called outside a Docket worker context.
session_idtask_id)
request_idmessageschemaexwaitingznotifications/tasks/statusinput_requiredi  )taskIdstatusstatusMessage	createdAtlastUpdatedAtttlz$io.modelcontextprotocol/related-task)	requestIdr   requestedSchema)r   r   r   elicitation)methodparams_meta)push_notificationzSFailed to queue input_required notification for task %s, cancelling elicitation: %scancelactioncontent)timeoutr'   acceptr(   z@BLPOP failed for task %s elicitation, falling back to cancel: %szIFailed to clean up elicitation keys for task %s (will expire via TTL): %s)'_docketRuntimeErrorstruuiduuid4fastmcp.server.dependenciesr   r   getattrELICIT_REQUEST_KEYformatELICIT_RESPONSE_KEYELICIT_STATUS_KEYredissetkeyjsondumpsELICIT_TTL_SECONDSr   nowr   utc	isoformat"fastmcp.server.tasks.notificationsr$   	ExceptionloggerwarningdeletemcptypesElicitResultr   r   blpoploadsgetdebug)r   sessionr   r   fastmcpdocketr   r   task_contextr   request_keyresponse_key
status_keyelicit_requestr6   	timestampnotification_dictr$   emax_wait_secondsresult_keyresponse_dataresponsecleanup_errors                            p/Users/bowang/.openclaw/workspace/ChatDev/.venv/lib/python3.12/site-packages/fastmcp/server/tasks/elicitation.pyelicit_for_taskr]   *   s    4 __F~_
 	
 TZZ\"J =#%L!,,
 W&=tD
e  %++z7+SK&--W-UL"))Z)QJ !N ||~~iiJJ{#JJ~&!  
 	
 	
 iiJJz"!  
 	
 	
 ~( X\\*446I.&$"&%,
 3!*!(!+&'- 		5
4 EE
,=vFFF. *!
<<>>U  ZZ-.,   F &,#m::m4 llJJ{+JJz*   yy--#<<(;$LL3 . / ">>>>H
<<>>U,,

;'

<(

:&   "> 99!!4!@@} 	
	
 ~~~d 	G E 	a	
	||~~llJJ{+JJz*   &~~~~
  		yy%%Xt%DD#E2 "# ">>>>6  
N	
 	

 " ">>>  
W	
 	

sP  CS<MS<>M*M!.M*?M$ M*S<M'AS<+N 8N 9N =S<R QR 5Q+QAQ+%Q"&AQ+)R 5Q%6R :S<;R Q(R S  R/!S $AR8(R2)R8-S 8R59S ="S<!M*$M*'S<*M=0M31M=8S< N 	QQ$P8N;9P=4P	1O42P	7PPP	P	PP	PQ	P+(Q*P++#QQS<QS<R Q+"Q+%R (R +Q>1Q42Q>9R 	R,
R'!S<'R,,S</S 2R85S 8S>S?SS 	S9S4.S<4S99S<c                  K   	 | j                  |d   |d          d{   }t        |||j                  |j                  |       d{    t        j                  d||j                         y7 R7 (# t        $ rW}t        j                  d||       t        ||dd|       d{  7  }|st        j                  d	|       Y d}~yY d}~yd}~ww xY ww)
aL  Relay elicitation from a background task worker to the client.

    Called by the notification subscriber when it detects an input_required
    notification with elicitation metadata. Sends a standard elicitation/create
    request to the client session, then uses handle_task_input() to push the
    response to Redis so the blocked worker can resume.

    Args:
        session: MCP ServerSession
        session_id: Session identifier
        task_id: Background task ID
        elicitation: Elicitation metadata (message, requestedSchema)
        fastmcp: FastMCP server instance
    r   r   )r   r   N)r   r   r'   r(   rL   z4Relayed elicitation response for task %s (action=%s)z+Failed to relay elicitation for task %s: %sr%   zGFailed to push cancel response for task %s (worker may block until TTL))elicithandle_task_inputr'   r(   rA   rJ   r@   rB   )rK   r   r   r    rL   rW   rU   successs           r\   relay_elicitationrb      s     * ~~	*'(9: & 
 
  !==NN
 	
 	
 	BMM	

	
  DgqQ)!
 
 
 NN/  s\   CA7 A3+A7 A5%A7 2C3A7 5A7 7	C *C*B-+C
CCCc                  K   |j                   }|yt        j                  ||       }t        j                  ||       }||d}|j	                         4 d{   }	|	j                  |j                  |             d{   }
|
|
j                  d      dk7  r	 ddd      d{    y|	j                  |j                  |      t        j                  |             d{    |	j                  |j                  |      t               d{    |	j                  |j                  |      dt               d{    ddd      d{    y	7 7 7 7 w7 L7 7 # 1 d{  7  sw Y   y	xY ww)
a  Handle input sent to a background task via tasks/sendInput.

    This is called when a client sends input in response to an elicitation
    request from a background task.

    Args:
        task_id: The background task ID
        session_id: The MCP session ID
        action: The elicitation action ("accept", "decline", "cancel")
        content: The response content (for "accept" action)
        fastmcp: The FastMCP server instance

    Returns:
        True if the input was successfully stored, False otherwise
    NFr   r&   zutf-8r   	respondedr   T)r+   r4   r3   r5   r6   rI   r8   decodelpushr9   r:   expirer;   r7   )r   r   r'   r(   rL   rM   rP   rQ   rZ   r6   r   s              r\   r`   r`   "  s[    , __F~&--W-UL"))Z)QJ H
 ||~~yyJ!788>V]]73y@	 ~~ kkJJ|$JJx 
 	
 	

 ll6::l35GHHH iiJJz"!  
 	
 	
! ~, - 8 	

 	I	
! ~~~, s   AE:EE:$E%EE%E:(E)E:.7E%%E&,E%E.E%E!E%E:E#E:E%E:E%E%!E%#E:%E7+E.,E73E:)r   r-   rK   zServerSession | Noner   r-   r   dict[str, Any]rL   r
   returnzmcp.types.ElicitResult)rK   r	   r   r-   r   r-   r    rh   rL   r
   ri   None)r   r-   r   r-   r'   r-   r(   zdict[str, Any] | NonerL   r
   ri   bool)__doc__
__future__r   r9   loggingr.   r   r   typingr   r   r   	mcp.typesrD   r	   	getLogger__name__rA   fastmcp.server.serverr
   r2   r4   r5   r;   r]   rb   r`        r\   <module>rv      s#   #    ' + +  			8	$- J K G   }A}A!}A }A 	}A
 }A }A@555 5  	5
 5 
5p888 8 #	8
 8 
8ru   