+
    iHàj_5  ã                   ób  a € R' t 0 t R t^ RIt^ RIt^ RIHt ^ RIHtHtH	t	 ^ RI
Ht ^ RIHtHtHt ^ RIHtHt RtR(R R	 lltR
RRRRRRRRRRRRRRRRR/	t] ^ k ];QJ d    . R R) 4       F  NK  	  5M! R R) 4       4      t]! 0 R*m4      tR R ltR R  ltR! R" ltR# R$ lt ! R% R&4      tR# )+a  File-mutation verification footers and turn-completion explanations for ``AIAgent``.

The footer tells the model (and user) when a claimed file mutation did not land; the explainer
summarises why a turn ended without a final answer. Every method resolves through ``AIAgent``'s MRO.
N)Úsuppress)ÚAnyÚDictÚOptional©Út)Ú_extract_error_previewÚ_extract_file_mutation_targetsÚ#_extract_landed_file_mutation_paths)ÚFILE_MUTATING_TOOL_NAMESÚfile_mutation_result_landedzy{model} didn't produce a reply this time, even after retries. Send `continue` to try again, or switch models with /model.c                ó0   € V ^8„  d   QhR\         R\         /# )é   ÚmodelÚreturn©Ústr)Úformats   "Ú:/home/ubuntu/.hermes/hermes-agent/agent/turn_explainers.pyÚ__annotate__r      s   € ÷ Yñ Y¤cð Y´3ñ Yó    c                óB   € \        RT ;'       g    \        R4      R7      # )zXLocalized ``EMPTY_RESPONSE_EXPLANATION`` with the model name (or "The model") filled in.úexplainer.empty_responseúexplainer.shared.the_model©r   r   r   s   &r   Úempty_response_explanationr      s   € äÐ'¨u×/WÐ/W¼Ð:VÓ8WÔXÐXr   Úempty_response_exhaustedr   Ú!all_retries_exhausted_no_responsez0explainer.exit.all_retries_exhausted_no_responseÚpartial_stream_recoveryz&explainer.exit.partial_stream_recoveryÚfallback_prior_turn_contentz*explainer.exit.fallback_prior_turn_contentÚredirect_restart_limit_exceededz.explainer.exit.redirect_restart_limit_exceededÚrebuilt_restart_limit_exceededz-explainer.exit.rebuilt_restart_limit_exceededÚbudget_exhaustedzexplainer.exit.budget_exhaustedÚ ollama_runtime_context_too_smallz/explainer.exit.ollama_runtime_context_too_smallÚpending_tool_resultz"explainer.exit.pending_tool_resultc              #   ó.   "  € T F  qR V 23x € K  	  R# 5i)zexplainer.exit.N© )Ú.0Úprefixs   & r   Ú	<genexpr>r)   0   s$   é € ð )ñ 8g¨Vˆ˜v˜hÐ'Õ(ó  8gùs   ‚c                óF   € V ^8„  d   QhR\         \        ,          R\        /# )r   Úcauser   )r   r   )r   s   "r   r   r   8   s"   € ÷ qñ q¬´­ð q¼#ñ qr   c                 ó&   € V \         9   d   R V  2# R# )zexplainer.persistence.zexplainer.persistence.default)Ú_PERSISTENCE_CAUSES)r+   s   &r   Ú_persistence_explanation_keyr.   8   s   € Ø/4Ô8KÔ/KÐ# E 7Ð+ÐpÐQpÐpr   c                óR   € V ^8„  d   QhR\         R\        \         ,          R\         /# )r   ÚpathÚtask_idr   ©r   r   )r   s   "r   r   r   <   s%   € ÷ 
8ñ 
8¤#ð 
8´¼µð 
8Ä#ñ 
8r   c                óX  €  ^ RI Hp \        T! Y;'       g    R4      4      p\        P
                  P                  \        P
                  P                  V4      4      #   \         d@    \        P
                  P                  \        P
                  P                  T 4      4      p L…i ; i)zÿOne key per on-disk target: the file tools' task-resolved absolute path, case-folded
