Ë
    ãß²jÓ ã                   ó®	  — U d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZ ddlmZmZmZmZmZmZmZmZmZmZ ddlmZmZmZmZ dd	lm Z m!Z!m"Z"m#Z#m$Z$ dd
l%m&Z& ddl'm(Z(m)Z)m*Z* ddl+m,Z,  ejZ                  e.«      Z/ e ej`                  dd«      «      Z1e2e3d<    ejh                  «       Z5i Z6e7e8e7f   e3d<   i Z9e7e8e:f   e3d<    e:«       Z;e:e8   e3d<    e:«       Z<e:e3d<   i Z=e7e8e:f   e3d<   i Z>e7e8e?f   e3d<   dZ@de?fd„ZAde8de?fd„ZBde8ddfd„ZCde8de8fd„ZDi ZEe7e8eFf   e3d<   i ZGe7e8eHf   e3d<   de8ddfd„ZIde8ddfd „ZJ	 	 	 dÛde8d"e8d#e2d$e	e8   d%e	e8   de?fd&„ZKde8d%e8d'e8de2fd(„ZLde8deFe7   fd)„ZMde8d%e8de2fd*„ZNde8d%e8de2fd+„ZOde8de2fd,„ZPde?fd-„ZQde8de7dz  fd.„ZRde8d/e7fd0„ZSde8d1e8fd2„ZTde8ddfd3„ZUde8d4e2ddfd5„ZVde8ddfd6„ZWde8ddfd7„ZXde8ddfd8„ZYde8de2fd9„ZZde2fd:„Z[de2fd;„Z\de:fd<„Z]de8d1e8de2fd=„Z^d1e8de2fd>„Z_d1e8fd?„Z`d@e:fdA„Zade8d"e8dBeFeb   ddfdC„Zcde:fdD„Zdi Zee7e8e:f   e3dE<   de8fdF„Zfde:fdG„Zgd@e:fdH„Zhde8de2fdI„Zide2fdJ„Zjde7fdK„ZkdLdMdNdOdPdQœZldÜdSe8dTe8de8fdU„ZmdRdVœdWe8d1e8dXe8dSe8dTe8de7fdY„ZndWe8d1e8dXe8de7fdZ„Zode8dXe8de7fd[„Zpde8fd\„Zqde8dRe8dXe8d1e8d]eFe8   d^e8dz  d_e2de7fd`„Zr eda¬b«       G dc„ dd«      «       Zs esdedfdgdhdi«      Zt esdjdkdldmdn«      ZudeFes   fdo„ZvdRe8dpesde7dz  fdq„Zw eda¬b«       G dr„ ds«      «       ZxdtZyduZz exdRdadad!dadvdweyz   dxz   dydzeyz   d{z   d|eyz   d}z   d~¬«      Z{ exd€dadadadad�d‚dƒd„ezz   d{z   d…d†¬«      Z| exd‡d!d!d!d!dvdˆezz   d‰z   dd„ezz   dŠz   d‹d¬«      Z}dŒexdRe8dXe8d1e8d]eFe8   de8d�e2debe7dz  e2f   fdŽ„Z~d!dadd�œdŒexdRe8dXe8d1e8d]eFe8   dBeFeb   de8d�e2d‘e2d’e2d“e2d”e2de7fd•„ZdÝdebfd–„Z€ddd—d˜dddd!dd™œ	d1e8dXe8dše8d›e8dTe8dœe8d�e8dže8dŸe8d e8d¡e2d¢e8de7fd£„Z�dÞd¤e8d¥e2de2fd¦„Z‚dRe8de7dz  fd§„Zƒd!d¨œdRe8d©e2de7dz  fdª„Z„	 	 dßdRe8d¤e8d¥e2de7fd«„Z…ddd¬œd­e8d$e8d®e8de7fd¯„Z†d°e7de8fd±„Z‡dRe8de7fd²„Zˆ	 	 dßdRe8d¤e8d¥e2de7fd³„Z‰d´ZŠdÞd€e8d¤e8d¥e2de7fdµ„Z‹ eg«        ddlŒZŒddl�Z�ddlŽZŽddl�Z�ddl�Z�ddl‘Z‘ddl’Z’ddl“Z“ddl”Z”ddl•Z•ddl–Z–i d¶d·“d¸d¹“dºd»“d¼d½“d¾d¿“dÀdÁ“dÂdÃ“dÄdÅ“dÆdÇ“dÈdÉ“dÊdË“dÌdÍ“dÎdÏ“dÐdÑ“dÒdÓ“dÔdÕ“dÖd×“dØdÙi¥Z—dÚ„ Z˜y)àac  Dangerous command approval -- the gate flow and per-session state.

Owns the session state (approvals, yolo, gateway queues, denial breaker), the three guard
entry points (``check_all_command_guards``, ``check_execute_code_guard``,
``request_tool_approval`` / ``_run_approval_gate``) and the shared human-decision engine
behind them. Leaves: ``approval_detection`` (hardline/dangerous patterns), ``approval_context``
(contextvars, config readers), ``approval_floors`` (pre-gate blocks, allowlist match),
``approval_prompt`` (CLI prompt, plugin transports, MCP elicitation), ``approval_gateway_wait``
(blocking gateway round-trip), ``approval_smart`` (guardian LLM), ``approval_human_wait``.
Leaves read facade-owned state (``_lock``, queues, denial breaker) back through ``tools.approval`` at
call time; sibling-defined names are imported from their defining module.
é    )Ú	dataclassN)ÚOptional)Úenv_var_enabledÚis_truthy_value)Úapproval_context)
Ú_get_session_platformÚ_is_cron_approval_contextÚ_is_gateway_approval_contextÚ_is_interactive_cliÚ!_is_single_query_approval_contextÚ(_is_unattended_platform_approval_contextÚ_resolve_cli_approval_callbackÚ$_should_fall_through_to_cli_approvalÚ_tirith_fail_openÚget_current_session_key)Ú_approval_key_aliasesÚ_check_sudo_stdin_guardÚdetect_dangerous_commandÚdetect_hardline_command)Ú$_command_matches_permanent_allowlistÚ_hardline_block_resultÚ_match_user_deny_ruleÚ_sudo_stdin_block_resultÚ_user_deny_block_result)Ú_await_gateway_decision)Ú _present_with_selected_transportÚ_transport_choiceÚprompt_dangerous_approval)Ú_smart_verdictÚHERMES_YOLO_MODEÚ Ú_YOLO_MODE_FROZENÚ_pendingÚ_session_approvedÚ_session_yoloÚ_permanent_approvedÚ_permanent_approved_by_homeÚ_denial_tallyé   Úreturnc                  óˆ   — 	 t        t        j                  «       j                  dd«      «      S # t        t
        f$ r Y yw xY w)zJ``approvals.denial_breaker_threshold``: default 3; 0 or negative disables.Údenial_breaker_thresholdé   )Úintr   Ú_get_approval_configÚgetÚ
ValueErrorÚ	TypeError© ó    ú3/home/ubuntu/.hermes/hermes-agent/tools/approval.pyÚ_get_denial_breaker_thresholdr6   D   sB   € ðÜÔ#×8Ñ8Ó:×>Ñ>Ð?YÐ[\Ó]Ó^Ð^øÜœ	Ð"ò Ùðús   ‚,/ ¯AÁ AÚsession_keyc                 ó2  — t         5  t        j                  | d«      dz   }|t        | <   t        t        «      t        kD  rBt        j                  t        t        t        «      «      «       t        t        «      t        kD  rŒB|cddd«       S # 1 sw Y   yxY w)z®Increment and return the session's consecutive guardian-denial count. Pop-and-reinsert
    keeps actively-denying sessions at the most-recent end so eviction drops idle keys.r   é   N)Ú_lockr(   ÚpopÚlenÚ_DENIAL_TALLY_MAX_SESSIONSÚnextÚiter)r7   Úcounts     r5   Ú_record_denialrA   L   sv   € ô 
ñ Ü×!Ñ! +¨qÓ1°AÑ5ˆØ%*Œ�kÑ"Ü”-Ó Ô#=Ò=Ü×Ñœd¤4¬Ó#6Ó7Ô8ô ”-Ó Ô#=Ó=à÷÷ ò ús   ‡A:BÂBÂBc                 óf   — t         5  t        j                  | d«       ddd«       y# 1 sw Y   yxY w)zDClear the session's consecutive-denial tally (an approval happened).N)r:   r(   r;   ©r7   s    r5   Ú_reset_denialsrD   W   s*   € ä	ñ -Ü×Ñ˜+ tÔ,÷-÷ -ñ -ús   ‡'§0c                 óÊ   — t         5  t        j                  | d«      }ddd«       t        «       }|dk  s|k  ryt        j                  d| ||«       d|› d�S # 1 sw Y   Œ<xY w)z¯Escalated hard-stop text once the breaker has tripped, else ''. Read-only: callers
    increment via :func:`_record_denial`; the text is appended verbatim to the deny message.r   Nr!   z\Smart-approval circuit breaker tripped for session %s: %d consecutive denials (threshold %d)z CIRCUIT BREAKER: zË consecutive commands were blocked by the security reviewer. STOP attempting variations of this operation. Report the blocked operation to the user and either ask them to run it manually or use /approve.)r:   r(   r0   r6   ÚloggerÚwarning)r7   r@   Ú	thresholds      r5   Ú_denial_breaker_addendumrI   ]   sy   € ô 
ñ 2Ü×!Ñ! +¨qÓ1ˆ÷2ä-Ó/€IØ�A‚~˜ Ò*Øô ‡N�NØfØ�U˜Iôð
 ˜U˜Gð $vð 	vð÷2ð 2ús   ‡AÁA"Ú_gateway_queuesÚ_gateway_notify_cbsc                 óL   — t         5  |t        | <   ddd«       y# 1 sw Y   yxY w)u¶   Register ``cb(approval_data: dict) -> None`` for sending approval requests. The callback
    bridges syncâ†’async: it runs in the agent thread and must schedule the send on the loop.N)r:   rK   )r7   Úcbs     r5   Úregister_gateway_notifyrN   z   s'   € ô 
