Ë
    ãß²jû  ã            
       ó.  — U d Z ddlZddlZddlZddlmZ ddlmZ  ej                  e	«      Z
 ed«      Zere
j                  ej                  «        e«       Zee   ed<   i Zeeef   ed<    e«       Zee   ed<    ej,                  «       Z ej0                  d	d¬
«      Zej0                  edz     ed<   dddœdededz  dedz  ddfd„Zdefd„Zdedz  defd„Zdeddfd„Zdedz  defd„Zdedz  defd„Z deg df   defd„Z!dedz  fd„Z"dd„Z#y)a-  Per-thread interrupt signaling for all tools: thread-scoped so interrupting one
agent session does not kill tools in other sessions (the gateway runs many agents in one
process). The agent passes its execution thread id to set_interrupt(); tools call
is_interrupted(), which checks the CURRENT thread.é    N)ÚCallable)Úenv_var_enabledÚHERMES_DEBUG_INTERRUPTÚ_interrupted_threadsÚ_interrupt_reasonsÚ_yield_threadsÚhermes_interrupt_acting_for_tid)ÚdefaultÚacting_for_tid)ÚreasonÚactiveÚ	thread_idr   Úreturnc                óê  — |�|nt        j                  «       j                  }t        5   | rt        j
                  nt        j                  |«       | r|r
|t        |<   nt        j                  |d«       | st        j                  |«       t        rt        t        «      nd}ddd«       t        r6t        j                  d| |t        j                  «       j                  «       yy# 1 sw Y   ŒFxY w)z¡Set or clear the interrupt for *thread_id* (default: current thread); ``reason`` is
    an optional user-safe cause. Clearing also drops a pending yield request.Nz[[interrupt-debug] set_interrupt(active=%s, target_tid=%s) called_from_tid=%s current_set=%s)Ú	threadingÚcurrent_threadÚidentÚ_lockr   ÚaddÚdiscardr   Úpopr   Ú_DEBUG_INTERRUPTÚsetÚloggerÚinfo)r   r   r   ÚtidÚ	_snapshots        ú4/home/ubuntu/.hermes/hermes-agent/tools/interrupt.pyÚset_interruptr   %   sË   € ð !Ð,‰)´)×2JÑ2JÓ2L×2RÑ2R€CÜ	ñ LØ	M¡VÔ	×	!Ò	!Ô1E×1MÑ1MÈsÔSÙ‘fØ&,Ô˜sÒ#ä×"Ñ" 3¨Ô-ÙÜ×"Ñ" 3Ô'Ý1A”CÔ,Ô-Àtˆ	÷Lõ Ü�‰ð0à�Cœ×1Ñ1Ó3×9Ñ9¸9õ	Fð ÷Lð Lús   ©A;C)Ã)C2c                  óŽ   — t        t        j                  «       j                  «      xs t        t        j                  «       «      S ©N)Úis_thread_interruptedr   r   r   r   Úget© ó    r   Úis_interruptedr&   9   s1   € Ü ¤×!9Ñ!9Ó!;×!AÑ!AÓBÒqÔF[Ô\j×\nÑ\nÓ\pÓFqÐqr%   c                 óP   — | €yt         5  | t        v cddd«       S # 1 sw Y   yxY w)zôWhether *thread_id* has an interrupt bit set (``None`` never is). Used when
    a wait moves onto a deadline worker (``run_bounded_sync``) so ``/stop``
    targeting the original tool-worker tid still kills the subprocess.

    See #94285.
    NF)r   r   ©r   s    r   r"   r"   =   s.   € ð ÐØÜ	ñ 1ØÔ0Ð0÷1÷ 1ò 1úó   Šœ%c                 ód   — t         5  t        j                  | «       ddd«       y# 1 sw Y   yxY w)aW  Ask the tool running on *thread_id* to yield: a foreground terminal command hands
    its live process to the background registry and returns at once, so a user's mid-turn
    message (``redirect()`` during tool execution) is delivered instead of parked behind it.
    The command itself is never killed; that is what ``set_interrupt`` is for.N)r   r   r   r(   s    r   Úrequest_yieldr+   J   s*   € ô
 
ñ &Ü×Ñ˜9Ô%÷&÷ &ñ &ús   ‡&¦/c                 óP   — | €yt         5  | t        v cddd«       S # 1 sw Y   yxY w)z?Whether a yield is pending for *thread_id* (``None`` never is).NF)r   r   r(   s    r   Úis_thread_yield_requestedr-   S   s+   € àÐØÜ	ñ +ØœNÐ*÷+÷ +ò +úr)   c                 ó�   — | €yt         5  | t        v rt        j                  | «       	 ddd«       y	 ddd«       y# 1 sw Y   yxY w)zKAtomically take the pending yield for *thread_id*; True if one was pending.NFT)r   r   r   r(   s    r   Úconsume_yieldr/   [   sK   € àÐØÜ	ñ ØœÑ&Ü×"Ñ" 9Ô-Ø÷ð ð ÷	÷ ñ ús   Š<²<¼AÚcallbackc                 óª   — t        j                  «       j                  }t        5  |t        v r
	 ddd«       y | «        	 ddd«       y# 1 sw Y   yxY w)a  Run a state transition atomically with current-thread interruption.

    Returns ``False`` without calling ``callback`` when the current thread is
    already interrupted. The callback runs under the interrupt lock and must
    not block or re-enter any interrupt API.
    NFT)r   r   r   r   r   )r0   r   s     r   Úrun_if_not_interruptedr2   f   sP   € ô ×