on case-insensitive hosts. A failure recorded as ``notes.md`` and the write that later
lands as ``/repo/notes.md`` (or ``Notes.md`` on Windows) must meet on the same key.)Ú_resolve_path_for_taskÚdefault)
Útools.file_tools_pathsr4   r   Ú	ExceptionÚosr0   ÚabspathÚ
expanduserÚnormcaseÚnormpath)r0   r1   r4   Úresolveds   &&  r   Ú_file_mutation_identityr>   <   sz   € ð=ÝAäÑ-¨d×4HÐ4H¸yÓIÓJˆô �7‰7×ÑœBŸG™G×,Ñ,¨XÓ6Ó7Ð7øô ô =Ü—7‘7—?‘?¤2§7¡7×#5Ñ#5°dÓ#;Ó<Šð=ús   ‚A ˜A ÁAB)Â(B)c                óF   € V ^8„  d   QhR\         R\        \        ,          /# )r   Úidentityr   )r   r   Útuple)r   s   "r   r   r   I   s   € ÷ (ñ (¤3ð (¬8´E­?ñ (r   c                ó„   €  \         P                  ! V 4      pTP                  TP                  3#   \         d     R# i ; i)zX``(mtime_ns, size)`` of the target, ``None`` when it does not exist (or cannot be read).N)r8   ÚstatÚOSErrorÚst_mtime_nsÚst_size)r@   Ústs   & r   Ú_file_stat_signaturerH   I   s>   € ðÜ�WŠW�XÓˆð �N‰N˜BŸJ™JÐ'Ð'øô ô Úðús   ‚0 °?¾?c                óH   € V ^8„  d   QhR\         R\         R\         R\        /# )r   Úenv_varÚ
config_keyÚ
cache_attrr   )r   Úbool)r   s   "r   r   r   R   s)   € ÷ ñ ¬Sð ¼cð Ìsð ÔW[ñ r   c               ó
  €  \         P                  P                  V4      pVe"   VP                  4       P	                  4       R9  # \        WR4      pVe   V#  ^ RIHp V! 4       ;'       g    / p\        V\        4      '       d   VP                  R4      MRp\        V\        4      '       d"   W(9   d   \        VP                  V4      4      p	MRp	\        WV	4       V	#   \         d    / p Li ; i  \         d     R# i ; i)uV  ``display.<config_key>`` (default True), cached per agent on ``cache_attr``.

``env_var`` overrides on every call and is never cached. Reads the persisted config.yaml
so gateway and CLI share the setting; ``load_config`` is imported lazily (startup cycle,
and tests patch it at ``hermes_cli.config``). Any failure â†’ True (safe default: on).N)Úload_configÚdisplayT>   Ú0ÚnoÚoffÚfalse)r8   ÚenvironÚgetÚstripÚlowerÚgetattrÚhermes_cli.configrO   r7   Ú
isinstanceÚdictrM   Úsetattr)
ÚagentrJ   rK   rL   ÚenvÚcachedÚ_load_configÚ_cfgÚ_displayÚenableds
   &$$$      r   Ú_display_flag_enabledre   R   sç   € ðÜ�j‰j�n‰n˜WÓ%ˆØŠ?Ø—9‘9“;×$Ñ$Ó&Ð.IÑIÐIÜ˜¨DÓ1ˆØÒØˆMð	ÝEÙ“>×'Ð' RˆDô +5°T¼4×*@Ò*@�4—8‘8˜IÔ&ÀdˆÜ�h¤×%Ò%¨*Ô*@Ü˜8Ÿ<™<¨
Ó3Ó4‰GàˆGÜ� 7Ô+Øˆøô ô 	ØŠDð	ûô ô ÚðúsC   ‚AC3 ÁC3 ÁC  Á-C  Á0A/C3 Ã C0Ã-C3 Ã/C0Ã0C3 Ã3DÄDc                   óú   a € ] tR t^ot o RtRR/V 3R lR llt]V 3R lR l4       tV 3R lR	 ltV 3R
 lR lt	]