ñ .Ø+-Ô˜KÑ(÷.÷ .ñ .úó   ‡
š#c                 óÒ   — t         5  t        j                  | d«       t        j                  | g «      D ]  }|j                  j                  «        Œ 	 ddd«       y# 1 sw Y   yxY w)z‰Unregister the callback and wake ALL blocked threads for this session so
    they don't hang forever (agent run finished or interrupted).N)r:   rK   r;   rJ   ÚeventÚset©r7   Úentrys     r5   Úunregister_gateway_notifyrU   �   sV   € ô 
ñ Ü×Ñ ¨TÔ2Ü$×(Ñ(¨°bÓ9ò 	ˆEØ�K‰K�O‰OÕñ	÷÷ ñ ús   ‡AAÁA&FÚchoiceÚresolve_allÚreasonÚ
request_idc                 óV  — t         5  t        j                  | «      }|s
	 ddd«       y|rS|D �cg c]#  }|j                  j                  d«      |k(  sŒ"|‘Œ% }}|s
	 ddd«       y|D �cg c]	  }||vsŒ|‘Œ c}|dd n0|rt	        |«      }|j                  «        n|j                  d«      g}|st        j                  | d«       |D ],  }||_        |r||_        |j                  j                  «        Œ. 	 ddd«       t        |«      S c c}w c c}w # 1 sw Y   t        «      S xY w)aW  Unblock waiting agent thread(s) from the gateway's /approve or /deny handler.

    *resolve_all* resolves every pending approval (``/approve all``); otherwise the oldest
    (FIFO) or the one matching *request_id*. *reason* is the ``/deny <reason>`` free text,
    relayed to the agent in the BLOCKED message. Returns the number resolved.
    Nr   rY   )r:   rJ   r0   ÚdataÚlistÚclearr;   ÚresultrX   rQ   rR   r<   )r7   rV   rW   rX   rY   ÚqueuerT   Útargetss           r5   Úresolve_gateway_approvalra   Š   s  € ô 
ñ Ü×#Ñ# KÓ0ˆÙØ÷ð ñ Ø*/Ö^ °5·:±:·>±>À,Ó3OÐS]Ó3]’uÐ^ˆGÐ^ÙØ÷ð ð ,1ÖI %°EÀÒ4HšÒIˆE‘!‰HÙÜ˜5“kˆGØ�K‰K�Mà—y‘y “|�nˆGÙÜ×Ñ ¨TÔ2ð ò 	ˆEØ!ˆEŒLÙØ%�”Ø�K‰K�O‰OÕñ		÷'ô0 ˆw‹<Ðùò' _ùò J÷ô0 ˆw‹<Ðús@   ‡D©D¯#DÁDÁDÁ%DÁ)	DÁ3DÁ7B DÄ
DÄD(Úcausec                 ó>  ‡— t         5  t        j                  | g «      }t        ˆfd„|D «       d«      }|€
	 ddd«       y|j	                  |«       |st        j                  | d«       ||_        |j                  j                  «        ddd«       y# 1 sw Y   yxY w)u  Withdraw one pending approval nobody can answer (the only attached client cannot render it).
    The waiter wakes at once with ``cancelled=cause`` â€” a withdrawal, never a user deny â€” instead of
    idling for the whole approvals.timeout (#112548). False when it is no longer pending.c              3   ó`   •K  — | ]%  }|j                   j                  d «      ‰k(  sŒ"|–— Œ' y­w)rY   N)r[   r0   )Ú.0ÚerY   s     €r5   ú	<genexpr>z,withdraw_gateway_approval.<locals>.<genexpr>µ   s%   øè ø€ ÒQ˜A¨!¯&©&¯*©*°\Ó*BÀjÓ*P”aÑQùs   ƒ#.§.NFT)	r:   rJ   r0   r>   Úremover;   Ú	cancelledrQ   rR   )r7   rY   rb   r_   rT   s    `   r5   Úwithdraw_gateway_approvalrj   ¯   s�   ø€ ô 
ñ 	Ü×#Ñ# K°Ó4ˆÜÓQ ÔQÐSWÓXˆØˆ=Ø÷		ð 	ð
 	�‰�UÔÙÜ×Ñ ¨TÔ2ØˆŒØ�‰�‰Ô÷	ð ÷	ð ús   ˆ/BÁ A
BÂBc                 ó²   — t         5  t        j                  | g «      D �cg c]  }t        |j                  «      ‘Œ c}cddd«       S c c}w # 1 sw Y   yxY w)zEReturn replay-safe snapshots of unresolved approvals for one session.N©r:   rJ   r0   Údictr[   rS   s     r5   Úlist_gateway_approvalsrn   À   sK   € ä	ñ TÜ.=×.AÑ.AÀ+ÈrÓ.RÖS U”�U—Z‘ZÕ ÒS÷Tñ TùÚS÷Tð Tús   ‡A A¼AÁAÁAc                 óÐ   — t         5  t        j                  | g «      D ]1  }|j                  j                  d«      |k(  sŒ"||_         ddd«       y 	 ddd«       y# 1 sw Y   yxY w)zÁAttach ``settle(reason)`` to one pending approval; it runs once when that wait ends by any path.
    False when the request is no longer pending (the surface should withdraw its prompt itself).rY   NTF)r:   rJ   r0   r[   Úsettle)r7   rY   rp   rT   s       r5   Úregister_gateway_settlerq   Æ   sf   € ô 
ñ Ü$×(Ñ(¨°bÓ9ò 	ˆEØ�z‰z�~‰~˜lÓ+¨zÓ9Ø%�”Ø÷	ð ñ	÷ð
 ÷ð
 úó   ‡8AÁ AÁAÁA%c                 óÐ   — t         5  t        j                  | g «      D ]1  }|j                  j                  d«      |k(  sŒ"d|_         ddd«       y 	 ddd«       y# 1 sw Y   yxY w)zDRecord that a client received a particular pending approval request.rY   TNF)r:   rJ   r0   r[   Úacknowledged)r7   rY   rT   s      r5   Úack_gateway_approvalru   Ñ   se   € ä	ñ Ü$×(Ñ(¨°bÓ9ò 	ˆEØ�z‰z�~‰~˜lÓ+¨zÓ9Ø%)�Ô"Ø÷	ð ñ	÷ð
 ÷ð
 úrr   c                 óv   — t         5  t        t        j                  | «      «      cddd«       S # 1 sw Y   yxY w)zFCheck if a session has one or more blocking gateway approvals waiting.N)r:   ÚboolrJ   r0   rC   s    r5   Úhas_blocking_approvalrx   Û   s-   € ä	ñ 6Ü”O×'Ñ'¨Ó4Ó5÷6÷ 6ò 6ús   ‡/¯8c                  ó‚   — t         5  t        d„ t        j                  «       D «       «      cddd«       S # 1 sw Y   yxY w)u[   Unresolved gateway approvals across every session â€” a backend blocked on one is not idle.c              3   ó2   K  — | ]  }t        |«      –— Œ y ­w©N)r<   )re   r_   s     r5   rg   z1pending_gateway_approval_count.<locals>.<genexpr>ä   s   è ø€ ÒD %”3�u—:ÑDùs   ‚N)r:   ÚsumrJ   Úvaluesr3   r4   r5   Úpending_gateway_approval_countr~   á   s5   € ä	ñ EÜÑD¬?×+AÑ+AÓ+CÔDÓD÷E÷ Eò Eús   ‡$5µ>c                 ó²   — | syt         5  t        j                  | «      }|s
	 ddd«       yt        |d   j                  «      cddd«       S # 1 sw Y   yxY w)u—   Copy of the oldest unresolved gateway approval, for reconnecting clients
    to restore a prompt. Read-only snapshot â€” the queue stays authoritative.Nr   rl   )r7   r_   s     r5   Úget_pending_gateway_approvalr€   ç   sT   € ñ ØÜ	ñ #Ü×#Ñ# KÓ0ˆÙØ÷#ð #ô �E˜!‘H—M‘MÓ"÷	#÷ #ò #ús   ŠA¬AÁAÚapprovalc                 óL   — t         5  |t        | <   ddd«       y# 1 sw Y   yxY w)z/Store a pending approval request for a session.N)r:   r#   )r7   r�   s     r5   Úsubmit_pendingrƒ   ó   s$   € ä	ñ )Ø (Œ�Ñ÷)÷ )ñ )úrO   Úpattern_keyc                 ó”   — t         5  t        j                  | t        «       «      j	                  |«       ddd«       y# 1 sw Y   yxY w)z(Approve a pattern for this session only.N)r:   r$   Ú
