+
    lHàj´5  ã                   óÞ   € R t ^ RIt^ RIt^ RIt^ RIt^ RIHtHt ^ RIH	t
 ^ RIHtHt ]P                  ! R4      t ! R R4      tR R	 ltR
 R ltR R ltR R ltR R ltRR/R R lltR# )u_  Blocking gateway approval wait for :mod:`tools.approval`.

Mirrors the CLI's synchronous ``input()`` flow: the agent thread enqueues a
pending approval, the gateway notifies the user, and the thread blocks until
``/approve`` / ``/deny`` resolves it or the approval timeout elapses. Multiple
threads (parallel subagents, execute_code RPC handlers) can block concurrently
â€” each gets its own ``threading.Event``; ``/approve`` resolves the oldest,
``/approve all`` every pending entry. Queue state (``_gateway_queues``,
``_lock``) is owned by ``tools.approval`` and reached through that module at
call time.
N)Úget_interrupt_reasonÚis_interrupted)Úapproval_context)Úactivity_heartbeatÚhuman_wait_windowztools.approvalc                   ó:   a € ] tR t^t o RtRtV 3R lR ltRtV tR# )Ú_ApprovalEntryz@One pending dangerous-command approval inside a gateway session.c                ó    <€ V ^8„  d   QhRS[ /# )é   Údata)Údict)ÚformatÚ__classdict__s   "€Ú@/home/ubuntu/.hermes/hermes-agent/tools/approval_gateway_wait.pyÚ__annotate__Ú_ApprovalEntry.__annotate__   s   ø€ ÷ ñ ™Tñ ó    c                ó   € \         P                  ! 4       V n        \        V4      V n        V P                  P                  R \        P                  ! 4       P                  4       RV n	        RV n
        RV n        RV n        RV n        RV n        R# )Ú
request_idFN)Ú	threadingÚEventÚeventr   r   Ú
setdefaultÚuuidÚuuid4ÚhexÚacknowledgedÚsettleÚresultÚreasonÚ	cancelledÚexpired)Úselfr   s   &&r   Ú__init__Ú_ApprovalEntry.__init__   sj   € Ü—_’_Ó&ˆŒ
Ü˜“JˆŒ	Ø�	‰	×Ñ˜\¬4¯:ª:«<×+;Ñ+;Ô<Ø!ˆÔð ˆŒØ"&ˆŒà"&ˆŒð &*ˆŒàˆŽr   )r   r    r   r   r!   r   r   r   N)	Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú	__slots__r#   Ú__static_attributes__Ú__classdictcell__)r   s   @r   r   r      s   ø‡ € ÙJØg€I÷ö r   r   c                ó\   € V ^8„  d   QhR\         P                  R\        R\        R\        /# )r
   r   Úsession_keyÚinterrupt_logÚreturn)r   r   Ústr)r   s   "r   r   r   /   s-   € ÷ ñ ”y—‘ð ´Sð ÌCð ÔTWñ r   c               ó  € \         P                  ! 4       \        \        P                  ! 4       ^ 4      ,           p\        R4      p\        V4      ;_uu_ 4         \        4       '       d!   \        P                  W!4        RRR4       R# V\         P                  ! 4       ,
          pV^ 8:  d    RRR4       R# V P                  \        RV4      R7      '       d    RRR4       R# V! 4        K•    + '       g   i     R# ; i)u  Wait on *event* until it fires, the turn is interrupted, or approvals.timeout
elapses; returns ``"set"`` | ``"interrupted"`` | ``"timeout"``. Polls in ~1s
slices so activity heartbeats reach the agent's inactivity tracker every ~10s â€”
otherwise the gateway watchdog kills the agent while the user is still
responding (mirrors ``_wait_for_process()`` cadence). The loop is recorded as
human-wait time so the concurrent batch deadline excludes it.