P                  ! R4      t]V 3R lR l4       t]V 3R lR l4       t]RV 3R lR ll4       tRtV tR# )ÚTurnExplainersMixinzPFile-mutation failure footer + turn-completion explainer (see module docstring).r1   Nc                ób   <€ V ^8„  d   QhRS[ RS[S[ S[3,          RS[RS[RS[S[ ,          RR/# )r   Ú	tool_nameÚargsÚresultÚis_errorr1   r   N)r   r\   r   rM   r   )r   Ú__classdict__s   "€r   r   Ú TurnExplainersMixin.__annotate__r   sK   ø€ ÷ 2*ñ 2*Ùð2*Ù$(©©c¨¥Nð2*Ù<?ð2*ÙKOð2*á™S•Mð2*ð 
ñ2*r   c               ó¶  € V\         9  d   R# \        V RR4      pVf   R# \        W4      pV'       g   R# \        W4      pV'       d§   \	        WV4      p	\        V RR4      p
V
e   V
P                  V	4       \        V RR4      pVeh   \        VRR4      '       dU   ^ RIHp T! T;'       g    R4      f;   V	 F4  p\        \        4      ;_uu_ 4        VP                  V4       RRR4       K6  	  V'       dM   V'       gE   \        V4      pV F1  p\        Wõ4      pVP                  VR	VR
VRVR\        V4      /4       K3  	  R# V'       d   X	MT Uu0 uF  p\        VV4      kK  	  pp\        VP!                  4       4       F:  w  ppVP#                  R\        Wõ4      4      V9   g   K(  VP%                  VR4       K<  	  R#   + '       g   i     EK  ; iu upi )a­  Record a ``write_file`` / ``patch`` outcome for the turn-end verifier.

Failures store ``{path: {error_preview, tool, identity, stat}}`` keyed by the model's
spelling; ``identity`` is the resolved on-disk target and ``stat`` its signature at
failure time. A later success on the same identity (any spelling) removes the entry.
No-op when the per-turn state dict is not initialised (tool dispatched outside ``run_conversation``).
NÚ_turn_failed_file_mutationsÚ_turn_file_mutation_pathsÚ_checkpoint_mgrrd   F)Úcontainer_backend_for_taskr5   ÚtoolÚerror_previewr@   rC   )Ú_FILE_MUTATING_TOOLSrY   r	   r   r
   Úupdater6   rs   r   r7   Úrecord_agent_writer   r>   Ú