setdefaultrR   Úadd)r7   r„   s     r5   Úapprove_sessionrˆ   ù   s;   € ä	ñ JÜ×$Ñ$ [´#³%Ó8×<Ñ<¸[ÔI÷J÷ Jñ Jús	   ‡.>¾Ac                 óp   — 	 ddl m}  || «       y# t        $ r t        j	                  d| d¬«       Y yw xY w)a  Drop resources whose immutable mode derives from Hermes YOLO. Lazy import so approval-only
    sessions never load computer-use; releasing on BOTH edges makes enabling YOLO replace a
    standard backend and disabling it revoke a private unrestricted daemon immediately.r   )Úrelease_computer_use_sessionz<Failed to release permission-mode dependent resources for %sT)Úexc_infoN)Útools.computer_use.toolrŠ   Ú	ExceptionrF   Údebug)r7   rŠ   s     r5   Ú#_release_permission_mode_dependentsr�   ÿ   s9   € ðqÝHá$ [Õ1øÜò qÜ�‰ÐSÐU`ÐkoˆÖpðqús   ‚ ‘!5´5Úenabledc                 ó¦   — | sy t         5   |rt        j                  nt        j                  | «       d d d «       t	        | «       y # 1 sw Y   ŒxY wr{   )r:   r%   r‡   Údiscardr�   )r7   r�   s     r5   Ú_set_session_yolor“     sF   € ÙØÜ	ñ OØ	@™gŒ×	Ò	¬=×+@Ñ+@À+ÔN÷Oä'¨Õ4÷Oð Oús   Š)AÁAc                 ó   — t        | d«       y)z,Enable YOLO bypass for a single session key.TN©r“   rC   s    r5   Úenable_session_yolor–     s   € ä�k 4Õ(r4   c                 ó   — t        | d«       y)z-Disable YOLO bypass for a single session key.FNr•   rC   s    r5   Údisable_session_yolor˜     s   € ä�k 5Õ)r4   c                 óÐ  — | syt         5  t        j                  | d«       t        j	                  | «       t
        j                  | d«       t        j                  | g «      D ]#  }d|_        |j                  j                  «        Œ% 	 ddd«       t        | «       dD ]+  \  }}	  t        t        j                  |«      |«      | «       Œ- y# 1 sw Y   ŒExY w# t        $ r Y ŒFw xY w)z7Remove all approval and yolo state for a given session.Nz0the session ended before the prompt was answered))ztools.code_kernelÚshutdown_kernels_for_owner)ztools.code_kernel_remoteÚ!shutdown_remote_kernels_for_owner)r:   r$   r;   r%   r’   r#   rJ   ri   rQ   rR   r�   ÚgetattrÚ	importlibÚimport_moduler�   )r7   rT   ÚmoduleÚshutdowns       r5   Úclear_sessionr¡     sÕ   € áØÜ	ñ Ü×Ñ˜k¨4Ô0Ü×Ñ˜kÔ*Ü�‰�[ $Ô'Ü$×(Ñ(¨°bÓ9ò 	ˆEð QˆEŒOØ�K‰K�O‰OÕñ		÷	ô (¨Ô4ð`ò Ñˆ�ð	Ø>ŒG”I×+Ñ+¨FÓ3°XÓ>¸{ÕKñ÷ð ûô  ò 	Ùð	ús   ŠA>CÂ%%CÃCÃ	C%Ã$C%c                 óP   — | syt         5  | t        v cddd«       S # 1 sw Y   yxY w)z?Return True when YOLO bypass is enabled for a specific session.FN)r:   r%   rC   s    r5   Úis_session_yolo_enabledr£   5  s(   € áØÜ	ñ ,ØœmÐ+÷,÷ ,ò ,ús   Šœ%c                  ó,   — t        t        d¬«      «      S )zEReturn True when the active approval session has YOLO bypass enabled.r!   ©Údefault)r£   r   r3   r4   r5   Úis_current_session_yolo_enabledr§   =  s   € ä"Ô#:À2Ô#FÓGÐGr4   c                  ó&   — t         xs
 t        «       S )z”CLI ``--yolo`` (process-scoped, frozen at import) or gateway ``/yolo``
    (session-scoped). Hardline / deny-rule floors run BEFORE this everywhere.)r"   r§   r3   r4   r5   Ú_yolo_activer©   B  s   € ô ÒAÔ ?Ó AÐAr4   c                  ó   — ddl m} m}  | «       €t        S  |«       }t        j                  |«      }|€	 t        «       }|t        |<   |S # t        $ r*}t        j                  d|«       t        «       }Y d}~Œ9d}~ww xY w)u÷  The permanent allowlist that governs the ACTIVE profile. Unscoped (single-profile process,
    or the multiplexer's own launch profile) â†’ the module-level set tests and the CLI seed. A routed
    profile (HERMES_HOME override) â†’ its own set, lazily loaded from ITS ``command_allowlist``: the
    launch profile's "always" approvals must not pre-approve commands for a secondary, nor may a
    secondary's "always" choice be written back into the launch profile's config. Callers hold ``_lock``.
    r   ©Úget_hermes_home_overrideÚhermes_home_keyNú&Failed to load permanent allowlist: %s)Úhermes_constantsr¬   r­   r&   r'   r0   Ú_read_permanent_allowlistr�   rF   rG   rR   )r¬   r­   Úhome_keyÚapprovedrf   s        r5   Ú_permanent_setr³   H  s|   € ÷ KÙÓ!Ð)Ü"Ð"ÙÓ €HÜ*×.Ñ.¨xÓ8€HØÐð	Ü0Ó2ˆHð 19Ô# HÑ-Ø€Oøô	 ò 	Ü�N‰NÐCÀQÔGÜ“u�Hûð	ús   µ
A
 Á
	A=Á A8Á8A=c                 óÊ   ‡— t        |«      }t        5  t        «       t        j	                  | t        «       «      z  Šddd«       t        ˆfd„|D «       «      S # 1 sw Y   ŒxY w)z¢Session-scoped or permanent approval. Accepts the canonical key and the legacy
    regex-derived key so existing command_allowlist entries survive key migrations.Nc              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wr{   r3   )re   Úaliasr²   s     €r5   rg   zis_approved.<locals>.<genexpr>d  s   øè ø€ Ò6 Uˆu˜Ô Ñ6ùs   ƒ)r   r:   r³   r$   r0   rR   Úany)r7   r„   Úaliasesr²   s      @r5   Úis_approvedr¹   ^  sY   ø€ ô $ KÓ0€GÜ	ñ PÜ!Ó#Ô&7×&;Ñ&;¸KÌËÓ&OÑOˆ÷PäÓ6¨gÔ6Ó6Ð6÷Pð Pús   “*AÁA"c                 ót   — t        | «      }t        5  t        d„ |D «       «      cddd«       S # 1 sw Y   yxY w)zFPermanent approval only, with compatibility for migrated pattern keys.c              3   ó4   K  — | ]  }|t        «       v –— Œ y ­wr{   )r³   )re   r¶   s     r5   rg   z+_is_permanently_approved.<locals>.<genexpr>k  s   è ø€ ÒB°�5œNÓ,Ô,ÑBùs   ‚N)r   r:   r·   )r„   r¸   s     r5   Ú_is_permanently_approvedr¼   g  s6   € ä# KÓ0€GÜ	ñ CÜÑB¸'ÔBÓB÷C÷ Cò Cús   ’.®7c                 ól   — t         5  t        «       j                  | «       ddd«       y# 1 sw Y   yxY w)z)Add a pattern to the permanent allowlist.N)r:   r³   r‡   )r„   s    r5   Úapprove_permanentr¾   n  s+   € ä	ñ *ÜÓ×Ñ˜[Ô)÷*÷ *ñ *ús   ‡*ª3Úpatternsc                 ó�   — t         5  t        «       }|j                  «        |j                  | «       ddd«       y# 1 sw Y   yxY w)z2Bulk-load permanent allowlist entries from config.N)r:   r³   r]   Úupdate)r¿   Ú	governings     r5   Úload_permanentrÃ   t  s:   € ä	ñ #Ü"Ó$ˆ	Ø�‰ÔØ×Ñ˜Ô"÷#÷ #ñ #ús	   ‡,<¼AÚwarningsc                 óÖ   — |D ]X  \  }}}|dvrŒt        | |«       |dk(  sŒ|rŒ!t        |«       t        5  t        t	        «       «      }ddd«       t        «       ŒZ y# 1 sw Y   ŒxY w)a  Persist a human ``session``/``always`` choice for each ``(key, _, is_tirith)``. Tirith
    findings are session-max by design (no broad permanent allowlisting of content-level
    findings), so ``always`` downgrades them to session. ``once`` persists nothing.)ÚsessionÚalwaysrÇ   N)rˆ   r¾   r:   rR   r³   Úsave_permanent_allowlist)r7   rV   rÄ   ÚkeyÚ_Ú	is_tirithÚsnapshots          r5   Ú_persist_choicerÍ   |  so   € ð &ò /ÑˆˆQ�	ØÐ.Ñ.ØÜ˜ SÔ)Ø�XÓ¢iÜ˜cÔ"Üñ 1Üœ~Ó/Ó0�÷1ä$ XÕ.ñ/÷1ð 1ús   µAÁA(	c                  óŽ  — ddl m}   | «       }|j                  d«      }t        |t        «      }|rddl}	 |j                  |«      }|€|sg }t        |t        «      rt        d„ |D «       «      rt        j                  d«       t        «       S |rt        j                  d«       t        |«      S # |j                  $ r d}Y Œ|w xY w)	zY``command_allowlist`` of the active profile's config as a set (empty on malformed input).r   )Úload_config_readonlyÚcommand_allowlistNFc              3   ó>   K  — | ]  }t        |t        «       –— Œ y ­wr{   )Ú
isinstanceÚstr)re   Úitems     r5   rg   z,_read_permanent_allowlist.<locals>.<genexpr>œ  s   è ø€ Ò'RÀd¬J°t¼SÓ,AÔ(AÑ'Rùs   ‚zBIgnoring malformed command_allowlist; configure a list of strings.zKRecovered legacy string command_allowlist; re-save it as a list of strings.)Úhermes_cli.configrÏ   r0   rÒ   rÓ   ÚyamlÚ	safe_loadÚ	YAMLErrorr\   r·   rF   rG   rR   )rÏ   ÚconfigÚrawÚlegacyrÖ   s        r5   r°   r°   �  s­   € å6Ù!Ó#€FØ
�*‰*Ð(Ó
)€CÜ˜œSÓ!€FÙãð	Ø—.‘. Ó%ˆCð €{™6ØˆÜ�cœ4Ô ¤CÑ'RÈcÔ'RÔ$RÜ�‰Ð[Ô\Ü‹uˆÙÜ�‰ÐdÔeÜˆs‹8€Oøð �~‰~ò 	ØŠCð	ús   ¶B0 Â0CÃCÚ_permanent_baseline_by_homec                  ó2   — ddl m} m}  | «       €dS  |«       S )Nr   r«   r!   )r¯   r¬   r­   r«   s     r5   Ú_baseline_keyrÞ   ­  s   € ßJÙ)Ó+Ð3ˆ2ÐJ¹Ó9JÐJr4   c                  ó
  — 	 t        «       } t        | «       t        5  t        | «      t        t        «       <   ddd«       | S # 1 sw Y   | S xY w# t        $ r*}t        j                  d|«       t        «       cY d}~S d}~ww xY w)z�Load ``command_allowlist`` from config and sync it into the approval state
    so is_approved() honors 'always' choices from previous sessions.Nr®   )	r°   rÃ   r:   rR   rÜ   rÞ   r�   rF   rG   )r¿   rf   s     r5   Úload_permanent_allowlistrà   ²  sm   € ðÜ,Ó.ˆÜ�xÔ Üñ 	IÜ;>¸x»=Ô'¬«Ñ8÷	Iàˆ÷	IàˆûÜò Ü�‰Ð?ÀÔCÜ‹u�ûðús9   ‚A �A¸	A ÁAÁA ÁA Á	BÁA=Á7BÁ=Bc                 ó  — 	 ddl m}m}  |«       }t        |j	                  dg «      xs g «      }t
        5  t        «       }t        j	                  |t        «       «      }|t        | «      |z
  z  }t        |«      |d<    ||«       t        |«      t        |<   t        «       }|j                  «        |j                  |«       ddd«       y# 1 sw Y   yxY w# t        $ r }	t        j                  d|	«       Y d}	~	yd}	~	ww xY w)a¯  Save permanently allowed command patterns to config, reconciling with the file.

    ``command_allowlist`` is a file an operator edits by hand; removing an entry
    there is the documented way to withdraw a standing approval. This process read
    it once at import and ``load_permanent`` only ever unions, so writing the
    in-memory set straight back deleted entries added on disk since import and
    resurrected the ones removed. The result written is ``what is on disk now``
    plus ``what this process approved since its own baseline``; revoked entries are
    also dropped from the governing permanent set so ``is_approved()`` stops
    honouring them. Nothing re-reads the file on the approval hot path.

    ``patterns`` may only ADD: an entry left out of it is not removed, because the
    on-disk list wins for anything this process did not approve itself. Remove
    entries by editing ``command_allowlist`` in config.yaml.
    r   )Úload_configÚsave_configrÐ   NzCould not save allowlist: %s)rÕ   râ   rã   rR   r0   r:   rÞ   rÜ   Úsortedr³   r]   rÁ   r�   rF   rG   )