Any interrupt (/stop, inactivity timeout, delegation teardown) ends the wait
fail-closed: the command does not run. Who caused it is read from the
per-thread interrupt-cause channel (``get_interrupt_reason()``, a trusted fixed
category), never inferred from message text, so the caller can report a
withdrawn prompt without inventing a user refusal.zwaiting for user approvalNÚinterruptedÚtimeoutg      ð?)r4   Úset)ÚtimeÚ	monotonicÚmaxÚ_ctxÚ_get_approval_timeoutr   r   r   ÚloggerÚinfoÚwaitÚmin)r   r.   r/   ÚdeadlineÚ	heartbeatÚ	remainings   &&$   r   Ú_poll_eventrB   /   s½   € ô �~Š~Ó¤#¤d×&@Ò&@Ó&BÀAÓ"FÕF€HÜ"Ð#>Ó?€IÜ	˜;×	'Õ	'Øô ×ÒÜ—‘˜MÔ7Ø$÷ 
(Ñ	'ð !¤4§>¢>Ó#3Õ3ˆIØ˜AŒ~Ø ÷ 
(Ñ	'ð �z‰z¤# c¨9Ó"5ˆz×6Ò6Ø÷ 
(Ñ	'ñ ŽK÷ 
(×	'Ð	'ús   Á(C.Â
$C.Â8#C.Ã%	C.Ã.C?	c                ó>   € V ^8„  d   QhR\         R\         R,          /# ©r
   Ústater0   N©r1   )r   s   "r   r   r   N   s   € ÷ 
ñ 
œð 
¬¨d­
ñ 
r   c                ó’   € V R8X  d   \        4       ;'       g    R# V R8X  d%   VP                  f   VP                  ;'       g    R# R# )um  Why the wait ended with nobody answering: the turn was interrupted (cause from the
per-thread channel â€” a user /stop or a parent's delegation teardown), the entry was
withdrawn with a stamped cause (leader interrupted, session torn down), or the turn ended
under the prompt (notifier unregistered, result never set). ``None`` for a real answer
or a plain timeout.r3   zturn interruptedr5   Nz-the turn ended before the prompt was answered)r   r   r    )rE   Úentrys   &&r   Ú_cancel_causerI   N   sD   € ð �ÔÜ#Ó%×;Ð;Ð);Ð;Ø�„~˜%Ÿ,™,Ò.Ø�‰×QÐQÐ"QÐQÙr   c                óV   € V ^8„  d   QhR\         R\        R\        R,          R\         /# )r
   ÚpayloadÚresolvedÚchoiceNr0   )r   Úboolr1   )r   s   "r   r   r   [   s3   € ÷ Oñ O”Tð O¤Tð O´3¸µ:ð OÔSWñ Or   c           
     ób   € \         P                  ! R/ V BR\        WV4      /BVB  RVRVRV/VC# )zÍFire the post hook and build the decision dict. Unresolved (timeout) and
a None choice both mean the user never answered; ``cancelled`` carries the
cause when the prompt was withdrawn rather than answered.rM   rL   r   ©Úpost_approval_response)r9   Ú_fire_approval_hookÚ_hook_choice)rK   rL   rM   r   Úextras   &&&&,r   Ú_finishrU   [   sA   € ô 	×ÒÑx¸ÑxÌÐV^ÐhmÓInÑxÐrwÒxØ˜ (¨F°H¸fÐNÈÐNÐNr   c                óV   € V ^8„  d   QhR\         R\        R,          R\        R\        /# )r
   rL   rM   NrT   r0   )rN   r1   r   )r   s   "r   r   r   c   s,   € ÷ <ñ <œ4ð <¬¨t­ð <¼Dð <ÄSñ <r   c                ó`   € VP                  R4      '       d   R# V '       d   T;'       g    R# R# )zPObserver-facing outcome of a wait: the choice, else ``cancelled`` / ``timeout``.r    r4   )Úget)rL   rM   rT   s   &&&r   rS   rS   c   s)   € à‡y�y�×ÒÙß$,ˆF×Ð�iÐ;°)Ð;r   c                ó0   € V ^8„  d   QhR\         R\        /# )r
   r.   rK   ©r1   r   )r   s   "r   r   r   j   s   € ÷ hñ h¬ð h¼tñ hr   c           
     ó~  € \         P                  ! R/ VBRR/B  \        VP                  V RR7      pVR8X  d#   VP                  f   VP
                  '       d   Rp\        W14      pVR8X  d   R	RreMVR8X  d   RR
