
    `gjw                       U 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mZm	Z	m
Z
mZmZ  ej                  e      Zi Zded<    ej$                         ZdZ	 	 	 	 	 	 	 	 	 	 ddZdd	Zdd
ZefddZef	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZy)u  Generic slash-command confirmation primitive (gateway-side).

Slash commands that have a non-destructive but expensive side effect worth
surfacing to the user (currently only ``/reload-mcp``, which invalidates
the provider prompt cache) route through this module.

Two delivery paths:

  1. Button UI — adapters that override ``send_slash_confirm`` render
     three inline buttons (Approve Once / Always Approve / Cancel).  The
     button callback calls ``resolve(session_key, confirm_id, choice)``.

  2. Text fallback — adapters without button UIs get a plain text prompt.
     Users reply with ``/approve``, ``/always``, or ``/cancel``; the
     gateway's ``_handle_message`` intercepts those replies and calls
     ``resolve()`` directly.

State is stored module-level (like ``tools.approval``) so platform
adapters can resolve callbacks without needing a backreference to the
``GatewayRunner`` instance.  The CLI path (``cli.py``) uses a local
synchronous variant — see ``_prompt_slash_confirm`` there.
    )annotationsN)Any	AwaitableCallableDictOptionalzDict[str, Dict[str, Any]]_pendingi,  c                z    t         5  |||t        j                         dt        | <   ddd       y# 1 sw Y   yxY w)u   Register a pending slash-command confirmation.

    Overwrites any prior pending confirm for the same ``session_key`` — the
    user invoking a new confirmable command supersedes the stale one.
    )
confirm_idcommandhandler
created_atN)_locktimer	   )session_keyr   r   r   s       F/root/.hermes/venv/lib/python3.12/site-packages/tools/slash_confirm.pyregisterr   3   s:     
 
$))+	!

 
 
s   !1:c                    t         5  t        j                  |       }|rt        |      ndcddd       S # 1 sw Y   yxY w)z7Return the pending confirm dict for a session, or None.N)r   r	   getdict)r   entrys     r   get_pendingr   G   s3    	 .[)#tE{. . .s   $5>c                f    t         5  t        j                  | d       ddd       y# 1 sw Y   yxY w)z@Drop the pending confirm for ``session_key`` without running it.N)r   r	   pop)r   s    r   clearr   N   s(    	 ([$'( ( (s   '0c                ,   t         5  t        j                  |       }|s
	 ddd       yt        j                         t	        |j                  dd      xs d      z
  |kD  r t        j                  | d       	 ddd       y	 ddd       y# 1 sw Y   yxY w)zkDrop the pending confirm if older than ``timeout`` seconds.

    Returns True if an entry was dropped.
    NFr   r   T)r   r	   r   r   floatr   )r   timeoutr   s      r   clear_if_staler   T   s    
 
 [)  99;uyyq9>Q??'ILLd+    s   B
AB
 B

Bc                n  K   t         5  t        j                  |       }|s
	 ddd       y|j                  d      |k7  r
	 ddd       yt        j                  | d       t	        j                         t        |j                  dd      xs d      z
  |kD  r
	 ddd       y|j                  d      }|j                  dd      }ddd       sy	  ||       d{   }t        |t              r|S dS # 1 sw Y   1xY w7 $# t        $ r(}t        j                  d|d	
       d| cY d}~S d}~ww xY ww)a  Resolve a pending confirm.

    ``choice`` must be one of ``"once"``, ``"always"``, or ``"cancel"``.
    Returns the handler's output string (to be sent as a follow-up
    message), or ``None`` if the confirm was stale, already resolved, or
    the confirm_id doesn't match.

    Safe to call from an asyncio callback (button click) or from the
    gateway's message intercept path.
    Nr   r   r   r   r   ?z(Slash-confirm handler for /%s raised: %sT)exc_infou!   ❌ Error handling confirmation: )r   r	   r   r   r   r   	Exceptionloggererror
isinstancestr)	r   r   choicer   r   r   r   resultexcs	            r   resolver+   c   s0      
 ,[), , 99\"j0, , 	[$'99;uyyq9>Q??'I, , ))I&))Is+, 9v&  ,66$63, ,$ ' 96S4 	 	
 33%889s   D5C3	D5C3 	D5	AC3	D5 #C3D5D C?D D53C<8D5?D 	D2
D-'D2(D5-D22D5c                    	 ddl m}  |t        |||      | t        d      }|y|j	                  d      S # t
        $ r }t        j                  d|       Y d}~yd}~ww xY w)	a"  Synchronous helper: schedule resolve() on a loop and wait for the result.

    Used by platform callback paths that run on a different thread than the
    event loop (e.g. Discord's button click handler in some configurations).
    Prefer the async ``resolve()`` from an async context.
    r   )safe_schedule_threadsafez%resolve_sync_compat scheduling failed)r$   log_messageN   )r   zresolve_sync_compat failed: %s)agent.async_utilsr-   r+   r$   r)   r#   r%   )loopr   r   r(   r-   futr*   s          r   resolve_sync_compatr3      se    >&KV4d?

 ;zz"z%% 5s;s   #8 8 	A!AA!)
r   r'   r   r'   r   r'   r   z)Callable[[str], Awaitable[Optional[str]]]returnNone)r   r'   r4   zOptional[Dict[str, Any]])r   r'   r4   r5   )r   r'   r   r   r4   bool)
r   r'   r   r'   r(   r'   r   r   r4   Optional[str])
r1   zasyncio.AbstractEventLoopr   r'   r   r'   r(   r'   r4   r7   )__doc__
__future__r   asynciologging	threadingr   typingr   r   r   r   r   	getLogger__name__r$   r	   __annotations__RLockr   DEFAULT_TIMEOUT_SECONDSr   r   r   r   r+   r3        r   <module>rE      s
  . #     ; ;			8	$ ')
# (	  


 
 7	

 

(.( 7N & -	)7)7)7 )7 	)7
 )7X
#  	
 rD   