r¿   râ   rã   rÙ   Úon_diskrÉ   ÚbaselineÚmergedrÂ   rf   s
             r5   rÈ   rÈ   À  sÛ   € ð :ß>Ù“ˆÜ�f—j‘jÐ!4°bÓ9Ò?¸RÓ@ˆÜñ 		%Ü“/ˆCÜ2×6Ñ6°s¼C»EÓBˆHØ¤ H£°Ñ 8Ñ9ˆFÜ*0°«.ˆFÐ&Ñ'Ù˜ÔÜ/2°6«{Ô'¨Ñ,Ü&Ó(ˆIØ�O‰OÔØ×Ñ˜VÔ$÷		%÷ 		%ñ 		%ûô ò :Ü�‰Ð5°q×9Ñ9ûð:ús5   ‚4C ¶BCÃC ÃCÃC ÃC Ã	DÃ!C<Ã<Dc                 óZ   — t         xs$ t        | «      xs t        j                  «       dk(  S )uü   Canonical three-source bypass check: process ``--yolo`` (frozen at import), the
    session-scoped gateway ``/yolo`` toggle, ``approvals.mode: off``. Pure bypass
    sub-expression only â€” hardline blocklist / permanent allowlist are the caller's job.Úoff)r"   r£   r   Ú_get_approval_moderC   s    r5   Ú%is_approval_bypass_active_for_sessionrë   ä  s*   € ô ÒwÔ!8¸Ó!EÒwÔIY×IlÑIlÓInÐrwÑIwÐxr4   c                  ó,   — t        t        d¬«      «      S )z?Return whether the current approval context has bypass enabled.r!   r¥   )rë   r   r3   r4   r5   Úis_approval_bypass_activerí   ë  s   € ä0Ô1HÐQSÔ1TÓUÐUr4   c                  ó   — dd dœS )NT©r²   Úmessager3   r3   r4   r5   Ú	_approvedrñ   ò  s   € Ø¨Ñ.Ð.r4   u*   You denied this {noun} â€” it did not run.u6   No answer within {minutes} â€” the {noun} did not run.uG   The approval request could not be delivered â€” the {noun} did not run.uR   The approval prompt was withdrawn or never reached you â€” the {noun} did not run.uG   This {noun} is not allowed in an unattended session â€” it did not run.)ÚdeniedÚtimeoutÚnotify_failedri   ÚblockedÚcommandÚoutcomeÚnounc                 óz   — ddl m}m}  | |«       «      }t        j	                  | d«      j                  ||¬«      S )Nr   )Ú_get_approval_timeoutÚformat_approval_windowzThis {noun} did not run.)rø   Úminutes)Útools.approval_contextrú   rû   Ú_USER_SUMMARIESr0   Úformat)r÷   rø   rú   rû   Úwindows        r5   Ú_user_summaryr    s9   € ßTÙ#Ñ$9Ó$;Ó<€FÜ×Ñ˜wÐ(BÓC×JÑJÐPTÐ^dÐJÓeÐer4   )rø   rð   Údescriptionc          
      ó.   — d| |||dt        ||«      dœ|¥S )z¤Standard non-consent result: the agent must not retry or rephrase. ``user_summary`` is the
    one-line human reading of the same outcome (see ``_USER_SUMMARIES``).F)r²   rð   r„   r  r÷   Úuser_consentÚuser_summary)r  )rð   r„   r  r÷   rø   Úextras         r5   Ú_deniedr    s1   € ð ¨'À+Ø&°7ÈEÜ)¨'°4Ó8ñCà<AðCð Cr4   c                ó   — d| ||dœS )zKNon-interactive block (cron / -q / unattended / no-human): no consent keys.F)r²   rð   r„   r  r3   )rð   r„   r  s      r5   Ú_blockedr	    s   € à¨'À+Ð^iÑjÐjr4   c                 ó&   — t        | «       ddd|dœS )zvA human approval (incl. ESCALATE-then-approve or a smart-DENY owner
    override) resets the consecutive-denial tally.TN)r²   rð   Úuser_approvedr  )rD   )r7   r  s     r5   Ú_user_approvedr    s   € ô �;ÔØ¨ÀÐU`ÑaÐar4   c                 ód   — t         5  t        j                  | «      cd d d «       S # 1 sw Y   y xY wr{   )r:   rK   r0   rC   s    r5   Ú_gateway_notify_cbr    s(   € Ü	ñ 4Ü"×&Ñ& {Ó3÷4÷ 4ò 4ús   ‡&¦/Úpattern_keysÚbodyÚsmart_deniedc                ó0  — ||dœ}| j                   r||d<   ||d<   |r|j                  dd¬«       t        ||«       | j                   sd|d||d|› d	|› d
�dœS |xs d|› d
�}d|dd||d|› d|› d| j                  › d�dœ}	|r|	j                  dd¬«       |	S )a  Queue an approval nobody can answer right now (no gateway notifier, no CLI panel) for
    ``/approve`` / ``/deny`` review. Command/code gates return the backward-compatible
    ``pending_approval`` shape (``pattern_keys`` + STOP text); the action gate ``approval_required``.)rö   r„   r  r  TF)r  Úallow_permanentÚapproval_requiredu-   âš ï¸� This action is potentially dangerous (z2). Asking the user for approval.

**Target:**
```
ú
```)r²   r„   Ústatusrö   r  rð   z**Command:**
```
Úpending_approvalu   âš ï¸� z!. Asking the user for approval.

z2

STOP: do NOT re-run, rephrase, or re-issue this u�    â€” each variant sends the user ANOTHER approval card. Wait for the user's decision; if this turn must end, report that approval is pending.)r²   r„   r  Úapproval_pendingrö   r  rð   )Úpending_keysrÁ   rƒ   rø   )
Úspecr7   rö   r  r„   r  r  r  Úpendingr^   s
             r5   Ú_pending_resultr  "  sô   € ð "°+Ñ>€GØ×ÒØ".ˆ�ÑØ(€GˆMÑÙØ�‰ D¸%ˆÔ@Ü�; Ô(Ø×Òà¨kÐEXØ¨{ØGÈÀ}ð UNØNUÈYÐV[ð]ñ
ð 	
ð Ò7Ð(¨¨	°Ð7€Dà¨+ÐASØ ¨WÀ[à�k�]Ð"EÀdÀVð L?Ø?C¿y¹y¸kð JWðWñ		€Fñ Ø�‰ 4¸ˆÔ?Ø€Mr4   T)Úfrozenc                   ó~   — e Zd ZU dZeed<   eed<   eed<   eed<   eed<   defd„Zd	ed
ededefd„Zedefd„«       Z	y)Ú_UnattendedzGOne non-interactive context and the text every gate uses to explain it.ÚnameÚcfg_keyÚclauseÚscopeÚtrustr*   c                 óH   —  t        t        d| j                  › d�«      «       S )NÚ_get_Ú_approval_mode)rœ   r   r   ©Úselfs    r5   Úmodez_Unattended.modeQ  s"   € àKŒwÔ'¨5°·±°¸>Ð)JÓKÓMÐMr4   Úsubjectrø   Úadvicec                óh   — d|› d| j                   › d|› d|› d| j                  › d| j                  › d�S )Nú	BLOCKED: z but z. z
 To allow Ú z, set approvals.ú: approve in config.yaml.)r"  r#  r!  )r)  r+  rø   r,  s       r5   Úblock_messagez_Unattended.block_messageU  sL   € Ø˜G˜9 E¨$¯+©+¨°b¸¸À
È4È&ÐPQÐRV×R\ÑR\ÐQ]ð ^Ø!Ÿ\™\˜NÐ*CðEð 	Fr4   c                 ó”   — | j                   d   j                  «       › | j                   dd  › d| j                  › d| j                  › d�S )Nr   r9   z-. Use normal tools instead, or set approvals.z: approve only if ú.)r"  Úupperr!  r$  r(  s    r5   Ú	exec_tailz_Unattended.exec_tailY  sP   € à—;‘;˜q‘>×'Ñ'Ó)Ð*¨4¯;©;°q°r¨?Ð*;ð <-Ø-1¯\©\¨NÐ:LÈTÏZÉZÈLÐXYð[ð 	\r4   N)
Ú__name__Ú
__module__Ú__qualname__Ú__doc__rÓ   Ú__annotations__r*  r1  Úpropertyr5  r3   r4   r5   r  r  H  sp   … áQØ
ƒIØƒLØƒKØƒJØƒJðN�có NðF Sð F°3ð FÀð FÈó Fð ð\˜3ò \ó ñ\r4   r  Úsingle_queryÚsingle_query_modez@single-query mode (-q) runs without a user present to approve itzin single-query modez.this single-query run is intentionally trustedÚcronÚ	cron_modez2cron jobs run without a user present to approve itzin cron jobsz*this cron profile is intentionally trustedc            	      óò   — g } t        «       r| j                  t        «       t        «       r| j                  t        «       | S t        «       r*| j                  t        dddt        «       › d�dd«      «       | S )zèActive unattended contexts in evaluation order: single-query first (``hermes chat -q``
    exports HERMES_INTERACTIVE=1 but nobody answers); cron beats a platform marker because
    cron binds the platform for delivery routing only.Ú