reMVP                  pVRJpVR8X  d   R# V'       d   RV/M/ p\        W&V\        VRR4      3RR/VB # )uH  Wait on an already-pending identical approval instead of re-prompting.
Adopts the leader's decision: ``session``/``always`` â†’ approval (same dict
shape as a direct resolution; persistence stays the caller's and is
idempotent across leader and followers); ``deny`` â†’ denial carrying the
leader's reason; leader timeout / our own deadline â†’ unresolved. ``once``
returns ``None``: single-use consent covers only the leader's execution,
so the caller must issue a fresh prompt. Hooks fire with ``coalesced=True``
so observers see the follower's lifecycle without a duplicate prompt.Ú	coalescedTuE   Coalesced approval wait interrupted â€” returning deny for session %s©r/   r5   Nr4   r3   ÚdenyFÚoncer    r   ©Úpre_approval_request)	r9   rR   rB   r   r   r!   rI   rU   Úgetattr)r.   ÚleaderrK   rE   r    rM   rL   rT   s   &&&     r   Ú_await_coalesced_leaderrd   j   sÊ   € ô 	×ÒÑO°wÑOÈ$ÓOÜ˜Ÿ™ kð'FôG€Eð �„~˜&Ÿ-™-Ò/°F·N·N°NØˆÜ˜eÓ,€IØ�Ôà! 4‘Ø	�)Ô	Ø ‘à—‘ˆØ Ð%ˆØ�Ôáß(1ˆ[˜)Ñ$°r€EÜ�7 f¬g°f¸hÈÓ.MÑgÐY]ÐgÐafÑgÐgr   ÚsurfaceÚgatewayc                óH   € V ^8„  d   QhR\         R\        R\         R\        /# )r
   r.   Úapproval_datare   r0   rZ   )r   s   "r   r   r   ‰   s6   € ÷ uIñ uI¬ð uIÌð uIÔZ]ð uIÔnrñ uIr   c               óð  a aaaaa€ ^ RI Ho ^ RIHpHpHo SP                  RR4      pVR8X  d   \        P                  ! 4       pRSP                  RR4      RSP                  RR4      RVR\        SP                  RV.4      4      R	S R
V/p\        SP                  R4      ;'       g    . 4      o\        S4      oR VVVV 3R llp SP                  ;_uu_ 4        Rp	V! 4       '       g2   \        VV3R lSP                  P                  S . 4       4       R4      p	V	f   V! 4         RRR4       M RRR4       \        S X	V4      p
V
f   K‡  V
# R VVV 3R llp^ RIHp V! RVR,          S R7      ;_uu_ 4       p\        P"                  ! R / VB   V! \%        SP&                  4      4       V! 4        \1        SP2                  S RR7      p\5        TS4      pTR8X  d"   TSn        SP2                  P9                  4        T! T4      pTR8X  d   RpTR8g  ;'       g    TRJpT'       d   RT/M/ p\;        TTT4      Tn        \=        TTTSP>                  3/ TB uuRRR4       #   + '       g   i     EL<; i  \(         d\   p\*        P-                  RT4       T! R4       \        P"                  ! R!/ TBRR/B  RTn        RRRRRR/u Rp?uuRRR4       # Rp?ii ; i  + '       g   i     R# ; i)"a  Enqueue *approval_data*, notify the user, and block until resolved or timed
out. Shared by the terminal command guard, the execute_code guard, the plugin
escalation gate, and MCP elicitation. Returns ``{"resolved", "choice",
"reason"}`` or ``{"resolved": False, "choice": None, "notify_failed": True}``
when the notify callback raised. Persisting the choice and building the
tool-facing result stay with the caller.

