§
    øžyjw  ã                  óÜ   — 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       ú9/home/ragecks/.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�   € å	ð .ð .Ý—’˜[Ñ)Ô)ˆØ#Ð-�t�E‰{Œ{ˆ{¨ð.ð .ð .ð .ñ .ô .ð .ð .ð .ð .ð .ð .øøøð .ð .ð .ð .ð .ð .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‰;Œ;�˜uŸyšy¨°qÑ9Ô9Ð>¸QÑ?Ô?Ñ?À'ÒIÐIÝ�LŠL˜ 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  è è € õ  
ð ,ð ,Ý—’˜[Ñ)Ô)ˆØð 	Øð,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,ð �9Š9�\Ñ"Ô" jÒ0Ð0àð,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,õ 	�Š�[ $Ñ'Ô'Ð'ÝŒ9‰;Œ;�˜uŸyšy¨°qÑ9Ô9Ð>¸QÑ?Ô?Ñ?À'ÒIÐIØð,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,ð —)’)˜IÑ&Ô&ˆØ—)’)˜I sÑ+Ô+ˆð,ð ,ð ,ñ ,ô ,ð ,ð ,ð ,ð ,ð ,ð ,øøøð ,ð ,ð ,ð ,ð ð Øˆtð9Ø�w˜v‘”Ð&Ð&Ð&Ð&Ð&Ð&ˆˆøÝð 9ð 9ð 9Ý�ŠØ6Ø�S 4ð 	ñ 	
ô 	
ð 	
ð 9°3Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8øøøøð9øøøõ   ­Ñ,Ô,Ð6ˆ6ˆ6°$Ð6sA   ŠC9µC9ÁAC9Ã+C9Ã9C=Ä C=Ä	D Ä
EÄ%"EÅEÅEÚloopúasyncio.AbstractEventLoopc                óð   — 	 ddl m}  |t          |||¦  «        | t          d¬¦  «        }|€dS |                     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   )Úsafe_schedule_threadsafez%resolve_sync_compat scheduling failed)r,   Úlog_messageNé   )r!   zresolve_sync_compat failed: %s)Úagent.async_utilsr5   r1   r,   r/   r+   r-   )r2   r
   r   r&   r5   Úfutr0   s          r   Úresolve_sync_compatr:   �   s¨   € ðØ>Ð>Ð>Ð>Ð>Ð>Ø&Ð&Ý�K ¨VÑ4Ô4°dÝØ?ð
ñ 
ô 
ˆð
 ˆ;Ø�4Ø�zŠz "ˆzÑ%Ô%Ð%øÝð ð ð Ý�ŠÐ5°sÑ;Ô;Ð;Øˆtˆtˆtˆtˆtøøøøðøøøs   ‚+A ¯A Á
A5ÁA0Á0A5)
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   ÚasyncioÚloggingÚ	threadingr   Útypingr   r   r   r   r   Ú	getLoggerÚ__name__r,   r	   Ú__annotations__ÚRLockr   ÚDEFAULT_TIMEOUT_SECONDSr   r   r    r%   r1   r:   © ó    r   ú<module>rH      sM  ððð ð ð. #Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø Ð Ð Ð Ø €€€Ø ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;à	ˆÔ	˜8Ñ	$Ô	$€ð ')€Ð (Ð (Ð (Ñ (Øˆ	ŒÑÔ€ð Ð ð
ð 
ð 
ð 
ð(.ð .ð .ð .ð(ð (ð (ð (ð 7Nð ð ð ð ð ð& -ð	)7ð )7ð )7ð )7ð )7ðXð ð ð ð ð rG   