unattendedÚunattended_modez-this session runs on an unattended platform (z$) with no user present to approve itzon unattended platformsz2sessions on this surface are intentionally trusted)r   ÚappendÚ_SINGLE_QUERY_CTXr	   Ú	_CRON_CTXr   r  r   )Úcontextss    r5   Ú_unattended_contextsrG  j  sz   € ð €HÜ(Ô*Ø�‰Ô)Ô*Ü Ô"Ø�‰œ	Ô"ð €Oô 
2Ô	3Ø�‰œØÐ+ðÜ%Ó'Ð(Ð(LðNà%Ð'[ó	
ô 	ð €Or4   Úctxc                 óÆ  ‡— ‰j                  «       dk7  rydt        dt        fˆfd„}t        | «      \  }}}|r;t	        |«      s0 |d|› d�«      }‰j
                  dk(  r|j                  ||¬	«       |S 	 d
dlm}  || «      }|j                  d«      dv r |t        |«      «      S y# t        $ r/ t        «       rY ydd‰j                  › d‰j                  › d�dœcY S w xY w)a„  Deny-mode handling for one unattended context (cron / -q / webhook); None = allow.

    Pattern detection first, then tirith so content-level threats (homograph URLs,
    pipe-to-interpreter, terminal injection) are caught even when the pattern detector misses.
    An un-importable tirith honours ``security.tirith_fail_open``: fail-closed means block,
    since nobody can approve.
    ÚdenyNr+  r*   c                 ó2   •— d‰j                  | dd¬«      dœS )NFúdangerous commandsú6Find an alternative approach that avoids this command.©rø   r,  rï   )r1  )r+  rH  s    €r5   Úblockz_unattended_deny.<locals>.blockˆ  s/   ø€ Ø!¨c×.?Ñ.?ØÐ.ØKð /@ó /Mñ Nð 	Nr4   úCommand flagged as dangerous (ú)r<  ©r„   r  r   ©Úcheck_command_securityFu–   BLOCKED: the Tirith security scanner could not be imported and security.tirith_fail_open is false, so this command cannot be silently allowed â€” and zA. Find an alternative approach, install tirith, or set approvals.r0  rï   Úaction)rO  Úwarn)r*  rÓ   rm   r   r¼   r   rÁ   Útools.tirith_securityrT  ÚImportErrorr   r"  r!  r0   Ú_format_tirith_description)	rö   rH  rO  Úis_dangerousr„   r  r^   rT  Útiriths	    `       r5   Ú_unattended_denyr\  }  s  ø€ ð ‡x�xƒz�VÒØðN”sð Nœtõ Nô
 .FÀgÓ-NÑ*€L�+˜{ÙÔ4°[ÔAÙÐ7¸°}ÀAÐFÓGˆØ�8‰8�~Ò%Ø�M‰M k¸{ˆMÔKØˆð	wÝ@Ù'¨Ó0ˆð ‡z�z�(ÓÐ0Ñ0ÙÔ/°Ó7Ó8Ð8Øøô ò wÜÔÙØ!ðBØBEÇ*Á*Àð NNØNQÏkÉkÈ]ÐZsðuñwò 	wðwús   Á5B( Â(C Â= C ÃC c                   ó|   — e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed<   eed	<   eed
<   eed<   y)Ú	_GateSpecrø   Ú	transportr  Ú
redact_clir  rô   Úgateway_refusedÚtransport_deniedÚcli_timeoutÚ
cli_deniedÚ	smart_logN)r6  r7  r8  rÓ   r:  rw   r3   r4   r5   r^  r^  ¨  sB   … à
ƒIØƒOØÓØÓØÓð ÓØÓØÓØÓØƒOØ„Nr4   r^  a   The user has NOT consented to this action. Do NOT retry this command, do NOT rephrase it, and do NOT attempt the same outcome via a different command. Stop the current workflow and wait for the user to respond before taking any further destructive or irreversible action.zŠ The user has NOT consented to this action. Do NOT retry it, do NOT rephrase it, and do NOT attempt the same outcome via a different path.z?BLOCKED: Failed to send approval request to user. Do NOT retry.z+BLOCKED: Command {reason}.{reason_addendum}z{timeout_addendum}{breaker}z¾BLOCKED: User denied this command through the selected approval transport. The user has NOT consented to this action. Do NOT retry or attempt the same outcome through another route.{breaker}z1BLOCKED: Command timed out without user response.z! Silence is not consent.{breaker}z"BLOCKED: User denied this command.ú	{breaker}z9Smart approval: auto-approved '{command}' ({description}))rø   r_  r  r`  r  rô   ra  rb  rc  rd  re  ÚcodezLBLOCKED: Failed to send execute_code approval request to user. Do NOT retry.zçBLOCKED: execute_code script {reason}.{reason_addendum} The user has NOT consented to running this code. Do NOT retry, do NOT rephrase the script, and do NOT attempt the same outcome via a different tool.{timeout_addendum}{breaker}zfBLOCKED: User denied execute_code through the selected approval transport. The user has NOT consented.z0BLOCKED: Action timed out without user response.uŒ   BLOCKED: User denied execute_code script execution (matched '{description}'). Do NOT retry â€” the user has explicitly rejected it.{breaker}zDSmart approval: auto-approved execute_code for session {session_key}rU  z*BLOCKED: Action {reason}.{reason_addendum}z{timeout_addendum}ú Silence is not consent.u‡   BLOCKED: User denied this potentially dangerous action (matched '{description}'). Do NOT retry â€” the user has explicitly rejected it.r  Úhuman_presentc                ó  — t        |||||«      }|dk(  rHt        |«       t        j                  | j                  j                  |dd ||¬«      «       ddd|dœdfS |dk7  ry	t        |«       |ry
dd|› dt        |«      › �ddœdfS )u3  Guardian-LLM step -> ``(result, smart_denied_for_owner)``: a result ends the gate;
    ``smart_denied_for_owner`` means an interactive owner may still override the DENY for this
    one operation (once/deny only, nothing persists).

    APPROVE approves this command only â€” pattern-level persistence would let one benign
    command suppress review of later commands in the same broad detector category. A DENY
    counts toward the denial breaker even when an owner may override it. ESCALATE follows the
    normal, potentially persistent manual behavior.
    ÚapproveNé<   )rö   r  r7   T)r²   rð   Úsmart_approvedr  FrJ  ©NF)NTzBLOCKED by smart approval: z@. The command was assessed as genuinely dangerous. Do NOT retry.)r²   rð   r  )r   rD   rF   rŽ   re  rÿ   rA   rI   )r  rö   r  r„   r  r7   ri  Úverdicts           r5   Ú_smart_gaterp  ù  s·   € ô ˜W k°;ÀÈkÓZ€GØ�)ÒÜ�{Ô#Ü�‰�T—^‘^×*Ñ*°7¸3¸B°<È[ÐfqÐ*ÓrÔsØ ¨TÀTÐZeÑfÐhmÐmÐmØ�&ÒØÜ�;ÔÙØð Ø1°+°ð ?/Ü/GÈÓ/TÐ.UðWàñð ðð r4   )ÚsmartÚpermanent_capableÚpending_bodyÚis_cliÚ
is_gatewayÚis_askrq  rr  c          
      óð  ‡ ‡‡‡‡‡— ddl m} dŠ|r!t        ‰ |‰‰|‰|xs |	xs |
¬«      \  }Š|�|S |r |«       nd}|xr ‰ }dt        dt        dt        fˆˆˆˆ fd	„}d
t        dt        fˆˆˆˆ ˆfd„}‰ j
                  r\t        |‰‰|‰|	s|
rdnd‰ |¬«      }t        |‰‰¬«      \  }}|�|S |�+|dk(  rt        ‰«        |‰ j                  d«      S  ||«      S |	s|
�r: ||«      } |‰«      }t        ‰«      }|�ì|‰|||xr ‰ ‰ dœ}‰rd|d<   t        ‰||d¬«      }|j                  d«      r$t        ‰ j                  ‰‰d‰ j                  ¬«      S |d
   |j                  d«      }}|j                  d«      r |‰ j                   dd|d   › d�ddd¬«      S |d   s |‰ j                   dd dd!|¬«      S |�|dk(  r  |‰ j                   dd"|rd#|› d$�ndd|¬«      S  ||«      S t#        |||¬%«      s#‰ j$                  s|‰}}t'        ‰ ‰||‰||‰¬&«      S |‰}}‰ j(                  r ||«      } |‰«      }t	        ||‰t+        |«      ‰d¬'«      }t-        j.                  d,i |¤Ž t1        |||‰|¬(«      }t-        j.                  d-i |¤d
|i¤Ž |dk(  r |‰ j2                  d«      S |dk(  r' |‰ j                   dd)t5        |d*d+«      › d�dd!d¬«      S |dk(  r |‰ j6                  d«      S  ||«      S ).a  Ask a human (after the optional guardian-LLM step) and turn the answer into the gate result.

    ``warnings`` are the ``(key, _, is_tirith)`` tuples :func:`_persist_choice` stores on
    session/always. ``permanent_capable`` hides [a]lways when no key could be permanently
    allowlisted (pure-tirith prompts); a smart-DENY owner override reduces every surface to
    once/deny and persists nothing. ``pending_body`` is a thunk, built only once a human is
    actually asked, so a smart APPROVE never pays for redacting a large script.
    r   ©Úredact_sensitive_textF)ri  NÚtemplater÷   r*   c                 óº   •— d}d| v rt        ‰«      }|j                  dd «      }d|v rd|ini }t         | j                  d‰|dœ|¤Žf‰‰|‰	j                  dœ|¤ŽS )Nr!   rf  Údeny_reasonrX   )r  Úbreaker©r„   r  r÷   rø   r3   )rI   r;   r  rÿ   rø   )
