+
    jHàjÂ  ã                  óÂ   € R t ^ RIHt ^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RI	H
t
Ht ^ RIHt ]P                  ! ]4      t]! RR04      tR R	 ltR
 R lt ! R R4      tR# )ao  Persistent registry of delivery targets confirmed unreachable. Re-sending to a permanently gone chat
(deleted group, bot kicked/blocked, deactivated user) every cron tick wastes flood-control budget; delivery
short-circuits targets proven dead and any later successful send clears the flag. Only *whole-chat* deaths
(``forbidden``, chat-level ``not_found``) are recorded: adapters self-heal thread/topic-level ``not_found``
by retrying without ``reply_to``. Storage is a per-profile JSON file; reads/writes are best-effort (a
corrupt or unwritable file degrades to in-memory-only rather than raising on the delivery path).
)ÚannotationsN)ÚPath)ÚDictÚOptional)Úget_hermes_homeÚ	forbiddenÚ	not_foundc               ó$   € V ^8„  d   QhRRRRRR/# )é   ÚplatformÚstrÚchat_idÚreturn© )Úformats   "Ú9/home/ubuntu/.hermes/hermes-agent/gateway/dead_targets.pyÚ__annotate__r      s&   € ÷ Eñ E˜ð E sð E¨sñ Eó    c                óˆ   € \        V 4      P                  4       P                  4        R\        V4      P                  4        2# )z-Canonical key for a (platform, chat_id) pair.Ú:)r   ÚstripÚlower)r   r   s   &&r   Ú
_normalizer      s8   € ä�(‹m×!Ñ!Ó#×)Ñ)Ó+Ð,¨A¬c°'«l×.@Ñ.@Ó.BÐ-CÐDÐDr   c               ó    € V ^8„  d   QhRRRR/# )r
   Ú
error_textúOptional[str]r   r   )r   s   "r   r   r      s   € ÷ "ñ " Mð "°mñ "r   c                óÆ   € V '       g   R#  ^RI HpHp T! RT R7      pT\        9   ;'       d    TR8g  ;'       g
    T! T R7      pT'       d   T# R#   \         d     R# i ; i)u�  Best-effort dead-target error_kind from a raised error's text, else None. ``_deliver_to_platform``
raises on hard failure (no SendResult), so ``deliver()`` only has the exception string. ``not_found``
collapses chat-level and thread/topic/message-level failures: only a whole-chat not_found means the
target is dead â€” a deleted forum topic or edited-away message must not mark the entire chat dead.N)Úclassify_send_errorÚis_chat_level_not_found)r   r   )Úplatforms.baser   r   Ú	ExceptionÚ_DEAD_ERROR_KINDS)r   r   r   ÚkindÚdeads   &    r   Úclassify_dead_errorr$      sh   € ÷
 ÙðßPñ ˜t°
Ô;€DØÔ$Ñ$×pÐp¨$°+Ñ*=×*oÐ*oÑAXÐdnÔAo€Dßˆ4Ð!˜TÐ!øô	 ô Úðús   ŒA ÁA ÁA c                  ó^   € ] tR t^/tRtRR R lltR R ltR R ltRR	 R
 lltR R lt	Rt
R# )ÚDeadTargetRegistryzÇThread-safe, persistent set of confirmed-dead targets keyed ``platform:chat_id``. Each entry stores
reason + timestamp for observability; :meth:`clear` (called on a successful send) removes the flag.Nc               ó    € V ^8„  d   QhRRRR/# )r
   ÚpathzOptional[Path]r   ÚNoner   )r   s   "r   r   ÚDeadTargetRegistry.__annotate__3   s   € ÷ eñ e˜^ð e°tñ er   c                	ór  € \         P                  ! 4       V n        / V n        Ve   TM\	        4       R,          R,          V n         V P
                  P                  4       '       dŒ   \        P                  ! V P
                  P                  RR7      4      p\        V\        4      '       dD   VP                  4        UUu/ uF  w  r4\        V\        4      '       g   K  W4bK!  	  uppV n        R # R # R # u uppi   \        \        3 d-   p\        P!                  RT P
                  T4        R p?R # R p?ii ; i)NÚgatewayzdead_targets.jsonz	utf-8-sig©Úencodingu7   dead_targets: could not load %s (%s) â€” starting empty)Ú	threadingÚRLockÚ_lockÚ_deadr   Ú_pathÚexistsÚjsonÚloadsÚ	read_textÚ
