
    i                        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dS )$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,  session_keystr
confirm_idcommandhandler)Callable[[str], Awaitable[Optional[str]]]returnNonec                    t           5  |||t          j                    dt          | <   ddd           dS # 1 swxY w Y   dS )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.
    )r   r   r   
created_atN)_locktimer	   )r
   r   r   r   s       8/home/ubuntu/.hermes/hermes-agent/tools/slash_confirm.pyregisterr   3   s     
 
 
$)++	!
 !

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   !6::Optional[Dict[str, Any]]c                    t           5  t                              |           }|rt          |          ndcddd           S # 1 swxY w Y   dS )z7Return the pending confirm dict for a session, or None.N)r   r	   getdict)r
   entrys     r   get_pendingr   G   s    	 . .[))#-tE{{{. . . . . . . . . . . . . . . . . .s   -AA	Ac                |    t           5  t                              | d           ddd           dS # 1 swxY w Y   dS )z@Drop the pending confirm for ``session_key`` without running it.N)r   r	   pop)r
   s    r   clearr    N   s    	 ( ([$'''( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (s   155timeoutfloatboolc                h   t           5  t                              |           }|s	 ddd           dS t          j                    t	          |                    dd          pd          z
  |k    r)t                              | d           	 ddd           dS 	 ddd           dS # 1 swxY w Y   dS )zkDrop the pending confirm if older than ``timeout`` seconds.

    Returns True if an entry was dropped.
    NFr   r   T)r   r	   r   r   r"   r   )r
   r!   r   s      r   clear_if_staler%   T   s)   
 
  [)) 	        9;;uyyq99>Q???'IILLd+++                         s   B'AB'B''B+.B+choiceOptional[str]c                  K   t           5  t                              |           }|s	 ddd           dS |                    d          |k    r	 ddd           dS t                              | d           t	          j                    t          |                    dd          pd          z
  |k    r	 ddd           dS |                    d          }|                    dd          }ddd           n# 1 swxY w Y   |sdS 	  ||           d{V }n:# t          $ r-}t                              d||d	
           d| cY d}~S d}~ww xY wt          |t                    r|ndS )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
isinstancer   )	r
   r   r&   r!   r   r   r   resultexcs	            r   resolver1   c   s6       
 , ,[)) 	, , , , , , , , 99\""j00, , , , , , , , 	[$'''9;;uyyq99>Q???'II, , , , , , , , ))I&&))Is++, , , , , , , , , , , , , , ,  t9wv&&&&&& 9 9 96S4 	 	
 	
 	
 93888888889  ,,666$6sA   C9C9AC9+C99C= C=	D 
E%"EEEloopasyncio.AbstractEventLoopc                    	 t          j        t          |||          |           }|                    d          S # t          $ r&}t
                              d|           Y d}~dS 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!   zresolve_sync_compat failed: %sN)asynciorun_coroutine_threadsafer1   r/   r+   r,   r-   )r2   r
   r   r&   futr0   s         r   resolve_sync_compatr9      s    .KV44d
 
 zz"z%%%   5s;;;ttttts   9< 
A,A''A,)
r
   r   r   r   r   r   r   r   r   r   )r
   r   r   r   )r
   r   r   r   )r
   r   r!   r"   r   r#   )
r
   r   r   r   r&   r   r!   r"   r   r'   )
r2   r3   r
   r   r   r   r&   r   r   r'   )__doc__
__future__r   r6   logging	threadingr   typingr   r   r   r   r   	getLogger__name__r,   r	   __annotations__RLockr   DEFAULT_TIMEOUT_SECONDSr   r   r    r%   r1   r9        r   <module>rF      sM    . # " " " " "        ; ; ; ; ; ; ; ; ; ; ; ; ; ;		8	$	$ ') ( ( ( (	  
 
 
 
(. . . .( ( ( ( 7N     & -	)7 )7 )7 )7 )7X     rE   