rz  r÷   Úfmtr}  r|  r  r  r„   r7   r  s
         €€€€r5   rJ  z_human_decision.<locals>.deny1  s€   ø€ ØˆØ˜(Ñ"Ü.¨{Ó;ˆGØ—g‘g˜m¨TÓ2ˆØ08¸C±� Ñ,ÀRˆÜ��x—‘ÐW°;ÈÑWÐSVÑWð AØ#.¸KØ&¨T¯Y©YñAà:?ñAð 	Ar4   rV   c                 óf   •— ‰st        ‰| ‰«       ‰j                  rt        ‰‰«      S t        «       S r{   )rÍ   r  r  rñ   )rV   r  r7   r  r  rÄ   s    €€€€€r5   Úgrantz_human_decision.<locals>.grant;  s0   ø€ áÜ˜K¨°Ô:Ø×ÒÜ! +¨{Ó;Ð;Ü‹{Ðr4   ÚgatewayÚcli)rö   r  r„   r  r7   ÚsurfaceÚallow_sessionr  rR  rJ  rò   )rö   r„   r  r  r  r…  Tr  )r„  rô   r~  rX   ri   z1approval was withdrawn before the user answered (rQ  r!   )rX   Úreason_addendumÚtimeout_addendumr|  Úresolvedró   ztimed out without user responserh  zdenied by userz Reason given by the user: "z".)rt  Úapproval_callbackÚ	notify_cb)rö   r  r„   r  r  r  )rö   r  r„   r  r7   r„  )r  r  r‰  zRwas not approved: the approval prompt could not be delivered or was not answered (rb   z	no answer)Úpre_approval_request)Úpost_approval_response)Úagent.redactry  rp  rÓ   rm   r_  r   r   rA   rb  r  r   r0   r  rô   rø   ra  r   r  r  r`  r\   r   Ú_fire_approval_hookr   rc  rœ   rd  ) r  rö   r  r„   r  rÄ   r7   r‰  rt  ru  rv  rq  rr  rs  ry  r^   r  rJ  r�  ÚattemptrV   rò   Údisplay_commandÚdisplay_descriptionrŠ  r[   Údecisionr|  Úprompt_commandÚprompt_descriptionÚhook_kwargsr  s    ` `` ``                        @r5   Ú_human_decisionr–    sø  ý€ õ 3à€LÙÜ*¨4°¸+À{ÐT`Ø+6ÀfÒFdÐPZÒFdÐ^dô fÑˆ�àÐØˆMÙ%1‘<”>°t€LØ'Ò<°Ð,<€OðA”sð A¤Sð A´D÷ Að Að”cð œd÷ ñ ð ‡~‚~Ü2Ø¨À+Ð\hØ#¹:É©YÐV[Ø*Ð*¸Oô
ˆô
 +¨7ÀÐYdÔe‰ˆ�ØÐØˆMØÐØ˜ÒÜ˜{Ô+Ù˜D×1Ñ1°8Ó<Ð<Ù˜“=Ð ñ ’Vñ 0°Ó8ˆÙ3°KÓ@ÐÜ& {Ó3ˆ	ØÐ ð
 +¸;Ø ,Ð=PØ#4Ò#I¸\Ð9IØ%1Ð!1ñ	ˆDñ Ø'+��^Ñ$Ü.¨{¸IÀtÐU^Ô_ˆHØ�|‰|˜OÔ,Ü˜t×1Ñ1¸{Ø+6ÀÐVZ×V_ÑV_ôað að
 #+¨8Ñ"4°h·l±lÀ8Ó6L�KˆFØ�|‰|˜KÔ(ñ ˜D×0Ñ0°+Ø%VÐW_Ð`kÑWlÐVmÐmnÐ#oØ,.ÀÐQUôWð Wð ˜JÒ'Ù˜D×0Ñ0°)ÐDeØ,.ÐA[Ø(3ô5ð 5ð ˆ~ ¨6Ò!1Ù˜D×0Ñ0°(ÐCSÙ_jÐ/KÈKÈ=ÐXZÑ-[ÐprØ-/¸[ôJð Jñ ˜“=Ð ô
 4ØÐ->È)õ
ð ×$Ò$Ø7>ÀÐ!4�Ü"Ø�k¨?ÐH[ÐitØ)°È<ôð ð *1°+Ð&€NØ‡‚Ù.¨wÓ7ˆÙ2°;Ó?ÐÜ˜~Ð;MÐ[fÜ$(¨Ó$6ÀKÐY^ô`€Kä×(Ñ(ÑOÀ;ÒOÜ& ~Ð7IÐ[jØ4@ÐTeôg€Fä×(Ñ(Ñ`À[Ñ`ÐY_Ó`Ø�ÒÙ�D×$Ñ$ iÓ0Ð0Ø�Òñ �D×(Ñ(¨+ðÜ& v¨w¸ÓDÐEÀQðHà$&Ð9SÐaeôgð 	gð �Òñ �D—O‘O XÓ.Ð.Ù�‹=Ðr4   c                 ó–   — t        | «      } t        «       t        «       }}t        d«      }t	        «       s
t        «       rdx}x}}| |||fS )uz  ``(approval_callback, is_cli, is_gateway, is_ask)`` for the current context.

    Single-query ``-q`` and cron clear the presence trio: ``hermes chat -q`` exports
    HERMES_INTERACTIVE=1 for sudo prompts, and a gateway sets HERMES_EXEC_ASK=1 at startup and
    passes its environ to every external cron worker (#110932) â€” in neither can a human answer
    the card, so the gate must resolve from ``approvals.<ctx>_mode`` instead of parking on a
    pending approval. Unattended *platforms* keep ``is_ask``: api_server relies on it for the
    ``/v1/runs`` approval bridge (``approval.request`` â†’ ``POST /v1/runs/{id}/approval``).ÚHERMES_EXEC_ASKF)r   r   r
   r   r   r	   )r‰  rt  ru  rv  s       r5   Ú	_presencer™  ¦  sU   € ô 7Ð7HÓIÐÜ,Ó.Ô0LÓ0NˆJ€FÜÐ.Ó/€FÜ(Ô*Ô.GÔ.IØ',Ð,ˆÐ,�˜fØ˜f j°&Ð8Ð8r4   úflagged actionsú5Find an alternative approach that avoids this action.)	r‰  r+  rø   r,  Úcron_deny_messageÚsingle_query_deny_messageÚunattended_deny_messageÚfail_closed_when_no_humanÚno_human_block_messageÚdisplay_targetr+  r,  rœ  r�  rž  Úautoapprove_log_prefixrŸ  r   c                 ó   — t        «       st        j                  «       dk(  r
t        «       S t	        «       }t        || «      r
t        «       S t        |«      \  }}}}|�s|�s|�s|
| |f}|||	dœ}t        «       D ]¦  }|j                  «       dk(  r_||j                     }|s(|j                  dk(  r|j                  d|› d�dd¬	«      }n|s|j                  |||¬	«      }t        || |¬
«      c S |j                  dk(  r"t        j                  dg|¢­Ž  t        «       c S  n/ |r,t        j                  dg|¢­Ž  t        |xs d|› d�| |¬
«      S t        j                  dg|¢­Ž  t        «       S t        t        ||| | g| ddfg|||||¬«      S )uå  Shared human-approval gate for a flagged action (tool call or write): decision core for
    :func:`request_tool_approval` and the file-tool write gates.

    Order: yolo bypass â†’ session-cache short-circuit â†’ interactive/gateway/unattended branch â†’
    prompt â†’ persistence. Input-shape checks (hardline, allowlist, pattern detection) are the
    caller's job. ``fail_closed_when_no_human``: a non-interactive, non-gateway, non-cron
    context without an ask bridge BLOCKS instead of auto-approving, so a plugin-flagged action
    never runs ungated.
    Unattended deny text is ``ctx.block_message(subject, noun, advice)`` unless the caller passes
    an explicit ``*_deny_message`` (the file-tool write gates word their own).
    ré   )r<  r>  rA  rJ  rA  zapproval required (rQ  rš  r›  rN  rR  r<  uZ   %s (pattern: %s): %s â€” single-query auto-approve (approvals.single_query_mode: approve).u›   %s (pattern: %s): %s â€” no interactive user/gateway present; BLOCKED (fail-closed). Set HERMES_INTERACTIVE or HERMES_GATEWAY_SESSION to answer the prompt.zBLOCKED: approval required (z>) but no interactive user or gateway is present to approve it.u^   %s (pattern: %s): %s â€” set HERMES_INTERACTIVE or HERMES_GATEWAY_SESSION to require approval.NF)
rö   r  r„   r  rÄ   r7   r‰  rt  ru  rv  )r©   r   rê   rñ   r   r¹   r™  rG  r*  r   r1  r	  rF   rG   r–  Ú_ACTION_GATE)r„   r  r¡  r‰  r+  rø   r,  rœ  r�  rž  r¢  rŸ  r   r7   rt  ru  rv  Úlog_argsÚdeny_messagesrH  rð   s                        r5   Ú_run_approval_gater§  ·  sì  € ô, „~Ô)×<Ñ<Ó>À%ÒGÜ‹{ÐÜ)Ó+€KÜ�; Ô,Ü‹{Ðä4=Ð>OÓ4PÑ1Ð�v˜z¨6Úš*ªVØ*¨K¸ÐEˆð 6Ð?PØ1ñ
ˆô (Ó)ò 	FˆCØ�x‰x‹z˜VÒ#Ø'¨¯©Ñ1�Ù 3§8¡8¨|Ò#;à!×/Ñ/Ð2EÀkÀ]ÐRSÐ0TÐ[lØ7nð 0ó p‘Gá Ø!×/Ñ/°¸dÈ6Ð/ÓR�GÜ °[ÈkÔZÒZØ�x‰x˜>Ò)ô —‘ð  Ið UØKSóUä “{Ò"Ùð!	Fñ$ )Ü—‘ð  Nð ZàPXóZô  Ð 6ò !MØ2°;°-ð @Lð Là +¸ôFð Fô 	�‰ð Eð 	QØGOó	Qä‹{ÐäÜ˜n¸+ÐS^Ø!�]¨{¸DÀ%Ð.HÐ-IÐWbØ+°FÀzÐZ`ôð r4   Úenv_typeÚhas_host_accessc                 ón   — | dk(  r| S | dv ry	 ddl m} t         || dd«      «      S # t        $ r Y yw xY w)z¸True when the backend is isolated enough to skip dangerous-command prompts. Docker is the
    exception once host paths are bind-mounted: ``rm -rf /workspace`` then reaches host files.Údocker)ÚsingularityÚmodalÚdaytonaÚvercel_sandboxTr   )Úprovider_flagÚskip_container_guardsF)Úagent.terminal_env_registryr°  rw   r�   )r¨  r©  r°  s      r5   Ú_should_skip_container_guardsr³     sP   € ð �8ÒØ"Ð"Ð"ØÐHÑHØðÝ=Ü‘M (Ð,CÀUÓKÓLÐLøÜò Ùðús   �( ¨	4³4c                 óh   — t        | «      }|€yt        j                  d|| dd «       t        |«      S )u  The operator's ``approvals.deny`` rules are documented as never bypassable â€” not by yolo,
    not by mode=off, and not by an isolated container either: they express intent about what the
    agent may DO, not what it can reach, so they are evaluated before the container fast path.Nz%User deny rule %r blocked command: %séÈ   )r   rF   rG   r   )rö   Údeny_patterns     r5   Ú_user_deny_blockr·    s;   € ô )¨Ó1€LØÐØÜ
‡N�NÐ:¸LÈ'ÐRVÐSVÈ-ÔXÜ" <Ó0Ð0r4   ©Ú
sudo_guardr¹  c                óò   — t        | «      \  }}|r&t        j                  d|| dd «       t        || «      S |r5t	        | «      \  }}|r%t        j                  d|| dd «       t        |«      S t        | «      S )a0  Unconditional floors, BEFORE yolo / mode=off / cron approve-mode so no
    session-level setting can bypass them: hardline catastrophic commands,
    password-piping to ``sudo -S`` with no SUDO_PASSWORD configured (full guard
    only), and the user's own approvals.deny rules ("never, even under yolo").z Hardline block: %s (command: %s)Nrµ  z(Sudo stdin guard block: %s (command: %s))r   rF   rG   r   r   r   r·  )rö   r¹  Úis_hardlineÚhardline_descÚis_sudo_guessÚsudo_guess_descs         r5   Ú_floor_blockr¿    s‚   € ô
 "9¸Ó!AÑ€K�ÙÜ�‰Ð9¸=È'ÐRVÐSVÈ-ÔXÜ% m°WÓ=Ð=ÙÜ)@ÀÓ)IÑ&ˆ�ÙÜ�N‰NÐEÀÐX_Ð`dÐadÐXeÔfÜ+¨OÓ<Ð<Ü˜GÓ$Ð$r4   c           
      ó  — t        ||¬«      rt        | «      xs
 t        «       S t        | «      }|�|S t	        «       r