isinstanceÚdictÚitemsÚOSErrorÚ
ValueErrorÚloggerÚdebug)Úselfr(   ÚrawÚkÚvÚexcs   &&    r   Ú__init__ÚDeadTargetRegistry.__init__3   sï   € Ü—_’_Ó&ˆŒ
Ø35ˆŒ
Ø!Ò-‘T´?Ó3DÀyÕ3PÐSfÕ3fˆŒ
ð		eØ�z‰z× Ñ ×"Ò"Ü—j’j §¡×!5Ñ!5¸{Ð!5Ó!KÓL�Ü˜c¤4×(Ò(ð *-¯©¬ô"Ù)4¡ ¼
À1Äd×8Kœ˜š©ò"�D–Jñ )ñ #ùó"øô œÐ$ô 	eÜ�L‰LÐRÐTX×T^ÑT^Ð`c×dÒdûð	eús7   ÁC9 Á&AC9 Â?C3ÃC3Ã$	C9 Ã3C9 Ã9D6Ä
!D1Ä1D6c               ó   € V ^8„  d   QhRR/# )r
   r   r)   r   )r   s   "r   r   r*   B   s   € ÷ Uñ U˜tñ Ur   c                	óÒ  €  V P                   P                  P                  R R R7       V P                   P                  V P                   P                  R,           4      pVP                  \        P                  ! V P                  ^R7      RR7       VP                  V P                   4       R#   \         d-   p\        P                  RT P                   T4        Rp?R# Rp?ii ; i)T)ÚparentsÚexist_okz.tmp)Úindentzutf-8r-   z'dead_targets: could not persist %s (%s)N)r3   ÚparentÚmkdirÚwith_suffixÚsuffixÚ
write_textr5   Údumpsr2   Úreplacer;   r=   r>   )r?   ÚtmprC   s   &  r   Ú_flush_lockedÚ DeadTargetRegistry._flush_lockedB   s¢   € ð	UØ�J‰J×Ñ×#Ñ#¨D¸4Ð#Ô@Ø—*‘*×(Ñ(¨¯©×):Ñ):¸VÕ)CÓDˆCØ�N‰Nœ4Ÿ:š: d§j¡j¸Ô;ÀgˆNÔNØ�K‰K˜Ÿ
™
Ö#øÜô 	UÜ�L‰LÐBÀDÇJÁJÐPS×TÒTûð	Uús   ‚B+B/ Â/C&Â:!C!Ã!C&c               ó$   € V ^8„  d   QhRRRRRR/# ©r
   r   r   r   r   r   Úboolr   )r   s   "r   r   r*   K   s&   € ÷ Qñ Q ð Q¨mð QÀñ Qr   c                	ó¾   € V P                   ;_uu_ 4        \        V4      ;'       d    \        W4      V P                  9   uuR R R 4       #   + '       g   i     R # ; i©N)r1   rW   r   r2   )r?   r   r   s   &&&r   Úis_deadÚDeadTargetRegistry.is_deadK   s4   € Ø�Z�Z‹ZÜ˜“=×PÐP¤Z°Ó%BÀdÇjÁjÑ%P÷ �Z�Z‹Zús   •+AÁA	c               ó(   € V ^8„  d   QhRRRRRRRR/# )r
   r   r   r   r   Úreasonr   rW   r   )r   s   "r   r   r*   O   s)   € ÷ ñ  #ð °ð Àsð ÐTXñ r   c                óö  € V'       g   R# \        W4      pV P                  ;_uu_ 4        W@P                  9   pR\        V4      P	                  4       P                  4       R\        V4      R\        V4      R,          R\        P                  ! 4       /V P                  V&   V P                  4        RRR4       X'       g!   \        P                  RYC;'       g    R	4       V'       * #   + '       g   i     L?; i)
z?Record a target as confirmed-dead. Returns True if newly added.Fr   r   r]   :NéÈ   NÚ	marked_atNuv   dead_targets: marked %s as unreachable (%s) â€” future deliveries to this target will be skipped until a send succeedszno reason given)
r   r1   r2   r   r   r   ÚtimerS   r=   Úinfo)r?   r   r   r]   ÚkeyÚexisteds   &&&&  r   Ú	mark_deadÚDeadTargetRegistry.mark_deadO   sº   € çÙÜ˜Ó+ˆØ�Z�Z‹ZØŸZ™ZÑ'ˆGØ)¬3¨x«=×+>Ñ+>Ó+@×+FÑ+FÓ+HÈ)ÔUXÐY`ÓUaØ'¬¨V«°TÕ):¸KÌÏÊËðVˆD�J‰J�s‰Oà×ÑÔ ÷	 ÷
 Ü�K‰Kð OØPS×UpÐUpÐ_pôràŒ{Ð÷ �Zús   ªBC(Ã(C8	c               ó$   € V ^8„  d   QhRRRRRR/# rV   r   )r   s   "r   r   r*   ^   s!   € ÷ 
ñ 
˜cð 
¨Mð 
¸dñ 
r   c                ó0  € V'       g   R# \        W4      pV P                  ;_uu_ 4        V P                  P                  VR4      f    RRR4       R# V P	                  4        \
        P                  RV4       RRR4       R#   + '       g   i     R# ; i)zGRemove a target's dead flag (self-healing). Returns True if it was set.FNz3dead_targets: cleared %s (delivery succeeded again)T)r   r1   r2   ÚpoprS   r=   rb   )r?   r   r   rc   s   &&& r   ÚclearÚDeadTargetRegistry.clear^   sn   € çÙÜ˜Ó+ˆØ�Z�Z‹ZØ�z‰z�~‰~˜c 4Ó(Ò0Ø÷ ‰Zð ×ÑÔ Ü�K‰KÐMÈsÔS÷	 ñ
 ÷ ŽZñ
 ús   ª BÁ&BÂB	)r2   r1   r3   rY   )Ú )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rD   rS   rZ   re   rj   Ú__static_attributes__r   r   r   r&   r&   /   s)   † ñk÷eõUõQ÷÷
ñ 
r   r&   )rq   Ú
__future__r   r5   Úloggingr/   ra   Úpathlibr   Útypingr   r   Úhermes_cli.configr   Ú	getLoggerrm   r=   Ú	frozensetr!   r   r$   r&   r   r   r   Ú<module>rz      s[   ðñõ #ã Û Û Û Ý ß !å -à	×	Ò	˜8Ó	$€ñ ˜{¨KÐ8Ó9Ð õEõ
"÷ 9ó 9r   