Identical concurrent approvals (same command text + pattern-key set) are
coalesced: parallel tool calls would otherwise fire N identical prompts
the user must /approve N times while the agent sits wedged. Followers adopt
the leader's ``session``/``always``/``deny``/timeout; a ``once`` covers only
the leader, so the followers fall through to ONE fresh prompt they coalesce on.)Úapproval)Úapproval_publishedÚpreparing_terminal_approvalÚregister_prepared_approvalÚpattern_keyÚ rf   ÚcommandÚdescriptionÚpattern_keysr.   re   c                ó   € V ^8„  d   QhRR/# )r
   r0   N© )r   s   "r   r   Ú-_await_gateway_decision.<locals>.__annotate__¦   s   € ÷ Lñ L�dñ Lr   c                  óp   <€ S! SS4       S P                   P                  S. 4      P                  S4       R # )N)Ú_gateway_queuesr   Úappend)Ú	_approvalrH   rm   r.   s   €€€€r   Ú_enqueueÚ)_await_gateway_decision.<locals>._enqueue¦   s.   ø€ Ù" ;°Ô6Ø×!Ñ!×,Ñ,¨[¸"Ó=×DÑDÀUÖKr   TNc              3   óô   <"  € T Fm  pVP                   P                  R 4      SP                  R 4      8X  g   K4  \        VP                   P                  R4      ;'       g    . 4      S8X  g   Ki  Vx € Ko  	  R# 5i)rp   rr   N)r   rX   Úlist)Ú.0Úerh   Úkeyss   & €€r   Ú	<genexpr>Ú*_await_gateway_decision.<locals>.<genexpr>²   sb   øé € ð SÑ*X QØ"#§&¡&§*¡*¨YÓ"7¸=×;LÑ;LÈYÓ;WÑ"Wô  !ä#'¨¯©¯
©
°>Ó(B×(HÐ(HÀbÓ#IÈTÑ#Q÷  !šqÓ*Xùs   ƒ1A8¹&A8Á 	A8Á.
A8c                ó>   € V ^8„  d   QhR\         R\         R,          /# rD   rF   )r   s   "r   r   ru   ¼   s   € ÷ !ñ !œ3ð !¤3¨¥:ñ !r   c                óf  <€ SP                   ;_uu_ 4        SP                  pSP                  P                  S. 4      pSV9   d   VP	                  S4       V'       g   SP                  P                  SR4       SP                  RupSn        Vf:   V R9   d3   V R8H  Sn        V R8X  d   RSn        SP                  P                  4        RRR4       Xe   V R8X  d
   Xe   RMRpMT p V! V4       X# X#   + '       g   i     L3; i  \         d    \        P                  RR	R
7        X# i ; i)a¸  Leave the queue and return the choice committed so far. Reading ``entry.result`` and
removing the entry are one critical section under the approval lock: ``resolve_gateway_approval``
commits under the same lock, so a choice that landed after the deadline check but before this
removal is still ours to honour, and one arriving later finds no entry (the client is told
nothing was pending instead of being acked "ok" while the agent denies).Nr4   Únotify_failedz*the approval prompt could not be deliveredr5   rL   Úsession_closedzapproval settle hook failedT)Úexc_info)r4   r…   )Ú_lockr   rw   rX   ÚremoveÚpopr   r!   r    r   r5   Ú	Exceptionr;   Údebug)rE   rM   Úqueuer   r   ry   rH   r.   s   &    €€€r   Ú_drop_entryÚ,_await_gateway_decision.<locals>._drop_entry¼   s  ø€ ð �_�_‹_Ø—\‘\ˆFØ×-Ñ-×1Ñ1°+¸rÓBˆEØ˜Œ~Ø—‘˜UÔ#ßØ×)Ñ)×-Ñ-¨k¸4Ô@Ø#(§<¡<°Ð ˆF�E”LØŠ~ %Ð+GÔ"Gð !&¨Ñ 2�”Ø˜OÔ+Ø&R�E”OØ—‘—‘Ô!÷ ð Òð ˜Œ~Ø'-Ò'9™Ð?O‘à�ðKÙ�v”ð ˆˆvˆ÷7 �_ûô2 ô KÜ—‘Ð:ÀT�ÕJØˆðKús%   –AC7ÁA-C7Ã+D
 Ã7D	Ä