t        «       S t        | «      r
t        «       S t        | «      \  }}}|s
t        «       S t        ||| |d|› d�ddd¬«      S )zéDetect a dangerous command and handle approval (pattern layer only). ``has_host_access``:
    a Docker sandbox that bind-mounts host paths must not skip approval.
    Returns ``{"approved": True/False, "message": str or None, ...}``.©r©  rP  rQ  rL  rM  zFAUTO-APPROVED dangerous command in non-interactive non-gateway context)r„   r  r¡  r‰  r+  rø   r,  r¢  )r³  r·  rñ   r¿  r©   r   r   r§  )rö   r¨  r‰  r©  rõ   rZ  r„   r  s           r5   Úcheck_dangerous_commandrÂ  -  sš   € ô % X¸ÕOÜ Ó(Ò7¬I«KÐ7Ü˜7Ó#€GØÐØˆÜ„~Ü‹{ÐÜ+¨GÔ4Ü‹{ÐÜ-EÀgÓ-NÑ*€L�+˜{ÙÜ‹{ÐÜØ¨[ÈÐduØ0°°¸QÐ?ÐFZØGØgô	ð r4   )Úrule_keyr‰  Ú	tool_namerÃ  c                óä   — |xs d| › �}|s:| › dt        j                  |j                  d«      «      j                  «       dd › �}d| › d|› d�}t	        d	|› �|d
| › d�||dd| › d�dd|› d�¬«	      S )aÌ  Escalate an arbitrary tool call to the human-approval gate.

    Entry point for a plugin ``pre_tool_call`` hook returning ``{"action": "approve", ...}``:
    it asks the SAME human gate as Tier-2 dangerous shell patterns (session/permanent
    allowlist, CLI prompt, gateway pending, once/session/always/deny, timeout fail-closed), so
    the LLM cannot skip it. Cron honors ``approvals.cron_mode``; any OTHER non-interactive
    context without an approval bridge fails CLOSED. ``rule_key`` controls the ``[a]lways``
    allowlist grain; when empty it is ``tool_name`` + a hash of ``reason`` so DISTINCT reasons
    on the same tool persist independently. Returns the ``check_dangerous_command`` result shape.
    zPlugin requires approval for ú:zutf-8Né   zTool 'z' requires approval (rQ  zplugin_rule:Ú<z> (plugin approval rule)zFind an alternative approach.zplugin-escalated tool call 'z(' in non-interactive non-gateway contextTr.  zr but no interactive user or gateway is present to approve it. A plugin flagged this action for human confirmation.)	r„   r  r¡  r‰  r+  r,  r¢  rŸ  r   )ÚhashlibÚsha256ÚencodeÚ	hexdigestr§  )rÄ  rX   rÃ  r‰  r  r+  s         r5   Úrequest_tool_approvalrÍ  G  s¹   € ð ÒGÐ;¸I¸;ÐG€KÙØ�[ ¤'§.¡.°×1CÑ1CÀGÓ1LÓ"M×"WÑ"WÓ"YÐZ]Ð[]Ð"^Ð!_Ð`ˆØ�y�kÐ!6°{°mÀ1ÐE€GÜð # 8 *Ð-¸;Ø˜9˜+Ð%=Ð>ÐRcØÐ ?Ø!=¸i¸[ÐHpÐqØ"&Ø"+¨G¨9ð 5fð !fô
ð 
r4   Útirith_resultc                 óX  — g }| j                  d«      xs g D ]a  }|j                  dd«      |j                  dd«      |j                  dd«      }}}|sŒ<|r|› d|› �n|}|j                  |rd|› d|› �n|«       Œc |s| j                  d	«      xs d
}d|› �S ddj                  |«      z   S )zEHuman-readable severity/title/description summary of tirith findings.ÚfindingsÚseverityr!   Útitler  z: ú[z] Úsummaryzsecurity issue detectedzSecurity scan: u   Security scan â€” ú; )r0   rC  Újoin)rÎ  ÚpartsÚfrÑ  rÒ  ÚdescÚtextrÔ  s           r5   rY  rY  e  sÈ   € à€EØ×Ñ˜zÓ*Ò0¨bò GˆØ !§¡ j°"Ó 5°q·u±u¸WÀbÓ7IÈ1Ï5É5ÐQ^Ð`bÓKc˜�%ˆÚÙ)-�e�W˜B˜t˜fÑ%°5ˆDØ�L‰L±8˜1˜X˜J b¨¨Ñ/ÀÕFð	Gñ
 Ø×#Ñ# IÓ.ÒKÐ2KˆØ   	Ð*Ð*Ø $§)¡)¨EÓ"2Ñ2Ð2r4   c                 óz   — 	 ddl m}  || «      S # t        $ r! t        «       rdg ddœcY S dddd	d
ddœgdœcY S w xY w)zÅTirith result for the interactive flow; an un-importable scanner allows
    (default) or, under fail-closed, synthesizes a HIGH warn finding that goes
    through the normal approval flow (#20733).r   rS  Úallowr!   )rU  rÐ  rÔ  rV  z Tirith unavailable (fail-closed)ztirith-import-errorÚHIGHz"Tirith security module unavailablez¾The Tirith security scanner could not be imported. Because security.tirith_fail_open is false, this command cannot be silently allowed. Approve only if you have verified the command is safe.)Úrule_idrÑ  rÒ  r  )rU  rÔ  rÐ  )rW  rT  rX  r   )rö   rT  s     r5   Ú_tirith_scanrß  s  sa   € ðÝ@Ù% gÓ.Ð.øÜò 
ÜÔØ%°2À"ÑEÒEØ Ð-OØ,¸&Ø9ðEñ_
ð ^ñ ò 	ð
ús   ‚ �:«:¹:c                 óÜ  — t        ||¬«      rt        | «      xs
 t        «       S t        | d¬«      }|�|S ddlm}  || ||«      }|�|S t        j                  «       }t        «       s|dk(  r
t        «       S t        | «      r
t        «       S t        |«      \  }}}	}
|s/|	s-|
s+t        «       D ]  }t        | |«      }|€Œ|c S  t        «       S t        | «      }t        | «      \  }}}g }t        «       }|d   dv r\|j!                  d	«      xs g }|r|d   j!                  d
d«      nd}d|› �}t#        ||«      s|j%                  |t'        |«      df«       |r t#        ||«      s|j%                  ||df«       |s
t        «       S dj)                  d„ |D «       «      }|d   d   }|D ��cg c]  \  }}}|‘Œ
 }}}t+        t,        | ||||||||	|
|dk(  t/        d„ |D «       «      ¬«      S c c}}w )ae  Run all pre-exec security checks and return a single approval decision. Tirith and
    dangerous-command findings are presented as ONE combined approval request, so a gateway
    force=True replay cannot bypass one check when only the other was shown to the user.
    ``has_host_access``: a Docker sandbox with bind-mounted host paths takes the normal flow.rÁ  Tr¸  r   )Úconsume_prepared_guardré   rU  >   rV  rO  rÐ  rÞ  Úunknownztirith:FrÕ  c              3   ó(   K  — | ]
  \  }}}|–— Œ y ­wr{   r3   )re   rÊ   rÙ  s      r5   rg   z+check_all_command_guards.<locals>.<genexpr>»  s   è ø€ Ò>¡z q¨$°œdÑ>ùs   ‚rq  c              3   ó*   K  — | ]  \  }}}| –— Œ y ­wr{   r3   )re   rÊ   Úis_ts      r5   rg   z+check_all_command_guards.<locals>.<genexpr>Ç  s   è ø€ ÒB©:¨1¨a° $œhÑBùs   ‚)rö   r  r„   r  rÄ   r7   r‰  rt  ru  rv  rq  rr  )r³  r·  rñ   r¿  Úagent.terminal_approval_batchrá  r   rê   r©   r   r™  rG  r\  rß  r   r   r0   r¹   rC  rY  rÖ  r–  Ú_COMMAND_GATEr·   )rö   r¨  r‰  r©  rõ   rá  ÚpreparedÚapproval_modert  ru  rv  rH  r^   rÎ  rZ  r„   r  rÄ   r7   rÐ  rÞ  Ú
tirith_keyÚcombined_descÚprimary_keyrÉ   rÊ   Úall_keyss                              r5   Úcheck_all_command_guardsrî  ‡  s  € ô % X¸ÕOÜ Ó(Ò7¬I«KÐ7ä˜7¨tÔ4€GØÐØˆåDÙ% g¨x¸ÓI€HØÐØˆä$×7Ñ7Ó9€MÜ„~˜¨%Ò/Ü‹{ÐÜ+¨GÔ4Ü‹{Ðä4=Ð>OÓ4PÑ1Ð�v˜z¨6ñ ™*©VÜ'Ó)ò 	ˆCÜ% g¨sÓ3ˆFØÑ!Ø’ð	ô ‹{Ðô ! Ó)€MÜ-EÀgÓ-NÑ*€L�+˜{Ø€HÜ)Ó+€KØ�XÑÐ"3Ñ3Ø ×$Ñ$ ZÓ0Ò6°BˆÙ;C�(˜1‘+—/‘/ )¨YÔ7ÈˆØ˜w˜iÐ(ˆ
Ü˜;¨
Ô3Ø�O‰O˜ZÔ)CÀMÓ)RÐTXÐYÔZÙœK¨°[ÔAØ�‰˜ k°5Ð9Ô:ÙÜ‹{Ðà—I‘IÑ>°XÔ>Ó>€MØ˜1‘+˜a‘.€KØ%-×.™	˜˜Q ’Ð.€HÑ.ô
 Ü˜w°MØ¨hÀØÐ3DØ *°VÀ=ÐT[ÑC[ÜÑB¸ÔBÓBôð ùó /s   Æ)G(z¦execute_code script execution. The script can spawn subprocesses or mutate files without passing through terminal command approval; approval is one-shot for this run.c                 ó6  ‡ ‡— d}t         }|dk(  r
t        «       S t        ||¬«      r
t        «       S t        j                  «       }t        «       s|dk(  r
t        «       S t        «       \  }}}}	t        «       D ]?  }
|
j                  «       dk(  rt        d|
j                  z   ||dd¬	«      c S t        «       c S  |s|	s
t        «       S t        «       }d
‰ › d�}t        ||«      r
t        «       S ddlmŠ t        t         ||||g|ddfg|||||	|dk(  ˆ ˆfd„¬«      S )ad  Approve an execute_code script before its child process is spawned.

    The script can call ``subprocess``/``os.system``/``ctypes`` directly, none of which pass
    through ``terminal()`` / ``DANGEROUS_PATTERNS``; in gateway/ask contexts we fail closed by
    approving the script as a whole. Same dict contract as ``check_all_command_guards``.
    Documented limitation: a purely local non-interactive non-gateway session returns approved
    (the terminal auto-approve contract); the hardline floor still blocks catastrophic
    ``terminal()`` commands the script issues.

    See #30882.
    The hardline floor still blocks catastrophic ``terminal()`` commands the script issues; running
    arbitrary code headlessly without any approval surface is trusted-by-config (set a gateway/ask surface
    or ``approvals.cron_mode`` to require approval). See #30882.
    Úexecute_coder¯  rÁ  ré   rJ  zyBLOCKED: execute_code runs arbitrary local Python (including subprocess calls that bypass shell-string approval checks). rõ   rg  r~  zexecute_code <<'PY'
