§
    øžyjV  ã                  ó`   — 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dS )uó  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.
Tool dispatch inside such a thread therefore silently loses:

  * the approval *session/platform* ContextVars (``tools.approval`` /
    ``gateway.session_context``) â€” so gateway sessions fall into
    ``check_dangerous_command``'s non-interactive auto-approve branch and
    dangerous commands run without prompting (#33057, #30882);
  * the thread-local CLI approval/sudo callbacks (``tools.terminal_tool``) â€”
    so ``prompt_dangerous_approval`` cannot reach the user
    (GHSA-qg5c-hvr5-hjgr, #15216).

This helper factors out that capture/install/clear lifecycle so the several
places that fan tool dispatch onto worker threads (``agent.tool_executor`` and
the ``execute_code`` RPC threads) share one audited implementation instead of
divergent copies.

Usage â€” call :func:`propagate_context_to_thread` **on the parent thread**
(it snapshots the parent's ContextVars and callbacks at call time) and use the
returned callable as the worker's target::

    t = threading.Thread(target=propagate_context_to_thread(loop_fn), args=(...))
    # or
    executor.submit(propagate_context_to_thread(worker_fn), *args)

Approval/sudo callbacks are installed for the worker's lifetime and **always
cleared on exit**, so a recycled thread never holds a stale reference to a
disposed CLI instance.
é    )ÚannotationsN)ÚCallablec                 ó&   — ddl m} m}m}m} | |||fS )züResolve the terminal_tool callback getters/setters.

    Imported lazily: ``tools.terminal_tool`` imports ``tools.approval`` at
    module load, so a top-level import here would risk an import cycle for
    callers that live in ``tools.approval``.
    r   ©Ú_get_approval_callbackÚ_get_sudo_password_callbackÚset_approval_callbackÚset_sudo_password_callback)Útools.terminal_toolr   r   r	   r
   r   s       ú:/home/ragecks/.hermes/hermes-agent/tools/thread_context.pyÚ_callback_apir   +   sV   € ðð ð ð ð ð ð ð ð ð ð ð ð 	Ø#ØØ"ð	ð ó    Útargetr   Úreturnc                ó  ‡ ‡‡‡‡	— t          j        ¦   «         ŠdxŠŠdŠ		 t          ¦   «         \  }}}} |¦   «         Š |¦   «         Š||fŠ	n,# t          $ r t                               dd¬¦  «         Y nw xY wˆˆˆˆ	ˆ fd„}|S )u�  Wrap *target* for execution on a worker thread with the *current*
    thread's ContextVars and approval/sudo callbacks propagated.

    Call this on the parent thread; pass the returned callable as the
    thread/executor target.  The returned callable forwards its positional
    and keyword arguments to *target* and returns its result.

    Fail-closed: if callback installation raises, the callbacks are left
    unset (``None``).  That is the safe outcome â€” ``prompt_dangerous_approval``
    denies dangerous commands when no callback is registered in an interactive
    context, and the gateway approval queue blocks when its notify callback is
    absent.
    Nz0Could not capture parent approval/sudo callbacksT©Úexc_infoc                 óF   •‡ ‡— ˆ ˆˆˆˆˆfd„}‰                      |¦  «        S )Nc                 óê  •— ‰�M‰\  } }	 ‰� | ‰¦  «         ‰� |‰¦  «         n,# t           $ r t                               dd¬¦  «         Y nw xY w	  ‰‰i ‰¤Ž‰�I‰\  } }	  | d ¦  «          |d ¦  «         S # t           $ r t                               dd¬¦  «         Y S w xY wS # ‰�I‰\  } }	  | d ¦  «          |d ¦  «         w # t           $ r t                               dd¬¦  «         Y w w xY w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)Úset_approvalÚset_sudoÚargsÚkwargsÚparent_approval_cbÚparent_sudo_cbÚsettersr   s     €€€€€€r   Ú_innerz<propagate_context_to_thread.<locals>._runner.<locals>._innerZ   s§  ø€ ØÐ"Ø)0Ñ&�˜hð
Ø)Ð5Ø$˜Ð%7Ñ8Ô8Ð8Ø%Ð1Ø ˜ Ñ0Ô0Ð0øøÝ ð ð ð Ý—L’LðFà!%ð !ñ ô ð ð ð ðøøøðØ�v˜tÐ. vÐ.Ð.àÐ&Ø-4Ñ*�L (ðØ$˜ TÑ*Ô*Ð*Ø ˜ ™œ˜˜øÝ$ð ð ð ÝŸšØPØ%)ð %ñ ô ð ð ð ðøøøð 'ø�7Ð&Ø-4Ñ*�L (ðØ$˜ TÑ*Ô*Ð*Ø ˜ ™œ˜˜øÝ$ð ð ð ÝŸšØPØ%)ð %ñ ô ð ð ð ðøøøð 'øøøsQ   Š% ¥&AÁAÁB% Á!A8Á8&B!Â B!Â%C2Â.CÃC2Ã&C.Ã+C2Ã-C.Ã.C2)Úrun)r   r   r    Úctxr   r   r   r   s   `` €€€€€r   Ú_runnerz,propagate_context_to_thread.<locals>._runnerY   sI   øøø€ ð	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð 	ð8 �wŠw�v‰ŒÐr   )ÚcontextvarsÚcopy_contextr   r   r   r   )
r   Úget_approvalÚget_sudor   r   r#   r"   r   r   r   s
   `     @@@@r   Úpropagate_context_to_threadr(   @   sÓ   øøøøø€ õ Ô
"Ñ
$Ô
$€CØ*.Ð.Ð˜Ø€GðXÝ9F¹¼Ñ6ˆ�h ¨hØ)˜\™^œ^ÐØ!˜™œˆØ Ð*ˆˆøÝð Xð Xð XÝ�ŠÐGÐRVˆÑWÔWÐWÐWÐWðXøøøðð ð ð ð ð ð ð ð ð> €Ns    +A Á&A5Á4A5)r   r   r   r   )Ú__doc__Ú
__future__r   r$   ÚloggingÚtypingr   Ú	getLoggerÚ__name__r   r   r(   © r   r   ú<module>r0      sŠ   ððð ð@ #Ð "Ð "Ð "Ð "Ð "à Ð Ð Ð Ø €€€Ø Ð Ð Ð Ð Ð à	ˆÔ	˜8Ñ	$Ô	$€ðð ð ð*8ð 8ð 8ð 8ð 8ð 8r   