+
    lHàjû  ã                   óÂ  a € R t 0 t R t^ RIt^ RIt^ RIt^ RIHt ^ RIHt ]P                  ! ]
4      t]! R4      t]'       d   ]P                  ]P                  4       ]! 4       t] ^ k / t] ^k ]! 4       t] ^k ]P&                  ! 4       t]P*                  ! RRR7      t] ^k RRR/R R	 llltR
 R ltR R ltR R ltR R ltR R ltR R ltR R ltR R ltR# )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Úhermes_interrupt_acting_for_tid)ÚdefaultÚreasonc                ó\   € V ^8„  d   QhR\         R\        R,          R\        R,          RR/# )é   ÚactiveÚ	thread_idNr   Úreturn)ÚboolÚintÚstr)Úformats   "Ú4/home/ubuntu/.hermes/hermes-agent/tools/interrupt.pyÚ__annotate__r   %   s7   € ÷ Fñ Fœ$ð F¬3°­:ð FÌÈtÍð FÐ_cñ Fó    c               óZ  € Ve   TM\         P                  ! 4       P                  p\        ;_uu_ 4        V '       d   \        P
                  M\        P                  ! V4       V '       d   V'       d   V\        V&   M\        P                  VR4       V '       g   \        P                  V4       \        '       d   \        \        4      MRpRRR4       \        '       d8   \        P                  RW\         P                  ! 4       P                  X4       R# R#   + '       g   i     LU; i)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Ú_lockÚ_interrupted_threadsÚaddÚdiscardÚ_interrupt_reasonsÚpopÚ_yield_threadsÚ_DEBUG_INTERRUPTÚsetÚloggerÚinfo)r
   r   r   ÚtidÚ	_snapshots   &&$  r   Úset_interruptr%   %   sÆ   € ð !Ò,‰)´)×2JÒ2JÓ2L×2RÑ2R€Cß	Žß%+Ô	×	!Ò	!Ô1E×1MÑ1MÐ	MÈsÔSß—fØ&,Ô˜sÒ#ä×"Ñ" 3¨Ô-ßÜ×"Ñ" 3Ô'ß1AÓ1A”CÔ,Ô-Àtˆ	÷ 