"D0Ä/D0)Úhuman_input_requestrj   )Úpromptr.   z"Gateway approval notify failed: %sr…   rM   rL   Fu;   Approval wait interrupted â€” returning deny for session %sr]   r3   r^   r4   r    r`   rP   ) Útoolsrj   Úagent.terminal_approval_batchrk   rl   rm   rX   r9   Úgateway_approval_surfacer}   r   rˆ   Únextrw   rd   Útools.human_input_hooksr�   rR   r   r   r‹   r;   ÚwarningÚoutcomerB   r   rI   r    r5   rS   rU   r   )r.   Ú	notify_cbrh   re   rk   rl   Úprimary_keyrK   rz   rc   ÚadoptedrŽ   r�   ÚhumanÚexcrE   r    rM   rL   rT   ry   rH   r€   rm   s   f&f$                @@@@r   Ú_await_gateway_decisionrž   ‰   sÆ  ý€ õ ,ßyÑyà×#Ñ# M°2Ó6€KØ�)ÔÜ×/Ò/Ó1ˆà�=×$Ñ$ Y°Ó3Ø�}×(Ñ(¨¸Ó;Ø�{Øœ˜]×.Ñ.¨~À¸}ÓMÓNØ�{ I¨wð€Gô �×!Ñ! .Ó1×7Ð7°RÓ8€DÜ˜=Ó)€E÷Ló Lð Ø�_�_‹_ØˆFÙ.×0Ò0Üõ S¨)×*CÑ*C×*GÑ*GÈÐUWÔ*Xó SàTXóZ�ð Š~Ù”
Ø÷ ˆ_ð ÷ ô *¨+°v¸wÓGˆØÔØˆN÷!ò !õF <Ù	˜Z°¸	Õ0BÐP[×	\Õ	\Ð`eä× Ò ÑC¸7ÒCð	NÙ”d˜5Ÿ:™:Ó&Ô'ÙÔ ô ˜EŸK™K¨Ø*gôiˆä! %¨Ó/ˆ	Ø�MÔ!à'ˆEŒOØ�K‰K�O‰OÔÙ˜UÓ#ˆØ�MÔ!àˆFð ˜IÑ%×;Ð;¨°tÐ);ˆß,5�˜iÑ(¸2ˆÜ$ X¨v°uÓ=ˆŒÜ�w ¨&°%·,±,ÑHÀ%ÑH÷= 
]Ò	\÷c �_ˆ_ûôp ô 	NÜ�N‰NÐ?ÀÔEÙ˜Ô(Ü×$Ò$ÑaÀÑaÐQ`ÓaØ+ˆEŒMØ  x°°ÈÐMÔM÷ 
]Ò	\ûð	Nú÷ 
]×	\Ð	\úsW   ÃAI'Å<K$Æ"I;Æ6A(K$ÈK$È,0K$É'I8	É;K!ÊAKËK!ËK$ËK!Ë!K$Ë$K5	)r)   Úloggingr   r6   r   Útools.interruptr   r   r’   r   r9   Útools.approval_human_waitr   r   Ú	getLoggerr;   r   rB   rI   rU   rS   rd   rž   rt   r   r   Ú<module>r£      so   ðñ
ó Û Û Û ç @Ý *ß Kà	×	Ò	Ð+Ó	,€÷ñ õ,õ>
õOõ<õhð>uIÐ`i÷ uIñ uIr   