z
PYr   rx  NFrq  c                  ó   •— d ‰‰ «      › d�S )Nz**Code:**
```python
r  r3   )rg  ry  s   €€r5   ú<lambda>z*check_execute_code_guard.<locals>.<lambda>  s   ø€ Ð5Ñ6KÈDÓ6QÐ5RÐRWÐX€ r4   )rö   r  r„   r  rÄ   r7   r‰  rt  ru  rv  rq  rs  )Ú_EXECUTE_CODE_DESCRIPTIONrñ   r³  r   rê   r©   r™  rG  r*  r  r5  r   r¹   r�  ry  r–  Ú_EXECUTE_CODE_GATE)rg  r¨  r©  r„   r  ré  r‰  rt  ru  rv  rH  r7   rö   ry  s   `            @r5   Úcheck_execute_code_guardrõ  Ñ  s?  ù€ ð !€KÜ+€Kð Ð#Ò#Ü‹{ÐÜ$ X¸ÕOÜ‹{ÐÜ$×7Ñ7Ó9€MÜ„~˜¨%Ò/Ü‹{Ðô 5>³KÑ1Ð�v˜z¨6ô $Ó%ò ˆØ�8‰8‹:˜ÒÜðOØQT×Q^ÑQ^ñ_à'°[È)ÐZ`ôò ô
 ‹{Òðñ ™fÜ‹{Ðä)Ó+€Kà% d V¨4Ð0€Gô �; Ô,Ü‹{Ðõ
 3ÜÜ G¸ÐR]Ø!�]¨{¸DÀ%Ð.HÐ-IÐWbØ+°FÀzÐZ`Ø˜wÑ&ÜXôð r4   ÚDANGEROUS_PATTERNS)útools.approval_detectionrö  ÚDANGEROUS_PATTERNS_COMPILED)r÷  rø  ÚHARDLINE_PATTERNS)r÷  rù  ÚHARDLINE_PATTERNS_COMPILED)r÷  rú  ÚHUMAN_WAIT_MARGIN_S)útools.approval_human_waitrû  Úcfg_get)zhermes_cli.configrý  Úget_plugin_manager)útools.approval_promptrþ  Úhuman_wait_ceiling)rü  r   Úhuman_wait_seconds)rü  r  Úhuman_wait_window)rü  r  Úis_interrupted)ztools.interruptr  Úrequest_elicitation_consent)rÿ  r  Ú#reset_current_observability_context)útools.approval_contextr  Úreset_current_session_key)r  r  Ú reset_hermes_interactive_context)r  r  Ú!set_current_observability_context)r  r	  Úset_current_session_key)r  r
  Úset_hermes_interactive_context)r  r  c                 óÎ   — t         j                  | «      }|€t        dt        ›d| ›�«      ‚dd l}ddlm}  |t        | g|¢­Ž  t         |j                  |d   «      |d   «      S )Nzmodule z has no attribute r   )Ú	warn_oncer9   )	Ú_PLUGIN_COMPAT_LAZYr0   ÚAttributeErrorr6  r�   Úhermes_cli.plugin_compatr  rœ   rž   )r   Útargetr�   r  s       r5   Ú__getattr__r  B  sh   € Ü ×$Ñ$ TÓ*€FØ€~Ü˜w¤x lÐ2DÀTÀHÐMÓNÐNÛÝ2ÙŒh˜Ð&˜vÓ&ÜÐ*�9×*Ñ*¨6°!©9Ó5°v¸a±yÓAÐAr4   )FNN)rö   r{   )Frn  )™r9  Údataclassesr   rÉ  r�   ÚloggingÚosÚ	threadingÚtypingr   Úutilsr   r   Útoolsr   rý   r   r	   r
   r   r   r   r   r   r   r   Útools.approval_detectionr   r   r   r   Útools.approval_floorsr   r   r   r   r   Útools.approval_gateway_waitr   Útools.approval_promptr   r   r   Útools.approval_smartr   Ú	getLoggerr6  rF   Úgetenvr"   rw   r:  ÚLockr:   r#   rm   rÓ   r$   rR   r%   r&   r'   r(   r.   r=   r6   rA   rD   rI   rJ   r\   rK   ÚobjectrN   rU   ra   rj   rn   rq   ru   rx   r~   r€   rƒ   rˆ   r�   r“   r–   r˜   r¡   r£   r§   r©   r³   r¹   r¼   r¾   rÃ   ÚtuplerÍ   r°   rÜ   rÞ   rà   rÈ   rë   rí   rñ   rþ   r  r  r	  r  r  r  r  rD  rE  rG  r\  r^  Ú_STOP_COMMANDÚ_STOP_ACTIONrç  rô  r¤  rp  r–  r™  r§  r³  r·  r¿  rÂ  rÍ  rY  rß  rî  ró  rõ  Ú
contextlibÚcontextvarsÚfnmatchÚ	functoolsÚreÚshlexÚsysÚtempfileÚtimeÚunicodedataÚuuidr  r  r3   r4   r5   ú<module>r1     sé
  ðòõ "Û Û Û Û 	Û Ý ç 2Ý "÷÷ ÷ ÷ó ÷õ õ @ß pÑ pÝ /à	ˆ×	Ñ	˜8Ó	$€ñ *¨)¨"¯)©)Ð4FÈÓ*KÓLÐ �4Ó Lð
 	ˆ	�‰Ó€Ø€ˆ$ˆs�Dˆy‰/Ó Ø$&Ð �4˜˜S˜‘>Ó &Ù›%€ˆs�3‰xÓ Ù›5Ð �SÓ  à.0Ð ˜T # s (™^Ó 0ð !#€ˆt�C˜�H‰~Ó "Ø Ð ð só ð ð ¨ó ð- ð -¨ó -ð¨#ð °#ó ð2 $&€��c˜4�i‘Ó %Ø)+Ð �T˜#˜v˜+Ñ&Ó +ð.¨ð .°Tó .ð¨3ð °4ó ð 27Ø59Ø9=ñ"¨#ð "°sð "Ø*.ð"à%-¨c¡]ð"ð *2°#©ð"ð CFó"ðJ¨3ð ¸Cð Èð ÐPTó ð"T¨ð T°°T±
ó Tð¨ð ¸#ð È$ó ð cð °sð ¸tó ð6 sð 6¨tó 6ðE¨ó Eð	#¨cð 	#°d¸T±kó 	#ð) ð )¨tó )ðJ ð J°3ó Jð	q°Sð 	q¸Tó 	qð5 3ð 5°ð 5¸$ó 5ð) Sð )¨Tó )ð
* cð *¨dó *ð
˜sð  tó ð0,¨ð ,°ó ,ðH¨ó Hð
B�dó Bð˜ó ð,7˜Sð 7¨sð 7°tó 7ðC¨#ð C°$ó Cð* 3ó *ð#˜Só #ð/ ð /¨cð /¸TÀ%¹[ð /ÈTó /ð" 3ó ð: /1Ð ˜T # s (™^Ó 0ðK�só Kð
 #ó ð: só :ðHy°sð y¸tó yðV 4ó Vð/�4ó /ð ;ØGØ^ØeØXñ€ñf˜3ð f cð f¸#ó fð \eò C�Sð C¨#ð C¸Cð CÈ#ð CÐUXð CØóCðk�cð k¨3ð k¸Sð kÀTó kð
b ð b°#ð b¸$ó bð4 Có 4ð
! sð !¸ð !È#ð !Ø!$ð!Ø48¸±Ið!ØEHÈ4ÁZð!à"&ð!à+/ó!ñL �$Ô÷\ð \ó ð\ñ,  ØÐ'ØFØÐLóÐ ñ
 Ø
ˆKÐMØÐ@ó€	ð˜d ;Ñ/ó ð&"˜cð "¨ð "¸¸t¹ó "ñV �$Ô÷ð ó ðð$=ð ðMð ñ
 Ø	˜d°$À5ÐW[ØSØAÀMÑQØ3ñ4ð	Cð DÀmÑSØ5ñ6à3°mÑCÀkÑQØIô€ñ Ø	˜4¨tÀÐSWØ`ð	gð
 	qàBÀ\ÑQØ5ñ6ð	[ð Uô#Ð ñ* Ø	˜U°%ÀEÐX]ØSØ@À<ÑOØ*ñ+àØBÀ\ÑQØ,ñ-ð	Rð ô€ð �ið ¨#ð ¸Cð Ècð Ø" 3™iðØ69ðà#ðà(-¨d°T©k¸4Ð.?Ñ(@óðF 16Ø.2Àò	J˜)ð J°ð JÀ3ð JØ!$ðJØ48¸±IðJØIMÈeÉðJà!$ðJàAEðJàSWðJð !ðJð *.ðJð (,ð	Jð KOó	JñZ9¨ó 9ð$ SWØÐ#4ØIØÀ"ÐegØCHÐhjòFØðFØ&)ðFØ;>ðFàðFà ðFð ðFð ð	Fð =@ð	Fð `cð	Fð
  ðFð
 =AðFð
 cfðFð 
óFñR¨Cð À$ð ÐSWó ð"1˜cð 1 d¨T¡kó 1ð 6;ò %˜#ð %¨dð %¸tÀd¹{ó %ð$ /3Ø49ñ Sð °Cð à-1ðà>Bóð4 KMÐ`dò  Sð °#ð ÀCð Ðimó ð<3¨dð 3°só 3ð˜#ð  $ó ð* 04Ø5:ñA cð A°Sð Aà.2ðAà?CóAðJið ñC 3ð C°#ð CÈð CÐY]ó CñN Ô ó Û Û Û Û 	Û Û 
Û Û Û Û ðØÐLðà!Ð#^ðð ÐJðð !Ð"\ð	ð
 ÐOðð Ð/ðð ÐIðð ÐMðð ÐMðð ÐKðð Ð;ðð "Ð#[ðð *Ð+lðð  Ð!Xðð 'Ð(fðð  (Ð)hð!ð" ÐTð#ð$ %Ð&bñ%Ð ó,Br4   