"Ñ
"Ó
$×
*Ñ
*€CÜ	ñ ØÔ&Ñ&Ø÷ð ñ 	Œ
Ø÷	÷ ñ ús   ¥
A	¸A	Á	Ac                  óœ   — t         5  t        j                  t        j                  «       j
                  «      cddd«       S # 1 sw Y   yxY w)z;User-safe interrupt cause for the current thread, if known.N)r   r   r#   r   r   r   r$   r%   r   Úget_interrupt_reasonr4   u   s;   € ä	ñ HÜ!×%Ñ%¤i×&>Ñ&>Ó&@×&FÑ&FÓG÷H÷ Hò Hús   ‡1AÁAc                  ó   — t        d«       y)a‡  Clear any interrupt bit on the CURRENT thread: gives a user-approved command a clean
    slate right before it spawns its child, so a stale bit that landed during the blocking
    approval-wait cannot SIGINT the just-approved run. A *genuine* interrupt arriving after
    this call re-sets the bit and is still observed by the executor's poll loop. Call
    directly on the executing thread.FN)r   r$   r%   r   Úclear_current_thread_interruptr6   {   s   € ô �%Õr%   r!   )r   N)$Ú__doc__ÚcontextvarsÚloggingr   Úcollections.abcr   Úutilsr   Ú	getLoggerÚ__name__r   r   ÚsetLevelÚINFOr   r   ÚintÚ__annotations__r   ÚdictÚstrr   ÚLockr   Ú
ContextVarr   Úboolr   r&   r"   r+   r-   r/   r2   r4   r6   r$   r%   r   ú<module>rG      s—  ðò6ó
 Û Û Ý $å !à	ˆ×	Ñ	˜8Ó	$€ñ #Ð#;Ó<Ð Ùð ‡O�O�G—L‘LÔ!ñ "%£Ð �c˜#‘hÓ &Ø%'Ð �D˜˜c˜‘NÓ 'ñ ›5€��C‘Ó  Øˆ	�‰Ó€ð 6L°[×5KÑ5KØ%¨tô6€�×&Ñ& s¨T¡zÑ2ó ð
FÐVZò F˜$ð F¨3°©:ð FÈÈtÉð FÐ_có Fð(r˜ó rð
1 S¨4¡Zð 
1°Dó 
1ð&˜Sð & Tó &ð+¨¨t©ð +¸ó +ð˜S 4™Zð ¨Dó ð X¨b°$¨hÑ%7ð ¸Dó ðH˜c D™jó Hôr%   