÷ ÓÜ�‰ð0àœ×1Ò1Ó3×9Ñ9¸9ö	Fñ ÷ 
�ús#   ´6DÁ+DÁ3'DÂ DÂ<DÄD*	c                ó$   € V ^8„  d   QhR\         /# )r	   r   )r   )r   s   "r   r   r   9   s   € ÷ rñ rœñ rr   c                  óœ   € \        \        P                  ! 4       P                  4      ;'       g    \        \        P                  4       4      # ©N)Úis_thread_interruptedr   r   r   Úacting_for_tidÚget© r   r   Úis_interruptedr-   9   s4   € Ü ¤×!9Ò!9Ó!;×!AÑ!AÓB×qÐqÔF[Ô\j×\nÑ\nÓ\pÓFqÐqr   c                ó>   € V ^8„  d   QhR\         R,          R\        /# ©r	   r   Nr   ©r   r   )r   s   "r   r   r   =   s   € ÷ 
1ñ 
1¤S¨4¥Zð 
1´Dñ 
1r   c                óz   € V f   R# \         ;_uu_ 4        V \        9   uuRRR4       #   + '       g   i     R# ; i)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'   € ð ÒÙß	ŽØÔ0Ñ0÷ 
��‹úó   •	)©:	c                ó(   € V ^8„  d   QhR\         RR/# )r	   r   r   N)r   )r   s   "r   r   r   J   s   € ÷ &ñ &œSð & Tñ &r   c                ó†   € \         ;_uu_ 4        \        P                  V 4       RRR4       R#   + '       g   i     R# ; i)aK  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   r2   s   &r   Úrequest_yieldr6   J   s#   € ÷
 
ŽÜ×Ñ˜9Ô%÷ 
��Šús	   �/¯A 	c                ó>   € V ^8„  d   QhR\         R,          R\        /# r/   r0   )r   s   "r   r   r   S   s   € ÷ +ñ +¬¨t­ð +¼ñ +r   c                óz   € V f   R# \         ;_uu_ 4        V \        9   uuRRR4       #   + '       g   i     R# ; i)z?Whether a yield is pending for *thread_id* (``None`` never is).NF)r   r   r2   s   &r   Úis_thread_yield_requestedr9   S   s$   € àÒÙß	ŽØœNÑ*÷ 
��‹úr3   c                ó>   € V ^8„  d   QhR\         R,          R\        /# r/   r0   )r   s   "r   r   r   [   s   € ÷ ñ œS 4�Zð ¬Dñ r   c                óÀ   € V f   R# \         ;_uu_ 4        V \        9   d!   \        P                  V 4        RRR4       R#  RRR4       R#   + '       g   i     R# ; i)zKAtomically take the pending yield for *thread_id*; True if one was pending.NFT)r   r   r   r2   s   &r   Úconsume_yieldr<   [   sA   € àÒÙß	ŽØœÔ&Ü×"Ñ" 9Ô-Ø÷ 
‰ð ÷	 
��Šús   •"AÁAÁA	c                óB   € V ^8„  d   QhR\         . R3,          R\        /# )r	   ÚcallbackNr   )r   r   )r   s   "r   r   r   f   s#   € ÷ ñ ¤X¨b°$¨hÕ%7ð ¼Dñ r   c                óÖ   € \         P                  ! 4       P                  p\        ;_uu_ 4        V\        9   d    RRR4       R# V ! 4         RRR4       R#   + '       g   i     R# ; i)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   )r>   r#   s   & r   Úrun_if_not_interruptedr@   f   sF   € ô ×
"Ò
"Ó
$×
*Ñ
*€Cß	ŽØÔ&Ô&Ø÷ 
‰ñ 	Œ
Ø÷	 
��Šús   ®AÁAÁA(	c                ó2   € V ^8„  d   QhR\         R,          /# ©r	   r   N)r   )r   s   "r   r   r   u   s   € ÷ Hñ Hœc D�jñ Hr   c                 óÀ   € \         ;_uu_ 4        \        P                  \        P                  ! 4       P
                  4      uuRRR4       #   + '       g   i     R# ; i)z;User-safe interrupt cause for the current thread, if known.N)r   r   r+   r   r   r   r,   r   r   Úget_interrupt_reasonrD   u   s0   € ç	ŽÜ!×%Ñ%¤i×&>Ò&>Ó&@×&FÑ&FÓG÷ 
��‹ús   �2AÁA	c                ó   € V ^8„  d   QhRR/# rB   r,   )r   s   "r   r   r   {   s   € ÷ ñ ¨ñ r   c                 ó   € \        R4       R# )aw  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_interruptrG   {   s   € ô �%Ör   c                ó>  € V ^8„  d   Qh/ ^ \         9   d   \        \        ,          ;R&   ^\         9   d   \        \        \        3,          ;R&   ^\         9   d   \        \        ,          ;R&   ^\         9   d&   \
        P                  \        R,          ,          ;R&   # )r	   r   r   r   Nr*   )Ú__conditional_annotations__r    r   Údictr   ÚcontextvarsÚ
ContextVar)r   s   "r   r   r      sw   € ÷ 6ñ 6÷, 'Ò &”cœ#•hÑ &ñ-6÷. (Ò '”Dœœc˜•NÑ 'ñ/6÷4 !Ò  ””C•Ñ  ñ56÷>ò ”×&Ñ&¤s¨T¥zÕ2ñ ò?6r   r(   )!rI   Ú__doc__rK   Úloggingr   Úcollections.abcr   Úutilsr   Ú	getLoggerÚ__name__r!   r   ÚsetLevelÚINFOr    r   r   r   ÚLockr   rL   r*   r%   r-   r)   r6   r9   r<   r@   rD   rG   r   )rI   s   @r   Ú<module>rV      sÙ   øðö6ó
 Û Û Ý $å !à	×	Ò	˜8Ó	$€ñ #Ð#;Ó<Ð ßð ‡O�O�G—L‘LÔ!ñ "%£Ð Ó &Ø%'Ð Ó 'ñ ›5€Ó  Ø�ŠÓ€ð 6A×5KÒ5KØ%¨tô6€ó ñ
FÐVZ÷ Fð Fõ(rõ
1õ&õ+õõõH÷r   