setdefaultrH   ÚlistÚitemsrV   Úpop)Úselfri   rj   rk   rl   r1   ÚstateÚtargetsÚlandedÚlanded_pathsÚchangedÚmgrrs   Ú_pÚpreviewr0   r@   ÚpÚclearedÚinfos   &&&&&$              r   Ú_record_file_mutation_resultÚ0TurnExplainersMixin._record_file_mutation_resultr   s¬  € ð Ô0Ô0ÙÜ˜Ð;¸TÓBˆØŠ=ÙÜ0°ÓAˆßÙÜ,¨YÓ?ˆßÜ>¸yÐPVÓWˆLÜ˜dÐ$?ÀÓFˆGØÒ"Ø—‘˜|Ô,ô ˜$Ð 1°4Ó8ˆCØŠ¤7¨3°	¸5×#AÒ#AÝMÙ-¨g×.BÐ.B¸ÓCÒKÛ*˜Ü%¤i×0Õ0Ø×2Ñ2°2Ô6÷ 1Ñ0ñ +÷ ŸFä,¨VÓ4ˆGÛ�Ü2°4ÓA�Ø× Ñ  Ø˜I ¸Ø ¨&Ô2FÀxÓ2Pð(ö ó  ÷ +1™,°gÐ=óá=�Aô (¨¨7Ö3Ù=ð ð ô # 5§;¡;£=Ö1‘
��dØ—8‘8˜JÔ(?ÀÓ(NÓOÐSZÖZØ—I‘I˜d DÖ)ó 2÷! 1×0Ñ0üòs   ÃGÅGÇGc                ó~   <€ V ^8„  d   QhRS[ S[S[ S[S[3,          3,          RS[ S[S[ S[S[3,          3,          /# ©r   Úfailedr   ©r\   r   r   )r   rm   s   "€r   r   rn   §   sE   ø€ ÷ 
ñ 
©T±#±t¹CÁ¸Hµ~Ð2EÕ-Fð 
É4ÑPSÑUYÑZ]Ñ_bÐZbÕUcÐPcÕKdñ 
r   c                ó¤   € V P                  4        UUu/ uF.  w  rRV9  g!   \        VR,          4      VR,          8X  g   K,  WbK0  	  upp# u uppi )ag  Drop entries whose target changed on disk since the failed call.

The recorder only sees write_file/patch receipts; a terminal redirect or an
execute_code write leaves none. Re-checking the stat signature at turn end keeps
the footer from listing a file that was in fact modified later this turn. Entries
without a snapshot (hand-built dicts) are kept as-is.
rC   r@   )r{   rH   )r�   r0   rˆ   s   &  r   Ú_file_mutations_still_failedÚ0TurnExplainersMixin._file_mutations_still_failed¦   sS   € ð *0¯©¬ô
Ù)7™:˜4Ø˜TÔ!Ô%9¸$¸zÕ:JÓ%KÈtÐTZÍ|Ñ%[ô ˆDŠJ©ò
ð 	
ùó 
s   ”)AÁAc                ó    <€ V ^8„  d   QhRS[ /# ©r   r   ©rM   )r   rm   s   "€r   r   rn   ´   s   ø€ ÷ 
ñ 
±ñ 
r   c                ó    € \        V RRRR7      # )zZ``display.file_mutation_verifier`` / ``HERMES_FILE_MUTATION_VERIFIER`` (a patchable seam).ÚHERMES_FILE_MUTATION_VERIFIERÚfile_mutation_verifierÚ%_file_mutation_verifier_enabled_cache©rJ   rK   rL   ©re   ©r}   s   &r   Ú_file_mutation_verifier_enabledÚ3TurnExplainersMixin._file_mutation_verifier_enabled´   s   € ä$ØÐ9ÐF^Ø>ô
ð 	
r   c                ó    <€ V ^8„  d   QhRS[ /# r“   r”   )r   rm   s   "€r   r   rn   »   s   ø€ ÷ 
ñ 
±Dñ 
r   c                ó    € \        V RRRR7      # )zM``display.turn_completion_explainer`` / ``HERMES_TURN_COMPLETION_EXPLAINER``.Ú HERMES_TURN_COMPLETION_EXPLAINERÚturn_completion_explainerÚ(_turn_completion_explainer_enabled_cacher™   rš   r›   s   &r   Ú"_turn_completion_explainer_enabledÚ6TurnExplainersMixin._turn_completion_explainer_enabled»   s   € ä$ØÐ<ÐIdØAô
ð 	
r   zE(?<![/:\w.`])(?:~/|/|[A-Za-z]:[/\\])(?:[\w.\-]+[/\\])*[\w.\-]+\.[\w]+c                ó&   <€ V ^8„  d   QhRS[ RS[ /# )r   Útextr   r   )r   rm   s   "€r   r   rn   É   s   ø€ ÷ Jñ J©Cð J±Cñ Jr   c                óP   € V'       g   V# V P                   P                  R V4      # )z¾Backtick bare file paths so the gateway's ``extract_local_files`` never auto-attaches them.

The extractor skips inline-code spans; already-backticked paths are left alone (no double-wrap).
c                 ó,   € R V P                  ^ 4       R 2# )Ú`)Úgroup)Úms   &r   Ú<lambda>Ú>TurnExplainersMixin._neutralize_footer_paths.<locals>.<lambda>Ð   s   € °1°Q·W±W¸Q³Z°LÀÑ1Br   )Ú_FOOTER_PATH_REÚsub)Úclsr¦   s   &&r   Ú_neutralize_footer_pathsÚ,TurnExplainersMixin._neutralize_footer_pathsÈ   s&   € ÷ ØˆKØ×"Ñ"×&Ñ&Ñ'BÀDÓIÐIr   c                óR   <€ V ^8„  d   QhRS[ S[S[ S[S[3,          3,          RS[/# rŒ   rŽ   )r   rm   s   "€r   r   rn   Ó   s.   ø€ ÷ >ñ >¹$¹sÁDÉÉcÈÅNÐ?RÕ:Sð >ÑX[ñ >r   c                ó>  € V'       g   R# \        R\        V4      R7      .p\        VP                  4       4      R,          pV Fy  w  rEVP	                  R4      ;'       g    RP                  4       pVP	                  R4      ;'       g    RpTP                  \        RYGT;'       g    \        R	4      R
7      4       K{  	  \        V4      \        V4      ,
          pV^ 8”  d   VP                  \        RVR7      4       V P                  RP                  V4      4      # )a  Render the per-turn failed-mutation dict as a user-facing footer.

Up to 10 paths with their first error preview, then an overflow count; "" when nothing failed.
Every path is backtick-wrapped via ``_neutralize_footer_paths`` so protected files cannot be
auto-delivered.
Ú zexplainer.file_mutation.header)Úcount:Né
   Nru   rt   Úpatchzexplainer.file_mutation.entryzexplainer.file_mutation.failed)r0   rt   r…   zexplainer.shared.and_moreÚ
)	r   Úlenrz   r{   rV   rW   Úappendr±   Újoin)	r°   r�   ÚlinesÚshownr0   rˆ   r…   rt   Ú	remainings	   &&       r   Ú$_format_file_mutation_failure_footerÚ8TurnExplainersMixin._format_file_mutation_failure_footerÒ   sè   € ÷ ÙÜÐ3¼3¸v»;ÔGÐHˆÜ�V—\‘\“^Ó$ SÕ)ˆÛ‰JˆDØ—x‘x Ó0×6Ð6°B×=Ñ=Ó?ˆGØ—8‘8˜FÓ#×.Ð. wˆDØ�L‰LœÐ:ÀØ#*×#QÐ#Q¬aÐ0PÓ.QôSö Tñ  ô
 ˜“K¤# e£*Õ,ˆ	Ø�qŒ=Ø�L‰LœÐ6¸iÔHÔIà×+Ñ+¨D¯I©I°eÓ,<Ó=Ð=r   c                óB   <€ V ^8„  d   QhRS[ RS[S[ ,          RS[ RS[ /# )r   Úturn_exit_reasonÚpersistence_causer   r   r2   )r   rm   s   "€r   r   rn   ê   s7   ø€ ÷ )Eñ )EÙð)EÙ2:¹3µ-ð)EÙ]`ð)Eá	ñ)Er   c           
     ó~  € V '       g   R# \        V 4      pVP                  R4      '       d   R# \        P                  V4      pVf+   \         F   w  rgVP                  V4      '       g   K  Tp M	  Ve!   \        YS;'       g    \        R4      R7      pM�VR8X  d…   ^ RIHp	Hp
 ^ RI	H
p R	V	! 4       R
V
! 4       RVRRRR/pVR9   dD   ^ RIHp ^ RIHp \        T;'       g    V! 4       4      VR&   \        V! 4       R,          4      VR&   \        \        V4      3/ VB pMRpV'       d   \        R4      V,           # R# )züUser-facing explanation for an abnormal turn ending, or "" for normal / unknown reasons.

``text_response(...)`` is the healthy terminal; unknown/diagnostic-only reasons (e.g.
``guardrail_halt``, which surfaces its own message) are not second-guessed.
rµ   Útext_responseNr   r   Úsession_persistence_failed)Údisplay_hermes_homeÚprofile_cli_selector)ÚSTORAGE_RECOVERY_DOCS_URLÚhomeÚprofile_argÚrecovery_docsÚdb_pathÚbackups_dir)Úget_default_hermes_root)Ú_default_db_pathÚbackupszexplainer.no_reply_prefix)ÚcorruptÚ	fts_index)r   Ú
startswithÚ_EXIT_REASON_EXPLANATIONSrV   Ú _EXIT_REASON_PREFIX_EXPLANATIONSr   Úhermes_constantsrÈ   rÉ   Úhermes_state_errorsrÊ   rÐ   Úhermes_staterÑ   r.   )rÃ   rÄ   rÎ   r   ÚreasonÚkeyr(   Ú
prefix_keyÚbodyrÈ   rÉ   rÊ   ÚfillrÐ   rÑ   s   &&&&           r   Ú#_format_turn_completion_explanationÚ7TurnExplainersMixin._format_turn_completion_explanationé   s2  € ÷  ÙÜÐ%Ó&ˆØ×Ñ˜_×-Ò-ÙÜ'×+Ñ+¨FÓ3ˆØŠ;ß&FÑ"�Ø×$Ñ$ V×,Ô,Ø$�CÙñ 'Gð Š?Ü�S× HÐ H¬Ð+GÓ)HÔI‰DØÐ3Ô3ßRÝEð Ñ+Ó-¨}Ñ>RÓ>TØÐ!:¸IÀrÈ=ÐZ\ð$ˆDð !Ð$<Ô<ÝDÝ9ä"% g×&CÐ&CÑ1AÓ1CÓ"D��Y‘Ü&)Ñ*AÓ*CÀiÕ*OÓ&P��]Ñ#ÜÔ1Ð2CÓDÑMÈÑM‰DàˆDß8<ŒqÐ,Ó-°Õ4ÐDÀ"ÐDr   r&   )NNrµ   )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r‰   Ústaticmethodr�   rœ   r£   ÚreÚcompiler®   Úclassmethodr±   rÀ   rà   Ú__static_attributes__Ú__classdictcell__)rm   s   @r   rg   rg   o   sœ   ø‡ € ÙZð2*à$(÷2*ò 2*ðh ÷
ó ð
÷
ð 
÷
ð 
ð —j’jØPó€Oð ÷Jó ðJð ÷>ó ð>ð, ÷)Eñ )Eó ö)Er   rg   c                ób   € V ^8„  d   Qh/ ^ \         9   d   \        \        \        3,          ;R&   # )r   rÖ   )Ú__conditional_annotations__r\   r   )r   s   "r   r   r      s,   € ÷ ñ ÷B
ò 
œ4¤¤S �>ñ 
òCr   )rµ   )Úinterrupted_during_api_callÚmax_iterations_reachedÚerror_near_max_iterationsÚrepeated_outer_errors>
   ÚdiskÚlockedrÓ   ÚreplacedrÔ   Ú
turn_leaseÚcompressionÚdeleted_walÚcompression_closedÚsession_row_missing)!rî   ræ   r8   rè   Ú
contextlibr   Útypingr   r   r   Ú
agent.i18nr   Úagent.tool_dispatch_helpersr   r	   r
   Ú agent.tool_result_classificationr   rv   r   ÚEMPTY_RESPONSE_EXPLANATIONr   rÖ   rA   r×   Ú	frozensetr-   r.   r>   rH   re   rg   r   )rî   s   @r   Ú<module>r     sî   øðöó
 
Û 	Ý ß &Ñ &å ÷ñ ÷ðBð ÷Yð Ð :Ø'Ð)[ØÐGØ!Ð#OØ%Ð'WØ$Ð&UØÐ9Ø&Ð(YØÐ?ð
-Ð ó 
÷ $) 5ñ )ñ 8gó)§5¡5ñ )ñ 8gó)ó $Ð  ñ
  ò  !pó  qÐ õqõ
8õ(õ÷:dEó dEr   