Ë
    ãß²j5  ã                  ób   — d Z ddlmZ ddlZddlZddlmZ  ej                  e«      Z	d„ Z
dd„Zy)a–  Propagate agent-turn context into worker threads that dispatch Hermes tools.

A bare ``threading.Thread`` / ``ThreadPoolExecutor`` worker starts with an empty
``contextvars.Context`` and no thread-local approval/sudo callbacks, so tool dispatch inside it
silently loses the approval ContextVars (gateway sessions then auto-approve dangerous commands)
and the CLI callbacks (``prompt_dangerous_approval`` cannot reach the user, GHSA-qg5c-hvr5-hjgr).
Call :func:`propagate_context_to_thread` **on the parent thread** (it snapshots at call time) and
use the result as the worker target; callbacks are installed for the worker's lifetime and
always cleared on exit.
é    )ÚannotationsN)ÚCallablec                 ó  — ddl m}  ddlm} |j                  |j
                  f|j                  |j                  f| j                  | j                  f| j                  | j                  f| j                  | j                  ffS )uf  (getter, setter) pairs for every thread-local prompt callback a tool may need mid-dispatch
    (lazy: terminal_tool imports tools.approval at load, so a top-level import risks a cycle).
    Add a new per-thread prompt here â€” a callback missing from this table is silently absent on
    every parallel/timeout worker, so the tool believes nobody can answer.r   )Úunlock)Úterminal_tool)Úagent.vault_backendsr   Útoolsr   Ú_get_approval_callbackÚset_approval_callbackÚ_get_sudo_password_callbackÚset_sudo_password_callbackÚget_unlock_prompt_callbackÚset_unlock_prompt_callbackÚget_save_login_prompt_callbackÚset_save_login_prompt_callbackÚget_code_prompt_callbackÚset_code_prompt_callback)Úvault_unlockÚtts     ú9/home/ubuntu/.hermes/hermes-agent/tools/thread_context.pyÚ_callback_apir      sz   € õ
 <Ý)à×&Ñ&¨×(@Ñ(@ÐAØ×+Ñ+¨R×-JÑ-JÐKØ×4Ñ4°l×6]Ñ6]Ð^Ø×8Ñ8¸,×:eÑ:eÐfØ×2Ñ2°L×4YÑ4YÐZð	\ð \ó    c                óÈ   ‡ ‡‡— t        j                  «       ŠdŠ	 t        d„ t        «       D «       «      Šˆˆˆ fd„}|S # t        $ r t
        j                  dd¬«       Y Œ+w xY w)uH  Wrap *target* to run with the *current* thread's ContextVars and per-thread prompt callbacks
    (approval, sudo, password-manager unlock).

    Fail-closed: if callback installation raises they stay ``None`` â€” dangerous commands are then
    denied by ``prompt_dangerous_approval`` and the gateway approval queue blocks.
    Nc              3  ó4   K  — | ]  \  }}| |«       f–— Œ y ­w)N© )Ú.0ÚgetterÚsetters      r   ú	<genexpr>z.propagate_context_to_thread.<locals>.<genexpr>/   s   è ø€ ÒR±°¸˜&¡&£(Ô+ÑRùs   ‚z0Could not capture parent approval/sudo callbacksT©Úexc_infoc                 ó:   •‡ ‡— ˆ ˆˆˆfd„}‰j                  |«      S )Nc                 ó’  •— ‰€ ‰‰i ‰¤ŽS 	 ‰D ]  \  } }|€Œ	 | |«       Œ 	 	  ‰‰i ‰¤Ž	 ‰D ]  \  } } | d «       Œ S # t         $ r t        j                  dd¬«       Y Œ>w xY w# t         $ r t        j                  dd¬«       Y S w xY w# 	 ‰D ]  \  } } | d «       Œ w # t         $ r t        j                  dd¬«       Y w w xY wxY w)NzaFailed to install propagated approval/sudo callbacks; dangerous-command approval will fail closedTr    z2Failed to clear propagated approval/sudo callbacks)Ú	ExceptionÚloggerÚdebug)r   ÚcbÚ_cbÚargsÚinstallsÚkwargsÚtargets      €€€€r   Ú_innerz<propagate_context_to_thread.<locals>._runner.<locals>._inner4   s	  ø€ ØÐÙ˜tÐ. vÑ.Ð.ð[Ø"*ò #‘J�F˜BØ‘~Ù˜r�
ñ#ð0Ù˜tÐ. vÑ.ð0Ø'/ò %™˜ Ù˜t�ñ%øô ò [Ü—‘ð KØUYð ö [ð[ûô !ò 0Ü—L‘LÐ!UØ*.ð !ö 0ð0ûð0Ø'/ò %™˜ Ù˜t�ñ%øä ò 0Ü—L‘LÐ!UØ*.ð !ö 0ð0ýsS   �
? ˜
? ¤B ¬A%¿ A"Á!A"Á% BÂBÂCÂB ÂCÂ  CÃ CÃCÃC)Úrun)r)   r+   r-   Úctxr*   r,   s   `` €€€r   Ú_runnerz,propagate_context_to_thread.<locals>._runner3   s   ú€ ÷	0ð( �w‰w�v‹Ðr   )ÚcontextvarsÚcopy_contextÚtupler   r$   r%   r&   )r,   r0   r/   r*   s   ` @@r   Úpropagate_context_to_threadr4   $   sa   ú€ ô ×
"Ñ
"Ó
$€Cà€HðXÜÑRÄ-Ã/ÔRÓRˆöð. €Nøô5 ò XÜ�‰ÐGÐRVˆÖWðXús   ›> ¾ A!Á A!)r,   r   Úreturnr   )Ú__doc__Ú
__future__r   r1   ÚloggingÚtypingr   Ú	getLoggerÚ__name__r%   r   r4   r   r   r   ú<module>r<      s5   ðñ	õ #ã Û Ý à	ˆ×	Ñ	˜8Ó	$€ò\ô&r   